From a09abfd1b9dc65bbda2d51074502f0ea34fa67eb Mon Sep 17 00:00:00 2001 From: Liew Hai Liang Date: Mon, 17 Oct 2022 11:36:49 +0900 Subject: [PATCH 1/3] Moved the functions to header file for easier include --- save_load_eigen_csv.hpp | 76 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 save_load_eigen_csv.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 */ From d9e5aa587260a68f3df2073b85db14fd8c5d4a27 Mon Sep 17 00:00:00 2001 From: Liew Hai Liang Date: Mon, 17 Oct 2022 11:37:20 +0900 Subject: [PATCH 2/3] Added tests for int, float and double data types --- .gitignore | 2 + CMakeLists.txt | 14 ++++++ double_test.cpp | 38 ++++++++++++++++ float_test.cpp | 38 ++++++++++++++++ int_test.cpp | 38 ++++++++++++++++ source_file.cpp | 113 ------------------------------------------------ 6 files changed, 130 insertions(+), 113 deletions(-) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 double_test.cpp create mode 100644 float_test.cpp create mode 100644 int_test.cpp delete mode 100644 source_file.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af96791 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c250976 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,14 @@ +project(save_and_load_eigen_csv CXX) +cmake_minimum_required(VERSION 3.0) +find_package(Eigen3 REQUIRED) + +include_directories(${CMAKE_SOURCE_DIR}) + +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..15545e5 --- /dev/null +++ b/double_test.cpp @@ -0,0 +1,38 @@ +// ConsoleApplication3.cpp : This file contains the 'main' function. Program execution begins and ends there. +// + +#include "save_load_eigen_csv.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 + saveData("matrix.csv", matrix_test); + + // matrix to be loaded from a file + Eigen::MatrixXd matrix_test2; + + // load the matrix from the file + matrix_test2 = openData("matrix.csv"); + + // 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..8a68606 --- /dev/null +++ b/float_test.cpp @@ -0,0 +1,38 @@ +// ConsoleApplication3.cpp : This file contains the 'main' function. Program execution begins and ends there. +// + +#include "save_load_eigen_csv.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 + saveData("matrix.csv", matrix_test); + + // matrix to be loaded from a file + Eigen::MatrixXf matrix_test2; + + // load the matrix from the file + matrix_test2 = openData("matrix.csv"); + + // print the matrix in console + std::cout << matrix_test2<("matrix.csv", matrix_test); + + // matrix to be loaded from a file + Eigen::MatrixXi matrix_test2; + + // load the matrix from the file + matrix_test2 = openData("matrix.csv"); + + // 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/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";*/ -} From f692ae873dd62e27d4bbceab20a43e40edbcc82e Mon Sep 17 00:00:00 2001 From: Liew Hai Liang Date: Mon, 17 Oct 2022 12:57:56 +0900 Subject: [PATCH 3/3] Set automated generated path to build folder --- .gitignore | 1 + CMakeLists.txt | 2 ++ double_test.cpp | 6 ++++-- float_test.cpp | 16 +++++++++------- int_test.cpp | 6 ++++-- path.hpp.in | 6 ++++++ 6 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 path.hpp.in diff --git a/.gitignore b/.gitignore index af96791..6cac072 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .vscode build +path.hpp \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c250976..fb9b3c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,8 @@ 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) diff --git a/double_test.cpp b/double_test.cpp index 15545e5..6f1f4d8 100644 --- a/double_test.cpp +++ b/double_test.cpp @@ -2,6 +2,7 @@ // #include "save_load_eigen_csv.hpp" +#include "path.hpp" int main() { @@ -15,13 +16,14 @@ int main() 1.3, 99, 100, 112; // save test matrix - saveData("matrix.csv", matrix_test); + 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("matrix.csv"); + matrix_test2 = openData(matrixFile); // print the matrix in console std::cout << matrix_test2 << std::endl; diff --git a/float_test.cpp b/float_test.cpp index 8a68606..500d922 100644 --- a/float_test.cpp +++ b/float_test.cpp @@ -2,12 +2,13 @@ // #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, @@ -15,21 +16,22 @@ int main() 1.3, 99, 100, 112; // save test matrix - saveData("matrix.csv", matrix_test); + 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("matrix.csv"); - + matrix_test2 = openData(matrixFile); + // print the matrix in console - std::cout << matrix_test2<("matrix.csv", matrix_test); + 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("matrix.csv"); + matrix_test2 = openData(matrixFile); // print the matrix in console std::cout << matrix_test2 << std::endl; 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 */