Implements some missing functions

See merge request oss/rotgen!28
This commit is contained in:
Joel Falcou 2025-09-28 16:15:15 +02:00
parent 5d8a084070
commit b6fcd4b341
34 changed files with 972 additions and 139 deletions

View file

@ -44,6 +44,7 @@ if(ROTGEN_FORCE_DYNAMIC)
src/matrix.cpp src/matrix.cpp
src/block.cpp src/block.cpp
src/info.cpp src/info.cpp
src/svd.cpp
src/operators.cpp src/operators.cpp
) )
else() else()

View file

@ -32,7 +32,7 @@ While the command `cmake -DROTGEN_FORCE_DYNAMIC=ON` will output:
```bash ```bash
-- ==================== Rotgen Configuration Summary ==================== -- ==================== Rotgen Configuration Summary ====================
-- Configuration mode: DYNAMIC -- Configuration mode: DYNAMIC
-- Reason : No static size options were provided -- Reason : No static size options were provided
-- Preprocessor flags: -DROTGEN_FORCE_DYNAMIC -- Preprocessor flags: -DROTGEN_FORCE_DYNAMIC
-- ====================================================================== -- ======================================================================
-- Configuring done (0.0s) -- Configuring done (0.0s)
@ -64,7 +64,7 @@ Supported scalar types are `float` and `double`.
+ Data generation interface (i.e `matrix::Zero`, etc...) + Data generation interface (i.e `matrix::Zero`, etc...)
+ Reductions (sum, prod, norms) + Reductions (sum, prod, norms)
+ Resizing and conservative resizing + Resizing and conservative resizing
## Project status ## Project status
### Current Releases ### Current Releases
+ 08/2025 - Version 0.0.1beta + 08/2025 - Version 0.0.1beta
@ -74,7 +74,7 @@ Supported scalar types are `float` and `double`.
+ Support `array` and related operations. + Support `array` and related operations.
+ Support non-trivial indexing. + Support non-trivial indexing.
+ Precompile and provide free functions API for common linear algebra solvers. + Precompile and provide free functions API for common linear algebra solvers.
## License ## License
**ROTGEN** is licensed under the Boost Software License **ROTGEN** is licensed under the Boost Software License

View file

@ -58,7 +58,7 @@ function(print_configuration_summary FORCE_DYNAMIC_VAR FORCE_CONFIG_REASON MAX_S
if(${FORCE_DYNAMIC_VAR}) if(${FORCE_DYNAMIC_VAR})
message(STATUS " Configuration mode: DYNAMIC") message(STATUS " Configuration mode: DYNAMIC")
if(${FORCE_CONFIG_REASON}) if(${FORCE_CONFIG_REASON})
message(STATUS " Reason : No static size options were provided") message(STATUS " Reason : No static size options were provided")
endif() endif()
else() else()
message(STATUS " Configuration mode: STATIC") message(STATUS " Configuration mode: STATIC")

View file

@ -17,13 +17,14 @@
namespace rotgen namespace rotgen
{ {
// Primary template: mutable ref // Primary template: mutable ref
template<typename T, int Options = T::storage_order, typename Stride = stride> template<typename T, int Options, typename Stride>
class ref : private map<T, Options, Stride> class ref : private map<T, Options, Stride>
{ {
public: public:
using parent = map<T, Options, Stride>; using parent = map<T, Options, Stride>;
using value_type = typename T::value_type; using value_type = typename T::value_type;
using rotgen_tag = void; using rotgen_tag = void;
using rotgen_ref_tag = void;
static constexpr int storage_order = T::storage_order; static constexpr int storage_order = T::storage_order;
static constexpr int RowsAtCompileTime = T::RowsAtCompileTime; static constexpr int RowsAtCompileTime = T::RowsAtCompileTime;
@ -42,6 +43,7 @@ namespace rotgen
using parent::prod; using parent::prod;
using parent::mean; using parent::mean;
using parent::trace; using parent::trace;
using parent::transpose;
using parent::cwiseAbs; using parent::cwiseAbs;
using parent::cwiseAbs2; using parent::cwiseAbs2;
using parent::cwiseInverse; using parent::cwiseInverse;
@ -49,6 +51,7 @@ namespace rotgen
using parent::maxCoeff; using parent::maxCoeff;
using parent::minCoeff; using parent::minCoeff;
using parent::norm; using parent::norm;
using parent::normalize;
using parent::squaredNorm; using parent::squaredNorm;
using parent::lpNorm; using parent::lpNorm;
using parent::operator+=; using parent::operator+=;
@ -59,6 +62,10 @@ namespace rotgen
using parent::Constant; using parent::Constant;
using parent::Random; using parent::Random;
using parent::Identity; using parent::Identity;
using parent::setZero;
using parent::setConstant;
using parent::setRandom;
using parent::setIdentity;
using parent::operator=; using parent::operator=;
@ -74,6 +81,12 @@ namespace rotgen
static_assert((O & 1) == storage_order, "ref: Incompatible storage layout"); static_assert((O & 1) == storage_order, "ref: Incompatible storage layout");
} }
template<typename Ref, int R, int C, bool I>
ref(block<Ref,R,C,I>&& b) : parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()})
{
static_assert((Ref::storage_order & 1) == storage_order, "ref: Incompatible storage layout");
}
template<typename Ref, int R, int C, bool I> template<typename Ref, int R, int C, bool I>
ref(block<Ref,R,C,I>& b) : parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()}) ref(block<Ref,R,C,I>& b) : parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()})
{ {
@ -120,6 +133,7 @@ namespace rotgen
using parent::prod; using parent::prod;
using parent::mean; using parent::mean;
using parent::trace; using parent::trace;
using parent::transpose;
using parent::cwiseAbs; using parent::cwiseAbs;
using parent::cwiseAbs2; using parent::cwiseAbs2;
using parent::cwiseInverse; using parent::cwiseInverse;
@ -127,6 +141,7 @@ namespace rotgen
using parent::maxCoeff; using parent::maxCoeff;
using parent::minCoeff; using parent::minCoeff;
using parent::norm; using parent::norm;
using parent::normalize;
using parent::squaredNorm; using parent::squaredNorm;
using parent::lpNorm; using parent::lpNorm;
using parent::operator+=; using parent::operator+=;
@ -201,18 +216,36 @@ namespace rotgen
return 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> 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) auto operator-(ref<A,O,S> lhs, ref<B,P,T> rhs)
{ {
return 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> 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) auto operator*(ref<A,O,S> lhs, ref<B,P,T> rhs)
{ {
return 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> template<typename A, int O, typename S>
auto operator*(ref<A,O,S> lhs, std::convertible_to<typename A::value_type> auto s) auto operator*(ref<A,O,S> lhs, std::convertible_to<typename A::value_type> auto s)
{ {
@ -297,6 +330,18 @@ namespace rotgen
return 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 // Convert entity/eigen types to a proper ref so we can write less function overloads
template<typename T> struct generalize; template<typename T> struct generalize;
@ -314,10 +359,28 @@ namespace rotgen
template<concepts::entity T> struct generalize<T> template<concepts::entity T> struct generalize<T>
{ {
static constexpr bool is_const = std::is_const_v<T>; static constexpr bool is_const = std::is_const_v<T>;
using base = matrix<typename T::value_type,Dynamic,Dynamic,T::storage_order>; 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>>; 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> template<concepts::entity T>
typename T::parent const& base_of(T const& a) typename T::parent const& base_of(T const& a)
{ {
@ -335,12 +398,18 @@ namespace rotgen
{ {
static constexpr bool is_const = std::is_const_v<T>; static constexpr bool is_const = std::is_const_v<T>;
using concrete_type = decltype(std::declval<T>().eval()); using concrete_type = decltype(std::declval<T>().eval());
using base = matrix<typename T::Scalar,Dynamic,Dynamic,concrete_type::Options&1>; 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>>; using type = std::conditional_t<is_const,ref<base const>, ref<base>>;
}; };
template<concepts::eigen_compatible T> template<concepts::eigen_compatible T>
T const& base_of(T const& a) auto const& base_of(T const& a)
{
return a;
}
template<concepts::eigen_compatible T>
auto& base_of(T& a)
{ {
return a; return a;
} }

View file

@ -9,6 +9,24 @@
namespace rotgen::concepts namespace rotgen::concepts
{ {
//================================================================================================
//! @brief Check if a type is a Rotgen reference.
//================================================================================================
template<typename T>
concept reference = requires { typename std::remove_cvref_t<T>::rotgen_ref_tag; };
//================================================================================================
//! @brief Check if a type is a vector.
//================================================================================================
template<typename T>
concept vector = T::IsVectorAtCompileTime;
//================================================================================================
//! @brief Check if a type is a 3D vector.
//================================================================================================
template<typename T, int N>
concept vectorND = vector<T> && (T::RowsAtCompileTime == N || T::ColsAtCompileTime == N);
//================================================================================================ //================================================================================================
//! @brief Check if a type is a ROTGEN type. //! @brief Check if a type is a ROTGEN type.
//================================================================================================ //================================================================================================
@ -25,12 +43,12 @@ namespace rotgen::concepts
template<typename T> template<typename T>
concept eigen_compatible = requires(T const& a) concept eigen_compatible = requires(T const& a)
{ {
typename T::Scalar; typename std::remove_cvref_t<T>::Scalar;
{ T::RowsAtCompileTime } -> std::convertible_to<int>; { std::remove_cvref_t<T>::RowsAtCompileTime } -> std::convertible_to<int>;
{ T::ColsAtCompileTime } -> std::convertible_to<int>; { std::remove_cvref_t<T>::ColsAtCompileTime } -> std::convertible_to<int>;
{ T::MaxRowsAtCompileTime } -> std::convertible_to<int>; { std::remove_cvref_t<T>::MaxRowsAtCompileTime } -> std::convertible_to<int>;
{ T::MaxColsAtCompileTime } -> std::convertible_to<int>; { std::remove_cvref_t<T>::MaxColsAtCompileTime } -> std::convertible_to<int>;
{ a.eval() }; { a.eval() };
}; };

View file

@ -22,6 +22,11 @@ namespace rotgen
return w == -1 ? 0 : w / 8; return w == -1 ? 0 : w / 8;
}(); }();
inline constexpr int ComputeFullU = 0x04;
inline constexpr int ComputeThinU = 0x08;
inline constexpr int ComputeFullV = 0x10;
inline constexpr int ComputeThinV = 0x20;
inline constexpr int Dynamic = -1; inline constexpr int Dynamic = -1;
inline constexpr int Infinity = -1; inline constexpr int Infinity = -1;
inline constexpr int AutoAlign = 0; inline constexpr int AutoAlign = 0;

View file

@ -15,6 +15,9 @@
namespace rotgen namespace rotgen
{ {
template<typename T, int Options = T::storage_order, typename Stride = stride>
class ref;
template<typename Ref, int Rows = Dynamic, int Cols = Dynamic, bool Inner = false> template<typename Ref, int Rows = Dynamic, int Cols = Dynamic, bool Inner = false>
class block : public find_block<Ref> class block : public find_block<Ref>
{ {
@ -55,7 +58,7 @@ namespace rotgen
block(Ref const& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) block(Ref const& 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) requires( !requires{typename Ref::rotgen_block_tag; } && is_immutable)
: parent(r,i0,j0,ni,nj) : parent(r.base(),i0,j0,ni,nj)
{} {}
block(Ref const& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) block(Ref const& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
@ -65,7 +68,7 @@ namespace rotgen
block(Ref const& r, std::size_t i0, std::size_t j0) 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) requires(!requires{typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && is_immutable)
: parent(r,i0,j0,Rows,Cols) : parent(r.base(),i0,j0,Rows,Cols)
{} {}
block(Ref const& r, std::size_t i0, std::size_t j0) block(Ref const& r, std::size_t i0, std::size_t j0)
@ -75,7 +78,7 @@ namespace rotgen
block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) 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) requires( !requires{typename Ref::rotgen_block_tag; } && !is_immutable)
: parent(r,i0,j0,ni,nj) : parent(r.base(),i0,j0,ni,nj)
{} {}
block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
@ -85,7 +88,7 @@ namespace rotgen
block(Ref& r, std::size_t i0, std::size_t j0) block(Ref& r, std::size_t i0, std::size_t j0)
requires(!requires{typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && !is_immutable) requires(!requires{typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && !is_immutable)
: parent(r,i0,j0,Rows,Cols) : parent(r.base(),i0,j0,Rows,Cols)
{} {}
block(Ref& r, std::size_t i0, std::size_t j0) block(Ref& r, std::size_t i0, std::size_t j0)

View file

@ -136,13 +136,33 @@ namespace rotgen
concrete_type cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); } concrete_type cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); }
concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); } concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); }
concrete_type cwiseSqrt() const { return concrete_type(base().cwiseSqrt()); } concrete_type cwiseSqrt() const { return concrete_type(base().cwiseSqrt()); }
concrete_type cwiseMin (map const& rhs) const { return concrete_type(base().cwiseMin(rhs.base())); } concrete_type cwiseMin(map const& rhs) const { return concrete_type(base().cwiseMin(rhs.base())); }
concrete_type cwiseMax (map const& rhs) const { return concrete_type(base().cwiseMax(rhs.base())); } concrete_type cwiseMax(map const& rhs) const { return concrete_type(base().cwiseMax(rhs.base())); }
concrete_type cwiseQuotient (map const& rhs) const { return concrete_type(base().cwiseQuotient(rhs.base())); } concrete_type cwiseQuotient(map const& rhs) const { return concrete_type(base().cwiseQuotient(rhs.base())); }
concrete_type cwiseProduct(map const& rhs) const { return concrete_type(base().cwiseProduct(rhs.base())); } concrete_type cwiseProduct(map const& rhs) const { return concrete_type(base().cwiseProduct(rhs.base())); }
concrete_type cwiseMin(value_type s) const { return concrete_type(base().cwiseMin(s)); } concrete_type cwiseMin(value_type s) const { return concrete_type(base().cwiseMin(s)); }
concrete_type cwiseMax(value_type s) const { return concrete_type(base().cwiseMax(s)); } concrete_type cwiseMax(value_type s) const { return concrete_type(base().cwiseMax(s)); }
concrete_type inverse() const { return concrete_type(base().inverse()); }
concrete_type cross(map const& other) const
{
concrete_type that;
if constexpr(RowsAtCompileTime==-1)
{
that(0,0) = (*this)(1,0) * other(2,0) - (*this)(2,0) * other(1,0);
that(1,0) = (*this)(2,0) * other(0,0) - (*this)(0,0) * other(2,0);
that(2,0) = (*this)(0,0) * other(1,0) - (*this)(1,0) * other(0,0);
}
else
{
that(0,0) = (*this)(0,1) * other(0,2) - (*this)(0,2) * other(0,1);
that(0,1) = (*this)(0,2) * other(0,0) - (*this)(0,0) * other(0,2);
that(0,2) = (*this)(0,0) * other(0,1) - (*this)(0,1) * other(0,0);
}
return that;
}
void normalize() requires(!is_immutable && IsVectorAtCompileTime) void normalize() requires(!is_immutable && IsVectorAtCompileTime)
{ {
parent::normalize(); parent::normalize();
@ -150,15 +170,17 @@ namespace rotgen
void transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); } void transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); }
void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); } void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); }
map& operator+=(map const& rhs) requires(!is_immutable) template<typename R2, int O2, typename S2>
map& operator+=(map<R2,O2,S2> const& rhs) requires(!is_immutable)
{ {
base() += static_cast<parent const&>(rhs); base() += rhs.base();
return *this; return *this;
} }
map& operator-=(map const& rhs) requires(!is_immutable) template<typename R2, int O2, typename S2>
map& operator-=(map<R2,O2,S2> const& rhs) requires(!is_immutable)
{ {
base() -= static_cast<parent const&>(rhs); base() -= rhs.base();
return *this; return *this;
} }
@ -167,9 +189,10 @@ namespace rotgen
return concrete_type(base().operator-()); return concrete_type(base().operator-());
} }
map& operator*=(map const& rhs) requires(!is_immutable) template<typename R2, int O2, typename S2>
map& operator*=(map<R2,O2,S2> const& rhs) requires(!is_immutable)
{ {
base() *= static_cast<parent const&>(rhs); base() *= rhs.base();
return *this; return *this;
} }
@ -297,22 +320,26 @@ namespace rotgen
template<typename R1, typename R2, int O1, typename S1, int O2, typename S2> template<typename R1, typename R2, int O1, typename S1, int O2, typename S2>
typename map<R1,O1,S1>::concrete_type operator+(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs) typename map<R1,O1,S1>::concrete_type operator+(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs)
{ {
using concrete_type = typename map<R1,O1,S1>::concrete_type; // REPLICATE TODO
return concrete_type(lhs.base().add(map<R1,O1,S1>(rhs))); using map_type = map<R1 const,O1,S1>;
using concrete_type = typename map_type::concrete_type;
return concrete_type(map_type(lhs).base().add(map_type(rhs)));
} }
template<typename R1, typename R2, int O1, typename S1, int O2, typename S2> template<typename R1, typename R2, int O1, typename S1, int O2, typename S2>
typename map<R1,O1,S1>::concrete_type operator-(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs) typename map<R1,O1,S1>::concrete_type operator-(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs)
{ {
using concrete_type = typename map<R1,O1,S1>::concrete_type; using map_type = map<R1 const,O1,S1>;
return concrete_type(lhs.base().sub(map<R1,O1,S1>(rhs))); using concrete_type = typename map_type::concrete_type;
return concrete_type(map_type(lhs).base().sub(map_type(rhs)));
} }
template<typename R1, typename R2, int O1, typename S1, int O2, typename S2> template<typename R1, typename R2, int O1, typename S1, int O2, typename S2>
typename map<R1,O1,S1>::concrete_type operator*(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs) typename map<R1,O1,S1>::concrete_type operator*(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs)
{ {
using concrete_type = typename map<R1,O1,S1>::concrete_type; using map_type = map<R1 const,O1,S1>;
return concrete_type(lhs.base().mul(map<R1,O1,S1>(rhs))); using concrete_type = typename map_type::concrete_type;
return concrete_type(map_type(lhs).base().mul(map_type(rhs)));
} }
template<typename R, int O, typename S> template<typename R, int O, typename S>

View file

@ -29,6 +29,7 @@ namespace rotgen
static constexpr auto storage_order = Opts & 1; static constexpr auto storage_order = Opts & 1;
static constexpr Index RowsAtCompileTime = Rows; static constexpr Index RowsAtCompileTime = Rows;
static constexpr Index ColsAtCompileTime = Cols; static constexpr Index ColsAtCompileTime = Cols;
static constexpr bool IsCompileTimeSized = Rows != -1 && Cols != -1;
static constexpr bool IsVectorAtCompileTime = (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1); static constexpr bool IsVectorAtCompileTime = (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1);
static constexpr int Options = Opts; static constexpr int Options = Opts;
static constexpr bool IsRowMajor = (Opts & RowMajor) == RowMajor; static constexpr bool IsRowMajor = (Opts & RowMajor) == RowMajor;
@ -37,7 +38,8 @@ namespace rotgen
matrix() : parent(Rows==-1?0:Rows,Cols==-1?0:Cols) {} matrix() : parent(Rows==-1?0:Rows,Cols==-1?0:Cols) {}
matrix(Index r, Index c) : parent(r, c) matrix(Index r, Index c) requires(!IsCompileTimeSized)
: parent(r, c)
{ {
if constexpr(Rows != -1) assert(r == Rows && "Mismatched between dynamic and static row size"); if constexpr(Rows != -1) assert(r == Rows && "Mismatched between dynamic and static row size");
if constexpr(Cols != -1) assert(c == Cols && "Mismatched between dynamic and static column size"); if constexpr(Cols != -1) assert(c == Cols && "Mismatched between dynamic and static column size");
@ -49,6 +51,11 @@ namespace rotgen
matrix(Scalar v) requires(Rows == 1 && Cols == 1) : parent(1,1,{v}) {} matrix(Scalar v) requires(Rows == 1 && Cols == 1) : parent(1,1,{v}) {}
matrix(Scalar v0, Scalar v1, auto... vs)
requires((Rows == (2+sizeof...(vs)) && Cols == 1) || (Rows == 1 && Cols == (2+sizeof...(vs))))
: parent(Rows,Cols,{v0,v1,static_cast<Scalar>(vs)...})
{}
matrix(parent const& base) : parent(base) {} matrix(parent const& base) : parent(base) {}
matrix(std::initializer_list<std::initializer_list<Scalar>> init) : parent(init) matrix(std::initializer_list<std::initializer_list<Scalar>> init) : parent(init)
@ -129,9 +136,9 @@ namespace rotgen
return matrix(base().normalized()); return matrix(base().normalized());
} }
matrix transpose() const matrix<Scalar,ColsAtCompileTime,RowsAtCompileTime,storage_order> transpose() const
{ {
return matrix(base().transpose()); return matrix<Scalar,ColsAtCompileTime,RowsAtCompileTime,storage_order>(base().transpose());
} }
matrix conjugate() const matrix conjugate() const
@ -139,9 +146,9 @@ namespace rotgen
return matrix(base().conjugate()); return matrix(base().conjugate());
} }
matrix adjoint() const matrix<Scalar,ColsAtCompileTime,RowsAtCompileTime,storage_order> adjoint() const
{ {
return matrix(base().adjoint()); return matrix<Scalar,ColsAtCompileTime,RowsAtCompileTime,storage_order>(base().adjoint());
} }
void normalize() requires(IsVectorAtCompileTime) void normalize() requires(IsVectorAtCompileTime)

View file

@ -0,0 +1,36 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/impl/svd.hpp>
namespace rotgen
{
template<typename M>
struct svd : find_svd<typename M::value_type,M::Options>
{
using parent = find_svd<typename M::value_type,M::Options>;
using m_type = matrix<typename M::value_type,Dynamic,Dynamic,M::Options>;
using d_type = matrix<typename M::value_type,M::ColsAtCompileTime,1>;
svd(M const& m, int options = ComputeThinU | ComputeThinV) : parent(m,options) {}
int rank() const { return parent::rank(); }
m_type U() const { return parent::U(); }
m_type D() const { return parent::D(); }
m_type V() const { return parent::V(); }
d_type singular_values() const { return parent::singular_values(); }
m_type U(int r) const { return parent::U(r); }
m_type D(int r) const { return parent::D(r); }
m_type V(int r) const { return parent::V(r); }
m_type singular_values(int r) const { return parent::singular_values(r); }
};
}

View file

@ -30,6 +30,12 @@ namespace rotgen
detail::validate_extract(e,i0,j0,ni,nj); detail::validate_extract(e,i0,j0,ni,nj);
return block<Entity>(e, i0, j0, ni, nj); return block<Entity>(e, i0, j0, ni, nj);
} }
template<concepts::entity Entity>
auto extract(Entity const& e, Index i0, Index j0, Index ni, Index nj)
{
detail::validate_extract(e,i0,j0,ni,nj);
return block<Entity const>(e, i0, j0, ni, nj);
}
template<Index NI, Index NJ, concepts::entity Entity> template<Index NI, Index NJ, concepts::entity Entity>
requires(NI!=-1 && NJ!=-1) requires(NI!=-1 && NJ!=-1)

View file

@ -12,6 +12,9 @@
namespace rotgen namespace rotgen
{ {
template<typename T, int Options = T::storage_order, typename Stride = stride>
class ref;
namespace detail namespace detail
{ {
template<typename Ref, int Rows, int Cols, bool Inner, bool IsConst> template<typename Ref, int Rows, int Cols, bool Inner, bool IsConst>
@ -25,6 +28,12 @@ namespace rotgen
>; >;
}; };
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> template<typename Ref, int Rows, int Cols, bool Inner, bool IsConst>
using block_type = typename compute_block_type<Ref,Rows,Cols,Inner,IsConst>::type; using block_type = typename compute_block_type<Ref,Rows,Cols,Inner,IsConst>::type;
} }
@ -46,7 +55,7 @@ namespace rotgen
using value_type = typename parent::value_type; using value_type = typename parent::value_type;
using Index = typename parent::Index; using Index = typename parent::Index;
static constexpr int storage_order = (ForceStorageOrder == -1) ? Ref::storage_order : ForceStorageOrder; static constexpr int storage_order = (ForceStorageOrder == -1) ? Ref::storage_order : ForceStorageOrder;
static constexpr bool is_immutable = std::is_const_v<Ref>; static constexpr bool is_immutable = std::is_const_v<Ref>;
static constexpr bool IsRowMajor = parent::IsRowMajor; static constexpr bool IsRowMajor = parent::IsRowMajor;
@ -57,7 +66,6 @@ namespace rotgen
template<typename ET> template<typename ET>
using as_concrete_type = as_concrete_t<ET, matrix>; using as_concrete_type = as_concrete_t<ET, matrix>;
static constexpr auto Flags = Ref::Flags;
static constexpr int Options = Ref::Options; static constexpr int Options = Ref::Options;
static constexpr int RowsAtCompileTime = Rows; static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols; static constexpr int ColsAtCompileTime = Cols;
@ -72,26 +80,48 @@ namespace rotgen
block& operator=(const block&) = default; block& operator=(const block&) = default;
block& operator=(block&&) = default; block& operator=(block&&) = default;
// Constructs from regular Ref
block(Ref const& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) block(Ref const& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
requires(is_immutable) requires(is_immutable && !concepts::reference<Ref>)
: parent(r.base(),i0,j0,ni,nj) : parent(r.base(),i0,j0,ni,nj)
{} {}
block(Ref const& r, std::size_t i0, std::size_t j0) block(Ref const& r, std::size_t i0, std::size_t j0)
requires(Rows != -1 && Cols != -1 && is_immutable) requires(Rows != -1 && Cols != -1 && is_immutable && !concepts::reference<Ref>)
: parent(r.base(),i0,j0,Rows,Cols) : parent(r.base(),i0,j0,Rows,Cols)
{} {}
block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
requires(!is_immutable) requires(!is_immutable && !concepts::reference<Ref>)
: parent(r.base(),i0,j0,ni,nj) : parent(r.base(),i0,j0,ni,nj)
{} {}
block(Ref& r, std::size_t i0, std::size_t j0) block(Ref& r, std::size_t i0, std::size_t j0)
requires(Rows != -1 && Cols != -1 && !is_immutable) requires(Rows != -1 && Cols != -1 && !is_immutable && !concepts::reference<Ref>)
: parent(r.base(),i0,j0,Rows,Cols) : parent(r.base(),i0,j0,Rows,Cols)
{} {}
// Constructs from rotgen::ref<T>
block(Ref const& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
requires(is_immutable && concepts::reference<Ref>)
: parent(r.base().base(),i0,j0,ni,nj)
{}
block(Ref const& r, std::size_t i0, std::size_t j0)
requires(Rows != -1 && Cols != -1 && is_immutable && concepts::reference<Ref>)
: parent(r.base().base(),i0,j0,Rows,Cols)
{}
block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
requires(!is_immutable && concepts::reference<Ref>)
: parent(r.base().base(),i0,j0,ni,nj)
{}
block(Ref& r, std::size_t i0, std::size_t j0)
requires(Rows != -1 && Cols != -1 && !is_immutable && concepts::reference<Ref>)
: parent(r.base().base(),i0,j0,Rows,Cols)
{}
template<typename B, Index R, Index C, bool I, int FS> template<typename B, Index R, Index C, bool I, int FS>
block(block<B,R,C,I,FS> const& other) : parent(other.base()) block(block<B,R,C,I,FS> const& other) : parent(other.base())
{} {}

View file

@ -39,7 +39,6 @@ namespace rotgen
using value_type = typename std::remove_const_t<Ref>::value_type; using value_type = typename std::remove_const_t<Ref>::value_type;
using concrete_type = typename std::remove_const_t<Ref>::concrete_type; using concrete_type = typename std::remove_const_t<Ref>::concrete_type;
static constexpr auto Flags = Ref::Flags;
static constexpr Index RowsAtCompileTime = Ref::RowsAtCompileTime; static constexpr Index RowsAtCompileTime = Ref::RowsAtCompileTime;
static constexpr Index ColsAtCompileTime = Ref::ColsAtCompileTime; static constexpr Index ColsAtCompileTime = Ref::ColsAtCompileTime;
static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime; static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime;
@ -131,21 +130,24 @@ namespace rotgen
value_type operator()(Index i) const requires(IsVectorAtCompileTime) { return base().data()[i]; } value_type operator()(Index i) const requires(IsVectorAtCompileTime) { return base().data()[i]; }
value_type operator[](Index i) const requires(IsVectorAtCompileTime) { return (*this)(i); } value_type operator[](Index i) const requires(IsVectorAtCompileTime) { return (*this)(i); }
map& operator+=(map const& rhs) template<typename R2, int O2, typename S2>
map& operator+=(map<R2,O2,S2> const& rhs) requires(!is_immutable)
{ {
base() += rhs.base(); base() += rhs.base();
return *this; return *this;
} }
map& operator-=(map const& rhs) template<typename R2, int O2, typename S2>
map& operator-=(map<R2,O2,S2> const& rhs) requires(!is_immutable)
{ {
base() -= rhs.base(); base() -= rhs.base();
return *this; return *this;
} }
map& operator*=(map const& rhs) template<typename R2, int O2, typename S2>
map& operator*=(map<R2,O2,S2> const& rhs) requires(!is_immutable)
{ {
base() *= rhs; base() *= rhs.base();
return *this; return *this;
} }
@ -221,6 +223,18 @@ namespace rotgen
else return base().cwiseSqrt(); else return base().cwiseSqrt();
} }
auto cross(map const& rhs) const
{
if constexpr(!use_expression_templates) return concrete_type{parent::cross(rhs.base())};
else return base().cross(rhs.base());
}
auto inverse() const
{
if constexpr(use_expression_templates) return base().inverse();
else return as_concrete_type<decltype(base().inverse())>(base().inverse());
}
auto normalized() const requires(IsVectorAtCompileTime) auto normalized() const requires(IsVectorAtCompileTime)
{ {
if constexpr(use_expression_templates) return base().normalized(); if constexpr(use_expression_templates) return base().normalized();
@ -253,7 +267,7 @@ namespace rotgen
void transposeInPlace() { base().transposeInPlace(); } void transposeInPlace() { base().transposeInPlace(); }
void adjointInPlace() { base().adjointInPlace(); } void adjointInPlace() { base().adjointInPlace(); }
auto qr_solve(map const& rhs) const auto qr_solve(auto const& rhs) const
{ {
return concrete_type(base().colPivHouseholderQr().solve(rhs.base())); return concrete_type(base().colPivHouseholderQr().solve(rhs.base()));
}; };

View file

@ -38,9 +38,9 @@ namespace rotgen
using concrete_type = matrix; using concrete_type = matrix;
using concrete_dynamic_type = matrix<value_type>; using concrete_dynamic_type = matrix<value_type>;
static constexpr auto Flags = parent::Flags;
static constexpr int RowsAtCompileTime = Rows; static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols; static constexpr int ColsAtCompileTime = Cols;
static constexpr bool IsCompileTimeSized = Rows != -1 && Cols != -1;
static constexpr bool IsVectorAtCompileTime = (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1); static constexpr bool IsVectorAtCompileTime = (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1);
static constexpr int Options = parent::Options; static constexpr int Options = parent::Options;
static constexpr bool IsRowMajor = parent::IsRowMajor; static constexpr bool IsRowMajor = parent::IsRowMajor;
@ -55,7 +55,7 @@ namespace rotgen
matrix() requires(has_static_storage) {} matrix() requires(has_static_storage) {}
matrix() requires(!has_static_storage) : parent(Rows > 0 ? Rows : 0, Cols > 0 ? Cols : 0){} matrix() requires(!has_static_storage) : parent(Rows > 0 ? Rows : 0, Cols > 0 ? Cols : 0){}
matrix(Index r, Index c) : parent(r, c) {} matrix(Index r, Index c) requires(!IsCompileTimeSized) : parent(r, c) {}
matrix(const matrix& other) = default; matrix(const matrix& other) = default;
matrix(matrix&& other) = default; matrix(matrix&& other) = default;
@ -94,6 +94,11 @@ namespace rotgen
(*this)(i) = first[i]; (*this)(i) = first[i];
} }
matrix(Scalar v0, Scalar v1, auto... vs)
requires((Rows == (2+sizeof...(vs)) && Cols == 1) || (Rows == 1 && Cols == (2+sizeof...(vs))))
: matrix({v0,v1,static_cast<Scalar>(vs)...})
{}
matrix(concepts::entity auto const& other) : parent(other.base()) matrix(concepts::entity auto const& other) : parent(other.base())
{} {}

View file

@ -0,0 +1,88 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <Eigen/Dense>
#include <Eigen/SVD>
namespace rotgen
{
template<typename M>
struct svd
{
using base = Eigen::JacobiSVD<typename M::parent>;
using u_type = typename base::MatrixUType;
using v_type = typename base::MatrixVType;
using d_type = typename base::SingularValuesType;
svd(M const& m, int options = ComputeThinU | ComputeThinV) : svd_(m.base(),options) {}
int rank() const { return svd_.rank(); }
auto singular_values() const
{
if constexpr(!use_expression_templates) return as_concrete_t<d_type, matrix>{svd_.singularValues()};
else return svd_.singularValues();
}
auto U() const
{
if constexpr(!use_expression_templates) return as_concrete_t<u_type, matrix>{svd_.matrixU()};
else return svd_.matrixU();
}
auto V() const
{
if constexpr(!use_expression_templates) return as_concrete_t<v_type, matrix>{svd_.matrixV()};
else return svd_.matrixV();
}
auto D() const
{
auto d = svd_.singularValues().asDiagonal();
if constexpr(!use_expression_templates)
return as_concrete_t<decltype(d.toDenseMatrix()), matrix>{d.toDenseMatrix ()};
else
return d;
}
auto singular_values(int r) const
{
auto that = svd_.singularValues().head(r);
if constexpr(!use_expression_templates) return as_concrete_t<decltype(that), matrix>{that};
else return svd_.singularValues();
}
auto U(int r) const
{
auto that = svd_.matrixU().leftCols(r);
if constexpr(!use_expression_templates) return as_concrete_t<decltype(that), matrix>{that};
else return that;
}
auto V(int r) const
{
auto that = svd_.matrixV().leftCols(r);
if constexpr(!use_expression_templates) return as_concrete_t<decltype(that), matrix>{that};
else return that;
}
auto D(int r) const
{
auto d = svd_.singularValues().head(r).asDiagonal();
if constexpr(!use_expression_templates)
return as_concrete_t<decltype(d.toDenseMatrix()), matrix>{d.toDenseMatrix ()};
else
return d;
}
private:
base svd_;
};
}

View file

@ -12,47 +12,43 @@ namespace rotgen
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
// Infos & Shape // Infos & Shape
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
std::size_t rows(concepts::entity auto const& arg) { return arg.rows(); } std::size_t rows(auto const& m) requires(requires{ m.rows(); }){ return m.rows(); }
std::size_t cols(concepts::entity auto const& arg) { return arg.cols(); } std::size_t cols(auto const& m) requires(requires{ m.cols(); }){ return m.cols(); }
std::size_t size(concepts::entity auto const& arg) { return arg.size(); } std::size_t size(auto const& m) requires(requires{ m.size(); }){ return m.size(); }
template<concepts::entity E> void resize(auto& a, int sz) requires requires{a.resize(sz);} { a.resize(sz); }
void resize(E& arg, int sz) requires requires{arg.resize(sz);}
{
arg.resize(sz);
}
template<concepts::entity E> template<typename E>
void resize(E& arg, int new_rows, int new_cols) void resize(E& a, int r, int c)
requires(E::RowsAtCompileTime == -1 && E::ColsAtCompileTime == -1) requires(E::RowsAtCompileTime == -1 && E::ColsAtCompileTime == -1)
{ {
arg.resize(new_rows, new_cols); a.resize(r, c);
} }
template<concepts::entity E> template<typename E>
void conservativeResize(E& arg, int sz) requires requires{arg.conservativeResize(sz);} void conservativeResize(E& a, int sz) requires requires{a.conservativeResize(sz);}
{ {
arg.conservativeResize(sz); a.conservativeResize(sz);
} }
template<concepts::entity E> template<typename E>
void conservativeResize(E& arg, int new_rows, int new_cols) void conservativeResize(E& a, int r, int c)
requires(E::RowsAtCompileTime == -1 && E::ColsAtCompileTime == -1) requires(E::RowsAtCompileTime == -1 && E::ColsAtCompileTime == -1)
{ {
arg.conservativeResize(new_rows, new_cols); a.conservativeResize(r, c);
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
// Global operations // Global operations
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
decltype(auto) normalized(concepts::entity auto const& arg) { return arg.normalized(); } decltype(auto) normalized (auto const& m) requires(requires{ m.normalized(); }) { return m.normalized(); }
decltype(auto) transpose (concepts::entity auto const& arg) { return arg.transpose(); } decltype(auto) transpose (auto const& m) requires(requires{ m.transpose(); }) { return m.transpose(); }
decltype(auto) conjugate (concepts::entity auto const& arg) { return arg.conjugate(); } decltype(auto) conjugate (auto const& m) requires(requires{ m.conjugate(); }) { return m.conjugate(); }
decltype(auto) adjoint (concepts::entity auto const& arg) { return arg.adjoint(); } decltype(auto) adjoint (auto const& m) requires(requires{ m.adjoint(); }) { return m.adjoint(); }
void normalize(concepts::entity auto& arg) { arg.normalize(); } void normalize(auto& a) requires(requires{ a.normalize(); }) { a.normalize(); }
void transposeInPlace(concepts::entity auto& arg) { arg.transposeInPlace(); } void transposeInPlace(auto& a) requires(requires{ a.transposeInPlace(); }) { a.transposeInPlace(); }
void adjointInPlace(concepts::entity auto& arg) { arg.adjointInPlace(); } void adjointInPlace(auto& a) requires(requires{ a.adjointInPlace(); }) { a.adjointInPlace(); }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
// Component-wise functions // Component-wise functions
@ -146,13 +142,8 @@ namespace rotgen
auto prod(concepts::entity auto const& arg) { return arg.prod(); } auto prod(concepts::entity auto const& arg) { return arg.prod(); }
auto mean(concepts::entity auto const& arg) { return arg.mean(); } auto mean(concepts::entity auto const& arg) { return arg.mean(); }
auto maxCoeff(auto const& arg) auto maxCoeff(auto const& arg) requires( requires{ arg.maxCoeff(); } ) { return arg.maxCoeff(); }
requires( requires{ arg.maxCoeff(); } ) auto minCoeff(auto const& arg) requires( requires{ arg.minCoeff(); } ) { return arg.minCoeff(); }
{
return arg.maxCoeff();
}
auto minCoeff(concepts::entity auto const& arg) { return arg.minCoeff(); }
template<std::integral IndexType> template<std::integral IndexType>
auto maxCoeff(concepts::entity auto const& arg, IndexType* row, IndexType* col) auto maxCoeff(concepts::entity auto const& arg, IndexType* row, IndexType* col)
@ -166,8 +157,8 @@ namespace rotgen
return arg.minCoeff(row, col); return arg.minCoeff(row, col);
} }
template<int P> template<int P, typename T>
auto lpNorm(concepts::entity auto const& arg) auto lpNorm(T const& arg) requires( requires{arg.template lpNorm<P>();} )
{ {
static_assert(P == 1 || P == 2 || P == Infinity); static_assert(P == 1 || P == 2 || P == Infinity);
return arg.template lpNorm<P>(); return arg.template lpNorm<P>();
@ -316,4 +307,24 @@ namespace rotgen
{ {
return T::Constant(r,c,v); return T::Constant(r,c,v);
} }
//-----------------------------------------------------------------------------------------------
// Others
// TODO: Adapt other functions ot behave as inverse and limit code in non-ref/non-map containers
//-----------------------------------------------------------------------------------------------
template<typename A> auto inverse(A const& a)
{
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();
}
template<concepts::vectorND<3> L, concepts::vectorND<3> R> auto cross(L const& l, R const& r)
{
if constexpr(!use_expression_templates)
return cross(generalize_t<R const>(l),generalize_t<R const>(r));
else if constexpr(requires{typename L::rotgen_tag;} || requires{typename R::rotgen_tag;} )
return base_of(l).cross(base_of(r));
else return l.cross(r);
}
} }

View file

@ -1,17 +1,21 @@
#define SIZE 64 #define SIZE 64
#define TYPE double #define TYPE double
#define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/map_model.hpp> #include <rotgen/impl/map_model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#undef CLASSCONSTNAME
#define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/map_model.hpp> #include <rotgen/impl/map_model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#undef CLASSCONSTNAME
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
@ -19,17 +23,21 @@
#define SIZE 32 #define SIZE 32
#define TYPE float #define TYPE float
#define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/map_model.hpp> #include <rotgen/impl/map_model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#undef CLASSCONSTNAME
#define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/map_model.hpp> #include <rotgen/impl/map_model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#undef CLASSCONSTNAME
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE

View file

@ -18,15 +18,13 @@ class ROTGEN_EXPORT CLASSNAME
CLASSNAME(TYPE CONST* ptr, Index r, Index c, stride s); CLASSNAME(TYPE CONST* ptr, Index r, Index c, stride s);
CLASSNAME(CLASSNAME const& other); CLASSNAME(CLASSNAME const& other);
CLASSNAME(CLASSNAME&&) noexcept;
#if !defined(USE_CONST) #if !defined(USE_CONST)
CLASSNAME& operator=(CLASSNAME const& other); CLASSNAME& operator=(CLASSNAME const& other);
CLASSNAME& operator=(CLASSNAME&& other);
#endif #endif
CLASSNAME(CLASSNAME&&) noexcept;
CLASSNAME& operator=(CLASSNAME&&) noexcept;
~CLASSNAME(); ~CLASSNAME();
Index rows() const; Index rows() const;
@ -85,8 +83,11 @@ class ROTGEN_EXPORT CLASSNAME
#if !defined(USE_CONST) #if !defined(USE_CONST)
CLASSNAME& operator+=(CLASSNAME const& rhs); CLASSNAME& operator+=(CLASSNAME const& rhs);
CLASSNAME& operator+=(CLASSCONSTNAME const& rhs);
CLASSNAME& operator-=(CLASSNAME const& rhs); CLASSNAME& operator-=(CLASSNAME const& rhs);
CLASSNAME& operator-=(CLASSCONSTNAME const& rhs);
CLASSNAME& operator*=(CLASSNAME const& rhs); CLASSNAME& operator*=(CLASSNAME const& rhs);
CLASSNAME& operator*=(CLASSCONSTNAME const& rhs);
CLASSNAME& operator*=(TYPE d); CLASSNAME& operator*=(TYPE d);
CLASSNAME& operator/=(TYPE d); CLASSNAME& operator/=(TYPE d);
#endif #endif
@ -98,6 +99,8 @@ class ROTGEN_EXPORT CLASSNAME
SOURCENAME mul(TYPE s) const; SOURCENAME mul(TYPE s) const;
SOURCENAME div(TYPE s) const; SOURCENAME div(TYPE s) const;
SOURCENAME inverse() const;
friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&,CLASSNAME const&); friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&,CLASSNAME const&);
const TYPE* data() const; const TYPE* data() const;

View file

@ -0,0 +1,68 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/detail/generators.hpp>
#include <rotgen/config.hpp>
#include <cstddef>
#include <memory>
namespace rotgen
{
class matrix_impl64_row;
class matrix_impl64_col;
class matrix_impl32_row;
class matrix_impl32_col;
#define SIZE 64
#define TYPE double
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/svd_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/svd_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#undef SIZE
#undef TYPE
#define SIZE 32
#define TYPE float
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/svd_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/svd_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#undef SIZE
#undef TYPE
template<typename Scalar,int Options> struct find_svd_impl;
template<> struct find_svd_impl<float , ColMajor> { using type = svd_impl32_col; };
template<> struct find_svd_impl<float , RowMajor> { using type = svd_impl32_row; };
template<> struct find_svd_impl<double, ColMajor> { using type = svd_impl64_col; };
template<> struct find_svd_impl<double, RowMajor> { using type = svd_impl64_row; };
template<typename Scalar,int Options>
using find_svd = typename find_svd_impl<Scalar,(Options & 1)>::type;
}

View file

@ -0,0 +1,44 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
//==================================================================================================
/*
This file is a X-File to generate various svd_impl_* declarations variant
*/
//==================================================================================================
class ROTGEN_EXPORT CLASSNAME
{
public:
CLASSNAME(SOURCENAME const& m, int options);
CLASSNAME(CLASSNAME const& other);
CLASSNAME(CLASSNAME&&) noexcept;
CLASSNAME& operator=(CLASSNAME const& other);
CLASSNAME& operator=(CLASSNAME&&) noexcept;
~CLASSNAME();
int rank() const;
SOURCENAME U() const;
SOURCENAME D() const;
SOURCENAME singular_values() const;
SOURCENAME V() const;
SOURCENAME U(int) const;
SOURCENAME D(int) const;
SOURCENAME singular_values(int) const;
SOURCENAME V(int) const;
private:
struct payload;
std::unique_ptr<payload> storage_;
public:
std::unique_ptr<payload>& storage() { return storage_; }
std::unique_ptr<payload> const& storage() const { return storage_; }
};

View file

@ -68,4 +68,30 @@ namespace rotgen
if constexpr(!use_expression_templates) return generalize_t<A const>(a) / b; if constexpr(!use_expression_templates) return generalize_t<A const>(a) / b;
else return base_of(a) / b; else return base_of(a) / b;
} }
//------------------------------------------------------------------------------------------------
// Compounds operators across types
template<typename A, typename B>
auto operator+=(A& a, B const& b)
requires(concepts::entity<A> || concepts::entity<B>)
{
if constexpr(!use_expression_templates) return generalize_t<A>(a) += generalize_t<B const>(b);
else return base_of(a) += base_of(b);
}
template<typename A, typename B>
auto operator-=(A& a, B const& b)
requires(concepts::entity<A> || concepts::entity<B>)
{
if constexpr(!use_expression_templates) return generalize_t<A>(a) -= generalize_t<B const>(b);
else return base_of(a) -= base_of(b);
}
template<typename A, typename B>
auto operator*=(A& a, B const& b)
requires(concepts::entity<A> || concepts::entity<B>)
{
if constexpr(!use_expression_templates) return generalize_t<A>(a) *= generalize_t<B const>(b);
else return base_of(a) *= base_of(b);
}
} }

View file

@ -16,10 +16,12 @@
#include <rotgen/dynamic/matrix.hpp> #include <rotgen/dynamic/matrix.hpp>
#include <rotgen/dynamic/block.hpp> #include <rotgen/dynamic/block.hpp>
#include <rotgen/dynamic/map.hpp> #include <rotgen/dynamic/map.hpp>
#include <rotgen/dynamic/svd.hpp>
#else #else
#include <rotgen/fixed/matrix.hpp> #include <rotgen/fixed/matrix.hpp>
#include <rotgen/fixed/block.hpp> #include <rotgen/fixed/block.hpp>
#include <rotgen/fixed/map.hpp> #include <rotgen/fixed/map.hpp>
#include <rotgen/fixed/svd.hpp>
#endif #endif
#include <rotgen/common/ref.hpp> #include <rotgen/common/ref.hpp>

View file

@ -11,8 +11,6 @@
This file is a X-File to generate various block_impl_* definitions variant This file is a X-File to generate various block_impl_* definitions variant
*/ */
//================================================================================================== //==================================================================================================
#define STR(text) STR_I(text)
#define STR_I(...) #__VA_ARGS__
//================================================================================================== //==================================================================================================
// Internal payload // Internal payload
@ -107,7 +105,11 @@ struct CLASSNAME::payload
return *this; return *this;
} }
CLASSNAME& CLASSNAME::operator=(CLASSNAME&&) noexcept = default; CLASSNAME& CLASSNAME::operator=(CLASSNAME&& o) noexcept
{
if (this != &o) { storage_->data = std::move(o.storage_->data); }
return *this;
}
#endif #endif

View file

@ -9,6 +9,7 @@
#include <rotgen/impl/map.hpp> #include <rotgen/impl/map.hpp>
#include <rotgen/impl/payload.hpp> #include <rotgen/impl/payload.hpp>
#include <Eigen/Dense> #include <Eigen/Dense>
#include <Eigen/LU>
namespace rotgen namespace rotgen
{ {

View file

@ -2,19 +2,23 @@
#define TYPE double #define TYPE double
#define STORAGE_ORDER Eigen::ColMajor #define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "map_model.cpp" #include "map_model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef CLASSCONSTNAME
#undef SOURCENAME #undef SOURCENAME
#undef STORAGE_ORDER #undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor #define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "map_model.cpp" #include "map_model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#undef CLASSCONSTNAME
#undef STORAGE_ORDER #undef STORAGE_ORDER
#undef SIZE #undef SIZE
@ -24,18 +28,22 @@
#define TYPE float #define TYPE float
#define STORAGE_ORDER Eigen::ColMajor #define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "map_model.cpp" #include "map_model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef CLASSCONSTNAME
#undef SOURCENAME #undef SOURCENAME
#undef STORAGE_ORDER #undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor #define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "map_model.cpp" #include "map_model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef CLASSCONSTNAME
#undef SOURCENAME #undef SOURCENAME
#undef STORAGE_ORDER #undef STORAGE_ORDER

View file

@ -35,10 +35,15 @@
if (this != &o) storage_->data = o.storage_->data; if (this != &o) storage_->data = o.storage_->data;
return *this; return *this;
} }
CLASSNAME& CLASSNAME::operator=(CLASSNAME&& o)
{
if (this != &o) storage_->data = std::move(o.storage_->data);
return *this;
}
#endif #endif
CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default; CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default;
CLASSNAME& CLASSNAME::operator=(CLASSNAME&&) noexcept = default;
CLASSNAME::~CLASSNAME() = default; CLASSNAME::~CLASSNAME() = default;
@ -160,6 +165,13 @@
return result; return result;
} }
SOURCENAME CLASSNAME::inverse() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.inverse().eval());
return result;
}
#if !defined(USE_CONST) #if !defined(USE_CONST)
void CLASSNAME::normalize() void CLASSNAME::normalize()
{ {
@ -267,18 +279,36 @@
return *this; return *this;
} }
CLASSNAME& CLASSNAME::operator+=(CLASSCONSTNAME const& rhs)
{
storage_->data += rhs.storage()->data;
return *this;
}
CLASSNAME& CLASSNAME::operator-=(CLASSNAME const& rhs) CLASSNAME& CLASSNAME::operator-=(CLASSNAME const& rhs)
{ {
storage_->data -= rhs.storage_->data; storage_->data -= rhs.storage_->data;
return *this; return *this;
} }
CLASSNAME& CLASSNAME::operator-=(CLASSCONSTNAME const& rhs)
{
storage_->data -= rhs.storage()->data;
return *this;
}
CLASSNAME& CLASSNAME::operator*=(CLASSNAME const& rhs) CLASSNAME& CLASSNAME::operator*=(CLASSNAME const& rhs)
{ {
storage_->data *= rhs.storage_->data; storage_->data *= rhs.storage_->data;
return *this; return *this;
} }
CLASSNAME& CLASSNAME::operator*=(CLASSCONSTNAME const& rhs)
{
storage_->data *= rhs.storage()->data;
return *this;
}
CLASSNAME& CLASSNAME::operator*=(TYPE s) CLASSNAME& CLASSNAME::operator*=(TYPE s)
{ {
storage_->data *= s; storage_->data *= s;

61
src/svd.cpp Normal file
View file

@ -0,0 +1,61 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/detail/generators.hpp>
#include <rotgen/impl/matrix.hpp>
#include <rotgen/impl/payload.hpp>
#include <rotgen/impl/svd.hpp>
#include <rotgen/config.hpp>
#include <Eigen/Dense>
#include <Eigen/SVD>
namespace rotgen
{
#define SIZE 64
#define TYPE double
#define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "svd_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "svd_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#undef SIZE
#undef TYPE
#define SIZE 32
#define TYPE float
#define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "svd_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "svd_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#undef SIZE
#undef TYPE
}

111
src/svd_model.cpp Normal file
View file

@ -0,0 +1,111 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
//==================================================================================================
/*
This file is a X-File to generate various svd_impl_* definitions variant
*/
//==================================================================================================
//==================================================================================================
// Internal payload
//==================================================================================================
struct CLASSNAME::payload
{
using matrix_type = Eigen::Matrix<TYPE,Eigen::Dynamic,Eigen::Dynamic,STORAGE_ORDER>;
Eigen::JacobiSVD<matrix_type> data;
payload(SOURCENAME const& src, int options) : data(src.storage()->data,options) {}
};
//==================================================================================================
// Constructors & Special Members
//==================================================================================================
CLASSNAME::CLASSNAME(SOURCENAME const& m, int options)
: storage_(std::make_unique<payload>(m,options))
{}
CLASSNAME::CLASSNAME(CLASSNAME const& o)
: storage_(std::make_unique<payload>(*o.storage_))
{
}
CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default;
CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
{
if (this != &o) storage_->data = o.storage_->data;
return *this;
}
CLASSNAME& CLASSNAME::operator=(CLASSNAME&& o) noexcept
{
if (this != &o) storage_->data = std::move(o.storage_->data);
return *this;
}
CLASSNAME::~CLASSNAME() = default;
int CLASSNAME::rank() const { return storage_->data.rank(); }
SOURCENAME CLASSNAME::U() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.matrixU());
return result;
}
SOURCENAME CLASSNAME::U(int r) const
{
SOURCENAME result;
result.storage()->assign( storage_->data.matrixU().leftCols(r) );
return result;
}
SOURCENAME CLASSNAME::singular_values() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.singularValues());
return result;
}
SOURCENAME CLASSNAME::singular_values(int r) const
{
SOURCENAME result;
result.storage()->assign(storage_->data.singularValues().head(r));
return result;
}
SOURCENAME CLASSNAME::D() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.singularValues().asDiagonal());
return result;
}
SOURCENAME CLASSNAME::D(int r) const
{
SOURCENAME result;
result.storage()->assign(storage_->data.singularValues().head(r).asDiagonal());
return result;
}
SOURCENAME CLASSNAME::V() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.matrixV());
return result;
}
SOURCENAME CLASSNAME::V(int r) const
{
SOURCENAME result;
result.storage()->assign( storage_->data.matrixV().leftCols(r) );
return result;
}

View file

@ -30,7 +30,10 @@ MatrixType make_initialized_matrix(rotgen::tests::matrix_block_test_case<MatrixT
auto[d,i0,j0,ni,nj] = matrix_construct; auto[d,i0,j0,ni,nj] = matrix_construct;
auto[r,c,fn] = d; auto[r,c,fn] = d;
MatrixType matrix(r, c); MatrixType matrix;
if constexpr(MatrixType::RowsAtCompileTime == -1 &&MatrixType::ColsAtCompileTime == -1)
rotgen::resize(matrix, r, c);
for(rotgen::Index i = 0; i < r; ++i) for(rotgen::Index i = 0; i < r; ++i)
for(rotgen::Index j = 0; j < c; ++j) for(rotgen::Index j = 0; j < c; ++j)

View file

@ -21,17 +21,11 @@ namespace rotgen::tests
prepare([&](auto r, auto c) { return input(r,c); }, ref); prepare([&](auto r, auto c) { return input(r,c); }, ref);
TTS_EQUAL(input.norm() , ref.norm()); TTS_EQUAL(rotgen::norm(input) , ref.norm());
TTS_EQUAL(input.squaredNorm() , ref.squaredNorm()); TTS_EQUAL(rotgen::squaredNorm(input) , ref.squaredNorm());
TTS_EQUAL(input.template lpNorm<1>() , ref.template lpNorm<1>()); TTS_EQUAL(rotgen::lpNorm<1>(input) , ref.template lpNorm<1>());
TTS_EQUAL(input.template lpNorm<2>() , ref.template lpNorm<2>()); TTS_EQUAL(rotgen::lpNorm<2>(input) , ref.template lpNorm<2>());
TTS_EQUAL(input.template lpNorm<rotgen::Infinity>() , ref.template lpNorm<Eigen::Infinity>()); TTS_EQUAL(rotgen::lpNorm<rotgen::Infinity>(input) , ref.template lpNorm<Eigen::Infinity>());
TTS_EQUAL(norm(input) , ref.norm());
TTS_EQUAL(squaredNorm(input) , ref.squaredNorm());
TTS_EQUAL(lpNorm<1>(input) , ref.template lpNorm<1>());
TTS_EQUAL(lpNorm<2>(input) , ref.template lpNorm<2>());
TTS_EQUAL(lpNorm<rotgen::Infinity>(input) , ref.template lpNorm<Eigen::Infinity>());
if constexpr(T::IsVectorAtCompileTime) if constexpr(T::IsVectorAtCompileTime)
{ {
@ -40,14 +34,10 @@ namespace rotgen::tests
mat_t norm_ref(input.rows(), input.cols()); mat_t norm_ref(input.rows(), input.cols());
prepare([&](auto r, auto c) { return e_norm(r,c); }, norm_ref); prepare([&](auto r, auto c) { return e_norm(r,c); }, norm_ref);
TTS_EQUAL(input.normalized(), norm_ref); TTS_EQUAL(rotgen::normalized(input), norm_ref);
TTS_EQUAL(normalized(input), norm_ref);
auto m_norm = input;
m_norm.normalize();
TTS_EQUAL(m_norm, norm_ref);
auto f_norm = input; auto f_norm = input;
normalize(f_norm); rotgen::normalize(f_norm);
TTS_EQUAL(f_norm, norm_ref); TTS_EQUAL(f_norm, norm_ref);
} }
} }

View file

@ -0,0 +1,79 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
TTS_CASE_TPL("SVD decomposition - Dynamic case", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
int rank, i = 5;
auto eps = std::numeric_limits<T>::epsilon();
auto m = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>::Random(5,5);
auto decomp = rotgen::svd(m);
do
{
rank = decomp.rank();
auto u = decomp.U(rank);
auto d = decomp.singular_values(rank);
auto dd = decomp.D(rank);
auto v = decomp.V(rank);
TTS_EQUAL(rank, i);
auto rec = (u * dd * rotgen::transpose(v));
auto error = m - rec;
TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 16.)
<< "Result:\n" << rec << "\n"
<< "Residuals:\n" << error << "\n";
// Reduce rank by duplicating one column
i--;
col(m,i) = col(m,0);
decomp = rotgen::svd(m);
}while(rank != 1);
};
TTS_CASE_TPL("SVD decomposition - Static case", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
int rank, i = 5;
auto eps = std::numeric_limits<T>::epsilon();
auto m = rotgen::matrix<T,5,5,O::value>::Random();
auto decomp = rotgen::svd(m);
do
{
rank = decomp.rank();
auto u = decomp.U(rank);
auto d = decomp.singular_values(rank);
auto dd = decomp.D(rank);
auto v = decomp.V(rank);
TTS_EQUAL(rank, i);
auto rec = (u * dd * rotgen::transpose(v));
auto error = m - rec;
TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 16.)
<< "Result:\n" << rec << "\n"
<< "Residuals:\n" << error << "\n";
// Reduce rank by duplicating one column
i--;
col(m,i) = col(m,0);
decomp = rotgen::svd(m);
}while(rank != 1);
};

View file

@ -35,13 +35,28 @@ TTS_CASE_TPL("Dynamic matrix constructor with row and columns", rotgen::tests::t
TTS_EQUAL(matrix.cols(), rotgen::Index{5}); TTS_EQUAL(matrix.cols(), rotgen::Index{5});
}; };
TTS_CASE_TPL("Static matrix constructor with row and columns", rotgen::tests::types) TTS_CASE_TPL("Static matrix constructor with row and columns", float, double)
<typename T, typename O>( tts::type< tts::types<T,O>> ) <typename T>( tts::type<T> )
{ {
rotgen::matrix<T,6,11,O::value> matrix(6, 11); rotgen::matrix<T,1,2> v2(6, 11);
rotgen::matrix<T,2,1> w2(6, 11);
TTS_EQUAL(matrix.rows(), rotgen::Index{6}); TTS_EQUAL(v2(0), T{6});
TTS_EQUAL(matrix.cols(), rotgen::Index{11}); TTS_EQUAL(v2(1), T{11});
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);
TTS_EQUAL(v3(0), T{6});
TTS_EQUAL(v3(1), T{11});
TTS_EQUAL(v3(2), T{125});
TTS_EQUAL(w3(0), T{6});
TTS_EQUAL(w3(1), T{11});
TTS_EQUAL(w3(2), T{125});
}; };
TTS_CASE_TPL("Copy constructor produces identical but independent matrix", rotgen::tests::types) TTS_CASE_TPL("Copy constructor produces identical but independent matrix", rotgen::tests::types)

View file

@ -51,7 +51,7 @@ TTS_CASE_TPL("Test zero", rotgen::tests::types)
test_value(setZero(matrix<T, 1, 1, O::value>{} ), 1, 1, 0); test_value(setZero(matrix<T, 1, 1, O::value>{} ), 1, 1, 0);
test_value(setZero(matrix<T, 10, 10, O::value>{} ), 10, 10, 0); test_value(setZero(matrix<T, 10, 10, O::value>{} ), 10, 10, 0);
test_value(setZero(matrix<T,Dynamic,Dynamic, O::value>{3, 4}), 3, 4, 0); test_value(setZero(matrix<T,Dynamic,Dynamic, O::value>{3, 4}), 3, 4, 0);
test_value(setZero(matrix<T, 7, 5, O::value>{7, 5} ), 7, 5, 0); test_value(setZero(matrix<T, 7, 5, O::value>{} ), 7, 5, 0);
test_value(setZero(matrix<T, 9,Dynamic>{9, 3} ), 9, 3, 0); test_value(setZero(matrix<T, 9,Dynamic>{9, 3} ), 9, 3, 0);
test_value(setZero(matrix<T,Dynamic, 3>{2, 3} ), 2, 3, 0); test_value(setZero(matrix<T,Dynamic, 3>{2, 3} ), 2, 3, 0);
}; };
@ -72,7 +72,7 @@ TTS_CASE_TPL("Test ones", rotgen::tests::types)
test_value(setOnes(matrix<T, 1, 1, O::value>{} ), 1, 1, 1); test_value(setOnes(matrix<T, 1, 1, O::value>{} ), 1, 1, 1);
test_value(setOnes(matrix<T, 10, 10, O::value>{} ), 10, 10, 1); test_value(setOnes(matrix<T, 10, 10, O::value>{} ), 10, 10, 1);
test_value(setOnes(matrix<T,Dynamic,Dynamic, O::value>{3, 4}), 3, 4, 1); test_value(setOnes(matrix<T,Dynamic,Dynamic, O::value>{3, 4}), 3, 4, 1);
test_value(setOnes(matrix<T, 7, 5, O::value>{7, 5} ), 7, 5, 1); test_value(setOnes(matrix<T, 7, 5, O::value>{} ), 7, 5, 1);
test_value(setOnes(matrix<T, 9,Dynamic>{9, 3} ), 9, 3, 1); test_value(setOnes(matrix<T, 9,Dynamic>{9, 3} ), 9, 3, 1);
test_value(setOnes(matrix<T,Dynamic, 3>{2, 3} ), 2, 3, 1); test_value(setOnes(matrix<T,Dynamic, 3>{2, 3} ), 2, 3, 1);
}; };
@ -93,7 +93,7 @@ TTS_CASE_TPL("Test constant", rotgen::tests::types)
test_value(setConstant(matrix<T, 1, 1, O::value>{} , T(5.12)), 1, 1, T(5.12)); test_value(setConstant(matrix<T, 1, 1, O::value>{} , T(5.12)), 1, 1, T(5.12));
test_value(setConstant(matrix<T, 10, 10, O::value>{} , T(5.12)), 10, 10, T(5.12)); test_value(setConstant(matrix<T, 10, 10, O::value>{} , T(5.12)), 10, 10, T(5.12));
test_value(setConstant(matrix<T,Dynamic,Dynamic, O::value>{3, 4}, T(5.12)), 3, 4, T(5.12)); test_value(setConstant(matrix<T,Dynamic,Dynamic, O::value>{3, 4}, T(5.12)), 3, 4, T(5.12));
test_value(setConstant(matrix<T, 7, 5, O::value>{7, 5} , T(5.12)), 7, 5, T(5.12)); test_value(setConstant(matrix<T, 7, 5, O::value>{} , T(5.12)), 7, 5, T(5.12));
test_value(setConstant(matrix<T, 9,Dynamic>{9, 3} , T(5.12)), 9, 3, T(5.12)); test_value(setConstant(matrix<T, 9,Dynamic>{9, 3} , T(5.12)), 9, 3, T(5.12));
test_value(setConstant(matrix<T,Dynamic, 3>{2, 3} , T(5.12)), 2, 3, T(5.12)); test_value(setConstant(matrix<T,Dynamic, 3>{2, 3} , T(5.12)), 2, 3, T(5.12));
}; };
@ -114,7 +114,7 @@ TTS_CASE_TPL("Test random", rotgen::tests::types)
test_random(setRandom(matrix<T, 1, 1, O::value>{} ), 1, 1); test_random(setRandom(matrix<T, 1, 1, O::value>{} ), 1, 1);
test_random(setRandom(matrix<T, 10, 10, O::value>{} ), 10, 10); test_random(setRandom(matrix<T, 10, 10, O::value>{} ), 10, 10);
test_random(setRandom(matrix<T,Dynamic,Dynamic, O::value>{3, 4}), 3, 4); test_random(setRandom(matrix<T,Dynamic,Dynamic, O::value>{3, 4}), 3, 4);
test_random(setRandom(matrix<T, 7, 5, O::value>{7, 5} ), 7, 5); test_random(setRandom(matrix<T, 7, 5, O::value>{} ), 7, 5);
test_random(setRandom(matrix<T, 9,Dynamic>{9, 3} ), 9, 3); test_random(setRandom(matrix<T, 9,Dynamic>{9, 3} ), 9, 3);
test_random(setRandom(matrix<T,Dynamic, 3>{2, 3} ), 2, 3); test_random(setRandom(matrix<T,Dynamic, 3>{2, 3} ), 2, 3);
}; };
@ -135,7 +135,7 @@ TTS_CASE_TPL("Test identity", rotgen::tests::types)
test_identity(setIdentity(matrix<T, 1, 1, O::value>{} ), 1, 1); test_identity(setIdentity(matrix<T, 1, 1, O::value>{} ), 1, 1);
test_identity(setIdentity(matrix<T, 10, 10, O::value>{} ), 10, 10); test_identity(setIdentity(matrix<T, 10, 10, O::value>{} ), 10, 10);
test_identity(setIdentity(matrix<T,Dynamic,Dynamic, O::value>{3, 4}), 3, 4); test_identity(setIdentity(matrix<T,Dynamic,Dynamic, O::value>{3, 4}), 3, 4);
test_identity(setIdentity(matrix<T, 7, 5, O::value>{7, 5} ), 7, 5); test_identity(setIdentity(matrix<T, 7, 5, O::value>{} ), 7, 5);
test_identity(setIdentity(matrix<T, 9,Dynamic>{9, 3} ), 9, 3); test_identity(setIdentity(matrix<T, 9,Dynamic>{9, 3} ), 9, 3);
test_identity(setIdentity(matrix<T,Dynamic, 3>{2, 3} ), 2, 3); test_identity(setIdentity(matrix<T,Dynamic, 3>{2, 3} ), 2, 3);
}; };

View file

@ -0,0 +1,62 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include "unit/common/arithmetic.hpp"
#include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic 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_matrix_references();
for (const auto& [r, c, fn] : cases)
{
if(r == c)
{
auto input = mat_t::Random(r, c);
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";
}
}
};
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);
};