From 5ffe169da2b56ac275977744b7b87e63586167ff Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Sun, 18 Feb 2024 11:11:16 +0100 Subject: [PATCH] Add examples for Eigen. --- src/examples/CMakeLists.txt | 12 +++++++++ src/examples/eigen_map.cpp | 48 +++++++++++++++++++++++++++++++++++ src/examples/eigen_matrix.cpp | 33 ++++++++++++++++++++++++ src/examples/eigen_vector.cpp | 33 ++++++++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 src/examples/eigen_map.cpp create mode 100644 src/examples/eigen_matrix.cpp create mode 100644 src/examples/eigen_vector.cpp diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index ab5700c6a..47c43e00a 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -30,6 +30,12 @@ set(boost_examples ${CMAKE_CURRENT_SOURCE_DIR}/boost_ublas_double.cpp ) +set(eigen_examples + ${CMAKE_CURRENT_SOURCE_DIR}/eigen_matrix.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/eigen_vector.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/eigen_map.cpp +) + set(hl_hdf5_examples ${CMAKE_CURRENT_SOURCE_DIR}/hl_hdf5_inmemory_files.cpp ) @@ -70,6 +76,12 @@ if(HIGHFIVE_TEST_BOOST) endforeach() endif() +if(HIGHFIVE_TEST_EIGEN) + foreach(example_source ${eigen_examples}) + compile_example(${example_source} HighFiveEigenDependency) + endforeach() +endif() + if(HDF5_IS_PARALLEL) foreach(example_source ${parallel_hdf5_examples}) compile_example(${example_source}) diff --git a/src/examples/eigen_map.cpp b/src/examples/eigen_map.cpp new file mode 100644 index 000000000..caf477b3b --- /dev/null +++ b/src/examples/eigen_map.cpp @@ -0,0 +1,48 @@ +#include +#include + +// Example showing reading and writing of `Eigen::Map`. Using +// `Map` as an example, but `Map` works +// analogously. +// +// Both `Eigen::Matrix` and `Eigen::Vector` have their own examples. + +int main() { + HighFive::File file("eigen_map.h5", HighFive::File::Truncate); + + // Somehow allocate some memory: + double* p1 = (double*) malloc(4*3 * sizeof(double)); + + Eigen::Map A(p1, 4, 3); + + // clang-format off + A << 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12; + // clang-format on + std::cout << "A = \n" << A << "\n\n"; + + // Write it to the file: + file.createDataSet("mat", A); + + // ... and read it back as fixed-size and row-major: + using Matrix43d = Eigen::Matrix; + + // Again, memory was obtain somehow, and we create an `Eigen::Map` + // from it: + double* p2 = (double*) malloc(4*3 * sizeof(double)); + Eigen::Map B(p2, 4, 3); + + // Since, we've pre-allocated the memory, we use the overload of `read` + // accepts `B` and an argument. Note, this will throw if `B` needs to be + // resized, because a map shouldn't resize the underlying memory: + file.getDataSet("mat").read(B); + + std::cout << "B = \n" << B << "\n"; + + free(p1); + free(p2); + + return 0; +} diff --git a/src/examples/eigen_matrix.cpp b/src/examples/eigen_matrix.cpp new file mode 100644 index 000000000..7a40445d7 --- /dev/null +++ b/src/examples/eigen_matrix.cpp @@ -0,0 +1,33 @@ +#include +#include + +// Example showing reading and writing of `Eigen::Matrix`. Using +// `Eigen::Matrix` as an example, but `Eigen::Array` works analogously. +// +// Both `Eigen::Vector` and `Eigen::Map` have their own examples. + +int main() { + HighFive::File file("eigen_matrix.h5", HighFive::File::Truncate); + + // Create a matrix. + Eigen::MatrixXd A(4, 3); + // clang-format off + A << 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12; + // clang-format on + // + std::cout << "A = \n" << A << "\n\n"; + + // Write it to the file: + file.createDataSet("mat", A); + + // ... and read it back as fixed-size and row-major: + using Matrix43d = Eigen::Matrix; + auto B = file.getDataSet("mat").read(); + + std::cout << "B = \n" << B << "\n"; + + return 0; +} diff --git a/src/examples/eigen_vector.cpp b/src/examples/eigen_vector.cpp new file mode 100644 index 000000000..c5f723de2 --- /dev/null +++ b/src/examples/eigen_vector.cpp @@ -0,0 +1,33 @@ +#include +#include + +// Example showing reading and writing of `Eigen::Matrix`. Using +// `Eigen::Matrix` as an example, but `Eigen::Array` works analogously. +// +// Both `Eigen::Vector` and `Eigen::Map` have their own examples. + +int main() { + HighFive::File file("eigen_vector.h5", HighFive::File::Truncate); + + // Create a matrix. + Eigen::VectorXd v(3); + v << 1, 2, 3; + std::cout << "v = \n" << v << "\n\n"; + + // Write it to the file: + file.createDataSet("col_vec", v); + + // The twist is that Eigen typedefs: + // using VectorXd = Matrix; + // + // Therefore, for HighFive it's indistinguishable from a Nx1 matrix. Since, + // Eigen distinguishes row and column vectors, the HighFive chooses to + // respect the distinction and deduces the shape of vector as Nx1. + + // ... and read it back as fixed-size: + auto w = file.getDataSet("col_vec").read(); + + std::cout << "w = \n" << w << "\n"; + + return 0; +}