Fix a lot of ref issues reagrding extarction, rvalueness and proper use of temporary memory.

This commit is contained in:
Joel Falcou 2025-10-28 20:12:33 +01:00
parent d5c41bf43e
commit 379d77ebef
50 changed files with 2945 additions and 1397 deletions

View file

@ -261,4 +261,10 @@ QualifierOrder:
- inline
- static
- type
- const
- const
StatementMacros:
- TTS_CASE
- TTS_CASE_TPL
- TTS_CASE_WITH
- TTS_AND_THEN
- TTS_WHEN

View file

@ -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
)

View file

@ -15,6 +15,6 @@ namespace rotgen::solver
auto r_x = generalize_t<X>(x);
auto r_m = generalize_t<M const>(m);
auto r_rhs = generalize_t<RHS const>(rhs);
r_x = r_m.base().qr_solve(r_rhs.base());
r_x = r_m.qr_solve(r_rhs);
}
}

View file

@ -7,6 +7,9 @@
//==================================================================================================
#pragma once
#include <concepts>
#include <type_traits>
namespace rotgen::concepts
{
//================================================================================================

View file

@ -10,45 +10,68 @@
#include <rotgen/concepts.hpp>
#include <rotgen/container/block/dynamic/impl.hpp>
#include <rotgen/container/matrix/dynamic.hpp>
#include <initializer_list>
#include <cassert>
#include <initializer_list>
namespace rotgen
{
template<typename T, int Options = T::storage_order, typename Stride = stride>
template<typename T,
int Options = 0,
typename Stride = std::conditional_t<T::IsVectorAtCompileTime,
inner_stride<1>,
outer_stride<>>>
class ref;
template<typename Ref,
int Rows = Dynamic,
int Cols = Dynamic,
bool Inner = false>
class block : public find_block<Ref>
class block : public find_block<Ref, Rows, Cols>
{
public:
static_assert(concepts::entity<Ref>,
"[ROTGEN][CRITICAL] - Block of non-rotgen type instanciated");
using parent = find_block<Ref>;
using parent = find_block<Ref, Rows, Cols>;
using rotgen_tag = void;
using rotgen_block_tag = void;
using value_type = typename std::remove_const_t<Ref>::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<Ref>;
using concrete_type = matrix<value_type, Rows, Cols, storage_order>;
using transposed_type = matrix<value_type, Cols, Rows, storage_order>;
using concrete_dynamic_type =
matrix<value_type, Dynamic, Dynamic, storage_order>;
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();
}

View file

@ -8,10 +8,14 @@
#pragma once
#include <rotgen/detail/generators.hpp>
// clang-format off
#include <rotgen/container/matrix/dynamic.hpp>
#include <rotgen/container/map/dynamic.hpp>
#include <initializer_list>
// clang-format on
#include <cstddef>
#include <initializer_list>
#include <memory>
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<typename Ref>
template<typename Ref, int Rows, int Cols>
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<typename Ref, int Rows, int Cols>
using find_block =
typename find_block_impl<typename std::remove_const_t<Ref>::value_type,
Ref::storage_order,
block_storage_order<Ref, Rows, Cols>(),
std::is_const_v<Ref>>::type;
}

View file

@ -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 <rotgen/container/block/dynamic/model.hpp>
#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 <rotgen/container/block/dynamic/model.hpp>
#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 <rotgen/container/block/dynamic/model.hpp>
#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 <rotgen/container/block/dynamic/model.hpp>
#undef CLASSNAME
#undef TRANSSOURCENAME
#undef TRANSCLASSNAME
#undef TRANSNAME
#undef SOURCENAME
#undef MAPNAME

View file

@ -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;

View file

@ -8,12 +8,17 @@
#pragma once
#include <rotgen/container/strides.hpp>
#include <Eigen/Dense>
#include <iostream>
namespace rotgen
{
template<typename T, int Options = T::storage_order, typename Stride = stride>
template<typename T,
int Options = 0,
typename Stride = std::conditional_t<T::IsVectorAtCompileTime,
inner_stride<1>,
outer_stride<>>>
class ref;
namespace detail
@ -31,22 +36,6 @@ namespace rotgen
Eigen::Block<ref_t, Eigen::Dynamic, Eigen::Dynamic, Inner>>;
};
template<typename T,
int O,
typename S,
int Rows,
int Cols,
bool Inner,
bool IsConst>
struct compute_block_type<ref<T, O, S>, Rows, Cols, Inner, IsConst>
: compute_block_type<typename ref<T, O, S>::parent,
Rows,
Cols,
Inner,
IsConst>
{
};
template<typename Ref, int Rows, int Cols, bool Inner, bool IsConst>
using block_type =
typename compute_block_type<Ref, Rows, Cols, Inner, IsConst>::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<Ref>;
static constexpr bool IsRowMajor = parent::IsRowMajor;
using concrete_type = matrix<value_type, Rows, Cols, storage_order>;
using concrete_dynamic_type =
matrix<value_type, Dynamic, Dynamic, storage_order>;
template<typename ET>
using as_concrete_type = detail::as_concrete_t<ET, matrix>;
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<Rows, Cols, Rows, Cols>;
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<Ref>;
using concrete_type = matrix<value_type, Rows, Cols, storage_order>;
using concrete_dynamic_type =
matrix<value_type, Dynamic, Dynamic, storage_order>;
public:
block(block const& other) = default;
block(block&& other) = default;

View file

@ -7,16 +7,25 @@
//==================================================================================================
#pragma once
#include <rotgen/detail/helpers.hpp>
#include <rotgen/concepts.hpp>
#include <rotgen/container/map/dynamic/impl.hpp>
#include <rotgen/detail/helpers.hpp>
#include <cassert>
namespace rotgen
{
namespace detail
{
struct postpone
{
};
}
template<typename Ref,
int Options = Unaligned,
typename Stride = rotgen::stride>
typename Stride = rotgen::stride<0, 0>>
class map : public find_map<Ref>
{
public:
@ -33,7 +42,6 @@ namespace rotgen
static constexpr bool has_static_storage = false;
static constexpr bool is_immutable = std::is_const_v<Ref>;
static constexpr bool is_defined_static = false;
using ptr_type =
std::conditional_t<is_immutable, value_type const*, value_type*>;
@ -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<value_type, ColsAtCompileTime, RowsAtCompileTime, storage_order>;
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<storage_order>(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<stride_type, dynamic_stride>)
: map(ptr, r, c, strides<storage_order>(s, r, c))
{
}
map(ptr_type ptr, Index r, Index c)
: parent(ptr, r, c, [&]() {
if constexpr (!std::same_as<Stride, stride>)
if constexpr (!std::same_as<Stride, stride<0, 0>>)
return strides<storage_order>(Stride{}, r, c);
else return strides<storage_order>(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<storage_order>(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); })
{

View file

@ -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;

View file

@ -14,7 +14,8 @@ namespace rotgen
{
namespace detail
{
template<typename Ref, int Options, bool isConst> struct compute_map_type
template<typename Ref, int Options, bool isConst, typename Stride>
struct compute_map_type
{
using base = Eigen::Matrix<typename Ref::value_type,
Ref::RowsAtCompileTime,
@ -22,22 +23,26 @@ namespace rotgen
Ref::storage_order>;
using ref_t = std::conditional_t<isConst, base const, base>;
using type = Eigen::Map<ref_t, Options, Eigen::Stride<-1, -1>>;
using type = Eigen::Map<ref_t, Options, Stride>;
};
template<typename Ref, int Options, bool isConst>
using map_type = typename compute_map_type<Ref, Options, isConst>::type;
template<typename Ref, int Options, bool isConst, typename Stride>
using map_type =
typename compute_map_type<Ref, Options, isConst, Stride>::type;
}
template<typename Ref, int Options = Unaligned, typename Stride = stride>
template<typename Ref,
int Options = Unaligned,
typename Stride = rotgen::stride<0, 0>>
class map : private detail::map_type<std::remove_const_t<Ref>,
Options,
std::is_const_v<Ref>>
std::is_const_v<Ref>,
Stride>
{
public:
using rotgen_tag = void;
using parent =
detail::map_type<std::remove_const_t<Ref>, Options, std::is_const_v<Ref>>;
using parent = detail::
map_type<std::remove_const_t<Ref>, Options, std::is_const_v<Ref>, Stride>;
using value_type = typename std::remove_const_t<Ref>::value_type;
using concrete_type = typename std::remove_const_t<Ref>::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<Ref>;
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<typename ET>
using as_concrete_type = detail::as_concrete_t<ET, matrix>;
@ -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<storage_order>(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<Stride, stride>)
return strides<storage_order>(Stride{}, r, c);
else return strides<storage_order>(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<storage_order>(s, RowsAtCompileTime, ColsAtCompileTime))
: parent(ptr, s)
{
}
@ -115,6 +122,12 @@ namespace rotgen
return as_concrete_type<decltype(res)>(res);
}
auto evaluate()
{
auto res = static_cast<parent&>(*this).eval();
return as_concrete_type<decltype(res)>(res);
}
decltype(auto) noalias() const
{
if constexpr (use_expression_templates) return base().noalias();

View file

@ -7,10 +7,13 @@
//==================================================================================================
#pragma once
#include <rotgen/container/matrix/dynamic/impl.hpp>
#include <rotgen/detail/helpers.hpp>
#include <rotgen/concepts.hpp>
#include <initializer_list>
#include <rotgen/container/matrix/dynamic/impl.hpp>
#include <cassert>
#include <initializer_list>
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<matrix>();
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<value_type, Cols, Rows, storage_order>;
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<Scalar>(value));
parent::setConstant(parent::rows(), parent::cols(),
static_cast<Scalar>(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<Scalar>(value));
parent::setConstant(rows, cols, static_cast<Scalar>(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;
}

View file

@ -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<payload> storage_;

View file

@ -8,6 +8,7 @@
#pragma once
#include <rotgen/detail/helpers.hpp>
#include <Eigen/Dense>
#include <iostream>
@ -49,13 +50,21 @@ namespace rotgen
static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols;
static constexpr int SizeAtCompileTime = detail::static_size<matrix>();
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<typename ET>
using as_concrete_type = detail::as_concrete_t<ET, matrix>;
@ -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<Scalar> init)
matrix(std::initializer_list<Scalar> 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<parent&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }

View file

@ -7,501 +7,13 @@
//==================================================================================================
#pragma once
#include <cassert>
#include <type_traits>
#include <rotgen/config.hpp>
#if !defined(ROTGEN_FORCE_DYNAMIC)
#include <Eigen/Dense>
#if defined(ROTGEN_FORCE_DYNAMIC)
#include <rotgen/container/ref/dynamic.hpp>
#else
#include <rotgen/container/ref/fixed.hpp>
#endif
namespace rotgen
{
// Primary template: mutable ref
template<typename T, int Options, typename Stride>
class ref : private map<T, Options, Stride>
{
public:
using parent = map<T, Options, Stride>;
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<parent const&>(*this); }
parent& base() { return static_cast<parent&>(*this); }
template<std::same_as<value_type> S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC>& m)
: parent(m.data(), m.rows(), m.cols(), strides(m))
{
}
template<typename Ref, int R, int C, bool I>
requires(std::same_as<value_type, typename Ref::value_type> &&
(Ref::storage_order & 1) == storage_order)
ref(block<Ref, R, C, I>&& b)
: parent(b.data(),
b.rows(),
b.cols(),
stride_type{b.outerStride(), b.innerStride()})
{
}
template<typename Ref, int R, int C, bool I>
requires(std::same_as<value_type, typename Ref::value_type> &&
(Ref::storage_order & 1) == storage_order)
ref(block<Ref, R, C, I>& b)
: parent(b.data(),
b.rows(),
b.cols(),
stride_type{b.outerStride(), b.innerStride()})
{
}
template<typename Ref, int O, typename S>
requires(std::same_as<value_type, typename Ref::value_type> &&
(Ref::storage_order & 1) == storage_order)
ref(map<Ref, O, S>& b)
: parent(b.data(),
b.rows(),
b.cols(),
stride_type{b.outerStride(), b.innerStride()})
{
}
template<typename TT, int OO, typename SS>
ref(ref<TT, OO, SS>& b)
requires(std::same_as<value_type, typename TT::value_type> &&
(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<ref> const& r)
{
return os << format{r.matrix_.base(), r.format_};
}
};
// Specialization for const matrix type
template<typename T, int Options, typename Stride>
class ref<T const, Options, Stride> : private map<T const, Options, Stride>
{
public:
using parent = map<T const, Options, Stride>;
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<parent const&>(*this); }
template<std::same_as<value_type> S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC> const& m)
: parent(m.data(), m.rows(), m.cols(), strides(m))
{
}
template<typename Ref, int R, int C, bool I>
ref(block<Ref, R, C, I> const& b)
requires(std::same_as<value_type, typename Ref::value_type> &&
(Ref::storage_order & 1) == storage_order)
: parent(b.data(),
b.rows(),
b.cols(),
stride_type{b.outerStride(), b.innerStride()})
{
}
template<typename Ref, int O, typename S>
ref(map<Ref, O, S> const& b)
requires(std::same_as<value_type, typename Ref::value_type> &&
(Ref::storage_order & 1) == storage_order)
: parent(b.data(),
b.rows(),
b.cols(),
stride_type{b.outerStride(), b.innerStride()})
{
}
template<typename TT, int OO, typename SS>
ref(ref<TT, OO, SS> const& b)
requires(std::same_as<value_type, typename TT::value_type> &&
(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<ref> const& r)
{
return os << format{r.matrix_.base(), r.format_};
}
};
template<typename S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC>&) -> ref<matrix<S>>;
template<typename Ref, int R, int C, bool I>
ref(block<Ref, R, C, I>& b) -> ref<Ref>;
template<typename S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC> const&) -> ref<matrix<S> const>;
template<typename Ref, int R, int C, bool I>
ref(block<Ref, R, C, I> const& b) -> ref<Ref const>;
template<typename A, int O, typename S, typename B, int P, typename T>
bool operator==(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return lhs.base() == rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
bool operator!=(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return lhs.base() != rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator+(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base() + rhs.base())
{
return lhs.base() + rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator+=(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base() += rhs.base())
{
return lhs.base() += rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator-(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return lhs.base() - rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator-=(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base() -= rhs.base())
{
return lhs.base() -= rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator*(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return lhs.base() * rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator*=(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base() *= rhs.base())
{
return lhs.base() *= rhs.base();
}
template<typename A, int O, typename S>
auto operator*(ref<A, O, S> lhs,
std::convertible_to<typename A::value_type> auto s)
{
return lhs.base() * s;
}
template<typename A, int O, typename S>
auto operator*(std::convertible_to<typename A::value_type> auto s,
ref<A, O, S> rhs)
{
return s * rhs.base();
}
template<typename A, int O, typename S>
auto operator/(ref<A, O, S> lhs,
std::convertible_to<typename A::value_type> auto s)
{
return lhs.base() / s;
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto dot(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return lhs.base().dot(rhs.base());
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto min(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseMin(rhs.base()))
{
return lhs.base().cwiseMin(rhs.base());
}
template<typename A, int O, typename S>
auto min(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
-> decltype(lhs.base().cwiseMin(s))
{
return lhs.base().cwiseMin(s);
}
template<typename A, int O, typename S>
auto min(std::convertible_to<typename A::value_type> auto s, ref<A, O, S> rhs)
-> decltype(rhs.base().cwiseMin(s))
{
return rhs.base().cwiseMin(s);
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto max(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseMax(rhs.base()))
{
return lhs.base().cwiseMax(rhs.base());
}
template<typename A, int O, typename S>
auto max(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
-> decltype(lhs.base().cwiseMax(s))
{
return lhs.base().cwiseMax(s);
}
template<typename A, int O, typename S>
auto max(std::convertible_to<typename A::value_type> auto s, ref<A, O, S> rhs)
-> decltype(rhs.base().cwiseMax(s))
{
return rhs.base().cwiseMax(s);
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto mul(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseProduct(rhs.base()))
{
return lhs.base().cwiseProduct(rhs.base());
}
template<typename A, int O, typename S>
auto mul(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
-> decltype(lhs * s)
{
return lhs * s;
}
template<typename A, int O, typename S>
auto mul(std::convertible_to<typename A::value_type> auto s, ref<A, O, S> rhs)
-> decltype(s * rhs)
{
return s * rhs;
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto div(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseQuotient(rhs.base()))
{
return lhs.base().cwiseQuotient(rhs.base());
}
template<typename A, int O, typename S>
auto div(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
-> decltype(lhs / s)
{
return lhs / s;
}
template<typename A, int O, typename S>
auto inverse(ref<A, O, S> lhs) -> decltype(lhs.base().inverse())
{
return lhs.base().inverse();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto cross(ref<A, O, S> lhs, ref<B, P, T> 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<typename T> struct generalize;
template<typename T>
requires(std::is_arithmetic_v<std::remove_cvref_t<T>>)
struct generalize<T>
{
using type = std::remove_cvref_t<T>;
};
template<typename T> using generalize_t = typename generalize<T>::type;
template<concepts::entity T> struct generalize<T>
{
static constexpr bool is_const = std::is_const_v<T>;
using base = matrix<typename T::value_type,
T::RowsAtCompileTime,
T::ColsAtCompileTime,
T::storage_order>;
using type = std::conditional_t<is_const, ref<base const>, ref<base>>;
};
template<typename T, int O, typename S> struct generalize<ref<T, O, S>>
{
using type = ref<T, O, S>;
};
template<typename T, int O, typename S> struct generalize<ref<T, O, S> const>
{
using type = ref<T, O, S>;
};
template<concepts::entity T> typename T::parent& base_of(T& a)
{
return a.base();
}
template<concepts::entity T> typename T::parent const& base_of(T const& a)
{
return a.base();
}
template<typename T>
T base_of(T a)
requires(std::is_arithmetic_v<T>)
{
return a;
}
#if !defined(ROTGEN_FORCE_DYNAMIC)
template<concepts::eigen_compatible T> struct generalize<T>
{
static constexpr bool is_const = std::is_const_v<T>;
using concrete_type = decltype(std::declval<T>().eval());
using base = matrix<typename T::Scalar,
T::RowsAtCompileTime,
T::ColsAtCompileTime,
concrete_type::Options & 1>;
using type = std::conditional_t<is_const, ref<base const>, ref<base>>;
};
template<concepts::eigen_compatible T> auto const& base_of(T const& a)
{
return a;
}
template<concepts::eigen_compatible T> auto& base_of(T& a)
{
return a;
}
#endif
}
#include <rotgen/container/ref/functions.hpp>
#include <rotgen/container/ref/generalize.hpp>

View file

@ -0,0 +1,353 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <cassert>
#include <type_traits>
#if !defined(ROTGEN_FORCE_DYNAMIC)
#include <Eigen/Dense>
#endif
#include <rotgen/detail/accept_as_ref.hpp>
namespace rotgen
{
template<typename T, int Options, typename Stride>
class ref : private map<T, Options, Stride>
{
public:
using parent = map<T, Options, Stride>;
using referee = std::remove_const_t<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<T>;
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<typename RO, int OO, typename SO>
auto qr_solve(ref<RO, OO, SO> rhs) const
{
return parent::qr_solve(rhs.base());
};
using stride_type = typename parent::stride_type;
parent const& base() const { return static_cast<parent const&>(*this); }
parent& base() { return static_cast<parent&>(*this); }
parent const& as_map() const { return base(); }
parent& as_map() { return base(); }
template<typename S, int R, int C, int O, int MR, int MC>
requires(detail::accept_as_ref<ref, matrix<S, R, C, O, MR, MC>>)
ref(matrix<S, R, C, O, MR, MC>& m) : parent(detail::postpone{})
{
[[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, m);
assert(correct_ref_setup);
}
template<typename S, int R, int C, int O, int MR, int MC>
requires(is_immutable &&
detail::same_scalar<ref, matrix<S, R, C, O, MR, MC>> &&
(detail::accept_as_ref<ref, matrix<S, R, C, O, MR, MC>> ||
may_map_object))
ref(matrix<S, R, C, O, MR, MC> const& m) : parent(detail::postpone{})
{
if (!detail::validate_ref(*this, m))
{
potential_local_copy = m;
detail::validate_ref(*this, potential_local_copy);
}
}
template<typename Ref, int R, int C, bool I>
requires(detail::accept_as_ref<ref, block<Ref, R, C, I>>)
ref(block<Ref, R, C, I>&& b) : parent(detail::postpone{})
{
[[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, b);
assert(correct_ref_setup);
}
template<typename Ref, int R, int C, bool I>
requires(detail::accept_as_ref<ref, block<Ref, R, C, I>>)
ref(block<Ref, R, C, I>& b) : parent(detail::postpone{})
{
[[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, b);
assert(correct_ref_setup);
}
template<typename Ref, int R, int C, bool I>
requires(is_immutable && detail::same_scalar<ref, block<Ref, R, C, I>> &&
(detail::accept_as_ref<ref, block<Ref, R, C, I>> ||
may_map_object))
ref(block<Ref, R, C, I> const& b) : parent(detail::postpone{})
{
if (!detail::validate_ref(*this, b))
{
potential_local_copy = b;
detail::validate_ref(*this, potential_local_copy);
}
}
template<typename Ref, int O, typename S>
requires(detail::accept_as_ref<ref, map<Ref, O, S>>)
ref(map<Ref, O, S>& b) : parent(detail::postpone{})
{
[[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, b);
assert(correct_ref_setup);
}
template<typename Ref, int O, typename S>
requires(is_immutable && detail::same_scalar<ref, map<Ref, O, S>> &&
(detail::accept_as_ref<ref, map<Ref, O, S>> || may_map_object))
ref(map<Ref, O, S> const& b) : parent(detail::postpone{})
{
if (!detail::validate_ref(*this, b))
{
potential_local_copy = b;
detail::validate_ref(*this, potential_local_copy);
}
}
template<typename TT, int OO, typename SS>
requires(detail::accept_as_ref<ref, ref<TT, OO, SS>>)
ref(ref<TT, OO, SS>& b) : parent(detail::postpone{})
{
[[maybe_unused]] bool correct_ref_setup = detail::validate_ref(*this, b);
assert(correct_ref_setup);
}
template<typename TT, int OO, typename SS>
requires(is_immutable && detail::same_scalar<ref, ref<TT, OO, SS>> &&
(detail::accept_as_ref<ref, ref<TT, OO, SS>> || may_map_object))
ref(ref<TT, OO, SS> 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<ref> const& r)
{
return os << format{r.matrix_.base(), r.format_};
}
private:
referee potential_local_copy;
};
template<typename S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC>&) -> ref<matrix<S>>;
template<typename Ref, int R, int C, bool I>
ref(block<Ref, R, C, I>& b) -> ref<Ref>;
template<typename S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC> const&) -> ref<matrix<S> const>;
template<typename Ref, int R, int C, bool I>
ref(block<Ref, R, C, I> const& b) -> ref<Ref const>;
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator+(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base() + rhs.base())
{
return lhs.base() + rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator-(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return lhs.base() - rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator*(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return lhs.base() * rhs.base();
}
template<typename A, int O, typename S>
auto operator*(ref<A, O, S> lhs,
std::convertible_to<typename A::value_type> auto s)
{
return lhs.base() * s;
}
template<typename A, int O, typename S>
auto operator/(ref<A, O, S> lhs,
std::convertible_to<typename A::value_type> auto s)
{
return lhs.base() / s;
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto min(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseMin(rhs.base()))
{
return lhs.base().cwiseMin(rhs.base());
}
template<typename A, int O, typename S>
auto min(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
-> decltype(lhs.base().cwiseMin(s))
{
return lhs.base().cwiseMin(s);
}
template<typename A, int O, typename S>
auto min(std::convertible_to<typename A::value_type> auto s, ref<A, O, S> rhs)
-> decltype(rhs.base().cwiseMin(s))
{
return rhs.base().cwiseMin(s);
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto max(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseMax(rhs.base()))
{
return lhs.base().cwiseMax(rhs.base());
}
template<typename A, int O, typename S>
auto max(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
-> decltype(lhs.base().cwiseMax(s))
{
return lhs.base().cwiseMax(s);
}
template<typename A, int O, typename S>
auto max(std::convertible_to<typename A::value_type> auto s, ref<A, O, S> rhs)
-> decltype(rhs.base().cwiseMax(s))
{
return rhs.base().cwiseMax(s);
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto mul(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseProduct(rhs.base()))
{
return lhs.base().cwiseProduct(rhs.base());
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto div(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseQuotient(rhs.base()))
{
return lhs.base().cwiseQuotient(rhs.base());
}
template<typename A, int O, typename S>
auto inverse(ref<A, O, S> lhs) -> decltype(lhs.base().inverse())
{
return lhs.base().inverse();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto cross(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cross(rhs.base()))
{
return lhs.base().cross(rhs.base());
}
}

View file

@ -0,0 +1,397 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/detail/helpers.hpp>
#include <Eigen/Dense>
#include <type_traits>
namespace rotgen
{
namespace detail
{
template<typename T, int Options, typename Stride> struct compile_ref;
template<typename Scalar,
int Rows,
int Cols,
int Opts,
int MaxRows,
int MaxCols,
int Options,
typename Stride>
struct compile_ref<matrix<Scalar, Rows, Cols, Opts, MaxRows, MaxCols>,
Options,
Stride>
{
using base = Eigen::Matrix<Scalar, Rows, Cols, Opts, MaxRows, MaxCols>;
using type = Eigen::Ref<base, Options, Stride>;
};
template<typename Scalar,
int Rows,
int Cols,
int Opts,
int MaxRows,
int MaxCols,
int Options,
typename Stride>
struct compile_ref<matrix<Scalar, Rows, Cols, Opts, MaxRows, MaxCols> const,
Options,
Stride>
{
using base = Eigen::Matrix<Scalar, Rows, Cols, Opts, MaxRows, MaxCols>;
using type = Eigen::Ref<base const, Options, Stride>;
};
template<typename T, int Options, typename Stride>
using compile_ref_t = typename compile_ref<T, Options, Stride>::type;
}
template<typename T, int Options, typename Stride>
class ref : private detail::compile_ref_t<T, Options, Stride>
{
public:
using parent = detail::compile_ref_t<T, Options, Stride>;
using referee = std::remove_const_t<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<T>;
// 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<parent const&>(*this).eval();
return as_concrete_type<decltype(res)>(res);
}
auto evaluate()
{
auto res = static_cast<parent&>(*this).eval();
return as_concrete_type<decltype(res)>(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<parent const&>(*this); }
parent& base() { return static_cast<parent&>(*this); }
template<typename S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC>& m)
requires(requires { parent(m.base()); })
: parent(m.base())
{
}
template<typename S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC> const& m)
requires(requires { parent(m.base()); } && is_immutable)
: parent(m.base())
{
}
template<typename Ref, int R, int C, bool I>
ref(block<Ref, R, C, I>&& b)
requires(requires { parent(b.base()); })
: parent(b.base())
{
}
template<typename Ref, int R, int C, bool I>
ref(block<Ref, R, C, I>& b)
requires(requires { parent(b.base()); })
: parent(b.base())
{
}
template<typename Ref, int R, int C, bool I>
ref(block<Ref, R, C, I> const& b)
requires(requires { parent(b.base()); } && is_immutable)
: parent(b.base())
{
}
template<typename Ref, int O, typename S>
ref(map<Ref, O, S>& m)
requires(requires { parent(m.base()); })
: parent(m.base())
{
}
template<typename Ref, int O, typename S>
ref(map<Ref, O, S> const& m)
requires(requires { parent(m.base()); } && is_immutable)
: parent(m.base())
{
}
template<typename TT, int OO, typename SS>
ref(ref<TT, OO, SS>& r)
requires(requires { parent(r.base()); })
: parent(r.base())
{
}
template<typename TT, int OO, typename SS>
ref(ref<TT, OO, SS> 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<ref> const& r)
{
return os << format{r.matrix_.base(), r.format_};
}
};
//============================================================================
// Deduction Guides
//============================================================================
template<typename S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC>&) -> ref<matrix<S>>;
template<typename Ref, int R, int C, bool I>
ref(block<Ref, R, C, I>& b) -> ref<Ref>;
template<typename S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC> const&) -> ref<matrix<S> const>;
template<typename Ref, int R, int C, bool I>
ref(block<Ref, R, C, I> const& b) -> ref<Ref const>;
//============================================================================
// Operators
//============================================================================
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator+(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return detail::concretize<matrix>(lhs.base() + rhs.base());
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator-(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return detail::concretize<matrix>(lhs.base() - rhs.base());
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator*(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return detail::concretize<matrix>(lhs.base() * rhs.base());
}
template<typename A, int O, typename S>
auto operator*(ref<A, O, S> lhs,
std::convertible_to<typename A::value_type> auto s)
{
return detail::concretize<matrix>(lhs.base() * s);
}
template<typename A, int O, typename S>
auto operator/(ref<A, O, S> lhs,
std::convertible_to<typename A::value_type> auto s)
{
return detail::concretize<matrix>(lhs.base() / s);
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto mul(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return detail::concretize<matrix>(lhs.base().cwiseProduct(rhs.base()));
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto div(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return detail::concretize<matrix>(lhs.base().cwiseQuotient(rhs.base()));
}
//============================================================================
// Functions
//============================================================================
template<typename A, int O, typename S, typename B, int P, typename T>
auto min(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return detail::concretize<matrix>(lhs.base().cwiseMin(rhs.base()));
}
template<typename A, int O, typename S>
auto min(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
{
return detail::concretize<matrix>(lhs.base().cwiseMin(s));
}
template<typename A, int O, typename S>
auto min(std::convertible_to<typename A::value_type> auto s, ref<A, O, S> rhs)
{
return detail::concretize<matrix>(rhs.base().cwiseMin(s));
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto max(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return detail::concretize<matrix>(lhs.base().cwiseMax(rhs.base()));
}
template<typename A, int O, typename S>
auto max(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
{
return detail::concretize<matrix>(lhs.base().cwiseMax(s));
}
template<typename A, int O, typename S>
auto max(std::convertible_to<typename A::value_type> auto s, ref<A, O, S> rhs)
{
return detail::concretize<matrix>(rhs.base().cwiseMax(s));
}
template<typename A, int O, typename S> auto inverse(ref<A, O, S> lhs)
{
return detail::concretize<matrix>(lhs.base().inverse());
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto cross(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cross(rhs.base()))
{
return detail::concretize<matrix>(lhs.base().cross(rhs.base()));
}
//-------------------------------------------------------------------------------------------
// Convert entity/eigen types to a proper ref so we can write less function
// overloads
template<typename T> struct generalize;
template<concepts::eigen_compatible T> struct generalize<T>
{
static constexpr bool is_const = std::is_const_v<T>;
using concrete_type = decltype(std::declval<T>().eval());
using base = matrix<typename T::Scalar,
T::RowsAtCompileTime,
T::ColsAtCompileTime,
concrete_type::Options & 1>;
using type = std::conditional_t<is_const, ref<base const>, ref<base>>;
};
template<concepts::eigen_compatible T> auto const& base_of(T const& a)
{
return a;
}
template<concepts::eigen_compatible T> auto& base_of(T& a)
{
return a;
}
}

View file

@ -0,0 +1,88 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <type_traits>
namespace rotgen
{
template<typename A, int O, typename S, typename B, int P, typename T>
bool operator==(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return lhs.base() == rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
bool operator!=(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return lhs.base() != rhs.base();
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator+=(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
lhs.base() += rhs.base();
return lhs;
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator-=(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
lhs.base() -= rhs.base();
return lhs;
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator*=(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
lhs.base() *= rhs.base();
return lhs;
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto operator/=(ref<A, O, S> lhs,
std::convertible_to<typename A::value_type> auto s)
{
lhs.base() /= s;
return lhs;
}
template<typename A, int O, typename S>
auto operator*(std::convertible_to<typename A::value_type> auto s,
ref<A, O, S> rhs)
{
return rhs * s;
}
template<typename A, int O, typename S, typename B, int P, typename T>
auto dot(ref<A, O, S> lhs, ref<B, P, T> rhs)
{
return lhs.base().dot(rhs.base());
}
template<typename A, int O, typename S>
auto mul(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
-> decltype(lhs * s)
{
return lhs * s;
}
template<typename A, int O, typename S>
auto mul(std::convertible_to<typename A::value_type> auto s, ref<A, O, S> rhs)
-> decltype(s * rhs)
{
return s * rhs;
}
template<typename A, int O, typename S>
auto div(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
-> decltype(lhs / s)
{
return lhs / s;
}
}

View file

@ -0,0 +1,65 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <type_traits>
namespace rotgen
{
//-------------------------------------------------------------------------------------------
// Convert entity/eigen types to a proper ref so we can write less function
// overloads
template<typename T> struct generalize;
template<typename T>
requires(std::is_arithmetic_v<std::remove_cvref_t<T>>)
struct generalize<T>
{
using type = std::remove_cvref_t<T>;
};
template<typename T> using generalize_t = typename generalize<T>::type;
template<concepts::entity T> struct generalize<T>
{
static constexpr bool is_const = std::is_const_v<T>;
using base = matrix<typename T::value_type,
T::RowsAtCompileTime,
T::ColsAtCompileTime,
T::storage_order>;
using type = std::conditional_t<is_const, ref<base const>, ref<base>>;
};
template<typename T, int O, typename S> struct generalize<ref<T, O, S>>
{
using type = ref<T, O, S>;
};
template<typename T, int O, typename S> struct generalize<ref<T, O, S> const>
{
using type = ref<T, O, S>;
};
template<concepts::entity T> typename T::parent& base_of(T& a)
{
return a.base();
}
template<concepts::entity T> typename T::parent const& base_of(T const& a)
{
return a.base();
}
template<typename T>
T base_of(T a)
requires(std::is_arithmetic_v<T>)
{
return a;
}
}

View file

@ -7,76 +7,10 @@
//==================================================================================================
#pragma once
#include <rotgen/concepts.hpp>
#include <rotgen/config.hpp>
#if !defined(ROTGEN_FORCE_DYNAMIC)
#include <Eigen/Dense>
#endif
namespace rotgen
{
#if !defined(ROTGEN_FORCE_DYNAMIC)
using stride = Eigen::Stride<-1, -1>;
#if defined(ROTGEN_FORCE_DYNAMIC)
#include <rotgen/container/strides/dynamic.hpp>
#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 <rotgen/container/strides/fixed.hpp>
#endif
template<Index Value = Dynamic> struct inner_stride : stride
{
static constexpr bool is_dynamic = Value == Dynamic;
inner_stride() : stride(-1, Value) {}
inner_stride(Index v) : stride(0, v) {}
};
template<Index Value = Dynamic> 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<Dynamic>;
outer_stride(Index) -> outer_stride<Dynamic>;
template<int Order> stride strides(Index r, Index c)
{
if constexpr (Order == RowMajor) return {c, 1};
else return {r, 1};
}
template<int Order> stride strides(stride const& original, Index, Index)
{
return original;
}
template<int Order, Index N>
stride strides(outer_stride<N> const& original, Index r, Index c)
{
if constexpr (N == 0) return stride{Order == ColMajor ? r : c, 1};
else return {original.outer(), 1};
}
template<concepts::entity E> auto strides(E const& e)
{
return strides<E::storage_order>(e.rows(), e.cols());
}
}

View file

@ -0,0 +1,84 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/concepts.hpp>
namespace rotgen
{
template<int Outer = 0, int Inner = 0> 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<int Value = Dynamic> struct inner_stride : stride<0, Value>
{
using parent = stride<0, Value>;
inner_stride() : parent() {}
inner_stride(int v) : parent(0, v) {}
};
template<int Value = Dynamic> struct outer_stride : stride<Value, 0>
{
using parent = stride<Value, 0>;
outer_stride() : parent() {}
outer_stride(int v) : parent(v, 0) {}
};
using dynamic_stride = stride<-1, -1>;
template<int Order> dynamic_stride strides(Index r, Index c)
{
if constexpr (Order == RowMajor) return {c, 1};
else return {r, 1};
}
template<int Order, concepts::entity E> dynamic_stride strides(E const& e)
{
return strides<Order>(e.rows(), e.cols());
}
template<int Order, int O, int I>
dynamic_stride strides(stride<O, I> const& original, Index, Index)
{
return {original.outer(), original.inner()};
}
template<int Order, int N>
dynamic_stride strides(outer_stride<N> const& original, Index r, Index c)
{
if constexpr (N == 0) return {Order == ColMajor ? r : c, 1};
else return {original.outer(), 1};
}
template<concepts::entity E> auto strides(E const& e)
{
return strides<E::storage_order>(e.rows(), e.cols());
}
}

View file

@ -0,0 +1,40 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/concepts.hpp>
#include <Eigen/Dense>
namespace rotgen
{
template<int Outer, int Inner> struct stride : Eigen::Stride<Outer, Inner>
{
using parent = Eigen::Stride<Outer, Inner>;
using parent::parent;
};
template<int Value = Eigen::Dynamic>
struct inner_stride : Eigen::InnerStride<Value>
{
using parent = Eigen::InnerStride<Value>;
using parent::parent;
};
template<int Value = Eigen::Dynamic>
struct outer_stride : Eigen::OuterStride<Value>
{
using parent = Eigen::OuterStride<Value>;
using parent::parent;
};
inner_stride(int) -> inner_stride<-1>;
outer_stride(int) -> outer_stride<-1>;
using dynamic_stride = stride<-1, -1>;
}

View file

@ -0,0 +1,160 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <cassert>
#include <concepts>
namespace rotgen::detail
{
// We split each sub-check into its own concept to improve
// diagnostic messages
template<typename Ref, typename Input>
concept same_scalar =
std::same_as<typename Ref::value_type, typename Input::value_type>;
template<typename Ref, typename Input>
concept any_is_vector =
Ref::IsVectorAtCompileTime || Input::IsVectorAtCompileTime;
template<typename Ref, typename Input>
concept compatible_storage =
any_is_vector<Ref, Input> || (Ref::storage_order == Input::storage_order);
template<typename Ref, typename Input>
concept compatible_inner_stride =
(Ref::InnerStrideAtCompileTime == rotgen::Dynamic) ||
(Ref::InnerStrideAtCompileTime == Input::InnerStrideAtCompileTime) ||
(Ref::InnerStrideAtCompileTime == 0 &&
Input::InnerStrideAtCompileTime == 1);
template<typename Ref, typename Input>
concept compatible_outer_stride =
any_is_vector<Ref, Input> ||
(Ref::OuterStrideAtCompileTime == rotgen::Dynamic) ||
(Ref::OuterStrideAtCompileTime == Input::OuterStrideAtCompileTime);
// Check what we can actually pass to ref<>
template<typename Ref, typename Input>
concept accept_as_ref =
same_scalar<Ref, Input> && compatible_storage<Ref, Input> &&
compatible_inner_stride<Ref, Input> && compatible_outer_stride<Ref, Input>;
// 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<typename Ref, typename Input> 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;
}
}

View file

@ -7,8 +7,21 @@
//==================================================================================================
#pragma once
#include <rotgen/config.hpp>
#include <type_traits>
namespace rotgen::detail
{
template<typename T> 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 EigenType,
template<typename, int, int, int, int, int> typename Wrapper>
struct as_concrete
@ -26,6 +39,13 @@ namespace rotgen::detail
using as_concrete_t =
typename as_concrete<std::remove_cvref_t<EigenType>, Wrapper>::type;
template<template<typename, int, int, int, int, int> typename Wrapper>
decltype(auto) concretize(auto const& t)
{
if constexpr (use_expression_templates) return t;
else return as_concrete_t<std::remove_cvref_t<decltype(t)>, Wrapper>(t);
}
template<typename M, typename N>
inline constexpr bool has_same_vector_size = []() {
// No vector = noo size
@ -42,13 +62,13 @@ namespace rotgen::detail
template<typename T>
using propagate_const =
std::conditional_t<T::is_immutable || std::is_const_v<T>,
std::add_const_t<T>,
T>;
std::conditional_t<std::remove_cvref_t<T>::is_immutable ||
std::is_const_v<T>,
std::add_const_t<std::remove_cvref_t<T>>,
std::remove_cvref_t<T>>;
template<auto M, auto N>
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<typename M1,
typename M2,

View file

@ -7,263 +7,13 @@
//==================================================================================================
#pragma once
#include <cstddef>
#include <memory>
#include <rotgen/container/matrix/dynamic/impl.hpp>
#include <rotgen/container/map/dynamic/impl.hpp>
#include <Eigen/Dense>
#include <Eigen/Core>
#include <rotgen/detail/payload/block.hpp>
#include <rotgen/detail/payload/map.hpp>
#include <rotgen/detail/payload/matrix.hpp>
namespace rotgen
{
//==================================================================================================
// Internal payload - Required for cross-referencing from block_impl*
//==================================================================================================
struct matrix_impl64_col::payload
{
using data_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
data_type data;
payload(std::size_t r = 0, std::size_t c = 0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<double>> init)
: data(init)
{
}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> 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<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
data_type data;
payload(std::size_t r = 0, std::size_t c = 0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<double>> init)
: data(init)
{
}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> 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<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
data_type data;
payload(std::size_t r = 0, std::size_t c = 0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<float>> init)
: data(init)
{
}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> 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<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
data_type data;
payload(std::size_t r = 0, std::size_t c = 0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<float>> init)
: data(init)
{
}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> 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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using data_type =
Eigen::Map<base_type const, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using data_type =
Eigen::Map<base_type const, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using data_type =
Eigen::Map<base_type const, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using data_type =
Eigen::Map<base_type const, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
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;

View file

@ -0,0 +1,209 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/container/block/dynamic/impl.hpp>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <cstddef>
#include <memory>
#include <variant>
namespace rotgen
{
struct source_t
{
};
struct trans_t
{
};
struct map_t
{
};
struct matrix_t
{
};
//================================================================================================
// Template payload implementation
//================================================================================================
template<typename ScalarType, int StorageOrder, bool IsConst>
struct payload_impl
{
using row_matrix_type = Eigen::
Matrix<ScalarType, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using col_matrix_type = Eigen::
Matrix<ScalarType, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using source_matrix_type =
std::conditional_t<StorageOrder == Eigen::RowMajor,
row_matrix_type,
col_matrix_type>;
using trans_matrix_type =
std::conditional_t<StorageOrder != Eigen::RowMajor,
row_matrix_type,
col_matrix_type>;
template<typename T>
using maybe_const = std::conditional_t<IsConst, T const, T>;
using source_matrix_block_type =
Eigen::Block<maybe_const<source_matrix_type>>;
using trans_matrix_block_type =
Eigen::Block<maybe_const<trans_matrix_type>>;
using source_matrix_storage_t =
std::pair<source_matrix_block_type, maybe_const<source_matrix_type>*>;
using trans_matrix_storage_t =
std::pair<trans_matrix_block_type, maybe_const<trans_matrix_type>*>;
using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using source_map_type = Eigen::
Map<maybe_const<source_matrix_type>, Eigen::Unaligned, stride_type>;
using trans_map_type =
Eigen::Map<maybe_const<trans_matrix_type>, Eigen::Unaligned, stride_type>;
using source_map_block_type = Eigen::Block<maybe_const<source_map_type>>;
using trans_map_block_type = Eigen::Block<maybe_const<trans_map_type>>;
using source_map_storage_t =
std::pair<source_map_block_type, maybe_const<source_map_type>*>;
using trans_map_storage_t =
std::pair<trans_map_block_type, maybe_const<trans_map_type>*>;
using data_type = std::variant<source_matrix_storage_t,
trans_matrix_storage_t,
source_map_storage_t,
trans_map_storage_t>;
data_type data;
rotgen::Index abs_i0 = 0;
rotgen::Index abs_j0 = 0;
rotgen::Index rel_i0 = 0;
rotgen::Index rel_j0 = 0;
template<typename Func> void apply(Func f)
{
std::visit([&](auto& blk) { return f(blk.first); }, data);
}
template<typename Func> 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<double, Eigen::ColMajor, true>
{
using payload_impl::payload_impl;
};
struct block_const_impl64_row::payload
: payload_impl<double, Eigen::RowMajor, true>
{
using payload_impl::payload_impl;
};
struct block_const_impl32_col::payload
: payload_impl<float, Eigen::ColMajor, true>
{
using payload_impl::payload_impl;
};
struct block_const_impl32_row::payload
: payload_impl<float, Eigen::RowMajor, true>
{
using payload_impl::payload_impl;
};
struct block_impl64_col::payload
: payload_impl<double, Eigen::ColMajor, false>
{
using payload_impl::payload_impl;
};
struct block_impl64_row::payload
: payload_impl<double, Eigen::RowMajor, false>
{
using payload_impl::payload_impl;
};
struct block_impl32_col::payload : payload_impl<float, Eigen::ColMajor, false>
{
using payload_impl::payload_impl;
};
struct block_impl32_row::payload : payload_impl<float, Eigen::RowMajor, false>
{
using payload_impl::payload_impl;
};
}

View file

@ -0,0 +1,170 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/container/map/dynamic/impl.hpp>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <cstddef>
#include <memory>
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using data_type =
Eigen::Map<base_type const, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using data_type =
Eigen::Map<base_type const, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using data_type =
Eigen::Map<base_type const, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using data_type =
Eigen::Map<base_type const, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
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<Eigen::Dynamic, Eigen::Dynamic>;
using base_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
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)
{
}
};
}

View file

@ -0,0 +1,113 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/container/matrix/dynamic/impl.hpp>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <cstddef>
#include <memory>
namespace rotgen
{
//==================================================================================================
// Internal payload - Required for cross-referencing from block_impl*
//==================================================================================================
struct matrix_impl64_col::payload
{
using data_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
data_type data;
payload(std::size_t r = 0, std::size_t c = 0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<double>> init)
: data(init)
{
}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> 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<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
data_type data;
payload(std::size_t r = 0, std::size_t c = 0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<double>> init)
: data(init)
{
}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> 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<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
data_type data;
payload(std::size_t r = 0, std::size_t c = 0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<float>> init)
: data(init)
{
}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> 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<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
data_type data;
payload(std::size_t r = 0, std::size_t c = 0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<float>> init)
: data(init)
{
}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> ref) { data = ref; }
void assign(data_type const& mat) { data = mat; }
void assign(data_type&& mat) { data = std::move(mat); }
};
}

View file

@ -9,5 +9,6 @@
#include <rotgen/functions/extract.hpp>
#include <rotgen/functions/functions.hpp>
#include <rotgen/functions/generators.hpp>
#include <rotgen/functions/operators.hpp>
#include <rotgen/functions/reshaper.hpp>

View file

@ -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<Entity>)
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<detail::propagate_const<Entity>>(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<Entity>)
return extract<NI, NJ>(e.base(), i0, j0);
if constexpr (requires { e.as_map(); })
return extract<NI, NJ>(e.as_map(), i0, j0);
else return block<detail::propagate_const<Entity>, 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<Entity>)
return extract<NI, NJ>(e.base(), i0, j0, ni, nj);
if constexpr (requires { e.as_map(); })
return extract<NI, NJ>(e.as_map(), i0, j0, ni, nj);
else
return block<detail::propagate_const<Entity>, NI, NJ>(e, i0, j0, ni, nj);
}
@ -112,83 +112,116 @@ namespace rotgen
//======================== TOP ROWS ========================
template<concepts::entity Entity> 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<Index NI, concepts::entity Entity> auto topRows(Entity& e)
{
return extract<NI, -1>(e, 0, 0, NI, e.cols());
if constexpr (Entity::ColsAtCompileTime == -1)
return extract<NI, -1>(e, 0, 0, NI, e.cols());
else return extract<NI, Entity::ColsAtCompileTime>(e, 0, 0);
}
//======================== MIDDLE ROWS ========================
template<concepts::entity Entity>
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<Index NI, concepts::entity Entity>
auto middleRows(Entity& e, Index i0)
{
return extract<NI, -1>(e, i0, 0, NI, e.cols());
if constexpr (Entity::ColsAtCompileTime == -1)
return extract<NI, -1>(e, i0, 0, NI, e.cols());
else return extract<NI, Entity::ColsAtCompileTime>(e, i0, 0);
}
//======================== BOTTOM ROWS ========================
template<concepts::entity Entity> 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<Index NI, concepts::entity Entity> auto bottomRows(Entity& e)
{
return extract<NI, -1>(e, e.rows() - NI, 0, NI, e.cols());
if constexpr (Entity::ColsAtCompileTime == -1)
return extract<NI, -1>(e, e.rows() - NI, 0, NI, e.cols());
else return extract<NI, Entity::ColsAtCompileTime>(e, e.rows() - NI, 0);
}
//======================== LEFT COLS ========================
template<concepts::entity Entity> 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<Entity::RowsAtCompileTime, -1>(e, 0, 0, e.rows(), nj);
}
template<Index NJ, concepts::entity Entity> 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<Entity::RowsAtCompileTime, NJ>(e, 0, 0);
}
//======================== MIDDLE COLS ========================
template<concepts::entity Entity>
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<Entity::RowsAtCompileTime, -1>(e, 0, j0, e.rows(), nj);
}
template<Index NJ, concepts::entity Entity>
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<Entity::RowsAtCompileTime, NJ>(e, 0, j0);
}
//======================== RIGHT COLS ========================
template<concepts::entity Entity> 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<Entity::RowsAtCompileTime, -1>(e, 0, e.cols() - nj,
e.rows(), nj);
;
}
template<Index NJ, concepts::entity Entity> 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<Entity::RowsAtCompileTime, NJ>(e, 0, e.cols() - NJ);
}
//======================== ROW ========================
template<concepts::entity Entity> 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<concepts::entity Entity> 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<Entity::RowsAtCompileTime, 1>(e, 0, j0);
}
//======================== VECTOR HEAD ========================

View file

@ -322,149 +322,6 @@ namespace rotgen
return std::forward<T>(t).eval();
}
//-----------------------------------------------------------------------------------------------
// Generators
//-----------------------------------------------------------------------------------------------
template<typename T>
auto setZero(T&& t)
requires(requires { std::forward<T>(t).setZero(); })
{
return std::forward<T>(t).setZero();
}
template<typename T>
auto setZero()
requires(requires { T::Zero(); })
{
return T::Zero();
}
template<typename T>
auto setZero(std::integral auto n)
requires(requires { T::Zero(n); })
{
return T::Zero(n);
}
template<typename T>
auto setZero(std::integral auto r, std::integral auto c)
requires(requires { T::Zero(r, c); })
{
return T::Zero(r, c);
}
template<typename T>
auto setOnes(T&& t)
requires(requires { std::forward<T>(t).setOnes(); })
{
return std::forward<T>(t).setOnes();
}
template<typename T>
auto setOnes()
requires(requires { T::Ones(); })
{
return T::Ones();
}
template<typename T>
auto setOnes(std::integral auto n)
requires(requires { T::Ones(n); })
{
return T::Ones(n);
}
template<typename T>
auto setOnes(std::integral auto r, std::integral auto c)
requires(requires { T::Ones(r, c); })
{
return T::Ones(r, c);
}
template<typename T>
auto setIdentity(T&& t)
requires(requires { std::forward<T>(t).setIdentity(); })
{
return std::forward<T>(t).setIdentity();
}
template<typename T>
auto setIdentity()
requires(requires { T::Identity(); })
{
return T::Identity();
}
template<typename T>
auto setIdentity(std::integral auto n)
requires(requires { T::Identity(n); })
{
return T::Identity(n);
}
template<typename T>
auto setIdentity(std::integral auto r, std::integral auto c)
requires(requires { T::Identity(r, c); })
{
return T::Identity(r, c);
}
template<typename T>
auto setRandom(T&& t)
requires(requires { std::forward<T>(t).setRandom(); })
{
return std::forward<T>(t).setRandom();
}
template<typename T>
auto setRandom()
requires(requires { T::Random(); })
{
return T::Random();
}
template<typename T>
auto setRandom(std::integral auto n)
requires(requires { T::Random(n); })
{
return T::Random(n);
}
template<typename T>
auto setRandom(std::integral auto r, std::integral auto c)
requires(requires { T::Random(r, c); })
{
return T::Random(r, c);
}
template<typename T>
auto setConstant(T&& t, auto v)
requires(requires { std::forward<T>(t).setConstant(v); })
{
return std::forward<T>(t).setConstant(v);
}
template<typename T>
auto setConstant(auto v)
requires(requires { T::Constant(v); })
{
return T::Constant(v);
}
template<typename T>
auto setConstant(std::integral auto n, auto v)
requires(requires { T::Constant(n, v); })
{
return T::Constant(n, v);
}
template<typename T>
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 const>(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<concepts::vectorND<3> L, concepts::vectorND<3> R>

View file

@ -0,0 +1,156 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/detail/helpers.hpp>
namespace rotgen
{
//-----------------------------------------------------------------------------------------------
// Generators
//-----------------------------------------------------------------------------------------------
template<typename T>
auto setZero(T&& t)
requires(requires { std::forward<T>(t).setZero(); })
{
return std::forward<T>(t).setZero();
}
template<typename T>
auto setZero()
requires(requires { T::Zero(); })
{
return T::Zero();
}
template<typename T>
auto setZero(std::integral auto n)
requires(requires { T::Zero(n); })
{
return T::Zero(n);
}
template<typename T>
auto setZero(std::integral auto r, std::integral auto c)
requires(requires { T::Zero(r, c); })
{
return T::Zero(r, c);
}
template<typename T>
auto setOnes(T&& t)
requires(requires { std::forward<T>(t).setOnes(); })
{
return std::forward<T>(t).setOnes();
}
template<typename T>
auto setOnes()
requires(requires { T::Ones(); })
{
return T::Ones();
}
template<typename T>
auto setOnes(std::integral auto n)
requires(requires { T::Ones(n); })
{
return T::Ones(n);
}
template<typename T>
auto setOnes(std::integral auto r, std::integral auto c)
requires(requires { T::Ones(r, c); })
{
return T::Ones(r, c);
}
template<typename T>
auto setIdentity(T&& t)
requires(requires { std::forward<T>(t).setIdentity(); })
{
return std::forward<T>(t).setIdentity();
}
template<typename T>
auto setIdentity()
requires(requires { T::Identity(); })
{
return T::Identity();
}
template<typename T>
auto setIdentity(std::integral auto n)
requires(requires { T::Identity(n); })
{
return T::Identity(n);
}
template<typename T>
auto setIdentity(std::integral auto r, std::integral auto c)
requires(requires { T::Identity(r, c); })
{
return T::Identity(r, c);
}
template<typename T>
auto setRandom(T&& t)
requires(requires { std::forward<T>(t).setRandom(); })
{
return std::forward<T>(t).setRandom();
}
template<typename T>
auto setRandom()
requires(requires { T::Random(); })
{
return T::Random();
}
template<typename T>
auto setRandom(std::integral auto n)
requires(requires { T::Random(n); })
{
return T::Random(n);
}
template<typename T>
auto setRandom(std::integral auto r, std::integral auto c)
requires(requires { T::Random(r, c); })
{
return T::Random(r, c);
}
template<typename T>
auto setConstant(T&& t, auto v)
requires(requires { std::forward<T>(t).setConstant(v); })
{
return std::forward<T>(t).setConstant(v);
}
template<typename T>
auto setConstant(auto v)
requires(requires { T::Constant(v); })
{
return T::Constant(v);
}
template<typename T>
auto setConstant(std::integral auto n, auto v)
requires(requires { T::Constant(n, v); })
{
return T::Constant(n, v);
}
template<typename T>
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);
}
}

View file

@ -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

View file

@ -5,9 +5,11 @@
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/detail/generators.hpp>
#include <rotgen/container/block/dynamic/impl.hpp>
#include <rotgen/detail/generators.hpp>
#include <rotgen/detail/payload.hpp>
#include <Eigen/Dense>
#include <variant>

View file

@ -12,80 +12,65 @@
*/
//==================================================================================================
//==================================================================================================
// Internal payload
//==================================================================================================
struct CLASSNAME::payload
{
using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using matrix_type =
Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic, STORAGE_ORDER>;
using matrix_block_type = Eigen::Block<matrix_type CONST>;
using matrix_storage_t = std::pair<matrix_block_type, matrix_type CONST*>;
using map_type = Eigen::Map<matrix_type CONST, Eigen::Unaligned, stride_type>;
using map_block_type = Eigen::Block<map_type CONST>;
using map_storage_t = std::pair<map_block_type, map_type CONST*>;
using data_type = std::variant<matrix_storage_t, map_storage_t>;
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<typename Func> void apply(Func f)
{
std::visit([&](auto& blk) { return f(blk.first); }, data);
}
template<typename Func> 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<payload>(r, i0, j0, ni, nj))
: storage_(
std::make_unique<payload>(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<payload>(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<payload>(r, i0, j0, ni, nj))
: storage_(std::make_unique<payload>(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(
[&]<typename T>(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<payload>(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;
}

View file

@ -5,9 +5,11 @@
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/detail/generators.hpp>
#include <rotgen/container/map/dynamic/impl.hpp>
#include <rotgen/detail/generators.hpp>
#include <rotgen/detail/payload.hpp>
#include <Eigen/Dense>
#include <Eigen/LU>

View file

@ -19,12 +19,14 @@
//==================================================================================================
// Constructors & Special Members
//==================================================================================================
CLASSNAME::CLASSNAME() {}
CLASSNAME::CLASSNAME(TYPE CONST* ptr, Index r, Index c)
: storage_(std::make_unique<payload>(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<payload>(
ptr, r, c, payload::stride_type{s.outer(), s.inner()}))
{

View file

@ -5,10 +5,11 @@
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/detail/generators.hpp>
#include <rotgen/container/matrix/dynamic/impl.hpp>
#include <rotgen/detail/generators.hpp>
#include <rotgen/detail/payload.hpp>
#include <rotgen/config.hpp>
#include <Eigen/Dense>
namespace rotgen

View file

@ -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;

View file

@ -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)
##======================================================================================================================

View file

@ -5,12 +5,13 @@
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Chains of extraction",
rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
#include "unit/tests.hpp"
TTS_CASE_TPL("Chains of extraction", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
constexpr int N = 8;
auto a = rotgen::matrix<T, N, N, O::value>::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<rotgen::matrix<float>> 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<rotgen::matrix<float, 4, 3>>(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);
};

View file

@ -5,8 +5,9 @@
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
#include "unit/tests.hpp"
#include <iostream>
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<rotgen::matrix<float> const>) {}
void process_ref(rotgen::ref<rotgen::matrix<double> const>) {}
void process_ref(
rotgen::ref<
rotgen::
matrix<float, rotgen::Dynamic, rotgen::Dynamic, rotgen::RowMajor> const>)
{
}
void process_ref(
rotgen::ref<
rotgen::
matrix<double, rotgen::Dynamic, rotgen::Dynamic, rotgen::RowMajor> const>)
{
}
TTS_CASE_TPL("Extraction of outer_stride<?> blocks",
rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{
using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
if constexpr (O::value == rotgen::ColMajor)
{
T padded[] = {1, 2, 3, 4, 99, 5, 6, 7, 8, 99, 9, 10, 11, 12};
rotgen::map<mat_t, 0, rotgen::outer_stride<5>> sp(&padded[0], 4, 3);
rotgen::map<mat_t, 0, rotgen::outer_stride<>> 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<mat_t, 0, rotgen::outer_stride<4>> sp(&padded[0], 4, 3);
rotgen::map<mat_t, 0, rotgen::outer_stride<>> 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)); });
}
};

View file

@ -5,9 +5,10 @@
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
#include "unit/tests.hpp"
template<int size = rotgen::Dynamic,
typename Scalar = float,
int maxSize = size>
@ -63,3 +64,34 @@ TTS_CASE("Reference of reference check")
TTS_EQUAL(v2[0], sum2);
TTS_EQUAL(v3[0], sum3);
};
int f(rotgen::ref<rotgen::matrix<float, 1, 3, rotgen::RowMajor>>)
{
return +2;
}
template<int N>
int g(rotgen::ref<rotgen::matrix<float, -1, N, rotgen::ColMajor>>)
{
return +1;
}
template<int N>
int g(rotgen::ref<rotgen::matrix<float, -1, N, rotgen::RowMajor>>)
requires(N > 1)
{
return -1;
}
TTS_CASE("Reference overload on stroage order check")
{
rotgen::matrix<float> mat_dyn(1, 3);
rotgen::matrix<float, -1, 3, rotgen::ColMajor> mat_col(1, 3);
rotgen::matrix<float, -1, 3, rotgen::RowMajor> 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);
};

View file

@ -5,9 +5,10 @@
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
#include "unit/tests.hpp"
template<typename EigenType, typename F>
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<decltype(block)>;
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)<typename T, typename O>(tts::type<tts::types<T, O>>)
{
using mat_t =
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value, 1>;
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, rotgen::RowMajor>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> 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)<typename T, typename O>(tts::type<tts::types<T, O>>)
{
using mat_t = rotgen::matrix<T, 4, 5, O::value, 0>;
using mat_t = rotgen::matrix<T, 4, 5, rotgen::ColMajor>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> 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<T, 1, rotgen::Dynamic, O::value>;
using mat_t = rotgen::matrix<T, 1, rotgen::Dynamic>;
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<T, rotgen::Dynamic, 1, O::value>;
using mat_t = rotgen::matrix<T, rotgen::Dynamic, 1>;
mat_t m(11, 1);
for (rotgen::Index i = 0; i < 11; ++i) m(i) = 1 + i;

View file

@ -5,10 +5,11 @@
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
#include <vector>
#include "unit/tests.hpp"
#include <Eigen/Core>
#include <vector>
auto generate_data(int rows, int cols)
{
@ -26,7 +27,7 @@ using r_mat_t = rotgen::matrix<float, rotgen::Dynamic, rotgen::Dynamic, O>;
template<int O>
using e_mat_t = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, O>;
template<typename M, typename S = rotgen::stride>
template<typename M, typename S = rotgen::stride<0, 0>>
using r_map_t = rotgen::map<M, 0, S>;
template<typename M, typename S = Eigen::Stride<0, 0>>
using e_map_t = Eigen::Map<M, 0, S>;
@ -56,7 +57,7 @@ TTS_CASE("Validate Column Major Map with specific outer stride behavior")
auto buffer = generate_data(rows, cols);
r_map_t<r_mat_t<rotgen::ColMajor>, 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_mat_t<rotgen::ColMajor>> r_map(buffer.data(), rows, cols,
rotgen::stride(rows, 2));
r_map_t<r_mat_t<rotgen::ColMajor>, 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<r_mat_t<rotgen::RowMajor>, 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<r_mat_t<rotgen::RowMajor>, rotgen::stride> r_map(
buffer.data(), rows, cols, rotgen::stride(2, cols));
r_map_t<r_mat_t<rotgen::RowMajor>, 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);

View file

@ -5,12 +5,13 @@
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Default matrix dynamic constructor",
rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
#include "unit/tests.hpp"
TTS_CASE_TPL("Default matrix dynamic constructor", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
TTS_CASE_TPL("Default matrix static constructor", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, 4, 9, O::value> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> 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)<typename T>(tts::type<T>)
TTS_CASE_TPL("Static matrix constructor with row and columns", float, double)
<typename T>(tts::type<T>)
{
rotgen::matrix<T, 1, 2> v2(6, 11);
rotgen::matrix<T, 2, 1> w2(6, 11);
rotgen::matrix<T, 1, 2> v2 = {6, 11};
rotgen::matrix<T, 2, 1> 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<T, 1, 3> v3(6, 11, 125);
rotgen::matrix<T, 3, 1> w3(6, 11, 125);
rotgen::matrix<T, 1, 3> v3 = {6, 11, 125};
rotgen::matrix<T, 3, 1> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
TTS_CASE_TPL("Copy constructor on default matrix", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> a;
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
TTS_CASE_TPL("Copy constructor from const matrix", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
TTS_CASE_TPL("Copy constructor on static matrix", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, 2, 5> a;
rotgen::matrix<T, 2, 5> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
TTS_CASE_TPL("Copy constructor on static/dynamic matrix", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, 11, 4, O::value> a;
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
TTS_CASE_TPL("Copy constructor on dynamic/static matrix", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> a(5, 7);
rotgen::matrix<T, 5, 7, O::value> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
TTS_CASE_TPL("Move constructor transfers contents", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
TTS_CASE_TPL("Move constructor from Rvalue", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> b =
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>(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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
TTS_CASE_TPL("Constructor from Initializer list", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, 1, 1, O::value> 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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
TTS_CASE_TPL("Constructor from Initializer list of rows", rotgen::tests::types)
<typename T, typename O>(tts::type<tts::types<T, O>>)
{
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> b1{{3.5}};
TTS_EQUAL(b1.rows(), rotgen::Index{1});

View file

@ -7,7 +7,6 @@
//==================================================================================================
#include <rotgen/rotgen.hpp>
#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<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto eps = std::numeric_limits<T>::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<mat_t>(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<typename T, typename O, int N> void check_static_inverse()
{
using mat_t = rotgen::matrix<T, N, N, O::value>;
auto eps = std::numeric_limits<T>::epsilon();
auto input = rotgen::setRandom<mat_t>();
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)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{
using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto eps = std::numeric_limits<T>::epsilon();
auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = [&]<typename D>(D const&) {
if constexpr (D::rows == D::cols)
{
auto input = rotgen::matrix<T, D::rows, D::cols, O::value>::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<T, O, 2>();
check_static_inverse<T, O, 3>();
check_static_inverse<T, O, 4>();
check_static_inverse<T, O, 6>();
check_static_inverse<T, O, 9>();
check_static_inverse<T, O, 13>();
};

View file

@ -0,0 +1,211 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/rotgen.hpp>
#include "unit/tests.hpp"
#include <Eigen/Core>
template<typename RType, typename EType> void check_size_properties()
{
TTS_CONSTEXPR_EQUAL(RType::RowsAtCompileTime, EType::RowsAtCompileTime)
<< tts::typename_<RType> << " vs " << tts::typename_<EType> << "\n";
TTS_CONSTEXPR_EQUAL(RType::ColsAtCompileTime, EType::ColsAtCompileTime)
<< tts::typename_<RType> << " vs " << tts::typename_<EType> << "\n";
TTS_CONSTEXPR_EQUAL(RType::MaxRowsAtCompileTime, EType::MaxRowsAtCompileTime)
<< tts::typename_<RType> << " vs " << tts::typename_<EType> << "\n";
TTS_CONSTEXPR_EQUAL(RType::MaxColsAtCompileTime, EType::MaxColsAtCompileTime)
<< tts::typename_<RType> << " vs " << tts::typename_<EType> << "\n";
TTS_CONSTEXPR_EQUAL(RType::IsVectorAtCompileTime,
EType::IsVectorAtCompileTime)
<< tts::typename_<RType> << " vs " << tts::typename_<EType> << "\n";
TTS_CONSTEXPR_EQUAL(RType::InnerStrideAtCompileTime,
EType::InnerStrideAtCompileTime)
<< tts::typename_<RType> << " vs " << tts::typename_<EType> << "\n";
TTS_CONSTEXPR_EQUAL(RType::OuterStrideAtCompileTime,
EType::OuterStrideAtCompileTime)
<< tts::typename_<RType> << " vs " << tts::typename_<EType> << "\n";
}
TTS_CASE("Compile-Time informations conformance w/r to Eigen - matrix")
{
using namespace rotgen;
using namespace Eigen;
check_size_properties<matrixXf, MatrixXf>();
check_size_properties<matrix<float, -1, -1, 0, 3, 3>,
Matrix<float, -1, -1, 0, 3, 3>>();
check_size_properties<matrix<float, 4, 9>, Matrix<float, 4, 9>>();
check_size_properties<vector4f, Vector4f>();
check_size_properties<matrix<float, 1, -1>, Matrix<float, 1, -1>>();
check_size_properties<row_vector4f, RowVector4f>();
check_size_properties<matrix<float, -1, 1>, Matrix<float, -1, 1>>();
// RowMajor / ColMajor
{
TTS_CONSTEXPR_EQUAL(matrixXf::IsRowMajor, MatrixXf::IsRowMajor);
TTS_CONSTEXPR_EQUAL((matrix<float, -1, -1, rotgen::RowMajor>::IsRowMajor),
(Matrix<float, -1, -1, Eigen::RowMajor>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((matrix<float, -1, 7, rotgen::RowMajor>::IsRowMajor),
(Matrix<float, -1, 7, Eigen::RowMajor>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((matrix<float, 7, -1, rotgen::RowMajor>::IsRowMajor),
(Matrix<float, 7, -1, Eigen::RowMajor>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((matrix<float, 9, 1>::IsRowMajor),
(Matrix<float, 9, 1>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(row_vectorXf::IsRowMajor, RowVectorXf::IsRowMajor);
TTS_CONSTEXPR_EQUAL((matrix<float, 1, 9>::IsRowMajor),
(Matrix<float, 1, 9>::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<matrixXf>, Map<MatrixXf>>();
check_size_properties<map<matrix<float, -1, -1, 0, 3, 3>>,
Map<Matrix<float, -1, -1, 0, 3, 3>>>();
check_size_properties<map<matrix<float, -1, -1, 0, 3, 3>>,
Map<Matrix<float, -1, -1, 0, 3, 3>>>();
check_size_properties<map<matrix<float, 4, 9>>, Map<Matrix<float, 4, 9>>>();
check_size_properties<map<vector4f>, Map<Vector4f>>();
check_size_properties<map<matrix<float, 1, -1>>, Map<Matrix<float, 1, -1>>>();
check_size_properties<map<row_vector4f>, Map<RowVector4f>>();
check_size_properties<map<matrix<float, -1, 1>>, Map<Matrix<float, -1, 1>>>();
// Row/Col Major
{
TTS_CONSTEXPR_EQUAL((map<matrixXf>::IsRowMajor),
(Map<MatrixXf>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(map<matrix<float, -1, -1, rotgen::RowMajor>>::IsRowMajor),
(Map<Matrix<float, -1, -1, Eigen::RowMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(map<matrix<float, -1, -1, rotgen::ColMajor>>::IsRowMajor),
(Map<Matrix<float, -1, -1, Eigen::ColMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((map<vectorXf>::IsRowMajor),
(Map<VectorXf>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((map<row_vectorXf>::IsRowMajor),
(Map<RowVectorXf>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(map<matrix<float, -1, 5, rotgen::RowMajor>>::IsRowMajor),
(Map<Matrix<float, -1, 5, Eigen::RowMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(map<matrix<float, -1, 7, rotgen::ColMajor>>::IsRowMajor),
(Map<Matrix<float, -1, 7, Eigen::ColMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(map<matrix<float, 5, -1, rotgen::RowMajor>>::IsRowMajor),
(Map<Matrix<float, 5, -1, Eigen::RowMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(map<matrix<float, 7, -1, rotgen::ColMajor>>::IsRowMajor),
(Map<Matrix<float, 7, -1, Eigen::ColMajor>>::IsRowMajor));
}
};
TTS_CASE("Compile-Time informations conformance w/r to Eigen - block")
{
using namespace rotgen;
using namespace Eigen;
check_size_properties<block<matrixXf>, Block<MatrixXf>>();
check_size_properties<block<matrix<float, 2, 4>>,
Block<Matrix<float, 2, 4>>>();
check_size_properties<block<matrixXf, 3, 6>, Block<MatrixXf, 3, 6>>();
check_size_properties<block<matrix<float, 8, 8>, 3, 6>,
Block<Matrix<float, 8, 8>, 3, 6>>();
check_size_properties<block<matrixXf, 1, 6>, Block<MatrixXf, 1, 6>>();
check_size_properties<block<matrix<float, 8, 8>, 1, 6>,
Block<Matrix<float, 8, 8>, 1, 6>>();
check_size_properties<block<matrixXf, 7, 1>, Block<MatrixXf, 7, 1>>();
check_size_properties<block<matrix<float, 8, 8>, 7, 1>,
Block<Matrix<float, 8, 8>, 7, 1>>();
check_size_properties<block<map<matrixXf>>, Block<Map<MatrixXf>>>();
check_size_properties<block<map<matrix<float, 2, 4>>>,
Block<Map<Matrix<float, 2, 4>>>>();
check_size_properties<block<map<matrixXf>, 3, 6>,
Block<Map<MatrixXf>, 3, 6>>();
check_size_properties<block<map<matrix<float, 8, 8>>, 3, 6>,
Block<Map<Matrix<float, 8, 8>>, 3, 6>>();
check_size_properties<block<map<matrixXf>, 1, 6>,
Block<Map<MatrixXf>, 1, 6>>();
check_size_properties<block<map<matrix<float, 8, 8>>, 1, 6>,
Block<Map<Matrix<float, 8, 8>>, 1, 6>>();
check_size_properties<block<map<matrixXf>, 7, 1>,
Block<Map<MatrixXf>, 7, 1>>();
check_size_properties<block<map<matrix<float, 8, 8>>, 7, 1>,
Block<Map<Matrix<float, 8, 8>>, 7, 1>>();
// Row/Col Major
{
TTS_CONSTEXPR_EQUAL((block<matrixXf>::IsRowMajor),
(Block<MatrixXf>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((block<matrixXf, 1, 8>::IsRowMajor),
(Block<MatrixXf, 1, 8>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((block<matrixXf, 8, 1>::IsRowMajor),
(Block<MatrixXf, 8, 1>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(block<matrix<float, -1, -1, rotgen::RowMajor>>::IsRowMajor),
(Block<Matrix<float, -1, -1, Eigen::RowMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(block<matrix<float, -1, -1, rotgen::ColMajor>>::IsRowMajor),
(Block<Matrix<float, -1, -1, Eigen::ColMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((block<vectorXf>::IsRowMajor),
(Block<VectorXf>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((block<row_vectorXf>::IsRowMajor),
(Block<RowVectorXf>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((block<vectorXf, 1, 8>::IsRowMajor),
(Block<VectorXf, 1, 8>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((block<row_vectorXf, 8, 1>::IsRowMajor),
(Block<RowVectorXf, 8, 1>::IsRowMajor));
}
};
TTS_CASE("Compile-Time informations conformance w/r to Eigen - ref")
{
using namespace rotgen;
using namespace Eigen;
check_size_properties<ref<matrixXf>, Ref<MatrixXf>>();
check_size_properties<ref<matrix<float, -1, -1, 0, 3, 3>>,
Ref<Matrix<float, -1, -1, 0, 3, 3>>>();
check_size_properties<ref<matrix<float, 4, 9>>, Ref<Matrix<float, 4, 9>>>();
check_size_properties<ref<vector4f>, Ref<Vector4f>>();
check_size_properties<ref<matrix<float, 1, -1>>, Ref<Matrix<float, 1, -1>>>();
check_size_properties<ref<row_vector4f>, Ref<RowVector4f>>();
check_size_properties<ref<matrix<float, -1, 1>>, Ref<Matrix<float, -1, 1>>>();
// Row/Col Major
{
TTS_CONSTEXPR_EQUAL((ref<matrixXf>::IsRowMajor),
(Ref<MatrixXf>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(ref<matrix<float, -1, -1, rotgen::RowMajor>>::IsRowMajor),
(Ref<Matrix<float, -1, -1, Eigen::RowMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(ref<matrix<float, -1, -1, rotgen::ColMajor>>::IsRowMajor),
(Ref<Matrix<float, -1, -1, Eigen::ColMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((ref<vectorXf>::IsRowMajor),
(Ref<VectorXf>::IsRowMajor));
TTS_CONSTEXPR_EQUAL((ref<row_vectorXf>::IsRowMajor),
(Ref<RowVectorXf>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(ref<matrix<float, -1, 5, rotgen::RowMajor>>::IsRowMajor),
(Ref<Matrix<float, -1, 5, Eigen::RowMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(ref<matrix<float, -1, 7, rotgen::ColMajor>>::IsRowMajor),
(Ref<Matrix<float, -1, 7, Eigen::ColMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(ref<matrix<float, 5, -1, rotgen::RowMajor>>::IsRowMajor),
(Ref<Matrix<float, 5, -1, Eigen::RowMajor>>::IsRowMajor));
TTS_CONSTEXPR_EQUAL(
(ref<matrix<float, 7, -1, rotgen::ColMajor>>::IsRowMajor),
(Ref<Matrix<float, 7, -1, Eigen::ColMajor>>::IsRowMajor));
}
};

193
test/unit/meta/ref.cpp Normal file
View file

@ -0,0 +1,193 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/rotgen.hpp>
#include "unit/tests.hpp"
using row_matrixXf = rotgen::matrix<float, -1, -1, rotgen::RowMajor>;
template<typename Ref, typename Generator> void check_acceptance(Generator f)
{
auto in = f();
rotgen::matrixXf data;
bool verbose = ::tts::arguments()[{"--verbose"}];
auto acceptor = [&](rotgen::ref<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<Ref const> 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)
<typename T>(::tts::type<T>)
{
TTS_WHEN("Call a function accepting a ref<" << ::tts::typename_<T> << "> ...")
{
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<T>([&]() { return mc; });
check_acceptance<T>([&]() { return vc; });
check_acceptance<T>([&]() { return mr; });
check_acceptance<T>([&]() { return mrr; });
check_acceptance<T>([&]() { return vr; });
check_acceptance<T>([&]() { return vcf; });
check_acceptance<T>([&]() { return vrf; });
}
TTS_AND_THEN("with a vector-like block")
{
check_acceptance<T>([&]() { return rotgen::head(vc, 2); });
check_acceptance<T>([&]() { return rotgen::head(vr, 2); });
check_acceptance<T>([&]() { return rotgen::head(vcf, 2); });
check_acceptance<T>([&]() { return rotgen::head(vrf, 2); });
check_acceptance<T>([&]() { return rotgen::head<2>(vc); });
check_acceptance<T>([&]() { return rotgen::head<2>(vr); });
check_acceptance<T>([&]() { return rotgen::head<2>(vcf); });
check_acceptance<T>([&]() { return rotgen::head<2>(vrf); });
}
TTS_AND_THEN("with a vector-like map")
{
rotgen::map<rotgen::matrixXf> mmc(vc.data(), 2, 1);
rotgen::map<rotgen::matrixXf> mmr(vc.data(), 1, 2);
rotgen::map<row_matrixXf> mmrr(vc.data(), 1, 2);
rotgen::map<rotgen::vectorXf> mvc(vc.data(), vc.size());
rotgen::map<rotgen::row_vectorXf> mvr(vr.data(), vr.size());
rotgen::map<rotgen::vector2f> mvcf(vc.data());
rotgen::map<rotgen::row_vector2f> mvrf(vr.data());
check_acceptance<T>([&]() { return mmc; });
check_acceptance<T>([&]() { return mvc; });
check_acceptance<T>([&]() { return mvr; });
check_acceptance<T>([&]() { return mmr; });
check_acceptance<T>([&]() { return mmrr; });
check_acceptance<T>([&]() { return mvcf; });
check_acceptance<T>([&]() { return mvrf; });
}
TTS_AND_THEN("with a vector-like ref")
{
rotgen::ref<row_matrixXf> mmrr(mrr);
rotgen::ref<rotgen::vectorXf> mvc(mc);
rotgen::ref<rotgen::row_vectorXf> mvr(mc);
rotgen::ref<rotgen::vector2f> mvcf(mc);
rotgen::ref<rotgen::row_vector2f> mvrf(mc);
check_acceptance<T>([&]() { return mvc; });
check_acceptance<T>([&]() { return mvr; });
check_acceptance<T>([&]() { return mmrr; });
check_acceptance<T>([&]() { return mvcf; });
check_acceptance<T>([&]() { return mvrf; });
}
}
};
TTS_CASE("Assert ref construction rules Matrix cases")
{
using MatC = rotgen::matrix<float, -1, -1, rotgen::ColMajor>;
using MatR = rotgen::matrix<float, -1, -1, rotgen::RowMajor>;
TTS_WHEN("Call a function accepting a ref<"
<< ::tts::typename_<MatC> << "> ...")
{
rotgen::matrixXf mc(2, 1);
rotgen::matrixXf mr(1, 2);
rotgen::matrixXf mn(4, 2);
row_matrixXf mnr(4, 2);
rotgen::matrix<float, 2, 1> mcf(2, 1);
rotgen::matrix<float, 1, 2> mrf(1, 2);
rotgen::matrix<float, 4, 2> mnf(4, 2);
TTS_AND_THEN("with a matrix")
{
check_acceptance<MatC>([&]() { return mc; });
check_acceptance<MatC>([&]() { return mr; });
check_acceptance<MatC>([&]() { return mn; });
check_acceptance<MatC>([&]() { return mcf; });
check_acceptance<MatC>([&]() { return mrf; });
check_acceptance<MatC>([&]() { return mnf; });
TTS_EXPECT_COMPILES(mnr, { rotgen::ref<MatC const>{mnr}; });
}
TTS_AND_THEN("with a map")
{
rotgen::map<rotgen::matrixXf> mmc(mc.data(), 2, 1);
rotgen::map<rotgen::matrixXf> mmr(mc.data(), 1, 2);
rotgen::map<row_matrixXf> mmrr(mc.data(), 1, 2);
rotgen::map<row_matrixXf> mmnr(mnr.data(), 4, 2);
rotgen::map<rotgen::vectorXf> mvc(mc.data(), mc.size());
rotgen::map<rotgen::row_vectorXf> mvr(mr.data(), mr.size());
rotgen::map<rotgen::vector2f> mvcf(mc.data());
rotgen::map<rotgen::row_vector2f> mvrf(mr.data());
check_acceptance<MatC>([&]() { return mmc; });
check_acceptance<MatC>([&]() { return mmr; });
check_acceptance<MatC>([&]() { return mvc; });
check_acceptance<MatC>([&]() { return mvr; });
check_acceptance<MatC>([&]() { return mvcf; });
check_acceptance<MatC>([&]() { return mvrf; });
TTS_EXPECT_COMPILES(mmnr, { rotgen::ref<MatC const>{mmnr}; });
TTS_EXPECT_COMPILES(mmrr, { rotgen::ref<MatC const>{mmrr}; });
}
}
TTS_WHEN("Call a function accepting a ref<"
<< ::tts::typename_<MatR> << "> ...")
{
row_matrixXf mc(2, 1);
row_matrixXf mr(1, 2);
row_matrixXf mn(4, 2);
rotgen::matrix<float, 2, 1> mcf(2, 1);
rotgen::matrix<float, 1, 2> mrf(1, 2);
rotgen::matrix<float, 4, 2, rotgen::RowMajor> mnf(4, 2);
TTS_AND_THEN("with a matrix")
{
check_acceptance<MatR>([&]() { return mc; });
check_acceptance<MatR>([&]() { return mr; });
check_acceptance<MatR>([&]() { return mn; });
check_acceptance<MatR>([&]() { return mcf; });
check_acceptance<MatR>([&]() { return mrf; });
check_acceptance<MatR>([&]() { return mnf; });
}
}
};