From afd504d6796b056958c89e30bc4e2f4975dfc589 Mon Sep 17 00:00:00 2001 From: Karen Kaspar Date: Fri, 16 May 2025 16:01:17 +0200 Subject: [PATCH] First batch of rotgen implementation: constructors, basic infrastructure --- .gitignore | 3 +- CMakeLists.txt | 2 +- include/rotgen/impl/matrix_impl64.hpp | 18 ++- include/rotgen/matrix.hpp | 38 +++++- src/matrix_impl64.cpp | 29 ++++- test/CMakeLists.txt | 2 +- test/basic/constructors.cpp | 175 ++++++++++++++++++++++++++ test/basic/functions.cpp | 167 ++++++++++++++++++++++++ test/basic/operators.cpp | 4 +- 9 files changed, 428 insertions(+), 10 deletions(-) create mode 100644 test/basic/constructors.cpp create mode 100644 test/basic/functions.cpp diff --git a/.gitignore b/.gitignore index 19c5f3a..3d9b80e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ install_manifest.txt compile_commands.json CTestTestfile.cmake _deps -build/* \ No newline at end of file +build/* +.idea \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index bb2d9b4..d88bafa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,7 @@ add_library(rotgen SHARED ${SOURCES}) set_target_properties(rotgen PROPERTIES VERSION ${PROJECT_VERSION}) set_target_properties(rotgen PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR}) -target_compile_features(rotgen INTERFACE cxx_std_17) +target_compile_options(rotgen PUBLIC -std=c++20 -Werror -Wall -Wextra -Wshadow -Wunused-variable) set_target_properties(rotgen PROPERTIES EXPORT_NAME rotgen) add_library(rotgen::rotgen ALIAS rotgen) diff --git a/include/rotgen/impl/matrix_impl64.hpp b/include/rotgen/impl/matrix_impl64.hpp index b61c544..e3345a7 100644 --- a/include/rotgen/impl/matrix_impl64.hpp +++ b/include/rotgen/impl/matrix_impl64.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace rotgen { @@ -16,10 +17,14 @@ namespace rotgen { public: matrix_impl64(std::size_t rows = 0, std::size_t cols = 0); + matrix_impl64(std::size_t rows, std::size_t cols,std::initializer_list init); + + matrix_impl64(std::initializer_list> init); matrix_impl64(matrix_impl64 const& other); - matrix_impl64& operator=(matrix_impl64 const& other); matrix_impl64(matrix_impl64&&) noexcept; + + matrix_impl64& operator=(matrix_impl64 const& other); matrix_impl64& operator=(matrix_impl64&&) noexcept; ~matrix_impl64(); @@ -27,9 +32,16 @@ namespace rotgen std::size_t rows() const; std::size_t cols() const; + std::size_t size() const; + void resize(std::size_t new_rows, std::size_t new_cols); + void conservativeResize(std::size_t new_rows, std::size_t new_cols); + double& operator()(std::size_t i, std::size_t j); double const& operator()(std::size_t i, std::size_t j) const; + double& operator()(std::size_t index); + double const& operator()(std::size_t index) const; + matrix_impl64& operator+=(matrix_impl64 const& rhs); matrix_impl64& operator*=(matrix_impl64 const& rhs); matrix_impl64& operator*=(double d); @@ -37,7 +49,9 @@ namespace rotgen friend std::ostream& operator<<(std::ostream&,matrix_impl64 const&); friend bool operator==(matrix_impl64 const& lhs, matrix_impl64 const& rhs); - private: + const double* data() const; + + private: struct payload; std::unique_ptr storage_; }; diff --git a/include/rotgen/matrix.hpp b/include/rotgen/matrix.hpp index fac61df..a481c23 100644 --- a/include/rotgen/matrix.hpp +++ b/include/rotgen/matrix.hpp @@ -8,6 +8,8 @@ #pragma once #include +#include +#include namespace rotgen { @@ -20,7 +22,41 @@ namespace rotgen public: matrix() : parent(Rows==-1?0:Rows,Cols==-1?0:Cols) {} - matrix(std::size_t r, std::size_t c) : parent(r,c) {} + + matrix(int r, int c) : parent(r, c) + { + if constexpr(Rows != -1) assert(r == Rows && "Mismatched between dynamic and static row size"); + if constexpr(Cols != -1) assert(c == Cols && "Mismatched between dynamic and static column size"); + } + + matrix(std::initializer_list> init) : parent(init) + { + if constexpr(Rows != -1) assert(init.size() == Rows && "Mismatched between dynamic and static row size"); + if constexpr(Cols != -1) + { + std::size_t c = 0; + if(init.size()) c = init.begin()->size(); + assert(c == Cols && "Mismatched between dynamic and static column size"); + } + } + + template... S> + matrix(Scalar s0,S... init) + requires((Rows == 1 && Cols == (1+sizeof...(S))) || (Cols == 1 && Rows == (1+sizeof...(S)))) + : parent(Rows, Cols, {s0,static_cast(init)...}) + {} + + void resize(int new_rows, int new_cols) + requires(Rows == -1 && Cols == -1) + { + parent::resize(new_rows, new_cols); + } + + void conservativeResize(int new_rows, int new_cols) + requires(Rows == -1 && Cols == -1) + { + parent::conservativeResize(new_rows, new_cols); + } friend bool operator==(matrix const& lhs, matrix const& rhs) { diff --git a/src/matrix_impl64.cpp b/src/matrix_impl64.cpp index d5382a8..e1fec52 100644 --- a/src/matrix_impl64.cpp +++ b/src/matrix_impl64.cpp @@ -17,6 +17,7 @@ namespace rotgen { Eigen::Matrix data; payload(std::size_t r=0, std::size_t c=0) : data(r, c) {} + payload(std::initializer_list> init) : data(init) {} }; @@ -25,19 +26,34 @@ namespace rotgen //================================================================================================== matrix_impl64::matrix_impl64(std::size_t r, std::size_t c) : storage_(std::make_unique(r,c)) {} + matrix_impl64::matrix_impl64(std::initializer_list> init) + : storage_(std::make_unique(init)) + {} + + matrix_impl64::matrix_impl64(std::size_t r, std::size_t c,std::initializer_list init) + : matrix_impl64(r,c) + { + auto first = init.begin(); + for(std::size_t i=0; i < init.size(); i++) + (*this)(i) = first[i]; + } + matrix_impl64::matrix_impl64(matrix_impl64 const& o) - : matrix_impl64(o.storage_->data.rows(),o.storage_->data.cols()) + : matrix_impl64(o.rows(),o.cols()) { storage_->data = o.storage_->data; } + matrix_impl64::matrix_impl64(matrix_impl64&&) noexcept = default; + + matrix_impl64& matrix_impl64::operator=(matrix_impl64 const& o) { if (this != &o) storage_->data = o.storage_->data; return *this; } - matrix_impl64::matrix_impl64(matrix_impl64&&) noexcept = default; + matrix_impl64& matrix_impl64::operator=(matrix_impl64&&) noexcept = default; matrix_impl64::~matrix_impl64() = default; @@ -48,9 +64,18 @@ namespace rotgen std::size_t matrix_impl64::rows() const { return static_cast(storage_->data.rows()); } std::size_t matrix_impl64::cols() const { return static_cast(storage_->data.cols()); } + std::size_t matrix_impl64::size() const { return static_cast(storage_->data.size()); } + void matrix_impl64::resize(std::size_t new_rows, std::size_t new_cols) { storage_->data.resize(new_rows, new_cols); } + void matrix_impl64::conservativeResize(std::size_t new_rows, std::size_t new_cols) { storage_->data.conservativeResize(new_rows, new_cols); } + double& matrix_impl64::operator()(std::size_t i, std::size_t j) { return storage_->data(i,j); } double const& matrix_impl64::operator()(std::size_t i, std::size_t j) const { return storage_->data(i,j); } + double& matrix_impl64::operator()(std::size_t index) { return storage_->data(index); } + double const& matrix_impl64::operator()(std::size_t index) const { return storage_->data(index); } + + const double* matrix_impl64::data() const { return storage_->data.data(); } + //================================================================================================== // Operators //================================================================================================== diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2ac4b21..e2dfd7b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,7 +10,7 @@ rotgen_setup_test_targets() ## Compiler options for Unit Tests ##====================================================================================================================== add_library(rotgen_test INTERFACE) -target_compile_features(rotgen_test INTERFACE cxx_std_20) +target_compile_options(rotgen_test INTERFACE -std=c++20 -Werror -Wall -Wextra -Wshadow -Wunused-variable) target_include_directories( rotgen_test INTERFACE ${PROJECT_SOURCE_DIR}/test) target_link_libraries(rotgen_test INTERFACE rotgen) diff --git a/test/basic/constructors.cpp b/test/basic/constructors.cpp new file mode 100644 index 0000000..c69b1b1 --- /dev/null +++ b/test/basic/constructors.cpp @@ -0,0 +1,175 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#define TTS_MAIN +#include +#include "tts.hpp" + +TTS_CASE("Default matrix dynamic constructor") +{ + rotgen::matrix matrix; + + TTS_EQUAL(matrix.rows(), 0ULL); + TTS_EQUAL(matrix.cols(), 0ULL); +}; + +TTS_CASE("Default matrix static constructor") +{ + rotgen::matrix matrix; + + TTS_EQUAL(matrix.rows(), 4ULL); + TTS_EQUAL(matrix.cols(), 9ULL); +}; + +TTS_CASE("Dynamic matrix constructor with row and columns") +{ + rotgen::matrix matrix(10, 5); + + TTS_EQUAL(matrix.rows(), 10ULL); + TTS_EQUAL(matrix.cols(), 5ULL); +}; + +TTS_CASE("Static matrix constructor with row and columns") +{ + rotgen::matrix matrix(6, 11); + + TTS_EQUAL(matrix.rows(), 6ULL); + TTS_EQUAL(matrix.cols(), 11ULL); +}; + +TTS_CASE("Copy constructor produces identical but independent matrix") +{ + rotgen::matrix a(3, 3); + + for(std::size_t r=0;r b = a; + + TTS_EQUAL(b.rows(), a.rows()); + TTS_EQUAL(b.cols(), a.cols()); + + for(std::size_t r=0;r a; + rotgen::matrix b = a; + TTS_EQUAL(b.rows(), 0ULL); + TTS_EQUAL(b.cols(), 0ULL); +}; + +TTS_CASE("Copy constructor from const matrix") +{ + const rotgen::matrix a(2, 2); + auto b = a; + TTS_EQUAL(b.rows(), 2ULL); + TTS_EQUAL(b.cols(), 2ULL); +}; + +TTS_CASE("Copy constructor on static matrix") +{ + rotgen::matrix a; + rotgen::matrix b = a; + TTS_EQUAL(b.rows(), 2ULL); + TTS_EQUAL(b.cols(), 5ULL); +}; + +/* +TTS_CASE("Copy constructor on static/dynamic matrix") +{ + rotgen::matrix a; + rotgen::matrix b = a; + TTS_EQUAL(b.rows(), 11); + TTS_EQUAL(b.cols(), 4); +}; + +TTS_CASE("Copy constructor on dynamic/static matrix") +{ + rotgen::matrix a(5, 7); + rotgen::matrix b = a; + TTS_EQUAL(b.rows(), 5); + TTS_EQUAL(b.cols(), 7); +};*/ + +TTS_CASE("Move constructor transfers contents") +{ + rotgen::matrix a(3, 3); + a(1,1) = 7; + auto ptr = a.data(); + + rotgen::matrix b = std::move(a); + + TTS_EQUAL(b(1,1), 7); + TTS_EQUAL(b.rows(), 3ULL); + TTS_EQUAL(b.cols(), 3ULL); + TTS_EXPECT(b.data() == ptr); +// TTS_EXPECT(a.data() == nullptr); +}; + +TTS_CASE("Move constructor from Rvalue") +{ + rotgen::matrix b = rotgen::matrix(2, 2); + TTS_EQUAL(b.rows(), 2ULL); + TTS_EQUAL(b.cols(), 2ULL); +}; + +TTS_CASE("Constructor from Initializer list") +{ + rotgen::matrix b1 = {3.5}; + TTS_EQUAL(b1.rows(), 1ULL); + TTS_EQUAL(b1.cols(), 1ULL); + TTS_EQUAL(b1(0) , 3.5); + + rotgen::matrix b9 = {0.01, 0.1, 1, 10, 100}; + TTS_EQUAL(b9.rows(), 5ULL); + TTS_EQUAL(b9.cols(), 1ULL); + + int i = 0.01; + for(std::size_t r=0;r b13 = {1.2,2.3,3.4}; + TTS_EQUAL(b13.rows(), 1ULL); + TTS_EQUAL(b13.cols(), 3ULL); + TTS_EQUAL(b13(0) , 1.2); + TTS_EQUAL(b13(1) , 2.3); + TTS_EQUAL(b13(2) , 3.4); +}; + +TTS_CASE("Constructor from Initializer list of rows") +{ + rotgen::matrix b1 = {{3.5}}; + TTS_EQUAL(b1.rows(), 1ULL); + TTS_EQUAL(b1.cols(), 1ULL); + TTS_EQUAL(b1(0,0) , 3.5); + + rotgen::matrix b23 = { {1.2,2.3,3.4} + , {10,200,3000} + }; + TTS_EQUAL(b23.rows(), 2ULL); + TTS_EQUAL(b23.cols(), 3ULL); + TTS_EQUAL(b23(0,0) , 1.2); + TTS_EQUAL(b23(0,1) , 2.3); + TTS_EQUAL(b23(0,2) , 3.4); + TTS_EQUAL(b23(1,0) , 10); + TTS_EQUAL(b23(1,1) , 200); + TTS_EQUAL(b23(1,2) , 3000); +}; \ No newline at end of file diff --git a/test/basic/functions.cpp b/test/basic/functions.cpp new file mode 100644 index 0000000..7d5c3a4 --- /dev/null +++ b/test/basic/functions.cpp @@ -0,0 +1,167 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#define TTS_MAIN +#include +#include "tts.hpp" + +TTS_CASE("Function size") +{ + rotgen::matrix empty_matrix; + rotgen::matrix matrix(3,4); + rotgen::matrix row_vector(9,1); + rotgen::matrix column_vector(1,5); + + TTS_EQUAL(empty_matrix.size(), 0ULL); + TTS_EQUAL(matrix.size(), 12ULL); + TTS_EQUAL(row_vector.size(), 9ULL); + TTS_EQUAL(column_vector.size(), 5ULL); +}; + +TTS_CASE("Resizing dynamic matrix") +{ + rotgen::matrix a(2, 3); + + for(std::size_t r=0;r a; + TTS_EXPECT_NOT_COMPILES(a, { a.resize(4, 5); }); +}; + +TTS_CASE("Dynamix matrix conservative resizing") +{ + rotgen::matrix a(2, 3); + + int i = 1; + for(std::size_t r=0;r a; + TTS_EXPECT_NOT_COMPILES(a, { a.conservativeResize(4, 5); }); +}; + +TTS_CASE("Test coefficient accessors") +{ + rotgen::matrix a(3, 5); + + for(std::size_t r=0;r a(2, 4); + + int i = 1; + for(std::size_t c=0;c b (2, 3); + + i = 1; + for(std::size_t c=0;c a(2,2); rotgen::matrix ref(2,2); - for(int r=0;r