diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6cac072 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode +build +path.hpp \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..fb9b3c0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,16 @@ +project(save_and_load_eigen_csv CXX) +cmake_minimum_required(VERSION 3.0) +find_package(Eigen3 REQUIRED) + +include_directories(${CMAKE_SOURCE_DIR}) + +configure_file(${CMAKE_SOURCE_DIR}/path.hpp.in ${CMAKE_SOURCE_DIR}/path.hpp) + +add_executable(double_test double_test.cpp) +target_link_libraries(double_test Eigen3::Eigen) + +add_executable(float_test float_test.cpp) +target_link_libraries(float_test Eigen3::Eigen) + +add_executable(int_test int_test.cpp) +target_link_libraries(int_test Eigen3::Eigen) diff --git a/double_test.cpp b/double_test.cpp new file mode 100644 index 0000000..6f1f4d8 --- /dev/null +++ b/double_test.cpp @@ -0,0 +1,40 @@ +// ConsoleApplication3.cpp : This file contains the 'main' function. Program execution begins and ends there. +// + +#include "save_load_eigen_csv.hpp" +#include "path.hpp" + +int main() +{ + // test matrix to be saved + // Eigen::MatrixXd matrix_test(4, 4); + Eigen::Matrix matrix_test; + // define the test matrix + matrix_test << 1.2, 1.4, 1.6, 1.8, + 1.5, 1.7, 1.9, 1.10, + 0.8, 1.2, -0.1, -0.2, + 1.3, 99, 100, 112; + + // save test matrix + std::string matrixFile = build_path + std::string("matrix.csv"); + saveData(matrixFile, matrix_test); + + // matrix to be loaded from a file + Eigen::MatrixXd matrix_test2; + + // load the matrix from the file + matrix_test2 = openData(matrixFile); + + // print the matrix in console + std::cout << matrix_test2 << std::endl; + + // test the load function on a matrix defined outside this environment. + // make sure that the "matrix_outside.csv" file exhists + /*MatrixXd matrix_test3; + + matrix_test3 = openData("matrix_outside.csv"); + + cout <<"\n\n"<< matrix_test3<<"\n\n"; + + cout << 10*matrix_test3 << "\n";*/ +} diff --git a/float_test.cpp b/float_test.cpp new file mode 100644 index 0000000..500d922 --- /dev/null +++ b/float_test.cpp @@ -0,0 +1,40 @@ +// ConsoleApplication3.cpp : This file contains the 'main' function. Program execution begins and ends there. +// + +#include "save_load_eigen_csv.hpp" +#include "path.hpp" + +int main() +{ + // test matrix to be saved + Eigen::MatrixXf matrix_test(4, 4); + + // define the test matrix + matrix_test << 1.2, 1.4, 1.6, 1.8, + 1.5, 1.7, 1.9, 1.10, + 0.8, 1.2, -0.1, -0.2, + 1.3, 99, 100, 112; + + // save test matrix + std::string matrixFile = build_path + std::string("matrix.csv"); + saveData(matrixFile, matrix_test); + + // matrix to be loaded from a file + Eigen::MatrixXf matrix_test2; + + // load the matrix from the file + matrix_test2 = openData(matrixFile); + + // print the matrix in console + std::cout << matrix_test2 << std::endl; + + // test the load function on a matrix defined outside this environment. + // make sure that the "matrix_outside.csv" file exhists + /*MatrixXd matrix_test3; + + matrix_test3 = openData("matrix_outside.csv"); + + cout <<"\n\n"<< matrix_test3<<"\n\n"; + + cout << 10*matrix_test3 << "\n";*/ +} diff --git a/int_test.cpp b/int_test.cpp new file mode 100644 index 0000000..4b6c7e4 --- /dev/null +++ b/int_test.cpp @@ -0,0 +1,40 @@ +// ConsoleApplication3.cpp : This file contains the 'main' function. Program execution begins and ends there. +// + +#include "save_load_eigen_csv.hpp" +#include "path.hpp" + +int main() +{ + // test matrix to be saved + Eigen::MatrixXi matrix_test(4, 4); + + // define the test matrix + matrix_test << 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16; + + // save test matrix + std::string matrixFile = build_path + std::string("matrix.csv"); + saveData(matrixFile, matrix_test); + + // matrix to be loaded from a file + Eigen::MatrixXi matrix_test2; + + // load the matrix from the file + matrix_test2 = openData(matrixFile); + + // print the matrix in console + std::cout << matrix_test2 << std::endl; + + // test the load function on a matrix defined outside this environment. + // make sure that the "matrix_outside.csv" file exhists + /*MatrixXd matrix_test3; + + matrix_test3 = openData("matrix_outside.csv"); + + cout <<"\n\n"<< matrix_test3<<"\n\n"; + + cout << 10*matrix_test3 << "\n";*/ +} diff --git a/path.hpp.in b/path.hpp.in new file mode 100644 index 0000000..5ea32d1 --- /dev/null +++ b/path.hpp.in @@ -0,0 +1,6 @@ +#ifndef PATH_HPP +#define PATH_HPP + +const auto build_path= "${CMAKE_CURRENT_BINARY_DIR}/"; + +#endif /* PATH_HPP */ diff --git a/save_load_eigen_csv.hpp b/save_load_eigen_csv.hpp new file mode 100644 index 0000000..20cfa74 --- /dev/null +++ b/save_load_eigen_csv.hpp @@ -0,0 +1,76 @@ +#ifndef SAVE_LOAD_EIGEN_CSV_HPP +#define SAVE_LOAD_EIGEN_CSV_HPP + +#include +#include +#include +#include + +template +void saveData(std::string fileName, Eigen::Matrix matrix) +{ + // https://eigen.tuxfamily.org/dox/structEigen_1_1IOFormat.html + const static Eigen::IOFormat CSVFormat(Eigen::FullPrecision, Eigen::DontAlignCols, ", ", "\n"); + + std::ofstream file(fileName); + if (file.is_open()) + { + file << matrix.format(CSVFormat); + file.close(); + } +} + + +template +Eigen::Matrix openData(std::string fileToOpen) +{ + + // the inspiration for creating this function was drawn from here (I did NOT copy and paste the code) + // https://stackoverflow.com/questions/34247057/how-to-read-csv-file-and-assign-to-eigen-matrix + + // the input is the file: "fileToOpen.csv": + // a,b,c + // d,e,f + // This function converts input file data into the Eigen matrix format + + + + // the matrix entries are stored in this variable row-wise. For example if we have the matrix: + // M=[a b c + // d e f] + // the entries are stored as matrixEntries=[a,b,c,d,e,f], that is the variable "matrixEntries" is a row vector + // later on, this vector is mapped into the Eigen matrix format + std::vector matrixEntries; + + // in this object we store the data from the matrix + std::ifstream matrixDataFile(fileToOpen); + + // this variable is used to store the row of the matrix that contains commas + std::string matrixRowString; + + // this variable is used to store the matrix entry; + std::string matrixEntry; + + // this variable is used to track the number of rows + int matrixRowNumber = 0; + + + while (std::getline(matrixDataFile, matrixRowString)) // here we read a row by row of matrixDataFile and store every line into the string variable matrixRowString + { + std::stringstream matrixRowStringStream(matrixRowString); //convert matrixRowString that is a string to a stream variable. + + while (std::getline(matrixRowStringStream, matrixEntry, ',')) // here we read pieces of the stream matrixRowStringStream until every comma, and store the resulting character into the matrixEntry + { + matrixEntries.push_back(std::stod(matrixEntry)); //here we convert the string to double and fill in the row vector storing all the matrix entries + } + matrixRowNumber++; //update the column numbers + } + + // here we convet the vector variable into the matrix and return the resulting object, + // note that matrixEntries.data() is the pointer to the first memory location at which the entries of the vector matrixEntries are stored; + return Eigen::Map>(matrixEntries.data(), matrixRowNumber, matrixEntries.size() / matrixRowNumber); + +} + + +#endif /* SAVE_LOAD_EIGEN_CSV_HPP */ diff --git a/source_file.cpp b/source_file.cpp deleted file mode 100644 index 1a5625f..0000000 --- a/source_file.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// ConsoleApplication3.cpp : This file contains the 'main' function. Program execution begins and ends there. -// - -#include -#include -#include -#include - -using namespace std; -using namespace Eigen; - - -void saveData(string fileName, MatrixXd matrix) -{ - //https://eigen.tuxfamily.org/dox/structEigen_1_1IOFormat.html - const static IOFormat CSVFormat(FullPrecision, DontAlignCols, ", ", "\n"); - - ofstream file(fileName); - if (file.is_open()) - { - file << matrix.format(CSVFormat); - file.close(); - } -} - - - -MatrixXd openData(string fileToOpen) -{ - - // the inspiration for creating this function was drawn from here (I did NOT copy and paste the code) - // https://stackoverflow.com/questions/34247057/how-to-read-csv-file-and-assign-to-eigen-matrix - - // the input is the file: "fileToOpen.csv": - // a,b,c - // d,e,f - // This function converts input file data into the Eigen matrix format - - - - // the matrix entries are stored in this variable row-wise. For example if we have the matrix: - // M=[a b c - // d e f] - // the entries are stored as matrixEntries=[a,b,c,d,e,f], that is the variable "matrixEntries" is a row vector - // later on, this vector is mapped into the Eigen matrix format - vector matrixEntries; - - // in this object we store the data from the matrix - ifstream matrixDataFile(fileToOpen); - - // this variable is used to store the row of the matrix that contains commas - string matrixRowString; - - // this variable is used to store the matrix entry; - string matrixEntry; - - // this variable is used to track the number of rows - int matrixRowNumber = 0; - - - while (getline(matrixDataFile, matrixRowString)) // here we read a row by row of matrixDataFile and store every line into the string variable matrixRowString - { - stringstream matrixRowStringStream(matrixRowString); //convert matrixRowString that is a string to a stream variable. - - while (getline(matrixRowStringStream, matrixEntry, ',')) // here we read pieces of the stream matrixRowStringStream until every comma, and store the resulting character into the matrixEntry - { - matrixEntries.push_back(stod(matrixEntry)); //here we convert the string to double and fill in the row vector storing all the matrix entries - } - matrixRowNumber++; //update the column numbers - } - - // here we convet the vector variable into the matrix and return the resulting object, - // note that matrixEntries.data() is the pointer to the first memory location at which the entries of the vector matrixEntries are stored; - return Map>(matrixEntries.data(), matrixRowNumber, matrixEntries.size() / matrixRowNumber); - -} - - - - -int main() -{ - // test matrix to be saved - MatrixXd matrix_test(4, 4); - - // define the test matrix - matrix_test << 1.2, 1.4, 1.6, 1.8, - 1.5, 1.7, 1.9, 1.10, - 0.8, 1.2, -0.1, -0.2, - 1.3, 99, 100, 112; - - // save test matrix - saveData("matrix.csv", matrix_test); - - // matrix to be loaded from a file - MatrixXd matrix_test2; - - // load the matrix from the file - matrix_test2 = openData("matrix.csv"); - - // print the matrix in console - cout << matrix_test2; - - // test the load function on a matrix defined outside this environment. - // make sure that the "matrix_outside.csv" file exhists - /*MatrixXd matrix_test3; - - matrix_test3 = openData("matrix_outside.csv"); - - cout <<"\n\n"<< matrix_test3<<"\n\n"; - - cout << 10*matrix_test3 << "\n";*/ -}