diff --git a/CMakeLists.txt b/CMakeLists.txt index a2a5ad2..7d121d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ endif() ##====================================================================================================================== set ( SOURCES src/matrix.cpp + src/block.cpp ) ##====================================================================================================================== diff --git a/include/rotgen/block.hpp b/include/rotgen/block.hpp new file mode 100644 index 0000000..5c1c963 --- /dev/null +++ b/include/rotgen/block.hpp @@ -0,0 +1,197 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include +#include +#include +#include + +namespace rotgen +{ + template + class block : public find_block + { + using parent = find_block; + public: + using scalar_type = typename Ref::scalar_type; + static constexpr int storage_order = (ForceStorageOrder == -1) ? Ref::storage_order : ForceStorageOrder; + using concrete_type = matrix; + + static constexpr int RowsAtCompileTime = Rows; + static constexpr int ColsAtCompileTime = Cols; + + block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) : parent(r,i0,j0,ni,nj) + {} + + block(Ref& r, std::size_t i0, std::size_t j0) requires(Rows != -1 && Cols != -1) + : parent(r,i0,j0,Rows,Cols) + {} + + block(parent const& base) : parent(base) {} + +/* +block transpose() const +{ + return block(static_cast(*this).transpose()); +} + +block conjugate() const +{ + return block(static_cast(*this).conjugate()); +} + +block adjoint() const +{ + return block(static_cast(*this).adjoint()); +} +*/ + + friend bool operator==(block const& lhs, block const& rhs) + { + return static_cast(lhs) == static_cast(rhs); + } + + block& operator+=(block const& rhs) + { + static_cast(*this) += static_cast(rhs); + return *this; + } + + block& operator-=(block const& rhs) + { + static_cast(*this) -= static_cast(rhs); + return *this; + } + + concrete_type operator-() const + { + return concrete_type(static_cast(*this).operator-()); + } + + block& operator*=(block const& rhs) + { + static_cast(*this) *= static_cast(rhs); + return *this; + } + + block& operator*=(scalar_type rhs) + { + static_cast(*this) *= rhs; + return *this; + } + + block& operator/=(scalar_type rhs) + { + static_cast(*this) /= rhs; + return *this; + } + + static concrete_type Zero() + requires (Rows != -1 && Cols != -1) + { + return parent::Zero(Rows, Cols); + } + + static concrete_type Zero(int rows, int cols) + { + if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); + if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); + return parent::Zero(rows, cols); + } + + static concrete_type Constant(scalar_type value) + requires (Rows != -1 && Cols != -1) + { + return parent::Constant(Rows, Cols, static_cast(value)); + } + + static concrete_type Constant(int rows, int cols, scalar_type value) + { + if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); + if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); + return parent::Constant(rows, cols, static_cast(value)); + } + + static concrete_type Random() + requires (Rows != -1 && Cols != -1) + { + return parent::Random(Rows, Cols); + } + + static concrete_type Random(int rows, int cols) + { + if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); + if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); + return parent::Random(rows, cols); + } + + static concrete_type Identity() + requires (Rows != -1 && Cols != -1) + { + return parent::Identity(Rows, Cols); + } + + static concrete_type Identity(int rows, int cols) + { + if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); + if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); + return parent::Identity(rows, cols); + } + + template + double lpNorm() const + { + assert(P == 1 || P == 2 || P == Infinity); + return parent::lpNorm(P); + } +}; + +/* +template +block operator+(block const& lhs, block const& rhs) +{ + block that(lhs); + return that += rhs; +} + +template +block operator-(block const& lhs, block const& rhs) +{ + block that(lhs); + return that -= rhs; +} + +template +block operator*(block const& lhs, block const& rhs) +{ + block that(lhs); + return that *= rhs; + } + + template + block operator*(block const& lhs, double rhs) + { + block that(lhs); + return that *= rhs; + } + + template + block operator*(double lhs, block const& rhs) + { + return rhs * lhs; + } + + template + block operator/(block const& lhs, double rhs) + { + block that(lhs); + return that /= rhs; + } +*/ +} \ No newline at end of file diff --git a/include/rotgen/extract.hpp b/include/rotgen/extract.hpp new file mode 100644 index 0000000..dd88510 --- /dev/null +++ b/include/rotgen/extract.hpp @@ -0,0 +1,235 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include +#include + +namespace rotgen +{ + template< typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto extract(matrix& m, int i0, int j0,int ni, int nj) + { + using base = matrix; + return block(m, i0,j0,ni,nj); + } + + template< int NI, int NJ + , typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto extract(matrix& m, int i0, int j0) + { + using base = matrix; + return block(m,i0,j0); + } + + template< typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto topLeftCorner(matrix& m, int ni, int nj) + { + using base = matrix; + return block(m,0,0,ni,nj); + } + + template< typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto topRightCorner(matrix& m, int ni, int nj) + { + using base = matrix; + return block(m,0,m.cols()-nj,ni,nj); + } + + template< typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto bottomLeftCorner(matrix& m, int ni, int nj) + { + using base = matrix; + return block(m,m.rows()-ni,0,ni,nj); + } + + template< typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto bottomRightCorner(matrix& m, int ni, int nj) + { + using base = matrix; + return block(m,m.rows()-ni,m.cols()-nj,ni,nj); + } + + template< typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto topRows(matrix& m, int ni) + { + using base = matrix; + return block(m,0,0,ni,m.cols()); + } + + template< typename S, int R , int C, + int Opts , int MaxR, int MaxC + > + auto middleRows(matrix& m, int i0, int ni) + { + using base = matrix; + return block(m,i0,0,ni,m.cols()); + } + + template< typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto bottomRows(matrix& m, int ni) + { + using base = matrix; + return block(m,m.rows()-ni,0,ni,m.cols()); + } + + template< typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto leftCols(matrix& m, int nj) + { + using base = matrix; + return block(m,0,0,m.rows(),nj); + } + + template< typename S, int R , int C, + int Opts , int MaxR, int MaxC + > + auto middleCols(matrix& m, int j0, int nj) + { + using base = matrix; + return block(m,0,j0,m.rows(),nj); + } + + template< typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto rightCols(matrix& m, int nj) + { + using base = matrix; + return block(m,0,m.cols()-nj,m.rows(),nj); + } + + template< typename S, int R, int C + , int Opts , int MaxR, int MaxC + > + auto row(matrix& m, int i0) + { + using base = matrix; + return block(m,i0,0, 1, m.cols()); + } + + template< typename S, int R, int C + , int Opts , int MaxR, int MaxC + > + auto col(matrix& m, int j0) + { + using base = matrix; + return block(m,0,j0, m.rows(), 1); + } + + template< int NI, typename S, int R, int C, + int Opts, int MaxR, int MaxC + > + auto topRows(matrix& m) + { + using base = matrix; + return block(m,0,0, NI, m.cols()); + } + + template< int NI, typename S, int R, int C, + int Opts, int MaxR, int MaxC + > + auto bottomRows(matrix& m) + { + using base = matrix; + return block(m,m.rows()-NI,0, NI, m.cols()); + } + + template< int NI, typename S, int R, int C, + int Opts , int MaxR, int MaxC + > + auto middleRows(matrix& m, int i0) + { + using base = matrix; + return block(m,i0,0, NI, m.cols()); + } + + template< int NJ, typename S, int R, int C, + int Opts, int MaxR, int MaxC + > + auto leftCols(matrix& m) + { + using base = matrix; + return block(m,0,0, m.rows(), NJ); + } + + template< int NJ, typename S, int R, int C, + int Opts, int MaxR, int MaxC + > + auto rightCols(matrix& m) + { + using base = matrix; + return block(m,0,m.cols()-NJ, m.rows(), NJ); + } + + template< int NJ, typename S, int R, int C, + int Opts , int MaxR, int MaxC + > + auto middleCols(matrix& m, int j0) + { + using base = matrix; + return block(m,0,j0, m.rows(), NJ); + } + + template< int NI, int NJ + , typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto topLeftCorner(matrix& m) + { + using base = matrix; + return block(m,0,0); + } + + template< int NI, int NJ + , typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto topRightCorner(matrix& m) + { + using base = matrix; + return block(m,0,m.cols()-NJ); + } + + template< int NI, int NJ + , typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto bottomLeftCorner(matrix& m) + { + using base = matrix; + return block(m,m.rows()-NI,0); + } + + template< int NI, int NJ + , typename S, int R , int C + , int Opts , int MaxR, int MaxC + > + auto bottomRightCorner(matrix& m) + { + using base = matrix; + return block(m,m.rows()-NI,m.cols()-NJ); + } +} \ No newline at end of file diff --git a/include/rotgen/impl/block.hpp b/include/rotgen/impl/block.hpp new file mode 100644 index 0000000..a5db371 --- /dev/null +++ b/include/rotgen/impl/block.hpp @@ -0,0 +1,64 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace rotgen +{ + #define SIZE 64 + #define TYPE double + + #define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_col) + #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) + #include + #undef CLASSNAME + #undef SOURCENAME + + #define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_row) + #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) + #include + #undef CLASSNAME + #undef SOURCENAME + + #undef SIZE + #undef TYPE + + #define SIZE 32 + #define TYPE float + + #define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_col) + #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) + #include + #undef CLASSNAME + #undef SOURCENAME + + #define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_row) + #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) + #include + #undef CLASSNAME + #undef SOURCENAME + + #undef SIZE + #undef TYPE + + template struct find_block_impl; + + template<> struct find_block_impl { using type = block_impl32_col; }; + template<> struct find_block_impl { using type = block_impl32_row; }; + template<> struct find_block_impl { using type = block_impl64_col; }; + template<> struct find_block_impl { using type = block_impl64_row; }; + + template + using find_block = typename find_block_impl::type; +} diff --git a/include/rotgen/impl/block_model.hpp b/include/rotgen/impl/block_model.hpp new file mode 100644 index 0000000..c68db37 --- /dev/null +++ b/include/rotgen/impl/block_model.hpp @@ -0,0 +1,81 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== + +//================================================================================================== +/* + This file is a X-File to generate various block_impl_* declarations variant +*/ +//================================================================================================== +class CLASSNAME +{ + public: + CLASSNAME(SOURCENAME& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj); + + CLASSNAME(CLASSNAME const& other); + CLASSNAME(CLASSNAME&&) noexcept; + + CLASSNAME& operator=(CLASSNAME const& other); + CLASSNAME& operator=(CLASSNAME&&) noexcept; + + ~CLASSNAME(); + + std::size_t rows() const; + std::size_t cols() const; + std::size_t size() const; + + // CLASSNAME transpose() const; + // CLASSNAME conjugate() const; + // CLASSNAME adjoint() const; + + // void transposeInPlace(); + // void adjointInPlace(); + + TYPE sum() const; + TYPE prod() const; + TYPE mean() const; + TYPE trace() const; + TYPE maxCoeff() const; + TYPE minCoeff() const; + TYPE maxCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const; + TYPE minCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const; + + TYPE squaredNorm() const; + TYPE norm() const; + TYPE lpNorm(int p) const; + + TYPE& operator()(std::size_t i, std::size_t j); + TYPE const& operator()(std::size_t i, std::size_t j) const; + + // TYPE& operator()(std::size_t index); + // TYPE const& operator()(std::size_t index) const; + + CLASSNAME& operator+=(CLASSNAME const& rhs); + CLASSNAME& operator-=(CLASSNAME const& rhs); + SOURCENAME operator-() const; + CLASSNAME& operator*=(CLASSNAME const& rhs); + CLASSNAME& operator*=(TYPE d); + CLASSNAME& operator/=(TYPE d); + + friend std::ostream& operator<<(std::ostream&,CLASSNAME const&); + friend bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs); + + const TYPE* data() const; + + static SOURCENAME Zero(std::size_t r, std::size_t c) { return SOURCENAME::Zero(r,c); } + static SOURCENAME Constant(std::size_t r, std::size_t c, TYPE v) { return SOURCENAME::Constant(r,c,v); } + static SOURCENAME Random(std::size_t r, std::size_t c) { return SOURCENAME::Random(r,c); } + static SOURCENAME Identity(std::size_t r, std::size_t c) { return SOURCENAME::Identity(r,c); } + + private: + struct payload; + std::unique_ptr storage_; + + public: + std::unique_ptr& storage() { return storage_; } + std::unique_ptr const& storage() const { return storage_; } +}; \ No newline at end of file diff --git a/include/rotgen/impl/matrix.hpp b/include/rotgen/impl/matrix.hpp index 98379b2..7969b1c 100644 --- a/include/rotgen/impl/matrix.hpp +++ b/include/rotgen/impl/matrix.hpp @@ -18,13 +18,13 @@ namespace rotgen #define SIZE 64 #define TYPE double - #define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) + #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #include - #undef MATRIX + #undef CLASSNAME - #define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) + #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #include - #undef MATRIX + #undef CLASSNAME #undef SIZE #undef TYPE @@ -32,13 +32,13 @@ namespace rotgen #define SIZE 32 #define TYPE float - #define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) + #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #include - #undef MATRIX + #undef CLASSNAME - #define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) + #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #include - #undef MATRIX + #undef CLASSNAME #undef SIZE #undef TYPE diff --git a/include/rotgen/impl/matrix_model.hpp b/include/rotgen/impl/matrix_model.hpp index f9ccb2c..a4da96b 100644 --- a/include/rotgen/impl/matrix_model.hpp +++ b/include/rotgen/impl/matrix_model.hpp @@ -8,24 +8,24 @@ //================================================================================================== /* - This file is a X-File to generate various matrix_impl_* definitions variant + This file is a X-File to generate various matrix_impl_* declarations variant */ //================================================================================================== -class MATRIX +class CLASSNAME { public: - MATRIX(std::size_t rows = 0, std::size_t cols = 0); - MATRIX(std::size_t rows, std::size_t cols,std::initializer_list init); + CLASSNAME(std::size_t rows = 0, std::size_t cols = 0); + CLASSNAME(std::size_t rows, std::size_t cols,std::initializer_list init); - MATRIX(std::initializer_list> init); + CLASSNAME(std::initializer_list> init); - MATRIX(MATRIX const& other); - MATRIX(MATRIX&&) noexcept; + CLASSNAME(CLASSNAME const& other); + CLASSNAME(CLASSNAME&&) noexcept; - MATRIX& operator=(MATRIX const& other); - MATRIX& operator=(MATRIX&&) noexcept; + CLASSNAME& operator=(CLASSNAME const& other); + CLASSNAME& operator=(CLASSNAME&&) noexcept; - ~MATRIX(); + ~CLASSNAME(); std::size_t rows() const; std::size_t cols() const; @@ -34,9 +34,9 @@ class MATRIX void resize(std::size_t new_rows, std::size_t new_cols); void conservativeResize(std::size_t new_rows, std::size_t new_cols); - MATRIX transpose() const; - MATRIX conjugate() const; - MATRIX adjoint() const; + CLASSNAME transpose() const; + CLASSNAME conjugate() const; + CLASSNAME adjoint() const; void transposeInPlace(); void adjointInPlace(); @@ -60,24 +60,28 @@ class MATRIX TYPE& operator()(std::size_t index); TYPE const& operator()(std::size_t index) const; - MATRIX& operator+=(MATRIX const& rhs); - MATRIX& operator-=(MATRIX const& rhs); - MATRIX operator-() const; - MATRIX& operator*=(MATRIX const& rhs); - MATRIX& operator*=(TYPE d); - MATRIX& operator/=(TYPE d); + CLASSNAME& operator+=(CLASSNAME const& rhs); + CLASSNAME& operator-=(CLASSNAME const& rhs); + CLASSNAME operator-() const; + CLASSNAME& operator*=(CLASSNAME const& rhs); + CLASSNAME& operator*=(TYPE d); + CLASSNAME& operator/=(TYPE d); - friend std::ostream& operator<<(std::ostream&,MATRIX const&); - friend bool operator==(MATRIX const& lhs, MATRIX const& rhs); + friend std::ostream& operator<<(std::ostream&,CLASSNAME const&); + friend bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs); const TYPE* data() const; - static MATRIX Zero(std::size_t rows, std::size_t cols); - static MATRIX Constant(std::size_t rows, std::size_t cols, TYPE value); - static MATRIX Random(std::size_t rows, std::size_t cols); - static MATRIX Identity(std::size_t rows, std::size_t cols); + static CLASSNAME Zero(std::size_t rows, std::size_t cols); + static CLASSNAME Constant(std::size_t rows, std::size_t cols, TYPE value); + static CLASSNAME Random(std::size_t rows, std::size_t cols); + static CLASSNAME Identity(std::size_t rows, std::size_t cols); private: struct payload; std::unique_ptr storage_; + + public: + std::unique_ptr& storage() { return storage_; } + std::unique_ptr const& storage() const { return storage_; } }; \ No newline at end of file diff --git a/include/rotgen/impl/payload.hpp b/include/rotgen/impl/payload.hpp new file mode 100644 index 0000000..9685228 --- /dev/null +++ b/include/rotgen/impl/payload.hpp @@ -0,0 +1,67 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include +#include +#include +#include + +namespace rotgen +{ + //================================================================================================== + // Internal payload - Requried for cross-referencing from block_impl* + //================================================================================================== + struct matrix_impl64_col::payload + { + using data_type = Eigen::Matrix; + + data_type data; + payload(std::size_t r=0, std::size_t c=0) : data(r, c) {} + payload(std::initializer_list> init) : data(init) {} + payload(data_type&& matrix) : data(std::move(matrix)) {} + + void assign(Eigen::Block ref) { data = ref; } + }; + + struct matrix_impl64_row::payload + { + using data_type = Eigen::Matrix; + + data_type data; + payload(std::size_t r=0, std::size_t c=0) : data(r, c) {} + payload(std::initializer_list> init) : data(init) {} + payload(data_type&& matrix) : data(std::move(matrix)) {} + + void assign(Eigen::Block ref) { data = ref; } + }; + + struct matrix_impl32_col::payload + { + using data_type = Eigen::Matrix; + + data_type data; + payload(std::size_t r=0, std::size_t c=0) : data(r, c) {} + payload(std::initializer_list> init) : data(init) {} + payload(data_type&& matrix) : data(std::move(matrix)) {} + + void assign(Eigen::Block ref) { data = ref; } + }; + + struct matrix_impl32_row::payload + { + using data_type = Eigen::Matrix; + + data_type data; + payload(std::size_t r=0, std::size_t c=0) : data(r, c) {} + payload(std::initializer_list> init) : data(init) {} + payload(data_type&& matrix) : data(std::move(matrix)) {} + + void assign(Eigen::Block ref) { data = ref; } + }; +} diff --git a/include/rotgen/matrix.hpp b/include/rotgen/matrix.hpp index 2723930..12e8b68 100644 --- a/include/rotgen/matrix.hpp +++ b/include/rotgen/matrix.hpp @@ -20,10 +20,11 @@ namespace rotgen > class matrix : public find_matrix { - using parent = find_matrix; + using parent = find_matrix; public: - using value_type = Scalar; + using scalar_type = Scalar; + static constexpr auto storage_order = Options & 1; matrix() : parent(Rows==-1?0:Rows,Cols==-1?0:Cols) {} diff --git a/include/rotgen/rotgen.hpp b/include/rotgen/rotgen.hpp new file mode 100644 index 0000000..0726f3e --- /dev/null +++ b/include/rotgen/rotgen.hpp @@ -0,0 +1,12 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include +#include +#include diff --git a/src/block.cpp b/src/block.cpp new file mode 100644 index 0000000..df11c60 --- /dev/null +++ b/src/block.cpp @@ -0,0 +1,58 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include +#include +#include +#include + +namespace rotgen +{ + #define SIZE 64 + #define TYPE double + #define STORAGE_ORDER Eigen::ColMajor + + #define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_col) + #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) + #include "block_model.cpp" + #undef CLASSNAME + #undef SOURCENAME + #undef STORAGE_ORDER + + #define STORAGE_ORDER Eigen::RowMajor + #define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_row) + #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) + #include "block_model.cpp" + #undef CLASSNAME + #undef SOURCENAME + #undef STORAGE_ORDER + + #undef SIZE + #undef TYPE + + #define SIZE 32 + #define TYPE float + #define STORAGE_ORDER Eigen::ColMajor + + #define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_col) + #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) + #include "block_model.cpp" + #undef CLASSNAME + #undef SOURCENAME + #undef STORAGE_ORDER + + #define STORAGE_ORDER Eigen::RowMajor + #define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_row) + #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) + #include "block_model.cpp" + #undef CLASSNAME + #undef SOURCENAME + #undef STORAGE_ORDER + + #undef SIZE + #undef TYPE +} diff --git a/src/block_model.cpp b/src/block_model.cpp new file mode 100644 index 0000000..1756a50 --- /dev/null +++ b/src/block_model.cpp @@ -0,0 +1,172 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== + +//================================================================================================== +/* + This file is a X-File to generate various block_impl_* definitions variant +*/ +//================================================================================================== + +//================================================================================================== +// Internal payload +//================================================================================================== +struct CLASSNAME::payload +{ + using base_type = Eigen::Matrix; + using data_type = Eigen::Block; + + data_type data; + payload (data_type const& o) : data(o) {} + + payload (base_type& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) + : data(r,i0,j0,ni,nj) + {} +}; + + //================================================================================================== + // Constructors & Special Members + //================================================================================================== + CLASSNAME::CLASSNAME(SOURCENAME& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) + : storage_(std::make_unique(r.storage()->data,i0,j0,ni,nj)) + {} + + CLASSNAME::CLASSNAME(CLASSNAME const& o) : storage_(std::make_unique(o.storage_->data)) + {} + + CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o) + { + if (this != &o) storage_->data = o.storage_->data; + return *this; + } + + CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default; + CLASSNAME& CLASSNAME::operator=(CLASSNAME&&) noexcept = default; + + CLASSNAME::~CLASSNAME() = default; + + //================================================================================================== + // Matrix API + //================================================================================================== + std::size_t CLASSNAME::rows() const { return static_cast(storage_->data.rows()); } + std::size_t CLASSNAME::cols() const { return static_cast(storage_->data.cols()); } + std::size_t CLASSNAME::size() const { return static_cast(storage_->data.size()); } + + TYPE& CLASSNAME::operator()(std::size_t i, std::size_t j) { return storage_->data(i,j); } + TYPE const& CLASSNAME::operator()(std::size_t i, std::size_t j) const { return storage_->data(i,j); } + +/* +TYPE& CLASSNAME::operator()(std::size_t index) { return storage_->data(index); } +TYPE const& CLASSNAME::operator()(std::size_t index) const { return storage_->data(index); } +*/ + + const TYPE* CLASSNAME::data() const { return storage_->data.data(); } + +/* +CLASSNAME CLASSNAME::transpose() const +{ + CLASSNAME result(*this); + result.storage_->data.transposeInPlace(); + return result; + +} + +CLASSNAME CLASSNAME::conjugate() const +{ + CLASSNAME result(*this); + result.storage_->data = storage_->data.conjugate(); + return result; +} + +CLASSNAME CLASSNAME::adjoint() const +{ + CLASSNAME result(*this); + result.storage_->data.adjointInPlace(); + return result; +} + +void CLASSNAME::transposeInPlace() +{ + storage_->data.transposeInPlace(); +} + +void CLASSNAME::adjointInPlace() +{ + storage_->data.adjointInPlace(); +} +*/ + +TYPE CLASSNAME::sum() const { return storage_->data.sum(); } +TYPE CLASSNAME::prod() const { return storage_->data.prod(); } +TYPE CLASSNAME::mean() const { return storage_->data.mean(); } +TYPE CLASSNAME::trace() const { return storage_->data.trace(); } + +TYPE CLASSNAME::minCoeff() const { return storage_->data.minCoeff(); } +TYPE CLASSNAME::maxCoeff() const { return storage_->data.maxCoeff(); } + +TYPE CLASSNAME::minCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.minCoeff(row, col); } +TYPE CLASSNAME::maxCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.maxCoeff(row, col); } + +TYPE CLASSNAME::squaredNorm() const { return storage_->data.squaredNorm(); } +TYPE CLASSNAME::norm() const { return storage_->data.norm(); } + +TYPE CLASSNAME::lpNorm(int p) const +{ + if (p == 1) return storage_->data.lpNorm<1>(); + else if (p == 2) return storage_->data.lpNorm<2>(); + else return storage_->data.lpNorm(); +} + +//================================================================================================== +// Operators +//================================================================================================== +std::ostream& operator<<(std::ostream& os,CLASSNAME const& m) +{ + return os << m.storage_->data; +} + +bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs) +{ + return lhs.storage_->data == rhs.storage_->data; +} + +CLASSNAME& CLASSNAME::operator+=(CLASSNAME const& rhs) +{ + storage_->data += rhs.storage_->data; + return *this; +} + +CLASSNAME& CLASSNAME::operator-=(CLASSNAME const& rhs) +{ + storage_->data -= rhs.storage_->data; + return *this; +} + +SOURCENAME CLASSNAME::operator-() const +{ + SOURCENAME result; + result.storage()->assign(storage_->data); + return -result; +} + +CLASSNAME& CLASSNAME::operator*=(CLASSNAME const& rhs) +{ + storage_->data *= rhs.storage_->data; + return *this; +} + +CLASSNAME& CLASSNAME::operator*=(TYPE s) +{ + storage_->data *= s; + return *this; +} + +CLASSNAME& CLASSNAME::operator/=(TYPE s) +{ + storage_->data /= s; + return *this; +} diff --git a/src/matrix.cpp b/src/matrix.cpp index 66ca20d..3d467cd 100644 --- a/src/matrix.cpp +++ b/src/matrix.cpp @@ -7,6 +7,7 @@ //================================================================================================== #include #include +#include #include namespace rotgen @@ -15,15 +16,15 @@ namespace rotgen #define TYPE double #define STORAGE_ORDER Eigen::ColMajor - #define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) + #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #include "matrix_model.cpp" - #undef MATRIX + #undef CLASSNAME #undef STORAGE_ORDER #define STORAGE_ORDER Eigen::RowMajor - #define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) + #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #include "matrix_model.cpp" - #undef MATRIX + #undef CLASSNAME #undef STORAGE_ORDER #undef SIZE @@ -33,15 +34,15 @@ namespace rotgen #define TYPE float #define STORAGE_ORDER Eigen::ColMajor - #define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) + #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #include "matrix_model.cpp" - #undef MATRIX + #undef CLASSNAME #undef STORAGE_ORDER #define STORAGE_ORDER Eigen::RowMajor - #define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) + #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #include "matrix_model.cpp" - #undef MATRIX + #undef CLASSNAME #undef STORAGE_ORDER #undef SIZE diff --git a/src/matrix_model.cpp b/src/matrix_model.cpp index 721d5a6..9b0fb50 100644 --- a/src/matrix_model.cpp +++ b/src/matrix_model.cpp @@ -12,127 +12,114 @@ */ //================================================================================================== -//================================================================================================== -// Internal payload -//================================================================================================== -struct MATRIX::payload -{ - using data_type = Eigen::Matrix; - - data_type data; - payload(std::size_t r=0, std::size_t c=0) : data(r, c) {} - payload(std::initializer_list> init) : data(init) {} - payload(data_type&& matrix) : data(std::move(matrix)) {} -}; - //================================================================================================== // Constructors & Special Members //================================================================================================== -MATRIX::MATRIX(std::size_t r, std::size_t c) : storage_(std::make_unique(r,c)) {} +CLASSNAME::CLASSNAME(std::size_t r, std::size_t c) : storage_(std::make_unique(r,c)) {} -MATRIX::MATRIX(std::initializer_list> init) +CLASSNAME::CLASSNAME(std::initializer_list> init) : storage_(std::make_unique(init)) {} -MATRIX::MATRIX(std::size_t r, std::size_t c,std::initializer_list init) -: MATRIX(r,c) +CLASSNAME::CLASSNAME(std::size_t r, std::size_t c,std::initializer_list init) +: CLASSNAME(r,c) { auto first = init.begin(); for(std::size_t i=0; i < init.size(); i++) (*this)(i) = first[i]; } -MATRIX::MATRIX(MATRIX const& o) - : MATRIX(o.rows(),o.cols()) +CLASSNAME::CLASSNAME(CLASSNAME const& o) + : CLASSNAME(o.rows(),o.cols()) { storage_->data = o.storage_->data; } -MATRIX::MATRIX(MATRIX&&) noexcept = default; +CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default; -MATRIX& MATRIX::operator=(MATRIX const& o) +CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o) { if (this != &o) storage_->data = o.storage_->data; return *this; } -MATRIX& MATRIX::operator=(MATRIX&&) noexcept = default; +CLASSNAME& CLASSNAME::operator=(CLASSNAME&&) noexcept = default; -MATRIX::~MATRIX() = default; +CLASSNAME::~CLASSNAME() = default; //================================================================================================== // Matrix API //================================================================================================== -std::size_t MATRIX::rows() const { return static_cast(storage_->data.rows()); } -std::size_t MATRIX::cols() const { return static_cast(storage_->data.cols()); } -std::size_t MATRIX::size() const { return static_cast(storage_->data.size()); } +std::size_t CLASSNAME::rows() const { return static_cast(storage_->data.rows()); } +std::size_t CLASSNAME::cols() const { return static_cast(storage_->data.cols()); } +std::size_t CLASSNAME::size() const { return static_cast(storage_->data.size()); } -void MATRIX::resize(std::size_t new_rows, std::size_t new_cols) +void CLASSNAME::resize(std::size_t new_rows, std::size_t new_cols) { storage_->data.resize(new_rows, new_cols); } -void MATRIX::conservativeResize(std::size_t new_rows, std::size_t new_cols) +void CLASSNAME::conservativeResize(std::size_t new_rows, std::size_t new_cols) { storage_->data.conservativeResize(new_rows, new_cols); } -TYPE& MATRIX::operator()(std::size_t i, std::size_t j) { return storage_->data(i,j); } -TYPE const& MATRIX::operator()(std::size_t i, std::size_t j) const { return storage_->data(i,j); } +TYPE& CLASSNAME::operator()(std::size_t i, std::size_t j) { return storage_->data(i,j); } +TYPE const& CLASSNAME::operator()(std::size_t i, std::size_t j) const { return storage_->data(i,j); } -TYPE& MATRIX::operator()(std::size_t index) { return storage_->data(index); } -TYPE const& MATRIX::operator()(std::size_t index) const { return storage_->data(index); } +TYPE& CLASSNAME::operator()(std::size_t index) { return storage_->data(index); } +TYPE const& CLASSNAME::operator()(std::size_t index) const { return storage_->data(index); } -const TYPE* MATRIX::data() const { return storage_->data.data(); } +const TYPE* CLASSNAME::data() const { return storage_->data.data(); } -MATRIX MATRIX::transpose() const +CLASSNAME CLASSNAME::transpose() const { - MATRIX result(*this); + CLASSNAME result(*this); result.storage_->data.transposeInPlace(); return result; } -MATRIX MATRIX::conjugate() const +CLASSNAME CLASSNAME::conjugate() const { - MATRIX result(*this); + CLASSNAME result(*this); result.storage_->data = storage_->data.conjugate(); return result; } -MATRIX MATRIX::adjoint() const +CLASSNAME CLASSNAME::adjoint() const { - MATRIX result(*this); + CLASSNAME result(*this); result.storage_->data.adjointInPlace(); return result; } -void MATRIX::transposeInPlace() +void CLASSNAME::transposeInPlace() { storage_->data.transposeInPlace(); } -void MATRIX::adjointInPlace() +void CLASSNAME::adjointInPlace() { storage_->data.adjointInPlace(); } -TYPE MATRIX::sum() const { return storage_->data.sum(); } -TYPE MATRIX::prod() const { return storage_->data.prod(); } -TYPE MATRIX::mean() const { return storage_->data.mean(); } -TYPE MATRIX::trace() const { return storage_->data.trace(); } +TYPE CLASSNAME::sum() const { return storage_->data.sum(); } +TYPE CLASSNAME::prod() const { return storage_->data.prod(); } +TYPE CLASSNAME::mean() const { return storage_->data.mean(); } +TYPE CLASSNAME::trace() const { return storage_->data.trace(); } -TYPE MATRIX::minCoeff() const { return storage_->data.minCoeff(); } -TYPE MATRIX::maxCoeff() const { return storage_->data.maxCoeff(); } +TYPE CLASSNAME::minCoeff() const { return storage_->data.minCoeff(); } +TYPE CLASSNAME::maxCoeff() const { return storage_->data.maxCoeff(); } -TYPE MATRIX::minCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.minCoeff(row, col); } -TYPE MATRIX::maxCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.maxCoeff(row, col); } +TYPE CLASSNAME::minCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.minCoeff(row, col); } +TYPE CLASSNAME::maxCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.maxCoeff(row, col); } -TYPE MATRIX::squaredNorm() const { return storage_->data.squaredNorm(); } -TYPE MATRIX::norm() const { return storage_->data.norm(); } +TYPE CLASSNAME::squaredNorm() const { return storage_->data.squaredNorm(); } +TYPE CLASSNAME::norm() const { return storage_->data.norm(); } -TYPE MATRIX::lp_norm(int p) const +TYPE CLASSNAME::lp_norm(int p) const { if (p == 1) return storage_->data.lpNorm<1>(); else if (p == 2) return storage_->data.lpNorm<2>(); @@ -142,48 +129,48 @@ TYPE MATRIX::lp_norm(int p) const //================================================================================================== // Operators //================================================================================================== -std::ostream& operator<<(std::ostream& os,MATRIX const& m) +std::ostream& operator<<(std::ostream& os,CLASSNAME const& m) { return os << m.storage_->data; } -bool operator==(MATRIX const& lhs, MATRIX const& rhs) +bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs) { return lhs.storage_->data == rhs.storage_->data; } -MATRIX& MATRIX::operator+=(MATRIX const& rhs) +CLASSNAME& CLASSNAME::operator+=(CLASSNAME const& rhs) { storage_->data += rhs.storage_->data; return *this; } -MATRIX& MATRIX::operator-=(MATRIX const& rhs) +CLASSNAME& CLASSNAME::operator-=(CLASSNAME const& rhs) { storage_->data -= rhs.storage_->data; return *this; } -MATRIX MATRIX::operator-() const +CLASSNAME CLASSNAME::operator-() const { - MATRIX result(*this); + CLASSNAME result(*this); result.storage_->data = -result.storage_->data; return result; } -MATRIX& MATRIX::operator*=(MATRIX const& rhs) +CLASSNAME& CLASSNAME::operator*=(CLASSNAME const& rhs) { storage_->data *= rhs.storage_->data; return *this; } -MATRIX& MATRIX::operator*=(TYPE s) +CLASSNAME& CLASSNAME::operator*=(TYPE s) { storage_->data *= s; return *this; } -MATRIX& MATRIX::operator/=(TYPE s) +CLASSNAME& CLASSNAME::operator/=(TYPE s) { storage_->data /= s; return *this; @@ -193,30 +180,30 @@ MATRIX& MATRIX::operator/=(TYPE s) // Static functions //================================================================================================== -MATRIX MATRIX::Zero(std::size_t rows, std::size_t cols) +CLASSNAME CLASSNAME::Zero(std::size_t rows, std::size_t cols) { - MATRIX m; + CLASSNAME m; m.storage_ = std::make_unique(payload::data_type::Zero(rows, cols)); return m; } -MATRIX MATRIX::Constant(std::size_t rows, std::size_t cols, TYPE value) +CLASSNAME CLASSNAME::Constant(std::size_t rows, std::size_t cols, TYPE value) { - MATRIX m; + CLASSNAME m; m.storage_ = std::make_unique(payload::data_type::Constant(rows, cols, value)); return m; } -MATRIX MATRIX::Random(std::size_t rows, std::size_t cols) +CLASSNAME CLASSNAME::Random(std::size_t rows, std::size_t cols) { - MATRIX m; + CLASSNAME m; m.storage_ = std::make_unique(payload::data_type::Random(rows, cols)); return m; } -MATRIX MATRIX::Identity(std::size_t rows, std::size_t cols) +CLASSNAME CLASSNAME::Identity(std::size_t rows, std::size_t cols) { - MATRIX m; + CLASSNAME m; m.storage_ = std::make_unique(payload::data_type::Identity(rows, cols)); return m; } \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e3f0df6..301f714 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,5 +17,6 @@ target_link_libraries(rotgen_test INTERFACE rotgen Eigen3::Eigen) ##====================================================================================================================== ## Unit Tests registration ##====================================================================================================================== -rotgen_glob_unit(PATTERN "unit/basic/*.cpp" INTERFACE rotgen_test) rotgen_glob_unit(PATTERN "unit/free_functions/*.cpp" INTERFACE rotgen_test) +rotgen_glob_unit(PATTERN "unit/matrix/*.cpp" INTERFACE rotgen_test) +rotgen_glob_unit(PATTERN "unit/block/*.cpp" INTERFACE rotgen_test) diff --git a/test/unit/block/arithmetic_functions.cpp b/test/unit/block/arithmetic_functions.cpp new file mode 100644 index 0000000..4609d44 --- /dev/null +++ b/test/unit/block/arithmetic_functions.cpp @@ -0,0 +1,97 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include "unit/tests.hpp" +#include +#include +#include +#include + +template +void compare_reductions(const Block1& block, const Block2& ref) +{ + constexpr double epsilon = 0.0001; + TTS_RELATIVE_EQUAL(block.sum(), ref.sum(), epsilon); + TTS_RELATIVE_EQUAL(block.prod(), ref.prod(), epsilon); + TTS_RELATIVE_EQUAL(block.mean(), ref.mean(), epsilon); + TTS_EQUAL(block.trace(), ref.trace()); + TTS_EQUAL(block.minCoeff(), ref.minCoeff()); + TTS_EQUAL(block.maxCoeff(), ref.maxCoeff()); + + std::ptrdiff_t row, col, ref_row, ref_col; + + TTS_EQUAL(block.minCoeff(&row, &col), ref.minCoeff(&ref_row, &ref_col)); + TTS_EQUAL(row, ref_row); + TTS_EQUAL(col, ref_col); + + TTS_EQUAL(block.maxCoeff(&row, &col), ref.maxCoeff(&ref_row, &ref_col)); + TTS_EQUAL(row, ref_row); + TTS_EQUAL(col, ref_col); +} + +template +void test_dynamic_block_reductions(rotgen::tests::matrix_block_test_case const& matrix_construct) +{ + using EigenMatrix = Eigen::Matrix; + + MatrixType original(matrix_construct.rows, matrix_construct.cols); + EigenMatrix ref(matrix_construct.rows, matrix_construct.cols); + + for (std::size_t r = 0; r < matrix_construct.rows; ++r) + for (std::size_t c = 0; c < matrix_construct.cols; ++c) + ref(r, c) = original(r,c) = static_cast(matrix_construct.init_fn(r, c)); + + std::vector, Eigen::Block>> test_cases { + { rotgen::extract(original, matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj), + ref.block(matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj) }, + + { rotgen::topLeftCorner(original, matrix_construct.ni, matrix_construct.nj), + ref.topLeftCorner(matrix_construct.ni, matrix_construct.nj) }, + { rotgen::topRightCorner(original, matrix_construct.ni, matrix_construct.nj), + ref.topRightCorner(matrix_construct.ni, matrix_construct.nj) }, + { rotgen::bottomLeftCorner(original, matrix_construct.ni, matrix_construct.nj), + ref.bottomLeftCorner(matrix_construct.ni, matrix_construct.nj) }, + { rotgen::bottomRightCorner(original, matrix_construct.ni, matrix_construct.nj), + ref.bottomRightCorner(matrix_construct.ni, matrix_construct.nj) }, + + { rotgen::topRows(original, matrix_construct.ni), + ref.topRows(matrix_construct.ni) }, + { rotgen::middleRows(original, matrix_construct.i0, matrix_construct.ni), + ref.middleRows(matrix_construct.i0, matrix_construct.ni) }, + { rotgen::bottomRows(original, matrix_construct.ni), + ref.bottomRows(matrix_construct.ni) }, + }; + + for (const auto& [original_block, ref_block] : test_cases) + compare_reductions(original_block, ref_block); +} + +TTS_CASE_TPL("Test dynamic block reductions", rotgen::tests::types) +( tts::type< tts::types> ) +{ + using mat_t = rotgen::matrix; + + std::vector> test_cases = + { + {6, 5, [](auto r, auto c) {return r + c; }, 1, 2, 3, 2}, + {9, 11, [](auto r, auto c) {return r + c; }, 0, 1, 4, 9}, + {3, 3, [](auto , auto ) {return 0.0; }, 1, 1, 1, 1}, + {1, 4, [](auto r, auto c) {return -r -c*c - 1234; }, 0, 0, 1, 1}, + {4, 1, [](auto , auto ) {return 7.0; }, 2, 0, 2, 1}, + {1, 1, [](auto , auto ) {return 42.0; }, 0, 0, 1, 1}, + {12, 13, [](auto r, auto c) {return std::sin(r + c); }, 2, 3, 4, 5 }, + {4, 9, [](auto r, auto c) {return -1.5 * r + 2.56 * c; }, 0, 1, 2, 3 }, + {2, 5, [](auto r, auto c) {return (r == c ? 1.0 : 0.0); }, 1, 1, 1, 1}, + }; + + for (const auto& test_case : test_cases) + test_dynamic_block_reductions(test_case); + + +}; diff --git a/test/unit/block/extract.cpp b/test/unit/block/extract.cpp new file mode 100644 index 0000000..0b20451 --- /dev/null +++ b/test/unit/block/extract.cpp @@ -0,0 +1,266 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include "unit/tests.hpp" +#include +#include + +template +void for_each_element(EigenType const& m, F&& f) +{ + for(std::size_t i = 0; i < m.rows(); ++i) + for(std::size_t j = 0; j < m.cols(); ++j) + f(i, j, m(i,j)); +} + +template +void for_each_element(EigenType& m, F&& f) +{ + for(std::size_t i = 0; i < m.rows(); ++i) + for(std::size_t j = 0; j < m.cols(); ++j) + f(i, j, m(i,j)); +} + +template +MatrixType make_initialized_matrix(rotgen::tests::matrix_block_test_case const& matrix_construct) +{ + MatrixType matrix(matrix_construct.rows, matrix_construct.cols); + + for(std::size_t i = 0; i < matrix_construct.rows; ++i) + for(std::size_t j = 0; j < matrix_construct.cols; ++j) + matrix(i, j) = static_cast(matrix_construct.init_fn(i, j)); + + return matrix; +} + +template +void validate_block_behavior(MatrixType& matrix, BlockType& block, + std::size_t i0, std::size_t j0, + std::size_t ni, std::size_t nj) +{ + TTS_EQUAL(block.rows(), ni); + TTS_EQUAL(block.cols(), nj); + TTS_EQUAL(block.size(), ni * nj); + + // test block values + for_each_element(block, [&](auto i, auto j, auto val) { + TTS_EQUAL(val, matrix(i0 + i, j0 + j)); + }); + + // test aliasing + T value = 1; + for_each_element(block, [&](auto i, auto j, auto&) { + block(i, j) = value++; + }); + + value = 1; + for_each_element(block, [&](auto i, auto j, auto&) { + TTS_EQUAL(matrix(i0 + i, j0 + j), value++); + }); + + for_each_element(block, [&](auto i, auto j, auto&) { + matrix(i0 + i, j0 + j) = T(42); + }); + + for_each_element(block, [&](auto&, auto&, auto val) { + TTS_EQUAL(val, T(42)); + }); +} + +template +void test_dynamic_block_extraction(rotgen::tests::matrix_block_test_case const& matrix_construct) +{ + MatrixType matrix = make_initialized_matrix(matrix_construct); + + auto block_main = rotgen::extract(matrix, matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj); + auto block_top_left_corner = rotgen::topLeftCorner(matrix, matrix_construct.ni, matrix_construct.nj); + auto block_top_right_corner = rotgen::topRightCorner(matrix, matrix_construct.ni, matrix_construct.nj); + auto block_bottom_left_corner = rotgen::bottomLeftCorner(matrix, matrix_construct.ni, matrix_construct.nj); + auto block_bottom_right_corner = rotgen::bottomRightCorner(matrix, matrix_construct.ni, matrix_construct.nj); + + auto block_top_rows = rotgen::topRows(matrix, matrix_construct.ni); + auto block_middle_rows = rotgen::middleRows(matrix, matrix_construct.i0, matrix_construct.ni); + auto block_bottom_rows = rotgen::bottomRows(matrix, matrix_construct.ni); + + auto block_left_cols = rotgen::leftCols(matrix, matrix_construct.nj); + auto block_middle_cols = rotgen::middleCols(matrix, matrix_construct.j0, matrix_construct.nj); + auto block_right_cols = rotgen::rightCols(matrix, matrix_construct.nj); + + auto blocks = std::make_tuple( + std::make_tuple(block_main, matrix_construct.i0, matrix_construct.j0, matrix_construct.ni, matrix_construct.nj), + std::make_tuple(block_top_left_corner, 0, 0, matrix_construct.ni, matrix_construct.nj), + std::make_tuple(block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, matrix_construct.ni, matrix_construct.nj), + std::make_tuple(block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix_construct.nj), + std::make_tuple(block_bottom_right_corner, matrix.rows() - matrix_construct.ni, matrix.cols() - matrix_construct.nj, + matrix_construct.ni, matrix_construct.nj), + + std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols()), + std::make_tuple(block_middle_rows, matrix_construct.i0, 0, matrix_construct.ni, matrix.cols()), + std::make_tuple(block_bottom_rows, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix.cols()), + + std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj), + std::make_tuple(block_middle_cols, 0, matrix_construct.j0, matrix.rows(), matrix_construct.nj), + std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj, matrix.rows(), matrix_construct.nj) + ); + + std::apply([&](auto&&... block_entries) + { + (([&] + { + auto&& [block, i_offset, j_offset, ni, nj] = block_entries; + using block_t = std::remove_reference_t; + + TTS_EQUAL(block_t::RowsAtCompileTime, rotgen::Dynamic); + TTS_EQUAL(block_t::ColsAtCompileTime, rotgen::Dynamic); + TTS_EQUAL(block_t::storage_order, MatrixType::storage_order); + + validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj); + })(), ...); + }, blocks); + +} + +template +void test_static_block_extraction(rotgen::tests::static_matrix_block_test_case const& matrix_construct) +{ + MatrixType matrix(matrix_construct.rows, matrix_construct.cols); + + for (std::size_t i = 0; i < matrix_construct.rows; ++i) + for (std::size_t j = 0; j < matrix_construct.cols; ++j) + matrix(i, j) = static_cast(matrix_construct.init_fn(i, j)); + + auto block_main = rotgen::extract(matrix, matrix_construct.i0, matrix_construct.j0); + auto block_top_left_corner = rotgen::topLeftCorner(matrix); + auto block_top_right_corner = rotgen::topRightCorner(matrix); + auto block_bottom_left_corner = rotgen::bottomLeftCorner(matrix); + auto block_bottom_right_corner = rotgen::bottomRightCorner(matrix); + + auto block_top_rows = rotgen::topRows(matrix); + auto block_middle_rows = rotgen::middleRows(matrix, matrix_construct.i0); + auto block_bottom_rows = rotgen::bottomRows(matrix); + + auto block_left_cols = rotgen::leftCols(matrix); + auto block_middle_cols = rotgen::middleCols(matrix, matrix_construct.j0); + auto block_right_cols = rotgen::rightCols(matrix); + + auto block_row = rotgen::row(matrix, matrix_construct.i0); + auto block_col = rotgen::col(matrix, matrix_construct.j0); + + auto blocks = std::make_tuple( + std::make_tuple(block_main, matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1), + std::make_tuple(block_top_left_corner, 0, 0, + matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1), + std::make_tuple(block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, + matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1), + std::make_tuple(block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, + matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1), + std::make_tuple(block_bottom_right_corner, matrix.rows() - matrix_construct.ni, + matrix.cols() - matrix_construct.nj, matrix_construct.ni, + matrix_construct.nj, int(NI), int(NJ), -1), + + std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic, -1), + std::make_tuple(block_middle_rows, matrix_construct.i0, 0, matrix_construct.ni, + matrix.cols(), int(NI), rotgen::Dynamic, -1), + std::make_tuple(block_bottom_rows, matrix.rows() - matrix_construct.ni, + 0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic, -1), + + std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ), -1), + std::make_tuple(block_middle_cols, 0, matrix_construct.j0, + matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ), -1), + std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj, + matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ), -1), + + std::make_tuple(block_row, matrix_construct.i0, 0, + 1, matrix.cols(), 1, rotgen::Dynamic, 1), + std::make_tuple(block_col, 0, matrix_construct.j0, + matrix.rows(), 1, rotgen::Dynamic, 1, 0) + ); + + std::apply([&](auto&&... block_entries) + { + (([&] + { + auto&& [block, i_offset, j_offset, ni, nj, rows_ct, cols_ct, storage_order] = block_entries; + using block_t = std::remove_reference_t; + + TTS_EQUAL(block_t::RowsAtCompileTime, rows_ct); + TTS_EQUAL(block_t::ColsAtCompileTime, cols_ct); + + auto expected_storage_order = (storage_order == -1) ? MatrixType::storage_order : storage_order; + TTS_EQUAL(block_t::storage_order, expected_storage_order); + + validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj); + })(), ...); + }, blocks); +} + +TTS_CASE_TPL("Check all dynamic block extractions on a dynamic row-major matrix", rotgen::tests::types) +( tts::type< tts::types> ) +{ + using mat_t = rotgen::matrix; + + std::vector> cases = { + { 6, 11, [](std::size_t i, std::size_t j) { return T(i * 10 + j); }, 1, 2, 3, 2 }, + { 7, 10, [](std::size_t i, std::size_t j) { return T(std::sin(i + j)); }, 4, 4, 3, 3 }, + { 5, 5, [](std::size_t i, std::size_t j) { return T((i + j) % 7); }, 0, 0, 5, 5 }, + { 9, 14, [](std::size_t i, std::size_t j) { return T(i+j + 3*j); }, 3, 7, 1, 1 } + }; + + for (auto const& matrix_case : cases) { + test_dynamic_block_extraction(matrix_case); + } + +}; + +TTS_CASE_TPL("Check all dynamic block extractions on a static column-major matrix", rotgen::tests::types) +( tts::type< tts::types> ) +{ + using mat_t = rotgen::matrix; + + std::vector> cases = { + { 4, 5, [](std::size_t i, std::size_t j) { return T(2*i + j*j*j - 42); }, 1, 2, 3, 2 }, + { 4, 5, [](std::size_t i, std::size_t j) { return T(std::tan(i*i*j)); }, 0, 1, 2, 1 }, + { 4, 5, [](std::size_t i, std::size_t j) { return T((i*i + j*j) / 6); }, 2, 0, 0, 0 } + }; + + for (auto const& matrix_case : cases) { + test_dynamic_block_extraction(matrix_case); + } + +}; + +TTS_CASE_TPL("Check all static block extractions", rotgen::tests::types) +( tts::type< tts::types> ) +{ + using mat_t = rotgen::matrix; + + test_static_block_extraction( + rotgen::tests::static_matrix_block_test_case{ + 11, 11, + [](std::size_t i, std::size_t j) { return T(i*i*i + 3*j - 127); }, + 3, 2 + } + ); + + test_static_block_extraction( + rotgen::tests::static_matrix_block_test_case{ + 14, 15, + [](std::size_t i, std::size_t j) { return T(std::cos(i * j * 2)); }, + 5, 1 + } + ); + + test_static_block_extraction( + rotgen::tests::static_matrix_block_test_case{ + 5, 5, + [](std::size_t i, std::size_t j) { return T((i + j) % 9); }, + 0, 0 + } + ); +}; \ No newline at end of file diff --git a/test/unit/block/norms.cpp b/test/unit/block/norms.cpp new file mode 100644 index 0000000..7a30347 --- /dev/null +++ b/test/unit/block/norms.cpp @@ -0,0 +1,49 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include "unit/tests.hpp" +#include +#include +#include + +TTS_CASE_TPL("Matrix norm-related operations", rotgen::tests::types) +( tts::type< tts::types> ) +{ + using mat_t = rotgen::matrix; + + std::vector> test_cases = + { + {6, 5, [](auto r, auto c) {return r + c; }, 1, 2, 3, 2}, + {9, 11, [](auto r, auto c) {return r + c; }, 0, 1, 4, 9}, + {3, 3, [](auto , auto ) {return 0.0; }, 1, 1, 1, 1}, + {1, 4, [](auto r, auto c) {return -r -c*c - 1234; }, 0, 0, 1, 1}, + {4, 1, [](auto , auto ) {return 7.0; }, 2, 0, 2, 1}, + {1, 1, [](auto , auto ) {return 42.0; }, 0, 0, 1, 1}, + {12, 13, [](auto r, auto c) {return std::sin(r + c); }, 2, 3, 4, 5 }, + {4, 9, [](auto r, auto c) {return -1.5 * r + 2.56 * c; }, 0, 1, 2, 3 }, + {2, 5, [](auto r, auto c) {return (r == c ? 1.0 : 0.0); }, 1, 1, 1, 1}, + }; + + for (const auto& [rows, cols, fn, i0, j0, ni, nj] : test_cases) + { + rotgen::matrix original_matrix(rows, cols); + Eigen::Matrix ref_matrix(rows, cols); + + for (std::size_t r = 0; r < rows; ++r) + for (std::size_t c = 0; c < cols; ++c) + ref_matrix(r, c) = original_matrix(r, c) = fn(r,c); + + auto original_block = rotgen::extract(original_matrix, i0, j0, ni, nj); + auto ref_block = ref_matrix.block(i0, j0, ni, nj); + + TTS_EQUAL(original_block.norm(), ref_block.norm()); + TTS_EQUAL(original_block.squaredNorm(), ref_block.squaredNorm()); + TTS_EQUAL(original_block.template lpNorm<1>() , ref_block.template lpNorm<1>()); + TTS_EQUAL(original_block.template lpNorm<2>() , ref_block.template lpNorm<2>()); + TTS_EQUAL(original_block.template lpNorm(), ref_block.template lpNorm()); + } +}; \ No newline at end of file diff --git a/test/unit/block/operators.cpp b/test/unit/block/operators.cpp new file mode 100644 index 0000000..62ea4a7 --- /dev/null +++ b/test/unit/block/operators.cpp @@ -0,0 +1,274 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include "unit/tests.hpp" +#include +#include +#include + +template +void test_block_matrix_operations(rotgen::tests::matrix_block_test_case const& matrix_construct, + auto b_init_fn, auto self_ops) +{ + using EigenMatrix = Eigen::Matrix; + + MatrixType a(matrix_construct.rows, matrix_construct.cols); + MatrixType b(matrix_construct.rows, matrix_construct.cols); + EigenMatrix ref_a(matrix_construct.rows, matrix_construct.cols); + EigenMatrix ref_b(matrix_construct.rows, matrix_construct.cols); + + for (std::size_t r = 0; r < matrix_construct.rows; ++r) + { + for (std::size_t c = 0; c < matrix_construct.cols; ++c) + { + ref_a(r,c) = a(r,c) = static_cast(matrix_construct.init_fn(r, c)); + ref_b(r,c) = b(r,c) = static_cast(b_init_fn(r, c)); + } + } + + auto a_block = rotgen::extract(a, matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj); + auto b_block = rotgen::extract(b, matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj); + auto ref_a_block = ref_a.block(matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj); + auto ref_b_block = ref_b.block(matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj); + + /*auto result_block = ops(a_block, b_block); + auto ref_result_block = ops(ref_a_block, ref_b_block); + + for (std::size_t r = 0; r < matrix_construct.ni; ++r) + for (std::size_t c = 0; c < matrix_construct.nj; ++c) + TTS_EQUAL(result_block(r, c), ref_result_block(r, c));*/ + + self_ops(a_block,b_block); + self_ops(ref_a_block, ref_b_block); + + for (std::size_t r = 0; r < matrix_construct.ni; ++r) + for (std::size_t c = 0; c < matrix_construct.nj; ++c) + TTS_EQUAL(a_block(r, c), ref_a_block(r, c)); + + for (std::size_t r = 0; r < matrix_construct.rows; ++r) + { + for (std::size_t c = 0; c < matrix_construct.cols; ++c) + { + TTS_EQUAL(a(r, c), ref_a(r, c)); + TTS_EQUAL(b(r, c), ref_b(r, c)); + } + } +} + +template +void test_block_scalar_operations(rotgen::tests::matrix_block_test_case const& matrix_construct, + auto scalar, auto self_ops) +{ + using EigenMatrix = Eigen::Matrix; + + MatrixType a(matrix_construct.rows, matrix_construct.cols); + EigenMatrix ref_a(matrix_construct.rows, matrix_construct.cols); + + for (std::size_t r = 0; r < matrix_construct.rows; ++r) + for (std::size_t c = 0; c < matrix_construct.cols; ++c) + ref_a(r,c) = a(r,c) = static_cast(matrix_construct.init_fn(r, c)); + + auto a_block = rotgen::extract(a, matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj); + auto ref_a_block = ref_a.block(matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj); + + //TTS_EQUAL(ops(a, s), ref); + + self_ops(a_block,scalar); + self_ops(ref_a_block, scalar); + + for (std::size_t r = 0; r < matrix_construct.ni; ++r) + for (std::size_t c = 0; c < matrix_construct.nj; ++c) + TTS_EQUAL(a_block(r, c), ref_a_block(r, c)); + + for (std::size_t r = 0; r < matrix_construct.rows; ++r) + for (std::size_t c = 0; c < matrix_construct.cols; ++c) + TTS_EQUAL(a(r, c), ref_a(r, c)); +} + +template +void test_scalar_block_multiplications(rotgen::tests::matrix_block_test_case const& matrix_construct, + T scalar) +{ + using EigenMatrix = Eigen::Matrix; + + MatrixType a(matrix_construct.rows, matrix_construct.cols); + EigenMatrix ref_a(matrix_construct.rows, matrix_construct.cols); + + for (std::size_t r = 0; r < matrix_construct.rows; ++r) + for (std::size_t c = 0; c < matrix_construct.cols; ++c) + ref_a(r,c) = a(r,c) = static_cast(matrix_construct.init_fn(r, c)); + + auto a_block = rotgen::extract(a, matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj); + auto ref_a_block = ref_a.block(matrix_construct.i0, matrix_construct.j0, + matrix_construct.ni, matrix_construct.nj); + + //TTS_EQUAL(a * s, ref); + //TTS_EQUAL(s * a, ref); + + a_block *= scalar; + ref_a_block *= scalar; + + for (std::size_t r = 0; r < matrix_construct.ni; ++r) + for (std::size_t c = 0; c < matrix_construct.nj; ++c) + TTS_EQUAL(a_block(r, c), ref_a_block(r, c)); + + for (std::size_t r = 0; r < matrix_construct.rows; ++r) + for (std::size_t c = 0; c < matrix_construct.cols; ++c) + TTS_EQUAL(a(r, c), ref_a(r, c)); +} + +template +void test_block_multiplication(rotgen::tests::matrix_block_test_case const& a_matrix_construct, + rotgen::tests::matrix_block_test_case const& b_matrix_construct) +{ + using EigenMatrix = Eigen::Matrix; + + MatrixType a(a_matrix_construct.rows, a_matrix_construct.cols); + MatrixType b(b_matrix_construct.rows, b_matrix_construct.cols); + EigenMatrix ref_a(a_matrix_construct.rows, a_matrix_construct.cols); + EigenMatrix ref_b(b_matrix_construct.rows, b_matrix_construct.cols); + + for (std::size_t r = 0; r < a_matrix_construct.rows; ++r) + for (std::size_t c = 0; c < a_matrix_construct.cols; ++c) + ref_a(r,c) = a(r,c) = static_cast(a_matrix_construct.init_fn(r, c)); + + for (std::size_t r = 0; r < b_matrix_construct.rows; ++r) + for (std::size_t c = 0; c < b_matrix_construct.cols; ++c) + ref_b(r,c) = b(r,c) = static_cast(b_matrix_construct.init_fn(r, c)); + + + auto a_block = rotgen::extract(a, a_matrix_construct.i0, a_matrix_construct.j0, + a_matrix_construct.ni, a_matrix_construct.nj); + auto b_block = rotgen::extract(b, b_matrix_construct.i0, b_matrix_construct.j0, + b_matrix_construct.ni, b_matrix_construct.nj); + auto ref_a_block = ref_a.block(a_matrix_construct.i0, a_matrix_construct.j0, + a_matrix_construct.ni, a_matrix_construct.nj); + auto ref_b_block = ref_b.block(b_matrix_construct.i0, b_matrix_construct.j0, + b_matrix_construct.ni, b_matrix_construct.nj); + + // a * b + a_block *= b_block; + ref_a_block *= ref_b_block; + + for (std::size_t r = 0; r < a_matrix_construct.ni; ++r) + for (std::size_t c = 0; c < a_matrix_construct.nj; ++c) + TTS_EQUAL(a_block(r, c), ref_a_block(r, c)); + + for (std::size_t r = 0; r < a_matrix_construct.rows; ++r) + for (std::size_t c = 0; c < a_matrix_construct.cols; ++c) + TTS_EQUAL(a(r, c), ref_a(r, c)); + + for (std::size_t r = 0; r < b_matrix_construct.rows; ++r) + for (std::size_t c = 0; c < b_matrix_construct.cols; ++c) + TTS_EQUAL(b(r, c), ref_b(r, c)); +} + +// Basic initializers +inline constexpr auto init_a = [](auto r, auto c) { return 9.9*r*r*r - 6*c -12; }; +inline constexpr auto init_b = [](auto r, auto c) { return 3.1*r + 4.2*c - 12.3; }; +inline constexpr auto init_0 = [](auto , auto ) { return 0; }; + +TTS_CASE_TPL("Check block addition", rotgen::tests::types) +( tts::type< tts::types> ) +{ + using mat_t = rotgen::matrix; + //auto op = [](auto a, auto b) { return a + b; }; + auto s_op = [](auto& a, auto b) { return a += b; }; + + //test_block_matrix_operations({1 , 1, init_a, 0, 0, 1, 1}, init_b, op, s_op); + test_block_matrix_operations({1 , 1, init_a, 0, 0, 1, 1}, init_b, s_op); + test_block_matrix_operations({13 , 15, init_a, 1, 2, 3, 4}, init_b, s_op); + test_block_matrix_operations({5 , 9, init_a, 2, 2, 2, 2}, init_b, s_op); + test_block_matrix_operations({15 , 15, init_a, 3, 4, 5, 5}, init_b, s_op); + test_block_matrix_operations({5 , 5, init_b, 1, 0, 3, 2}, init_a, s_op); + test_block_matrix_operations({10, 1, init_a, 0, 0, 5, 1}, init_b, s_op); + test_block_matrix_operations({1 , 10, init_a, 0, 0, 1, 5}, init_b, s_op); + test_block_matrix_operations({21 , 5, init_0, 4, 4, 10, 1}, init_b, s_op); + test_block_matrix_operations({11 , 7, init_a, 2, 0, 7, 5}, init_0, s_op); +}; + + +TTS_CASE_TPL("Check block subtraction", rotgen::tests::types) +( tts::type< tts::types> ) +{ + using mat_t = rotgen::matrix; + //auto op = [](auto a, auto b) { return a - b; }; + auto s_op = [](auto& a, auto b) { return a -= b; }; + + //test_block_matrix_operations({1 , 1, init_a, 0, 0, 1, 1}, init_b, op, s_op); + test_block_matrix_operations({1 , 1, init_a, 0, 0, 1, 1}, init_b, s_op); + test_block_matrix_operations({13 , 15, init_a, 1, 2, 3, 4}, init_b, s_op); + test_block_matrix_operations({5 , 9, init_a, 2, 2, 2, 2}, init_b, s_op); + test_block_matrix_operations({15 , 15, init_a, 3, 4, 5, 5}, init_b, s_op); + test_block_matrix_operations({5 , 5, init_b, 1, 0, 3, 2}, init_a, s_op); + test_block_matrix_operations({10, 1, init_a, 0, 0, 5, 1}, init_b, s_op); + test_block_matrix_operations({1 , 10, init_a, 0, 0, 1, 5}, init_b,s_op); + test_block_matrix_operations({21 , 5, init_0, 4, 4, 10, 1}, init_b, s_op); + test_block_matrix_operations({11 , 7, init_a, 2, 0, 7, 5}, init_0, s_op); +}; + + +TTS_CASE_TPL("Check block multiplications", rotgen::tests::types) +( tts::type< tts::types> ) +{ + using mat_t = rotgen::matrix; + auto init_id = [](auto r, auto c) { return r == c ? 1 : 0; }; + + test_block_multiplication({1 , 1, init_a, 0, 0, 1, 1}, {1 , 1, init_b, 0, 0, 1, 1}); + test_block_multiplication({13 , 15, init_b, 1, 2, 4, 4}, {13 , 15, init_b, 0, 1, 4, 4}); + test_block_multiplication({6 , 9, init_a, 2, 2, 2, 2}, {5 , 9, init_b, 2, 2, 2, 2}); + test_block_multiplication({15 , 15, init_a, 3, 4, 5, 5}, {15 , 15, init_b, 0, 0, 5, 5}); + test_block_multiplication({5 , 5, init_b, 1, 0, 3, 3}, {5 , 5, init_a, 0, 0, 3, 3}); + test_block_multiplication({11 , 3, init_id, 2, 0, 2, 2}, {18 , 7, init_a, 2, 0, 2, 2}); + test_block_multiplication({10, 1, init_a, 0, 0, 1, 1}, {10, 1, init_a, 0, 0, 1, 1}); + test_block_multiplication({1 , 10, init_a, 0, 0, 1, 1}, {1 , 10, init_id, 0, 0, 1, 1}); + test_block_multiplication({21 , 5, init_0, 1, 1, 3, 3}, {12 , 7, init_0, 4, 4, 3, 3}); + test_block_multiplication({11 , 7, init_a, 2, 0, 7, 7}, {11 , 11, init_a, 2, 1, 7, 7}); + test_block_multiplication({11 , 7, init_a, 2, 0, 5, 5}, {11 , 12, init_id, 0, 0, 5, 5}); +}; + +TTS_CASE_TPL("Check block multiplication with scalar", rotgen::tests::types) +( tts::type< tts::types> ) +{ + using mat_t = rotgen::matrix; + + test_scalar_block_multiplications({1 , 1, init_a, 0, 0, 1, 1}, T{ 3.5}); + test_scalar_block_multiplications({13 , 15, init_a, 1, 2, 3, 4}, T{ 0.}); + test_scalar_block_multiplications({5 , 9, init_a, 2, 2, 2, 2}, T{-2.5}); + test_scalar_block_multiplications({15 , 15, init_a, 3, 4, 5, 5}, T{ 42. }); + test_scalar_block_multiplications({5 , 5, init_b, 1, 0, 3, 2}, T{-5. }); + test_scalar_block_multiplications({10, 1, init_a, 0, 0, 5, 1}, T{ 1. }); + test_scalar_block_multiplications({1 , 10, init_a, 0, 0, 1, 5}, T{ 6. }); + test_scalar_block_multiplications({21 , 5, init_0, 4, 4, 10, 1}, T{ 10.1}); + test_scalar_block_multiplications({11 , 7, init_a, 2, 0, 7, 5}, T{-0.5}); +}; + +TTS_CASE_TPL("Check block division with scalar", rotgen::tests::types) +( tts::type< tts::types> ) +{ + using mat_t = rotgen::matrix; + //auto op = [](auto a, auto b) { return a / b; }; + auto s_op = [](auto& a, auto b) { return a /= b; }; + + //test_block_scalar_operations({1 , 1, init_a, 0, 0, 1, 1}, T{ 3.5}, op, s_op); + test_block_scalar_operations({1 , 1, init_a, 0, 0, 1, 1}, T{ 3.5}, s_op); + test_block_scalar_operations({13 , 15, init_a, 1, 2, 3, 4}, T{-2.5}, s_op); + test_block_scalar_operations({5 , 9, init_a, 2, 2, 2, 2}, T{ 42. }, s_op); + test_block_scalar_operations({15 , 15, init_a, 3, 4, 5, 5}, T{-5. }, s_op); + test_block_scalar_operations({5 , 5, init_b, 1, 0, 3, 2}, T{ 1. }, s_op); + test_block_scalar_operations({10, 1, init_a, 0, 0, 5, 1}, T{ 0. }, s_op); + test_block_scalar_operations({1 , 10, init_a, 0, 0, 1, 5}, T{ 6. },s_op); + test_block_scalar_operations({21 , 5, init_0, 4, 4, 10, 1}, T{ 10.}, s_op); + test_block_scalar_operations({11 , 7, init_a, 2, 0, 7, 5}, T{-0.5}, s_op); +}; diff --git a/test/unit/block/static_functions.cpp b/test/unit/block/static_functions.cpp new file mode 100644 index 0000000..7b210ab --- /dev/null +++ b/test/unit/block/static_functions.cpp @@ -0,0 +1,115 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include "unit/tests.hpp" +#include +#include + +void test_size(const auto& matrix, std::size_t rows, std::size_t cols) +{ + TTS_EQUAL(matrix.rows(), rows); + TTS_EQUAL(matrix.cols(), cols); + TTS_EQUAL(matrix.size(), rows*cols); +} + +void test_value(const auto& matrix, std::size_t rows, std::size_t cols, auto constant) +{ + test_size(matrix, rows, cols); + for(std::size_t r=0;r( tts::type< tts::types>) +{ + test_value(rotgen::block, 3, 4>::Zero(), 3, 4, 0); + test_value(rotgen::block, 1, 1>::Zero(), 1, 1, 0); + test_value(rotgen::block, 10, 10>::Zero(), 10, 10, 0); + test_value(rotgen::block, 3, 4>::Zero(3, 4), 3, 4, 0); + test_value(rotgen::block, 3, 3>::Zero(3, 3), 3, 3, 0); + test_value(rotgen::block, 2, 2>::Zero(2, 2), 2, 2, 0); + test_value(rotgen::block, rotgen::Dynamic, rotgen::Dynamic>::Zero(2, 3), 2, 3, 0); + test_value(rotgen::block, 0, 0>::Zero(0, 0), 0, 0, 0); + test_value(rotgen::block::Identity(2, 7)), + rotgen::Dynamic, 7>::Zero(3, 7), 3, 7, 0); + test_value(rotgen::block::Random(14, 3)), + 4, rotgen::Dynamic>::Zero(4, 3), 4, 3, 0); +}; + + +TTS_CASE_TPL("Test constant", rotgen::tests::types) +( tts::type< tts::types> ) +{ + test_value(rotgen::block, 3, 4>::Constant(5.12), 3, 4, T(5.12)); + test_value(rotgen::block, 1, 1>::Constant(2.2), 1, 1, T(2.2)); + test_value(rotgen::block, 10, 10>::Constant(13), 10, 10, T(13)); + test_value(rotgen::block, rotgen::Dynamic, rotgen::Dynamic>::Constant(2, 7, 5.6), 2, 7, T(5.6)); + test_value(rotgen::block, 2, 2>::Constant(2, 2, 2.0), 2, 2, T(2.0)); + test_value(rotgen::block, rotgen::Dynamic, 9>::Constant(9, 9, 1.1), 9, 9, T(1.1)); + test_value(rotgen::block, 5, rotgen::Dynamic>::Constant(5, 9, 42), 5, 9, T(42)); + test_value(rotgen::block, 4, 3>::Constant(4, 3, 0), 4, 3, 0); + test_value(rotgen::block::Identity(3, 7)), + rotgen::Dynamic, 7>::Constant(3, 7, 88), 3, 7, T(88)); + test_value(rotgen::block::Random(14, 3)), + 4, rotgen::Dynamic>::Constant(4, 3, 3.99), 4, 3, T(3.99)); +}; + + +TTS_CASE_TPL("Test random", rotgen::tests::types) +( tts::type< tts::types> ) +{ + test_random(rotgen::block, 3, 3>::Random(), 3, 3); + test_random(rotgen::block, 1, 1>::Random(), 1, 1); + test_random(rotgen::block, 3, 4>::Random(), 3, 4); + test_random(rotgen::block, rotgen::Dynamic, rotgen::Dynamic>::Random(1, 5), 1, 5); + test_random(rotgen::block, 2, 1>::Random(2, 1), 2, 1); + test_random(rotgen::block, rotgen::Dynamic, 9>::Random(3, 9), 3, 9); + test_random(rotgen::block, 5, rotgen::Dynamic>::Random(5, 2), 5, 2); + test_random(rotgen::block, 4, 3>::Random(4, 3), 4, 3); + test_random(rotgen::block::Identity(3, 7)), + rotgen::Dynamic, 7>::Random(3, 7), 3, 7); + test_random(rotgen::block::Random(14, 15)), + 4, rotgen::Dynamic>::Random(4, 11), 4, 11); +}; + + +TTS_CASE_TPL("Test identity", rotgen::tests::types) +( tts::type< tts::types> ) +{ + test_identity(rotgen::block, 3, 3>::Identity(), 3, 3); + test_identity(rotgen::block, 1, 1>::Identity(), 1, 1); + test_identity(rotgen::block, 3, 4>::Identity(), 3, 4); + test_identity(rotgen::block, rotgen::Dynamic, rotgen::Dynamic>::Identity(1, 5), 1, 5); + test_identity(rotgen::block, 2, 1>::Identity(2, 1), 2, 1); + test_identity(rotgen::block, rotgen::Dynamic, 9>::Identity(3, 9), 3, 9); + test_identity(rotgen::block, 5, rotgen::Dynamic>::Identity(5, 2), 5, 2); + test_identity(rotgen::block, 4, 3>::Identity(4, 3), 4, 3); + test_identity(rotgen::block::Identity(3, 7)), + rotgen::Dynamic, 7>::Identity(3, 7), 3, 7); + test_identity(rotgen::block::Random(14, 15)), + 4, rotgen::Dynamic>::Identity(4, 11), 4, 11); +}; \ No newline at end of file diff --git a/test/unit/basic/arithmetic_functions.cpp b/test/unit/matrix/arithmetic_functions.cpp similarity index 97% rename from test/unit/basic/arithmetic_functions.cpp rename to test/unit/matrix/arithmetic_functions.cpp index 5b50daf..b51e47e 100644 --- a/test/unit/basic/arithmetic_functions.cpp +++ b/test/unit/matrix/arithmetic_functions.cpp @@ -59,7 +59,7 @@ TTS_CASE_TPL("Test transpotion related operations", rotgen::tests::types) template void test_matrix_reductions(std::size_t rows, std::size_t cols, auto const& init_fn) { - using EigenMatrix = Eigen::Matrix; + using EigenMatrix = Eigen::Matrix; MatrixType original(rows, cols); EigenMatrix ref(rows, cols); diff --git a/test/unit/basic/constructors.cpp b/test/unit/matrix/constructors.cpp similarity index 100% rename from test/unit/basic/constructors.cpp rename to test/unit/matrix/constructors.cpp diff --git a/test/unit/basic/functions.cpp b/test/unit/matrix/functions.cpp similarity index 100% rename from test/unit/basic/functions.cpp rename to test/unit/matrix/functions.cpp diff --git a/test/unit/basic/io.cpp b/test/unit/matrix/io.cpp similarity index 100% rename from test/unit/basic/io.cpp rename to test/unit/matrix/io.cpp diff --git a/test/unit/basic/norms.cpp b/test/unit/matrix/norms.cpp similarity index 100% rename from test/unit/basic/norms.cpp rename to test/unit/matrix/norms.cpp diff --git a/test/unit/basic/operators.cpp b/test/unit/matrix/operators.cpp similarity index 100% rename from test/unit/basic/operators.cpp rename to test/unit/matrix/operators.cpp diff --git a/test/unit/basic/static_functions.cpp b/test/unit/matrix/static_functions.cpp similarity index 100% rename from test/unit/basic/static_functions.cpp rename to test/unit/matrix/static_functions.cpp diff --git a/test/unit/tests.hpp b/test/unit/tests.hpp index 7798c6d..c1d6bcc 100644 --- a/test/unit/tests.hpp +++ b/test/unit/tests.hpp @@ -28,4 +28,22 @@ namespace rotgen::tests std::size_t rows, cols; std::function init_fn; }; + + template + struct matrix_block_test_case + { + std::size_t rows, cols; + std::function init_fn; + std::size_t i0, j0, ni, nj; + }; + + template + struct static_matrix_block_test_case + { + std::size_t rows, cols; + std::function init_fn; + static constexpr std::size_t ni = NI; + static constexpr std::size_t nj = NJ; + std::size_t i0, j0; + }; } \ No newline at end of file