diff --git a/.clang-format b/.clang-format index ecfe19d..b73e75c 100644 --- a/.clang-format +++ b/.clang-format @@ -261,4 +261,10 @@ QualifierOrder: - inline - static - type - - const \ No newline at end of file + - const +StatementMacros: + - TTS_CASE + - TTS_CASE_TPL + - TTS_CASE_WITH + - TTS_AND_THEN + - TTS_WHEN \ No newline at end of file diff --git a/cmake/config/rotgen-install.cmake b/cmake/config/rotgen-install.cmake index 5369cf6..6d05f41 100644 --- a/cmake/config/rotgen-install.cmake +++ b/cmake/config/rotgen-install.cmake @@ -6,12 +6,12 @@ include(GNUInstallDirs) include(CMakePackageConfigHelpers) -set(MAIN_DEST "${CMAKE_INSTALL_LIBDIR}/rotgen") +set(MAIN_DEST "${CMAKE_INSTALL_LIBDIR}") set(INSTALL_DEST "${CMAKE_INSTALL_INCLUDEDIR}") set(DOC_DEST "${CMAKE_INSTALL_DOCDIR}") write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/rotgen-config-version.cmake" - VERSION "${EVE_VERSION}" + VERSION "${ROTGEN_VERSION}" COMPATIBILITY ExactVersion ) diff --git a/include/rotgen/algebra/qr.hpp b/include/rotgen/algebra/qr.hpp index dfe1eaf..a54d669 100644 --- a/include/rotgen/algebra/qr.hpp +++ b/include/rotgen/algebra/qr.hpp @@ -15,6 +15,6 @@ namespace rotgen::solver auto r_x = generalize_t(x); auto r_m = generalize_t(m); auto r_rhs = generalize_t(rhs); - r_x = r_m.base().qr_solve(r_rhs.base()); + r_x = r_m.qr_solve(r_rhs); } } diff --git a/include/rotgen/concepts.hpp b/include/rotgen/concepts.hpp index 30449db..9029597 100644 --- a/include/rotgen/concepts.hpp +++ b/include/rotgen/concepts.hpp @@ -7,6 +7,9 @@ //================================================================================================== #pragma once +#include +#include + namespace rotgen::concepts { //================================================================================================ diff --git a/include/rotgen/container/block/dynamic.hpp b/include/rotgen/container/block/dynamic.hpp index 5289727..f452f46 100644 --- a/include/rotgen/container/block/dynamic.hpp +++ b/include/rotgen/container/block/dynamic.hpp @@ -10,45 +10,68 @@ #include #include #include -#include + #include +#include namespace rotgen { - template + template, + outer_stride<>>> class ref; template - class block : public find_block + class block : public find_block { public: static_assert(concepts::entity, "[ROTGEN][CRITICAL] - Block of non-rotgen type instanciated"); - using parent = find_block; + using parent = find_block; using rotgen_tag = void; using rotgen_block_tag = void; using value_type = typename std::remove_const_t::value_type; - static constexpr int storage_order = Ref::storage_order; + static constexpr int RowsAtCompileTime = Rows; + static constexpr int ColsAtCompileTime = Cols; + static constexpr int MaxRowsAtCompileTime = + (Rows != Dynamic) ? Rows : Ref::MaxRowsAtCompileTime; + static constexpr int MaxColsAtCompileTime = + (Cols != Dynamic) ? Cols : Ref::MaxColsAtCompileTime; + static constexpr bool IsRowMajor = + (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? true + : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) + ? false + : Ref::IsRowMajor; + + static constexpr int storage_order = IsRowMajor ? RowMajor : ColMajor; + + static constexpr bool has_same_storage_order = + storage_order == Ref::storage_order; + static constexpr int InnerStrideAtCompileTime = + has_same_storage_order ? Ref::InnerStrideAtCompileTime + : Ref::OuterStrideAtCompileTime; + static constexpr int OuterStrideAtCompileTime = + has_same_storage_order ? Ref::OuterStrideAtCompileTime + : Ref::InnerStrideAtCompileTime; + static constexpr bool is_immutable = std::is_const_v; using concrete_type = matrix; using transposed_type = matrix; using concrete_dynamic_type = matrix; - static constexpr int RowsAtCompileTime = Rows; - static constexpr int ColsAtCompileTime = Cols; - static constexpr int MaxRowsAtCompileTime = Rows; - static constexpr int MaxColsAtCompileTime = Cols; - static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime; - static constexpr int Options = Ref::Options; - static constexpr bool IsRowMajor = (storage_order & RowMajor) == RowMajor; + static constexpr bool IsVectorAtCompileTime = + (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1); + static constexpr int Options = IsRowMajor ? RowMajor : ColMajor; - static constexpr bool is_defined_static = false; + static constexpr bool is_defined_static = Rows != -1 && Cols != -1; static constexpr bool has_static_storage = false; using parent::operator=; @@ -80,7 +103,7 @@ namespace rotgen std::size_t ni, std::size_t nj) requires(requires { typename Ref::rotgen_block_tag; } && is_immutable) - : parent(*r.storage(), i0, j0, ni, nj) + : parent(r.base(), i0, j0, ni, nj) { } @@ -94,7 +117,7 @@ namespace rotgen block(Ref const& r, std::size_t i0, std::size_t j0) requires(requires { typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && is_immutable) - : parent(*r.storage(), i0, j0, Rows, Cols) + : parent(r.base(), i0, j0, Rows, Cols) { } @@ -108,7 +131,7 @@ namespace rotgen block( Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) requires(requires { typename Ref::rotgen_block_tag; } && !is_immutable) - : parent(*r.storage(), i0, j0, ni, nj) + : parent(r.base(), i0, j0, ni, nj) { } @@ -122,7 +145,7 @@ namespace rotgen block(Ref& r, std::size_t i0, std::size_t j0) requires(requires { typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && !is_immutable) - : parent(*r.storage(), i0, j0, Rows, Cols) + : parent(r.base(), i0, j0, Rows, Cols) { } @@ -131,8 +154,7 @@ namespace rotgen bool is_contiguous_linear() const { if (parent::innerStride() != 1) return false; - if constexpr (storage_order) - return parent::outerStride() == parent::cols(); + if constexpr (IsRowMajor) return parent::outerStride() == parent::cols(); else return parent::outerStride() == parent::rows(); } diff --git a/include/rotgen/container/block/dynamic/impl.hpp b/include/rotgen/container/block/dynamic/impl.hpp index 2212338..b7a224b 100644 --- a/include/rotgen/container/block/dynamic/impl.hpp +++ b/include/rotgen/container/block/dynamic/impl.hpp @@ -8,10 +8,14 @@ #pragma once #include + +// clang-format off #include #include -#include +// clang-format on + #include +#include #include namespace rotgen @@ -21,6 +25,15 @@ namespace rotgen class matrix_impl32_row; class matrix_impl32_col; + class block_impl64_row; + class block_impl64_col; + class block_impl32_row; + class block_impl32_col; + class block_const_impl64_row; + class block_const_impl64_col; + class block_const_impl32_row; + class block_const_impl32_col; + #define USE_CONST #define CONST const #define BASENAME block_const_impl @@ -81,9 +94,24 @@ namespace rotgen using type = block_impl64_row; }; - template + template + constexpr auto block_storage_order() + { + int MaxRowsAtCompileTime = + (Rows != Dynamic) ? Rows : Ref::MaxRowsAtCompileTime; + int MaxColsAtCompileTime = + (Cols != Dynamic) ? Cols : Ref::MaxColsAtCompileTime; + bool IsRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) + ? true + : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) + ? false + : Ref::IsRowMajor; + return IsRowMajor ? RowMajor : ColMajor; + } + + template using find_block = typename find_block_impl::value_type, - Ref::storage_order, + block_storage_order(), std::is_const_v>::type; } diff --git a/include/rotgen/container/block/dynamic/indirect.hpp b/include/rotgen/container/block/dynamic/indirect.hpp index fc99030..ad7ae77 100644 --- a/include/rotgen/container/block/dynamic/indirect.hpp +++ b/include/rotgen/container/block/dynamic/indirect.hpp @@ -2,22 +2,26 @@ #define TYPE double #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col) +#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) -#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) +#define TRANSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _col) #include #undef CLASSNAME -#undef TRANSSOURCENAME +#undef TRANSCLASSNAME +#undef TRANSNAME #undef SOURCENAME #undef MAPNAME #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row) +#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) -#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) +#define TRANSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _row) #include #undef CLASSNAME -#undef TRANSSOURCENAME +#undef TRANSCLASSNAME +#undef TRANSNAME #undef SOURCENAME #undef MAPNAME @@ -28,22 +32,26 @@ #define TYPE float #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col) +#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) -#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) +#define TRANSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _col) #include #undef CLASSNAME -#undef TRANSSOURCENAME +#undef TRANSCLASSNAME +#undef TRANSNAME #undef SOURCENAME #undef MAPNAME #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row) +#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) -#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) +#define TRANSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _row) #include #undef CLASSNAME -#undef TRANSSOURCENAME +#undef TRANSCLASSNAME +#undef TRANSNAME #undef SOURCENAME #undef MAPNAME diff --git a/include/rotgen/container/block/dynamic/model.hpp b/include/rotgen/container/block/dynamic/model.hpp index 8e6727e..ed04c01 100644 --- a/include/rotgen/container/block/dynamic/model.hpp +++ b/include/rotgen/container/block/dynamic/model.hpp @@ -19,8 +19,10 @@ private: public: CLASSNAME(SOURCENAME CONST& r, Index i0, Index j0, Index ni, Index nj); + CLASSNAME(TRANSNAME CONST& r, Index i0, Index j0, Index ni, Index nj); CLASSNAME(MAPNAME CONST& r, Index i0, Index j0, Index ni, Index nj); - CLASSNAME(payload const& r, Index i0, Index j0, Index ni, Index nj); + CLASSNAME(CLASSNAME CONST& r, Index i0, Index j0, Index ni, Index nj); + CLASSNAME(TRANSCLASSNAME CONST& r, Index i0, Index j0, Index ni, Index nj); CLASSNAME(CLASSNAME const& other); CLASSNAME(CLASSNAME&&) noexcept; diff --git a/include/rotgen/container/block/fixed.hpp b/include/rotgen/container/block/fixed.hpp index 70599c5..e9ab4a2 100644 --- a/include/rotgen/container/block/fixed.hpp +++ b/include/rotgen/container/block/fixed.hpp @@ -8,12 +8,17 @@ #pragma once #include + #include #include namespace rotgen { - template + template, + outer_stride<>>> class ref; namespace detail @@ -31,22 +36,6 @@ namespace rotgen Eigen::Block>; }; - template - struct compute_block_type, Rows, Cols, Inner, IsConst> - : compute_block_type::parent, - Rows, - Cols, - Inner, - IsConst> - { - }; - template using block_type = typename compute_block_type::type; @@ -77,29 +66,43 @@ namespace rotgen using value_type = typename parent::value_type; using Index = typename parent::Index; - static constexpr int storage_order = - (ForceStorageOrder == -1) ? Ref::storage_order : ForceStorageOrder; - static constexpr bool is_immutable = std::is_const_v; - - static constexpr bool IsRowMajor = parent::IsRowMajor; - - using concrete_type = matrix; - using concrete_dynamic_type = - matrix; - template using as_concrete_type = detail::as_concrete_t; static constexpr int Options = Ref::Options; static constexpr int RowsAtCompileTime = Rows; static constexpr int ColsAtCompileTime = Cols; - static constexpr int MaxRowsAtCompileTime = Ref::MaxRowsAtCompileTime; - static constexpr int MaxColsAtCompileTime = Ref::MaxColsAtCompileTime; - static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime; + static constexpr int MaxRowsAtCompileTime = + (Rows != Dynamic) ? Rows : Ref::MaxRowsAtCompileTime; + static constexpr int MaxColsAtCompileTime = + (Cols != Dynamic) ? Cols : Ref::MaxColsAtCompileTime; + static constexpr bool IsVectorAtCompileTime = + (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1); static constexpr bool is_defined_static = Rows != -1 && Cols != -1; static constexpr bool has_static_storage = storage_status; + static constexpr bool IsRowMajor = + (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? true + : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) + ? false + : Ref::IsRowMajor; + + static constexpr int storage_order = IsRowMajor ? RowMajor : ColMajor; + static constexpr bool has_same_storage_order = + storage_order == Ref::storage_order; + static constexpr int InnerStrideAtCompileTime = + has_same_storage_order ? Ref::InnerStrideAtCompileTime + : Ref::OuterStrideAtCompileTime; + static constexpr int OuterStrideAtCompileTime = + has_same_storage_order ? Ref::OuterStrideAtCompileTime + : Ref::InnerStrideAtCompileTime; + static constexpr bool is_immutable = std::is_const_v; + + using concrete_type = matrix; + using concrete_dynamic_type = + matrix; + public: block(block const& other) = default; block(block&& other) = default; diff --git a/include/rotgen/container/map/dynamic.hpp b/include/rotgen/container/map/dynamic.hpp index dcec9c4..ffb2223 100644 --- a/include/rotgen/container/map/dynamic.hpp +++ b/include/rotgen/container/map/dynamic.hpp @@ -7,16 +7,25 @@ //================================================================================================== #pragma once +#include + #include #include -#include + #include namespace rotgen { + namespace detail + { + struct postpone + { + }; + } + template + typename Stride = rotgen::stride<0, 0>> class map : public find_map { public: @@ -33,7 +42,6 @@ namespace rotgen static constexpr bool has_static_storage = false; static constexpr bool is_immutable = std::is_const_v; - static constexpr bool is_defined_static = false; using ptr_type = std::conditional_t; @@ -44,13 +52,25 @@ namespace rotgen static constexpr int MaxRowsAtCompileTime = Ref::MaxRowsAtCompileTime; static constexpr int MaxColsAtCompileTime = Ref::MaxColsAtCompileTime; static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime; - static constexpr bool IsCompileTimeSized = + static constexpr bool is_defined_static = RowsAtCompileTime != -1 && ColsAtCompileTime != -1; + static constexpr int inner_size = + Ref::IsRowMajor ? ColsAtCompileTime : RowsAtCompileTime; + + static constexpr int InnerStrideAtCompileTime = + Stride::InnerStrideAtCompileTime == 0 ? Ref::InnerStrideAtCompileTime + : Stride::InnerStrideAtCompileTime; + static constexpr int OuterStrideAtCompileTime = + Stride::OuterStrideAtCompileTime == 0 + ? (InnerStrideAtCompileTime == -1 || inner_size == -1) + ? Dynamic + : InnerStrideAtCompileTime * inner_size + : Stride::OuterStrideAtCompileTime; using transposed_type = matrix; - map(ptr_type ptr, Index r, Index c, stride_type s) + map(ptr_type ptr, Index r, Index c, dynamic_stride s) : parent(ptr, r, c, strides(s, r, c)) { if constexpr (RowsAtCompileTime != -1) @@ -62,9 +82,18 @@ namespace rotgen "Mismatched between dynamic and static column size"); } + // Used to properly delay ref dynamic construction + map(detail::postpone const&) {} + + map(ptr_type ptr, Index r, Index c, stride_type s) + requires(!std::same_as) + : map(ptr, r, c, strides(s, r, c)) + { + } + map(ptr_type ptr, Index r, Index c) : parent(ptr, r, c, [&]() { - if constexpr (!std::same_as) + if constexpr (!std::same_as>) return strides(Stride{}, r, c); else return strides(r, c); }()) @@ -72,7 +101,7 @@ namespace rotgen } map(ptr_type ptr, stride_type s) - requires(IsCompileTimeSized) + requires(is_defined_static) : parent( ptr, RowsAtCompileTime, ColsAtCompileTime, strides(s)) { @@ -87,7 +116,7 @@ namespace rotgen } map(ptr_type ptr) - requires(IsCompileTimeSized) + requires(is_defined_static) : map(ptr, RowsAtCompileTime, ColsAtCompileTime) { } @@ -97,7 +126,7 @@ namespace rotgen : map(other.data(), other.rows(), other.cols(), - stride{other.outerStride(), other.innerStride()}) + dynamic_stride{other.outerStride(), other.innerStride()}) { } @@ -116,9 +145,17 @@ namespace rotgen requires(!is_immutable) { assert(parent::rows() == other.rows() && parent::cols() == other.cols()); - for (rotgen::Index r = 0; r < parent::rows(); ++r) - for (rotgen::Index c = 0; c < parent::cols(); ++c) - (*this)(r, c) = other(r, c); + if constexpr (IsVectorAtCompileTime) + { + for (rotgen::Index i = 0; i < parent::size(); ++i) + (*this)(i) = other(i); + } + else + { + for (rotgen::Index r = 0; r < parent::rows(); ++r) + for (rotgen::Index c = 0; c < parent::cols(); ++c) + (*this)(r, c) = other(r, c); + } return *this; } @@ -132,9 +169,6 @@ namespace rotgen value_type& operator()(Index i) requires(!is_immutable && IsVectorAtCompileTime) { - assert(parent::innerStride() == 1 && - parent::outerStride() == - (storage_order == RowMajor ? parent::cols() : parent::rows())); return parent::operator()(i); } @@ -152,9 +186,6 @@ namespace rotgen value_type operator()(Index i) const requires(IsVectorAtCompileTime) { - assert(parent::innerStride() == 1 && - parent::outerStride() == - (storage_order == RowMajor ? parent::cols() : parent::rows())); return parent::operator()(i); } @@ -349,8 +380,16 @@ namespace rotgen return Ref::Zero(); } + static auto Ones() + requires(requires { Ref::Ones(); }) + { + return Ref::Ones(); + } + static auto Zero(int rows, int cols) { return Ref::Zero(rows, cols); } + static auto Ones(int rows, int cols) { return Ref::Ones(rows, cols); } + static auto Constant(value_type value) requires(requires { Ref::Constant(value); }) { diff --git a/include/rotgen/container/map/dynamic/model.hpp b/include/rotgen/container/map/dynamic/model.hpp index d7b90d9..7790efd 100644 --- a/include/rotgen/container/map/dynamic/model.hpp +++ b/include/rotgen/container/map/dynamic/model.hpp @@ -14,8 +14,9 @@ class ROTGEN_EXPORT CLASSNAME { public: + CLASSNAME(); CLASSNAME(TYPE CONST* ptr, Index r, Index c); - CLASSNAME(TYPE CONST* ptr, Index r, Index c, stride s); + CLASSNAME(TYPE CONST* ptr, Index r, Index c, dynamic_stride s); CLASSNAME(CLASSNAME const& other); CLASSNAME(CLASSNAME&&) noexcept; diff --git a/include/rotgen/container/map/fixed.hpp b/include/rotgen/container/map/fixed.hpp index d0882ea..70af3a2 100644 --- a/include/rotgen/container/map/fixed.hpp +++ b/include/rotgen/container/map/fixed.hpp @@ -14,7 +14,8 @@ namespace rotgen { namespace detail { - template struct compute_map_type + template + struct compute_map_type { using base = Eigen::Matrix; using ref_t = std::conditional_t; - using type = Eigen::Map>; + using type = Eigen::Map; }; - template - using map_type = typename compute_map_type::type; + template + using map_type = + typename compute_map_type::type; } - template + template> class map : private detail::map_type, Options, - std::is_const_v> + std::is_const_v, + Stride> { public: using rotgen_tag = void; - using parent = - detail::map_type, Options, std::is_const_v>; + using parent = detail:: + map_type, Options, std::is_const_v, Stride>; using value_type = typename std::remove_const_t::value_type; using concrete_type = typename std::remove_const_t::concrete_type; @@ -47,10 +52,23 @@ namespace rotgen static constexpr int MaxColsAtCompileTime = Ref::MaxColsAtCompileTime; static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime; static constexpr bool has_static_storage = Ref::has_static_storage; + static constexpr bool IsRowMajor = Ref::IsRowMajor; static constexpr int storage_order = Ref::storage_order; static constexpr bool is_immutable = std::is_const_v; static constexpr bool is_defined_static = Ref::is_defined_static; + static constexpr int inner_size = + Ref::IsRowMajor ? ColsAtCompileTime : RowsAtCompileTime; + static constexpr int InnerStrideAtCompileTime = + Stride::InnerStrideAtCompileTime == 0 ? Ref::InnerStrideAtCompileTime + : Stride::InnerStrideAtCompileTime; + static constexpr int OuterStrideAtCompileTime = + Stride::OuterStrideAtCompileTime == 0 + ? (InnerStrideAtCompileTime == -1 || inner_size == -1) + ? Dynamic + : InnerStrideAtCompileTime * inner_size + : Stride::OuterStrideAtCompileTime; + template using as_concrete_type = detail::as_concrete_t; @@ -63,24 +81,13 @@ namespace rotgen map& operator=(map const&) = default; map& operator=(map&&) = default; - map(ptr_type ptr, Index r, Index c, stride_type s) - : parent(ptr, r, c, strides(s, r, c)) - { - } + map(ptr_type ptr, Index r, Index c, stride_type s) : parent(ptr, r, c, s) {} - map(ptr_type ptr, Index r, Index c) - : parent(ptr, r, c, [&]() { - if constexpr (!std::same_as) - return strides(Stride{}, r, c); - else return strides(r, c); - }()) - { - } + map(ptr_type ptr, Index r, Index c) : parent(ptr, r, c) {} map(ptr_type ptr, stride_type s) requires(RowsAtCompileTime != -1 && ColsAtCompileTime != -1) - : parent(ptr, - strides(s, RowsAtCompileTime, ColsAtCompileTime)) + : parent(ptr, s) { } @@ -115,6 +122,12 @@ namespace rotgen return as_concrete_type(res); } + auto evaluate() + { + auto res = static_cast(*this).eval(); + return as_concrete_type(res); + } + decltype(auto) noalias() const { if constexpr (use_expression_templates) return base().noalias(); diff --git a/include/rotgen/container/matrix/dynamic.hpp b/include/rotgen/container/matrix/dynamic.hpp index 6f888aa..697d177 100644 --- a/include/rotgen/container/matrix/dynamic.hpp +++ b/include/rotgen/container/matrix/dynamic.hpp @@ -7,10 +7,13 @@ //================================================================================================== #pragma once -#include +#include + #include -#include +#include + #include +#include namespace rotgen { @@ -31,24 +34,29 @@ namespace rotgen static constexpr auto storage_order = Opts & 1; static constexpr int RowsAtCompileTime = Rows; static constexpr int ColsAtCompileTime = Cols; + static constexpr int SizeAtCompileTime = detail::static_size(); static constexpr int MaxRowsAtCompileTime = MaxRows; static constexpr int MaxColsAtCompileTime = MaxCols; - static constexpr bool IsCompileTimeSized = Rows != -1 && Cols != -1; - static constexpr bool IsVectorAtCompileTime = - (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1); + static constexpr bool IsVectorAtCompileTime = (Rows == 1) || (Cols == 1); static constexpr int Options = Opts; static constexpr bool IsRowMajor = (Opts & RowMajor) == RowMajor; - static constexpr bool is_defined_static = false; + static constexpr int InnerSizeAtCompileTime = + IsVectorAtCompileTime ? SizeAtCompileTime + : IsRowMajor ? ColsAtCompileTime + : RowsAtCompileTime; + + static constexpr bool is_defined_static = Rows != -1 && Cols != -1; static constexpr bool has_static_storage = false; static constexpr bool is_immutable = false; + static constexpr int InnerStrideAtCompileTime = 1; + static constexpr int OuterStrideAtCompileTime = + IsRowMajor ? ColsAtCompileTime : RowsAtCompileTime; using transposed_type = matrix; matrix() : parent(Rows == -1 ? 0 : Rows, Cols == -1 ? 0 : Cols) {} - matrix(Index r, Index c) - requires(!IsCompileTimeSized) - : parent(r, c) + matrix(Index r, Index c) : parent(r, c) { if constexpr (Rows != -1) assert(r == Rows && "Mismatched between dynamic and static row size"); @@ -145,6 +153,15 @@ namespace rotgen decltype(auto) noalias() { return *this; } + Index innerStride() const noexcept { return 1; } + + Index outerStride() const noexcept + { + return IsVectorAtCompileTime ? this->size() + : IsRowMajor ? this->cols() + : this->rows(); + } + void resize(int r, int c) { if constexpr (Rows == 1) @@ -361,62 +378,62 @@ namespace rotgen matrix& setOnes() { - *this = parent::Ones(parent::rows(), parent::cols()); + parent::setOnes(parent::rows(), parent::cols()); return *this; } matrix& setOnes(int rows, int cols) { - *this = parent::Ones(rows, cols); + parent::setOnes(rows, cols); return *this; } matrix& setZero() { - *this = parent::Zero(parent::rows(), parent::cols()); + parent::setZero(parent::rows(), parent::cols()); return *this; } matrix& setZero(int rows, int cols) { - *this = parent::Zero(rows, cols); + parent::setZero(rows, cols); return *this; } - matrix& setConstant(Scalar value) + matrix& setConstant(Scalar v) { - *this = parent::Constant(parent::rows(), parent::cols(), - static_cast(value)); + parent::setConstant(parent::rows(), parent::cols(), + static_cast(v)); return *this; } - matrix& setConstant(int rows, int cols, Scalar value) + matrix& setConstant(int rows, int cols, Scalar v) { - *this = parent::Constant(rows, cols, static_cast(value)); + parent::setConstant(rows, cols, static_cast(v)); return *this; } matrix& setRandom() { - *this = parent::Random(parent::rows(), parent::cols()); + parent::setRandom(parent::rows(), parent::cols()); return *this; } matrix& setRandom(int rows, int cols) { - *this = parent::Random(rows, cols); + parent::setRandom(rows, cols); return *this; } matrix& setIdentity() { - *this = parent::Identity(parent::rows(), parent::cols()); + parent::setIdentity(parent::rows(), parent::cols()); return *this; } matrix& setIdentity(int rows, int cols) { - *this = parent::Identity(rows, cols); + parent::setIdentity(rows, cols); return *this; } diff --git a/include/rotgen/container/matrix/dynamic/model.hpp b/include/rotgen/container/matrix/dynamic/model.hpp index 9d43c1d..6e1f153 100644 --- a/include/rotgen/container/matrix/dynamic/model.hpp +++ b/include/rotgen/container/matrix/dynamic/model.hpp @@ -95,6 +95,12 @@ public: static CLASSNAME Random(std::size_t rows, std::size_t cols); static CLASSNAME Identity(std::size_t rows, std::size_t cols); + void setOnes(std::size_t rows, std::size_t cols); + void setZero(std::size_t rows, std::size_t cols); + void setConstant(std::size_t rows, std::size_t cols, TYPE value); + void setRandom(std::size_t rows, std::size_t cols); + void setIdentity(std::size_t rows, std::size_t cols); + private: struct payload; std::unique_ptr storage_; diff --git a/include/rotgen/container/matrix/fixed.hpp b/include/rotgen/container/matrix/fixed.hpp index 0bc2752..a74fc24 100644 --- a/include/rotgen/container/matrix/fixed.hpp +++ b/include/rotgen/container/matrix/fixed.hpp @@ -8,6 +8,7 @@ #pragma once #include + #include #include @@ -49,13 +50,21 @@ namespace rotgen static constexpr int RowsAtCompileTime = Rows; static constexpr int ColsAtCompileTime = Cols; + static constexpr int SizeAtCompileTime = detail::static_size(); static constexpr int MaxRowsAtCompileTime = MaxRows; static constexpr int MaxColsAtCompileTime = MaxCols; - static constexpr bool IsCompileTimeSized = Rows != -1 && Cols != -1; static constexpr bool IsVectorAtCompileTime = (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1); static constexpr int Options = parent::Options; static constexpr bool IsRowMajor = parent::IsRowMajor; + static constexpr int InnerStrideAtCompileTime = 1; + static constexpr int OuterStrideAtCompileTime = + IsRowMajor ? ColsAtCompileTime : RowsAtCompileTime; + + static constexpr int InnerSizeAtCompileTime = + IsVectorAtCompileTime ? SizeAtCompileTime + : IsRowMajor ? ColsAtCompileTime + : RowsAtCompileTime; template using as_concrete_type = detail::as_concrete_t; @@ -77,10 +86,15 @@ namespace rotgen { } - matrix(Index r, Index c) - requires(!IsCompileTimeSized) - : parent(r, c) + matrix(Index r, Index c) : parent(r, c) { + if constexpr (RowsAtCompileTime != -1) + assert(r == RowsAtCompileTime && + "Mismatched between dynamic and static row size"); + + if constexpr (ColsAtCompileTime != -1) + assert(c == ColsAtCompileTime && + "Mismatched between dynamic and static column size"); } matrix(matrix const& other) = default; @@ -99,7 +113,7 @@ namespace rotgen { } - matrix(Scalar v) + explicit matrix(Scalar v) requires(Rows == 1 && Cols == 1) : parent([&]() { if constexpr (has_static_storage) return parent(v); @@ -109,7 +123,7 @@ namespace rotgen if constexpr (!has_static_storage) (*this)(0) = v; } - explicit matrix(std::initializer_list init) + matrix(std::initializer_list init) requires(IsVectorAtCompileTime) : parent([&]() { if constexpr (has_static_storage) return parent{}; @@ -159,6 +173,9 @@ namespace rotgen return *this; } + using parent::innerStride; + using parent::outerStride; + parent& base() { return static_cast(*this); } parent const& base() const { return static_cast(*this); } diff --git a/include/rotgen/container/ref.hpp b/include/rotgen/container/ref.hpp index 16c7fe7..f59fa47 100644 --- a/include/rotgen/container/ref.hpp +++ b/include/rotgen/container/ref.hpp @@ -7,501 +7,13 @@ //================================================================================================== #pragma once -#include -#include +#include -#if !defined(ROTGEN_FORCE_DYNAMIC) -#include +#if defined(ROTGEN_FORCE_DYNAMIC) +#include +#else +#include #endif -namespace rotgen -{ - // Primary template: mutable ref - template - class ref : private map - { - public: - using parent = map; - using value_type = typename T::value_type; - using rotgen_tag = void; - using rotgen_ref_tag = void; - - static constexpr int storage_order = T::storage_order; - static constexpr int RowsAtCompileTime = T::RowsAtCompileTime; - static constexpr int ColsAtCompileTime = T::ColsAtCompileTime; - static constexpr bool IsVectorAtCompileTime = T::IsVectorAtCompileTime; - static constexpr bool is_immutable = T::is_immutable; - - using parent::evaluate; - using parent::noalias; - using parent::operator(); - using parent::operator[]; - using parent::cols; - using parent::cwiseAbs; - using parent::cwiseAbs2; - using parent::cwiseInverse; - using parent::cwiseSqrt; - using parent::data; - using parent::lpNorm; - using parent::maxCoeff; - using parent::mean; - using parent::minCoeff; - using parent::norm; - using parent::normalize; - using parent::prod; - using parent::rows; - using parent::size; - using parent::squaredNorm; - using parent::sum; - using parent::trace; - using parent::transpose; - using parent::operator+=; - using parent::operator-=; - using parent::operator*=; - using parent::operator/=; - using parent::Constant; - using parent::Identity; - using parent::innerStride; - using parent::outerStride; - using parent::Random; - using parent::setConstant; - using parent::setIdentity; - using parent::setRandom; - using parent::setZero; - using parent::Zero; - - using parent::operator=; - - using stride_type = typename parent::stride_type; - - parent const& base() const { return static_cast(*this); } - - parent& base() { return static_cast(*this); } - - template S, int R, int C, int O, int MR, int MC> - ref(matrix& m) - : parent(m.data(), m.rows(), m.cols(), strides(m)) - { - } - - template - requires(std::same_as && - (Ref::storage_order & 1) == storage_order) - ref(block&& b) - : parent(b.data(), - b.rows(), - b.cols(), - stride_type{b.outerStride(), b.innerStride()}) - { - } - - template - requires(std::same_as && - (Ref::storage_order & 1) == storage_order) - ref(block& b) - : parent(b.data(), - b.rows(), - b.cols(), - stride_type{b.outerStride(), b.innerStride()}) - { - } - - template - requires(std::same_as && - (Ref::storage_order & 1) == storage_order) - ref(map& b) - : parent(b.data(), - b.rows(), - b.cols(), - stride_type{b.outerStride(), b.innerStride()}) - { - } - - template - ref(ref& b) - requires(std::same_as && - (TT::storage_order & 1) == storage_order) - : parent(b.data(), - b.rows(), - b.cols(), - stride_type{b.outerStride(), b.innerStride()}) - { - } - - ref(parent& m) : parent(m.data(), m.rows(), m.cols()) {} - - friend std::ostream& operator<<(std::ostream& os, ref const& r) - { - return os << r.base(); - } - - friend std::ostream& operator<<(std::ostream& os, format const& r) - { - return os << format{r.matrix_.base(), r.format_}; - } - }; - - // Specialization for const matrix type - template - class ref : private map - { - public: - using parent = map; - using value_type = typename T::value_type; - using rotgen_tag = void; - using rotgen_ref_tag = void; - - static constexpr int storage_order = T::storage_order; - static constexpr int RowsAtCompileTime = T::RowsAtCompileTime; - static constexpr int ColsAtCompileTime = T::ColsAtCompileTime; - static constexpr bool IsVectorAtCompileTime = T::IsVectorAtCompileTime; - static constexpr bool is_immutable = T::is_immutable; - - using parent::evaluate; - using parent::noalias; - using parent::operator(); - using parent::operator[]; - using parent::cols; - using parent::cwiseAbs; - using parent::cwiseAbs2; - using parent::cwiseInverse; - using parent::cwiseSqrt; - using parent::data; - using parent::lpNorm; - using parent::maxCoeff; - using parent::mean; - using parent::minCoeff; - using parent::norm; - using parent::normalize; - using parent::prod; - using parent::rows; - using parent::size; - using parent::squaredNorm; - using parent::sum; - using parent::trace; - using parent::transpose; - using parent::operator+=; - using parent::operator-=; - using parent::operator*=; - using parent::operator/=; - using parent::Constant; - using parent::Identity; - using parent::innerStride; - using parent::outerStride; - using parent::Random; - using parent::Zero; - - using parent::operator=; - - using stride_type = typename parent::stride_type; - static constexpr bool has_static_storage = parent::has_static_storage; - - parent const& base() const { return static_cast(*this); } - - template S, int R, int C, int O, int MR, int MC> - ref(matrix const& m) - : parent(m.data(), m.rows(), m.cols(), strides(m)) - { - } - - template - ref(block const& b) - requires(std::same_as && - (Ref::storage_order & 1) == storage_order) - : parent(b.data(), - b.rows(), - b.cols(), - stride_type{b.outerStride(), b.innerStride()}) - { - } - - template - ref(map const& b) - requires(std::same_as && - (Ref::storage_order & 1) == storage_order) - : parent(b.data(), - b.rows(), - b.cols(), - stride_type{b.outerStride(), b.innerStride()}) - { - } - - template - ref(ref const& b) - requires(std::same_as && - (TT::storage_order & 1) == storage_order) - : parent(b.data(), - b.rows(), - b.cols(), - stride_type{b.outerStride(), b.innerStride()}) - { - } - - ref(parent const& m) : parent(m.data(), m.rows(), m.cols()) {} - - friend std::ostream& operator<<(std::ostream& os, ref const& r) - { - return os << r.base(); - } - - friend std::ostream& operator<<(std::ostream& os, format const& r) - { - return os << format{r.matrix_.base(), r.format_}; - } - }; - - template - ref(matrix&) -> ref>; - - template - ref(block& b) -> ref; - - template - ref(matrix const&) -> ref const>; - - template - ref(block const& b) -> ref; - - template - bool operator==(ref lhs, ref rhs) - { - return lhs.base() == rhs.base(); - } - - template - bool operator!=(ref lhs, ref rhs) - { - return lhs.base() != rhs.base(); - } - - template - auto operator+(ref lhs, ref rhs) - -> decltype(lhs.base() + rhs.base()) - { - return lhs.base() + rhs.base(); - } - - template - auto operator+=(ref lhs, ref rhs) - -> decltype(lhs.base() += rhs.base()) - { - return lhs.base() += rhs.base(); - } - - template - auto operator-(ref lhs, ref rhs) - { - return lhs.base() - rhs.base(); - } - - template - auto operator-=(ref lhs, ref rhs) - -> decltype(lhs.base() -= rhs.base()) - { - return lhs.base() -= rhs.base(); - } - - template - auto operator*(ref lhs, ref rhs) - { - return lhs.base() * rhs.base(); - } - - template - auto operator*=(ref lhs, ref rhs) - -> decltype(lhs.base() *= rhs.base()) - { - return lhs.base() *= rhs.base(); - } - - template - auto operator*(ref lhs, - std::convertible_to auto s) - { - return lhs.base() * s; - } - - template - auto operator*(std::convertible_to auto s, - ref rhs) - { - return s * rhs.base(); - } - - template - auto operator/(ref lhs, - std::convertible_to auto s) - { - return lhs.base() / s; - } - - template - auto dot(ref lhs, ref rhs) - { - return lhs.base().dot(rhs.base()); - } - - template - auto min(ref lhs, ref rhs) - -> decltype(lhs.base().cwiseMin(rhs.base())) - { - return lhs.base().cwiseMin(rhs.base()); - } - - template - auto min(ref lhs, std::convertible_to auto s) - -> decltype(lhs.base().cwiseMin(s)) - { - return lhs.base().cwiseMin(s); - } - - template - auto min(std::convertible_to auto s, ref rhs) - -> decltype(rhs.base().cwiseMin(s)) - { - return rhs.base().cwiseMin(s); - } - - template - auto max(ref lhs, ref rhs) - -> decltype(lhs.base().cwiseMax(rhs.base())) - { - return lhs.base().cwiseMax(rhs.base()); - } - - template - auto max(ref lhs, std::convertible_to auto s) - -> decltype(lhs.base().cwiseMax(s)) - { - return lhs.base().cwiseMax(s); - } - - template - auto max(std::convertible_to auto s, ref rhs) - -> decltype(rhs.base().cwiseMax(s)) - { - return rhs.base().cwiseMax(s); - } - - template - auto mul(ref lhs, ref rhs) - -> decltype(lhs.base().cwiseProduct(rhs.base())) - { - return lhs.base().cwiseProduct(rhs.base()); - } - - template - auto mul(ref lhs, std::convertible_to auto s) - -> decltype(lhs * s) - { - return lhs * s; - } - - template - auto mul(std::convertible_to auto s, ref rhs) - -> decltype(s * rhs) - { - return s * rhs; - } - - template - auto div(ref lhs, ref rhs) - -> decltype(lhs.base().cwiseQuotient(rhs.base())) - { - return lhs.base().cwiseQuotient(rhs.base()); - } - - template - auto div(ref lhs, std::convertible_to auto s) - -> decltype(lhs / s) - { - return lhs / s; - } - - template - auto inverse(ref lhs) -> decltype(lhs.base().inverse()) - { - return lhs.base().inverse(); - } - - template - auto cross(ref lhs, ref rhs) - -> decltype(lhs.base().cross(rhs.base())) - { - return lhs.base().cross(rhs.base()); - } - - //------------------------------------------------------------------------------------------- - // Convert entity/eigen types to a proper ref so we can write less function - // overloads - template struct generalize; - - template - requires(std::is_arithmetic_v>) - struct generalize - { - using type = std::remove_cvref_t; - }; - - template using generalize_t = typename generalize::type; - - template struct generalize - { - static constexpr bool is_const = std::is_const_v; - using base = matrix; - using type = std::conditional_t, ref>; - }; - - template struct generalize> - { - using type = ref; - }; - - template struct generalize const> - { - using type = ref; - }; - - template typename T::parent& base_of(T& a) - { - return a.base(); - } - - template typename T::parent const& base_of(T const& a) - { - return a.base(); - } - - template - T base_of(T a) - requires(std::is_arithmetic_v) - { - return a; - } - -#if !defined(ROTGEN_FORCE_DYNAMIC) - template struct generalize - { - static constexpr bool is_const = std::is_const_v; - using concrete_type = decltype(std::declval().eval()); - using base = matrix; - using type = std::conditional_t, ref>; - }; - - template auto const& base_of(T const& a) - { - return a; - } - - template auto& base_of(T& a) - { - return a; - } -#endif -} +#include +#include diff --git a/include/rotgen/container/ref/dynamic.hpp b/include/rotgen/container/ref/dynamic.hpp new file mode 100644 index 0000000..75010d3 --- /dev/null +++ b/include/rotgen/container/ref/dynamic.hpp @@ -0,0 +1,353 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include +#include + +#if !defined(ROTGEN_FORCE_DYNAMIC) +#include +#endif + +#include + +namespace rotgen +{ + template + class ref : private map + { + public: + using parent = map; + using referee = std::remove_const_t; + using value_type = typename referee::value_type; + using rotgen_tag = void; + using rotgen_ref_tag = void; + + static constexpr int storage_order = referee::storage_order; + static constexpr int RowsAtCompileTime = referee::RowsAtCompileTime; + static constexpr int ColsAtCompileTime = referee::ColsAtCompileTime; + static constexpr int MaxRowsAtCompileTime = referee::MaxRowsAtCompileTime; + static constexpr int MaxColsAtCompileTime = referee::MaxColsAtCompileTime; + static constexpr bool IsRowMajor = referee::IsRowMajor; + static constexpr bool IsVectorAtCompileTime = + referee::IsVectorAtCompileTime; + static constexpr bool is_immutable = std::is_const_v; + + static constexpr int InnerStrideAtCompileTime = + parent::InnerStrideAtCompileTime; + static constexpr int OuterStrideAtCompileTime = + parent::OuterStrideAtCompileTime; + + static constexpr bool may_map_object = + (Stride::InnerStrideAtCompileTime == 0 || + Stride::InnerStrideAtCompileTime == 1 || + Stride::InnerStrideAtCompileTime == Dynamic) && + (referee::IsVectorAtCompileTime || + Stride::OuterStrideAtCompileTime == 0 || + Stride::OuterStrideAtCompileTime == Dynamic || + Stride::OuterStrideAtCompileTime == referee::InnerSizeAtCompileTime || + referee::InnerSizeAtCompileTime == Dynamic); + + // Access to values + using parent::operator(); + using parent::operator[]; + + // Size related functions + using parent::cols; + using parent::data; + using parent::innerStride; + using parent::outerStride; + using parent::rows; + using parent::size; + + // Aliasing handling + using parent::evaluate; + using parent::noalias; + + // Reductions + using parent::lpNorm; + using parent::maxCoeff; + using parent::mean; + using parent::minCoeff; + using parent::norm; + using parent::prod; + using parent::squaredNorm; + using parent::sum; + using parent::trace; + + // Arithmetic + using parent::cwiseAbs; + using parent::cwiseAbs2; + using parent::cwiseInverse; + using parent::cwiseSqrt; + + // Shape modifications + using parent::adjoint; + using parent::conjugate; + using parent::normalized; + using parent::transpose; + + // In-place Shape modifications + using parent::adjointInPlace; + using parent::normalize; + using parent::transposeInPlace; + + // Generators + using parent::Constant; + using parent::Identity; + using parent::Ones; + using parent::Random; + using parent::setConstant; + using parent::setIdentity; + using parent::setOnes; + using parent::setRandom; + using parent::setZero; + using parent::Zero; + + using parent::operator=; + + template + auto qr_solve(ref rhs) const + { + return parent::qr_solve(rhs.base()); + }; + + using stride_type = typename parent::stride_type; + + parent const& base() const { return static_cast(*this); } + + parent& base() { return static_cast(*this); } + + parent const& as_map() const { return base(); } + + parent& as_map() { return base(); } + + template + requires(detail::accept_as_ref>) + ref(matrix& m) : parent(detail::postpone{}) + { + [[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, m); + assert(correct_ref_setup); + } + + template + requires(is_immutable && + detail::same_scalar> && + (detail::accept_as_ref> || + may_map_object)) + ref(matrix const& m) : parent(detail::postpone{}) + { + if (!detail::validate_ref(*this, m)) + { + potential_local_copy = m; + detail::validate_ref(*this, potential_local_copy); + } + } + + template + requires(detail::accept_as_ref>) + ref(block&& b) : parent(detail::postpone{}) + { + [[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, b); + assert(correct_ref_setup); + } + + template + requires(detail::accept_as_ref>) + ref(block& b) : parent(detail::postpone{}) + { + [[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, b); + assert(correct_ref_setup); + } + + template + requires(is_immutable && detail::same_scalar> && + (detail::accept_as_ref> || + may_map_object)) + ref(block const& b) : parent(detail::postpone{}) + { + if (!detail::validate_ref(*this, b)) + { + potential_local_copy = b; + detail::validate_ref(*this, potential_local_copy); + } + } + + template + requires(detail::accept_as_ref>) + ref(map& b) : parent(detail::postpone{}) + { + [[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, b); + assert(correct_ref_setup); + } + + template + requires(is_immutable && detail::same_scalar> && + (detail::accept_as_ref> || may_map_object)) + ref(map const& b) : parent(detail::postpone{}) + { + if (!detail::validate_ref(*this, b)) + { + potential_local_copy = b; + detail::validate_ref(*this, potential_local_copy); + } + } + + template + requires(detail::accept_as_ref>) + ref(ref& b) : parent(detail::postpone{}) + { + [[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, b); + assert(correct_ref_setup); + } + + template + requires(is_immutable && detail::same_scalar> && + (detail::accept_as_ref> || may_map_object)) + ref(ref const& b) : parent(detail::postpone{}) + { + [[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, b); + assert(correct_ref_setup); + } + + ref(parent& m) : parent(m.data(), m.rows(), m.cols()) {} + + ref(parent const& m) + requires(is_immutable) + : parent(m.data(), m.rows(), m.cols()) + { + } + + friend std::ostream& operator<<(std::ostream& os, ref const& r) + { + return os << r.base(); + } + + friend std::ostream& operator<<(std::ostream& os, format const& r) + { + return os << format{r.matrix_.base(), r.format_}; + } + + private: + referee potential_local_copy; + }; + + template + ref(matrix&) -> ref>; + + template + ref(block& b) -> ref; + + template + ref(matrix const&) -> ref const>; + + template + ref(block const& b) -> ref; + + template + auto operator+(ref lhs, ref rhs) + -> decltype(lhs.base() + rhs.base()) + { + return lhs.base() + rhs.base(); + } + + template + auto operator-(ref lhs, ref rhs) + { + return lhs.base() - rhs.base(); + } + + template + auto operator*(ref lhs, ref rhs) + { + return lhs.base() * rhs.base(); + } + + template + auto operator*(ref lhs, + std::convertible_to auto s) + { + return lhs.base() * s; + } + + template + auto operator/(ref lhs, + std::convertible_to auto s) + { + return lhs.base() / s; + } + + template + auto min(ref lhs, ref rhs) + -> decltype(lhs.base().cwiseMin(rhs.base())) + { + return lhs.base().cwiseMin(rhs.base()); + } + + template + auto min(ref lhs, std::convertible_to auto s) + -> decltype(lhs.base().cwiseMin(s)) + { + return lhs.base().cwiseMin(s); + } + + template + auto min(std::convertible_to auto s, ref rhs) + -> decltype(rhs.base().cwiseMin(s)) + { + return rhs.base().cwiseMin(s); + } + + template + auto max(ref lhs, ref rhs) + -> decltype(lhs.base().cwiseMax(rhs.base())) + { + return lhs.base().cwiseMax(rhs.base()); + } + + template + auto max(ref lhs, std::convertible_to auto s) + -> decltype(lhs.base().cwiseMax(s)) + { + return lhs.base().cwiseMax(s); + } + + template + auto max(std::convertible_to auto s, ref rhs) + -> decltype(rhs.base().cwiseMax(s)) + { + return rhs.base().cwiseMax(s); + } + + template + auto mul(ref lhs, ref rhs) + -> decltype(lhs.base().cwiseProduct(rhs.base())) + { + return lhs.base().cwiseProduct(rhs.base()); + } + + template + auto div(ref lhs, ref rhs) + -> decltype(lhs.base().cwiseQuotient(rhs.base())) + { + return lhs.base().cwiseQuotient(rhs.base()); + } + + template + auto inverse(ref lhs) -> decltype(lhs.base().inverse()) + { + return lhs.base().inverse(); + } + + template + auto cross(ref lhs, ref rhs) + -> decltype(lhs.base().cross(rhs.base())) + { + return lhs.base().cross(rhs.base()); + } +} diff --git a/include/rotgen/container/ref/fixed.hpp b/include/rotgen/container/ref/fixed.hpp new file mode 100644 index 0000000..51e96f3 --- /dev/null +++ b/include/rotgen/container/ref/fixed.hpp @@ -0,0 +1,397 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include + +#include +#include + +namespace rotgen +{ + namespace detail + { + template struct compile_ref; + + template + struct compile_ref, + Options, + Stride> + { + using base = Eigen::Matrix; + using type = Eigen::Ref; + }; + + template + struct compile_ref const, + Options, + Stride> + { + using base = Eigen::Matrix; + using type = Eigen::Ref; + }; + + template + using compile_ref_t = typename compile_ref::type; + } + + template + class ref : private detail::compile_ref_t + { + public: + using parent = detail::compile_ref_t; + using referee = std::remove_const_t; + using value_type = typename referee::value_type; + using rotgen_tag = void; + using rotgen_ref_tag = void; + using stride_type = Stride; + + static constexpr int RowsAtCompileTime = parent::RowsAtCompileTime; + static constexpr int ColsAtCompileTime = parent::ColsAtCompileTime; + static constexpr int MaxRowsAtCompileTime = parent::MaxRowsAtCompileTime; + static constexpr int MaxColsAtCompileTime = parent::MaxColsAtCompileTime; + static constexpr int InnerStrideAtCompileTime = + parent::InnerStrideAtCompileTime; + static constexpr int OuterStrideAtCompileTime = + parent::OuterStrideAtCompileTime; + static constexpr bool IsRowMajor = parent::IsRowMajor; + static constexpr bool IsVectorAtCompileTime = parent::IsVectorAtCompileTime; + static constexpr int storage_order = IsRowMajor ? RowMajor : ColMajor; + static constexpr bool is_immutable = std::is_const_v; + + // Access to values + using parent::operator(); + using parent::operator[]; + + // Size related functions + using parent::cols; + using parent::data; + using parent::innerStride; + using parent::outerStride; + using parent::rows; + using parent::size; + + // Aliasing handling + auto evaluate() const + { + auto res = static_cast(*this).eval(); + return as_concrete_type(res); + } + + auto evaluate() + { + auto res = static_cast(*this).eval(); + return as_concrete_type(res); + } + + decltype(auto) noalias() const + { + if constexpr (use_expression_templates) return base().noalias(); + else return *this; + } + + decltype(auto) noalias() + { + if constexpr (use_expression_templates) return base().noalias(); + else return *this; + } + + // Numeric functions + using parent::cwiseAbs; + using parent::cwiseAbs2; + using parent::cwiseInverse; + using parent::cwiseSqrt; + + // Reductions + using parent::lpNorm; + using parent::maxCoeff; + using parent::mean; + using parent::minCoeff; + using parent::norm; + using parent::prod; + using parent::squaredNorm; + using parent::sum; + using parent::trace; + + // Shape modifications + using parent::adjoint; + using parent::conjugate; + using parent::normalized; + using parent::transpose; + + // In-place Shape modifications + using parent::adjointInPlace; + using parent::normalize; + using parent::transposeInPlace; + + // Generators + using parent::Constant; + using parent::Identity; + using parent::Ones; + using parent::Random; + using parent::setConstant; + using parent::setIdentity; + using parent::setOnes; + using parent::setRandom; + using parent::setZero; + using parent::Zero; + + auto qr_solve(auto const& rhs) const + { + // Can't store the result of this .solve has it's some deep E.T + return detail::as_concrete_t< + decltype(base().colPivHouseholderQr().solve(rhs.base())), matrix>( + base().colPivHouseholderQr().solve(rhs.base())); + }; + + // using parent::operator=; + ref& operator=(concepts::entity auto const& e) + { + base() = e.base(); + return *this; + } + + parent const& base() const { return static_cast(*this); } + + parent& base() { return static_cast(*this); } + + template + ref(matrix& m) + requires(requires { parent(m.base()); }) + : parent(m.base()) + { + } + + template + ref(matrix const& m) + requires(requires { parent(m.base()); } && is_immutable) + : parent(m.base()) + { + } + + template + ref(block&& b) + requires(requires { parent(b.base()); }) + : parent(b.base()) + { + } + + template + ref(block& b) + requires(requires { parent(b.base()); }) + : parent(b.base()) + { + } + + template + ref(block const& b) + requires(requires { parent(b.base()); } && is_immutable) + : parent(b.base()) + { + } + + template + ref(map& m) + requires(requires { parent(m.base()); }) + : parent(m.base()) + { + } + + template + ref(map const& m) + requires(requires { parent(m.base()); } && is_immutable) + : parent(m.base()) + { + } + + template + ref(ref& r) + requires(requires { parent(r.base()); }) + : parent(r.base()) + { + } + + template + ref(ref const& r) + requires(requires { parent(r.base()); } && is_immutable) + : parent(r.base()) + { + } + + ref(parent& m) : parent(m) {} + + ref(parent const& m) + requires(is_immutable) + : parent(m) + { + } + + friend std::ostream& operator<<(std::ostream& os, ref const& r) + { + return os << r.base(); + } + + friend std::ostream& operator<<(std::ostream& os, format const& r) + { + return os << format{r.matrix_.base(), r.format_}; + } + }; + + //============================================================================ + // Deduction Guides + //============================================================================ + template + ref(matrix&) -> ref>; + + template + ref(block& b) -> ref; + + template + ref(matrix const&) -> ref const>; + + template + ref(block const& b) -> ref; + + //============================================================================ + // Operators + //============================================================================ + template + auto operator+(ref lhs, ref rhs) + { + return detail::concretize(lhs.base() + rhs.base()); + } + + template + auto operator-(ref lhs, ref rhs) + { + return detail::concretize(lhs.base() - rhs.base()); + } + + template + auto operator*(ref lhs, ref rhs) + { + return detail::concretize(lhs.base() * rhs.base()); + } + + template + auto operator*(ref lhs, + std::convertible_to auto s) + { + return detail::concretize(lhs.base() * s); + } + + template + auto operator/(ref lhs, + std::convertible_to auto s) + { + return detail::concretize(lhs.base() / s); + } + + template + auto mul(ref lhs, ref rhs) + { + return detail::concretize(lhs.base().cwiseProduct(rhs.base())); + } + + template + auto div(ref lhs, ref rhs) + { + return detail::concretize(lhs.base().cwiseQuotient(rhs.base())); + } + + //============================================================================ + // Functions + //============================================================================ + template + auto min(ref lhs, ref rhs) + { + return detail::concretize(lhs.base().cwiseMin(rhs.base())); + } + + template + auto min(ref lhs, std::convertible_to auto s) + { + return detail::concretize(lhs.base().cwiseMin(s)); + } + + template + auto min(std::convertible_to auto s, ref rhs) + { + return detail::concretize(rhs.base().cwiseMin(s)); + } + + template + auto max(ref lhs, ref rhs) + { + return detail::concretize(lhs.base().cwiseMax(rhs.base())); + } + + template + auto max(ref lhs, std::convertible_to auto s) + { + return detail::concretize(lhs.base().cwiseMax(s)); + } + + template + auto max(std::convertible_to auto s, ref rhs) + { + return detail::concretize(rhs.base().cwiseMax(s)); + } + + template auto inverse(ref lhs) + { + return detail::concretize(lhs.base().inverse()); + } + + template + auto cross(ref lhs, ref rhs) + -> decltype(lhs.base().cross(rhs.base())) + { + return detail::concretize(lhs.base().cross(rhs.base())); + } + + //------------------------------------------------------------------------------------------- + // Convert entity/eigen types to a proper ref so we can write less function + // overloads + template struct generalize; + + template struct generalize + { + static constexpr bool is_const = std::is_const_v; + using concrete_type = decltype(std::declval().eval()); + using base = matrix; + using type = std::conditional_t, ref>; + }; + + template auto const& base_of(T const& a) + { + return a; + } + + template auto& base_of(T& a) + { + return a; + } +} diff --git a/include/rotgen/container/ref/functions.hpp b/include/rotgen/container/ref/functions.hpp new file mode 100644 index 0000000..732b95c --- /dev/null +++ b/include/rotgen/container/ref/functions.hpp @@ -0,0 +1,88 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include + +namespace rotgen +{ + template + bool operator==(ref lhs, ref rhs) + { + return lhs.base() == rhs.base(); + } + + template + bool operator!=(ref lhs, ref rhs) + { + return lhs.base() != rhs.base(); + } + + template + auto operator+=(ref lhs, ref rhs) + { + lhs.base() += rhs.base(); + return lhs; + } + + template + auto operator-=(ref lhs, ref rhs) + { + lhs.base() -= rhs.base(); + return lhs; + } + + template + auto operator*=(ref lhs, ref rhs) + { + lhs.base() *= rhs.base(); + return lhs; + } + + template + auto operator/=(ref lhs, + std::convertible_to auto s) + { + lhs.base() /= s; + return lhs; + } + + template + auto operator*(std::convertible_to auto s, + ref rhs) + { + return rhs * s; + } + + template + auto dot(ref lhs, ref rhs) + { + return lhs.base().dot(rhs.base()); + } + + template + auto mul(ref lhs, std::convertible_to auto s) + -> decltype(lhs * s) + { + return lhs * s; + } + + template + auto mul(std::convertible_to auto s, ref rhs) + -> decltype(s * rhs) + { + return s * rhs; + } + + template + auto div(ref lhs, std::convertible_to auto s) + -> decltype(lhs / s) + { + return lhs / s; + } +} diff --git a/include/rotgen/container/ref/generalize.hpp b/include/rotgen/container/ref/generalize.hpp new file mode 100644 index 0000000..021646b --- /dev/null +++ b/include/rotgen/container/ref/generalize.hpp @@ -0,0 +1,65 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include + +namespace rotgen +{ + //------------------------------------------------------------------------------------------- + // Convert entity/eigen types to a proper ref so we can write less function + // overloads + + template struct generalize; + + template + requires(std::is_arithmetic_v>) + struct generalize + { + using type = std::remove_cvref_t; + }; + + template using generalize_t = typename generalize::type; + + template struct generalize + { + static constexpr bool is_const = std::is_const_v; + using base = matrix; + using type = std::conditional_t, ref>; + }; + + template struct generalize> + { + using type = ref; + }; + + template struct generalize const> + { + using type = ref; + }; + + template typename T::parent& base_of(T& a) + { + return a.base(); + } + + template typename T::parent const& base_of(T const& a) + { + return a.base(); + } + + template + T base_of(T a) + requires(std::is_arithmetic_v) + { + return a; + } +} diff --git a/include/rotgen/container/strides.hpp b/include/rotgen/container/strides.hpp index f861794..f4c8545 100644 --- a/include/rotgen/container/strides.hpp +++ b/include/rotgen/container/strides.hpp @@ -7,76 +7,10 @@ //================================================================================================== #pragma once -#include +#include -#if !defined(ROTGEN_FORCE_DYNAMIC) -#include -#endif - -namespace rotgen -{ -#if !defined(ROTGEN_FORCE_DYNAMIC) - using stride = Eigen::Stride<-1, -1>; +#if defined(ROTGEN_FORCE_DYNAMIC) +#include #else - struct stride - { - static constexpr bool is_dynamic = true; - - stride() : outer_(-1), inner_(1) {} - - stride(Index s, Index i) : outer_(s), inner_(i) {} - - Index inner() const { return inner_; } - - Index outer() const { return outer_; } - - private: - Index outer_; - Index inner_; - }; +#include #endif - - template struct inner_stride : stride - { - static constexpr bool is_dynamic = Value == Dynamic; - - inner_stride() : stride(-1, Value) {} - - inner_stride(Index v) : stride(0, v) {} - }; - - template struct outer_stride : stride - { - static constexpr bool is_dynamic = Value == Dynamic; - - outer_stride() : stride(Value, 0) {} - - outer_stride(Index v) : stride(v, 0) {} - }; - - inner_stride(Index) -> inner_stride; - outer_stride(Index) -> outer_stride; - - template stride strides(Index r, Index c) - { - if constexpr (Order == RowMajor) return {c, 1}; - else return {r, 1}; - } - - template stride strides(stride const& original, Index, Index) - { - return original; - } - - template - stride strides(outer_stride const& original, Index r, Index c) - { - if constexpr (N == 0) return stride{Order == ColMajor ? r : c, 1}; - else return {original.outer(), 1}; - } - - template auto strides(E const& e) - { - return strides(e.rows(), e.cols()); - } -} diff --git a/include/rotgen/container/strides/dynamic.hpp b/include/rotgen/container/strides/dynamic.hpp new file mode 100644 index 0000000..e25597c --- /dev/null +++ b/include/rotgen/container/strides/dynamic.hpp @@ -0,0 +1,84 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include + +namespace rotgen +{ + template struct stride + { + static constexpr int InnerStrideAtCompileTime = Inner; + static constexpr int OuterStrideAtCompileTime = Outer; + + constexpr stride() + requires(Inner != Dynamic && Outer != Dynamic) + : outer_(Outer), inner_(Inner) + { + } + + stride(Index o, Index i) : outer_(o), inner_(i) {} + + constexpr Index outer() const { return outer_; } + + constexpr Index inner() const { return inner_; } + + protected: + Index outer_; + Index inner_; + }; + + template struct inner_stride : stride<0, Value> + { + using parent = stride<0, Value>; + + inner_stride() : parent() {} + + inner_stride(int v) : parent(0, v) {} + }; + + template struct outer_stride : stride + { + using parent = stride; + + outer_stride() : parent() {} + + outer_stride(int v) : parent(v, 0) {} + }; + + using dynamic_stride = stride<-1, -1>; + + template dynamic_stride strides(Index r, Index c) + { + if constexpr (Order == RowMajor) return {c, 1}; + else return {r, 1}; + } + + template dynamic_stride strides(E const& e) + { + return strides(e.rows(), e.cols()); + } + + template + dynamic_stride strides(stride const& original, Index, Index) + { + return {original.outer(), original.inner()}; + } + + template + dynamic_stride strides(outer_stride const& original, Index r, Index c) + { + if constexpr (N == 0) return {Order == ColMajor ? r : c, 1}; + else return {original.outer(), 1}; + } + + template auto strides(E const& e) + { + return strides(e.rows(), e.cols()); + } +} diff --git a/include/rotgen/container/strides/fixed.hpp b/include/rotgen/container/strides/fixed.hpp new file mode 100644 index 0000000..7e9cd56 --- /dev/null +++ b/include/rotgen/container/strides/fixed.hpp @@ -0,0 +1,40 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include + +#include + +namespace rotgen +{ + template struct stride : Eigen::Stride + { + using parent = Eigen::Stride; + using parent::parent; + }; + + template + struct inner_stride : Eigen::InnerStride + { + using parent = Eigen::InnerStride; + using parent::parent; + }; + + template + struct outer_stride : Eigen::OuterStride + { + using parent = Eigen::OuterStride; + using parent::parent; + }; + + inner_stride(int) -> inner_stride<-1>; + outer_stride(int) -> outer_stride<-1>; + + using dynamic_stride = stride<-1, -1>; +} diff --git a/include/rotgen/detail/accept_as_ref.hpp b/include/rotgen/detail/accept_as_ref.hpp new file mode 100644 index 0000000..0d71a22 --- /dev/null +++ b/include/rotgen/detail/accept_as_ref.hpp @@ -0,0 +1,160 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include +#include + +namespace rotgen::detail +{ + // We split each sub-check into its own concept to improve + // diagnostic messages + template + concept same_scalar = + std::same_as; + + template + concept any_is_vector = + Ref::IsVectorAtCompileTime || Input::IsVectorAtCompileTime; + + template + concept compatible_storage = + any_is_vector || (Ref::storage_order == Input::storage_order); + + template + concept compatible_inner_stride = + (Ref::InnerStrideAtCompileTime == rotgen::Dynamic) || + (Ref::InnerStrideAtCompileTime == Input::InnerStrideAtCompileTime) || + (Ref::InnerStrideAtCompileTime == 0 && + Input::InnerStrideAtCompileTime == 1); + + template + concept compatible_outer_stride = + any_is_vector || + (Ref::OuterStrideAtCompileTime == rotgen::Dynamic) || + (Ref::OuterStrideAtCompileTime == Input::OuterStrideAtCompileTime); + + // Check what we can actually pass to ref<> + template + concept accept_as_ref = + same_scalar && compatible_storage && + compatible_inner_stride && compatible_outer_stride; + + // Local helpersto compute some strides related runtime values + constexpr Index proper_inner_stride(Index inner) + { + return inner == 0 ? 1 : inner; + } + + constexpr Index proper_outer_stride(Index inner, + Index outer, + Index rows, + Index cols, + bool isVectorAtCompileTime, + bool isRowMajor) + { + return outer == 0 ? isVectorAtCompileTime ? inner * rows * cols + : isRowMajor ? inner * cols + : inner * rows + : outer; + } + + // Helper used to runtime validate some properties of ref adn tells ref + // if a local copy and reconstruction needs to be done + template bool validate_ref(Ref& ref, Input& in) + { + using stride_type = typename Ref::stride_type; + using parent = typename Ref::parent; + using map_base = typename parent::parent; + + auto rows = in.rows(); + auto cols = in.cols(); + + if (Ref::RowsAtCompileTime == 1) + { + assert(in.rows() == 1 || in.cols() == 1); + rows = 1; + cols = in.size(); + } + else if (Ref::ColsAtCompileTime == 1) + { + assert(in.rows() == 1 || in.cols() == 1); + rows = in.size(); + cols = 1; + } + + // Verify that the sizes are valid. + assert((Ref::RowsAtCompileTime == Dynamic) || + (Ref::RowsAtCompileTime == rows)); + assert((Ref::ColsAtCompileTime == Dynamic) || + (Ref::ColsAtCompileTime == cols)); + + // Swap stride if we are a vector and we changed rows as such + bool transpose = Ref::IsVectorAtCompileTime && (rows != in.rows()); + + // Swap stride if storage ordder doesn't match + constexpr bool row_major = Ref::IsRowMajor; + constexpr bool input_row_major = Input::IsRowMajor; + constexpr bool storage_differs = (row_major != input_row_major); + + bool swap_stride = (transpose != storage_differs); + + // Determine expr's actual strides, resolving any defaults if zero. + Index inner_actual = proper_inner_stride(in.innerStride()); + Index outer_actual = + proper_outer_stride(inner_actual, in.outerStride(), in.rows(), in.cols(), + Input::IsVectorAtCompileTime, input_row_major); + + bool row_vector = (rows == 1); + bool col_vector = (cols == 1); + + // Adapt inner stride based on row/col vector status + Index inner_stride = + ((!row_major && row_vector) || (row_major && col_vector)) + ? (stride_type::InnerStrideAtCompileTime > 0 + ? stride_type::InnerStrideAtCompileTime + : 1) + : swap_stride ? outer_actual + : inner_actual; + + // Adapt outer stride based on row/col vector status + Index outer_stride = + ((!row_major && col_vector) || (row_major && row_vector)) + ? (stride_type::OuterStrideAtCompileTime > 0 + ? stride_type::OuterStrideAtCompileTime + : rows * cols * inner_stride) + : swap_stride ? inner_actual + : outer_actual; + + // Validate compatibility of strides with compile-time strides + bool inner_valid = + (stride_type::InnerStrideAtCompileTime == Dynamic) || + (proper_inner_stride(Index(stride_type::InnerStrideAtCompileTime)) == + inner_stride); + + if (!inner_valid) return false; + + bool outer_valid = + (stride_type::OuterStrideAtCompileTime == Dynamic) || + (proper_outer_stride( + inner_stride, Index(stride_type::OuterStrideAtCompileTime), rows, cols, + Ref::IsVectorAtCompileTime != 0, row_major) == outer_stride); + + if (!outer_valid) return false; + + dynamic_stride proper_stride( + stride_type::OuterStrideAtCompileTime == 0 ? 1 : outer_stride, + stride_type::InnerStrideAtCompileTime == 0 ? 1 : inner_stride); + + auto actual = map_base(in.data(), rows, cols, proper_stride); + + ref.base().base().storage().swap(actual.storage()); + + return true; + } +} diff --git a/include/rotgen/detail/helpers.hpp b/include/rotgen/detail/helpers.hpp index 2055f84..f700640 100644 --- a/include/rotgen/detail/helpers.hpp +++ b/include/rotgen/detail/helpers.hpp @@ -7,8 +7,21 @@ //================================================================================================== #pragma once +#include + +#include + namespace rotgen::detail { + template constexpr int static_size() + { + auto rows = T::RowsAtCompileTime; + auto cols = T::ColsAtCompileTime; + if (rows == 0 || cols == 0) return 0; + if (rows == -1 || cols == -1) return -1; + return rows * cols; + } + template typename Wrapper> struct as_concrete @@ -26,6 +39,13 @@ namespace rotgen::detail using as_concrete_t = typename as_concrete, Wrapper>::type; + template typename Wrapper> + decltype(auto) concretize(auto const& t) + { + if constexpr (use_expression_templates) return t; + else return as_concrete_t, Wrapper>(t); + } + template inline constexpr bool has_same_vector_size = []() { // No vector = noo size @@ -42,13 +62,13 @@ namespace rotgen::detail template using propagate_const = - std::conditional_t, - std::add_const_t, - T>; + std::conditional_t::is_immutable || + std::is_const_v, + std::add_const_t>, + std::remove_cvref_t>; template - inline constexpr auto select_static = - (M == rotgen::Dynamic || N == rotgen::Dynamic) ? rotgen::Dynamic : M; + inline constexpr auto select_static = (M == -1 || N == -1) ? -1 : M; template -#include -#include -#include -#include -#include +#include +#include +#include namespace rotgen { - //================================================================================================== - // Internal payload - Required 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; } - - void assign(data_type const& mat) { data = mat; } - - void assign(data_type&& mat) { data = std::move(mat); } - }; - - 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; } - - void assign(data_type const& mat) { data = mat; } - - void assign(data_type&& mat) { data = std::move(mat); } - }; - - 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; } - - void assign(data_type const& mat) { data = mat; } - - void assign(data_type&& mat) { data = std::move(mat); } - }; - - 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; } - - void assign(data_type const& mat) { data = mat; } - - void assign(data_type&& mat) { data = std::move(mat); } - }; - - //================================================================================================== - // Internal payload - Required for cross-referencing from mixed order on map - // operators - //================================================================================================== - struct map_const_impl32_col::payload - { - using stride_type = Eigen::Stride; - using base_type = - Eigen::Matrix; - using data_type = - Eigen::Map; - - data_type data; - - payload(data_type const& o) : data(o) {} - - payload(float const* ptr, Index r, Index c) : data(ptr, r, c) {} - - payload(float const* ptr, Index r, Index c, stride_type s) - : data(ptr, r, c, s) - { - } - }; - - struct map_const_impl32_row::payload - { - using stride_type = Eigen::Stride; - using base_type = - Eigen::Matrix; - using data_type = - Eigen::Map; - - data_type data; - - payload(data_type const& o) : data(o) {} - - payload(float const* ptr, Index r, Index c) : data(ptr, r, c) {} - - payload(float const* ptr, Index r, Index c, stride_type s) - : data(ptr, r, c, s) - { - } - }; - - struct map_impl32_col::payload - { - using stride_type = Eigen::Stride; - using base_type = - Eigen::Matrix; - using data_type = Eigen::Map; - - data_type data; - - payload(data_type const& o) : data(o) {} - - payload(float* ptr, Index r, Index c) : data(ptr, r, c) {} - - payload(float* ptr, Index r, Index c, stride_type s) : data(ptr, r, c, s) {} - }; - - struct map_impl32_row::payload - { - using stride_type = Eigen::Stride; - using base_type = - Eigen::Matrix; - using data_type = Eigen::Map; - - data_type data; - - payload(data_type const& o) : data(o) {} - - payload(float* ptr, Index r, Index c) : data(ptr, r, c) {} - - payload(float* ptr, Index r, Index c, stride_type s) : data(ptr, r, c, s) {} - }; - - struct map_const_impl64_col::payload - { - using stride_type = Eigen::Stride; - using base_type = - Eigen::Matrix; - using data_type = - Eigen::Map; - - data_type data; - - payload(data_type const& o) : data(o) {} - - payload(double const* ptr, Index r, Index c) : data(ptr, r, c) {} - - payload(double const* ptr, Index r, Index c, stride_type s) - : data(ptr, r, c, s) - { - } - }; - - struct map_const_impl64_row::payload - { - using stride_type = Eigen::Stride; - using base_type = - Eigen::Matrix; - using data_type = - Eigen::Map; - - data_type data; - - payload(data_type const& o) : data(o) {} - - payload(double const* ptr, Index r, Index c) : data(ptr, r, c) {} - - payload(double const* ptr, Index r, Index c, stride_type s) - : data(ptr, r, c, s) - { - } - }; - - struct map_impl64_col::payload - { - using stride_type = Eigen::Stride; - using base_type = - Eigen::Matrix; - using data_type = Eigen::Map; - - data_type data; - - payload(data_type const& o) : data(o) {} - - payload(double* ptr, Index r, Index c) : data(ptr, r, c) {} - - payload(double* ptr, Index r, Index c, stride_type s) : data(ptr, r, c, s) - { - } - }; - - struct map_impl64_row::payload - { - using stride_type = Eigen::Stride; - using base_type = - Eigen::Matrix; - using data_type = Eigen::Map; - - data_type data; - - payload(data_type const& o) : data(o) {} - - payload(double* ptr, Index r, Index c) : data(ptr, r, c) {} - - payload(double* ptr, Index r, Index c, stride_type s) : data(ptr, r, c, s) - { - } - }; - - // + // IO Formatting paylod struct ioformat::payload { Eigen::IOFormat instance; diff --git a/include/rotgen/detail/payload/block.hpp b/include/rotgen/detail/payload/block.hpp new file mode 100644 index 0000000..4e3fef9 --- /dev/null +++ b/include/rotgen/detail/payload/block.hpp @@ -0,0 +1,209 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include + +#include +#include +#include +#include +#include + +namespace rotgen +{ + struct source_t + { + }; + + struct trans_t + { + }; + + struct map_t + { + }; + + struct matrix_t + { + }; + + //================================================================================================ + // Template payload implementation + //================================================================================================ + template + struct payload_impl + { + using row_matrix_type = Eigen:: + Matrix; + using col_matrix_type = Eigen:: + Matrix; + + using source_matrix_type = + std::conditional_t; + using trans_matrix_type = + std::conditional_t; + + template + using maybe_const = std::conditional_t; + + using source_matrix_block_type = + Eigen::Block>; + using trans_matrix_block_type = + Eigen::Block>; + using source_matrix_storage_t = + std::pair*>; + using trans_matrix_storage_t = + std::pair*>; + + using stride_type = Eigen::Stride; + + using source_map_type = Eigen:: + Map, Eigen::Unaligned, stride_type>; + using trans_map_type = + Eigen::Map, Eigen::Unaligned, stride_type>; + using source_map_block_type = Eigen::Block>; + using trans_map_block_type = Eigen::Block>; + using source_map_storage_t = + std::pair*>; + using trans_map_storage_t = + std::pair*>; + + using data_type = std::variant; + + data_type data; + rotgen::Index abs_i0 = 0; + rotgen::Index abs_j0 = 0; + rotgen::Index rel_i0 = 0; + rotgen::Index rel_j0 = 0; + + template void apply(Func f) + { + std::visit([&](auto& blk) { return f(blk.first); }, data); + } + + template void apply(Func f) const + { + std::visit([&](auto const& blk) { return f(blk.first); }, data); + } + + payload_impl(data_type const& o) : data(o) {} + + payload_impl(auto const& o, + rotgen::Index i0, + rotgen::Index j0, + rotgen::Index ni, + rotgen::Index nj, + matrix_t const&, + source_t const&) + : data(source_matrix_storage_t{ + source_matrix_block_type{o.storage()->data, i0, j0, ni, nj}, + &o.storage()->data}), + abs_i0(i0), abs_j0(j0), rel_i0(i0), rel_j0(j0) + { + } + + payload_impl(auto const& o, + rotgen::Index i0, + rotgen::Index j0, + rotgen::Index ni, + rotgen::Index nj, + matrix_t const&, + trans_t const&) + : data(trans_matrix_storage_t{ + trans_matrix_block_type{o.storage()->data, i0, j0, ni, nj}, + &o.storage()->data}), + abs_i0(i0), abs_j0(j0), rel_i0(i0), rel_j0(j0) + { + } + + payload_impl(auto const& o, + rotgen::Index i0, + rotgen::Index j0, + rotgen::Index ni, + rotgen::Index nj, + map_t const&, + source_t const&) + : data(source_map_storage_t{ + source_map_block_type{o.storage()->data, i0, j0, ni, nj}, + &o.storage()->data}), + abs_i0(i0), abs_j0(j0), rel_i0(i0), rel_j0(j0) + { + } + + payload_impl(auto const& o, + rotgen::Index i0, + rotgen::Index j0, + rotgen::Index ni, + rotgen::Index nj, + map_t const&, + trans_t const&) + : data(trans_map_storage_t{ + trans_map_block_type{o.storage()->data, i0, j0, ni, nj}, + &o.storage()->data}), + abs_i0(i0), abs_j0(j0), rel_i0(i0), rel_j0(j0) + { + } + }; + + //================================================================================================ + // Concrete payload definitions + //================================================================================================ + struct block_const_impl64_col::payload + : payload_impl + { + using payload_impl::payload_impl; + }; + + struct block_const_impl64_row::payload + : payload_impl + { + using payload_impl::payload_impl; + }; + + struct block_const_impl32_col::payload + : payload_impl + { + using payload_impl::payload_impl; + }; + + struct block_const_impl32_row::payload + : payload_impl + { + using payload_impl::payload_impl; + }; + + struct block_impl64_col::payload + : payload_impl + { + using payload_impl::payload_impl; + }; + + struct block_impl64_row::payload + : payload_impl + { + using payload_impl::payload_impl; + }; + + struct block_impl32_col::payload : payload_impl + { + using payload_impl::payload_impl; + }; + + struct block_impl32_row::payload : payload_impl + { + using payload_impl::payload_impl; + }; +} diff --git a/include/rotgen/detail/payload/map.hpp b/include/rotgen/detail/payload/map.hpp new file mode 100644 index 0000000..5980e13 --- /dev/null +++ b/include/rotgen/detail/payload/map.hpp @@ -0,0 +1,170 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include + +#include +#include +#include +#include + +namespace rotgen +{ + //================================================================================================== + // Internal payload - Required for cross-referencing from mixed order on map + // operators + //================================================================================================== + struct map_const_impl32_col::payload + { + using stride_type = Eigen::Stride; + using base_type = + Eigen::Matrix; + using data_type = + Eigen::Map; + + data_type data; + + payload(data_type const& o) : data(o) {} + + payload(float const* ptr, Index r, Index c) : data(ptr, r, c) {} + + payload(float const* ptr, Index r, Index c, stride_type s) + : data(ptr, r, c, s) + { + } + }; + + struct map_const_impl32_row::payload + { + using stride_type = Eigen::Stride; + using base_type = + Eigen::Matrix; + using data_type = + Eigen::Map; + + data_type data; + + payload(data_type const& o) : data(o) {} + + payload(float const* ptr, Index r, Index c) : data(ptr, r, c) {} + + payload(float const* ptr, Index r, Index c, stride_type s) + : data(ptr, r, c, s) + { + } + }; + + struct map_impl32_col::payload + { + using stride_type = Eigen::Stride; + using base_type = + Eigen::Matrix; + using data_type = Eigen::Map; + + data_type data; + + payload(data_type const& o) : data(o) {} + + payload(float* ptr, Index r, Index c) : data(ptr, r, c) {} + + payload(float* ptr, Index r, Index c, stride_type s) : data(ptr, r, c, s) {} + }; + + struct map_impl32_row::payload + { + using stride_type = Eigen::Stride; + using base_type = + Eigen::Matrix; + using data_type = Eigen::Map; + + data_type data; + + payload(data_type const& o) : data(o) {} + + payload(float* ptr, Index r, Index c) : data(ptr, r, c) {} + + payload(float* ptr, Index r, Index c, stride_type s) : data(ptr, r, c, s) {} + }; + + struct map_const_impl64_col::payload + { + using stride_type = Eigen::Stride; + using base_type = + Eigen::Matrix; + using data_type = + Eigen::Map; + + data_type data; + + payload(data_type const& o) : data(o) {} + + payload(double const* ptr, Index r, Index c) : data(ptr, r, c) {} + + payload(double const* ptr, Index r, Index c, stride_type s) + : data(ptr, r, c, s) + { + } + }; + + struct map_const_impl64_row::payload + { + using stride_type = Eigen::Stride; + using base_type = + Eigen::Matrix; + using data_type = + Eigen::Map; + + data_type data; + + payload(data_type const& o) : data(o) {} + + payload(double const* ptr, Index r, Index c) : data(ptr, r, c) {} + + payload(double const* ptr, Index r, Index c, stride_type s) + : data(ptr, r, c, s) + { + } + }; + + struct map_impl64_col::payload + { + using stride_type = Eigen::Stride; + using base_type = + Eigen::Matrix; + using data_type = Eigen::Map; + + data_type data; + + payload(data_type const& o) : data(o) {} + + payload(double* ptr, Index r, Index c) : data(ptr, r, c) {} + + payload(double* ptr, Index r, Index c, stride_type s) : data(ptr, r, c, s) + { + } + }; + + struct map_impl64_row::payload + { + using stride_type = Eigen::Stride; + using base_type = + Eigen::Matrix; + using data_type = Eigen::Map; + + data_type data; + + payload(data_type const& o) : data(o) {} + + payload(double* ptr, Index r, Index c) : data(ptr, r, c) {} + + payload(double* ptr, Index r, Index c, stride_type s) : data(ptr, r, c, s) + { + } + }; +} diff --git a/include/rotgen/detail/payload/matrix.hpp b/include/rotgen/detail/payload/matrix.hpp new file mode 100644 index 0000000..d10f755 --- /dev/null +++ b/include/rotgen/detail/payload/matrix.hpp @@ -0,0 +1,113 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include + +#include +#include +#include +#include + +namespace rotgen +{ + //================================================================================================== + // Internal payload - Required 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; } + + void assign(data_type const& mat) { data = mat; } + + void assign(data_type&& mat) { data = std::move(mat); } + }; + + 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; } + + void assign(data_type const& mat) { data = mat; } + + void assign(data_type&& mat) { data = std::move(mat); } + }; + + 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; } + + void assign(data_type const& mat) { data = mat; } + + void assign(data_type&& mat) { data = std::move(mat); } + }; + + 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; } + + void assign(data_type const& mat) { data = mat; } + + void assign(data_type&& mat) { data = std::move(mat); } + }; +} diff --git a/include/rotgen/functions.hpp b/include/rotgen/functions.hpp index 9c9b91d..f3fee0f 100644 --- a/include/rotgen/functions.hpp +++ b/include/rotgen/functions.hpp @@ -9,5 +9,6 @@ #include #include +#include #include #include diff --git a/include/rotgen/functions/extract.hpp b/include/rotgen/functions/extract.hpp index d77e7f0..46d4633 100644 --- a/include/rotgen/functions/extract.hpp +++ b/include/rotgen/functions/extract.hpp @@ -31,8 +31,8 @@ namespace rotgen auto extract(Entity& e, Index i0, Index j0, Index ni, Index nj) { detail::validate_extract(e, i0, j0, ni, nj); - if constexpr (concepts::reference) - return extract(e.base(), i0, j0, ni, nj); + if constexpr (requires { e.as_map(); }) + return extract(e.as_map(), i0, j0, ni, nj); else return block>(e, i0, j0, ni, nj); } @@ -41,8 +41,8 @@ namespace rotgen auto extract(Entity& e, Index i0, Index j0) { detail::validate_extract(e, i0, j0, NI, NJ); - if constexpr (concepts::reference) - return extract(e.base(), i0, j0); + if constexpr (requires { e.as_map(); }) + return extract(e.as_map(), i0, j0); else return block, NI, NJ>(e, i0, j0); } @@ -51,8 +51,8 @@ namespace rotgen auto extract(Entity& e, Index i0, Index j0, Index ni, Index nj) { detail::validate_extract(e, i0, j0, ni, nj); - if constexpr (concepts::reference) - return extract(e.base(), i0, j0, ni, nj); + if constexpr (requires { e.as_map(); }) + return extract(e.as_map(), i0, j0, ni, nj); else return block, NI, NJ>(e, i0, j0, ni, nj); } @@ -112,83 +112,116 @@ namespace rotgen //======================== TOP ROWS ======================== template auto topRows(Entity& e, Index ni) { - return extract(e, 0, 0, ni, e.cols()); + if constexpr (Entity::ColsAtCompileTime == -1) + return extract(e, 0, 0, ni, e.cols()); + else return extract<-1, Entity::ColsAtCompileTime>(e, 0, 0, ni, e.cols()); } template auto topRows(Entity& e) { - return extract(e, 0, 0, NI, e.cols()); + if constexpr (Entity::ColsAtCompileTime == -1) + return extract(e, 0, 0, NI, e.cols()); + else return extract(e, 0, 0); } //======================== MIDDLE ROWS ======================== template auto middleRows(Entity& e, Index i0, Index ni) { - return extract(e, i0, 0, ni, e.cols()); + if constexpr (Entity::ColsAtCompileTime == -1) + return extract(e, i0, 0, ni, e.cols()); + else return extract<-1, Entity::ColsAtCompileTime>(e, i0, 0, ni, e.cols()); } template auto middleRows(Entity& e, Index i0) { - return extract(e, i0, 0, NI, e.cols()); + if constexpr (Entity::ColsAtCompileTime == -1) + return extract(e, i0, 0, NI, e.cols()); + else return extract(e, i0, 0); } //======================== BOTTOM ROWS ======================== template auto bottomRows(Entity& e, Index ni) { - return extract(e, e.rows() - ni, 0, ni, e.cols()); + if constexpr (Entity::ColsAtCompileTime == -1) + return extract(e, e.rows() - ni, 0, ni, e.cols()); + else + return extract<-1, Entity::ColsAtCompileTime>(e, e.rows() - ni, 0, ni, + e.cols()); } template auto bottomRows(Entity& e) { - return extract(e, e.rows() - NI, 0, NI, e.cols()); + if constexpr (Entity::ColsAtCompileTime == -1) + return extract(e, e.rows() - NI, 0, NI, e.cols()); + else return extract(e, e.rows() - NI, 0); } //======================== LEFT COLS ======================== template auto leftCols(Entity& e, Index nj) { - return extract(e, 0, 0, e.rows(), nj); + if constexpr (Entity::RowsAtCompileTime == -1) + return extract(e, 0, 0, e.rows(), nj); + else return extract(e, 0, 0, e.rows(), nj); } template auto leftCols(Entity& e) { - return extract<-1, NJ>(e, 0, 0, e.rows(), NJ); + if constexpr (Entity::RowsAtCompileTime == -1) + return extract<-1, NJ>(e, 0, 0, e.rows(), NJ); + else return extract(e, 0, 0); } //======================== MIDDLE COLS ======================== template auto middleCols(Entity& e, Index j0, Index nj) { - return extract(e, 0, j0, e.rows(), nj); + if constexpr (Entity::RowsAtCompileTime == -1) + return extract(e, 0, j0, e.rows(), nj); + else return extract(e, 0, j0, e.rows(), nj); } template auto middleCols(Entity& e, Index j0) { - return extract<-1, NJ>(e, 0, j0, e.rows(), NJ); + if constexpr (Entity::RowsAtCompileTime == -1) + return extract<-1, NJ>(e, 0, j0, e.rows(), NJ); + else return extract(e, 0, j0); } //======================== RIGHT COLS ======================== template auto rightCols(Entity& e, Index nj) { - return extract(e, 0, e.cols() - nj, e.rows(), nj); + if constexpr (Entity::RowsAtCompileTime == -1) + return extract(e, 0, e.cols() - nj, e.rows(), nj); + else + return extract(e, 0, e.cols() - nj, + e.rows(), nj); + ; } template auto rightCols(Entity& e) { - return extract<-1, NJ>(e, 0, e.cols() - NJ, e.rows(), NJ); + if constexpr (Entity::RowsAtCompileTime == -1) + return extract<-1, NJ>(e, 0, e.cols() - NJ, e.rows(), NJ); + else return extract(e, 0, e.cols() - NJ); } //======================== ROW ======================== template auto row(Entity& e, Index i0) { - return extract<1, -1>(e, i0, 0, 1, e.cols()); + if constexpr (Entity::ColsAtCompileTime == -1) + return extract<1, -1>(e, i0, 0, 1, e.cols()); + else return extract<1, Entity::ColsAtCompileTime>(e, i0, 0); } //======================== COL ======================== template auto col(Entity& e, Index j0) { - return extract<-1, 1>(e, 0, j0, e.rows(), 1); + if constexpr (Entity::RowsAtCompileTime == -1) + return extract<-1, 1>(e, 0, j0, e.rows(), 1); + else return extract(e, 0, j0); } //======================== VECTOR HEAD ======================== diff --git a/include/rotgen/functions/functions.hpp b/include/rotgen/functions/functions.hpp index c48cb59..6ec88d4 100644 --- a/include/rotgen/functions/functions.hpp +++ b/include/rotgen/functions/functions.hpp @@ -322,149 +322,6 @@ namespace rotgen return std::forward(t).eval(); } - //----------------------------------------------------------------------------------------------- - // Generators - //----------------------------------------------------------------------------------------------- - template - auto setZero(T&& t) - requires(requires { std::forward(t).setZero(); }) - { - return std::forward(t).setZero(); - } - - template - auto setZero() - requires(requires { T::Zero(); }) - { - return T::Zero(); - } - - template - auto setZero(std::integral auto n) - requires(requires { T::Zero(n); }) - { - return T::Zero(n); - } - - template - auto setZero(std::integral auto r, std::integral auto c) - requires(requires { T::Zero(r, c); }) - { - return T::Zero(r, c); - } - - template - auto setOnes(T&& t) - requires(requires { std::forward(t).setOnes(); }) - { - return std::forward(t).setOnes(); - } - - template - auto setOnes() - requires(requires { T::Ones(); }) - { - return T::Ones(); - } - - template - auto setOnes(std::integral auto n) - requires(requires { T::Ones(n); }) - { - return T::Ones(n); - } - - template - auto setOnes(std::integral auto r, std::integral auto c) - requires(requires { T::Ones(r, c); }) - { - return T::Ones(r, c); - } - - template - auto setIdentity(T&& t) - requires(requires { std::forward(t).setIdentity(); }) - { - return std::forward(t).setIdentity(); - } - - template - auto setIdentity() - requires(requires { T::Identity(); }) - { - return T::Identity(); - } - - template - auto setIdentity(std::integral auto n) - requires(requires { T::Identity(n); }) - { - return T::Identity(n); - } - - template - auto setIdentity(std::integral auto r, std::integral auto c) - requires(requires { T::Identity(r, c); }) - { - return T::Identity(r, c); - } - - template - auto setRandom(T&& t) - requires(requires { std::forward(t).setRandom(); }) - { - return std::forward(t).setRandom(); - } - - template - auto setRandom() - requires(requires { T::Random(); }) - { - return T::Random(); - } - - template - auto setRandom(std::integral auto n) - requires(requires { T::Random(n); }) - { - return T::Random(n); - } - - template - auto setRandom(std::integral auto r, std::integral auto c) - requires(requires { T::Random(r, c); }) - { - return T::Random(r, c); - } - - template - auto setConstant(T&& t, auto v) - requires(requires { std::forward(t).setConstant(v); }) - { - return std::forward(t).setConstant(v); - } - - template - auto setConstant(auto v) - requires(requires { T::Constant(v); }) - { - return T::Constant(v); - } - - template - auto setConstant(std::integral auto n, auto v) - requires(requires { T::Constant(n, v); }) - { - return T::Constant(n, v); - } - - template - auto setConstant(std::integral auto r, std::integral auto c, auto v) - requires(requires { T::Constant(r, c, v); }) - { - return T::Constant(r, c, v); - } - //----------------------------------------------------------------------------------------------- // Others // TODO: Adapt other functions ot behave as inverse and limit code in @@ -474,9 +331,7 @@ namespace rotgen { if constexpr (!use_expression_templates) return inverse(generalize_t(a)); - else if constexpr (requires { typename A::rotgen_tag; }) - return base_of(a).inverse(); - else return a.inverse(); + else return base_of(a).inverse(); } template L, concepts::vectorND<3> R> diff --git a/include/rotgen/functions/generators.hpp b/include/rotgen/functions/generators.hpp new file mode 100644 index 0000000..b91e2d1 --- /dev/null +++ b/include/rotgen/functions/generators.hpp @@ -0,0 +1,156 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include + +namespace rotgen +{ + //----------------------------------------------------------------------------------------------- + // Generators + //----------------------------------------------------------------------------------------------- + template + auto setZero(T&& t) + requires(requires { std::forward(t).setZero(); }) + { + return std::forward(t).setZero(); + } + + template + auto setZero() + requires(requires { T::Zero(); }) + { + return T::Zero(); + } + + template + auto setZero(std::integral auto n) + requires(requires { T::Zero(n); }) + { + return T::Zero(n); + } + + template + auto setZero(std::integral auto r, std::integral auto c) + requires(requires { T::Zero(r, c); }) + { + return T::Zero(r, c); + } + + template + auto setOnes(T&& t) + requires(requires { std::forward(t).setOnes(); }) + { + return std::forward(t).setOnes(); + } + + template + auto setOnes() + requires(requires { T::Ones(); }) + { + return T::Ones(); + } + + template + auto setOnes(std::integral auto n) + requires(requires { T::Ones(n); }) + { + return T::Ones(n); + } + + template + auto setOnes(std::integral auto r, std::integral auto c) + requires(requires { T::Ones(r, c); }) + { + return T::Ones(r, c); + } + + template + auto setIdentity(T&& t) + requires(requires { std::forward(t).setIdentity(); }) + { + return std::forward(t).setIdentity(); + } + + template + auto setIdentity() + requires(requires { T::Identity(); }) + { + return T::Identity(); + } + + template + auto setIdentity(std::integral auto n) + requires(requires { T::Identity(n); }) + { + return T::Identity(n); + } + + template + auto setIdentity(std::integral auto r, std::integral auto c) + requires(requires { T::Identity(r, c); }) + { + return T::Identity(r, c); + } + + template + auto setRandom(T&& t) + requires(requires { std::forward(t).setRandom(); }) + { + return std::forward(t).setRandom(); + } + + template + auto setRandom() + requires(requires { T::Random(); }) + { + return T::Random(); + } + + template + auto setRandom(std::integral auto n) + requires(requires { T::Random(n); }) + { + return T::Random(n); + } + + template + auto setRandom(std::integral auto r, std::integral auto c) + requires(requires { T::Random(r, c); }) + { + return T::Random(r, c); + } + + template + auto setConstant(T&& t, auto v) + requires(requires { std::forward(t).setConstant(v); }) + { + return std::forward(t).setConstant(v); + } + + template + auto setConstant(auto v) + requires(requires { T::Constant(v); }) + { + return T::Constant(v); + } + + template + auto setConstant(std::integral auto n, auto v) + requires(requires { T::Constant(n, v); }) + { + return T::Constant(n, v); + } + + template + auto setConstant(std::integral auto r, std::integral auto c, auto v) + requires(requires { T::Constant(r, c, v); }) + { + return T::Constant(r, c, v); + } +} diff --git a/src/block/generate.cpp b/src/block/generate.cpp index 7202234..3d3faf0 100644 --- a/src/block/generate.cpp +++ b/src/block/generate.cpp @@ -10,24 +10,28 @@ #define STORAGE_ORDER Eigen::ColMajor #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col) +#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) -#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) +#define TRANSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _col) #include "model.cpp" #undef CLASSNAME -#undef TRANSSOURCENAME +#undef TRANSNAME +#undef TRANSCLASSNAME #undef SOURCENAME #undef MAPNAME #undef STORAGE_ORDER #define STORAGE_ORDER Eigen::RowMajor #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row) +#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) -#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) +#define TRANSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _row) #include "model.cpp" #undef CLASSNAME -#undef TRANSSOURCENAME +#undef TRANSNAME +#undef TRANSCLASSNAME #undef SOURCENAME #undef MAPNAME #undef STORAGE_ORDER @@ -40,24 +44,28 @@ #define STORAGE_ORDER Eigen::ColMajor #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col) +#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) -#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) +#define TRANSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _col) #include "model.cpp" #undef CLASSNAME -#undef TRANSSOURCENAME +#undef TRANSNAME +#undef TRANSCLASSNAME #undef SOURCENAME #undef MAPNAME #undef STORAGE_ORDER #define STORAGE_ORDER Eigen::RowMajor #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row) +#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row) -#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) +#define TRANSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _row) #include "model.cpp" #undef CLASSNAME -#undef TRANSSOURCENAME +#undef TRANSNAME +#undef TRANSCLASSNAME #undef SOURCENAME #undef MAPNAME #undef STORAGE_ORDER diff --git a/src/block/impl.cpp b/src/block/impl.cpp index fe8f510..c184f53 100644 --- a/src/block/impl.cpp +++ b/src/block/impl.cpp @@ -5,9 +5,11 @@ SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== -#include #include + +#include #include + #include #include diff --git a/src/block/model.cpp b/src/block/model.cpp index 104c007..dc01f1d 100644 --- a/src/block/model.cpp +++ b/src/block/model.cpp @@ -12,80 +12,65 @@ */ //================================================================================================== -//================================================================================================== -// Internal payload -//================================================================================================== -struct CLASSNAME::payload -{ - using stride_type = Eigen::Stride; - using matrix_type = - Eigen::Matrix; - using matrix_block_type = Eigen::Block; - using matrix_storage_t = std::pair; - using map_type = Eigen::Map; - using map_block_type = Eigen::Block; - using map_storage_t = std::pair; - using data_type = std::variant; - - data_type data; - rotgen::Index abs_i0 = 0; // absolute start row in original matrix - rotgen::Index abs_j0 = 0; // absolute start col in original matrix - rotgen::Index rel_i0 = 0; // relative start row in original matrix - rotgen::Index rel_j0 = 0; // relative start col in original matrix - - template void apply(Func f) - { - std::visit([&](auto& blk) { return f(blk.first); }, data); - } - - template void apply(Func f) const - { - std::visit([&](auto const& blk) { return f(blk.first); }, data); - } - - payload(data_type const& o) : data(o) {} - - payload(SOURCENAME CONST& o, - rotgen::Index i0, - rotgen::Index j0, - rotgen::Index ni, - rotgen::Index nj) - : data( - matrix_storage_t{matrix_block_type{o.storage()->data, i0, j0, ni, nj}, - &o.storage()->data}), - abs_i0(i0), abs_j0(j0), rel_i0(i0), rel_j0(j0) - { - } - - payload(MAPNAME CONST& o, - rotgen::Index i0, - rotgen::Index j0, - rotgen::Index ni, - rotgen::Index nj) - : data(map_storage_t{map_block_type{o.storage()->data, i0, j0, ni, nj}, - &o.storage()->data}), - abs_i0(i0), abs_j0(j0), rel_i0(i0), rel_j0(j0) - { - } -}; - //================================================================================================== // Constructors & Special Members //================================================================================================== CLASSNAME::CLASSNAME( SOURCENAME CONST& r, Index i0, Index j0, Index ni, Index nj) - : storage_(std::make_unique(r, i0, j0, ni, nj)) + : storage_( + std::make_unique(r, i0, j0, ni, nj, matrix_t{}, source_t{})) +{ +} + +CLASSNAME::CLASSNAME(TRANSNAME CONST& r, Index i0, Index j0, Index ni, Index nj) + : storage_( + std::make_unique(r, i0, j0, ni, nj, matrix_t{}, trans_t{})) { } CLASSNAME::CLASSNAME(MAPNAME CONST& r, Index i0, Index j0, Index ni, Index nj) - : storage_(std::make_unique(r, i0, j0, ni, nj)) + : storage_(std::make_unique(r, i0, j0, ni, nj, map_t{}, source_t{})) { } // We're building a block from a block - So we have to dig around the internals -CLASSNAME::CLASSNAME(payload const& o, Index i0, Index j0, Index ni, Index nj) +CLASSNAME::CLASSNAME( + TRANSCLASSNAME CONST& p, Index i0, Index j0, Index ni, Index nj) { + auto const& o = *(p.storage()); + + // Compute absolute indices from the parent stored block + Index abs_i0 = 0; + Index abs_j0 = 0; + std::visit( + [&](auto const& blk) { + abs_i0 = blk.first.startRow() + i0; + abs_j0 = blk.first.startCol() + j0; + }, + o.data); + + // Build a payload::data_type that holds the child block using absolute + // indices + payload::data_type new_data = std::visit( + [&](T const& blk) -> payload::data_type { + auto& [parent_block, ref] = blk; + using block_type = typename T::first_type; + return T{block_type{*ref, abs_i0, abs_j0, ni, nj}, ref}; + }, + o.data); + + storage_ = std::make_unique(new_data); + storage_->abs_i0 = abs_i0; + storage_->abs_j0 = abs_j0; + storage_->rel_i0 = i0; + storage_->rel_j0 = j0; +} + +// We're building a block from a block - So we have to dig around the internals +CLASSNAME::CLASSNAME(CLASSNAME CONST& p, Index i0, Index j0, Index ni, Index nj) +{ + auto const& o = *(p.storage()); + // Compute absolute indices from the parent stored block Index abs_i0 = 0; Index abs_j0 = 0; @@ -495,50 +480,54 @@ CLASSNAME& CLASSNAME::operator/=(TYPE s) SOURCENAME CLASSNAME::add(CLASSNAME const& rhs) const { SOURCENAME result; - result.storage()->assign(std::visit( - [](auto const& lhs_blk, auto const& rhs_blk) { - return (lhs_blk.first + rhs_blk.first).eval(); + std::visit( + [&](auto const& lhs_blk, auto const& rhs_blk) { + result.storage()->assign((lhs_blk.first + rhs_blk.first).eval()); }, - storage_->data, rhs.storage_->data)); + storage_->data, rhs.storage_->data); return result; } SOURCENAME CLASSNAME::sub(CLASSNAME const& rhs) const { SOURCENAME result; - result.storage()->assign(std::visit( - [](auto const& lhs_blk, auto const& rhs_blk) { - return (lhs_blk.first - rhs_blk.first).eval(); + std::visit( + [&](auto const& lhs_blk, auto const& rhs_blk) { + result.storage()->assign((lhs_blk.first - rhs_blk.first).eval()); }, - storage_->data, rhs.storage_->data)); + storage_->data, rhs.storage_->data); return result; } SOURCENAME CLASSNAME::mul(CLASSNAME const& rhs) const { SOURCENAME result; - result.storage()->assign(std::visit( - [](auto const& lhs_blk, auto const& rhs_blk) { - return (lhs_blk.first * rhs_blk.first).eval(); + std::visit( + [&](auto const& lhs_blk, auto const& rhs_blk) { + result.storage()->assign((lhs_blk.first * rhs_blk.first).eval()); }, - storage_->data, rhs.storage_->data)); + storage_->data, rhs.storage_->data); return result; } SOURCENAME CLASSNAME::mul(TYPE s) const { SOURCENAME result; - result.storage()->assign( - std::visit([s](auto const& lhs_blk) { return (lhs_blk.first * s).eval(); }, - storage_->data)); + std::visit( + [&](auto const& lhs_blk) { + result.storage()->assign((lhs_blk.first * s).eval()); + }, + storage_->data); return result; } SOURCENAME CLASSNAME::div(TYPE s) const { SOURCENAME result; - result.storage()->assign( - std::visit([s](auto const& lhs_blk) { return (lhs_blk.first / s).eval(); }, - storage_->data)); + std::visit( + [&](auto const& lhs_blk) { + result.storage()->assign((lhs_blk.first / s).eval()); + }, + storage_->data); return result; } diff --git a/src/map/impl.cpp b/src/map/impl.cpp index 6061684..365f36e 100644 --- a/src/map/impl.cpp +++ b/src/map/impl.cpp @@ -5,9 +5,11 @@ SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== -#include #include + +#include #include + #include #include diff --git a/src/map/model.cpp b/src/map/model.cpp index 0dbe48a..1aefec6 100644 --- a/src/map/model.cpp +++ b/src/map/model.cpp @@ -19,12 +19,14 @@ //================================================================================================== // Constructors & Special Members //================================================================================================== +CLASSNAME::CLASSNAME() {} + CLASSNAME::CLASSNAME(TYPE CONST* ptr, Index r, Index c) : storage_(std::make_unique(ptr, r, c)) { } -CLASSNAME::CLASSNAME(TYPE CONST* ptr, Index r, Index c, stride s) +CLASSNAME::CLASSNAME(TYPE CONST* ptr, Index r, Index c, dynamic_stride s) : storage_(std::make_unique( ptr, r, c, payload::stride_type{s.outer(), s.inner()})) { diff --git a/src/matrix/impl.cpp b/src/matrix/impl.cpp index 5467e82..8899765 100644 --- a/src/matrix/impl.cpp +++ b/src/matrix/impl.cpp @@ -5,10 +5,11 @@ SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== -#include #include + +#include #include -#include + #include namespace rotgen diff --git a/src/matrix/model.cpp b/src/matrix/model.cpp index af29078..dcd0267 100644 --- a/src/matrix/model.cpp +++ b/src/matrix/model.cpp @@ -300,10 +300,37 @@ CLASSNAME& CLASSNAME::operator/=(TYPE s) return *this; } -//================================================================================================== -// Static functions -//================================================================================================== +//============================================================================== +// Generators functions +//============================================================================== +void CLASSNAME::setOnes(std::size_t rows, std::size_t cols) +{ + storage_->assign(payload::data_type::Ones(rows, cols).eval()); +} +void CLASSNAME::setZero(std::size_t rows, std::size_t cols) +{ + storage_->assign(payload::data_type::Zero(rows, cols).eval()); +} + +void CLASSNAME::setConstant(std::size_t rows, std::size_t cols, TYPE value) +{ + storage_->assign(payload::data_type::Constant(rows, cols, value).eval()); +} + +void CLASSNAME::setRandom(std::size_t rows, std::size_t cols) +{ + storage_->assign(payload::data_type::Random(rows, cols).eval()); +} + +void CLASSNAME::setIdentity(std::size_t rows, std::size_t cols) +{ + storage_->assign(payload::data_type::Identity(rows, cols).eval()); +} + +//============================================================================== +// Static functions +//============================================================================== CLASSNAME CLASSNAME::Ones(std::size_t rows, std::size_t cols) { CLASSNAME m; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3ae846d..ba0a2de 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -26,6 +26,7 @@ rotgen_glob_unit(QUIET PATTERN "unit/*.cpp" INTERFACE rotgen_test) rotgen_glob_unit(QUIET PATTERN "unit/matrix/*.cpp" INTERFACE rotgen_test) rotgen_glob_unit(QUIET PATTERN "unit/block/*.cpp" INTERFACE rotgen_test) rotgen_glob_unit(QUIET PATTERN "unit/map/*.cpp" INTERFACE rotgen_test) +rotgen_glob_unit(QUIET PATTERN "unit/meta/*.cpp" INTERFACE rotgen_test) rotgen_glob_unit(QUIET PATTERN "unit/functions/*.cpp" INTERFACE rotgen_test) ##====================================================================================================================== diff --git a/test/integration/extract.cpp b/test/integration/extract.cpp index cf54fe0..3e0a33f 100644 --- a/test/integration/extract.cpp +++ b/test/integration/extract.cpp @@ -5,12 +5,13 @@ SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== -#include "unit/tests.hpp" #include -TTS_CASE_TPL("Chains of extraction", - rotgen::tests::types)( - tts::type>) +#include "unit/tests.hpp" + +TTS_CASE_TPL("Chains of extraction", rotgen::tests::types) + +(tts::type>) { constexpr int N = 8; auto a = rotgen::matrix::Random(); @@ -44,6 +45,9 @@ TTS_CASE_TPL("Chains of extraction", setConstant(bbbb, 0.125); TTS_EQUAL(a(3, 3), 0.125); + + bool verbose = ::tts::arguments()[{"--verbose"}]; + if (verbose) std::cout << a << "\n\n"; }; auto ref_extract(rotgen::ref> m) @@ -66,9 +70,10 @@ TTS_CASE("Extraction of ref/ref const") for (rotgen::Index r = 0; r < 3; r++) for (rotgen::Index c = 0; c < 4; c++) TTS_EQUAL(m(r, c), 1.f); - auto sliced = ref_cextract(m); rotgen::extract(m, 3, 4, 4, 3) = rotgen::setConstant>(5); + auto sliced = ref_cextract(m); + for (rotgen::Index r = 0; r < 4; r++) for (rotgen::Index c = 0; c < 3; c++) TTS_EQUAL(sliced(r, c), 5.f); }; diff --git a/test/integration/outer_stride.cpp b/test/integration/outer_stride.cpp index ebd8c5a..67938c7 100644 --- a/test/integration/outer_stride.cpp +++ b/test/integration/outer_stride.cpp @@ -5,8 +5,9 @@ SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== -#include "unit/tests.hpp" #include + +#include "unit/tests.hpp" #include TTS_CASE_TPL("outer_stride<0> interactions", @@ -54,49 +55,3 @@ TTS_CASE_TPL("outer_stride<0> interactions", TTS_EQUAL(dp, sp); } }; - -void process_ref(rotgen::ref const>) {} - -void process_ref(rotgen::ref const>) {} - -void process_ref( - rotgen::ref< - rotgen:: - matrix const>) -{ -} - -void process_ref( - rotgen::ref< - rotgen:: - matrix const>) -{ -} - -TTS_CASE_TPL("Extraction of outer_stride blocks", - rotgen::tests::types)( - tts::type>) -{ - using mat_t = rotgen::matrix; - - if constexpr (O::value == rotgen::ColMajor) - { - T padded[] = {1, 2, 3, 4, 99, 5, 6, 7, 8, 99, 9, 10, 11, 12}; - rotgen::map> sp(&padded[0], 4, 3); - rotgen::map> dp(&padded[0], 4, 3, - rotgen::outer_stride(5)); - - TTS_EXPECT_COMPILES(sp, { process_ref(extract(sp, 0, 0, 3, 2)); }); - TTS_EXPECT_COMPILES(dp, { process_ref(extract(dp, 0, 0, 3, 2)); }); - } - else - { - T padded[] = {1, 2, 3, 99, 4, 5, 6, 99, 7, 8, 9, 99, 10, 11, 12}; - rotgen::map> sp(&padded[0], 4, 3); - rotgen::map> dp(&padded[0], 4, 3, - rotgen::outer_stride(4)); - - TTS_EXPECT_COMPILES(sp, { process_ref(extract(sp, 0, 0, 3, 2)); }); - TTS_EXPECT_COMPILES(dp, { process_ref(extract(dp, 0, 0, 3, 2)); }); - } -}; diff --git a/test/integration/ref_magic.cpp b/test/integration/ref_magic.cpp index 9ec210e..bb7809b 100644 --- a/test/integration/ref_magic.cpp +++ b/test/integration/ref_magic.cpp @@ -5,9 +5,10 @@ SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== -#include "unit/tests.hpp" #include +#include "unit/tests.hpp" + template @@ -63,3 +64,34 @@ TTS_CASE("Reference of reference check") TTS_EQUAL(v2[0], sum2); TTS_EQUAL(v3[0], sum3); }; + +int f(rotgen::ref>) +{ + return +2; +} + +template +int g(rotgen::ref>) +{ + return +1; +} + +template +int g(rotgen::ref>) +requires(N > 1) +{ + return -1; +} + +TTS_CASE("Reference overload on stroage order check") +{ + rotgen::matrix mat_dyn(1, 3); + rotgen::matrix mat_col(1, 3); + rotgen::matrix mat_row(1, 3); + + TTS_EQUAL(f(mat_dyn), +2); + + TTS_EQUAL(g<3>(mat_dyn), +1); + TTS_EQUAL(g<3>(mat_col), +1); + TTS_EQUAL(g<3>(mat_row), -1); +}; diff --git a/test/unit/block/extract.cpp b/test/unit/block/extract.cpp index e883a8f..3b61c5c 100644 --- a/test/unit/block/extract.cpp +++ b/test/unit/block/extract.cpp @@ -5,9 +5,10 @@ SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== -#include "unit/tests.hpp" #include +#include "unit/tests.hpp" + template void for_each_element(EigenType const& m, F&& f) { @@ -137,68 +138,81 @@ void test_dynamic_block_extraction( auto blocks = std::make_tuple( // --- CONST TESTS std::make_tuple(c_block_main, matrix_construct.i0, matrix_construct.j0, - matrix_construct.ni, matrix_construct.nj), + matrix_construct.ni, matrix_construct.nj, rotgen::Dynamic, + rotgen::Dynamic), std::make_tuple(c_block_top_left_corner, 0, 0, matrix_construct.ni, - matrix_construct.nj), + matrix_construct.nj, rotgen::Dynamic, rotgen::Dynamic), std::make_tuple(c_block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, matrix_construct.ni, - matrix_construct.nj), + matrix_construct.nj, rotgen::Dynamic, rotgen::Dynamic), std::make_tuple(c_block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, - matrix_construct.nj), + matrix_construct.nj, rotgen::Dynamic, rotgen::Dynamic), std::make_tuple(c_block_bottom_right_corner, matrix.rows() - matrix_construct.ni, matrix.cols() - matrix_construct.nj, matrix_construct.ni, - matrix_construct.nj), + matrix_construct.nj, rotgen::Dynamic, rotgen::Dynamic), - std::make_tuple(c_block_top_rows, 0, 0, matrix_construct.ni, matrix.cols()), + std::make_tuple(c_block_top_rows, 0, 0, matrix_construct.ni, matrix.cols(), + rotgen::Dynamic, MatrixType::ColsAtCompileTime), std::make_tuple(c_block_middle_rows, matrix_construct.i0, 0, - matrix_construct.ni, matrix.cols()), + matrix_construct.ni, matrix.cols(), rotgen::Dynamic, + MatrixType::ColsAtCompileTime), std::make_tuple(c_block_bottom_rows, matrix.rows() - matrix_construct.ni, 0, - matrix_construct.ni, matrix.cols()), - - std::make_tuple(c_block_left_cols, 0, 0, matrix.rows(), - matrix_construct.nj), + matrix_construct.ni, matrix.cols(), rotgen::Dynamic, + MatrixType::ColsAtCompileTime), + std::make_tuple(c_block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj, + MatrixType::RowsAtCompileTime, rotgen::Dynamic), std::make_tuple(c_block_middle_cols, 0, matrix_construct.j0, matrix.rows(), - matrix_construct.nj), + matrix_construct.nj, MatrixType::RowsAtCompileTime, + rotgen::Dynamic), std::make_tuple(c_block_right_cols, 0, matrix.cols() - matrix_construct.nj, - matrix.rows(), matrix_construct.nj), + matrix.rows(), matrix_construct.nj, + MatrixType::RowsAtCompileTime, rotgen::Dynamic), + // --- REGULAR TESTS std::make_tuple(block_main, matrix_construct.i0, matrix_construct.j0, - matrix_construct.ni, matrix_construct.nj), + matrix_construct.ni, matrix_construct.nj, rotgen::Dynamic, + rotgen::Dynamic), std::make_tuple(block_top_left_corner, 0, 0, matrix_construct.ni, - matrix_construct.nj), + matrix_construct.nj, rotgen::Dynamic, rotgen::Dynamic), std::make_tuple(block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, matrix_construct.ni, - matrix_construct.nj), + matrix_construct.nj, rotgen::Dynamic, rotgen::Dynamic), std::make_tuple(block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, - matrix_construct.nj), + matrix_construct.nj, rotgen::Dynamic, rotgen::Dynamic), std::make_tuple(block_bottom_right_corner, matrix.rows() - matrix_construct.ni, matrix.cols() - matrix_construct.nj, matrix_construct.ni, - matrix_construct.nj), + matrix_construct.nj, rotgen::Dynamic, rotgen::Dynamic), - std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols()), + std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols(), + rotgen::Dynamic, MatrixType::ColsAtCompileTime), std::make_tuple(block_middle_rows, matrix_construct.i0, 0, - matrix_construct.ni, matrix.cols()), + matrix_construct.ni, matrix.cols(), rotgen::Dynamic, + MatrixType::ColsAtCompileTime), 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), + matrix_construct.ni, matrix.cols(), rotgen::Dynamic, + MatrixType::ColsAtCompileTime), + std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj, + MatrixType::RowsAtCompileTime, rotgen::Dynamic), std::make_tuple(block_middle_cols, 0, matrix_construct.j0, matrix.rows(), - matrix_construct.nj), + matrix_construct.nj, MatrixType::RowsAtCompileTime, + rotgen::Dynamic), std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj, - matrix.rows(), matrix_construct.nj)); + matrix.rows(), matrix_construct.nj, + MatrixType::RowsAtCompileTime, rotgen::Dynamic)); std::apply( [&](auto&&... block_entries) { (([&] { - auto&& [block, i_offset, j_offset, ni, nj] = block_entries; + auto&& [block, i_offset, j_offset, ni, nj, rows_ct, cols_ct] = + 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::RowsAtCompileTime, rows_ct); + TTS_EQUAL(block_t::ColsAtCompileTime, cols_ct); TTS_EQUAL(block_t::storage_order, MatrixType::storage_order); validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj); @@ -346,7 +360,7 @@ TTS_CASE_TPL( rotgen::tests::types)(tts::type>) { using mat_t = - rotgen::matrix; + rotgen::matrix; std::vector> cases = { {{6, 11, [](rotgen::Index i, rotgen::Index j) { return T(i * 10 + j); }}, @@ -381,7 +395,7 @@ TTS_CASE_TPL( "Check all dynamic block extractions on a static column-major matrix", rotgen::tests::types)(tts::type>) { - using mat_t = rotgen::matrix; + using mat_t = rotgen::matrix; std::vector> cases = { {{4, 5, [](auto i, auto j) { return T(2 * i + j * j * j - 42); }}, @@ -447,7 +461,7 @@ TTS_CASE_TPL("Check vector-only extractions", if constexpr (O::value == rotgen::RowMajor) { - using mat_t = rotgen::matrix; + using mat_t = rotgen::matrix; mat_t m(1, 11); for (rotgen::Index i = 0; i < 11; ++i) m(i) = 1 + i; @@ -473,7 +487,7 @@ TTS_CASE_TPL("Check vector-only extractions", } else { - using mat_t = rotgen::matrix; + using mat_t = rotgen::matrix; mat_t m(11, 1); for (rotgen::Index i = 0; i < 11; ++i) m(i) = 1 + i; diff --git a/test/unit/map/strides.cpp b/test/unit/map/strides.cpp index 01259b7..e0bf50a 100644 --- a/test/unit/map/strides.cpp +++ b/test/unit/map/strides.cpp @@ -5,10 +5,11 @@ SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== -#include "unit/tests.hpp" #include -#include + +#include "unit/tests.hpp" #include +#include auto generate_data(int rows, int cols) { @@ -26,7 +27,7 @@ using r_mat_t = rotgen::matrix; template using e_mat_t = Eigen::Matrix; -template +template> using r_map_t = rotgen::map; template> using e_map_t = Eigen::Map; @@ -56,7 +57,7 @@ TTS_CASE("Validate Column Major Map with specific outer stride behavior") auto buffer = generate_data(rows, cols); r_map_t, rotgen::outer_stride<>> r_map( - buffer.data(), rows, cols, rotgen::outer_stride(rows + 1)); + buffer.data(), rows, cols, rotgen::outer_stride<>(rows + 1)); TTS_EQUAL(r_map.innerStride(), 1); TTS_EQUAL(r_map.outerStride(), 4); @@ -75,8 +76,8 @@ TTS_CASE("Validate Column Major Map with specific inner stride behavior") auto cols = 4; auto buffer = generate_data(rows, cols); - r_map_t> r_map(buffer.data(), rows, cols, - rotgen::stride(rows, 2)); + r_map_t, rotgen::dynamic_stride> r_map( + buffer.data(), rows, cols, rotgen::dynamic_stride(rows, 2)); TTS_EQUAL(r_map.innerStride(), 2); TTS_EQUAL(r_map.outerStride(), 3); @@ -116,7 +117,7 @@ TTS_CASE("Validate Row Major Map with specific outer stride behavior") auto buffer = generate_data(rows, cols); r_map_t, rotgen::outer_stride<>> r_map( - buffer.data(), rows, cols, rotgen::outer_stride(cols + 1)); + buffer.data(), rows, cols, rotgen::outer_stride<>(cols + 1)); TTS_EQUAL(r_map.innerStride(), 1); TTS_EQUAL(r_map.outerStride(), 5); @@ -135,8 +136,8 @@ TTS_CASE("Validate Row Major Map with specific inner stride behavior") auto cols = 4; auto buffer = generate_data(rows, cols); - r_map_t, rotgen::stride> r_map( - buffer.data(), rows, cols, rotgen::stride(2, cols)); + r_map_t, rotgen::dynamic_stride> r_map( + buffer.data(), rows, cols, rotgen::dynamic_stride(2, cols)); TTS_EQUAL(r_map.innerStride(), 4); TTS_EQUAL(r_map.outerStride(), 2); diff --git a/test/unit/matrix/constructors.cpp b/test/unit/matrix/constructors.cpp index 1318f5c..0471a2b 100644 --- a/test/unit/matrix/constructors.cpp +++ b/test/unit/matrix/constructors.cpp @@ -5,12 +5,13 @@ SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== -#include "unit/tests.hpp" #include -TTS_CASE_TPL("Default matrix dynamic constructor", - rotgen::tests::types)( - tts::type>) +#include "unit/tests.hpp" + +TTS_CASE_TPL("Default matrix dynamic constructor", rotgen::tests::types) + +(tts::type>) { rotgen::matrix matrix; @@ -18,9 +19,9 @@ TTS_CASE_TPL("Default matrix dynamic constructor", TTS_EQUAL(matrix.cols(), rotgen::Index{0}); }; -TTS_CASE_TPL("Default matrix static constructor", - rotgen::tests::types)( - tts::type>) +TTS_CASE_TPL("Default matrix static constructor", rotgen::tests::types) + +(tts::type>) { rotgen::matrix matrix; @@ -29,8 +30,9 @@ TTS_CASE_TPL("Default matrix static constructor", }; TTS_CASE_TPL("Dynamic matrix constructor with row and columns", - rotgen::tests::types)( - tts::type>) + rotgen::tests::types) + +(tts::type>) { rotgen::matrix matrix(10, 5); @@ -38,12 +40,12 @@ TTS_CASE_TPL("Dynamic matrix constructor with row and columns", TTS_EQUAL(matrix.cols(), rotgen::Index{5}); }; -TTS_CASE_TPL("Static matrix constructor with row and columns", - float, - double)(tts::type) +TTS_CASE_TPL("Static matrix constructor with row and columns", float, double) + +(tts::type) { - rotgen::matrix v2(6, 11); - rotgen::matrix w2(6, 11); + rotgen::matrix v2 = {6, 11}; + rotgen::matrix w2 = {6, 11}; TTS_EQUAL(v2(0), T{6}); TTS_EQUAL(v2(1), T{11}); @@ -51,8 +53,8 @@ TTS_CASE_TPL("Static matrix constructor with row and columns", TTS_EQUAL(w2(0), T{6}); TTS_EQUAL(w2(1), T{11}); - rotgen::matrix v3(6, 11, 125); - rotgen::matrix w3(6, 11, 125); + rotgen::matrix v3 = {6, 11, 125}; + rotgen::matrix w3 = {6, 11, 125}; TTS_EQUAL(v3(0), T{6}); TTS_EQUAL(v3(1), T{11}); @@ -64,8 +66,9 @@ TTS_CASE_TPL("Static matrix constructor with row and columns", }; TTS_CASE_TPL("Copy constructor produces identical but independent matrix", - rotgen::tests::types)( - tts::type>) + rotgen::tests::types) + +(tts::type>) { rotgen::matrix a(3, 3); @@ -88,9 +91,9 @@ TTS_CASE_TPL("Copy constructor produces identical but independent matrix", TTS_NOT_EQUAL(b(0, 0), a(0, 0)); }; -TTS_CASE_TPL("Copy constructor on default matrix", - rotgen::tests::types)( - tts::type>) +TTS_CASE_TPL("Copy constructor on default matrix", rotgen::tests::types) + +(tts::type>) { rotgen::matrix a; rotgen::matrix b = a; @@ -98,9 +101,9 @@ TTS_CASE_TPL("Copy constructor on default matrix", TTS_EQUAL(b.cols(), rotgen::Index{0}); }; -TTS_CASE_TPL("Copy constructor from const matrix", - rotgen::tests::types)( - tts::type>) +TTS_CASE_TPL("Copy constructor from const matrix", rotgen::tests::types) + +(tts::type>) { rotgen::matrix const a(2, 2); auto b = a; @@ -108,9 +111,9 @@ TTS_CASE_TPL("Copy constructor from const matrix", TTS_EQUAL(b.cols(), rotgen::Index{2}); }; -TTS_CASE_TPL("Copy constructor on static matrix", - rotgen::tests::types)( - tts::type>) +TTS_CASE_TPL("Copy constructor on static matrix", rotgen::tests::types) + +(tts::type>) { rotgen::matrix a; rotgen::matrix b = a; @@ -118,9 +121,9 @@ TTS_CASE_TPL("Copy constructor on static matrix", TTS_EQUAL(b.cols(), rotgen::Index{5}); }; -TTS_CASE_TPL("Copy constructor on static/dynamic matrix", - rotgen::tests::types)( - tts::type>) +TTS_CASE_TPL("Copy constructor on static/dynamic matrix", rotgen::tests::types) + +(tts::type>) { rotgen::matrix a; rotgen::matrix b = a; @@ -128,9 +131,9 @@ TTS_CASE_TPL("Copy constructor on static/dynamic matrix", TTS_EQUAL(b.cols(), 4); }; -TTS_CASE_TPL("Copy constructor on dynamic/static matrix", - rotgen::tests::types)( - tts::type>) +TTS_CASE_TPL("Copy constructor on dynamic/static matrix", rotgen::tests::types) + +(tts::type>) { rotgen::matrix a(5, 7); rotgen::matrix b = a; @@ -138,9 +141,9 @@ TTS_CASE_TPL("Copy constructor on dynamic/static matrix", TTS_EQUAL(b.cols(), 7); }; -TTS_CASE_TPL("Move constructor transfers contents", - rotgen::tests::types)( - tts::type>) +TTS_CASE_TPL("Move constructor transfers contents", rotgen::tests::types) + +(tts::type>) { rotgen::matrix a(3, 3); a(1, 1) = 7; @@ -155,9 +158,9 @@ TTS_CASE_TPL("Move constructor transfers contents", TTS_EXPECT(b.data() == ptr); }; -TTS_CASE_TPL("Move constructor from Rvalue", - rotgen::tests::types)( - tts::type>) +TTS_CASE_TPL("Move constructor from Rvalue", rotgen::tests::types) + +(tts::type>) { rotgen::matrix b = rotgen::matrix(2, 2); @@ -165,9 +168,9 @@ TTS_CASE_TPL("Move constructor from Rvalue", TTS_EQUAL(b.cols(), rotgen::Index{2}); }; -TTS_CASE_TPL("Constructor from Initializer list", - rotgen::tests::types)( - tts::type>) +TTS_CASE_TPL("Constructor from Initializer list", rotgen::tests::types) + +(tts::type>) { rotgen::matrix b1{3.5}; TTS_EQUAL(b1.rows(), rotgen::Index{1}); @@ -193,9 +196,9 @@ TTS_CASE_TPL("Constructor from Initializer list", TTS_EQUAL(b13(2), T(3.4)); }; -TTS_CASE_TPL("Constructor from Initializer list of rows", - rotgen::tests::types)( - tts::type>) +TTS_CASE_TPL("Constructor from Initializer list of rows", rotgen::tests::types) + +(tts::type>) { rotgen::matrix b1{{3.5}}; TTS_EQUAL(b1.rows(), rotgen::Index{1}); diff --git a/test/unit/matrix/inverse.cpp b/test/unit/matrix/inverse.cpp index adac60b..83bcf34 100644 --- a/test/unit/matrix/inverse.cpp +++ b/test/unit/matrix/inverse.cpp @@ -7,7 +7,6 @@ //================================================================================================== #include -#include "unit/common/arithmetic.hpp" #include "unit/tests.hpp" TTS_CASE_TPL("Test dynamic matrix inverse", @@ -17,52 +16,50 @@ TTS_CASE_TPL("Test dynamic matrix inverse", using mat_t = rotgen::matrix; auto eps = std::numeric_limits::epsilon(); - auto const cases = rotgen::tests::generate_matrix_references(); - for (auto const& [r, c, fn] : cases) + for (int n = 2; n < 15; n *= 1.5) { - if (r == c) - { - auto input = mat_t::Random(r, c); - auto inv = rotgen::inverse(input); + auto input = 10 * rotgen::setRandom(n, n); + auto inv = rotgen::inverse(input); - auto rec = input * inv; - auto id = mat_t::Identity(rotgen::rows(rec), rotgen::cols(rec)); - auto error = rec - id; + auto rec = input * inv; + auto id = mat_t::Identity(rotgen::rows(rec), rotgen::cols(rec)); + auto error = rec - id; - TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 64.) - << "Result:\n" - << rec << "\n" - << "Residuals:\n" - << error << "\n"; - } + TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 256.) + << "Result:\n" + << rec << "\n" + << "Residuals:\n" + << error << "\n"; } }; +template void check_static_inverse() +{ + using mat_t = rotgen::matrix; + auto eps = std::numeric_limits::epsilon(); + + auto input = rotgen::setRandom(); + auto inv = rotgen::inverse(input); + + auto rec = input * inv; + auto id = mat_t::Identity(rotgen::rows(rec), rotgen::cols(rec)); + auto error = rec - id; + + TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 256.) + << "Result:\n" + << rec << "\n" + << "Residuals:\n" + << error << "\n"; +} + TTS_CASE_TPL("Test static matrix inverse", rotgen::tests::types)( tts::type>) { - using mat_t = rotgen::matrix; - auto eps = std::numeric_limits::epsilon(); - auto const cases = rotgen::tests::generate_static_matrix_references(); - - auto process = [&](D const&) { - if constexpr (D::rows == D::cols) - { - auto input = rotgen::matrix::Random(); - auto inv = rotgen::inverse(input); - - auto rec = input * inv; - auto id = mat_t::Identity(rotgen::rows(rec), rotgen::cols(rec)); - auto error = rec - id; - - TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 64.) - << "Result:\n" - << rec << "\n" - << "Residuals:\n" - << error << "\n"; - } - }; - - std::apply([&](auto const&... d) { (process(d), ...); }, cases); + check_static_inverse(); + check_static_inverse(); + check_static_inverse(); + check_static_inverse(); + check_static_inverse(); + check_static_inverse(); }; diff --git a/test/unit/meta/properties.cpp b/test/unit/meta/properties.cpp new file mode 100644 index 0000000..8682536 --- /dev/null +++ b/test/unit/meta/properties.cpp @@ -0,0 +1,211 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include + +#include "unit/tests.hpp" +#include + +template void check_size_properties() +{ + TTS_CONSTEXPR_EQUAL(RType::RowsAtCompileTime, EType::RowsAtCompileTime) + << tts::typename_ << " vs " << tts::typename_ << "\n"; + TTS_CONSTEXPR_EQUAL(RType::ColsAtCompileTime, EType::ColsAtCompileTime) + << tts::typename_ << " vs " << tts::typename_ << "\n"; + TTS_CONSTEXPR_EQUAL(RType::MaxRowsAtCompileTime, EType::MaxRowsAtCompileTime) + << tts::typename_ << " vs " << tts::typename_ << "\n"; + TTS_CONSTEXPR_EQUAL(RType::MaxColsAtCompileTime, EType::MaxColsAtCompileTime) + << tts::typename_ << " vs " << tts::typename_ << "\n"; + TTS_CONSTEXPR_EQUAL(RType::IsVectorAtCompileTime, + EType::IsVectorAtCompileTime) + << tts::typename_ << " vs " << tts::typename_ << "\n"; + TTS_CONSTEXPR_EQUAL(RType::InnerStrideAtCompileTime, + EType::InnerStrideAtCompileTime) + << tts::typename_ << " vs " << tts::typename_ << "\n"; + TTS_CONSTEXPR_EQUAL(RType::OuterStrideAtCompileTime, + EType::OuterStrideAtCompileTime) + << tts::typename_ << " vs " << tts::typename_ << "\n"; +} + +TTS_CASE("Compile-Time informations conformance w/r to Eigen - matrix") +{ + using namespace rotgen; + using namespace Eigen; + + check_size_properties(); + check_size_properties, + Matrix>(); + check_size_properties, Matrix>(); + check_size_properties(); + check_size_properties, Matrix>(); + check_size_properties(); + check_size_properties, Matrix>(); + + // RowMajor / ColMajor + { + TTS_CONSTEXPR_EQUAL(matrixXf::IsRowMajor, MatrixXf::IsRowMajor); + TTS_CONSTEXPR_EQUAL((matrix::IsRowMajor), + (Matrix::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((matrix::IsRowMajor), + (Matrix::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((matrix::IsRowMajor), + (Matrix::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((matrix::IsRowMajor), + (Matrix::IsRowMajor)); + TTS_CONSTEXPR_EQUAL(row_vectorXf::IsRowMajor, RowVectorXf::IsRowMajor); + TTS_CONSTEXPR_EQUAL((matrix::IsRowMajor), + (Matrix::IsRowMajor)); + TTS_CONSTEXPR_EQUAL(vectorXf::IsRowMajor, VectorXf::IsRowMajor); + } +}; + +TTS_CASE("Compile-Time informations conformance w/r to Eigen - map") +{ + using namespace rotgen; + using namespace Eigen; + + check_size_properties, Map>(); + check_size_properties>, + Map>>(); + check_size_properties>, + Map>>(); + check_size_properties>, Map>>(); + check_size_properties, Map>(); + check_size_properties>, Map>>(); + check_size_properties, Map>(); + check_size_properties>, Map>>(); + + // Row/Col Major + { + TTS_CONSTEXPR_EQUAL((map::IsRowMajor), + (Map::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (map>::IsRowMajor), + (Map>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (map>::IsRowMajor), + (Map>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((map::IsRowMajor), + (Map::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((map::IsRowMajor), + (Map::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (map>::IsRowMajor), + (Map>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (map>::IsRowMajor), + (Map>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (map>::IsRowMajor), + (Map>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (map>::IsRowMajor), + (Map>::IsRowMajor)); + } +}; + +TTS_CASE("Compile-Time informations conformance w/r to Eigen - block") +{ + using namespace rotgen; + using namespace Eigen; + + check_size_properties, Block>(); + check_size_properties>, + Block>>(); + check_size_properties, Block>(); + check_size_properties, 3, 6>, + Block, 3, 6>>(); + check_size_properties, Block>(); + check_size_properties, 1, 6>, + Block, 1, 6>>(); + check_size_properties, Block>(); + check_size_properties, 7, 1>, + Block, 7, 1>>(); + + check_size_properties>, Block>>(); + check_size_properties>>, + Block>>>(); + check_size_properties, 3, 6>, + Block, 3, 6>>(); + check_size_properties>, 3, 6>, + Block>, 3, 6>>(); + check_size_properties, 1, 6>, + Block, 1, 6>>(); + check_size_properties>, 1, 6>, + Block>, 1, 6>>(); + check_size_properties, 7, 1>, + Block, 7, 1>>(); + check_size_properties>, 7, 1>, + Block>, 7, 1>>(); + + // Row/Col Major + { + TTS_CONSTEXPR_EQUAL((block::IsRowMajor), + (Block::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((block::IsRowMajor), + (Block::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((block::IsRowMajor), + (Block::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (block>::IsRowMajor), + (Block>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (block>::IsRowMajor), + (Block>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((block::IsRowMajor), + (Block::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((block::IsRowMajor), + (Block::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((block::IsRowMajor), + (Block::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((block::IsRowMajor), + (Block::IsRowMajor)); + } +}; + +TTS_CASE("Compile-Time informations conformance w/r to Eigen - ref") +{ + using namespace rotgen; + using namespace Eigen; + + check_size_properties, Ref>(); + check_size_properties>, + Ref>>(); + check_size_properties>, Ref>>(); + check_size_properties, Ref>(); + check_size_properties>, Ref>>(); + check_size_properties, Ref>(); + check_size_properties>, Ref>>(); + + // Row/Col Major + { + TTS_CONSTEXPR_EQUAL((ref::IsRowMajor), + (Ref::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (ref>::IsRowMajor), + (Ref>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (ref>::IsRowMajor), + (Ref>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((ref::IsRowMajor), + (Ref::IsRowMajor)); + TTS_CONSTEXPR_EQUAL((ref::IsRowMajor), + (Ref::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (ref>::IsRowMajor), + (Ref>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (ref>::IsRowMajor), + (Ref>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (ref>::IsRowMajor), + (Ref>::IsRowMajor)); + TTS_CONSTEXPR_EQUAL( + (ref>::IsRowMajor), + (Ref>::IsRowMajor)); + } +}; diff --git a/test/unit/meta/ref.cpp b/test/unit/meta/ref.cpp new file mode 100644 index 0000000..ed19e7c --- /dev/null +++ b/test/unit/meta/ref.cpp @@ -0,0 +1,193 @@ +//================================================================================================== +/* + ROTGEN - Runtime Overlay for Eigen + Copyright : CODE RECKONS + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include + +#include "unit/tests.hpp" + +using row_matrixXf = rotgen::matrix; + +template void check_acceptance(Generator f) +{ + auto in = f(); + rotgen::matrixXf data; + bool verbose = ::tts::arguments()[{"--verbose"}]; + + auto acceptor = [&](rotgen::ref v, auto ptr) { + // Check that ref is not a copy + TTS_EQUAL(v.data(), ptr); + + // Setup the data correctly + data.resize(v.rows(), v.cols()); + rotgen::setRandom(data); + + // Assign through the ref + v = data; + if (verbose) std::cout << "V:\n" << v << std::endl << std::endl; + }; + auto constant_acceptor = [&](rotgen::ref v) { + return minCoeff(v); + }; + + acceptor(in, in.data()); + data.resize(in.rows(), in.cols()); + + TTS_EQUAL(in, data); + TTS_EQUAL(constant_acceptor(in), minCoeff(data)) << in << "\n" + << data << "\n"; +} + +TTS_CASE_TPL("Assert ref construction rules - Vector cases", + rotgen::vectorXf, + rotgen::vector2f, + rotgen::row_vectorXf, + rotgen::row_vector2f) + +(::tts::type) +{ + TTS_WHEN("Call a function accepting a ref<" << ::tts::typename_ << "> ...") + { + rotgen::matrixXf mc(2, 1); + rotgen::vectorXf vc(2); + rotgen::matrixXf mr(1, 2); + row_matrixXf mrr(1, 2); + rotgen::row_vectorXf vr(2); + rotgen::vector2f vcf; + rotgen::row_vector2f vrf; + + TTS_AND_THEN("with a vector-like matrix") + { + check_acceptance([&]() { return mc; }); + check_acceptance([&]() { return vc; }); + check_acceptance([&]() { return mr; }); + check_acceptance([&]() { return mrr; }); + check_acceptance([&]() { return vr; }); + check_acceptance([&]() { return vcf; }); + check_acceptance([&]() { return vrf; }); + } + + TTS_AND_THEN("with a vector-like block") + { + check_acceptance([&]() { return rotgen::head(vc, 2); }); + check_acceptance([&]() { return rotgen::head(vr, 2); }); + check_acceptance([&]() { return rotgen::head(vcf, 2); }); + check_acceptance([&]() { return rotgen::head(vrf, 2); }); + + check_acceptance([&]() { return rotgen::head<2>(vc); }); + check_acceptance([&]() { return rotgen::head<2>(vr); }); + check_acceptance([&]() { return rotgen::head<2>(vcf); }); + check_acceptance([&]() { return rotgen::head<2>(vrf); }); + } + + TTS_AND_THEN("with a vector-like map") + { + rotgen::map mmc(vc.data(), 2, 1); + rotgen::map mmr(vc.data(), 1, 2); + rotgen::map mmrr(vc.data(), 1, 2); + rotgen::map mvc(vc.data(), vc.size()); + rotgen::map mvr(vr.data(), vr.size()); + rotgen::map mvcf(vc.data()); + rotgen::map mvrf(vr.data()); + + check_acceptance([&]() { return mmc; }); + check_acceptance([&]() { return mvc; }); + check_acceptance([&]() { return mvr; }); + check_acceptance([&]() { return mmr; }); + check_acceptance([&]() { return mmrr; }); + check_acceptance([&]() { return mvcf; }); + check_acceptance([&]() { return mvrf; }); + } + + TTS_AND_THEN("with a vector-like ref") + { + rotgen::ref mmrr(mrr); + rotgen::ref mvc(mc); + rotgen::ref mvr(mc); + rotgen::ref mvcf(mc); + rotgen::ref mvrf(mc); + + check_acceptance([&]() { return mvc; }); + check_acceptance([&]() { return mvr; }); + check_acceptance([&]() { return mmrr; }); + check_acceptance([&]() { return mvcf; }); + check_acceptance([&]() { return mvrf; }); + } + } +}; + +TTS_CASE("Assert ref construction rules Matrix cases") +{ + using MatC = rotgen::matrix; + using MatR = rotgen::matrix; + + TTS_WHEN("Call a function accepting a ref<" + << ::tts::typename_ << "> ...") + { + rotgen::matrixXf mc(2, 1); + rotgen::matrixXf mr(1, 2); + rotgen::matrixXf mn(4, 2); + row_matrixXf mnr(4, 2); + rotgen::matrix mcf(2, 1); + rotgen::matrix mrf(1, 2); + rotgen::matrix mnf(4, 2); + + TTS_AND_THEN("with a matrix") + { + check_acceptance([&]() { return mc; }); + check_acceptance([&]() { return mr; }); + check_acceptance([&]() { return mn; }); + check_acceptance([&]() { return mcf; }); + check_acceptance([&]() { return mrf; }); + check_acceptance([&]() { return mnf; }); + + TTS_EXPECT_COMPILES(mnr, { rotgen::ref{mnr}; }); + } + + TTS_AND_THEN("with a map") + { + rotgen::map mmc(mc.data(), 2, 1); + rotgen::map mmr(mc.data(), 1, 2); + rotgen::map mmrr(mc.data(), 1, 2); + rotgen::map mmnr(mnr.data(), 4, 2); + rotgen::map mvc(mc.data(), mc.size()); + rotgen::map mvr(mr.data(), mr.size()); + rotgen::map mvcf(mc.data()); + rotgen::map mvrf(mr.data()); + + check_acceptance([&]() { return mmc; }); + check_acceptance([&]() { return mmr; }); + check_acceptance([&]() { return mvc; }); + check_acceptance([&]() { return mvr; }); + check_acceptance([&]() { return mvcf; }); + check_acceptance([&]() { return mvrf; }); + + TTS_EXPECT_COMPILES(mmnr, { rotgen::ref{mmnr}; }); + TTS_EXPECT_COMPILES(mmrr, { rotgen::ref{mmrr}; }); + } + } + + TTS_WHEN("Call a function accepting a ref<" + << ::tts::typename_ << "> ...") + { + row_matrixXf mc(2, 1); + row_matrixXf mr(1, 2); + row_matrixXf mn(4, 2); + rotgen::matrix mcf(2, 1); + rotgen::matrix mrf(1, 2); + rotgen::matrix mnf(4, 2); + + TTS_AND_THEN("with a matrix") + { + check_acceptance([&]() { return mc; }); + check_acceptance([&]() { return mr; }); + check_acceptance([&]() { return mn; }); + check_acceptance([&]() { return mcf; }); + check_acceptance([&]() { return mrf; }); + check_acceptance([&]() { return mnf; }); + } + } +};