Merge branch 'infra/format' into 'main'

Adding clang-format configuration file and formatting all source files

Co-authored-by: Jules Pénuchot <jules@penuchot.com>
Co-authored-by: Joel FALCOU <jfalcou@codereckons.com>

See merge request oss/rotgen!41
This commit is contained in:
Jules Pénuchot 2025-10-14 16:19:03 +02:00
commit 6fa95fb22d
94 changed files with 6778 additions and 4722 deletions

264
.clang-format Normal file
View file

@ -0,0 +1,264 @@
## -------------------------------------------------------------------------------------------------
## SPY - C++ Informations Broker
## Copyright: SPY Project Contributors
## SPDX-License-Identifier: BSL-1.0
## -------------------------------------------------------------------------------------------------
BasedOnStyle: Microsoft
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionPointers: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveShortCaseStatements:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCaseArrows: false
AlignCaseColons: false
AlignConsecutiveTableGenBreakingDAGArgColons:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveTableGenCondOperatorColons:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveTableGenDefinitionColons:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionPointers: false
PadOperators: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowBreakBeforeNoexceptSpecifier: Always
AllowShortBlocksOnASingleLine: Always
AllowShortCaseExpressionOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortCompoundRequirementOnASingleLine: true
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: false
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: false
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAdjacentStringLiterals: true
BreakAfterAttributes: Leave
BreakAfterJavaFieldAnnotations: false
BreakAfterReturnType: None
BreakArrays: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeConceptDeclarations: Always
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakFunctionDefinitionParameters: false
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
BreakTemplateDeclarations: MultiLine
ColumnLimit: 80
CommentPragmas: ""
CompactNamespaces: false
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
IncludeBlocks: Regroup
IncludeCategories:
- Regex: <rotgen/detail/.*>
Priority: 1
CaseSensitive: true
SortPriority: 1
- Regex: <rotgen/.*>
Priority: 2
CaseSensitive: true
SortPriority: 2
- Regex: .*
Priority: 3
CaseSensitive: true
SortPriority: 3
IncludeIsMainRegex: ""
IncludeIsMainSourceRegex: ""
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequiresClause: false
IndentWidth: 2
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: true
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLines:
AtEndOfFile: false
AtStartOfBlock: true
AtStartOfFile: true
LambdaBodyIndentation: Signature
LineEnding: LF
MacroBlockBegin: ""
MacroBlockEnd: ""
MainIncludeChar: AngleBracket
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PPIndentWidth: -1
PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakScopeResolution: 500
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Left
QualifierAlignment: Custom
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveParentheses: ReturnStatement
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Always
ShortNamespaceLines: 1
SkipMacroDefinitionBody: false
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeJsonColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDeclarationName: false
AfterFunctionDefinitionName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterPlacementOperator: true
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParens: Never
SpacesInParensOptions:
ExceptDoubleParentheses: false
InConditionalStatements: false
InCStyleCasts: false
InEmptyParentheses: false
Other: false
SpacesInSquareBrackets: false
Standard: c++20
TabWidth: 2
TableGenBreakInsideDAGArg: DontBreak
UseTab: Never
VerilogBreakBetweenInstancePorts: true
Language: Cpp
QualifierOrder:
- inline
- static
- type
- const

View file

@ -10,10 +10,10 @@
namespace rotgen::solver namespace rotgen::solver
{ {
template<typename X, typename M, typename RHS> template<typename X, typename M, typename RHS>
void qr(X& x, M const& m, RHS const& rhs ) void qr(X& x, M const& m, RHS const& rhs)
{ {
auto r_x = generalize_t<X>(x); auto r_x = generalize_t<X>(x);
auto r_m = generalize_t<M const>(m); auto r_m = generalize_t<M const>(m);
auto r_rhs = generalize_t<RHS const>(rhs); auto r_rhs = generalize_t<RHS const>(rhs);
r_x = r_m.base().qr_solve(r_rhs.base()); r_x = r_m.base().qr_solve(r_rhs.base());
} }

View file

@ -11,26 +11,34 @@
namespace rotgen namespace rotgen
{ {
template<typename M> template<typename M> struct svd : find_svd<typename M::value_type, M::Options>
struct svd : find_svd<typename M::value_type,M::Options>
{ {
using parent = 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 m_type = matrix<typename M::value_type, Dynamic, Dynamic, M::Options>;
using d_type = matrix<typename M::value_type,M::ColsAtCompileTime,1>; using d_type = matrix<typename M::value_type, M::ColsAtCompileTime, 1>;
svd(M const& m, int options = ComputeThinU | ComputeThinV) : parent(m,options) {} svd(M const& m, int options = ComputeThinU | ComputeThinV)
: parent(m, options)
{
}
int rank() const { return parent::rank(); } int rank() const { return parent::rank(); }
m_type U() const { return parent::U(); } 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() const { return parent::D(); }
m_type D(int r) const { return parent::D(r); }
m_type V(int r) const { return parent::V(r); } m_type V() const { return parent::V(); }
m_type singular_values(int r) const { return parent::singular_values(r); }
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

@ -19,50 +19,64 @@ namespace rotgen
class matrix_impl32_row; class matrix_impl32_row;
class matrix_impl32_col; class matrix_impl32_col;
#define SIZE 64 #define SIZE 64
#define TYPE double #define TYPE double
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl, SIZE, _col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include <rotgen/algebra/svd/dynamic/model.hpp> #include <rotgen/algebra/svd/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl, SIZE, _row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include <rotgen/algebra/svd/dynamic/model.hpp> #include <rotgen/algebra/svd/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
#define SIZE 32 #define SIZE 32
#define TYPE float #define TYPE float
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl, SIZE, _col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include <rotgen/algebra/svd/dynamic/model.hpp> #include <rotgen/algebra/svd/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl, SIZE, _row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include <rotgen/algebra/svd/dynamic/model.hpp> #include <rotgen/algebra/svd/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
template<typename Scalar, int Options> struct find_svd_impl;
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 , ColMajor> { using type = svd_impl32_col; }; template<> struct find_svd_impl<float, RowMajor>
template<> struct find_svd_impl<float , RowMajor> { using type = svd_impl32_row; }; {
template<> struct find_svd_impl<double, ColMajor> { using type = svd_impl64_col; }; using type = svd_impl32_row;
template<> struct find_svd_impl<double, RowMajor> { using type = svd_impl64_row; }; };
template<typename Scalar,int Options> template<> struct find_svd_impl<double, ColMajor>
using find_svd = typename find_svd_impl<Scalar,(Options & 1)>::type; {
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

@ -13,7 +13,7 @@
//================================================================================================== //==================================================================================================
class ROTGEN_EXPORT CLASSNAME class ROTGEN_EXPORT CLASSNAME
{ {
public: public:
CLASSNAME(SOURCENAME const& m, int options); CLASSNAME(SOURCENAME const& m, int options);
CLASSNAME(CLASSNAME const& other); CLASSNAME(CLASSNAME const& other);
CLASSNAME(CLASSNAME&&) noexcept; CLASSNAME(CLASSNAME&&) noexcept;
@ -23,22 +23,23 @@ class ROTGEN_EXPORT CLASSNAME
~CLASSNAME(); ~CLASSNAME();
int rank() const; int rank() const;
SOURCENAME U() const; SOURCENAME U() const;
SOURCENAME D() const; SOURCENAME D() const;
SOURCENAME singular_values() const; SOURCENAME singular_values() const;
SOURCENAME V() const; SOURCENAME V() const;
SOURCENAME U(int) const; SOURCENAME U(int) const;
SOURCENAME D(int) const; SOURCENAME D(int) const;
SOURCENAME singular_values(int) const; SOURCENAME singular_values(int) const;
SOURCENAME V(int) const; SOURCENAME V(int) const;
private: private:
struct payload; struct payload;
std::unique_ptr<payload> storage_; std::unique_ptr<payload> storage_;
public: public:
std::unique_ptr<payload>& storage() { return storage_; } std::unique_ptr<payload>& storage() { return storage_; }
std::unique_ptr<payload> const& storage() const { return storage_; } std::unique_ptr<payload> const& storage() const { return storage_; }
}; };

View file

@ -12,77 +12,84 @@
namespace rotgen namespace rotgen
{ {
template<typename M> template<typename M> struct svd
struct svd
{ {
using base = Eigen::JacobiSVD<typename M::parent>; using base = Eigen::JacobiSVD<typename M::parent>;
using u_type = typename base::MatrixUType; using u_type = typename base::MatrixUType;
using v_type = typename base::MatrixVType; using v_type = typename base::MatrixVType;
using d_type = typename base::SingularValuesType; using d_type = typename base::SingularValuesType;
svd(M const& m, int options = ComputeThinU | ComputeThinV) : svd_(m.base(),options) {} svd(M const& m, int options = ComputeThinU | ComputeThinV)
: svd_(m.base(), options)
{
}
int rank() const { return svd_.rank(); } int rank() const { return svd_.rank(); }
auto singular_values() const auto singular_values() const
{ {
if constexpr(!use_expression_templates) return detail::as_concrete_t<d_type, matrix>{svd_.singularValues()}; if constexpr (!use_expression_templates)
return detail::as_concrete_t<d_type, matrix>{svd_.singularValues()};
else return svd_.singularValues(); else return svd_.singularValues();
} }
auto U() const auto U() const
{ {
if constexpr(!use_expression_templates) return detail::as_concrete_t<u_type, matrix>{svd_.matrixU()}; if constexpr (!use_expression_templates)
return detail::as_concrete_t<u_type, matrix>{svd_.matrixU()};
else return svd_.matrixU(); else return svd_.matrixU();
} }
auto V() const auto V() const
{ {
if constexpr(!use_expression_templates) return detail::as_concrete_t<v_type, matrix>{svd_.matrixV()}; if constexpr (!use_expression_templates)
return detail::as_concrete_t<v_type, matrix>{svd_.matrixV()};
else return svd_.matrixV(); else return svd_.matrixV();
} }
auto D() const auto D() const
{ {
auto d = svd_.singularValues().asDiagonal(); auto d = svd_.singularValues().asDiagonal();
if constexpr(!use_expression_templates) if constexpr (!use_expression_templates)
return detail::as_concrete_t<decltype(d.toDenseMatrix()), matrix>{d.toDenseMatrix ()}; return detail::as_concrete_t<decltype(d.toDenseMatrix()), matrix>{
else d.toDenseMatrix()};
return d; else return d;
} }
auto singular_values(int r) const auto singular_values(int r) const
{ {
auto that = svd_.singularValues().head(r); auto that = svd_.singularValues().head(r);
if constexpr(!use_expression_templates) return detail::as_concrete_t<decltype(that), matrix>{that}; if constexpr (!use_expression_templates)
return detail::as_concrete_t<decltype(that), matrix>{that};
else return svd_.singularValues(); else return svd_.singularValues();
} }
auto U(int r) const auto U(int r) const
{ {
auto that = svd_.matrixU().leftCols(r); auto that = svd_.matrixU().leftCols(r);
if constexpr(!use_expression_templates) return detail::as_concrete_t<decltype(that), matrix>{that}; if constexpr (!use_expression_templates)
return detail::as_concrete_t<decltype(that), matrix>{that};
else return that; else return that;
} }
auto V(int r) const auto V(int r) const
{ {
auto that = svd_.matrixV().leftCols(r); auto that = svd_.matrixV().leftCols(r);
if constexpr(!use_expression_templates) return detail::as_concrete_t<decltype(that), matrix>{that}; if constexpr (!use_expression_templates)
return detail::as_concrete_t<decltype(that), matrix>{that};
else return that; else return that;
} }
auto D(int r) const auto D(int r) const
{ {
auto d = svd_.singularValues().head(r).asDiagonal(); auto d = svd_.singularValues().head(r).asDiagonal();
if constexpr(!use_expression_templates) if constexpr (!use_expression_templates)
return detail::as_concrete_t<decltype(d.toDenseMatrix()), matrix>{d.toDenseMatrix ()}; return detail::as_concrete_t<decltype(d.toDenseMatrix()), matrix>{
else d.toDenseMatrix()};
return d; else return d;
} }
private: private:
base svd_; base svd_;
}; };
} }

View file

@ -8,25 +8,25 @@
namespace rotgen namespace rotgen
{ {
// matrix aliases (float and double, fixed and dynamic) // matrix aliases (float and double, fixed and dynamic)
using matrix2f = rotgen::matrix<float, 2, 2>; using matrix2f = rotgen::matrix<float, 2, 2>;
using matrix3f = rotgen::matrix<float, 3, 3>; using matrix3f = rotgen::matrix<float, 3, 3>;
using matrix4f = rotgen::matrix<float, 4, 4>; using matrix4f = rotgen::matrix<float, 4, 4>;
using matrix2d = rotgen::matrix<double, 2, 2>; using matrix2d = rotgen::matrix<double, 2, 2>;
using matrix3d = rotgen::matrix<double, 3, 3>; using matrix3d = rotgen::matrix<double, 3, 3>;
using matrix4d = rotgen::matrix<double, 4, 4>; using matrix4d = rotgen::matrix<double, 4, 4>;
using matrixXf = rotgen::matrix<float, rotgen::Dynamic, rotgen::Dynamic>; using matrixXf = rotgen::matrix<float, rotgen::Dynamic, rotgen::Dynamic>;
using matrixXd = rotgen::matrix<double, rotgen::Dynamic, rotgen::Dynamic>; using matrixXd = rotgen::matrix<double, rotgen::Dynamic, rotgen::Dynamic>;
using matrixXi = rotgen::matrix<int, rotgen::Dynamic, rotgen::Dynamic>; using matrixXi = rotgen::matrix<int, rotgen::Dynamic, rotgen::Dynamic>;
// Column vector aliases // Column vector aliases
using vector2f = rotgen::matrix<float, 2, 1>; using vector2f = rotgen::matrix<float, 2, 1>;
using vector3f = rotgen::matrix<float, 3, 1>; using vector3f = rotgen::matrix<float, 3, 1>;
using vector4f = rotgen::matrix<float, 4, 1>; using vector4f = rotgen::matrix<float, 4, 1>;
using vector2d = rotgen::matrix<double, 2, 1>; using vector2d = rotgen::matrix<double, 2, 1>;
using vector3d = rotgen::matrix<double, 3, 1>; using vector3d = rotgen::matrix<double, 3, 1>;
using vector4d = rotgen::matrix<double, 4, 1>; using vector4d = rotgen::matrix<double, 4, 1>;
using vectorXf = rotgen::matrix<float, rotgen::Dynamic, 1>; using vectorXf = rotgen::matrix<float, rotgen::Dynamic, 1>;
using vectorXd = rotgen::matrix<double, rotgen::Dynamic, 1>; using vectorXd = rotgen::matrix<double, rotgen::Dynamic, 1>;
// Row vector aliases // Row vector aliases
using row_vector2f = rotgen::matrix<float, 1, 2>; using row_vector2f = rotgen::matrix<float, 1, 2>;

View file

@ -13,26 +13,27 @@ namespace rotgen::concepts
//! @brief Check if a type is a Rotgen reference. //! @brief Check if a type is a Rotgen reference.
//================================================================================================ //================================================================================================
template<typename T> template<typename T>
concept reference = requires { typename std::remove_cvref_t<T>::rotgen_ref_tag; }; concept reference =
requires { typename std::remove_cvref_t<T>::rotgen_ref_tag; };
//================================================================================================ //================================================================================================
//! @brief Check if a type is a vector. //! @brief Check if a type is a vector.
//================================================================================================ //================================================================================================
template<typename T> template<typename T>
concept vector = T::IsVectorAtCompileTime; concept vector = T::IsVectorAtCompileTime;
//================================================================================================ //================================================================================================
//! @brief Check if a type is a 3D vector. //! @brief Check if a type is a 3D vector.
//================================================================================================ //================================================================================================
template<typename T, int N> template<typename T, int N>
concept vectorND = vector<T> && (T::RowsAtCompileTime == N || T::ColsAtCompileTime == 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.
//================================================================================================ //================================================================================================
template<typename T> template<typename T>
concept entity = requires(T const&) concept entity = requires(T const&) {
{
typename std::remove_cvref_t<T>::rotgen_tag; typename std::remove_cvref_t<T>::rotgen_tag;
typename std::remove_cvref_t<T>::parent; typename std::remove_cvref_t<T>::parent;
}; };
@ -41,14 +42,17 @@ namespace rotgen::concepts
//! @brief Check if a type is an EIGEN type. //! @brief Check if a type is an EIGEN type.
//================================================================================================ //================================================================================================
template<typename T> template<typename T>
concept eigen_compatible = requires(T const& a) concept eigen_compatible = requires(T const& a) {
{
typename std::remove_cvref_t<T>::Scalar; typename std::remove_cvref_t<T>::Scalar;
{ std::remove_cvref_t<T>::RowsAtCompileTime } -> std::convertible_to<int>; { std::remove_cvref_t<T>::RowsAtCompileTime } -> std::convertible_to<int>;
{ std::remove_cvref_t<T>::ColsAtCompileTime } -> std::convertible_to<int>; { std::remove_cvref_t<T>::ColsAtCompileTime } -> std::convertible_to<int>;
{ std::remove_cvref_t<T>::MaxRowsAtCompileTime } -> std::convertible_to<int>; {
{ std::remove_cvref_t<T>::MaxColsAtCompileTime } -> std::convertible_to<int>; std::remove_cvref_t<T>::MaxRowsAtCompileTime
} -> std::convertible_to<int>;
{
std::remove_cvref_t<T>::MaxColsAtCompileTime
} -> std::convertible_to<int>;
{ a.eval() }; { a.eval() };
}; };

View file

@ -16,8 +16,7 @@ namespace rotgen
{ {
using Index = std::ptrdiff_t; using Index = std::ptrdiff_t;
inline constexpr std::ptrdiff_t default_alignment = []() inline constexpr std::ptrdiff_t default_alignment = []() {
{
constexpr auto w = spy::simd_instruction_set.width; constexpr auto w = spy::simd_instruction_set.width;
return w == -1 ? 0 : w / 8; return w == -1 ? 0 : w / 8;
}(); }();
@ -27,30 +26,31 @@ namespace rotgen
inline constexpr int ComputeFullV = 0x10; inline constexpr int ComputeFullV = 0x10;
inline constexpr int ComputeThinV = 0x20; 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;
inline constexpr int ColMajor = 0; inline constexpr int ColMajor = 0;
inline constexpr int RowMajor = 1; inline constexpr int RowMajor = 1;
inline constexpr int DontAlign = 2; inline constexpr int DontAlign = 2;
inline constexpr int Unaligned = 0; inline constexpr int Unaligned = 0;
inline constexpr int Aligned8 = 8; inline constexpr int Aligned8 = 8;
inline constexpr int Aligned16 = 16; inline constexpr int Aligned16 = 16;
inline constexpr int Aligned32 = 32; inline constexpr int Aligned32 = 32;
inline constexpr int Aligned64 = 64; inline constexpr int Aligned64 = 64;
inline constexpr int Aligned128 = 128; inline constexpr int Aligned128 = 128;
inline constexpr int Aligned = default_alignment; inline constexpr int Aligned = default_alignment;
inline constexpr int DontAlignCols = 1; inline constexpr int DontAlignCols = 1;
inline constexpr int StreamPrecision = -1; inline constexpr int StreamPrecision = -1;
inline constexpr int FullPrecision = -2; inline constexpr int FullPrecision = -2;
} }
namespace rotgen::detail namespace rotgen::detail
{ {
template<Index R, Index C> template<Index R, Index C>
inline constexpr int force_order = AutoAlign | ((R==1 && C!=1) ? RowMajor : ColMajor); inline constexpr int force_order =
AutoAlign | ((R == 1 && C != 1) ? RowMajor : ColMajor);
} }
#if !defined(ROTGEN_MAX_SIZE) && defined(ROTGEN_ENABLE_EXPRESSION_TEMPLATES) #if !defined(ROTGEN_MAX_SIZE) && defined(ROTGEN_ENABLE_EXPRESSION_TEMPLATES)
@ -58,15 +58,15 @@ namespace rotgen::detail
#endif #endif
#if !defined(ROTGEN_FORCE_DYNAMIC) #if !defined(ROTGEN_FORCE_DYNAMIC)
#if !defined(ROTGEN_MAX_SIZE) #if !defined(ROTGEN_MAX_SIZE)
#define ROTGEN_FORCE_DYNAMIC #define ROTGEN_FORCE_DYNAMIC
#endif #endif
#endif #endif
#if defined(ROTGEN_FORCE_DYNAMIC) #if defined(ROTGEN_FORCE_DYNAMIC)
#define ROTGEN_HAS_STATIC_LIMIT false #define ROTGEN_HAS_STATIC_LIMIT false
#else #else
#define ROTGEN_HAS_STATIC_LIMIT true #define ROTGEN_HAS_STATIC_LIMIT true
#endif #endif
namespace rotgen namespace rotgen
@ -77,8 +77,8 @@ namespace rotgen
inline constexpr bool use_expression_templates = false; inline constexpr bool use_expression_templates = false;
#endif #endif
inline constexpr bool has_static_limit = ROTGEN_HAS_STATIC_LIMIT; inline constexpr bool has_static_limit = ROTGEN_HAS_STATIC_LIMIT;
inline constexpr bool is_forcing_dynamic_status = !has_static_limit; inline constexpr bool is_forcing_dynamic_status = !has_static_limit;
namespace detail namespace detail
{ {
@ -91,8 +91,7 @@ namespace rotgen
{ {
inline constexpr Index max_static_size = -1; inline constexpr Index max_static_size = -1;
template<int Rows, int Cols> template<int Rows, int Cols> inline constexpr bool storage_status = false;
inline constexpr bool storage_status = false;
} }
#else #else
namespace rotgen namespace rotgen
@ -100,19 +99,18 @@ namespace rotgen
inline constexpr Index max_static_size = ROTGEN_MAX_SIZE; inline constexpr Index max_static_size = ROTGEN_MAX_SIZE;
template<int Rows, int Cols, int MaxRows, int MaxCols> template<int Rows, int Cols, int MaxRows, int MaxCols>
inline constexpr bool storage_status = inline constexpr bool storage_status = []() {
[]()
{
// Actual static size - vector 1xN // Actual static size - vector 1xN
if(Rows == 1 && Cols == -1) return true; if (Rows == 1 && Cols == -1) return true;
// Actual static size - vector Nx1 // Actual static size - vector Nx1
else if(Rows == -1 && Cols == 1) return true; else if (Rows == -1 && Cols == 1) return true;
// Actual static size - matrix // Actual static size - matrix
else if(Rows > 0 && Cols > 0) return (Rows*Cols) <= max_static_size; else if (Rows > 0 && Cols > 0) return (Rows * Cols) <= max_static_size;
// Dynamic size but static Max Size // Dynamic size but static Max Size
else if(MaxRows > 0 && MaxCols > 0) return (MaxRows*MaxCols) <= max_static_size; else if (MaxRows > 0 && MaxCols > 0)
return (MaxRows * MaxCols) <= max_static_size;
// Everything dynamic already // Everything dynamic already
else return false; else return false;
}(); }();
} }
#endif #endif
@ -122,16 +120,17 @@ namespace rotgen
inline std::ostream& setup_summary(std::ostream& os) inline std::ostream& setup_summary(std::ostream& os)
{ {
detail::dynamic_info(os); detail::dynamic_info(os);
os << " * Default alignment: " << default_alignment << " bytes." << std::endl; os << " * Default alignment: " << default_alignment << " bytes."
if(!is_forcing_dynamic_status) << std::endl;
if (!is_forcing_dynamic_status)
{ {
if constexpr(use_expression_templates) if constexpr (use_expression_templates)
os << " * Expression templates : Enabled." << std::endl; os << " * Expression templates : Enabled." << std::endl;
else else os << " * Expression templates : Disabled." << std::endl;
os << " * Expression templates : Disabled." << std::endl;
if constexpr(rotgen::max_static_size) if constexpr (rotgen::max_static_size)
os << " * Static/Dynamic mode with maximum size: " << rotgen::max_static_size << std::endl; os << " * Static/Dynamic mode with maximum size: "
<< rotgen::max_static_size << std::endl;
} }
return os; return os;

View file

@ -18,38 +18,43 @@ namespace rotgen
template<typename T, int Options = T::storage_order, typename Stride = stride> template<typename T, int Options = T::storage_order, typename Stride = stride>
class ref; 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>
{ {
public: public:
static_assert ( concepts::entity<Ref> static_assert(concepts::entity<Ref>,
, "[ROTGEN][CRITICAL] - Block of non-rotgen type instanciated" "[ROTGEN][CRITICAL] - Block of non-rotgen type instanciated");
);
using parent = find_block<Ref>; using parent = find_block<Ref>;
using rotgen_tag = void; using rotgen_tag = void;
using rotgen_block_tag = void; using rotgen_block_tag = void;
using value_type = typename std::remove_const_t<Ref>::value_type; using value_type = typename std::remove_const_t<Ref>::value_type;
static constexpr int storage_order = Ref::storage_order; static constexpr int storage_order = Ref::storage_order;
static constexpr bool is_immutable = std::is_const_v<Ref>; static constexpr bool is_immutable = std::is_const_v<Ref>;
using concrete_type = matrix<value_type,Rows,Cols,storage_order>; using concrete_type = matrix<value_type, Rows, Cols, storage_order>;
using transposed_type = matrix<value_type,Cols,Rows, storage_order>; using transposed_type = matrix<value_type, Cols, Rows, storage_order>;
using concrete_dynamic_type = matrix<value_type,Dynamic,Dynamic,storage_order>; using concrete_dynamic_type =
matrix<value_type, Dynamic, Dynamic, storage_order>;
static constexpr int RowsAtCompileTime = Rows; static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols; static constexpr int ColsAtCompileTime = Cols;
static constexpr int MaxRowsAtCompileTime = Rows; static constexpr int MaxRowsAtCompileTime = Rows;
static constexpr int MaxColsAtCompileTime = Cols; static constexpr int MaxColsAtCompileTime = Cols;
static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime; static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime;
static constexpr int Options = Ref::Options; static constexpr int Options = Ref::Options;
static constexpr bool IsRowMajor = (storage_order & RowMajor) == RowMajor; static constexpr bool IsRowMajor = (storage_order & RowMajor) == RowMajor;
static constexpr bool is_defined_static = false; static constexpr bool is_defined_static = false;
static constexpr bool has_static_storage = false; static constexpr bool has_static_storage = false;
using parent::operator=; using parent::operator=;
block& operator=(concepts::entity auto const& other) requires(!is_immutable)
block& operator=(concepts::entity auto const& other)
requires(!is_immutable)
{ {
assert(parent::rows() == other.rows() && parent::cols() == other.cols()); assert(parent::rows() == other.rows() && parent::cols() == other.cols());
for (rotgen::Index r = 0; r < parent::rows(); ++r) for (rotgen::Index r = 0; r < parent::rows(); ++r)
@ -59,117 +64,191 @@ namespace rotgen
return *this; return *this;
} }
block(Ref const& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) block(Ref const& r,
requires( !requires{typename Ref::rotgen_block_tag; } && is_immutable) std::size_t i0,
: parent(r.base(),i0,j0,ni,nj) std::size_t j0,
{} std::size_t ni,
std::size_t nj)
requires(!requires { typename Ref::rotgen_block_tag; } && is_immutable)
: 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,
requires( requires{typename Ref::rotgen_block_tag; } && is_immutable) std::size_t i0,
: parent(*r.storage(),i0,j0,ni,nj) 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)
{
}
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 &&
: parent(r.base(),i0,j0,Rows,Cols) Cols != -1 && is_immutable)
{} : 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)
requires(requires{typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && is_immutable) requires(requires { typename Ref::rotgen_block_tag; } && Rows != -1 &&
: parent(*r.storage(),i0,j0,Rows,Cols) Cols != -1 && is_immutable)
{} : parent(*r.storage(), i0, j0, Rows, Cols)
{
}
block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) block(
requires( !requires{typename Ref::rotgen_block_tag; } && !is_immutable) Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
: parent(r.base(),i0,j0,ni,nj) requires(!requires { typename Ref::rotgen_block_tag; } && !is_immutable)
{} : 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(
requires( requires{typename Ref::rotgen_block_tag; } && !is_immutable) Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
: parent(*r.storage(),i0,j0,ni,nj) requires(requires { typename Ref::rotgen_block_tag; } && !is_immutable)
{} : parent(*r.storage(), 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(!requires{typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && !is_immutable) requires(!requires { typename Ref::rotgen_block_tag; } && Rows != -1 &&
: parent(r.base(),i0,j0,Rows,Cols) Cols != -1 && !is_immutable)
{} : 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)
requires(requires{typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && !is_immutable) requires(requires { typename Ref::rotgen_block_tag; } && Rows != -1 &&
: parent(*r.storage(),i0,j0,Rows,Cols) Cols != -1 && !is_immutable)
{} : parent(*r.storage(), i0, j0, Rows, Cols)
{
}
block(parent const& base) : parent(base) {} block(parent const& base) : parent(base) {}
bool is_contiguous_linear() const bool is_contiguous_linear() const
{ {
if(parent::innerStride() != 1) return false; if (parent::innerStride() != 1) return false;
if constexpr(storage_order) return parent::outerStride() == parent::cols(); if constexpr (storage_order)
else return parent::outerStride() == parent::rows(); return parent::outerStride() == parent::cols();
else return parent::outerStride() == parent::rows();
} }
value_type& operator()(Index i, Index j) requires(!is_immutable) { return parent::operator()(i,j); } value_type& operator()(Index i, Index j)
requires(!is_immutable)
{
return parent::operator()(i, j);
}
value_type& operator()(Index i) requires(!is_immutable && IsVectorAtCompileTime) value_type& operator()(Index i)
requires(!is_immutable && IsVectorAtCompileTime)
{ {
assert(is_contiguous_linear()); assert(is_contiguous_linear());
return parent::operator()(i); return parent::operator()(i);
} }
value_type& operator[](Index i) requires(!is_immutable && IsVectorAtCompileTime) value_type& operator[](Index i)
requires(!is_immutable && IsVectorAtCompileTime)
{ {
return (*this)(i); return (*this)(i);
} }
value_type operator()(Index i, Index j) const { return parent::operator()(i,j); } value_type operator()(Index i, Index j) const
{
return parent::operator()(i, j);
}
value_type operator()(Index i) const requires(IsVectorAtCompileTime) value_type operator()(Index i) const
requires(IsVectorAtCompileTime)
{ {
assert(is_contiguous_linear()); assert(is_contiguous_linear());
return parent::operator()(i); return parent::operator()(i);
} }
value_type operator[](Index i) const requires(IsVectorAtCompileTime) value_type operator[](Index i) const
requires(IsVectorAtCompileTime)
{ {
return (*this)(i); return (*this)(i);
} }
auto evaluate() const { return *this; } auto evaluate() const { return *this; }
decltype(auto) noalias() const { return *this; }
decltype(auto) noalias() { return *this; }
concrete_type normalized() const requires(IsVectorAtCompileTime) decltype(auto) noalias() const { return *this; }
decltype(auto) noalias() { return *this; }
concrete_type normalized() const
requires(IsVectorAtCompileTime)
{ {
return concrete_type(base().normalized()); return concrete_type(base().normalized());
} }
transposed_type transpose() const { return transposed_type(base().transpose());}
concrete_type conjugate() const { return concrete_type(base().conjugate());}
transposed_type adjoint() const { return transposed_type(base().adjoint());}
concrete_type cwiseAbs() const { return concrete_type(base().cwiseAbs()); } transposed_type transpose() const
concrete_type cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); } {
concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); } return transposed_type(base().transpose());
concrete_type cwiseSqrt() const { return concrete_type(base().cwiseSqrt()); } }
void normalize() requires(!is_immutable && IsVectorAtCompileTime) concrete_type conjugate() const
{
return concrete_type(base().conjugate());
}
transposed_type adjoint() const
{
return transposed_type(base().adjoint());
}
concrete_type cwiseAbs() const { return concrete_type(base().cwiseAbs()); }
concrete_type cwiseAbs2() const
{
return concrete_type(base().cwiseAbs2());
}
concrete_type cwiseInverse() const
{
return concrete_type(base().cwiseInverse());
}
concrete_type cwiseSqrt() const
{
return concrete_type(base().cwiseSqrt());
}
void normalize()
requires(!is_immutable && IsVectorAtCompileTime)
{ {
parent::normalize(); parent::normalize();
} }
void transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); }
void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); } void transposeInPlace()
requires(!is_immutable)
{
parent::transposeInPlace();
}
void adjointInPlace()
requires(!is_immutable)
{
parent::adjointInPlace();
}
friend bool operator==(block const& lhs, block const& rhs) friend bool operator==(block const& lhs, block const& rhs)
{ {
return static_cast<parent const&>(lhs) == static_cast<parent const&>(rhs); return static_cast<parent const&>(lhs) == static_cast<parent const&>(rhs);
} }
block& operator+=(block const& rhs) requires(!is_immutable) block& operator+=(block const& rhs)
requires(!is_immutable)
{ {
base() += static_cast<parent const&>(rhs); base() += static_cast<parent const&>(rhs);
return *this; return *this;
} }
block& operator-=(block const& rhs) requires(!is_immutable) block& operator-=(block const& rhs)
requires(!is_immutable)
{ {
base() -= static_cast<parent const&>(rhs); base() -= static_cast<parent const&>(rhs);
return *this; return *this;
@ -180,31 +259,35 @@ namespace rotgen
return concrete_type(static_cast<parent const&>(*this).operator-()); return concrete_type(static_cast<parent const&>(*this).operator-());
} }
block& operator*=(block const& rhs) requires(!is_immutable) block& operator*=(block const& rhs)
requires(!is_immutable)
{ {
base() *= static_cast<parent const&>(rhs); base() *= static_cast<parent const&>(rhs);
return *this; return *this;
} }
block& operator*=(value_type rhs) requires(!is_immutable) block& operator*=(value_type rhs)
requires(!is_immutable)
{ {
base() *= rhs; base() *= rhs;
return *this; return *this;
} }
block& operator/=(value_type rhs) requires(!is_immutable) block& operator/=(value_type rhs)
requires(!is_immutable)
{ {
base() /= rhs; base() /= rhs;
return *this; return *this;
} }
auto minCoeff() const { return parent::minCoeff(); } auto minCoeff() const { return parent::minCoeff(); }
auto maxCoeff() const { return parent::maxCoeff(); } auto maxCoeff() const { return parent::maxCoeff(); }
template<std::integral IndexType> template<std::integral IndexType>
auto minCoeff(IndexType* row, IndexType* col) const auto minCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::minCoeff(&r, &c); auto result = parent::minCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
@ -214,7 +297,7 @@ namespace rotgen
template<std::integral IndexType> template<std::integral IndexType>
auto maxCoeff(IndexType* row, IndexType* col) const auto maxCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::maxCoeff(&r, &c); auto result = parent::maxCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
@ -222,109 +305,134 @@ namespace rotgen
} }
static concrete_type Zero() static concrete_type Zero()
requires (Rows != -1 && Cols != -1) requires(Rows != -1 && Cols != -1)
{ {
return parent::Zero(Rows, Cols); return parent::Zero(Rows, Cols);
} }
static concrete_type Zero(int rows, int cols) static concrete_type Zero(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Zero(rows, cols); return parent::Zero(rows, cols);
} }
static concrete_type Ones() static concrete_type Ones()
requires (Rows != -1 && Cols != -1) requires(Rows != -1 && Cols != -1)
{ {
return parent::Ones(Rows, Cols); return parent::Ones(Rows, Cols);
} }
static concrete_type Ones(int rows, int cols) static concrete_type Ones(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Ones(rows, cols); return parent::Ones(rows, cols);
} }
static concrete_type Constant(value_type value) static concrete_type Constant(value_type value)
requires (Rows != -1 && Cols != -1) requires(Rows != -1 && Cols != -1)
{ {
return parent::Constant(Rows, Cols, static_cast<double>(value)); return parent::Constant(Rows, Cols, static_cast<double>(value));
} }
static concrete_type Constant(int rows, int cols, value_type value) static concrete_type Constant(int rows, int cols, value_type value)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Constant(rows, cols, static_cast<double>(value)); return parent::Constant(rows, cols, static_cast<double>(value));
} }
static concrete_type Random() static concrete_type Random()
requires (Rows != -1 && Cols != -1) requires(Rows != -1 && Cols != -1)
{ {
return parent::Random(Rows, Cols); return parent::Random(Rows, Cols);
} }
static concrete_type Random(int rows, int cols) static concrete_type Random(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Random(rows, cols); return parent::Random(rows, cols);
} }
static concrete_type Identity() static concrete_type Identity()
requires (Rows != -1 && Cols != -1) requires(Rows != -1 && Cols != -1)
{ {
return parent::Identity(Rows, Cols); return parent::Identity(Rows, Cols);
} }
static concrete_type Identity(int rows, int cols) static concrete_type Identity(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Identity(rows, cols); return parent::Identity(rows, cols);
} }
block& setOnes() requires(!is_immutable) block& setOnes()
requires(!is_immutable)
{ {
parent::assign(parent::Ones(parent::rows(), parent::cols())); parent::assign(parent::Ones(parent::rows(), parent::cols()));
return *this; return *this;
} }
block& setZero() requires(!is_immutable) block& setZero()
requires(!is_immutable)
{ {
parent::assign(parent::Zero(parent::rows(), parent::cols())); parent::assign(parent::Zero(parent::rows(), parent::cols()));
return *this; return *this;
} }
block& setConstant(value_type value) requires(!is_immutable) block& setConstant(value_type value)
requires(!is_immutable)
{ {
parent::assign(parent::Constant(parent::rows(), parent::cols(), value)); parent::assign(parent::Constant(parent::rows(), parent::cols(), value));
return *this; return *this;
} }
block& setRandom() requires(!is_immutable) block& setRandom()
requires(!is_immutable)
{ {
parent::assign(parent::Random(parent::rows(), parent::cols())); parent::assign(parent::Random(parent::rows(), parent::cols()));
return *this; return *this;
} }
block& setIdentity() requires(!is_immutable) block& setIdentity()
requires(!is_immutable)
{ {
parent::assign(parent::Identity(parent::rows(), parent::cols())); parent::assign(parent::Identity(parent::rows(), parent::cols()));
return *this; return *this;
} }
template<int P> template<int P> value_type lpNorm() const
value_type lpNorm() const
{ {
assert(P == 1 || P == 2 || P == Infinity); assert(P == 1 || P == 2 || P == Infinity);
return parent::lpNorm(P); return parent::lpNorm(P);
} }
parent& base() { return static_cast<parent&>(*this); } parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
}; };
template<typename Ref, int R, int C, bool I> template<typename Ref, int R, int C, bool I>

View file

@ -21,39 +21,69 @@ namespace rotgen
class matrix_impl32_row; class matrix_impl32_row;
class matrix_impl32_col; class matrix_impl32_col;
#define USE_CONST
#define CONST const
#define BASENAME block_const_impl
#define BASEMAP map_const_impl
#include <rotgen/container/block/dynamic/indirect.hpp>
#undef BASENAME
#undef BASEMAP
#undef CONST
#undef USE_CONST
#define USE_CONST #define CONST
#define CONST const #define BASENAME block_impl
#define BASENAME block_const_impl #define BASEMAP map_impl
#define BASEMAP map_const_impl #include <rotgen/container/block/dynamic/indirect.hpp>
#include <rotgen/container/block/dynamic/indirect.hpp> #undef BASENAME
#undef BASENAME #undef BASEMAP
#undef BASEMAP #undef CONST
#undef CONST
#undef USE_CONST
#define CONST template<typename Scalar, int Options, bool isConst> struct find_block_impl;
#define BASENAME block_impl
#define BASEMAP map_impl
#include <rotgen/container/block/dynamic/indirect.hpp>
#undef BASENAME
#undef BASEMAP
#undef CONST
template<typename Scalar,int Options, bool isConst> struct find_block_impl; template<> struct find_block_impl<float, ColMajor, true>
{
using type = block_const_impl32_col;
};
template<> struct find_block_impl<float , ColMajor, true> { using type = block_const_impl32_col; }; template<> struct find_block_impl<float, RowMajor, true>
template<> struct find_block_impl<float , RowMajor, true> { using type = block_const_impl32_row; }; {
template<> struct find_block_impl<double, ColMajor, true> { using type = block_const_impl64_col; }; using type = block_const_impl32_row;
template<> struct find_block_impl<double, RowMajor, true> { using type = block_const_impl64_row; }; };
template<> struct find_block_impl<float , ColMajor, false> { using type = block_impl32_col; };
template<> struct find_block_impl<float , RowMajor, false> { using type = block_impl32_row; }; template<> struct find_block_impl<double, ColMajor, true>
template<> struct find_block_impl<double, ColMajor, false> { using type = block_impl64_col; }; {
template<> struct find_block_impl<double, RowMajor, false> { using type = block_impl64_row; }; using type = block_const_impl64_col;
};
template<> struct find_block_impl<double, RowMajor, true>
{
using type = block_const_impl64_row;
};
template<> struct find_block_impl<float, ColMajor, false>
{
using type = block_impl32_col;
};
template<> struct find_block_impl<float, RowMajor, false>
{
using type = block_impl32_row;
};
template<> struct find_block_impl<double, ColMajor, false>
{
using type = block_impl64_col;
};
template<> struct find_block_impl<double, RowMajor, false>
{
using type = block_impl64_row;
};
template<typename Ref> template<typename Ref>
using find_block = typename find_block_impl < typename std::remove_const_t<Ref>::value_type using find_block =
, Ref::storage_order typename find_block_impl<typename std::remove_const_t<Ref>::value_type,
, std::is_const_v<Ref> Ref::storage_order,
>::type; std::is_const_v<Ref>>::type;
} }

View file

@ -1,51 +1,51 @@
#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 SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP,SIZE,_col) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _col)
#include <rotgen/container/block/dynamic/model.hpp> #include <rotgen/container/block/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
#undef SOURCENAME #undef SOURCENAME
#undef MAPNAME #undef MAPNAME
#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 SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP,SIZE,_row) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _row)
#include <rotgen/container/block/dynamic/model.hpp> #include <rotgen/container/block/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
#undef SOURCENAME #undef SOURCENAME
#undef MAPNAME #undef MAPNAME
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
#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 SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP,SIZE,_col) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _col)
#include <rotgen/container/block/dynamic/model.hpp> #include <rotgen/container/block/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
#undef SOURCENAME #undef SOURCENAME
#undef MAPNAME #undef MAPNAME
#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 SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP,SIZE,_row) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _row)
#include <rotgen/container/block/dynamic/model.hpp> #include <rotgen/container/block/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
#undef SOURCENAME #undef SOURCENAME
#undef MAPNAME #undef MAPNAME
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE

View file

@ -13,28 +13,28 @@
//================================================================================================== //==================================================================================================
class ROTGEN_EXPORT CLASSNAME class ROTGEN_EXPORT CLASSNAME
{ {
private: private:
struct payload; struct payload;
std::unique_ptr<payload> storage_; std::unique_ptr<payload> storage_;
public: public:
CLASSNAME(SOURCENAME CONST& r , Index i0, Index j0, Index ni, Index nj); CLASSNAME(SOURCENAME CONST& r, Index i0, Index j0, Index ni, Index nj);
CLASSNAME(MAPNAME 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(payload const& r, Index i0, Index j0, Index ni, Index nj);
CLASSNAME(CLASSNAME const& other); CLASSNAME(CLASSNAME const& other);
CLASSNAME(CLASSNAME&&) noexcept; CLASSNAME(CLASSNAME&&) noexcept;
#if !defined(USE_CONST) #if !defined(USE_CONST)
CLASSNAME& operator=(CLASSNAME const& other); CLASSNAME& operator=(CLASSNAME const& other);
CLASSNAME& operator=(CLASSNAME&&) noexcept; CLASSNAME& operator=(CLASSNAME&&) noexcept;
#endif #endif
~CLASSNAME(); ~CLASSNAME();
#if !defined(USE_CONST) #if !defined(USE_CONST)
void assign(SOURCENAME const&); void assign(SOURCENAME const&);
#endif #endif
Index rows() const; Index rows() const;
Index cols() const; Index cols() const;
@ -46,44 +46,44 @@ class ROTGEN_EXPORT CLASSNAME
Index startRow() const; Index startRow() const;
Index startCol() const; Index startCol() const;
SOURCENAME normalized() const; SOURCENAME normalized() const;
SOURCENAME transpose() const; SOURCENAME transpose() const;
SOURCENAME conjugate() const; SOURCENAME conjugate() const;
SOURCENAME adjoint() const; SOURCENAME adjoint() const;
SOURCENAME cwiseAbs() const; SOURCENAME cwiseAbs() const;
SOURCENAME cwiseAbs2() const; SOURCENAME cwiseAbs2() const;
SOURCENAME cwiseInverse() const; SOURCENAME cwiseInverse() const;
SOURCENAME cwiseSqrt() const; SOURCENAME cwiseSqrt() const;
#if !defined(USE_CONST) #if !defined(USE_CONST)
void normalize(); void normalize();
void transposeInPlace(); void transposeInPlace();
void adjointInPlace(); void adjointInPlace();
#endif #endif
TYPE sum() const; TYPE sum() const;
TYPE prod() const; TYPE prod() const;
TYPE mean() const; TYPE mean() const;
TYPE trace() const; TYPE trace() const;
TYPE maxCoeff() const; TYPE maxCoeff() const;
TYPE minCoeff() const; TYPE minCoeff() const;
TYPE maxCoeff(Index* row, Index* col) const; TYPE maxCoeff(Index* row, Index* col) const;
TYPE minCoeff(Index* row, Index* col) const; TYPE minCoeff(Index* row, Index* col) const;
TYPE squaredNorm() const; TYPE squaredNorm() const;
TYPE norm() const; TYPE norm() const;
TYPE lpNorm(int p) const; TYPE lpNorm(int p) const;
#if !defined(USE_CONST) #if !defined(USE_CONST)
TYPE& operator()(Index i, Index j); TYPE& operator()(Index i, Index j);
TYPE& operator()(Index index); TYPE& operator()(Index index);
CLASSNAME& operator+=(CLASSNAME const& rhs); CLASSNAME& operator+=(CLASSNAME const& rhs);
CLASSNAME& operator-=(CLASSNAME const& rhs); CLASSNAME& operator-=(CLASSNAME const& rhs);
CLASSNAME& operator*=(CLASSNAME const& rhs); CLASSNAME& operator*=(CLASSNAME const& rhs);
CLASSNAME& operator*=(TYPE d); CLASSNAME& operator*=(TYPE d);
CLASSNAME& operator/=(TYPE d); CLASSNAME& operator/=(TYPE d);
#endif #endif
TYPE operator()(Index i, Index j) const; TYPE operator()(Index i, Index j) const;
TYPE operator()(Index index) const; TYPE operator()(Index index) const;
@ -95,26 +95,43 @@ class ROTGEN_EXPORT CLASSNAME
SOURCENAME mul(TYPE s) const; SOURCENAME mul(TYPE s) const;
SOURCENAME div(TYPE s) const; SOURCENAME div(TYPE s) const;
friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&,CLASSNAME const&); friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&,
friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&, format<CLASSNAME> const&); CLASSNAME const&);
friend ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs); friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&,
friend ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs); format<CLASSNAME> const&);
friend ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs,
CLASSNAME const& rhs);
friend ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs,
CLASSNAME const& rhs);
#if !defined(USE_CONST) #if !defined(USE_CONST)
TYPE* data(); TYPE* data();
#endif #endif
const TYPE* data() const; const TYPE* data() const;
static SOURCENAME Zero(Index r, Index c) { return SOURCENAME::Zero(r,c); } static SOURCENAME Zero(Index r, Index c) { return SOURCENAME::Zero(r, c); }
static SOURCENAME Ones(Index r, Index c) { return SOURCENAME::Ones(r,c); }
static SOURCENAME Constant(Index r, Index c, TYPE v) { return SOURCENAME::Constant(r,c,v); }
static SOURCENAME Random(Index r, Index c) { return SOURCENAME::Random(r,c); }
static SOURCENAME Identity(Index r, Index c) { return SOURCENAME::Identity(r,c); }
public: static SOURCENAME Ones(Index r, Index c) { return SOURCENAME::Ones(r, c); }
#if !defined(USE_CONST)
std::unique_ptr<payload>& storage() { return storage_; } static SOURCENAME Constant(Index r, Index c, TYPE v)
#endif {
return SOURCENAME::Constant(r, c, v);
}
static SOURCENAME Random(Index r, Index c)
{
return SOURCENAME::Random(r, c);
}
static SOURCENAME Identity(Index r, Index c)
{
return SOURCENAME::Identity(r, c);
}
public:
#if !defined(USE_CONST)
std::unique_ptr<payload>& storage() { return storage_; }
#endif
std::unique_ptr<payload> const& storage() const { return storage_; } std::unique_ptr<payload> const& storage() const { return storage_; }
}; };

View file

@ -21,99 +21,136 @@ namespace rotgen
template<typename Ref, int Rows, int Cols, bool Inner, bool IsConst> template<typename Ref, int Rows, int Cols, bool Inner, bool IsConst>
struct compute_block_type struct compute_block_type
{ {
using ref_t = std::conditional_t<IsConst, typename Ref::parent const, typename Ref::parent>; using ref_t = std::conditional_t<IsConst,
typename Ref::parent const,
typename Ref::parent>;
using type = std::conditional_t < storage_status<Rows,Cols,Rows,Cols> using type = std::conditional_t<
, Eigen::Block<ref_t, Rows, Cols, Inner> storage_status<Rows, Cols, Rows, Cols>,
, Eigen::Block<ref_t, Eigen::Dynamic, Eigen::Dynamic, Inner> Eigen::Block<ref_t, Rows, Cols, Inner>,
>; Eigen::Block<ref_t, Eigen::Dynamic, Eigen::Dynamic, Inner>>;
}; };
template<typename T, int O, typename S, int Rows, int Cols, bool Inner, bool IsConst> template<typename T,
struct compute_block_type<ref<T,O,S>,Rows,Cols,Inner,IsConst> int O,
: compute_block_type<typename ref<T,O,S>::parent,Rows,Cols,Inner,IsConst> 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;
} }
template< typename Ref template<typename Ref,
, int Rows = Dynamic, int Cols = Dynamic int Rows = Dynamic,
, bool Inner = false , int ForceStorageOrder = -1 int Cols = Dynamic,
> bool Inner = false,
class block : private detail::block_type<std::remove_const_t<Ref>, Rows, Cols, Inner,std::is_const_v<Ref> > int ForceStorageOrder = -1>
class block : private detail::block_type<std::remove_const_t<Ref>,
Rows,
Cols,
Inner,
std::is_const_v<Ref>>
{ {
static_assert ( concepts::entity<Ref> static_assert(concepts::entity<Ref>,
, "[ROTGEN][CRITICAL] - Block of non-rotgen type instanciated" "[ROTGEN][CRITICAL] - Block of non-rotgen type instanciated");
);
public: public:
using rotgen_tag = void; using rotgen_tag = void;
using rotgen_block_tag = void; using rotgen_block_tag = void;
using parent = detail::block_type<std::remove_const_t<Ref>, Rows, Cols, Inner,std::is_const_v<Ref>>; using parent = detail::block_type<std::remove_const_t<Ref>,
using value_type = typename parent::value_type; Rows,
using Index = typename parent::Index; Cols,
Inner,
std::is_const_v<Ref>>;
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 int storage_order =
static constexpr bool is_immutable = std::is_const_v<Ref>; (ForceStorageOrder == -1) ? Ref::storage_order : ForceStorageOrder;
static constexpr bool is_immutable = std::is_const_v<Ref>;
static constexpr bool IsRowMajor = parent::IsRowMajor; static constexpr bool IsRowMajor = parent::IsRowMajor;
using concrete_type = matrix<value_type,Rows,Cols,storage_order>; using concrete_type = matrix<value_type, Rows, Cols, storage_order>;
using concrete_dynamic_type = matrix<value_type,Dynamic,Dynamic,storage_order>; using concrete_dynamic_type =
matrix<value_type, Dynamic, Dynamic, storage_order>;
template<typename ET> template<typename ET>
using as_concrete_type = detail::as_concrete_t<ET, matrix>; using as_concrete_type = detail::as_concrete_t<ET, matrix>;
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;
static constexpr int MaxRowsAtCompileTime = Ref::MaxRowsAtCompileTime; static constexpr int MaxRowsAtCompileTime = Ref::MaxRowsAtCompileTime;
static constexpr int MaxColsAtCompileTime = Ref::MaxColsAtCompileTime; static constexpr int MaxColsAtCompileTime = Ref::MaxColsAtCompileTime;
static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime; static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime;
static constexpr bool is_defined_static = Rows!=-1 && Cols!=-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 has_static_storage =
storage_status<Rows, Cols, Rows, Cols>;
public: public:
block(const block& other) = default; block(block const& other) = default;
block(block&& other) = default; block(block&& other) = default;
block& operator=(const block&) = default; block& operator=(block const&) = default;
block& operator=(block&&) = default; block& operator=(block&&) = default;
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)
: 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)
: 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)
: 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)
: parent(r.base(),i0,j0,Rows,Cols) : parent(r.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())
{} {
}
template<typename OtherDerived> template<typename OtherDerived>
block(const Eigen::MatrixBase<OtherDerived>& other) : parent(other) {} block(Eigen::MatrixBase<OtherDerived> const& other) : parent(other)
{
}
template<typename OtherDerived> template<typename OtherDerived>
block(const Eigen::EigenBase<OtherDerived>& other) : parent(other) {} block(Eigen::EigenBase<OtherDerived> const& other) : parent(other)
{
}
block(concepts::entity auto const& other) : parent(other.base()) block(concepts::entity auto const& other) : parent(other.base()) {}
{}
block& operator=(concepts::entity auto const& other) block& operator=(concepts::entity auto const& other)
{ {
@ -122,21 +159,22 @@ namespace rotgen
} }
template<typename OtherDerived> template<typename OtherDerived>
block& operator=(const Eigen::MatrixBase<OtherDerived>& other) block& operator=(Eigen::MatrixBase<OtherDerived> const& other)
{ {
parent::operator=(other); parent::operator=(other);
return *this; return *this;
} }
template<typename OtherDerived> template<typename OtherDerived>
block& operator=(const Eigen::EigenBase<OtherDerived>& other) block& operator=(Eigen::EigenBase<OtherDerived> const& other)
{ {
parent::operator=(other); parent::operator=(other);
return *this; return *this;
} }
parent& base() { return static_cast<parent&>(*this); } parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
auto evaluate() const auto evaluate() const
{ {
@ -146,239 +184,308 @@ namespace rotgen
decltype(auto) noalias() const decltype(auto) noalias() const
{ {
if constexpr(use_expression_templates) return base().noalias(); if constexpr (use_expression_templates) return base().noalias();
else return *this; else return *this;
} }
decltype(auto) noalias() decltype(auto) noalias()
{ {
if constexpr(use_expression_templates) return base().noalias(); if constexpr (use_expression_templates) return base().noalias();
else return *this; else return *this;
} }
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();
else return as_concrete_type<decltype(base().normalized())>(base().normalized()); else
return as_concrete_type<decltype(base().normalized())>(
base().normalized());
} }
auto transpose() const auto transpose() const
{ {
if constexpr(use_expression_templates) return base().transpose(); if constexpr (use_expression_templates) return base().transpose();
else return as_concrete_type<decltype(base().transpose())>(base().transpose()); else
return as_concrete_type<decltype(base().transpose())>(
base().transpose());
} }
auto adjoint() const auto adjoint() const
{ {
if constexpr(use_expression_templates) return base().adjoint(); if constexpr (use_expression_templates) return base().adjoint();
else return as_concrete_type<decltype(base().adjoint())>(base().adjoint()); else
return as_concrete_type<decltype(base().adjoint())>(base().adjoint());
} }
auto conjugate() const auto conjugate() const
{ {
if constexpr(use_expression_templates) return base().conjugate(); if constexpr (use_expression_templates) return base().conjugate();
else return as_concrete_type<decltype(base().conjugate())>(base().conjugate()); else
return as_concrete_type<decltype(base().conjugate())>(
base().conjugate());
} }
void normalize() requires(!is_immutable && IsVectorAtCompileTime) void normalize()
requires(!is_immutable && IsVectorAtCompileTime)
{ {
parent::normalize(); parent::normalize();
} }
void transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); } void transposeInPlace()
void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); } requires(!is_immutable)
{
parent::transposeInPlace();
}
void adjointInPlace()
requires(!is_immutable)
{
parent::adjointInPlace();
}
auto cwiseAbs() const auto cwiseAbs() const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseAbs()}; if constexpr (!use_expression_templates)
else return base().cwiseAbs(); return concrete_type{parent::cwiseAbs()};
else return base().cwiseAbs();
} }
auto cwiseAbs2() const auto cwiseAbs2() const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseAbs2()}; if constexpr (!use_expression_templates)
else return base().cwiseAbs2(); return concrete_type{parent::cwiseAbs2()};
else return base().cwiseAbs2();
} }
auto cwiseInverse() const auto cwiseInverse() const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseInverse()}; if constexpr (!use_expression_templates)
else return base().cwiseInverse(); return concrete_type{parent::cwiseInverse()};
else return base().cwiseInverse();
} }
auto cwiseSqrt() const auto cwiseSqrt() const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseSqrt()}; if constexpr (!use_expression_templates)
else return base().cwiseSqrt(); return concrete_type{parent::cwiseSqrt()};
else return base().cwiseSqrt();
} }
static concrete_type Constant(value_type value) requires (Rows != -1 && Cols != -1) static concrete_type Constant(value_type value)
requires(Rows != -1 && Cols != -1)
{ {
return parent::Constant(Rows, Cols, static_cast<value_type>(value)); return parent::Constant(Rows, Cols, static_cast<value_type>(value));
} }
static concrete_type Constant(int rows, int cols, value_type value) static concrete_type Constant(int rows, int cols, value_type value)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Constant(rows, cols, static_cast<value_type>(value)); return parent::Constant(rows, cols, static_cast<value_type>(value));
} }
static concrete_type Identity() requires (Rows != -1 && Cols != -1) static concrete_type Identity()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Identity(Rows, Cols); return parent::Identity(Rows, Cols);
} }
static concrete_type Identity(int rows, int cols) static concrete_type Identity(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Identity(rows, cols); return parent::Identity(rows, cols);
} }
static concrete_type Zero() requires (Rows != -1 && Cols != -1) static concrete_type Zero()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Zero(Rows, Cols); return parent::Zero(Rows, Cols);
} }
static concrete_type Zero(int rows, int cols) static concrete_type Zero(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Zero(rows, cols); return parent::Zero(rows, cols);
} }
static concrete_type Ones() requires (Rows != -1 && Cols != -1) static concrete_type Ones()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Ones(Rows, Cols); return parent::Ones(Rows, Cols);
} }
static concrete_type Ones(int rows, int cols) static concrete_type Ones(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Ones(rows, cols); return parent::Ones(rows, cols);
} }
static concrete_type Random() requires (Rows != -1 && Cols != -1) static concrete_type Random()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Random(Rows, Cols); return parent::Random(Rows, Cols);
} }
static concrete_type Random(int rows, int cols) static concrete_type Random(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Random(rows, cols); return parent::Random(rows, cols);
} }
block& setOnes() requires(!is_immutable) block& setOnes()
requires(!is_immutable)
{ {
*this = parent::Ones(rows(), cols()); *this = parent::Ones(rows(), cols());
return *this; return *this;
} }
block& setOnes(int r, int c) requires(!is_immutable) block& setOnes(int r, int c)
requires(!is_immutable)
{ {
*this = parent::Ones(r, c); *this = parent::Ones(r, c);
return *this; return *this;
} }
block& setZero() requires(!is_immutable) block& setZero()
requires(!is_immutable)
{ {
*this = parent::Zero(rows(), cols()); *this = parent::Zero(rows(), cols());
return *this; return *this;
} }
block& setZero(int r, int c) requires(!is_immutable) block& setZero(int r, int c)
requires(!is_immutable)
{ {
*this = parent::Zero(r,c); *this = parent::Zero(r, c);
return *this; return *this;
} }
block& setConstant(value_type value) requires(!is_immutable) block& setConstant(value_type value)
requires(!is_immutable)
{ {
*this = parent::Constant(rows(), cols(), value); *this = parent::Constant(rows(), cols(), value);
return *this; return *this;
} }
block& setConstant(int r, int c, value_type value) requires(!is_immutable) block& setConstant(int r, int c, value_type value)
requires(!is_immutable)
{ {
*this = parent::Constant(r,c, value); *this = parent::Constant(r, c, value);
return *this; return *this;
} }
block& setRandom() requires(!is_immutable) block& setRandom()
requires(!is_immutable)
{ {
*this = parent::Random(rows(),cols()); *this = parent::Random(rows(), cols());
return *this; return *this;
} }
block& setRandom(int r, int c) requires(!is_immutable) block& setRandom(int r, int c)
requires(!is_immutable)
{ {
*this = parent::Random(r,c); *this = parent::Random(r, c);
return *this; return *this;
} }
block& setIdentity() requires(!is_immutable) block& setIdentity()
requires(!is_immutable)
{ {
*this = parent::Identity(rows(),cols()); *this = parent::Identity(rows(), cols());
return *this; return *this;
} }
block& setIdentity(int r, int c) requires(!is_immutable) block& setIdentity(int r, int c)
requires(!is_immutable)
{ {
*this = parent::Identity(r,c); *this = parent::Identity(r, c);
return *this; return *this;
} }
template<int P> template<int P> value_type lpNorm() const
value_type lpNorm() const
{ {
static_assert(P == 1 || P == 2 || P == Infinity); static_assert(P == 1 || P == 2 || P == Infinity);
return parent::template lpNorm<P>(); return parent::template lpNorm<P>();
} }
value_type& operator()(Index i, Index j) requires(!is_immutable) value_type& operator()(Index i, Index j)
requires(!is_immutable)
{ {
return base()(i,j); return base()(i, j);
} }
value_type& operator()(Index i) requires(!is_immutable && IsVectorAtCompileTime) value_type& operator()(Index i)
requires(!is_immutable && IsVectorAtCompileTime)
{ {
return base().data()[i]; return base().data()[i];
} }
value_type& operator[](Index i) requires(!is_immutable && IsVectorAtCompileTime) value_type& operator[](Index i)
requires(!is_immutable && IsVectorAtCompileTime)
{ {
return (*this)(i); return (*this)(i);
} }
value_type operator()(Index i, Index j) const { return base()(i,j); } value_type operator()(Index i, Index j) const { return base()(i, j); }
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 base().data()[i];
}
value_type operator[](Index i) const
requires(IsVectorAtCompileTime)
{
return (*this)(i);
}
using parent::innerStride;
using parent::outerStride;
using parent::rows;
using parent::cols; using parent::cols;
using parent::size;
using parent::prod;
using parent::mean;
using parent::trace;
using parent::squaredNorm;
using parent::norm;
using parent::sum;
using parent::data; using parent::data;
using parent::innerStride;
using parent::mean;
using parent::norm;
using parent::outerStride;
using parent::prod;
using parent::rows;
using parent::size;
using parent::squaredNorm;
using parent::sum;
using parent::trace;
auto minCoeff() const { return parent::minCoeff(); } auto minCoeff() const { return parent::minCoeff(); }
auto maxCoeff() const { return parent::maxCoeff(); } auto maxCoeff() const { return parent::maxCoeff(); }
template<std::integral IndexType> template<std::integral IndexType>
auto minCoeff(IndexType* row, IndexType* col) const auto minCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::minCoeff(&r, &c); auto result = parent::minCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
@ -388,7 +495,7 @@ namespace rotgen
template<std::integral IndexType> template<std::integral IndexType>
auto maxCoeff(IndexType* row, IndexType* col) const auto maxCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::maxCoeff(&r, &c); auto result = parent::maxCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
@ -396,15 +503,18 @@ namespace rotgen
} }
Index startRow() const { return base().startRow(); } Index startRow() const { return base().startRow(); }
Index startCol() const { return base().startCol(); } Index startCol() const { return base().startCol(); }
block& operator+=(block const& rhs) requires(!is_immutable) block& operator+=(block const& rhs)
requires(!is_immutable)
{ {
static_cast<parent&>(*this) += static_cast<parent const&>(rhs); static_cast<parent&>(*this) += static_cast<parent const&>(rhs);
return *this; return *this;
} }
block& operator-=(block const& rhs) requires(!is_immutable) block& operator-=(block const& rhs)
requires(!is_immutable)
{ {
static_cast<parent&>(*this) -= static_cast<parent const&>(rhs); static_cast<parent&>(*this) -= static_cast<parent const&>(rhs);
return *this; return *this;
@ -415,19 +525,22 @@ namespace rotgen
return concrete_type(static_cast<parent const&>(*this).operator-()); return concrete_type(static_cast<parent const&>(*this).operator-());
} }
block& operator*=(block const& rhs) requires(!is_immutable) block& operator*=(block const& rhs)
requires(!is_immutable)
{ {
static_cast<parent&>(*this) *= static_cast<parent const&>(rhs); static_cast<parent&>(*this) *= static_cast<parent const&>(rhs);
return *this; return *this;
} }
block& operator*=(value_type rhs) requires(!is_immutable) block& operator*=(value_type rhs)
requires(!is_immutable)
{ {
static_cast<parent&>(*this) *= rhs; static_cast<parent&>(*this) *= rhs;
return *this; return *this;
} }
block& operator/=(value_type rhs) requires(!is_immutable) block& operator/=(value_type rhs)
requires(!is_immutable)
{ {
static_cast<parent&>(*this) /= rhs; static_cast<parent&>(*this) /= rhs;
return *this; return *this;

View file

@ -14,88 +14,106 @@
namespace rotgen namespace rotgen
{ {
template<typename Ref, int Options = Unaligned, typename Stride = rotgen::stride> template<typename Ref,
int Options = Unaligned,
typename Stride = rotgen::stride>
class map : public find_map<Ref> class map : public find_map<Ref>
{ {
public: public:
static_assert(concepts::entity<Ref>,
"[ROTGEN][CRITICAL] - Map of non-rotgen type instanciated");
static_assert ( concepts::entity<Ref> using parent = find_map<Ref>;
, "[ROTGEN][CRITICAL] - Map of non-rotgen type instanciated" using rotgen_tag = void;
); using value_type = typename std::remove_const_t<Ref>::value_type;
using concrete_type = typename std::remove_const_t<Ref>::concrete_type;
using parent = find_map<Ref>; static constexpr bool IsRowMajor = Ref::IsRowMajor;
using rotgen_tag = void; static constexpr int storage_order = Ref::storage_order;
using value_type = typename std::remove_const_t<Ref>::value_type; static constexpr bool has_static_storage = false;
using concrete_type = typename std::remove_const_t<Ref>::concrete_type;
static constexpr bool IsRowMajor = Ref::IsRowMajor;
static constexpr int storage_order = Ref::storage_order;
static constexpr bool has_static_storage = false;
static constexpr bool is_immutable = std::is_const_v<Ref>; static constexpr bool is_immutable = std::is_const_v<Ref>;
static constexpr bool is_defined_static = false; static constexpr bool is_defined_static = false;
using ptr_type = std::conditional_t<is_immutable, value_type const*, value_type*>; using ptr_type =
std::conditional_t<is_immutable, value_type const*, value_type*>;
using stride_type = Stride; using stride_type = Stride;
static constexpr int RowsAtCompileTime = Ref::RowsAtCompileTime; static constexpr int RowsAtCompileTime = Ref::RowsAtCompileTime;
static constexpr int ColsAtCompileTime = Ref::ColsAtCompileTime; static constexpr int ColsAtCompileTime = Ref::ColsAtCompileTime;
static constexpr int MaxRowsAtCompileTime = Ref::MaxRowsAtCompileTime; static constexpr int MaxRowsAtCompileTime = Ref::MaxRowsAtCompileTime;
static constexpr int MaxColsAtCompileTime = Ref::MaxColsAtCompileTime; static constexpr int MaxColsAtCompileTime = Ref::MaxColsAtCompileTime;
static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime; static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime;
static constexpr bool IsCompileTimeSized = RowsAtCompileTime != -1 && ColsAtCompileTime != -1; static constexpr bool IsCompileTimeSized =
RowsAtCompileTime != -1 && ColsAtCompileTime != -1;
using transposed_type = matrix<value_type,ColsAtCompileTime,RowsAtCompileTime, storage_order>; using transposed_type =
matrix<value_type, ColsAtCompileTime, RowsAtCompileTime, storage_order>;
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, strides<storage_order>(s, r, c))
{ {
if constexpr(RowsAtCompileTime != -1) if constexpr (RowsAtCompileTime != -1)
assert(r == RowsAtCompileTime && "Mismatched between dynamic and static row size"); assert(r == RowsAtCompileTime &&
"Mismatched between dynamic and static row size");
if constexpr(ColsAtCompileTime != -1) if constexpr (ColsAtCompileTime != -1)
assert(c == ColsAtCompileTime && "Mismatched between dynamic and static column size"); assert(c == ColsAtCompileTime &&
"Mismatched between dynamic and static column size");
} }
map(ptr_type ptr, Index r, Index c) map(ptr_type ptr, Index r, Index c)
: parent( ptr, r, c : parent(ptr, r, c, [&]() {
, [&]() if constexpr (!std::same_as<Stride, stride>)
{ return strides<storage_order>(Stride{}, r, c);
if constexpr(!std::same_as<Stride,stride>) return strides<storage_order>(Stride{},r,c); else return strides<storage_order>(r, c);
else return strides<storage_order>(r,c); }())
}() {
) }
{}
map(ptr_type ptr, stride_type s) requires(IsCompileTimeSized) map(ptr_type ptr, stride_type s)
: parent(ptr,RowsAtCompileTime,ColsAtCompileTime, strides<storage_order>(s)) requires(IsCompileTimeSized)
{} : parent(
ptr, RowsAtCompileTime, ColsAtCompileTime, strides<storage_order>(s))
{
}
map(ptr_type ptr, Index size) requires(RowsAtCompileTime==1 || ColsAtCompileTime==1) map(ptr_type ptr, Index size)
: map( ptr, RowsAtCompileTime==1?1:size, ColsAtCompileTime==1?1:size) requires(RowsAtCompileTime == 1 || ColsAtCompileTime == 1)
{} : map(ptr,
RowsAtCompileTime == 1 ? 1 : size,
ColsAtCompileTime == 1 ? 1 : size)
{
}
map(ptr_type ptr) requires(IsCompileTimeSized) map(ptr_type ptr)
: map( ptr, RowsAtCompileTime, ColsAtCompileTime ) requires(IsCompileTimeSized)
{} : map(ptr, RowsAtCompileTime, ColsAtCompileTime)
{
}
template<typename R2, int O2, typename S2> template<typename R2, int O2, typename S2>
map(map<R2,O2,S2> const& other) : map ( other.data(), other.rows(), other.cols() map(map<R2, O2, S2> const& other)
, stride{other.outerStride(),other.innerStride()} : map(other.data(),
) other.rows(),
{} other.cols(),
stride{other.outerStride(), other.innerStride()})
{
}
map(parent const& base) : parent(base) {} map(parent const& base) : parent(base) {}
map(map const& other) : parent(other) map(map const& other) : parent(other) {}
{}
map& operator=(map const& other) requires(!is_immutable) map& operator=(map const& other)
requires(!is_immutable)
{ {
base() = static_cast<parent const &>(other); base() = static_cast<parent const&>(other);
return *this; return *this;
} }
map& operator=(concepts::entity auto const& other) requires(!is_immutable) map& operator=(concepts::entity auto const& other)
requires(!is_immutable)
{ {
assert(parent::rows() == other.rows() && parent::cols() == other.cols()); assert(parent::rows() == other.rows() && parent::cols() == other.cols());
for (rotgen::Index r = 0; r < parent::rows(); ++r) for (rotgen::Index r = 0; r < parent::rows(); ++r)
@ -105,94 +123,170 @@ namespace rotgen
return *this; return *this;
} }
value_type& operator()(Index i, Index j) requires(!is_immutable) { return parent::operator()(i,j); } value_type& operator()(Index i, Index j)
value_type& operator()(Index i) requires(!is_immutable && IsVectorAtCompileTime) requires(!is_immutable)
{ {
assert( parent::innerStride() == 1 return parent::operator()(i, j);
&& parent::outerStride() ==(storage_order == RowMajor ? parent::cols() : parent::rows()) }
);
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); return parent::operator()(i);
} }
value_type& operator[](Index i) requires(!is_immutable && IsVectorAtCompileTime) value_type& operator[](Index i)
requires(!is_immutable && IsVectorAtCompileTime)
{ {
return (*this)(i); return (*this)(i);
} }
value_type operator()(Index i, Index j) const { return parent::operator()(i,j); } value_type operator()(Index i, Index j) const
value_type operator()(Index i) const requires(IsVectorAtCompileTime)
{ {
assert( parent::innerStride() == 1 return parent::operator()(i, j);
&& parent::outerStride() ==(storage_order == RowMajor ? parent::cols() : parent::rows()) }
);
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); return parent::operator()(i);
} }
value_type operator[](Index i) const requires(IsVectorAtCompileTime) value_type operator[](Index i) const
requires(IsVectorAtCompileTime)
{ {
return (*this)(i); return (*this)(i);
} }
auto evaluate() const { return *this; } auto evaluate() const { return *this; }
decltype(auto) noalias() const { return *this; }
decltype(auto) noalias() { return *this; }
concrete_type normalized() const requires(IsVectorAtCompileTime) decltype(auto) noalias() const { return *this; }
decltype(auto) noalias() { return *this; }
concrete_type normalized() const
requires(IsVectorAtCompileTime)
{ {
return concrete_type(base().normalized()); return concrete_type(base().normalized());
} }
transposed_type transpose() const { return transposed_type(base().transpose()); } transposed_type transpose() const
concrete_type conjugate() const { return concrete_type(base().conjugate()); } {
transposed_type adjoint() const { return transposed_type(base().adjoint()); } return transposed_type(base().transpose());
}
concrete_type cwiseAbs() const { return concrete_type(base().cwiseAbs()); } concrete_type conjugate() const
concrete_type cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); } {
concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); } return concrete_type(base().conjugate());
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 cwiseMax(map const& rhs) const { return concrete_type(base().cwiseMax(rhs.base())); } transposed_type adjoint() const
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())); } return transposed_type(base().adjoint());
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 cwiseAbs() const { return concrete_type(base().cwiseAbs()); }
concrete_type cwiseAbs2() const
{
return concrete_type(base().cwiseAbs2());
}
concrete_type cwiseInverse() const
{
return concrete_type(base().cwiseInverse());
}
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 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 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 cwiseMax(value_type s) const
{
return concrete_type(base().cwiseMax(s));
}
concrete_type inverse() const { return concrete_type(base().inverse()); } concrete_type inverse() const { return concrete_type(base().inverse()); }
concrete_type cross(map const& other) const concrete_type cross(map const& other) const
{ {
concrete_type that; concrete_type that;
if constexpr(RowsAtCompileTime==-1) if constexpr (RowsAtCompileTime == -1)
{ {
that(0,0) = (*this)(1,0) * other(2,0) - (*this)(2,0) * other(1,0); 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(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); that(2, 0) = (*this)(0, 0) * other(1, 0) - (*this)(1, 0) * other(0, 0);
} }
else else
{ {
that(0,0) = (*this)(0,1) * other(0,2) - (*this)(0,2) * other(0,1); 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, 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); that(0, 2) = (*this)(0, 0) * other(0, 1) - (*this)(0, 1) * other(0, 0);
} }
return that; return that;
} }
void normalize() requires(!is_immutable && IsVectorAtCompileTime) void normalize()
requires(!is_immutable && IsVectorAtCompileTime)
{ {
parent::normalize(); parent::normalize();
} }
void transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); }
void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); } void transposeInPlace()
requires(!is_immutable)
{
parent::transposeInPlace();
}
void adjointInPlace()
requires(!is_immutable)
{
parent::adjointInPlace();
}
template<typename R2, int O2, typename S2> template<typename R2, int O2, typename S2>
map& operator+=(map<R2,O2,S2> const& rhs) requires(!is_immutable) map& operator+=(map<R2, O2, S2> const& rhs)
requires(!is_immutable)
{ {
base() += rhs.base(); base() += rhs.base();
return *this; return *this;
} }
template<typename R2, int O2, typename S2> template<typename R2, int O2, typename S2>
map& operator-=(map<R2,O2,S2> const& rhs) requires(!is_immutable) map& operator-=(map<R2, O2, S2> const& rhs)
requires(!is_immutable)
{ {
base() -= rhs.base(); base() -= rhs.base();
return *this; return *this;
@ -204,31 +298,35 @@ namespace rotgen
} }
template<typename R2, int O2, typename S2> template<typename R2, int O2, typename S2>
map& operator*=(map<R2,O2,S2> const& rhs) requires(!is_immutable) map& operator*=(map<R2, O2, S2> const& rhs)
requires(!is_immutable)
{ {
base() *= rhs.base(); base() *= rhs.base();
return *this; return *this;
} }
map& operator*=(value_type rhs) requires(!is_immutable) map& operator*=(value_type rhs)
requires(!is_immutable)
{ {
base() *= rhs; base() *= rhs;
return *this; return *this;
} }
map& operator/=(value_type rhs) requires(!is_immutable) map& operator/=(value_type rhs)
requires(!is_immutable)
{ {
base() /= rhs; base() /= rhs;
return *this; return *this;
} }
auto minCoeff() const { return parent::minCoeff(); } auto minCoeff() const { return parent::minCoeff(); }
auto maxCoeff() const { return parent::maxCoeff(); } auto maxCoeff() const { return parent::maxCoeff(); }
template<std::integral IndexType> template<std::integral IndexType>
auto minCoeff(IndexType* row, IndexType* col) const auto minCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::minCoeff(&r, &c); auto result = parent::minCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
@ -238,24 +336,23 @@ namespace rotgen
template<std::integral IndexType> template<std::integral IndexType>
auto maxCoeff(IndexType* row, IndexType* col) const auto maxCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::maxCoeff(&r, &c); auto result = parent::maxCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
return result; return result;
} }
static auto Zero() requires( requires {Ref::Zero();} ) static auto Zero()
requires(requires { Ref::Zero(); })
{ {
return Ref::Zero(); return Ref::Zero();
} }
static auto Zero(int rows, int cols) static auto Zero(int rows, int cols) { return Ref::Zero(rows, cols); }
{
return Ref::Zero(rows,cols);
}
static auto Constant(value_type value) requires( requires {Ref::Constant(value);} ) static auto Constant(value_type value)
requires(requires { Ref::Constant(value); })
{ {
return Ref::Constant(value); return Ref::Constant(value);
} }
@ -265,17 +362,16 @@ namespace rotgen
return Ref::Constant(rows, cols, value); return Ref::Constant(rows, cols, value);
} }
static auto Random() requires( requires {Ref::Random();} ) static auto Random()
requires(requires { Ref::Random(); })
{ {
return Ref::Random(); return Ref::Random();
} }
static auto Random(int rows, int cols) static auto Random(int rows, int cols) { return Ref::Random(rows, cols); }
{
return Ref::Random(rows, cols);
}
static auto Identity() requires( requires {Ref::Identity();} ) static auto Identity()
requires(requires { Ref::Identity(); })
{ {
return Ref::Identity(); return Ref::Identity();
} }
@ -285,51 +381,56 @@ namespace rotgen
return Ref::Identity(rows, cols); return Ref::Identity(rows, cols);
} }
map& setZero() requires(!is_immutable) map& setZero()
requires(!is_immutable)
{ {
parent::setZero(); parent::setZero();
return *this; return *this;
} }
map& setOnes() requires(!is_immutable) map& setOnes()
requires(!is_immutable)
{ {
parent::setOnes(); parent::setOnes();
return *this; return *this;
} }
map& setIdentity() requires(!is_immutable) map& setIdentity()
requires(!is_immutable)
{ {
parent::setIdentity(); parent::setIdentity();
return *this; return *this;
} }
map& setRandom() requires(!is_immutable) map& setRandom()
requires(!is_immutable)
{ {
parent::setRandom(); parent::setRandom();
return *this; return *this;
} }
map& setConstant(value_type s) requires(!is_immutable) map& setConstant(value_type s)
requires(!is_immutable)
{ {
parent::setConstant(s); parent::setConstant(s);
return *this; return *this;
} }
template<typename R2, int O2, typename S2> template<typename R2, int O2, typename S2>
value_type dot(map<R2,O2,S2> const& rhs) const value_type dot(map<R2, O2, S2> const& rhs) const
{ {
return base().dot(rhs.base()); return base().dot(rhs.base());
} }
template<int P> template<int P> value_type lpNorm() const
value_type lpNorm() const
{ {
assert(P == 1 || P == 2 || P == Infinity); assert(P == 1 || P == 2 || P == Infinity);
return parent::lpNorm(P); return parent::lpNorm(P);
} }
parent& base() { return static_cast<parent&>(*this); } parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
concrete_type qr_solve(map const& rhs) const concrete_type qr_solve(map const& rhs) const
{ {
@ -338,68 +439,72 @@ 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>
detail::composite_type<R1,R2,matrix> operator+(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs) detail::composite_type<R1, R2, matrix> operator+(map<R1, O1, S1> const& lhs,
map<R2, O2, S2> const& rhs)
{ {
using map1_type = map<R1 const,O1,S1>; using map1_type = map<R1 const, O1, S1>;
using map2_type = map<R2 const,O2,S2>; using map2_type = map<R2 const, O2, S2>;
using concrete_type = detail::composite_type<R1,R2,matrix>; using concrete_type = detail::composite_type<R1, R2, matrix>;
return concrete_type(map1_type(lhs).base().add(map2_type(rhs))); return concrete_type(map1_type(lhs).base().add(map2_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>
detail::composite_type<R1,R2,matrix> operator-(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs) detail::composite_type<R1, R2, matrix> operator-(map<R1, O1, S1> const& lhs,
map<R2, O2, S2> const& rhs)
{ {
using map1_type = map<R1 const,O1,S1>; using map1_type = map<R1 const, O1, S1>;
using map2_type = map<R2 const,O2,S2>; using map2_type = map<R2 const, O2, S2>;
using concrete_type = detail::composite_type<R1,R2,matrix>; using concrete_type = detail::composite_type<R1, R2, matrix>;
return concrete_type(map1_type(lhs).base().sub(map2_type(rhs))); return concrete_type(map1_type(lhs).base().sub(map2_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>
matrix<typename R1::value_type,R1::RowsAtCompileTime,R2::ColsAtCompileTime,R1::storage_order> matrix<typename R1::value_type,
operator*(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs) R1::RowsAtCompileTime,
R2::ColsAtCompileTime,
R1::storage_order>
operator*(map<R1, O1, S1> const& lhs, map<R2, O2, S2> const& rhs)
{ {
using map1_type = map<R1 const,O1,S1>; using map1_type = map<R1 const, O1, S1>;
using map2_type = map<R2 const,O2,S2>; using map2_type = map<R2 const, O2, S2>;
using concrete_type = matrix< typename R1::value_type using concrete_type = matrix<typename R1::value_type, R1::RowsAtCompileTime,
, R1::RowsAtCompileTime,R2::ColsAtCompileTime R2::ColsAtCompileTime, R1::storage_order>;
, R1::storage_order
>;
return concrete_type(map1_type(lhs).base().mul(map2_type(rhs).base())); return concrete_type(map1_type(lhs).base().mul(map2_type(rhs).base()));
} }
template<typename R, int O, typename S> template<typename R, int O, typename S>
typename map<R,O,S>::concrete_type typename map<R, O, S>::concrete_type operator*(
operator*(map<R,O,S> const& lhs, std::convertible_to<typename R::value_type> auto s) map<R, O, S> const& lhs, std::convertible_to<typename R::value_type> auto s)
{ {
using concrete_type = typename map<R,O,S>::concrete_type; using concrete_type = typename map<R, O, S>::concrete_type;
return concrete_type(lhs.base().mul(s)); return concrete_type(lhs.base().mul(s));
} }
template<typename R, int O, typename S> template<typename R, int O, typename S>
typename map<R,O,S>::concrete_type typename map<R, O, S>::concrete_type operator*(
operator*(std::convertible_to<typename R::value_type> auto s, map<R,O,S> const& rhs) std::convertible_to<typename R::value_type> auto s, map<R, O, S> const& rhs)
{ {
using concrete_type = typename map<R,O,S>::concrete_type; using concrete_type = typename map<R, O, S>::concrete_type;
return concrete_type(rhs.base().mul(s)); return concrete_type(rhs.base().mul(s));
} }
template<typename R, int O, typename S> template<typename R, int O, typename S>
typename map<R,O,S>::concrete_type typename map<R, O, S>::concrete_type operator/(
operator/(map<R,O,S> const& lhs, std::convertible_to<typename R::value_type> auto s) map<R, O, S> const& lhs, std::convertible_to<typename R::value_type> auto s)
{ {
using concrete_type = typename map<R,O,S>::concrete_type; using concrete_type = typename map<R, O, S>::concrete_type;
return concrete_type(lhs.base().div(s)); return concrete_type(lhs.base().div(s));
} }
template<typename R1, int O1, typename S1, typename R2, int O2, typename S2> template<typename R1, int O1, typename S1, typename R2, int O2, typename S2>
bool operator==(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs) bool operator==(map<R1, O1, S1> const& lhs, map<R2, O2, S2> const& rhs)
{ {
return lhs.base() == rhs.base(); return lhs.base() == rhs.base();
} }
template<typename R1, int O1, typename S1, typename R2, int O2, typename S2> template<typename R1, int O1, typename S1, typename R2, int O2, typename S2>
bool operator!=(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs) bool operator!=(map<R1, O1, S1> const& lhs, map<R2, O2, S2> const& rhs)
{ {
return lhs.base() != rhs.base(); return lhs.base() != rhs.base();
} }

View file

@ -25,36 +25,67 @@ namespace rotgen
class map_impl32_col; class map_impl32_col;
class map_const_impl32_col; class map_const_impl32_col;
#define USE_CONST #define USE_CONST
#define CONST const #define CONST const
#define BASENAME map_const_impl #define BASENAME map_const_impl
#include <rotgen/container/map/dynamic/indirect.hpp> #include <rotgen/container/map/dynamic/indirect.hpp>
#undef BASENAME #undef BASENAME
#undef CONST #undef CONST
#undef USE_CONST #undef USE_CONST
#define CONST #define CONST
#define BASENAME map_impl #define BASENAME map_impl
#include <rotgen/container/map/dynamic/indirect.hpp> #include <rotgen/container/map/dynamic/indirect.hpp>
#undef BASENAME #undef BASENAME
#undef CONST #undef CONST
template<typename Scalar,int Options, bool isConst> struct find_map_impl; template<typename Scalar, int Options, bool isConst> struct find_map_impl;
template<> struct find_map_impl<float , ColMajor, true> { using type = map_const_impl32_col; }; template<> struct find_map_impl<float, ColMajor, true>
template<> struct find_map_impl<float , RowMajor, true> { using type = map_const_impl32_row; }; {
template<> struct find_map_impl<double, ColMajor, true> { using type = map_const_impl64_col; }; using type = map_const_impl32_col;
template<> struct find_map_impl<double, RowMajor, true> { using type = map_const_impl64_row; }; };
template<> struct find_map_impl<float , ColMajor, false> { using type = map_impl32_col; };
template<> struct find_map_impl<float , RowMajor, false> { using type = map_impl32_row; }; template<> struct find_map_impl<float, RowMajor, true>
template<> struct find_map_impl<double, ColMajor, false> { using type = map_impl64_col; }; {
template<> struct find_map_impl<double, RowMajor, false> { using type = map_impl64_row; }; using type = map_const_impl32_row;
};
template<> struct find_map_impl<double, ColMajor, true>
{
using type = map_const_impl64_col;
};
template<> struct find_map_impl<double, RowMajor, true>
{
using type = map_const_impl64_row;
};
template<> struct find_map_impl<float, ColMajor, false>
{
using type = map_impl32_col;
};
template<> struct find_map_impl<float, RowMajor, false>
{
using type = map_impl32_row;
};
template<> struct find_map_impl<double, ColMajor, false>
{
using type = map_impl64_col;
};
template<> struct find_map_impl<double, RowMajor, false>
{
using type = map_impl64_row;
};
template<typename Ref> template<typename Ref>
using find_map = typename find_map_impl < typename std::remove_const_t<Ref>::value_type using find_map =
, Ref::storage_order typename find_map_impl<typename std::remove_const_t<Ref>::value_type,
, std::is_const_v<Ref> Ref::storage_order,
>::type; std::is_const_v<Ref>>::type;
} }
#include <rotgen/container/map/dynamic/operators.hpp> #include <rotgen/container/map/dynamic/operators.hpp>

View file

@ -1,59 +1,59 @@
#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 TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row)
#define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl, SIZE, _col)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include <rotgen/container/map/dynamic/model.hpp> #include <rotgen/container/map/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
#undef SOURCENAME #undef SOURCENAME
#undef CLASSCONSTNAME #undef CLASSCONSTNAME
#define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row)
#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col)
#define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl, SIZE, _row)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include <rotgen/container/map/dynamic/model.hpp> #include <rotgen/container/map/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
#undef SOURCENAME #undef SOURCENAME
#undef CLASSCONSTNAME #undef CLASSCONSTNAME
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
#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 TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row)
#define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl, SIZE, _col)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include <rotgen/container/map/dynamic/model.hpp> #include <rotgen/container/map/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
#undef SOURCENAME #undef SOURCENAME
#undef CLASSCONSTNAME #undef CLASSCONSTNAME
#define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row)
#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col)
#define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl, SIZE, _row)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include <rotgen/container/map/dynamic/model.hpp> #include <rotgen/container/map/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
#undef SOURCENAME #undef SOURCENAME
#undef CLASSCONSTNAME #undef CLASSCONSTNAME
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE

View file

@ -13,17 +13,17 @@
//================================================================================================== //==================================================================================================
class ROTGEN_EXPORT CLASSNAME class ROTGEN_EXPORT CLASSNAME
{ {
public: public:
CLASSNAME(TYPE CONST* ptr, Index r, Index c); 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, stride s);
CLASSNAME(CLASSNAME const& other); CLASSNAME(CLASSNAME const& other);
CLASSNAME(CLASSNAME&&) noexcept; 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); CLASSNAME& operator=(CLASSNAME&& other);
#endif #endif
~CLASSNAME(); ~CLASSNAME();
@ -34,65 +34,64 @@ class ROTGEN_EXPORT CLASSNAME
Index innerStride() const; Index innerStride() const;
Index outerStride() const; Index outerStride() const;
SOURCENAME normalized() const; SOURCENAME normalized() const;
SOURCENAME transpose() const; SOURCENAME transpose() const;
SOURCENAME conjugate() const; SOURCENAME conjugate() const;
SOURCENAME adjoint() const; SOURCENAME adjoint() const;
SOURCENAME cwiseAbs() const; SOURCENAME cwiseAbs() const;
SOURCENAME cwiseAbs2() const; SOURCENAME cwiseAbs2() const;
SOURCENAME cwiseInverse() const; SOURCENAME cwiseInverse() const;
SOURCENAME cwiseSqrt() const; SOURCENAME cwiseSqrt() const;
SOURCENAME cwiseMax (CLASSNAME const&) const; SOURCENAME cwiseMax(CLASSNAME const&) const;
SOURCENAME cwiseMin (CLASSNAME const&) const; SOURCENAME cwiseMin(CLASSNAME const&) const;
SOURCENAME cwiseProduct (CLASSNAME const&) const; SOURCENAME cwiseProduct(CLASSNAME const&) const;
SOURCENAME cwiseQuotient (CLASSNAME const&) const; SOURCENAME cwiseQuotient(CLASSNAME const&) const;
SOURCENAME cwiseMax(TYPE) const; SOURCENAME cwiseMax(TYPE) const;
SOURCENAME cwiseMin(TYPE) const; SOURCENAME cwiseMin(TYPE) const;
#if !defined(USE_CONST) #if !defined(USE_CONST)
void normalize(); void normalize();
void transposeInPlace(); void transposeInPlace();
void adjointInPlace(); void adjointInPlace();
#endif #endif
TYPE sum() const; TYPE sum() const;
TYPE prod() const; TYPE prod() const;
TYPE mean() const; TYPE mean() const;
TYPE trace() const; TYPE trace() const;
TYPE maxCoeff() const; TYPE maxCoeff() const;
TYPE minCoeff() const; TYPE minCoeff() const;
TYPE maxCoeff(Index*, Index*) const; TYPE maxCoeff(Index*, Index*) const;
TYPE minCoeff(Index*, Index*) const; TYPE minCoeff(Index*, Index*) const;
TYPE dot(CLASSNAME const&) const; TYPE dot(CLASSNAME const&) const;
TYPE dot(TRANSCLASSNAME const&) const; TYPE dot(TRANSCLASSNAME const&) const;
TYPE squaredNorm() const; TYPE squaredNorm() const;
TYPE norm() const; TYPE norm() const;
TYPE lpNorm(int p) const; TYPE lpNorm(int p) const;
SOURCENAME qr_solve(CLASSNAME const& rhs) const; SOURCENAME qr_solve(CLASSNAME const& rhs) const;
#if !defined(USE_CONST) #if !defined(USE_CONST)
TYPE& operator()(Index i, Index j); TYPE& operator()(Index i, Index j);
TYPE& operator()(Index i); TYPE& operator()(Index i);
#endif #endif
TYPE operator()(Index i, Index j) const; TYPE operator()(Index i, Index j) const;
TYPE operator()(Index i) const; TYPE operator()(Index i) const;
#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+=(CLASSCONSTNAME const& rhs);
CLASSNAME& operator-=(CLASSNAME const& rhs); CLASSNAME& operator-=(CLASSNAME const& rhs);
CLASSNAME& operator-=(CLASSCONSTNAME const& rhs); CLASSNAME& operator-=(CLASSCONSTNAME const& rhs);
CLASSNAME& operator*=(CLASSNAME const& rhs); CLASSNAME& operator*=(CLASSNAME const& rhs);
CLASSNAME& operator*=(CLASSCONSTNAME 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
SOURCENAME operator-() const; SOURCENAME operator-() const;
SOURCENAME add(CLASSNAME const& rhs) const; SOURCENAME add(CLASSNAME const& rhs) const;
@ -106,27 +105,32 @@ class ROTGEN_EXPORT CLASSNAME
SOURCENAME inverse() const; SOURCENAME inverse() const;
friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&, CLASSNAME const&); friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&,
friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&, format<CLASSNAME> const&); CLASSNAME const&);
friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&,
format<CLASSNAME> const&);
const TYPE* data() const; const TYPE* data() const;
#if !defined(USE_CONST) #if !defined(USE_CONST)
TYPE* data(); TYPE* data();
void setZero(); void setZero();
void setOnes(); void setOnes();
void setRandom(); void setRandom();
void setIdentity(); void setIdentity();
void setConstant(TYPE); void setConstant(TYPE);
#endif #endif
friend ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs); friend ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs,
friend ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs); CLASSNAME const& rhs);
friend ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs,
CLASSNAME const& rhs);
private: private:
struct payload; struct payload;
std::unique_ptr<payload> storage_; std::unique_ptr<payload> storage_;
public: public:
std::unique_ptr<payload>& storage() { return storage_; } std::unique_ptr<payload>& storage() { return storage_; }
std::unique_ptr<payload> const& storage() const { return storage_; } std::unique_ptr<payload> const& storage() const { return storage_; }
}; };

View file

@ -7,24 +7,28 @@
//================================================================================================== //==================================================================================================
#pragma once #pragma once
#define ROTGEN_DEF_RELOP_PAIR(OP, T1, T2) \ #define ROTGEN_DEF_RELOP_PAIR(OP, T1, T2) \
ROTGEN_EXPORT bool operator OP (T1 const&, T2 const&); \ ROTGEN_EXPORT bool operator OP(T1 const&, T2 const&); \
inline bool operator OP (T2 const& a, T1 const& b) { return b OP a; } \ inline bool operator OP(T2 const& a, T1 const& b) \
/**/ { \
return b OP a; \
} \
/**/
#define ROTGEN_DEF_RELOP(OP) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl32_col, map_impl32_col) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl32_col, map_impl32_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl32_col, map_const_impl32_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl32_row, map_impl32_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl32_row, map_impl32_col) \
ROTGEN_DEF_RELOP_PAIR(OP, map_impl32_col, map_impl32_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl64_col, map_impl64_col) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl64_col, map_impl64_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl64_col, map_const_impl64_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl64_row, map_impl64_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl64_row, map_impl64_col) \
ROTGEN_DEF_RELOP_PAIR(OP, map_impl64_col, map_impl64_row)
#define ROTGEN_DEF_RELOP(OP) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl32_col, map_impl32_col) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl32_col, map_impl32_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl32_col, map_const_impl32_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl32_row, map_impl32_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl32_row, map_impl32_col) \
ROTGEN_DEF_RELOP_PAIR(OP, map_impl32_col, map_impl32_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl64_col, map_impl64_col) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl64_col, map_impl64_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl64_col, map_const_impl64_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl64_row, map_impl64_row) \
ROTGEN_DEF_RELOP_PAIR(OP, map_const_impl64_row, map_impl64_col) \
ROTGEN_DEF_RELOP_PAIR(OP, map_impl64_col, map_impl64_row) \
/**/ /**/
namespace rotgen namespace rotgen

View file

@ -14,77 +14,90 @@ namespace rotgen
{ {
namespace detail namespace detail
{ {
template<typename Ref, int Options, bool isConst> template<typename Ref, int Options, bool isConst> struct compute_map_type
struct compute_map_type
{ {
using base = Eigen::Matrix< typename Ref::value_type using base = Eigen::Matrix<typename Ref::value_type,
, Ref::RowsAtCompileTime, Ref::ColsAtCompileTime Ref::RowsAtCompileTime,
, Ref::storage_order Ref::ColsAtCompileTime,
>; Ref::storage_order>;
using ref_t = std::conditional_t<isConst, base const, base>; 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, Eigen::Stride<-1, -1>>;
}; };
template<typename Ref, int Options, bool isConst> template<typename Ref, int Options, bool isConst>
using map_type = typename compute_map_type<Ref,Options,isConst>::type; using map_type = typename compute_map_type<Ref, Options, isConst>::type;
} }
template<typename Ref, int Options = Unaligned, typename Stride = stride> template<typename Ref, int Options = Unaligned, typename Stride = stride>
class map : private detail::map_type<std::remove_const_t<Ref>, Options, std::is_const_v<Ref>> class map : private detail::map_type<std::remove_const_t<Ref>,
Options,
std::is_const_v<Ref>>
{ {
public: public:
using rotgen_tag = void; using rotgen_tag = void;
using parent = detail::map_type<std::remove_const_t<Ref>, Options, std::is_const_v<Ref>>; using parent =
using value_type = typename std::remove_const_t<Ref>::value_type; detail::map_type<std::remove_const_t<Ref>, Options, std::is_const_v<Ref>>;
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 int RowsAtCompileTime = Ref::RowsAtCompileTime; static constexpr int RowsAtCompileTime = Ref::RowsAtCompileTime;
static constexpr int ColsAtCompileTime = Ref::ColsAtCompileTime; static constexpr int ColsAtCompileTime = Ref::ColsAtCompileTime;
static constexpr int MaxRowsAtCompileTime = Ref::MaxRowsAtCompileTime; static constexpr int MaxRowsAtCompileTime = Ref::MaxRowsAtCompileTime;
static constexpr int MaxColsAtCompileTime = Ref::MaxColsAtCompileTime; static constexpr int MaxColsAtCompileTime = Ref::MaxColsAtCompileTime;
static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime; static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime;
static constexpr bool has_static_storage = Ref::has_static_storage; static constexpr bool has_static_storage = Ref::has_static_storage;
static constexpr int storage_order = Ref::storage_order; static constexpr int storage_order = Ref::storage_order;
static constexpr bool is_immutable = std::is_const_v<Ref>; static constexpr bool is_immutable = std::is_const_v<Ref>;
static constexpr bool is_defined_static = Ref::is_defined_static; static constexpr bool is_defined_static = Ref::is_defined_static;
template<typename ET> template<typename ET>
using as_concrete_type = detail::as_concrete_t<ET, matrix>; using as_concrete_type = detail::as_concrete_t<ET, matrix>;
using ptr_type = std::conditional_t<is_immutable, value_type const*, value_type*>; using ptr_type =
std::conditional_t<is_immutable, value_type const*, value_type*>;
using stride_type = Stride; using stride_type = Stride;
map(const map&) = default; map(map const&) = default;
map(map&&) = default; map(map&&) = default;
map& operator=(const map&) = default; map& operator=(map const&) = default;
map& operator=(map&&) = 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, strides<storage_order>(s,r,c)) {}
map(ptr_type ptr, Index r, Index c) map(ptr_type ptr, Index r, Index c)
: parent( ptr, r, c : parent(ptr, r, c, [&]() {
, [&]() if constexpr (!std::same_as<Stride, stride>)
{ return strides<storage_order>(Stride{}, r, c);
if constexpr(!std::same_as<Stride,stride>) return strides<storage_order>(Stride{},r,c); else return strides<storage_order>(r, c);
else return strides<storage_order>(r,c); }())
}() {
) }
{}
map(ptr_type ptr, stride_type s) requires(RowsAtCompileTime!=-1 && ColsAtCompileTime!=-1) map(ptr_type ptr, stride_type s)
: parent(ptr, strides<storage_order>(s,RowsAtCompileTime,ColsAtCompileTime)) requires(RowsAtCompileTime != -1 && ColsAtCompileTime != -1)
{} : parent(ptr,
strides<storage_order>(s, RowsAtCompileTime, ColsAtCompileTime))
{
}
map(ptr_type ptr, Index sz) requires(RowsAtCompileTime==1 || ColsAtCompileTime==1) map(ptr_type ptr, Index sz)
: map(ptr, RowsAtCompileTime==1?1:sz, ColsAtCompileTime==1?1:sz) requires(RowsAtCompileTime == 1 || ColsAtCompileTime == 1)
{} : map(
ptr, RowsAtCompileTime == 1 ? 1 : sz, ColsAtCompileTime == 1 ? 1 : sz)
{
}
map(ptr_type ptr) requires(RowsAtCompileTime!=-1 && ColsAtCompileTime!=-1) map(ptr_type ptr)
: map( ptr, RowsAtCompileTime, ColsAtCompileTime ) requires(RowsAtCompileTime != -1 && ColsAtCompileTime != -1)
{} : map(ptr, RowsAtCompileTime, ColsAtCompileTime)
{
}
map(concepts::entity auto const& other) : parent(other.base()) map(concepts::entity auto const& other) : parent(other.base()) {}
{}
map& operator=(concepts::entity auto const& other) map& operator=(concepts::entity auto const& other)
{ {
@ -92,62 +105,79 @@ namespace rotgen
return *this; return *this;
} }
parent& base() { return static_cast<parent&>(*this); } parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<const parent&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
auto evaluate() const auto evaluate() const
{ {
auto res = static_cast<parent const &>(*this).eval(); auto res = static_cast<parent const&>(*this).eval();
return as_concrete_type<decltype(res)>(res); return as_concrete_type<decltype(res)>(res);
} }
decltype(auto) noalias() const decltype(auto) noalias() const
{ {
if constexpr(use_expression_templates) return base().noalias(); if constexpr (use_expression_templates) return base().noalias();
else return *this; else return *this;
} }
decltype(auto) noalias() decltype(auto) noalias()
{ {
if constexpr(use_expression_templates) return base().noalias(); if constexpr (use_expression_templates) return base().noalias();
else return *this; else return *this;
} }
value_type& operator()(Index i, Index j) requires(!is_immutable) value_type& operator()(Index i, Index j)
requires(!is_immutable)
{ {
return base()(i,j); return base()(i, j);
} }
value_type& operator()(Index i) requires(!is_immutable && IsVectorAtCompileTime) value_type& operator()(Index i)
requires(!is_immutable && IsVectorAtCompileTime)
{ {
return base().data()[i]; return base().data()[i];
} }
value_type& operator[](Index i) requires(!is_immutable && IsVectorAtCompileTime) value_type& operator[](Index i)
requires(!is_immutable && IsVectorAtCompileTime)
{ {
return (*this)(i); return (*this)(i);
} }
value_type operator()(Index i, Index j) const { return base()(i,j); } value_type operator()(Index i, Index j) const { return base()(i, j); }
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 base().data()[i];
}
value_type operator[](Index i) const
requires(IsVectorAtCompileTime)
{
return (*this)(i);
}
template<typename R2, int O2, typename S2> template<typename R2, int O2, typename S2>
map& operator+=(map<R2,O2,S2> const& rhs) requires(!is_immutable) map& operator+=(map<R2, O2, S2> const& rhs)
requires(!is_immutable)
{ {
base() += rhs.base(); base() += rhs.base();
return *this; return *this;
} }
template<typename R2, int O2, typename S2> template<typename R2, int O2, typename S2>
map& operator-=(map<R2,O2,S2> const& rhs) requires(!is_immutable) map& operator-=(map<R2, O2, S2> const& rhs)
requires(!is_immutable)
{ {
base() -= rhs.base(); base() -= rhs.base();
return *this; return *this;
} }
template<typename R2, int O2, typename S2> template<typename R2, int O2, typename S2>
map& operator*=(map<R2,O2,S2> const& rhs) requires(!is_immutable) map& operator*=(map<R2, O2, S2> const& rhs)
requires(!is_immutable)
{ {
base() *= rhs.base(); base() *= rhs.base();
return *this; return *this;
@ -167,129 +197,180 @@ namespace rotgen
auto cwiseMin(map const& rhs) const auto cwiseMin(map const& rhs) const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseMin(rhs.base())}; if constexpr (!use_expression_templates)
else return base().cwiseMin(rhs.base()); return concrete_type{parent::cwiseMin(rhs.base())};
else return base().cwiseMin(rhs.base());
} }
auto cwiseMin(value_type rhs) const auto cwiseMin(value_type rhs) const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseMin(rhs)}; if constexpr (!use_expression_templates)
else return base().cwiseMin(rhs); return concrete_type{parent::cwiseMin(rhs)};
else return base().cwiseMin(rhs);
} }
auto cwiseMax(map const& rhs) const auto cwiseMax(map const& rhs) const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseMax(rhs.base())}; if constexpr (!use_expression_templates)
else return base().cwiseMax(rhs.base()); return concrete_type{parent::cwiseMax(rhs.base())};
else return base().cwiseMax(rhs.base());
} }
auto cwiseMax(value_type rhs) const auto cwiseMax(value_type rhs) const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseMax(rhs)}; if constexpr (!use_expression_templates)
else return base().cwiseMax(rhs); return concrete_type{parent::cwiseMax(rhs)};
else return base().cwiseMax(rhs);
} }
auto cwiseProduct(map const& rhs) const auto cwiseProduct(map const& rhs) const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseProduct(rhs.base())}; if constexpr (!use_expression_templates)
else return base().cwiseProduct(rhs.base()); return concrete_type{parent::cwiseProduct(rhs.base())};
else return base().cwiseProduct(rhs.base());
} }
auto cwiseQuotient(map const& rhs) const auto cwiseQuotient(map const& rhs) const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseQuotient(rhs.base())}; if constexpr (!use_expression_templates)
else return base().cwiseQuotient(rhs.base()); return concrete_type{parent::cwiseQuotient(rhs.base())};
else return base().cwiseQuotient(rhs.base());
} }
auto cwiseAbs() const auto cwiseAbs() const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseAbs()}; if constexpr (!use_expression_templates)
else return base().cwiseAbs(); return concrete_type{parent::cwiseAbs()};
else return base().cwiseAbs();
} }
auto cwiseAbs2() const auto cwiseAbs2() const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseAbs2()}; if constexpr (!use_expression_templates)
else return base().cwiseAbs2(); return concrete_type{parent::cwiseAbs2()};
else return base().cwiseAbs2();
} }
auto cwiseInverse() const auto cwiseInverse() const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseInverse()}; if constexpr (!use_expression_templates)
else return base().cwiseInverse(); return concrete_type{parent::cwiseInverse()};
else return base().cwiseInverse();
} }
auto cwiseSqrt() const auto cwiseSqrt() const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cwiseSqrt()}; if constexpr (!use_expression_templates)
else return base().cwiseSqrt(); return concrete_type{parent::cwiseSqrt()};
else return base().cwiseSqrt();
} }
auto cross(map const& rhs) const auto cross(map const& rhs) const
{ {
if constexpr(!use_expression_templates) return concrete_type{parent::cross(rhs.base())}; if constexpr (!use_expression_templates)
else return base().cross(rhs.base()); return concrete_type{parent::cross(rhs.base())};
else return base().cross(rhs.base());
} }
auto inverse() const auto inverse() const
{ {
if constexpr(use_expression_templates) return base().inverse(); if constexpr (use_expression_templates) return base().inverse();
else return as_concrete_type<decltype(base().inverse())>(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();
else return as_concrete_type<decltype(base().normalized())>(base().normalized()); else
return as_concrete_type<decltype(base().normalized())>(
base().normalized());
} }
auto transpose() const auto transpose() const
{ {
if constexpr(use_expression_templates) return base().transpose(); if constexpr (use_expression_templates) return base().transpose();
else return as_concrete_type<decltype(base().transpose())>(base().transpose()); else
return as_concrete_type<decltype(base().transpose())>(
base().transpose());
} }
auto adjoint() const auto adjoint() const
{ {
if constexpr(use_expression_templates) return base().adjoint(); if constexpr (use_expression_templates) return base().adjoint();
else return as_concrete_type<decltype(base().adjoint())>(base().adjoint()); else
return as_concrete_type<decltype(base().adjoint())>(base().adjoint());
} }
auto conjugate() const auto conjugate() const
{ {
if constexpr(use_expression_templates) return base().conjugate(); if constexpr (use_expression_templates) return base().conjugate();
else return as_concrete_type<decltype(base().conjugate())>(base().conjugate()); else
return as_concrete_type<decltype(base().conjugate())>(
base().conjugate());
} }
void normalize() requires(IsVectorAtCompileTime) void normalize()
requires(IsVectorAtCompileTime)
{ {
base().normalize(); base().normalize();
} }
void transposeInPlace() { base().transposeInPlace(); } void transposeInPlace() { base().transposeInPlace(); }
void adjointInPlace() { base().adjointInPlace(); }
void adjointInPlace() { base().adjointInPlace(); }
auto qr_solve(auto 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()));
}; };
static auto Zero() requires( requires {Ref::Zero();} ) { return Ref::Zero(); } static auto Zero()
static auto Zero(int rows, int cols) { return Ref::Zero(rows,cols); } requires(requires { Ref::Zero(); })
{
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);} ) static auto Ones()
{ return Ref::Constant(value); } requires(requires { Ref::Ones(); })
{
return Ref::Ones();
}
static auto Constant(int rows, int cols, value_type value) { return Ref::Constant(rows, cols, value); } static auto Ones(int rows, int cols) { return Ref::Ones(rows, cols); }
static auto Random() requires( requires {Ref::Random();} ) { return Ref::Random(); } static auto Constant(value_type value)
static auto Random(int rows, int cols) { return Ref::Random(rows, cols); } requires(requires { Ref::Constant(value); })
{
return Ref::Constant(value);
}
static auto Identity() requires( requires {Ref::Identity();} ) { return Ref::Identity(); } static auto Constant(int rows, int cols, value_type value)
static auto Identity(int rows, int cols) { return Ref::Identity(rows, cols); } {
return Ref::Constant(rows, cols, value);
}
static auto Random()
requires(requires { Ref::Random(); })
{
return Ref::Random();
}
static auto Random(int rows, int cols) { return Ref::Random(rows, cols); }
static auto Identity()
requires(requires { Ref::Identity(); })
{
return Ref::Identity();
}
static auto Identity(int rows, int cols)
{
return Ref::Identity(rows, cols);
}
map& setOnes() map& setOnes()
{ {
@ -321,27 +402,27 @@ namespace rotgen
return *this; return *this;
} }
using parent::innerStride;
using parent::outerStride;
using parent::rows;
using parent::cols; using parent::cols;
using parent::size;
using parent::data; using parent::data;
using parent::sum; using parent::innerStride;
using parent::mean; using parent::mean;
using parent::prod;
using parent::trace;
using parent::norm; using parent::norm;
using parent::outerStride;
using parent::prod;
using parent::rows;
using parent::size;
using parent::squaredNorm; using parent::squaredNorm;
using parent::sum;
using parent::trace;
auto minCoeff() const { return parent::minCoeff(); } auto minCoeff() const { return parent::minCoeff(); }
auto maxCoeff() const { return parent::maxCoeff(); } auto maxCoeff() const { return parent::maxCoeff(); }
template<std::integral IndexType> template<std::integral IndexType>
auto minCoeff(IndexType* row, IndexType* col) const auto minCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::minCoeff(&r, &c); auto result = parent::minCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
@ -351,7 +432,7 @@ namespace rotgen
template<std::integral IndexType> template<std::integral IndexType>
auto maxCoeff(IndexType* row, IndexType* col) const auto maxCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::maxCoeff(&r, &c); auto result = parent::maxCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
@ -359,7 +440,7 @@ namespace rotgen
} }
template<typename R2, int O2, typename S2> template<typename R2, int O2, typename S2>
value_type dot(map<R2,O2,S2> const& rhs) const value_type dot(map<R2, O2, S2> const& rhs) const
{ {
return base().dot(rhs.base()); return base().dot(rhs.base());
} }
@ -372,103 +453,104 @@ 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>
bool operator==(map<R1, O1, S1> const& lhs, map<R2,O2,S2> const& rhs) bool operator==(map<R1, O1, S1> const& lhs, map<R2, O2, S2> const& rhs)
{ {
return lhs.base() == rhs.base(); return lhs.base() == rhs.base();
} }
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>
bool operator!=(map<R1, O1, S1> const& lhs, map<R2,O2,S2> const& rhs) bool operator!=(map<R1, O1, S1> const& lhs, map<R2, O2, S2> const& rhs)
{ {
return lhs.base() != rhs.base(); return lhs.base() != rhs.base();
} }
#if defined(ROTGEN_ENABLE_EXPRESSION_TEMPLATES) #if defined(ROTGEN_ENABLE_EXPRESSION_TEMPLATES)
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>
auto operator+(map<R1, O1, S1> const& lhs, map<R2,O2,S2> const& rhs) auto operator+(map<R1, O1, S1> const& lhs, map<R2, O2, S2> const& rhs)
{ {
return lhs.base() + rhs.base(); return lhs.base() + rhs.base();
} }
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>
auto operator-(map<R1, O1, S1> const& lhs, map<R2,O2,S2> const& rhs) auto operator-(map<R1, O1, S1> const& lhs, map<R2, O2, S2> const& rhs)
{ {
return lhs.base() - rhs.base(); return lhs.base() - rhs.base();
} }
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>
auto operator*(map<R1, O1, S1> const& lhs, map<R2,O2,S2> const& rhs) auto operator*(map<R1, O1, S1> const& lhs, map<R2, O2, S2> const& rhs)
{ {
return lhs.base() * rhs.base(); return lhs.base() * rhs.base();
} }
template<typename R, int O, typename S> template<typename R, int O, typename S>
auto operator*( map<R, O, S> const& lhs, std::convertible_to<typename R::value_type> auto s) auto operator*(map<R, O, S> const& lhs,
std::convertible_to<typename R::value_type> auto s)
{ {
return lhs.base() * s; return lhs.base() * s;
} }
template<typename R, int O, typename S> template<typename R, int O, typename S>
auto operator*(std::convertible_to<typename R::value_type> auto s, map<R, O, S> const& rhs) auto operator*(std::convertible_to<typename R::value_type> auto s,
map<R, O, S> const& rhs)
{ {
return s * rhs.base(); return s * rhs.base();
} }
template<typename R, int O, typename S> template<typename R, int O, typename S>
auto operator/(map<R, O, S> const& lhs, std::convertible_to<typename R::value_type> auto s) auto operator/(map<R, O, S> const& lhs,
std::convertible_to<typename R::value_type> auto s)
{ {
return lhs.base() / s; return lhs.base() / s;
} }
#else #else
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 concrete_type = typename map<R1, O1, S1>::concrete_type;
return concrete_type(lhs.base() + rhs.base()); return concrete_type(lhs.base() + rhs.base());
} }
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 concrete_type = typename map<R1, O1, S1>::concrete_type;
return concrete_type(lhs.base() - rhs.base()); return concrete_type(lhs.base() - rhs.base());
} }
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>
matrix<typename R1::value_type,R1::RowsAtCompileTime,R2::ColsAtCompileTime> matrix<typename R1::value_type, R1::RowsAtCompileTime, R2::ColsAtCompileTime>
operator*(map<R1,O1,S1> const& lhs, map<R2,O2,S2> const& rhs) operator*(map<R1, O1, S1> const& lhs, map<R2, O2, S2> const& rhs)
{ {
using concrete_type = matrix< typename R1::value_type using concrete_type = matrix<typename R1::value_type, R1::RowsAtCompileTime,
, R1::RowsAtCompileTime,R2::ColsAtCompileTime R2::ColsAtCompileTime>;
>;
return concrete_type(lhs.base() * rhs.base()); return concrete_type(lhs.base() * rhs.base());
} }
template<typename R, int O, typename S> template<typename R, int O, typename S>
typename map<R,O,S>::concrete_type operator*( map<R, O, S> const& lhs typename map<R, O, S>::concrete_type operator*(
, std::convertible_to<typename R::value_type> auto s map<R, O, S> const& lhs, std::convertible_to<typename R::value_type> auto s)
)
{ {
using concrete_type = typename map<R,O,S>::concrete_type; using concrete_type = typename map<R, O, S>::concrete_type;
return concrete_type(lhs.base() * s); return concrete_type(lhs.base() * s);
} }
template<typename R, int O, typename S> template<typename R, int O, typename S>
typename map<R,O,S>::concrete_type operator*( std::convertible_to<typename R::value_type> auto s typename map<R, O, S>::concrete_type operator*(
, map<R, O, S> const& rhs std::convertible_to<typename R::value_type> auto s, map<R, O, S> const& rhs)
)
{ {
using concrete_type = typename map<R,O,S>::concrete_type; using concrete_type = typename map<R, O, S>::concrete_type;
return concrete_type(rhs.base() * s); return concrete_type(rhs.base() * s);
} }
template<typename R, int O, typename S> template<typename R, int O, typename S>
typename map<R,O,S>::concrete_type operator/( map<R, O, S> const& lhs typename map<R, O, S>::concrete_type operator/(
, std::convertible_to<typename R::value_type> auto s map<R, O, S> const& lhs, std::convertible_to<typename R::value_type> auto s)
)
{ {
using concrete_type = typename map<R,O,S>::concrete_type; using concrete_type = typename map<R, O, S>::concrete_type;
return concrete_type(lhs.base() / s); return concrete_type(lhs.base() / s);
} }
#endif #endif

View file

@ -14,134 +14,171 @@
namespace rotgen namespace rotgen
{ {
template< typename Scalar template<typename Scalar,
, int Rows = Dynamic , int Cols = Dynamic int Rows = Dynamic,
, int Opts = detail::force_order<Rows,Cols> int Cols = Dynamic,
, int MaxRows = Rows , int MaxCols = Cols int Opts = detail::force_order<Rows, Cols>,
> int MaxRows = Rows,
class matrix : public find_matrix<Scalar,Opts> int MaxCols = Cols>
class matrix : public find_matrix<Scalar, Opts>
{ {
public: public:
using parent = find_matrix<Scalar,Opts>; using parent = find_matrix<Scalar, Opts>;
using rotgen_tag = void; using rotgen_tag = void;
using concrete_type = matrix; using concrete_type = matrix;
using value_type = Scalar; using value_type = Scalar;
static constexpr auto storage_order = Opts & 1; static constexpr auto storage_order = Opts & 1;
static constexpr int RowsAtCompileTime = Rows; static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols; static constexpr int ColsAtCompileTime = Cols;
static constexpr int MaxRowsAtCompileTime = MaxRows; static constexpr int MaxRowsAtCompileTime = MaxRows;
static constexpr int MaxColsAtCompileTime = MaxCols; static constexpr int MaxColsAtCompileTime = MaxCols;
static constexpr bool IsCompileTimeSized = Rows != -1 && Cols != -1; static constexpr bool IsCompileTimeSized = Rows != -1 && Cols != -1;
static constexpr bool IsVectorAtCompileTime = (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1); static constexpr bool IsVectorAtCompileTime =
static constexpr int Options = Opts; (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1);
static constexpr bool IsRowMajor = (Opts & RowMajor) == RowMajor; static constexpr int Options = Opts;
static constexpr bool is_defined_static = false; static constexpr bool IsRowMajor = (Opts & RowMajor) == RowMajor;
static constexpr bool has_static_storage = false; static constexpr bool is_defined_static = false;
static constexpr bool is_immutable = false; static constexpr bool has_static_storage = false;
static constexpr bool is_immutable = false;
using transposed_type = matrix<value_type,Cols,Rows,storage_order>; using transposed_type = matrix<value_type, Cols, Rows, storage_order>;
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) requires(!IsCompileTimeSized) matrix(Index r, Index c)
: parent(r, c) requires(!IsCompileTimeSized)
: parent(r, c)
{ {
if constexpr(Rows != -1) assert(r == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(c == Cols && "Mismatched between dynamic and static column size"); assert(r == Rows && "Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(c == Cols &&
"Mismatched between dynamic and static column size");
} }
matrix(Index n) requires(IsVectorAtCompileTime && (Rows != 1 || Cols != 1)) matrix(Index n)
: parent(Rows != -1 ? 1 : n, Cols != -1 ? 1 : n) requires(IsVectorAtCompileTime && (Rows != 1 || Cols != 1))
{} : parent(Rows != -1 ? 1 : n, Cols != -1 ? 1 : n)
{
}
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) matrix(Scalar v0, Scalar v1, auto... vs)
requires((Rows == (2+sizeof...(vs)) && Cols == 1) || (Rows == 1 && Cols == (2+sizeof...(vs)))) requires((Rows == (2 + sizeof...(vs)) && Cols == 1) ||
: parent(Rows,Cols,{v0,v1,static_cast<Scalar>(vs)...}) (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)
{ {
if constexpr(Rows != -1) assert(init.size() == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(init.size() == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
{ {
[[maybe_unused]] std::size_t c = 0; [[maybe_unused]] std::size_t c = 0;
if(init.size()) c = init.begin()->size(); if (init.size()) c = init.begin()->size();
assert(c == Cols && "Mismatched between dynamic and static column size"); assert(c == Cols &&
"Mismatched between dynamic and static column size");
} }
} }
matrix(std::initializer_list<Scalar> init) matrix(std::initializer_list<Scalar> init)
requires(IsVectorAtCompileTime) : parent(Rows, Cols, init) requires(IsVectorAtCompileTime)
{} : parent(Rows, Cols, init)
matrix(concepts::entity auto const& e) : parent(e.rows(),e.cols())
{ {
if constexpr(Rows != -1) assert(e.rows() == Rows && "Mismatched between dynamic and static row size"); }
if constexpr(Cols != -1) assert(e.cols() == Cols && "Mismatched between dynamic and static col size");
matrix(concepts::entity auto const& e) : parent(e.rows(), e.cols())
{
if constexpr (Rows != -1)
assert(e.rows() == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(e.cols() == Cols &&
"Mismatched between dynamic and static col size");
for (rotgen::Index r = 0; r < e.rows(); ++r) for (rotgen::Index r = 0; r < e.rows(); ++r)
for (rotgen::Index c = 0; c < e.cols(); ++c) for (rotgen::Index c = 0; c < e.cols(); ++c) (*this)(r, c) = e(r, c);
(*this)(r, c) = e(r, c);
} }
matrix& operator=(concepts::entity auto const& e) matrix& operator=(concepts::entity auto const& e)
{ {
if constexpr(Rows != -1) assert(e.rows() == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(e.cols() == Cols && "Mismatched between dynamic and static col size"); assert(e.rows() == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(e.cols() == Cols &&
"Mismatched between dynamic and static col size");
resize(e.rows(), e.cols()); resize(e.rows(), e.cols());
for (rotgen::Index r = 0; r < e.rows(); ++r) for (rotgen::Index r = 0; r < e.rows(); ++r)
for (rotgen::Index c = 0; c < e.cols(); ++c) for (rotgen::Index c = 0; c < e.cols(); ++c) (*this)(r, c) = e(r, c);
(*this)(r, c) = e(r, c);
return *this; return *this;
} }
value_type& operator[](Index i) requires(IsVectorAtCompileTime) value_type& operator[](Index i)
requires(IsVectorAtCompileTime)
{ {
return (*this)(i); return (*this)(i);
} }
value_type operator[](Index i) const requires(IsVectorAtCompileTime) value_type operator[](Index i) const
requires(IsVectorAtCompileTime)
{ {
return (*this)(i); return (*this)(i);
} }
auto evaluate() const { return *this; } auto evaluate() const { return *this; }
decltype(auto) noalias() const { return *this; }
decltype(auto) noalias() { return *this; } decltype(auto) noalias() const { return *this; }
decltype(auto) noalias() { return *this; }
void resize(int r, int c) void resize(int r, int c)
{ {
if constexpr(Rows == 1) assert(c == Cols && "Mismatched between dynamic and static col size"); if constexpr (Rows == 1)
if constexpr(Cols == 1) assert(r == Rows && "Mismatched between dynamic and static row size"); assert(c == Cols && "Mismatched between dynamic and static col size");
if constexpr (Cols == 1)
assert(r == Rows && "Mismatched between dynamic and static row size");
parent::resize(r, c); parent::resize(r, c);
} }
void resize(int s) requires(IsVectorAtCompileTime) void resize(int s)
requires(IsVectorAtCompileTime)
{ {
if constexpr(Rows == 1) parent::resize(1,s); if constexpr (Rows == 1) parent::resize(1, s);
else parent::resize(s,1); else parent::resize(s, 1);
} }
void conservativeResize(int r, int c) void conservativeResize(int r, int c)
{ {
if constexpr(Rows == 1) assert(c == Cols && "Mismatched between dynamic and static col size"); if constexpr (Rows == 1)
if constexpr(Cols == 1) assert(r == Rows && "Mismatched between dynamic and static row size"); assert(c == Cols && "Mismatched between dynamic and static col size");
if constexpr (Cols == 1)
assert(r == Rows && "Mismatched between dynamic and static row size");
parent::conservativeResize(r, c); parent::conservativeResize(r, c);
} }
void conservativeResize(int s) requires(IsVectorAtCompileTime) void conservativeResize(int s)
requires(IsVectorAtCompileTime)
{ {
if constexpr(Rows == 1) parent::conservativeResize(1,s); if constexpr (Rows == 1) parent::conservativeResize(1, s);
else parent::conservativeResize(s,1); else parent::conservativeResize(s, 1);
} }
matrix normalized() const requires(IsVectorAtCompileTime) matrix normalized() const
requires(IsVectorAtCompileTime)
{ {
return matrix(base().normalized()); return matrix(base().normalized());
} }
@ -151,28 +188,30 @@ namespace rotgen
return transposed_type(base().transpose()); return transposed_type(base().transpose());
} }
matrix conjugate() const matrix conjugate() const { return matrix(base().conjugate()); }
{
return matrix(base().conjugate());
}
transposed_type adjoint() const transposed_type adjoint() const
{ {
return transposed_type(base().adjoint()); return transposed_type(base().adjoint());
} }
void normalize() requires(IsVectorAtCompileTime) void normalize()
requires(IsVectorAtCompileTime)
{ {
parent::normalize(); parent::normalize();
} }
void transposeInPlace() { parent::transposeInPlace(); } void transposeInPlace() { parent::transposeInPlace(); }
void adjointInPlace() { parent::adjointInPlace(); }
matrix cwiseAbs() const { return matrix(base().cwiseAbs()); } void adjointInPlace() { parent::adjointInPlace(); }
matrix cwiseAbs2() const { return matrix(base().cwiseAbs2()); }
matrix cwiseAbs() const { return matrix(base().cwiseAbs()); }
matrix cwiseAbs2() const { return matrix(base().cwiseAbs2()); }
matrix cwiseInverse() const { return matrix(base().cwiseInverse()); } matrix cwiseInverse() const { return matrix(base().cwiseInverse()); }
matrix cwiseSqrt() const { return matrix(base().cwiseSqrt()); }
matrix cwiseSqrt() const { return matrix(base().cwiseSqrt()); }
friend bool operator==(matrix const& lhs, matrix const& rhs) friend bool operator==(matrix const& lhs, matrix const& rhs)
{ {
@ -191,10 +230,7 @@ namespace rotgen
return *this; return *this;
} }
matrix operator-() const matrix operator-() const { return matrix(base().operator-()); }
{
return matrix(base().operator-());
}
matrix& operator*=(matrix const& rhs) matrix& operator*=(matrix const& rhs)
{ {
@ -215,12 +251,13 @@ namespace rotgen
} }
auto minCoeff() const { return parent::minCoeff(); } auto minCoeff() const { return parent::minCoeff(); }
auto maxCoeff() const { return parent::maxCoeff(); } auto maxCoeff() const { return parent::maxCoeff(); }
template<std::integral IndexType> template<std::integral IndexType>
auto minCoeff(IndexType* row, IndexType* col) const auto minCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::minCoeff(&r, &c); auto result = parent::minCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
@ -230,70 +267,95 @@ namespace rotgen
template<std::integral IndexType> template<std::integral IndexType>
auto maxCoeff(IndexType* row, IndexType* col) const auto maxCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::maxCoeff(&r, &c); auto result = parent::maxCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
return result; return result;
} }
static matrix Ones() requires (Rows != -1 && Cols != -1) static matrix Ones()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Ones(Rows, Cols); return parent::Ones(Rows, Cols);
} }
static matrix Ones(int rows, int cols) static matrix Ones(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Ones(rows, cols); return parent::Ones(rows, cols);
} }
static matrix Zero() requires (Rows != -1 && Cols != -1) static matrix Zero()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Zero(Rows, Cols); return parent::Zero(Rows, Cols);
} }
static matrix Zero(int rows, int cols) static matrix Zero(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Zero(rows, cols); return parent::Zero(rows, cols);
} }
static matrix Constant(Scalar value) requires (Rows != -1 && Cols != -1) static matrix Constant(Scalar value)
requires(Rows != -1 && Cols != -1)
{ {
return parent::Constant(Rows, Cols, static_cast<Scalar>(value)); return parent::Constant(Rows, Cols, static_cast<Scalar>(value));
} }
static matrix Constant(int rows, int cols, Scalar value) static matrix Constant(int rows, int cols, Scalar value)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Constant(rows, cols, static_cast<Scalar>(value)); return parent::Constant(rows, cols, static_cast<Scalar>(value));
} }
static matrix Random() requires (Rows != -1 && Cols != -1) static matrix Random()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Random(Rows, Cols); return parent::Random(Rows, Cols);
} }
static matrix Random(int rows, int cols) static matrix Random(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Random(rows, cols); return parent::Random(rows, cols);
} }
static matrix Identity() requires (Rows != -1 && Cols != -1) static matrix Identity()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Identity(Rows, Cols); return parent::Identity(Rows, Cols);
} }
static matrix Identity(int rows, int cols) static matrix Identity(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Identity(rows, cols); return parent::Identity(rows, cols);
} }
@ -323,7 +385,8 @@ namespace rotgen
matrix& setConstant(Scalar value) matrix& setConstant(Scalar value)
{ {
*this = parent::Constant(parent::rows(), parent::cols(), static_cast<Scalar>(value)); *this = parent::Constant(parent::rows(), parent::cols(),
static_cast<Scalar>(value));
return *this; return *this;
} }
@ -357,55 +420,65 @@ namespace rotgen
return *this; return *this;
} }
template<int P> template<int P> Scalar lpNorm() const
Scalar lpNorm() const
{ {
static_assert(P == 1 || P == 2 || P == Infinity); static_assert(P == 1 || P == 2 || P == Infinity);
return parent::lp_norm(P); return parent::lp_norm(P);
} }
parent& base() { return static_cast<parent&>(*this); } parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this);; }
parent const& base() const
{
return static_cast<parent const&>(*this);
;
}
}; };
template<typename S, int R, int C, int O, int MR, int MC> template<typename S, int R, int C, int O, int MR, int MC>
matrix<S,R,C,O,MR,MC> operator+(matrix<S,R,C,O,MR,MC> const& lhs, matrix<S,R,C,O,MR,MC> const& rhs) matrix<S, R, C, O, MR, MC> operator+(matrix<S, R, C, O, MR, MC> const& lhs,
matrix<S, R, C, O, MR, MC> const& rhs)
{ {
matrix<S,R,C,O,MR,MC> that(lhs); matrix<S, R, C, O, MR, MC> that(lhs);
return that += rhs; return that += rhs;
} }
template<typename S, int R, int C, int O, int MR, int MC> template<typename S, int R, int C, int O, int MR, int MC>
matrix<S,R,C,O,MR,MC> operator-(matrix<S,R,C,O,MR,MC> const& lhs, matrix<S,R,C,O,MR,MC> const& rhs) matrix<S, R, C, O, MR, MC> operator-(matrix<S, R, C, O, MR, MC> const& lhs,
matrix<S, R, C, O, MR, MC> const& rhs)
{ {
matrix<S,R,C,O,MR,MC> that(lhs); matrix<S, R, C, O, MR, MC> that(lhs);
return that -= rhs; return that -= rhs;
} }
template<typename S, int R, int C, int O, int MR, int MC> template<typename S, int R, int C, int O, int MR, int MC>
matrix<S,R,C,O,MR,MC> operator*(matrix<S,R,C,O,MR,MC> const& lhs, matrix<S,R,C,O,MR,MC> const& rhs) matrix<S, R, C, O, MR, MC> operator*(matrix<S, R, C, O, MR, MC> const& lhs,
matrix<S, R, C, O, MR, MC> const& rhs)
{ {
matrix<S,R,C,O,MR,MC> that(lhs); matrix<S, R, C, O, MR, MC> that(lhs);
return that *= rhs; return that *= rhs;
} }
template<typename S, int R, int C, int O, int MR, int MC> template<typename S, int R, int C, int O, int MR, int MC>
matrix<S,R,C,O,MR,MC> operator*(matrix<S,R,C,O,MR,MC> const& lhs, double rhs) matrix<S, R, C, O, MR, MC> operator*(matrix<S, R, C, O, MR, MC> const& lhs,
double rhs)
{ {
matrix<S,R,C,O,MR,MC> that(lhs); matrix<S, R, C, O, MR, MC> that(lhs);
return that *= rhs; return that *= rhs;
} }
template<typename S, int R, int C, int O, int MR, int MC> template<typename S, int R, int C, int O, int MR, int MC>
matrix<S,R,C,O,MR,MC> operator*(double lhs, matrix<S,R,C,O,MR,MC> const& rhs) matrix<S, R, C, O, MR, MC> operator*(double lhs,
matrix<S, R, C, O, MR, MC> const& rhs)
{ {
return rhs * lhs; return rhs * lhs;
} }
template<typename S, int R, int C, int O, int MR, int MC> template<typename S, int R, int C, int O, int MR, int MC>
matrix<S,R,C,O,MR,MC> operator/(matrix<S,R,C,O,MR,MC> const& lhs, double rhs) matrix<S, R, C, O, MR, MC> operator/(matrix<S, R, C, O, MR, MC> const& lhs,
double rhs)
{ {
matrix<S,R,C,O,MR,MC> that(lhs); matrix<S, R, C, O, MR, MC> that(lhs);
return that /= rhs; return that /= rhs;
} }
} }

View file

@ -21,49 +21,64 @@ namespace rotgen
class matrix_impl32_row; class matrix_impl32_row;
class matrix_impl32_col; class matrix_impl32_col;
#define SIZE 64 #define SIZE 64
#define TYPE double #define TYPE double
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include <rotgen/container/matrix/dynamic/model.hpp> #include <rotgen/container/matrix/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include <rotgen/container/matrix/dynamic/model.hpp> #include <rotgen/container/matrix/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
#define SIZE 32 #define SIZE 32
#define TYPE float #define TYPE float
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include <rotgen/container/matrix/dynamic/model.hpp> #include <rotgen/container/matrix/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include <rotgen/container/matrix/dynamic/model.hpp> #include <rotgen/container/matrix/dynamic/model.hpp>
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
template<typename Scalar,int Options> struct find_matrix_impl; template<typename Scalar, int Options> struct find_matrix_impl;
template<> struct find_matrix_impl<float , ColMajor> { using type = matrix_impl32_col; }; template<> struct find_matrix_impl<float, ColMajor>
template<> struct find_matrix_impl<float , RowMajor> { using type = matrix_impl32_row; }; {
template<> struct find_matrix_impl<double, ColMajor> { using type = matrix_impl64_col; }; using type = matrix_impl32_col;
template<> struct find_matrix_impl<double, RowMajor> { using type = matrix_impl64_row; }; };
template<typename Scalar,int Options> template<> struct find_matrix_impl<float, RowMajor>
using find_matrix = typename find_matrix_impl<Scalar,(Options & 1)>::type; {
using type = matrix_impl32_row;
};
template<> struct find_matrix_impl<double, ColMajor>
{
using type = matrix_impl64_col;
};
template<> struct find_matrix_impl<double, RowMajor>
{
using type = matrix_impl64_row;
};
template<typename Scalar, int Options>
using find_matrix = typename find_matrix_impl<Scalar, (Options & 1)>::type;
} }

View file

@ -13,10 +13,12 @@
//================================================================================================== //==================================================================================================
class ROTGEN_EXPORT CLASSNAME class ROTGEN_EXPORT CLASSNAME
{ {
public: public:
CLASSNAME(); CLASSNAME();
CLASSNAME(std::size_t rows, std::size_t cols); CLASSNAME(std::size_t rows, std::size_t cols);
CLASSNAME(std::size_t rows, std::size_t cols,std::initializer_list<TYPE> init); CLASSNAME(std::size_t rows,
std::size_t cols,
std::initializer_list<TYPE> init);
CLASSNAME(std::initializer_list<std::initializer_list<TYPE>> init); CLASSNAME(std::initializer_list<std::initializer_list<TYPE>> init);
@ -35,53 +37,57 @@ class ROTGEN_EXPORT CLASSNAME
void resize(std::size_t new_rows, std::size_t new_cols); void resize(std::size_t new_rows, std::size_t new_cols);
void conservativeResize(std::size_t new_rows, std::size_t new_cols); void conservativeResize(std::size_t new_rows, std::size_t new_cols);
CLASSNAME normalized() const; CLASSNAME normalized() const;
CLASSNAME transpose() const; CLASSNAME transpose() const;
CLASSNAME conjugate() const; CLASSNAME conjugate() const;
CLASSNAME adjoint() const; CLASSNAME adjoint() const;
CLASSNAME cwiseAbs() const; CLASSNAME cwiseAbs() const;
CLASSNAME cwiseAbs2() const; CLASSNAME cwiseAbs2() const;
CLASSNAME cwiseInverse() const; CLASSNAME cwiseInverse() const;
CLASSNAME cwiseSqrt() const; CLASSNAME cwiseSqrt() const;
void normalize(); void normalize();
void transposeInPlace(); void transposeInPlace();
void adjointInPlace(); void adjointInPlace();
TYPE sum() const; TYPE sum() const;
TYPE prod() const; TYPE prod() const;
TYPE mean() const; TYPE mean() const;
TYPE trace() const; TYPE trace() const;
TYPE maxCoeff() const; TYPE maxCoeff() const;
TYPE minCoeff() const; TYPE minCoeff() const;
TYPE maxCoeff(Index* row, Index* col) const; TYPE maxCoeff(Index* row, Index* col) const;
TYPE minCoeff(Index* row, Index* col) const; TYPE minCoeff(Index* row, Index* col) const;
TYPE squaredNorm() const; TYPE squaredNorm() const;
TYPE norm() const; TYPE norm() const;
TYPE lp_norm(int p) const; TYPE lp_norm(int p) const;
TYPE& operator()(std::size_t i, std::size_t j); TYPE& operator()(std::size_t i, std::size_t j);
TYPE const& operator()(std::size_t i, std::size_t j) const; TYPE const& operator()(std::size_t i, std::size_t j) const;
TYPE& operator()(std::size_t index); TYPE& operator()(std::size_t index);
TYPE const& operator()(std::size_t index) const; TYPE const& operator()(std::size_t index) const;
CLASSNAME& operator+=(CLASSNAME const& rhs); CLASSNAME& operator+=(CLASSNAME const& rhs);
CLASSNAME& operator-=(CLASSNAME const& rhs); CLASSNAME& operator-=(CLASSNAME const& rhs);
CLASSNAME operator-() const; CLASSNAME operator-() const;
CLASSNAME& operator*=(CLASSNAME const& rhs); CLASSNAME& operator*=(CLASSNAME const& rhs);
CLASSNAME& operator*=(TYPE d); CLASSNAME& operator*=(TYPE d);
CLASSNAME& operator/=(TYPE d); CLASSNAME& operator/=(TYPE d);
friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&,CLASSNAME const&); friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&,
friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&, format<CLASSNAME> const&); CLASSNAME const&);
friend ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs); friend ROTGEN_EXPORT std::ostream& operator<<(std::ostream&,
friend ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs); format<CLASSNAME> const&);
friend ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs,
CLASSNAME const& rhs);
friend ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs,
CLASSNAME const& rhs);
const TYPE* data() const; const TYPE* data() const;
TYPE* data(); TYPE* data();
static CLASSNAME Zero(std::size_t rows, std::size_t cols); static CLASSNAME Zero(std::size_t rows, std::size_t cols);
static CLASSNAME Ones(std::size_t rows, std::size_t cols); static CLASSNAME Ones(std::size_t rows, std::size_t cols);
@ -89,11 +95,12 @@ class ROTGEN_EXPORT CLASSNAME
static CLASSNAME Random(std::size_t rows, std::size_t cols); static CLASSNAME Random(std::size_t rows, std::size_t cols);
static CLASSNAME Identity(std::size_t rows, std::size_t cols); static CLASSNAME Identity(std::size_t rows, std::size_t cols);
private: private:
struct payload; struct payload;
std::unique_ptr<payload> storage_; std::unique_ptr<payload> storage_;
public: public:
std::unique_ptr<payload>& storage() { return storage_; } std::unique_ptr<payload>& storage() { return storage_; }
std::unique_ptr<payload> const& storage() const { return storage_; } std::unique_ptr<payload> const& storage() const { return storage_; }
}; };

View file

@ -15,114 +15,139 @@ namespace rotgen
{ {
namespace detail namespace detail
{ {
template<typename Scalar, int Rows, int Cols, int Opts, int MaxRows, int MaxCols> template<typename Scalar,
using storage_type = std::conditional_t < storage_status<Rows,Cols,MaxRows,MaxCols> int Rows,
, Eigen::Matrix<Scalar, Rows, Cols, Opts, MaxRows, MaxCols> int Cols,
, Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Opts> int Opts,
>; int MaxRows,
int MaxCols>
using storage_type = std::conditional_t<
storage_status<Rows, Cols, MaxRows, MaxCols>,
Eigen::Matrix<Scalar, Rows, Cols, Opts, MaxRows, MaxCols>,
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Opts>>;
} }
template< typename Scalar template<typename Scalar,
, int Rows = Dynamic , int Cols = Dynamic int Rows = Dynamic,
, int Opts = detail::force_order<Rows,Cols> int Cols = Dynamic,
, int MaxRows = Rows, int MaxCols = Cols int Opts = detail::force_order<Rows, Cols>,
> int MaxRows = Rows,
class matrix : private detail::storage_type<Scalar, Rows, Cols, Opts, MaxRows, MaxCols> int MaxCols = Cols>
class matrix
: private detail::storage_type<Scalar, Rows, Cols, Opts, MaxRows, MaxCols>
{ {
public: public:
using rotgen_tag = void; using rotgen_tag = void;
using parent = detail::storage_type<Scalar, Rows, Cols, Opts, MaxRows, MaxCols>; using parent =
using value_type = Scalar; detail::storage_type<Scalar, Rows, Cols, Opts, MaxRows, MaxCols>;
using Index = typename parent::Index; using value_type = Scalar;
using Index = typename parent::Index;
static constexpr auto storage_order = Opts & 1; static constexpr auto storage_order = Opts & 1;
using concrete_type = matrix; using concrete_type = matrix;
using concrete_dynamic_type = matrix<value_type>; using concrete_dynamic_type = matrix<value_type>;
static constexpr int RowsAtCompileTime = Rows; static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols; static constexpr int ColsAtCompileTime = Cols;
static constexpr int MaxRowsAtCompileTime = MaxRows; static constexpr int MaxRowsAtCompileTime = MaxRows;
static constexpr int MaxColsAtCompileTime = MaxCols; static constexpr int MaxColsAtCompileTime = MaxCols;
static constexpr bool IsCompileTimeSized = Rows != -1 && Cols != -1; static constexpr bool IsCompileTimeSized = Rows != -1 && Cols != -1;
static constexpr bool IsVectorAtCompileTime = (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1); static constexpr bool IsVectorAtCompileTime =
static constexpr int Options = parent::Options; (RowsAtCompileTime == 1) || (ColsAtCompileTime == 1);
static constexpr bool IsRowMajor = parent::IsRowMajor; static constexpr int Options = parent::Options;
static constexpr bool IsRowMajor = parent::IsRowMajor;
template<typename ET> template<typename ET>
using as_concrete_type = detail::as_concrete_t<ET, matrix>; using as_concrete_type = detail::as_concrete_t<ET, matrix>;
static constexpr bool is_immutable = false; static constexpr bool is_immutable = false;
static constexpr bool is_defined_static = Rows!=-1 && Cols!=-1; static constexpr bool is_defined_static = Rows != -1 && Cols != -1;
static constexpr bool has_static_storage = storage_status<Rows,Cols,MaxRows,MaxCols>; static constexpr bool has_static_storage =
storage_status<Rows, Cols, MaxRows, MaxCols>;
public: public:
matrix()
matrix() requires(has_static_storage) {} requires(has_static_storage)
matrix() requires(!has_static_storage) : parent(Rows > 0 ? Rows : 0, Cols > 0 ? Cols : 0){}
matrix(Index r, Index c) requires(!IsCompileTimeSized) : parent(r, c) {}
matrix(const matrix& other) = default;
matrix(matrix&& other) = default;
matrix& operator=(const matrix&) = default;
matrix& operator=(matrix&&) = default;
matrix(std::initializer_list<std::initializer_list<Scalar>> init) : parent(init)
{}
matrix(Index n) requires(IsVectorAtCompileTime && (Rows != 1 || Cols != 1))
: parent(n)
{}
matrix(Scalar v) requires(Rows == 1 && Cols == 1) : parent
( [&]()
{
if constexpr(has_static_storage) return parent(v);
else return parent{1,1};
}()
)
{ {
if constexpr(!has_static_storage) (*this)(0) = v; }
matrix()
requires(!has_static_storage)
: parent(Rows > 0 ? Rows : 0, Cols > 0 ? Cols : 0)
{
}
matrix(Index r, Index c)
requires(!IsCompileTimeSized)
: parent(r, c)
{
}
matrix(matrix const& other) = default;
matrix(matrix&& other) = default;
matrix& operator=(matrix const&) = default;
matrix& operator=(matrix&&) = default;
matrix(std::initializer_list<std::initializer_list<Scalar>> init)
: parent(init)
{
}
matrix(Index n)
requires(IsVectorAtCompileTime && (Rows != 1 || Cols != 1))
: parent(n)
{
}
matrix(Scalar v)
requires(Rows == 1 && Cols == 1)
: parent([&]() {
if constexpr (has_static_storage) return parent(v);
else return parent{1, 1};
}())
{
if constexpr (!has_static_storage) (*this)(0) = v;
} }
explicit matrix(std::initializer_list<Scalar> init) explicit matrix(std::initializer_list<Scalar> init)
requires(IsVectorAtCompileTime) requires(IsVectorAtCompileTime)
: parent( [&]() : parent([&]() {
{ if constexpr (has_static_storage) return parent{};
if constexpr(has_static_storage) return parent{}; else return parent{Rows, Cols};
else return parent{Rows,Cols}; }())
}()
)
{ {
auto first = init.begin(); auto first = init.begin();
for(rotgen::Index i=0; i < parent::size(); i++) for (rotgen::Index i = 0; i < parent::size(); i++) (*this)(i) = first[i];
(*this)(i) = first[i];
} }
matrix(Scalar v0, Scalar v1, auto... vs) matrix(Scalar v0, Scalar v1, auto... vs)
requires((Rows == (2+sizeof...(vs)) && Cols == 1) || (Rows == 1 && Cols == (2+sizeof...(vs)))) requires((Rows == (2 + sizeof...(vs)) && Cols == 1) ||
: matrix({v0,v1,static_cast<Scalar>(vs)...}) (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()) {}
{}
template<typename OtherDerived> template<typename OtherDerived>
matrix(const Eigen::MatrixBase<OtherDerived>& other) : parent(other) matrix(Eigen::MatrixBase<OtherDerived> const& other) : parent(other)
{} {
}
template<typename OtherDerived> template<typename OtherDerived>
matrix(const Eigen::EigenBase<OtherDerived>& other) : parent(other) matrix(Eigen::EigenBase<OtherDerived> const& other) : parent(other)
{} {
}
template<typename OtherDerived> template<typename OtherDerived>
matrix& operator=(const Eigen::MatrixBase<OtherDerived>& other) matrix& operator=(Eigen::MatrixBase<OtherDerived> const& other)
{ {
parent::operator=(other); parent::operator=(other);
return *this; return *this;
} }
template<typename OtherDerived> template<typename OtherDerived>
matrix& operator=(const Eigen::EigenBase<OtherDerived>& other) matrix& operator=(Eigen::EigenBase<OtherDerived> const& other)
{ {
parent::operator=(other); parent::operator=(other);
return *this; return *this;
@ -134,8 +159,9 @@ namespace rotgen
return *this; return *this;
} }
parent& base() { return static_cast<parent&>(*this); } parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
auto evaluate() const auto evaluate() const
{ {
@ -145,19 +171,20 @@ namespace rotgen
decltype(auto) noalias() const decltype(auto) noalias() const
{ {
if constexpr(use_expression_templates) return base().noalias(); if constexpr (use_expression_templates) return base().noalias();
else return *this; else return *this;
} }
decltype(auto) noalias() decltype(auto) noalias()
{ {
if constexpr(use_expression_templates) return base().noalias(); if constexpr (use_expression_templates) return base().noalias();
else return *this; else return *this;
} }
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();
else else
{ {
auto res = base().normalized(); auto res = base().normalized();
@ -167,7 +194,7 @@ namespace rotgen
auto transpose() const auto transpose() const
{ {
if constexpr(use_expression_templates) return base().transpose(); if constexpr (use_expression_templates) return base().transpose();
else else
{ {
auto res = base().transpose(); auto res = base().transpose();
@ -187,163 +214,205 @@ namespace rotgen
return as_concrete_type<decltype(res)>(res); return as_concrete_type<decltype(res)>(res);
} }
void normalize() requires(IsVectorAtCompileTime) void normalize()
requires(IsVectorAtCompileTime)
{ {
parent::normalize(); parent::normalize();
} }
void transposeInPlace() { parent::transposeInPlace(); } void transposeInPlace() { parent::transposeInPlace(); }
void adjointInPlace() { parent::adjointInPlace(); }
void adjointInPlace() { parent::adjointInPlace(); }
auto cwiseAbs() const auto cwiseAbs() const
{ {
if constexpr(!use_expression_templates) return matrix{parent::cwiseAbs()}; if constexpr (!use_expression_templates)
else return base().cwiseAbs(); return matrix{parent::cwiseAbs()};
else return base().cwiseAbs();
} }
auto cwiseAbs2() const auto cwiseAbs2() const
{ {
if constexpr(!use_expression_templates) return matrix{parent::cwiseAbs2()}; if constexpr (!use_expression_templates)
else return base().cwiseAbs2(); return matrix{parent::cwiseAbs2()};
else return base().cwiseAbs2();
} }
auto cwiseInverse() const auto cwiseInverse() const
{ {
if constexpr(!use_expression_templates) return matrix{parent::cwiseInverse()}; if constexpr (!use_expression_templates)
else return base().cwiseInverse(); return matrix{parent::cwiseInverse()};
else return base().cwiseInverse();
} }
auto cwiseSqrt() const auto cwiseSqrt() const
{ {
if constexpr(!use_expression_templates) return matrix{parent::cwiseSqrt()}; if constexpr (!use_expression_templates)
else return base().cwiseSqrt(); return matrix{parent::cwiseSqrt()};
else return base().cwiseSqrt();
} }
void resize(int s) requires(IsVectorAtCompileTime) void resize(int s)
requires(IsVectorAtCompileTime)
{ {
if constexpr(Rows == 1) assert(s == Cols && "Mismatched between dynamic and static col size"); if constexpr (Rows == 1)
if constexpr(Cols == 1) assert(s == Rows && "Mismatched between dynamic and static row size"); assert(s == Cols && "Mismatched between dynamic and static col size");
if constexpr (Cols == 1)
assert(s == Rows && "Mismatched between dynamic and static row size");
parent::resize(s); parent::resize(s);
} }
void resize(int r, int c) void resize(int r, int c)
{ {
if constexpr(Rows == 1) assert(c == Cols && "Mismatched between dynamic and static col size"); if constexpr (Rows == 1)
if constexpr(Cols == 1) assert(r == Rows && "Mismatched between dynamic and static row size"); assert(c == Cols && "Mismatched between dynamic and static col size");
if constexpr (Cols == 1)
assert(r == Rows && "Mismatched between dynamic and static row size");
parent::resize(r, c); parent::resize(r, c);
} }
void conservativeResize(int s) requires(IsVectorAtCompileTime) void conservativeResize(int s)
requires(IsVectorAtCompileTime)
{ {
if constexpr(Rows == 1) assert(s == Cols && "Mismatched between dynamic and static col size"); if constexpr (Rows == 1)
if constexpr(Cols == 1) assert(s == Rows && "Mismatched between dynamic and static row size"); assert(s == Cols && "Mismatched between dynamic and static col size");
if constexpr (Cols == 1)
assert(s == Rows && "Mismatched between dynamic and static row size");
parent::conservativeResize(s); parent::conservativeResize(s);
} }
void conservativeResize(int r, int c) void conservativeResize(int r, int c)
{ {
if constexpr(Rows == 1) assert(c == Cols && "Mismatched between dynamic and static col size"); if constexpr (Rows == 1)
if constexpr(Cols == 1) assert(r == Rows && "Mismatched between dynamic and static row size"); assert(c == Cols && "Mismatched between dynamic and static col size");
if constexpr (Cols == 1)
assert(r == Rows && "Mismatched between dynamic and static row size");
parent::conservativeResize(r, c); parent::conservativeResize(r, c);
} }
static matrix Constant(Scalar value) requires (Rows != -1 && Cols != -1) static matrix Constant(Scalar value)
requires(Rows != -1 && Cols != -1)
{ {
return parent::Constant(Rows, Cols, static_cast<Scalar>(value)); return parent::Constant(Rows, Cols, static_cast<Scalar>(value));
} }
static matrix Constant(int rows, int cols, Scalar value) static matrix Constant(int rows, int cols, Scalar value)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Constant(rows, cols, static_cast<Scalar>(value)); return parent::Constant(rows, cols, static_cast<Scalar>(value));
} }
static matrix Identity() requires (Rows != -1 && Cols != -1) static matrix Identity()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Identity(Rows, Cols); return parent::Identity(Rows, Cols);
} }
static matrix Identity(int rows, int cols) static matrix Identity(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Identity(rows, cols); return parent::Identity(rows, cols);
} }
static matrix Ones() requires (Rows != -1 && Cols != -1) static matrix Ones()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Ones(Rows, Cols); return parent::Ones(Rows, Cols);
} }
static matrix Ones(int rows, int cols) static matrix Ones(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Ones(rows, cols); return parent::Ones(rows, cols);
} }
static matrix Zero() requires (Rows != -1 && Cols != -1) static matrix Zero()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Zero(Rows, Cols); return parent::Zero(Rows, Cols);
} }
static matrix Zero(int rows, int cols) static matrix Zero(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Zero(rows, cols); return parent::Zero(rows, cols);
} }
static matrix Random() requires (Rows != -1 && Cols != -1) static matrix Random()
requires(Rows != -1 && Cols != -1)
{ {
return parent::Random(Rows, Cols); return parent::Random(Rows, Cols);
} }
static matrix Random(int rows, int cols) static matrix Random(int rows, int cols)
{ {
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size"); if constexpr (Rows != -1)
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size"); assert(rows == Rows &&
"Mismatched between dynamic and static row size");
if constexpr (Cols != -1)
assert(cols == Cols &&
"Mismatched between dynamic and static column size");
return parent::Random(rows, cols); return parent::Random(rows, cols);
} }
template<int P> template<int P> value_type lpNorm() const
value_type lpNorm() const
{ {
static_assert(P == 1 || P == 2 || P == Infinity); static_assert(P == 1 || P == 2 || P == Infinity);
return parent::template lpNorm<P>(); return parent::template lpNorm<P>();
} }
value_type& operator[](Index i) requires(IsVectorAtCompileTime) value_type& operator[](Index i)
requires(IsVectorAtCompileTime)
{ {
return (*this)(i); return (*this)(i);
} }
value_type operator[](Index i) const requires(IsVectorAtCompileTime) value_type operator[](Index i) const
requires(IsVectorAtCompileTime)
{ {
return (*this)(i); return (*this)(i);
} }
using parent::operator(); using parent::operator();
using parent::rows;
using parent::cols; using parent::cols;
using parent::size;
using parent::prod;
using parent::mean;
using parent::trace;
using parent::squaredNorm;
using parent::norm;
using parent::sum;
using parent::data; using parent::data;
using parent::mean;
using parent::norm;
using parent::prod;
using parent::rows;
using parent::size;
using parent::squaredNorm;
using parent::sum;
using parent::trace;
auto minCoeff() const { return parent::minCoeff(); } auto minCoeff() const { return parent::minCoeff(); }
auto maxCoeff() const { return parent::maxCoeff(); } auto maxCoeff() const { return parent::maxCoeff(); }
template<std::integral IndexType> template<std::integral IndexType>
auto minCoeff(IndexType* row, IndexType* col) const auto minCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::minCoeff(&r, &c); auto result = parent::minCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
@ -353,7 +422,7 @@ namespace rotgen
template<std::integral IndexType> template<std::integral IndexType>
auto maxCoeff(IndexType* row, IndexType* col) const auto maxCoeff(IndexType* row, IndexType* col) const
{ {
Index r,c; Index r, c;
auto result = parent::maxCoeff(&r, &c); auto result = parent::maxCoeff(&r, &c);
*row = r; *row = r;
*col = c; *col = c;
@ -362,7 +431,7 @@ namespace rotgen
matrix& setOnes() matrix& setOnes()
{ {
*this = parent::Ones(rows(),cols()); *this = parent::Ones(rows(), cols());
return *this; return *this;
} }
@ -374,7 +443,7 @@ namespace rotgen
matrix& setZero() matrix& setZero()
{ {
*this = parent::Zero(rows(),cols()); *this = parent::Zero(rows(), cols());
return *this; return *this;
} }
@ -386,7 +455,7 @@ namespace rotgen
matrix& setConstant(Scalar value) matrix& setConstant(Scalar value)
{ {
*this = parent::Constant(rows(),cols(), static_cast<Scalar>(value)); *this = parent::Constant(rows(), cols(), static_cast<Scalar>(value));
return *this; return *this;
} }
@ -398,7 +467,7 @@ namespace rotgen
matrix& setRandom() matrix& setRandom()
{ {
*this = parent::Random(rows(),cols()); *this = parent::Random(rows(), cols());
return *this; return *this;
} }
@ -410,7 +479,7 @@ namespace rotgen
matrix& setIdentity() matrix& setIdentity()
{ {
*this = parent::Identity(rows(),cols()); *this = parent::Identity(rows(), cols());
return *this; return *this;
} }
@ -432,10 +501,7 @@ namespace rotgen
return *this; return *this;
} }
matrix operator-() const matrix operator-() const { return matrix(base()(*this).operator-()); }
{
return matrix(base()(*this).operator-());
}
matrix& operator*=(matrix const& rhs) matrix& operator*=(matrix const& rhs)
{ {

View file

@ -7,8 +7,8 @@
//================================================================================================== //==================================================================================================
#pragma once #pragma once
#include <type_traits>
#include <cassert> #include <cassert>
#include <type_traits>
#if !defined(ROTGEN_FORCE_DYNAMIC) #if !defined(ROTGEN_FORCE_DYNAMIC)
#include <Eigen/Dense> #include <Eigen/Dense>
@ -20,88 +20,113 @@ namespace rotgen
template<typename T, int Options, typename 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; 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;
static constexpr int ColsAtCompileTime = T::ColsAtCompileTime; static constexpr int ColsAtCompileTime = T::ColsAtCompileTime;
static constexpr bool IsVectorAtCompileTime = T::IsVectorAtCompileTime; static constexpr bool IsVectorAtCompileTime = T::IsVectorAtCompileTime;
static constexpr bool is_immutable = T::is_immutable; static constexpr bool is_immutable = T::is_immutable;
using parent::evaluate; using parent::evaluate;
using parent::noalias; using parent::noalias;
using parent::operator(); using parent::operator();
using parent::operator[]; using parent::operator[];
using parent::rows;
using parent::cols; using parent::cols;
using parent::size;
using parent::data;
using parent::sum;
using parent::prod;
using parent::mean;
using parent::trace;
using parent::transpose;
using parent::cwiseAbs; using parent::cwiseAbs;
using parent::cwiseAbs2; using parent::cwiseAbs2;
using parent::cwiseInverse; using parent::cwiseInverse;
using parent::cwiseSqrt; using parent::cwiseSqrt;
using parent::data;
using parent::lpNorm;
using parent::maxCoeff; using parent::maxCoeff;
using parent::mean;
using parent::minCoeff; using parent::minCoeff;
using parent::norm; using parent::norm;
using parent::normalize; using parent::normalize;
using parent::prod;
using parent::rows;
using parent::size;
using parent::squaredNorm; using parent::squaredNorm;
using parent::lpNorm; using parent::sum;
using parent::trace;
using parent::transpose;
using parent::operator+=; using parent::operator+=;
using parent::operator-=; using parent::operator-=;
using parent::operator*=; using parent::operator*=;
using parent::operator/=; using parent::operator/=;
using parent::Zero;
using parent::Constant; using parent::Constant;
using parent::Random;
using parent::Identity; using parent::Identity;
using parent::setZero;
using parent::setConstant;
using parent::setRandom;
using parent::setIdentity;
using parent::outerStride;
using parent::innerStride; 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 parent::operator=;
using stride_type = typename parent::stride_type; using stride_type = typename parent::stride_type;
parent const& base() const { return static_cast<parent const&>(*this); } parent const& base() const { return static_cast<parent const&>(*this); }
parent& base() { return static_cast<parent&>(*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> 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) ref(matrix<S, R, C, O, MR, MC>& m)
: parent(m.data(), m.rows(), m.cols(), strides(m)) : parent(m.data(), m.rows(), m.cols(), strides(m))
{} {
}
template<typename Ref, int R, int C, bool I> 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) requires(std::same_as<value_type, typename Ref::value_type> &&
ref(block<Ref,R,C,I>&& b) : parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()}) (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> 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) requires(std::same_as<value_type, typename Ref::value_type> &&
ref(block<Ref,R,C,I>& b) : parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()}) (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> template<typename Ref, int O, typename S>
requires(std::same_as<value_type, typename Ref::value_type> && (Ref::storage_order & 1) == storage_order) requires(std::same_as<value_type, typename Ref::value_type> &&
ref(map<Ref,O,S>& b) : parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()}) (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> template<typename TT, int OO, typename SS>
ref ( ref<TT,OO,SS>& b ) ref(ref<TT, OO, SS>& b)
requires(std::same_as<value_type, typename TT::value_type> && (TT::storage_order & 1) == storage_order) requires(std::same_as<value_type, typename TT::value_type> &&
: parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()}) (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()) {} ref(parent& m) : parent(m.data(), m.rows(), m.cols()) {}
@ -112,59 +137,59 @@ namespace rotgen
friend std::ostream& operator<<(std::ostream& os, format<ref> const& r) friend std::ostream& operator<<(std::ostream& os, format<ref> const& r)
{ {
return os << format{r.matrix_.base(),r.format_}; return os << format{r.matrix_.base(), r.format_};
} }
}; };
// Specialization for const matrix type // Specialization for const matrix type
template<typename T, int Options, typename Stride> template<typename T, int Options, typename Stride>
class ref<const T, Options,Stride> : private map<const T, Options,Stride> class ref<T const, Options, Stride> : private map<T const, Options, Stride>
{ {
public: public:
using parent = map<const T, Options,Stride>; using parent = map<T const, 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; 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;
static constexpr int ColsAtCompileTime = T::ColsAtCompileTime; static constexpr int ColsAtCompileTime = T::ColsAtCompileTime;
static constexpr bool IsVectorAtCompileTime = T::IsVectorAtCompileTime; static constexpr bool IsVectorAtCompileTime = T::IsVectorAtCompileTime;
static constexpr bool is_immutable = T::is_immutable; static constexpr bool is_immutable = T::is_immutable;
using parent::evaluate; using parent::evaluate;
using parent::noalias; using parent::noalias;
using parent::operator(); using parent::operator();
using parent::operator[]; using parent::operator[];
using parent::rows;
using parent::cols; using parent::cols;
using parent::size;
using parent::data;
using parent::sum;
using parent::prod;
using parent::mean;
using parent::trace;
using parent::transpose;
using parent::cwiseAbs; using parent::cwiseAbs;
using parent::cwiseAbs2; using parent::cwiseAbs2;
using parent::cwiseInverse; using parent::cwiseInverse;
using parent::cwiseSqrt; using parent::cwiseSqrt;
using parent::data;
using parent::lpNorm;
using parent::maxCoeff; using parent::maxCoeff;
using parent::mean;
using parent::minCoeff; using parent::minCoeff;
using parent::norm; using parent::norm;
using parent::normalize; using parent::normalize;
using parent::prod;
using parent::rows;
using parent::size;
using parent::squaredNorm; using parent::squaredNorm;
using parent::lpNorm; using parent::sum;
using parent::trace;
using parent::transpose;
using parent::operator+=; using parent::operator+=;
using parent::operator-=; using parent::operator-=;
using parent::operator*=; using parent::operator*=;
using parent::operator/=; using parent::operator/=;
using parent::Zero;
using parent::Constant; using parent::Constant;
using parent::Random;
using parent::Identity; using parent::Identity;
using parent::outerStride;
using parent::innerStride; using parent::innerStride;
using parent::outerStride;
using parent::Random;
using parent::Zero;
using parent::operator=; using parent::operator=;
@ -176,25 +201,41 @@ namespace rotgen
template<std::same_as<value_type> S, int R, int C, int O, int MR, int MC> 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) ref(matrix<S, R, C, O, MR, MC> const& m)
: parent(m.data(), m.rows(), m.cols(), strides(m)) : parent(m.data(), m.rows(), m.cols(), strides(m))
{} {
}
template<typename Ref, int R, int C, bool I> template<typename Ref, int R, int C, bool I>
ref ( block<Ref,R,C,I> const& b ) ref(block<Ref, R, C, I> const& b)
requires(std::same_as<value_type, typename Ref::value_type> && (Ref::storage_order & 1) == storage_order) requires(std::same_as<value_type, typename Ref::value_type> &&
: parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()}) (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> template<typename Ref, int O, typename S>
ref ( map<Ref,O,S> const& b ) ref(map<Ref, O, S> const& b)
requires(std::same_as<value_type, typename Ref::value_type> && (Ref::storage_order & 1) == storage_order) requires(std::same_as<value_type, typename Ref::value_type> &&
: parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()}) (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> template<typename TT, int OO, typename SS>
ref ( ref<TT,OO,SS> const& b ) ref(ref<TT, OO, SS> const& b)
requires(std::same_as<value_type, typename TT::value_type> && (TT::storage_order & 1) == storage_order) requires(std::same_as<value_type, typename TT::value_type> &&
: parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()}) (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()) {} ref(parent const& m) : parent(m.data(), m.rows(), m.cols()) {}
@ -205,7 +246,7 @@ namespace rotgen
friend std::ostream& operator<<(std::ostream& os, format<ref> const& r) friend std::ostream& operator<<(std::ostream& os, format<ref> const& r)
{ {
return os << format{r.matrix_.base(),r.format_}; return os << format{r.matrix_.base(), r.format_};
} }
}; };
@ -213,166 +254,186 @@ namespace rotgen
ref(matrix<S, R, C, O, MR, MC>&) -> ref<matrix<S>>; ref(matrix<S, R, C, O, MR, MC>&) -> ref<matrix<S>>;
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) -> ref<Ref>; ref(block<Ref, R, C, I>& b) -> ref<Ref>;
template<typename S, int R, int C, int O, int MR, int MC> 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>; ref(matrix<S, R, C, O, MR, MC> const&) -> ref<matrix<S> const>;
template<typename Ref, int R, int C, bool I> template<typename Ref, int R, int C, bool I>
ref(block<Ref,R,C,I> const& b) -> ref<Ref const>; ref(block<Ref, R, C, I> const& b) -> ref<Ref const>;
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>
bool operator==(ref<A,O,S> lhs, ref<B,P,T> rhs) bool 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> 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) bool 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> 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()) auto operator+(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base() + rhs.base())
{ {
return 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) -> decltype(lhs.base() += rhs.base()) auto operator+=(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base() += rhs.base())
{ {
return 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> 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()) auto operator-=(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base() -= rhs.base())
{ {
return 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> 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()) auto operator*=(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base() *= rhs.base())
{ {
return 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)
{ {
return lhs.base() * s; return lhs.base() * s;
} }
template<typename A, int O, typename S> template<typename A, int O, typename S>
auto operator*(std::convertible_to<typename A::value_type> auto s, ref<A,O,S> rhs) auto operator*(std::convertible_to<typename A::value_type> auto s,
ref<A, O, S> rhs)
{ {
return s * rhs.base(); return s * 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)
{ {
return lhs.base() / s; return lhs.base() / s;
} }
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 dot(ref<A,O,S> lhs, ref<B,P,T> rhs) auto dot(ref<A, O, S> lhs, ref<B, P, T> rhs)
{ {
return lhs.base().dot(rhs.base()); return lhs.base().dot(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 min(ref<A,O,S> lhs, ref<B,P,T> rhs) -> decltype(lhs.base().cwiseMin(rhs.base())) auto min(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseMin(rhs.base()))
{ {
return lhs.base().cwiseMin(rhs.base()); return lhs.base().cwiseMin(rhs.base());
} }
template<typename A, int O, typename S> 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)) 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); return lhs.base().cwiseMin(s);
} }
template<typename A, int O, typename 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)) 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); return rhs.base().cwiseMin(s);
} }
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 max(ref<A,O,S> lhs, ref<B,P,T> rhs) -> decltype(lhs.base().cwiseMax(rhs.base())) auto max(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseMax(rhs.base()))
{ {
return lhs.base().cwiseMax(rhs.base()); return lhs.base().cwiseMax(rhs.base());
} }
template<typename A, int O, typename S> 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)) 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); return lhs.base().cwiseMax(s);
} }
template<typename A, int O, typename 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)) 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); return rhs.base().cwiseMax(s);
} }
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 mul(ref<A,O,S> lhs, ref<B,P,T> rhs) -> decltype(lhs.base().cwiseProduct(rhs.base())) auto mul(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseProduct(rhs.base()))
{ {
return lhs.base().cwiseProduct(rhs.base()); return lhs.base().cwiseProduct(rhs.base());
} }
template<typename A, int O, typename S> 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) auto mul(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
-> decltype(lhs * s)
{ {
return lhs * s; return lhs * s;
} }
template<typename A, int O, typename 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) auto mul(std::convertible_to<typename A::value_type> auto s, ref<A, O, S> rhs)
-> decltype(s * rhs)
{ {
return s * rhs; return s * rhs;
} }
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 div(ref<A,O,S> lhs, ref<B,P,T> rhs) -> decltype(lhs.base().cwiseQuotient(rhs.base())) auto div(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cwiseQuotient(rhs.base()))
{ {
return lhs.base().cwiseQuotient(rhs.base()); return lhs.base().cwiseQuotient(rhs.base());
} }
template<typename A, int O, typename S> 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) auto div(ref<A, O, S> lhs, std::convertible_to<typename A::value_type> auto s)
-> decltype(lhs / s)
{ {
return lhs / s; return lhs / s;
} }
template<typename A, int O, typename S> template<typename A, int O, typename S>
auto inverse(ref<A,O,S> lhs) -> decltype(lhs.base().inverse()) auto inverse(ref<A, O, S> lhs) -> decltype(lhs.base().inverse())
{ {
return lhs.base().inverse(); return lhs.base().inverse();
} }
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 cross(ref<A,O,S> lhs, ref<B,P,T> rhs) -> decltype(lhs.base().cross(rhs.base())) auto cross(ref<A, O, S> lhs, ref<B, P, T> rhs)
-> decltype(lhs.base().cross(rhs.base()))
{ {
return 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;
template<typename T> template<typename T>
@ -382,42 +443,41 @@ namespace rotgen
using type = std::remove_cvref_t<T>; using type = std::remove_cvref_t<T>;
}; };
template<typename T> template<typename T> using generalize_t = typename generalize<T>::type;
using generalize_t = typename generalize<T>::type;
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,T::RowsAtCompileTime,T::ColsAtCompileTime,T::storage_order>; using base = matrix<typename T::value_type,
using type = std::conditional_t<is_const,ref<base const>, ref<base>>; 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> template<typename T, int O, typename S> struct generalize<ref<T, O, S>>
struct generalize<ref<T,O,S>>
{ {
using type = ref<T,O,S>; using type = ref<T, O, S>;
}; };
template<typename T, int O, typename S> template<typename T, int O, typename S> struct generalize<ref<T, O, S> const>
struct generalize<ref<T,O,S> const>
{ {
using type = ref<T,O,S>; using type = ref<T, O, S>;
}; };
template<concepts::entity T> template<concepts::entity T> typename T::parent& base_of(T& a)
typename T::parent& base_of(T& a)
{ {
return a.base(); 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)
{ {
return a.base(); return a.base();
} }
template<typename T> template<typename T>
T base_of(T a) requires(std::is_arithmetic_v<T>) T base_of(T a)
requires(std::is_arithmetic_v<T>)
{ {
return a; return a;
} }
@ -427,18 +487,19 @@ 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,T::RowsAtCompileTime,T::ColsAtCompileTime,concrete_type::Options&1>; using base = matrix<typename T::Scalar,
using type = std::conditional_t<is_const,ref<base const>, ref<base>>; 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> template<concepts::eigen_compatible T> auto const& base_of(T const& a)
auto const& base_of(T const& a)
{ {
return a; return a;
} }
template<concepts::eigen_compatible T> template<concepts::eigen_compatible T> auto& base_of(T& a)
auto& base_of(T& a)
{ {
return a; return a;
} }

View file

@ -16,65 +16,66 @@
namespace rotgen namespace rotgen
{ {
#if !defined(ROTGEN_FORCE_DYNAMIC) #if !defined(ROTGEN_FORCE_DYNAMIC)
using stride = Eigen::Stride<-1,-1>; using stride = Eigen::Stride<-1, -1>;
#else #else
struct stride struct stride
{ {
static constexpr bool is_dynamic = true; static constexpr bool is_dynamic = true;
stride() : outer_(-1), inner_(1) {} stride() : outer_(-1), inner_(1) {}
stride(Index s, Index i) : outer_(s), inner_(i) {}
stride(Index s, Index i) : outer_(s), inner_(i) {}
Index inner() const { return inner_; } Index inner() const { return inner_; }
Index outer() const { return outer_; } Index outer() const { return outer_; }
private: private:
Index outer_; Index outer_;
Index inner_; Index inner_;
}; };
#endif #endif
template<Index Value= Dynamic> template<Index Value = Dynamic> struct inner_stride : stride
struct inner_stride : stride
{ {
static constexpr bool is_dynamic = Value == Dynamic; static constexpr bool is_dynamic = Value == Dynamic;
inner_stride() : stride(-1,Value) {}
inner_stride() : stride(-1, Value) {}
inner_stride(Index v) : stride(0, v) {} inner_stride(Index v) : stride(0, v) {}
}; };
template<Index Value = Dynamic> template<Index Value = Dynamic> struct outer_stride : stride
struct outer_stride : stride
{ {
static constexpr bool is_dynamic = Value == Dynamic; static constexpr bool is_dynamic = Value == Dynamic;
outer_stride() : stride(Value,0) {}
outer_stride(Index v) : stride(v,0) {} outer_stride() : stride(Value, 0) {}
outer_stride(Index v) : stride(v, 0) {}
}; };
inner_stride(Index) -> inner_stride<Dynamic>; inner_stride(Index) -> inner_stride<Dynamic>;
outer_stride(Index) -> outer_stride<Dynamic>; outer_stride(Index) -> outer_stride<Dynamic>;
template<int Order> template<int Order> stride strides(Index r, Index c)
stride strides(Index r, Index c)
{ {
if constexpr (Order == RowMajor) return {c,1}; if constexpr (Order == RowMajor) return {c, 1};
else return {r,1}; else return {r, 1};
} }
template<int Order> template<int Order> stride strides(stride const& original, Index, Index)
stride strides(stride const& original,Index, Index)
{ {
return original; return original;
} }
template<int Order, Index N> template<int Order, Index N>
stride strides(outer_stride<N> const& original,Index r, Index c) stride strides(outer_stride<N> const& original, Index r, Index c)
{ {
if constexpr(N==0) return stride{ Order==ColMajor ? r : c, 1}; if constexpr (N == 0) return stride{Order == ColMajor ? r : c, 1};
else return {original.outer(),1}; else return {original.outer(), 1};
} }
template<concepts::entity E> template<concepts::entity E> auto strides(E const& e)
auto strides(const E& e)
{ {
return strides<E::storage_order>(e.rows(), e.cols()); return strides<E::storage_order>(e.rows(), e.cols());
} }

View file

@ -8,33 +8,32 @@
#pragma once #pragma once
#ifdef ROTGEN_STATIC_DEFINE #ifdef ROTGEN_STATIC_DEFINE
# define ROTGEN_EXPORT #define ROTGEN_EXPORT
# define ROTGEN_NO_EXPORT #define ROTGEN_NO_EXPORT
#else #else
# ifndef ROTGEN_EXPORT #ifndef ROTGEN_EXPORT
# ifdef rotgen_EXPORTS #ifdef rotgen_EXPORTS
/* We are building this library */ /* We are building this library */
# define ROTGEN_EXPORT __attribute__((visibility("default"))) #define ROTGEN_EXPORT __attribute__((visibility("default")))
# else #else
/* We are using this library */ /* We are using this library */
# define ROTGEN_EXPORT __attribute__((visibility("default"))) #define ROTGEN_EXPORT __attribute__((visibility("default")))
# endif #endif
# endif #endif
# ifndef ROTGEN_NO_EXPORT #ifndef ROTGEN_NO_EXPORT
# define ROTGEN_NO_EXPORT __attribute__((visibility("hidden"))) #define ROTGEN_NO_EXPORT __attribute__((visibility("hidden")))
# endif #endif
#endif #endif
#ifndef ROTGEN_DEPRECATED #ifndef ROTGEN_DEPRECATED
# define ROTGEN_DEPRECATED __attribute__ ((__deprecated__)) #define ROTGEN_DEPRECATED __attribute__((__deprecated__))
#endif #endif
#ifndef ROTGEN_DEPRECATED_EXPORT #ifndef ROTGEN_DEPRECATED_EXPORT
# define ROTGEN_DEPRECATED_EXPORT ROTGEN_EXPORT ROTGEN_DEPRECATED #define ROTGEN_DEPRECATED_EXPORT ROTGEN_EXPORT ROTGEN_DEPRECATED
#endif #endif
#ifndef ROTGEN_DEPRECATED_NO_EXPORT #ifndef ROTGEN_DEPRECATED_NO_EXPORT
# define ROTGEN_DEPRECATED_NO_EXPORT ROTGEN_NO_EXPORT ROTGEN_DEPRECATED #define ROTGEN_DEPRECATED_NO_EXPORT ROTGEN_NO_EXPORT ROTGEN_DEPRECATED
#endif #endif

View file

@ -7,6 +7,7 @@
//================================================================================================== //==================================================================================================
#pragma once #pragma once
#define ROTGEN_CAT(a, ...) ROTGEN_PRIMITIVE_CAT(a, __VA_ARGS__) #define ROTGEN_CAT(a, ...) ROTGEN_PRIMITIVE_CAT(a, __VA_ARGS__)
#define ROTGEN_PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ #define ROTGEN_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__
#define ROTGEN_MATRIX_NAME(BASE,ID,SUFFIX) ROTGEN_CAT(BASE,ROTGEN_CAT(ID,SUFFIX)) #define ROTGEN_MATRIX_NAME(BASE, ID, SUFFIX) \
ROTGEN_CAT(BASE, ROTGEN_CAT(ID, SUFFIX))

View file

@ -9,50 +9,55 @@
namespace rotgen::detail namespace rotgen::detail
{ {
template< typename EigenType template<typename EigenType,
, template<typename,int,int,int,int,int> typename Wrapper template<typename, int, int, int, int, int> typename Wrapper>
>
struct as_concrete struct as_concrete
{ {
using type = Wrapper< typename EigenType::value_type using type = Wrapper<typename EigenType::value_type,
, EigenType::RowsAtCompileTime, EigenType::ColsAtCompileTime EigenType::RowsAtCompileTime,
, EigenType::Flags & 1 EigenType::ColsAtCompileTime,
, EigenType::MaxRowsAtCompileTime, EigenType::MaxColsAtCompileTime EigenType::Flags & 1,
>; EigenType::MaxRowsAtCompileTime,
EigenType::MaxColsAtCompileTime>;
}; };
template<typename EigenType template<typename EigenType,
, template<typename,int,int,int,int,int> typename Wrapper template<typename, int, int, int, int, int> typename Wrapper>
> using as_concrete_t =
using as_concrete_t = typename as_concrete<std::remove_cvref_t<EigenType>,Wrapper>::type; typename as_concrete<std::remove_cvref_t<EigenType>, Wrapper>::type;
template<typename M, typename N> template<typename M, typename N>
inline constexpr bool has_same_vector_size = []() inline constexpr bool has_same_vector_size = []() {
{
// No vector = noo size // No vector = noo size
if(!(M::IsVectorAtCompileTime && N::IsVectorAtCompileTime)) return false; if (!(M::IsVectorAtCompileTime && N::IsVectorAtCompileTime)) return false;
// Row vectors -> same Cols // Row vectors -> same Cols
if(M::RowsAtCompileTime == 1 && N::RowsAtCompileTime == 1) return M::ColsAtCompileTime == N::ColsAtCompileTime; if (M::RowsAtCompileTime == 1 && N::RowsAtCompileTime == 1)
return M::ColsAtCompileTime == N::ColsAtCompileTime;
// Col vectors -> same Rows // Col vectors -> same Rows
if(M::ColsAtCompileTime == 1 && N::ColsAtCompileTime == 1) return M::RowsAtCompileTime == N::RowsAtCompileTime; if (M::ColsAtCompileTime == 1 && N::ColsAtCompileTime == 1)
return M::RowsAtCompileTime == N::RowsAtCompileTime;
// Mixing 1xN with Mx1 // Mixing 1xN with Mx1
return false; return false;
}(); }();
template<typename T> template<typename T>
using propagate_const = std::conditional_t<T::is_immutable || std::is_const_v<T>, std::add_const_t<T>, T>; using propagate_const =
std::conditional_t<T::is_immutable || std::is_const_v<T>,
std::add_const_t<T>,
T>;
template<auto M, auto N> 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 == rotgen::Dynamic || N == rotgen::Dynamic) ? rotgen::Dynamic : M;
template< typename M1, typename M2 template<typename M1,
, template<typename,int,int,int,int,int> typename Wrapper typename M2,
> template<typename, int, int, int, int, int> typename Wrapper>
using composite_type = Wrapper< typename M1::value_type using composite_type =
, select_static<M1::RowsAtCompileTime,M2::RowsAtCompileTime> Wrapper<typename M1::value_type,
, select_static<M1::ColsAtCompileTime,M2::ColsAtCompileTime> select_static<M1::RowsAtCompileTime, M2::RowsAtCompileTime>,
, M1::storage_order select_static<M1::ColsAtCompileTime, M2::ColsAtCompileTime>,
, select_static<M1::MaxRowsAtCompileTime,M2::MaxRowsAtCompileTime> M1::storage_order,
, select_static<M1::MaxColsAtCompileTime,M2::MaxColsAtCompileTime> select_static<M1::MaxRowsAtCompileTime, M2::MaxRowsAtCompileTime>,
>; select_static<M1::MaxColsAtCompileTime, M2::MaxColsAtCompileTime>>;
} }

View file

@ -21,180 +21,264 @@ namespace rotgen
//================================================================================================== //==================================================================================================
struct matrix_impl64_col::payload struct matrix_impl64_col::payload
{ {
using data_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>; using data_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
data_type data; 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(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)) {} payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> ref) { data = ref; } void assign(Eigen::Block<data_type> ref) { data = ref; }
void assign(data_type const& mat) { data = mat; } void assign(data_type const& mat) { data = mat; }
void assign(data_type&& mat) { data = std::move(mat); } void assign(data_type&& mat) { data = std::move(mat); }
}; };
struct matrix_impl64_row::payload struct matrix_impl64_row::payload
{ {
using data_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>; using data_type =
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
data_type data; 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(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)) {} payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> ref) { data = ref; } void assign(Eigen::Block<data_type> ref) { data = ref; }
void assign(data_type const& mat) { data = mat; } void assign(data_type const& mat) { data = mat; }
void assign(data_type&& mat) { data = std::move(mat); } void assign(data_type&& mat) { data = std::move(mat); }
}; };
struct matrix_impl32_col::payload struct matrix_impl32_col::payload
{ {
using data_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>; using data_type =
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
data_type data; 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(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)) {} payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> ref) { data = ref; } void assign(Eigen::Block<data_type> ref) { data = ref; }
void assign(data_type const& mat) { data = mat; } void assign(data_type const& mat) { data = mat; }
void assign(data_type&& mat) { data = std::move(mat); } void assign(data_type&& mat) { data = std::move(mat); }
}; };
struct matrix_impl32_row::payload struct matrix_impl32_row::payload
{ {
using data_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>; using data_type =
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
data_type data; 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(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)) {} payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> ref) { data = ref; } void assign(Eigen::Block<data_type> ref) { data = ref; }
void assign(data_type const& mat) { data = mat; } void assign(data_type const& mat) { data = mat; }
void assign(data_type&& mat) { data = std::move(mat); } void assign(data_type&& mat) { data = std::move(mat); }
}; };
//================================================================================================== //==================================================================================================
// Internal payload - Required for cross-referencing from mixed order on map operators // Internal payload - Required for cross-referencing from mixed order on map
// operators
//================================================================================================== //==================================================================================================
struct map_const_impl32_col::payload struct map_const_impl32_col::payload
{ {
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>; using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using base_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>; using base_type =
using data_type = Eigen::Map<base_type const,Eigen::Unaligned,stride_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; data_type data;
payload (data_type const& o) : data(o) {} 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) {} 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 struct map_const_impl32_row::payload
{ {
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>; using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using base_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>; using base_type =
using data_type = Eigen::Map<base_type const,Eigen::Unaligned,stride_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; data_type data;
payload (data_type const& o) : data(o) {} 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) {} 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 struct map_impl32_col::payload
{ {
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>; using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using base_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>; using base_type =
using data_type = Eigen::Map<base_type,Eigen::Unaligned,stride_type>; Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
data_type data; data_type data;
payload (data_type const& o) : data(o) {} 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) {} 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 struct map_impl32_row::payload
{ {
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>; using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using base_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>; using base_type =
using data_type = Eigen::Map<base_type,Eigen::Unaligned,stride_type>; Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
data_type data; data_type data;
payload (data_type const& o) : data(o) {} 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) {}
};
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 struct map_const_impl64_col::payload
{ {
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>; using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using base_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>; using base_type =
using data_type = Eigen::Map<base_type const,Eigen::Unaligned,stride_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; data_type data;
payload (data_type const& o) : data(o) {} 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) {} 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 struct map_const_impl64_row::payload
{ {
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>; using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using base_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>; using base_type =
using data_type = Eigen::Map<base_type const,Eigen::Unaligned,stride_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; data_type data;
payload (data_type const& o) : data(o) {} 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) {} 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 struct map_impl64_col::payload
{ {
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>; using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using base_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>; using base_type =
using data_type = Eigen::Map<base_type,Eigen::Unaligned,stride_type>; Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
data_type data; data_type data;
payload (data_type const& o) : data(o) {} 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) {} 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 struct map_impl64_row::payload
{ {
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>; using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using base_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>; using base_type =
using data_type = Eigen::Map<base_type,Eigen::Unaligned,stride_type>; Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using data_type = Eigen::Map<base_type, Eigen::Unaligned, stride_type>;
data_type data; data_type data;
payload (data_type const& o) : data(o) {} 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) {} 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 ioformat::payload struct ioformat::payload
{ {
Eigen::IOFormat instance; Eigen::IOFormat instance;
payload ( int p, int f payload(int p,
, std::string const& cs, std::string const& rsp int f,
, std::string const& rp, std::string const& rs std::string const& cs,
, std::string const& mp, std::string const& ms std::string const& rsp,
, char fill std::string const& rp,
) std::string const& rs,
: instance(p,f,cs,rsp,rp,rs,mp,ms,fill) std::string const& mp,
{} std::string const& ms,
char fill)
: instance(p, f, cs, rsp, rp, rs, mp, ms, fill)
{
}
}; };
} }

File diff suppressed because it is too large Load diff

View file

@ -15,36 +15,36 @@ namespace rotgen
{ {
class ROTGEN_EXPORT ioformat class ROTGEN_EXPORT ioformat
{ {
private: private:
struct payload; struct payload;
std::unique_ptr<payload> storage_; std::unique_ptr<payload> storage_;
public: public:
ioformat( int precision, int flags = 0 ioformat(int precision,
, std::string const& coeffSeparator = " " int flags = 0,
, std::string const& rowSeparator = "\n" std::string const& coeffSeparator = " ",
, std::string const& rowPrefix = "", std::string const& rowSuffix = "" std::string const& rowSeparator = "\n",
, std::string const& matPrefix = "", std::string const& matSuffix = "" std::string const& rowPrefix = "",
, char fill = ' ' std::string const& rowSuffix = "",
); std::string const& matPrefix = "",
std::string const& matSuffix = "",
char fill = ' ');
~ioformat(); ~ioformat();
std::unique_ptr<payload> const& storage() const { return storage_; } std::unique_ptr<payload> const& storage() const { return storage_; }
}; };
template <typename M> template<typename M> struct format
struct format
{ {
format(const M& m, const ioformat& f) : matrix_(m), format_(f) {} format(M const& m, ioformat const& f) : matrix_(m), format_(f) {}
M const& matrix_; M const& matrix_;
ioformat const& format_; ioformat const& format_;
}; };
template <typename M> template<typename M>
std::ostream& operator<<(std::ostream& os, const format<M>& f) std::ostream& operator<<(std::ostream& os, format<M> const& f)
{ {
return os << format{f.matrix_.base(), f.format_}; return os << format{f.matrix_.base(), f.format_};
} }

View file

@ -17,19 +17,19 @@ namespace rotgen
{ {
using ioformat = Eigen::IOFormat; using ioformat = Eigen::IOFormat;
template <typename M> template<typename M> struct format
struct format
{ {
format(const M& m, const ioformat& f) : matrix_(m), format_(f) {} format(M const& m, ioformat const& f) : matrix_(m), format_(f) {}
M const& matrix_; M const& matrix_;
ioformat const& format_; ioformat const& format_;
}; };
template <typename M> template<typename M>
std::ostream& operator<<(std::ostream& os, const format<M>& f) std::ostream& operator<<(std::ostream& os, format<M> const& f)
{ {
if constexpr(concepts::eigen_compatible<M>) return os << f.matrix_.format(f.format_); if constexpr (concepts::eigen_compatible<M>)
else return os << f.matrix_.base().format(f.format_); return os << f.matrix_.format(f.format_);
else return os << f.matrix_.base().format(f.format_);
} }
} }

View file

@ -13,10 +13,11 @@ namespace rotgen
namespace detail namespace detail
{ {
template<concepts::entity Entity> template<concepts::entity Entity>
void validate_extract ( [[maybe_unused]] Entity& e void validate_extract([[maybe_unused]] Entity& e,
, [[maybe_unused]] Index i0, [[maybe_unused]] Index j0 [[maybe_unused]] Index i0,
, [[maybe_unused]] Index ni, [[maybe_unused]] Index nj [[maybe_unused]] Index j0,
) [[maybe_unused]] Index ni,
[[maybe_unused]] Index nj)
{ {
assert(i0 >= 0 && "block extraction uses negative row index."); assert(i0 >= 0 && "block extraction uses negative row index.");
assert(j0 >= 0 && "block extraction uses negative col index."); assert(j0 >= 0 && "block extraction uses negative col index.");
@ -24,37 +25,36 @@ namespace rotgen
assert(j0 + nj <= e.cols() && "block extraction cols is out of range."); assert(j0 + nj <= e.cols() && "block extraction cols is out of range.");
} }
} }
//======================== EXTRACT ======================== //======================== EXTRACT ========================
template<concepts::entity Entity> template<concepts::entity Entity>
auto extract(Entity& e, Index i0, Index j0, Index ni, Index nj) auto extract(Entity& e, Index i0, Index j0, Index ni, Index nj)
{ {
detail::validate_extract(e,i0,j0,ni,nj); detail::validate_extract(e, i0, j0, ni, nj);
if constexpr(concepts::reference<Entity>) if constexpr (concepts::reference<Entity>)
return extract(e.base(), i0, j0, ni, nj); return extract(e.base(), i0, j0, ni, nj);
else else return block<detail::propagate_const<Entity>>(e, i0, j0, ni, nj);
return block<detail::propagate_const<Entity>>(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)
auto extract(Entity& e, Index i0, Index j0) auto extract(Entity& e, Index i0, Index j0)
{ {
detail::validate_extract(e,i0,j0,NI,NJ); detail::validate_extract(e, i0, j0, NI, NJ);
if constexpr(concepts::reference<Entity>) if constexpr (concepts::reference<Entity>)
return extract<NI,NJ>(e.base(), i0, j0); return extract<NI, NJ>(e.base(), i0, j0);
else else return block<detail::propagate_const<Entity>, NI, NJ>(e, i0, j0);
return block<detail::propagate_const<Entity> ,NI,NJ>(e, i0, j0);
} }
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))
auto extract(Entity& e, Index i0, Index j0, Index ni, Index nj) auto extract(Entity& e, Index i0, Index j0, Index ni, Index nj)
{ {
detail::validate_extract(e,i0,j0,ni,nj); detail::validate_extract(e, i0, j0, ni, nj);
if constexpr(concepts::reference<Entity>) if constexpr (concepts::reference<Entity>)
return extract<NI,NJ>(e.base(), i0, j0, ni, nj); return extract<NI, NJ>(e.base(), i0, j0, ni, nj);
else else
return block<detail::propagate_const<Entity>,NI,NJ>(e, i0, j0, ni, nj); return block<detail::propagate_const<Entity>, NI, NJ>(e, i0, j0, ni, nj);
} }
//======================== TOP LEFT CORNER ======================== //======================== TOP LEFT CORNER ========================
@ -67,7 +67,7 @@ namespace rotgen
template<Index NI, Index NJ, concepts::entity Entity> template<Index NI, Index NJ, concepts::entity Entity>
auto topLeftCorner(Entity& e) auto topLeftCorner(Entity& e)
{ {
return extract<NI,NJ>(e, 0, 0); return extract<NI, NJ>(e, 0, 0);
} }
//======================== TOP RIGHT CORNER ======================== //======================== TOP RIGHT CORNER ========================
@ -80,7 +80,7 @@ namespace rotgen
template<Index NI, Index NJ, concepts::entity Entity> template<Index NI, Index NJ, concepts::entity Entity>
auto topRightCorner(Entity& e) auto topRightCorner(Entity& e)
{ {
return extract<NI,NJ>(e, 0, e.cols()-NJ); return extract<NI, NJ>(e, 0, e.cols() - NJ);
} }
//======================== BOTTOM LEFT CORNER ======================== //======================== BOTTOM LEFT CORNER ========================
@ -93,7 +93,7 @@ namespace rotgen
template<Index NI, Index NJ, concepts::entity Entity> template<Index NI, Index NJ, concepts::entity Entity>
auto bottomLeftCorner(Entity& e) auto bottomLeftCorner(Entity& e)
{ {
return extract<NI,NJ>(e, e.rows()-NI, 0); return extract<NI, NJ>(e, e.rows() - NI, 0);
} }
//======================== BOTTOM RIGHT CORNER ======================== //======================== BOTTOM RIGHT CORNER ========================
@ -106,20 +106,18 @@ namespace rotgen
template<Index NI, Index NJ, concepts::entity Entity> template<Index NI, Index NJ, concepts::entity Entity>
auto bottomRightCorner(Entity& e) auto bottomRightCorner(Entity& e)
{ {
return extract<NI,NJ>(e, e.rows()-NI, e.cols()-NJ); return extract<NI, NJ>(e, e.rows() - NI, e.cols() - NJ);
} }
//======================== TOP ROWS ======================== //======================== TOP ROWS ========================
template<concepts::entity Entity> template<concepts::entity Entity> auto topRows(Entity& e, Index ni)
auto topRows(Entity& e, Index ni)
{ {
return extract(e, 0, 0, ni, e.cols()); return extract(e, 0, 0, ni, e.cols());
} }
template<Index NI, concepts::entity Entity> template<Index NI, concepts::entity Entity> auto topRows(Entity& e)
auto topRows(Entity& e)
{ {
return extract<NI,-1>(e, 0, 0, NI,e.cols()); return extract<NI, -1>(e, 0, 0, NI, e.cols());
} }
//======================== MIDDLE ROWS ======================== //======================== MIDDLE ROWS ========================
@ -132,33 +130,29 @@ namespace rotgen
template<Index NI, concepts::entity Entity> template<Index NI, concepts::entity Entity>
auto middleRows(Entity& e, Index i0) auto middleRows(Entity& e, Index i0)
{ {
return extract<NI,-1>(e, i0, 0,NI,e.cols()); return extract<NI, -1>(e, i0, 0, NI, e.cols());
} }
//======================== BOTTOM ROWS ======================== //======================== BOTTOM ROWS ========================
template<concepts::entity Entity> template<concepts::entity Entity> auto bottomRows(Entity& e, Index ni)
auto bottomRows(Entity& e, Index ni)
{ {
return extract(e, e.rows() - ni, 0, ni, e.cols()); return extract(e, e.rows() - ni, 0, ni, e.cols());
} }
template<Index NI, concepts::entity Entity> template<Index NI, concepts::entity Entity> auto bottomRows(Entity& e)
auto bottomRows(Entity& e)
{ {
return extract<NI,-1>(e, e.rows()-NI, 0,NI,e.cols()); return extract<NI, -1>(e, e.rows() - NI, 0, NI, e.cols());
} }
//======================== LEFT COLS ======================== //======================== LEFT COLS ========================
template<concepts::entity Entity> template<concepts::entity Entity> auto leftCols(Entity& e, Index nj)
auto leftCols(Entity& e, Index nj)
{ {
return extract(e, 0, 0, e.rows(), nj); return extract(e, 0, 0, e.rows(), nj);
} }
template<Index NJ, concepts::entity Entity> template<Index NJ, concepts::entity Entity> auto leftCols(Entity& e)
auto leftCols(Entity& e)
{ {
return extract<-1,NJ>(e, 0, 0,e.rows(),NJ); return extract<-1, NJ>(e, 0, 0, e.rows(), NJ);
} }
//======================== MIDDLE COLS ======================== //======================== MIDDLE COLS ========================
@ -171,81 +165,90 @@ namespace rotgen
template<Index NJ, concepts::entity Entity> template<Index NJ, concepts::entity Entity>
auto middleCols(Entity& e, Index j0) auto middleCols(Entity& e, Index j0)
{ {
return extract<-1,NJ>(e, 0, j0,e.rows(),NJ); return extract<-1, NJ>(e, 0, j0, e.rows(), NJ);
} }
//======================== RIGHT COLS ======================== //======================== RIGHT COLS ========================
template<concepts::entity Entity> template<concepts::entity Entity> auto rightCols(Entity& e, Index nj)
auto rightCols(Entity& e, Index nj)
{ {
return extract(e, 0, e.cols() - nj, e.rows(), nj); return extract(e, 0, e.cols() - nj, e.rows(), nj);
} }
template<Index NJ, concepts::entity Entity> template<Index NJ, concepts::entity Entity> auto rightCols(Entity& e)
auto rightCols(Entity& e)
{ {
return extract<-1,NJ>(e, 0, e.cols()-NJ,e.rows(),NJ); return extract<-1, NJ>(e, 0, e.cols() - NJ, e.rows(), NJ);
} }
//======================== ROW ======================== //======================== ROW ========================
template<concepts::entity Entity> template<concepts::entity Entity> auto row(Entity& e, Index i0)
auto row(Entity& e, Index i0)
{ {
return extract<1,-1>(e, i0, 0, 1, e.cols()); return extract<1, -1>(e, i0, 0, 1, e.cols());
} }
//======================== COL ======================== //======================== COL ========================
template<concepts::entity Entity> template<concepts::entity Entity> auto col(Entity& e, Index j0)
auto col(Entity& e, Index j0)
{ {
return extract<-1,1>(e, 0, j0, e.rows(), 1); return extract<-1, 1>(e, 0, j0, e.rows(), 1);
} }
//======================== VECTOR HEAD ======================== //======================== VECTOR HEAD ========================
template<concepts::entity Entity> template<concepts::entity Entity>
auto head(Entity& e, Index n) auto head(Entity& e, Index n)
requires(Entity::RowsAtCompileTime==1 || Entity::ColsAtCompileTime==1) requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1)
{ {
if constexpr(Entity::RowsAtCompileTime==1) return extract<1,Dynamic>(e,0,0,1,n); if constexpr (Entity::RowsAtCompileTime == 1)
else if constexpr(Entity::ColsAtCompileTime==1) return extract<Dynamic,1>(e,0,0,n,1); return extract<1, Dynamic>(e, 0, 0, 1, n);
else if constexpr (Entity::ColsAtCompileTime == 1)
return extract<Dynamic, 1>(e, 0, 0, n, 1);
} }
template<Index N, concepts::entity Entity> template<Index N, concepts::entity Entity>
auto head(Entity& e) requires(Entity::RowsAtCompileTime==1 || Entity::ColsAtCompileTime==1) auto head(Entity& e)
requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1)
{ {
if constexpr(Entity::RowsAtCompileTime==1) return extract<1,N>(e,0,0); if constexpr (Entity::RowsAtCompileTime == 1) return extract<1, N>(e, 0, 0);
else if constexpr(Entity::ColsAtCompileTime==1) return extract<N,1>(e,0,0); else if constexpr (Entity::ColsAtCompileTime == 1)
return extract<N, 1>(e, 0, 0);
} }
//======================== VECTOR TAIL ======================== //======================== VECTOR TAIL ========================
template<concepts::entity Entity> template<concepts::entity Entity>
auto tail(Entity& e, Index n) auto tail(Entity& e, Index n)
requires(Entity::RowsAtCompileTime==1 || Entity::ColsAtCompileTime==1) requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1)
{ {
if constexpr(Entity::RowsAtCompileTime==1) return extract<1,Dynamic>(e,0,e.cols()-n,1,n); if constexpr (Entity::RowsAtCompileTime == 1)
else if constexpr(Entity::ColsAtCompileTime==1) return extract<Dynamic,1>(e,e.rows()-n,0,n,1); return extract<1, Dynamic>(e, 0, e.cols() - n, 1, n);
else if constexpr (Entity::ColsAtCompileTime == 1)
return extract<Dynamic, 1>(e, e.rows() - n, 0, n, 1);
} }
template<Index N, concepts::entity Entity> template<Index N, concepts::entity Entity>
auto tail(Entity& e) requires(Entity::RowsAtCompileTime==1 || Entity::ColsAtCompileTime==1) auto tail(Entity& e)
requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1)
{ {
if constexpr(Entity::RowsAtCompileTime==1) return extract<1,N>(e,0,e.cols()-N); if constexpr (Entity::RowsAtCompileTime == 1)
else if constexpr(Entity::ColsAtCompileTime==1) return extract<N,1>(e,e.rows()-N,0); return extract<1, N>(e, 0, e.cols() - N);
else if constexpr (Entity::ColsAtCompileTime == 1)
return extract<N, 1>(e, e.rows() - N, 0);
} }
//======================== VECTOR SEGMENT ======================== //======================== VECTOR SEGMENT ========================
template<concepts::entity Entity> template<concepts::entity Entity>
auto segment(Entity& e, Index s, Index n) auto segment(Entity& e, Index s, Index n)
requires(Entity::RowsAtCompileTime==1 || Entity::ColsAtCompileTime==1) requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1)
{ {
if constexpr(Entity::RowsAtCompileTime==1) return extract<1,Dynamic>(e,0,s,1,n); if constexpr (Entity::RowsAtCompileTime == 1)
else if constexpr(Entity::ColsAtCompileTime==1) return extract<Dynamic,1>(e,s,0,n,1); return extract<1, Dynamic>(e, 0, s, 1, n);
else if constexpr (Entity::ColsAtCompileTime == 1)
return extract<Dynamic, 1>(e, s, 0, n, 1);
} }
template<Index N, concepts::entity Entity> template<Index N, concepts::entity Entity>
auto segment(Entity& e, Index s) requires(Entity::RowsAtCompileTime==1 || Entity::ColsAtCompileTime==1) auto segment(Entity& e, Index s)
requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1)
{ {
if constexpr(Entity::RowsAtCompileTime==1) return extract<1,N>(e,0,s); if constexpr (Entity::RowsAtCompileTime == 1) return extract<1, N>(e, 0, s);
else if constexpr(Entity::ColsAtCompileTime==1) return extract<N,1>(e,s,0); else if constexpr (Entity::ColsAtCompileTime == 1)
return extract<N, 1>(e, s, 0);
} }
} }

View file

@ -14,19 +14,44 @@ namespace rotgen
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
// Infos & Shape // Infos & Shape
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
std::size_t rows(auto const& m) requires(requires{ m.rows(); }){ return m.rows(); } std::size_t rows(auto const& m)
std::size_t cols(auto const& m) requires(requires{ m.cols(); }){ return m.cols(); } requires(requires { m.rows(); })
std::size_t size(auto const& m) requires(requires{ m.size(); }){ return m.size(); } {
return m.rows();
}
void resize(auto& a, int s) requires requires{a.resize(s);} { a.resize(s); } std::size_t cols(auto const& m)
void resize(auto& a, int r, int c) requires requires{a.resize(r,c);} { a.resize(r,c); } requires(requires { m.cols(); })
{
return m.cols();
}
void conservativeResize(auto& a, int s) requires requires{a.conservativeResize(s);} std::size_t size(auto const& m)
requires(requires { m.size(); })
{
return m.size();
}
void resize(auto& a, int s)
requires requires { a.resize(s); }
{
a.resize(s);
}
void resize(auto& a, int r, int c)
requires requires { a.resize(r, c); }
{
a.resize(r, c);
}
void conservativeResize(auto& a, int s)
requires requires { a.conservativeResize(s); }
{ {
a.conservativeResize(s); a.conservativeResize(s);
} }
void conservativeResize(auto& a, int r, int c) requires requires{a.conservativeResize(r,c);} void conservativeResize(auto& a, int r, int c)
requires requires { a.conservativeResize(r, c); }
{ {
a.conservativeResize(r, c); a.conservativeResize(r, c);
} }
@ -34,70 +59,129 @@ namespace rotgen
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
// Global operations // Global operations
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
decltype(auto) normalized (auto const& m) requires(requires{ m.normalized(); }) { return m.normalized(); } decltype(auto) normalized(auto const& m)
decltype(auto) transpose (auto const& m) requires(requires{ m.transpose(); }) { return m.transpose(); } requires(requires { m.normalized(); })
decltype(auto) conjugate (auto const& m) requires(requires{ m.conjugate(); }) { return m.conjugate(); } {
decltype(auto) adjoint (auto const& m) requires(requires{ m.adjoint(); }) { return m.adjoint(); } return m.normalized();
}
void normalize(auto& a) requires(requires{ a.normalize(); }) { a.normalize(); } decltype(auto) transpose(auto const& m)
void transposeInPlace(auto& a) requires(requires{ a.transposeInPlace(); }) { a.transposeInPlace(); } requires(requires { m.transpose(); })
void adjointInPlace(auto& a) requires(requires{ a.adjointInPlace(); }) { a.adjointInPlace(); } {
return m.transpose();
}
decltype(auto) conjugate(auto const& m)
requires(requires { m.conjugate(); })
{
return m.conjugate();
}
decltype(auto) adjoint(auto const& m)
requires(requires { m.adjoint(); })
{
return m.adjoint();
}
void normalize(auto& a)
requires(requires { a.normalize(); })
{
a.normalize();
}
void transposeInPlace(auto& a)
requires(requires { a.transposeInPlace(); })
{
a.transposeInPlace();
}
void adjointInPlace(auto& a)
requires(requires { a.adjointInPlace(); })
{
a.adjointInPlace();
}
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
// Component-wise functions // Component-wise functions
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
auto abs (auto const& arg) requires(requires{arg.cwiseAbs();} ) { return arg.cwiseAbs(); } auto abs(auto const& arg)
auto abs2(auto const& arg) requires(requires{arg.cwiseAbs2();} ) { return arg.cwiseAbs2(); } requires(requires { arg.cwiseAbs(); })
auto rec (auto const& arg) requires(requires{arg.cwiseInverse();}) { return arg.cwiseInverse(); } {
auto sqrt(auto const& arg) requires(requires{arg.cwiseSqrt();} ) { return arg.cwiseSqrt(); } return arg.cwiseAbs();
}
auto abs2(auto const& arg)
requires(requires { arg.cwiseAbs2(); })
{
return arg.cwiseAbs2();
}
auto rec(auto const& arg)
requires(requires { arg.cwiseInverse(); })
{
return arg.cwiseInverse();
}
auto sqrt(auto const& arg)
requires(requires { arg.cwiseSqrt(); })
{
return arg.cwiseSqrt();
}
template<concepts::entity A, concepts::entity B> template<concepts::entity A, concepts::entity B>
auto min(A const& a, B const& b) auto min(A const& a, B const& b)
{ {
if constexpr(!use_expression_templates) return min(generalize_t<A const>(a), generalize_t<B const>(b)); if constexpr (!use_expression_templates)
else return base_of(a).cwiseMin(base_of(b)); return min(generalize_t<A const>(a), generalize_t<B const>(b));
else return base_of(a).cwiseMin(base_of(b));
} }
template<concepts::entity A> template<concepts::entity A>
auto min(A const& a, std::convertible_to<typename A::value_type> auto b) auto min(A const& a, std::convertible_to<typename A::value_type> auto b)
{ {
if constexpr(!use_expression_templates) return min(generalize_t<A const>(a), b); if constexpr (!use_expression_templates)
else return base_of(a).cwiseMin(b); return min(generalize_t<A const>(a), b);
else return base_of(a).cwiseMin(b);
} }
template<concepts::entity B> template<concepts::entity B>
auto min(std::convertible_to<typename B::value_type> auto a, B const& b) auto min(std::convertible_to<typename B::value_type> auto a, B const& b)
{ {
if constexpr(!use_expression_templates) return min(a,generalize_t<B const>(b)); if constexpr (!use_expression_templates)
else return base_of(b).cwiseMin(a); return min(a, generalize_t<B const>(b));
else return base_of(b).cwiseMin(a);
} }
template<concepts::entity A, concepts::entity B> template<concepts::entity A, concepts::entity B>
auto max(A const& a, B const& b) auto max(A const& a, B const& b)
{ {
if constexpr(!use_expression_templates) return max(generalize_t<A const>(a), generalize_t<B const>(b)); if constexpr (!use_expression_templates)
else return base_of(a).cwiseMax(base_of(b)); return max(generalize_t<A const>(a), generalize_t<B const>(b));
else return base_of(a).cwiseMax(base_of(b));
} }
template<concepts::entity A> template<concepts::entity A>
auto max(A const& a, std::convertible_to<typename A::value_type> auto b) auto max(A const& a, std::convertible_to<typename A::value_type> auto b)
{ {
if constexpr(!use_expression_templates) return max(generalize_t<A const>(a), b); if constexpr (!use_expression_templates)
else return base_of(a).cwiseMax(b); return max(generalize_t<A const>(a), b);
else return base_of(a).cwiseMax(b);
} }
template<concepts::entity B> template<concepts::entity B>
auto max(std::convertible_to<typename B::value_type> auto a, B const& b) auto max(std::convertible_to<typename B::value_type> auto a, B const& b)
{ {
if constexpr(!use_expression_templates) return max(a, generalize_t<B const>(b)); if constexpr (!use_expression_templates)
else return base_of(b).cwiseMax(a); return max(a, generalize_t<B const>(b));
else return base_of(b).cwiseMax(a);
} }
template<concepts::entity A, concepts::entity B> template<concepts::entity A, concepts::entity B>
auto mul(A const& a, B const& b) auto mul(A const& a, B const& b)
{ {
if constexpr(!use_expression_templates) return mul(generalize_t<A const>(a), generalize_t<B const>(b)); if constexpr (!use_expression_templates)
else return base_of(a).cwiseProduct(base_of(b)); return mul(generalize_t<A const>(a), generalize_t<B const>(b));
else return base_of(a).cwiseProduct(base_of(b));
} }
template<concepts::entity A> template<concepts::entity A>
@ -115,8 +199,9 @@ namespace rotgen
template<concepts::entity A, concepts::entity B> template<concepts::entity A, concepts::entity B>
auto div(A const& a, B const& b) auto div(A const& a, B const& b)
{ {
if constexpr(!use_expression_templates) return div(generalize_t<A const>(a), generalize_t<B const>(b)); if constexpr (!use_expression_templates)
else return base_of(a).array() / base_of(b).array(); return div(generalize_t<A const>(a), generalize_t<B const>(b));
else return base_of(a).array() / base_of(b).array();
} }
template<concepts::entity A> template<concepts::entity A>
@ -125,47 +210,86 @@ namespace rotgen
return a / b; return a / b;
} }
template<concepts::entity A> template<concepts::entity A> auto square(A const& a)
auto square(A const& a)
{ {
return mul(a,a); return mul(a, a);
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
// Reductions // Reductions
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
auto trace(concepts::entity auto const& arg) { return arg.trace(); } auto trace(concepts::entity auto const& arg)
auto squaredNorm(concepts::entity auto const& arg) { return arg.squaredNorm(); } {
auto norm(concepts::entity auto const& arg) { return arg.norm(); } return arg.trace();
auto sum(auto const& arg) requires requires{ arg.sum(); } { return arg.sum(); } }
auto prod(concepts::entity auto const& arg) { return arg.prod(); }
auto mean(concepts::entity auto const& arg) { return arg.mean(); } auto squaredNorm(concepts::entity auto const& arg)
{
return arg.squaredNorm();
}
auto norm(concepts::entity auto const& arg)
{
return arg.norm();
}
auto sum(auto const& arg)
requires requires { arg.sum(); }
{
return arg.sum();
}
auto prod(concepts::entity auto const& arg)
{
return arg.prod();
}
auto mean(concepts::entity auto const& arg)
{
return arg.mean();
}
template<concepts::entity A, concepts::entity B> template<concepts::entity A, concepts::entity B>
auto dot(A const& a, B const& b) auto dot(A const& a, B const& b)
requires(detail::has_same_vector_size<A,B> && std::same_as<typename A::value_type, typename B::value_type>) requires(detail::has_same_vector_size<A, B> &&
std::same_as<typename A::value_type, typename B::value_type>)
{ {
if constexpr(!use_expression_templates) return dot(generalize_t<A const>(a), generalize_t<B const>(b)); if constexpr (!use_expression_templates)
else return base_of(a).dot(base_of(b)); return dot(generalize_t<A const>(a), generalize_t<B const>(b));
else return base_of(a).dot(base_of(b));
} }
auto maxCoeff(auto const& arg) requires( requires{ arg.maxCoeff(); } ) { return arg.maxCoeff(); } auto maxCoeff(auto const& arg)
auto minCoeff(auto const& arg) requires( requires{ arg.minCoeff(); } ) { return arg.minCoeff(); } requires(requires { arg.maxCoeff(); })
{
return arg.maxCoeff();
}
auto minCoeff(auto const& arg)
requires(requires { arg.minCoeff(); })
{
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)
{ {
return arg.maxCoeff(row, col); return arg.maxCoeff(row, col);
} }
template<std::integral IndexType> template<std::integral IndexType>
auto minCoeff(concepts::entity auto const& arg, IndexType* row, IndexType* col) auto minCoeff(concepts::entity auto const& arg,
IndexType* row,
IndexType* col)
{ {
return arg.minCoeff(row, col); return arg.minCoeff(row, col);
} }
template<int P, typename T> template<int P, typename T>
auto lpNorm(T const& arg) requires( requires{arg.template lpNorm<P>();} ) 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>();
@ -175,19 +299,22 @@ namespace rotgen
// Expression handling // Expression handling
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
template<typename T> template<typename T>
decltype(auto) noalias(T&& t) requires( requires{std::forward<T>(t).noalias();} ) decltype(auto) noalias(T&& t)
requires(requires { std::forward<T>(t).noalias(); })
{ {
return std::forward<T>(t).noalias(); return std::forward<T>(t).noalias();
} }
template<typename T> template<typename T>
auto evaluate(T&& t) requires( requires{std::forward<T>(t).evaluate();} ) auto evaluate(T&& t)
requires(requires { std::forward<T>(t).evaluate(); })
{ {
return std::forward<T>(t).evaluate(); return std::forward<T>(t).evaluate();
} }
template<typename T> template<typename T>
auto evaluate(T&& t) requires( requires{std::forward<T>(t).eval();} ) auto evaluate(T&& t)
requires(requires { std::forward<T>(t).eval(); })
{ {
return std::forward<T>(t).eval(); return std::forward<T>(t).eval();
} }
@ -196,142 +323,168 @@ namespace rotgen
// Generators // Generators
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
template<typename T> template<typename T>
auto setZero(T&& t) requires( requires{std::forward<T>(t).setZero();} ) auto setZero(T&& t)
requires(requires { std::forward<T>(t).setZero(); })
{ {
return std::forward<T>(t).setZero(); return std::forward<T>(t).setZero();
} }
template<typename T> template<typename T>
auto setZero() requires( requires{T::Zero();} ) auto setZero()
requires(requires { T::Zero(); })
{ {
return T::Zero(); return T::Zero();
} }
template<typename T> template<typename T>
auto setZero(std::integral auto n) requires( requires{T::Zero(n);} ) auto setZero(std::integral auto n)
requires(requires { T::Zero(n); })
{ {
return T::Zero(n); return T::Zero(n);
} }
template<typename T> template<typename T>
auto setZero(std::integral auto r,std::integral auto c) requires( requires{T::Zero(r,c);} ) auto setZero(std::integral auto r, std::integral auto c)
requires(requires { T::Zero(r, c); })
{ {
return T::Zero(r,c); return T::Zero(r, c);
} }
template<typename T> template<typename T>
auto setOnes(T&& t) requires( requires{std::forward<T>(t).setOnes();} ) auto setOnes(T&& t)
requires(requires { std::forward<T>(t).setOnes(); })
{ {
return std::forward<T>(t).setOnes(); return std::forward<T>(t).setOnes();
} }
template<typename T> template<typename T>
auto setOnes() requires( requires{T::Ones();} ) auto setOnes()
requires(requires { T::Ones(); })
{ {
return T::Ones(); return T::Ones();
} }
template<typename T> template<typename T>
auto setOnes(std::integral auto n) requires( requires{T::Ones(n);} ) auto setOnes(std::integral auto n)
requires(requires { T::Ones(n); })
{ {
return T::Ones(n); return T::Ones(n);
} }
template<typename T> template<typename T>
auto setOnes(std::integral auto r,std::integral auto c) requires( requires{T::Ones(r,c);} ) auto setOnes(std::integral auto r, std::integral auto c)
requires(requires { T::Ones(r, c); })
{ {
return T::Ones(r,c); return T::Ones(r, c);
} }
template<typename T> template<typename T>
auto setIdentity(T&& t) requires( requires{std::forward<T>(t).setIdentity();} ) auto setIdentity(T&& t)
requires(requires { std::forward<T>(t).setIdentity(); })
{ {
return std::forward<T>(t).setIdentity(); return std::forward<T>(t).setIdentity();
} }
template<typename T> template<typename T>
auto setIdentity() requires( requires{T::Identity();} ) auto setIdentity()
requires(requires { T::Identity(); })
{ {
return T::Identity(); return T::Identity();
} }
template<typename T> template<typename T>
auto setIdentity(std::integral auto n) requires( requires{T::Identity(n);} ) auto setIdentity(std::integral auto n)
requires(requires { T::Identity(n); })
{ {
return T::Identity(n); return T::Identity(n);
} }
template<typename T> template<typename T>
auto setIdentity(std::integral auto r,std::integral auto c) requires( requires{T::Identity(r,c);} ) auto setIdentity(std::integral auto r, std::integral auto c)
requires(requires { T::Identity(r, c); })
{ {
return T::Identity(r,c); return T::Identity(r, c);
} }
template<typename T> template<typename T>
auto setRandom(T&& t) requires( requires{std::forward<T>(t).setRandom();} ) auto setRandom(T&& t)
requires(requires { std::forward<T>(t).setRandom(); })
{ {
return std::forward<T>(t).setRandom(); return std::forward<T>(t).setRandom();
} }
template<typename T> template<typename T>
auto setRandom() requires( requires{T::Random();} ) auto setRandom()
requires(requires { T::Random(); })
{ {
return T::Random(); return T::Random();
} }
template<typename T> template<typename T>
auto setRandom(std::integral auto n) requires( requires{T::Random(n);} ) auto setRandom(std::integral auto n)
requires(requires { T::Random(n); })
{ {
return T::Random(n); return T::Random(n);
} }
template<typename T> template<typename T>
auto setRandom(std::integral auto r,std::integral auto c) requires( requires{T::Random(r,c);} ) auto setRandom(std::integral auto r, std::integral auto c)
requires(requires { T::Random(r, c); })
{ {
return T::Random(r,c); return T::Random(r, c);
} }
template<typename T> template<typename T>
auto setConstant(T&& t, auto v) requires( requires{std::forward<T>(t).setConstant(v);} ) auto setConstant(T&& t, auto v)
requires(requires { std::forward<T>(t).setConstant(v); })
{ {
return std::forward<T>(t).setConstant(v); return std::forward<T>(t).setConstant(v);
} }
template<typename T> template<typename T>
auto setConstant(auto v) requires( requires{T::Constant(v);} ) auto setConstant(auto v)
requires(requires { T::Constant(v); })
{ {
return T::Constant(v); return T::Constant(v);
} }
template<typename T> template<typename T>
auto setConstant(std::integral auto n, auto v) requires( requires{T::Constant(n,v);} ) auto setConstant(std::integral auto n, auto v)
requires(requires { T::Constant(n, v); })
{ {
return T::Constant(n,v); return T::Constant(n, v);
} }
template<typename T> template<typename T>
auto setConstant(std::integral auto r,std::integral auto c, auto v) requires( requires{T::Constant(r,c,v);} ) 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); return T::Constant(r, c, v);
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
// Others // Others
// TODO: Adapt other functions ot behave as inverse and limit code in non-ref/non-map containers // 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) template<typename A> auto inverse(A const& a)
{ {
if constexpr(!use_expression_templates) return inverse(generalize_t<A const>(a)); if constexpr (!use_expression_templates)
else if constexpr(requires{typename A::rotgen_tag;}) return base_of(a).inverse(); return inverse(generalize_t<A const>(a));
else return a.inverse(); 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) template<concepts::vectorND<3> L, concepts::vectorND<3> R>
auto cross(L const& l, R const& r)
{ {
if constexpr(!use_expression_templates) if constexpr (!use_expression_templates)
return cross(generalize_t<R const>(l),generalize_t<R const>(r)); 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;} ) else if constexpr (
requires { typename L::rotgen_tag; } ||
requires { typename R::rotgen_tag; })
return base_of(l).cross(base_of(r)); return base_of(l).cross(base_of(r));
else return l.cross(r); else return l.cross(r);
} }
} }

View file

@ -23,50 +23,58 @@ namespace rotgen
constexpr bool operator==(A const& a, B const& b) noexcept constexpr bool operator==(A const& a, B const& b) noexcept
requires(concepts::entity<A> || concepts::entity<B>) requires(concepts::entity<A> || concepts::entity<B>)
{ {
static_assert ( std::same_as<typename A::value_type,typename B::value_type> static_assert(std::same_as<typename A::value_type, typename B::value_type>,
, "[ROTGEN] Incompatible type in operator==" "[ROTGEN] Incompatible type in operator==");
); if constexpr (!use_expression_templates)
if constexpr(!use_expression_templates) return generalize_t<A const>(a) == generalize_t<B const>(b); return generalize_t<A const>(a) == generalize_t<B const>(b);
else return base_of(a) == base_of(b); else return base_of(a) == base_of(b);
} }
template<typename A, typename B> template<typename A, typename B>
constexpr bool operator!=(A const& a, B const& b) noexcept constexpr bool operator!=(A const& a, B const& b) noexcept
requires(concepts::entity<A> || concepts::entity<B>) requires(concepts::entity<A> || concepts::entity<B>)
{ {
static_assert ( std::same_as<typename A::value_type,typename B::value_type> static_assert(std::same_as<typename A::value_type, typename B::value_type>,
, "[ROTGEN] Incompatible type in operator!=" "[ROTGEN] Incompatible type in operator!=");
); if constexpr (!use_expression_templates)
if constexpr(!use_expression_templates) return generalize_t<A const>(a) != generalize_t<B const>(b); return generalize_t<A const>(a) != generalize_t<B const>(b);
else return base_of(a) != base_of(b); else return base_of(a) != base_of(b);
} }
template<typename A, typename B> template<typename A, typename B>
auto operator+(A const& a, B const& b) requires(concepts::entity<A> || concepts::entity<B>) auto operator+(A const& a, B const& b)
requires(concepts::entity<A> || concepts::entity<B>)
{ {
if constexpr(!use_expression_templates) return generalize_t<A const>(a) + generalize_t<B const>(b); if constexpr (!use_expression_templates)
else return base_of(a) + base_of(b); return generalize_t<A const>(a) + generalize_t<B const>(b);
else return base_of(a) + base_of(b);
} }
template<typename A, typename B> template<typename A, typename B>
auto operator-(A const& a, B const& b) requires(concepts::entity<A> || concepts::entity<B>) auto operator-(A const& a, B const& b)
requires(concepts::entity<A> || concepts::entity<B>)
{ {
if constexpr(!use_expression_templates) return generalize_t<A const>(a) - generalize_t<B const>(b); if constexpr (!use_expression_templates)
else return base_of(a) - base_of(b); return generalize_t<A const>(a) - generalize_t<B const>(b);
else return base_of(a) - base_of(b);
} }
template<typename A, typename B> template<typename A, typename B>
auto operator*(A const& a, B const& b) requires(concepts::entity<A> || concepts::entity<B>) auto operator*(A const& a, B const& b)
requires(concepts::entity<A> || concepts::entity<B>)
{ {
if constexpr(!use_expression_templates) return generalize_t<A const>(a) * generalize_t<B const>(b); if constexpr (!use_expression_templates)
else return base_of(a) * base_of(b); return generalize_t<A const>(a) * generalize_t<B const>(b);
else return base_of(a) * base_of(b);
} }
template<typename A, typename B> template<typename A, typename B>
auto operator/(A const& a, B const& b) requires(concepts::entity<A> && std::is_arithmetic_v<B>) auto operator/(A const& a, B const& b)
requires(concepts::entity<A> && std::is_arithmetic_v<B>)
{ {
if constexpr(!use_expression_templates) return generalize_t<A const>(a) / b; if constexpr (!use_expression_templates)
else return base_of(a) / b; return generalize_t<A const>(a) / b;
else return base_of(a) / b;
} }
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
@ -75,23 +83,26 @@ namespace rotgen
auto operator+=(A& a, B const& b) auto operator+=(A& a, B const& b)
requires(concepts::entity<A> || concepts::entity<B>) requires(concepts::entity<A> || concepts::entity<B>)
{ {
if constexpr(!use_expression_templates) return generalize_t<A>(a) += generalize_t<B const>(b); if constexpr (!use_expression_templates)
else return base_of(a) += base_of(b); return generalize_t<A>(a) += generalize_t<B const>(b);
else return base_of(a) += base_of(b);
} }
template<typename A, typename B> template<typename A, typename B>
auto operator-=(A& a, B const& b) auto operator-=(A& a, B const& b)
requires(concepts::entity<A> || concepts::entity<B>) requires(concepts::entity<A> || concepts::entity<B>)
{ {
if constexpr(!use_expression_templates) return generalize_t<A>(a) -= generalize_t<B const>(b); if constexpr (!use_expression_templates)
else return base_of(a) -= base_of(b); return generalize_t<A>(a) -= generalize_t<B const>(b);
else return base_of(a) -= base_of(b);
} }
template<typename A, typename B> template<typename A, typename B>
auto operator*=(A& a, B const& b) auto operator*=(A& a, B const& b)
requires(concepts::entity<A> || concepts::entity<B>) requires(concepts::entity<A> || concepts::entity<B>)
{ {
if constexpr(!use_expression_templates) return generalize_t<A>(a) *= generalize_t<B const>(b); if constexpr (!use_expression_templates)
else return base_of(a) *= base_of(b); return generalize_t<A>(a) *= generalize_t<B const>(b);
else return base_of(a) *= base_of(b);
} }
} }

View file

@ -16,64 +16,62 @@ namespace rotgen
concrete_type sum() const concrete_type sum() const
{ {
concrete_type res(target_.rows(),1); concrete_type res(target_.rows(), 1);
apply([&](auto r, auto i){ res(i) = r.sum(); }); apply([&](auto r, auto i) { res(i) = r.sum(); });
return res; return res;
} }
concrete_type mean() const concrete_type mean() const
{ {
concrete_type res(target_.rows(),1); concrete_type res(target_.rows(), 1);
apply([&](auto r, auto i){ res(i) = r.mean(); }); apply([&](auto r, auto i) { res(i) = r.mean(); });
return res; return res;
} }
concrete_type prod() const concrete_type prod() const
{ {
concrete_type res(target_.rows(),1); concrete_type res(target_.rows(), 1);
apply([&](auto r, auto i){ res(i) = r.prod(); }); apply([&](auto r, auto i) { res(i) = r.prod(); });
return res; return res;
} }
concrete_type maxCoeff() const concrete_type maxCoeff() const
{ {
concrete_type res(target_.rows(),1); concrete_type res(target_.rows(), 1);
apply([&](auto r, auto i){ res(i) = r.maxCoeff(); }); apply([&](auto r, auto i) { res(i) = r.maxCoeff(); });
return res; return res;
} }
concrete_type minCoeff() const concrete_type minCoeff() const
{ {
concrete_type res(target_.rows(),1); concrete_type res(target_.rows(), 1);
apply([&](auto r, auto i){ res(i) = r.minCoeff(); }); apply([&](auto r, auto i) { res(i) = r.minCoeff(); });
return res; return res;
} }
concrete_type squaredNorm() const concrete_type squaredNorm() const
{ {
concrete_type res(target_.rows(),1); concrete_type res(target_.rows(), 1);
apply([&](auto r, auto i){ res(i) = r.squaredNorm(); }); apply([&](auto r, auto i) { res(i) = r.squaredNorm(); });
return res; return res;
} }
concrete_type norm() const concrete_type norm() const
{ {
concrete_type res(target_.rows(),1); concrete_type res(target_.rows(), 1);
apply([&](auto r, auto i){ res(i) = r.norm(); }); apply([&](auto r, auto i) { res(i) = r.norm(); });
return res; return res;
} }
private: private:
template<typename Func> void apply(Func f) template<typename Func> void apply(Func f)
{ {
for(Index i = 0; i < target_.rows(); ++i) for (Index i = 0; i < target_.rows(); ++i) f(row(target_, i), i);
f(row(target_,i), i);
} }
template<typename Func> void apply(Func f) const template<typename Func> void apply(Func f) const
{ {
for(Index i = 0; i < target_.rows(); ++i) for (Index i = 0; i < target_.rows(); ++i) f(row(target_, i), i);
f(row(target_,i), i);
} }
}; };
@ -85,75 +83,73 @@ namespace rotgen
concrete_type sum() const concrete_type sum() const
{ {
concrete_type res(1, target_.cols()); concrete_type res(1, target_.cols());
apply([&](auto r, auto i){ res(i) = r.sum(); }); apply([&](auto r, auto i) { res(i) = r.sum(); });
return res; return res;
} }
concrete_type mean() const concrete_type mean() const
{ {
concrete_type res(1, target_.cols()); concrete_type res(1, target_.cols());
apply([&](auto r, auto i){ res(i) = r.mean(); }); apply([&](auto r, auto i) { res(i) = r.mean(); });
return res; return res;
} }
concrete_type prod() const concrete_type prod() const
{ {
concrete_type res(1, target_.cols()); concrete_type res(1, target_.cols());
apply([&](auto r, auto i){ res(i) = r.prod(); }); apply([&](auto r, auto i) { res(i) = r.prod(); });
return res; return res;
} }
concrete_type maxCoeff() const concrete_type maxCoeff() const
{ {
concrete_type res(1, target_.cols()); concrete_type res(1, target_.cols());
apply([&](auto r, auto i){ res(i) = r.maxCoeff(); }); apply([&](auto r, auto i) { res(i) = r.maxCoeff(); });
return res; return res;
} }
concrete_type minCoeff() const concrete_type minCoeff() const
{ {
concrete_type res(1, target_.cols()); concrete_type res(1, target_.cols());
apply([&](auto r, auto i){ res(i) = r.minCoeff(); }); apply([&](auto r, auto i) { res(i) = r.minCoeff(); });
return res; return res;
} }
concrete_type squaredNorm() const concrete_type squaredNorm() const
{ {
concrete_type res(1, target_.cols()); concrete_type res(1, target_.cols());
apply([&](auto r, auto i){ res(i) = r.squaredNorm(); }); apply([&](auto r, auto i) { res(i) = r.squaredNorm(); });
return res; return res;
} }
concrete_type norm() const concrete_type norm() const
{ {
concrete_type res(1, target_.cols()); concrete_type res(1, target_.cols());
apply([&](auto r, auto i){ res(i) = r.norm(); }); apply([&](auto r, auto i) { res(i) = r.norm(); });
return res; return res;
} }
private: private:
template<typename Func> void apply(Func f) template<typename Func> void apply(Func f)
{ {
for(Index i = 0; i < target_.cols(); ++i) for (Index i = 0; i < target_.cols(); ++i) f(col(target_, i), i);
f(col(target_,i), i);
} }
template<typename Func> void apply(Func f) const template<typename Func> void apply(Func f) const
{ {
for(Index i = 0; i < target_.cols(); ++i) for (Index i = 0; i < target_.cols(); ++i) f(col(target_, i), i);
f(col(target_,i), i);
} }
}; };
template<typename T> auto rowwise(T&& t) template<typename T> auto rowwise(T&& t)
{ {
if constexpr(use_expression_templates) return t.base().rowwise(); if constexpr (use_expression_templates) return t.base().rowwise();
else return rowwise_adaptor<T>{t}; else return rowwise_adaptor<T>{t};
} }
template<typename T> auto colwise(T&& t) template<typename T> auto colwise(T&& t)
{ {
if constexpr(use_expression_templates) return t.base().colwise(); if constexpr (use_expression_templates) return t.base().colwise();
else return colwise_adaptor<T>{t}; else return colwise_adaptor<T>{t};
} }
} }

View file

@ -7,9 +7,11 @@
//================================================================================================== //==================================================================================================
#pragma once #pragma once
//clang-format off
#include <rotgen/config.hpp> #include <rotgen/config.hpp>
#include <rotgen/format.hpp> #include <rotgen/format.hpp>
#include <rotgen/container.hpp> #include <rotgen/container.hpp>
#include <rotgen/alias.hpp> #include <rotgen/alias.hpp>
#include <rotgen/algebra.hpp> #include <rotgen/algebra.hpp>
#include <rotgen/functions.hpp> #include <rotgen/functions.hpp>
//clang-format on

View file

@ -9,10 +9,10 @@
#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 SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP,SIZE,_col) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _col)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
@ -21,10 +21,10 @@
#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 SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP,SIZE,_row) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _row)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
@ -39,10 +39,10 @@
#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 SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP,SIZE,_col) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _col)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME
@ -51,10 +51,10 @@
#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 SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP,SIZE,_row) #define MAPNAME ROTGEN_MATRIX_NAME(BASEMAP, SIZE, _row)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSSOURCENAME #undef TRANSSOURCENAME

View file

@ -13,21 +13,21 @@
namespace rotgen namespace rotgen
{ {
#define USE_CONST #define USE_CONST
#define CONST const #define CONST const
#define BASENAME block_const_impl #define BASENAME block_const_impl
#define BASEMAP map_const_impl #define BASEMAP map_const_impl
#include "generate.cpp" #include "generate.cpp"
#undef BASENAME #undef BASENAME
#undef BASEMAP #undef BASEMAP
#undef USE_CONST #undef USE_CONST
#undef CONST #undef CONST
#define CONST #define CONST
#define BASENAME block_impl #define BASENAME block_impl
#define BASEMAP map_impl #define BASEMAP map_impl
#include "generate.cpp" #include "generate.cpp"
#undef BASENAME #undef BASENAME
#undef BASEMAP #undef BASEMAP
#undef CONST #undef CONST
} }

View file

@ -17,518 +17,528 @@
//================================================================================================== //==================================================================================================
struct CLASSNAME::payload struct CLASSNAME::payload
{ {
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>; using stride_type = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using matrix_type = Eigen::Matrix<TYPE,Eigen::Dynamic,Eigen::Dynamic,STORAGE_ORDER>; using matrix_type =
Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic, STORAGE_ORDER>;
using matrix_block_type = Eigen::Block<matrix_type CONST>; using matrix_block_type = Eigen::Block<matrix_type CONST>;
using matrix_storage_t = std::pair<matrix_block_type, 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_type = Eigen::Map<matrix_type CONST, Eigen::Unaligned, stride_type>;
using map_block_type = Eigen::Block<map_type CONST>; using map_block_type = Eigen::Block<map_type CONST>;
using map_storage_t = std::pair<map_block_type, 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>; using data_type = std::variant<matrix_storage_t, map_storage_t>;
data_type data; data_type data;
rotgen::Index abs_i0 = 0; // absolute start row in original matrix rotgen::Index abs_i0 = 0; // absolute start row in original matrix
rotgen::Index abs_j0 = 0; // absolute start col 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_i0 = 0; // relative start row in original matrix
rotgen::Index rel_j0 = 0; // relative start col in original matrix rotgen::Index rel_j0 = 0; // relative start col in original matrix
template <typename Func> template<typename Func> void apply(Func f)
void apply(Func f) { std::visit([&](auto& blk) { return f(blk.first); }, data); } {
std::visit([&](auto& blk) { return f(blk.first); }, data);
}
template <typename Func> template<typename Func> void apply(Func f) const
void apply(Func f) const { std::visit([&](auto const& blk) { return f(blk.first); }, data); } {
std::visit([&](auto const& blk) { return f(blk.first); }, data);
}
payload (data_type const& o) : data(o) {} payload(data_type const& o) : data(o) {}
payload (SOURCENAME CONST& o, rotgen::Index i0, rotgen::Index j0, rotgen::Index ni, rotgen::Index nj) payload(SOURCENAME CONST& o,
: data(matrix_storage_t{matrix_block_type{o.storage()->data,i0,j0,ni,nj},&o.storage()->data}) rotgen::Index i0,
, abs_i0(i0), abs_j0(j0), rel_i0(i0), rel_j0(j0) 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) payload(MAPNAME CONST& o,
: data(map_storage_t{map_block_type{o.storage()->data,i0,j0,ni,nj},&o.storage()->data}) rotgen::Index i0,
, abs_i0(i0), abs_j0(j0), rel_i0(i0), rel_j0(j0) 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 // Constructors & Special Members
//================================================================================================== //==================================================================================================
CLASSNAME::CLASSNAME(SOURCENAME CONST& r, Index i0, Index j0, Index ni, Index nj) CLASSNAME::CLASSNAME(
: storage_(std::make_unique<payload>(r, i0,j0,ni,nj)) SOURCENAME CONST& r, Index i0, Index j0, Index ni, Index nj)
{} : storage_(std::make_unique<payload>(r, i0, j0, ni, nj))
{
}
CLASSNAME::CLASSNAME(MAPNAME CONST& r, Index i0, Index j0, Index ni, Index nj) 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))
{} {
}
// We're building a block from a block - So we have to dig around the internals // 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(payload const& o, Index i0, Index j0, Index ni, Index nj)
{ {
// Compute absolute indices from the parent stored block // Compute absolute indices from the parent stored block
Index abs_i0 = 0; Index abs_i0 = 0;
Index abs_j0 = 0; Index abs_j0 = 0;
std::visit( [&](auto const& blk) std::visit(
{ [&](auto const& blk) {
abs_i0 = blk.first.startRow() + i0; abs_i0 = blk.first.startRow() + i0;
abs_j0 = blk.first.startCol() + j0; abs_j0 = blk.first.startCol() + j0;
} },
, o.data o.data);
);
// Build a payload::data_type that holds the child block using absolute indices // Build a payload::data_type that holds the child block using absolute
payload::data_type new_data = // indices
std::visit([&]<typename T>(T const& blk) -> payload::data_type payload::data_type new_data = std::visit(
{ [&]<typename T>(T const& blk) -> payload::data_type {
auto& [parent_block, ref] = blk; auto& [parent_block, ref] = blk;
using block_type = typename T::first_type; using block_type = typename T::first_type;
return T{ block_type{ *ref, abs_i0, abs_j0, ni, nj }, ref }; return T{block_type{*ref, abs_i0, abs_j0, ni, nj}, ref};
}, o.data); },
o.data);
storage_ = std::make_unique<payload>(new_data); storage_ = std::make_unique<payload>(new_data);
storage_->abs_i0 = abs_i0; storage_->abs_i0 = abs_i0;
storage_->abs_j0 = abs_j0; storage_->abs_j0 = abs_j0;
storage_->rel_i0 = i0; storage_->rel_i0 = i0;
storage_->rel_j0 = j0; storage_->rel_j0 = j0;
} }
CLASSNAME::CLASSNAME(CLASSNAME const& o) CLASSNAME::CLASSNAME(CLASSNAME const& o)
: storage_(std::make_unique<payload>(o.storage_->data)) : storage_(std::make_unique<payload>(o.storage_->data))
{} {
}
CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default; CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default;
#if !defined(USE_CONST) #if !defined(USE_CONST)
CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o) CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
{ {
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) noexcept CLASSNAME& CLASSNAME::operator=(CLASSNAME&& o) noexcept
{ {
if (this != &o) { storage_->data = std::move(o.storage_->data); } if (this != &o) { storage_->data = std::move(o.storage_->data); }
return *this; return *this;
} }
#endif #endif
CLASSNAME::~CLASSNAME() = default;
CLASSNAME::~CLASSNAME() = default; #if !defined(USE_CONST)
void CLASSNAME::assign(SOURCENAME const& m)
{
storage_->apply([&](auto& blk) { blk = m.storage()->data; });
}
#endif
#if !defined(USE_CONST) //==================================================================================================
void CLASSNAME::assign(SOURCENAME const& m) // Matrix API
{ //==================================================================================================
storage_->apply([&](auto& blk) rotgen::Index CLASSNAME::rows() const
{ {
blk = m.storage()->data; rotgen::Index that;
}); storage_->apply([&](auto const& blk) { that = blk.rows(); });
} return that;
#endif }
//================================================================================================== rotgen::Index CLASSNAME::cols() const
// Matrix API {
//================================================================================================== rotgen::Index that;
rotgen::Index CLASSNAME::rows() const storage_->apply([&](auto const& blk) { that = blk.cols(); });
{ return that;
rotgen::Index that; }
storage_->apply([&](const auto& blk) { that = blk.rows(); });
return that;
}
rotgen::Index CLASSNAME::cols() const rotgen::Index CLASSNAME::size() const
{ {
rotgen::Index that; rotgen::Index that;
storage_->apply([&](const auto& blk) { that = blk.cols(); }); storage_->apply([&](auto const& blk) { that = blk.size(); });
return that; return that;
} }
rotgen::Index CLASSNAME::size() const rotgen::Index CLASSNAME::innerStride() const
{ {
rotgen::Index that; rotgen::Index that;
storage_->apply([&](const auto& blk) { that = blk.size(); }); storage_->apply([&](auto const& blk) { that = blk.innerStride(); });
return that; return that;
} }
rotgen::Index CLASSNAME::innerStride() const rotgen::Index CLASSNAME::outerStride() const
{ {
rotgen::Index that; rotgen::Index that;
storage_->apply([&](const auto& blk) { that = blk.innerStride(); }); storage_->apply([&](auto const& blk) { that = blk.outerStride(); });
return that; return that;
} }
rotgen::Index CLASSNAME::outerStride() const rotgen::Index CLASSNAME::startRow() const
{ {
rotgen::Index that; return storage_->rel_i0;
storage_->apply([&](const auto& blk) { that = blk.outerStride(); }); }
return that;
}
rotgen::Index CLASSNAME::startRow() const rotgen::Index CLASSNAME::startCol() const
{ {
return storage_->rel_i0; return storage_->rel_j0;
} }
rotgen::Index CLASSNAME::startCol() const // Element access by (i,j)
{ #if !defined(USE_CONST)
return storage_->rel_j0; TYPE& CLASSNAME::operator()(Index i, Index j)
} {
TYPE* ptr = nullptr;
storage_->apply([&](auto& blk) { ptr = &blk(i, j); });
return *ptr;
}
#endif
// Element access by (i,j) TYPE CLASSNAME::operator()(Index i, Index j) const
#if !defined(USE_CONST) {
TYPE& CLASSNAME::operator()(Index i, Index j) TYPE ptr;
{ storage_->apply([&](auto const& blk) { ptr = blk(i, j); });
TYPE* ptr = nullptr; return ptr;
storage_->apply([&](auto& blk) { ptr = &blk(i,j); }); }
return *ptr;
}
#endif
TYPE CLASSNAME::operator()(Index i, Index j) const // Element access by linear index
{ #if !defined(USE_CONST)
TYPE ptr; TYPE& CLASSNAME::operator()(Index index)
storage_->apply([&](auto const& blk) { ptr = blk(i,j); }); {
return ptr; TYPE* ptr = nullptr;
} storage_->apply([&](auto& blk) { ptr = blk.data() + index; });
return *ptr;
}
#endif
// Element access by linear index TYPE CLASSNAME::operator()(Index index) const
#if !defined(USE_CONST) {
TYPE& CLASSNAME::operator()(Index index) TYPE ptr;
{ storage_->apply([&](auto const& blk) { ptr = *(blk.data() + index); });
TYPE* ptr = nullptr; return ptr;
storage_->apply([&](auto& blk) { ptr = blk.data() + index; }); }
return *ptr;
}
#endif
TYPE CLASSNAME::operator()(Index index) const // Raw pointer access
{ #if !defined(USE_CONST)
TYPE ptr; TYPE* CLASSNAME::data()
storage_->apply([&](auto const& blk) { ptr = *(blk.data() + index); }); {
return ptr; TYPE* ptr = nullptr;
} storage_->apply([&](auto& blk) { ptr = blk.data(); });
return ptr;
}
#endif
// Raw pointer access TYPE const* CLASSNAME::data() const
#if !defined(USE_CONST) {
TYPE* CLASSNAME::data() TYPE const* ptr = nullptr;
{ storage_->apply([&](auto const& blk) { ptr = blk.data(); });
TYPE* ptr = nullptr; return ptr;
storage_->apply([&](auto& blk) { ptr = blk.data(); }); }
return ptr;
}
#endif
TYPE const* CLASSNAME::data() const //==================================================================================================
{ // Matrix operations
TYPE const* ptr = nullptr; //==================================================================================================
storage_->apply([&](auto const& blk) { ptr = blk.data(); }); SOURCENAME CLASSNAME::normalized() const
return ptr; {
} SOURCENAME result;
storage_->apply([&](auto const& blk) {
result.storage()->assign(blk.normalized().eval());
});
return result;
}
//================================================================================================== SOURCENAME CLASSNAME::transpose() const
// Matrix operations {
//================================================================================================== SOURCENAME result;
SOURCENAME CLASSNAME::normalized() const storage_->apply(
{ [&](auto const& blk) { result.storage()->assign(blk.transpose().eval()); });
SOURCENAME result; return result;
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.normalized().eval()); }); }
return result;
}
SOURCENAME CLASSNAME::transpose() const SOURCENAME CLASSNAME::conjugate() const
{ {
SOURCENAME result; SOURCENAME result;
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.transpose().eval()); }); storage_->apply(
return result; [&](auto const& blk) { result.storage()->assign(blk.conjugate().eval()); });
} return result;
}
SOURCENAME CLASSNAME::conjugate() const SOURCENAME CLASSNAME::adjoint() const
{ {
SOURCENAME result; SOURCENAME result;
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.conjugate().eval()); }); storage_->apply(
return result; [&](auto const& blk) { result.storage()->assign(blk.adjoint().eval()); });
} return result;
}
SOURCENAME CLASSNAME::adjoint() const SOURCENAME CLASSNAME::cwiseAbs() const
{ {
SOURCENAME result; SOURCENAME result;
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.adjoint().eval()); }); storage_->apply(
return result; [&](auto const& blk) { result.storage()->assign(blk.cwiseAbs().eval()); });
} return result;
}
SOURCENAME CLASSNAME::cwiseAbs() const SOURCENAME CLASSNAME::cwiseAbs2() const
{ {
SOURCENAME result; SOURCENAME result;
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.cwiseAbs().eval()); }); storage_->apply(
return result; [&](auto const& blk) { result.storage()->assign(blk.cwiseAbs2().eval()); });
} return result;
}
SOURCENAME CLASSNAME::cwiseAbs2() const SOURCENAME CLASSNAME::cwiseInverse() const
{ {
SOURCENAME result; SOURCENAME result;
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.cwiseAbs2().eval()); }); storage_->apply([&](auto const& blk) {
return result; result.storage()->assign(blk.cwiseInverse().eval());
} });
return result;
}
SOURCENAME CLASSNAME::cwiseInverse() const SOURCENAME CLASSNAME::cwiseSqrt() const
{ {
SOURCENAME result; SOURCENAME result;
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.cwiseInverse().eval()); }); storage_->apply(
return result; [&](auto const& blk) { result.storage()->assign(blk.cwiseSqrt().eval()); });
} return result;
}
SOURCENAME CLASSNAME::cwiseSqrt() const #if !defined(USE_CONST)
{ void CLASSNAME::normalize()
SOURCENAME result; {
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.cwiseSqrt().eval()); }); storage_->apply([](auto& blk) { blk.normalize(); });
return result; }
}
#if !defined(USE_CONST) void CLASSNAME::transposeInPlace()
void CLASSNAME::normalize() {
{ storage_->apply([](auto& blk) { blk.transposeInPlace(); });
storage_->apply([](auto& blk) { blk.normalize(); }); }
}
void CLASSNAME::transposeInPlace() void CLASSNAME::adjointInPlace()
{ {
storage_->apply([](auto& blk) { blk.transposeInPlace(); }); storage_->apply([](auto& blk) { blk.adjointInPlace(); });
} }
#endif
void CLASSNAME::adjointInPlace() //==================================================================================================
{ // Reductions
storage_->apply([](auto& blk) { blk.adjointInPlace(); }); //==================================================================================================
} TYPE CLASSNAME::sum() const
#endif {
TYPE val{};
storage_->apply([&](auto const& blk) { val = blk.sum(); });
return val;
}
//================================================================================================== TYPE CLASSNAME::prod() const
// Reductions {
//================================================================================================== TYPE val{};
TYPE CLASSNAME::sum() const storage_->apply([&](auto const& blk) { val = blk.prod(); });
{ return val;
TYPE val{}; }
storage_->apply([&](const auto& blk) { val = blk.sum(); });
return val;
}
TYPE CLASSNAME::prod() const TYPE CLASSNAME::mean() const
{ {
TYPE val{}; TYPE val{};
storage_->apply([&](const auto& blk) { val = blk.prod(); }); storage_->apply([&](auto const& blk) { val = blk.mean(); });
return val; return val;
} }
TYPE CLASSNAME::mean() const TYPE CLASSNAME::trace() const
{ {
TYPE val{}; TYPE val{};
storage_->apply([&](const auto& blk) { val = blk.mean(); }); storage_->apply([&](auto const& blk) { val = blk.trace(); });
return val; return val;
} }
TYPE CLASSNAME::trace() const TYPE CLASSNAME::minCoeff() const
{ {
TYPE val{}; TYPE val{};
storage_->apply([&](const auto& blk) { val = blk.trace(); }); storage_->apply([&](auto const& blk) { val = blk.minCoeff(); });
return val; return val;
} }
TYPE CLASSNAME::minCoeff() const TYPE CLASSNAME::maxCoeff() const
{ {
TYPE val{}; TYPE val{};
storage_->apply([&](const auto& blk) { val = blk.minCoeff(); }); storage_->apply([&](auto const& blk) { val = blk.maxCoeff(); });
return val; return val;
} }
TYPE CLASSNAME::maxCoeff() const TYPE CLASSNAME::minCoeff(Index* row, Index* col) const
{ {
TYPE val{}; TYPE val{};
storage_->apply([&](const auto& blk) { val = blk.maxCoeff(); }); storage_->apply([&](auto const& blk) { val = blk.minCoeff(row, col); });
return val; return val;
} }
TYPE CLASSNAME::minCoeff(Index* row, Index* col) const TYPE CLASSNAME::maxCoeff(Index* row, Index* col) const
{ {
TYPE val{}; TYPE val{};
storage_->apply([&](const auto& blk) { val = blk.minCoeff(row, col); }); storage_->apply([&](auto const& blk) { val = blk.maxCoeff(row, col); });
return val; return val;
} }
TYPE CLASSNAME::maxCoeff(Index* row, Index* col) const TYPE CLASSNAME::squaredNorm() const
{ {
TYPE val{}; TYPE val{};
storage_->apply([&](const auto& blk) { val = blk.maxCoeff(row, col); }); storage_->apply([&](auto const& blk) { val = blk.squaredNorm(); });
return val; return val;
} }
TYPE CLASSNAME::squaredNorm() const TYPE CLASSNAME::norm() const
{ {
TYPE val{}; TYPE val{};
storage_->apply([&](const auto& blk) { val = blk.squaredNorm(); }); storage_->apply([&](auto const& blk) { val = blk.norm(); });
return val; return val;
} }
TYPE CLASSNAME::norm() const TYPE CLASSNAME::lpNorm(int p) const
{ {
TYPE val{}; TYPE val{};
storage_->apply([&](const auto& blk) { val = blk.norm(); }); storage_->apply([&](auto const& blk) {
return val; if (p == 1) val = blk.template lpNorm<1>();
} else if (p == 2) val = blk.template lpNorm<2>();
else val = blk.template lpNorm<Eigen::Infinity>();
});
return val;
}
TYPE CLASSNAME::lpNorm(int p) const //==================================================================================================
{ // Operators
TYPE val{}; //==================================================================================================
storage_->apply([&](const auto& blk) ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os, CLASSNAME const& m)
{ {
if (p == 1) val = blk.template lpNorm<1>(); m.storage_->apply([&](auto const& blk) { os << blk; });
else if (p == 2) val = blk.template lpNorm<2>(); return os;
else val = blk.template lpNorm<Eigen::Infinity>(); }
});
return val;
}
//================================================================================================== ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os,
// Operators format<CLASSNAME> const& m)
//================================================================================================== {
ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os, CLASSNAME const& m) m.matrix_.storage_->apply(
{ [&](auto const& blk) { os << blk.format(m.format_.storage()->instance); });
m.storage_->apply([&](const auto& blk) { os << blk; }); return os;
return os; }
}
ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os,format<CLASSNAME> const& m) ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs)
{ {
m.matrix_.storage_->apply([&](const auto& blk) { os << blk.format(m.format_.storage()->instance); }); return std::visit(
return os; [](auto const& lhs_blk, auto const& rhs_blk) {
} return lhs_blk.first == rhs_blk.first;
},
lhs.storage_->data, rhs.storage_->data);
}
ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs) ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs)
{ {
return std::visit ( [](auto const& lhs_blk, auto const& rhs_blk) { return lhs_blk.first == rhs_blk.first; } return std::visit(
, lhs.storage_->data [](auto const& lhs_blk, auto const& rhs_blk) {
, rhs.storage_->data return lhs_blk.first != rhs_blk.first;
); },
} lhs.storage_->data, rhs.storage_->data);
}
ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs) SOURCENAME CLASSNAME::operator-() const
{ {
return std::visit ( [](auto const& lhs_blk, auto const& rhs_blk) { return lhs_blk.first != rhs_blk.first; } SOURCENAME result;
, lhs.storage_->data storage_->apply([&](auto const& blk) { result.storage()->assign(blk); });
, rhs.storage_->data return -result;
); }
}
#if !defined(USE_CONST)
CLASSNAME& CLASSNAME::operator+=(CLASSNAME const& rhs)
{
std::visit(
[](auto& lhs_blk, auto const& rhs_blk) { lhs_blk.first += rhs_blk.first; },
storage_->data, rhs.storage_->data);
return *this;
}
SOURCENAME CLASSNAME::operator-() const CLASSNAME& CLASSNAME::operator-=(CLASSNAME const& rhs)
{ {
SOURCENAME result; std::visit(
storage_->apply([&](const auto& blk) { result.storage()->assign(blk); }); [](auto& lhs_blk, auto const& rhs_blk) { lhs_blk.first -= rhs_blk.first; },
return -result; storage_->data, rhs.storage_->data);
} return *this;
}
#if !defined(USE_CONST) CLASSNAME& CLASSNAME::operator*=(CLASSNAME const& rhs)
CLASSNAME& CLASSNAME::operator+=(CLASSNAME const& rhs) {
{ std::visit(
std::visit( [](auto& lhs_blk, auto const& rhs_blk) { lhs_blk.first += rhs_blk.first; } [](auto& lhs_blk, auto const& rhs_blk) { lhs_blk.first *= rhs_blk.first; },
, storage_->data storage_->data, rhs.storage_->data);
, rhs.storage_->data return *this;
); }
return *this;
}
CLASSNAME& CLASSNAME::operator-=(CLASSNAME const& rhs) CLASSNAME& CLASSNAME::operator*=(TYPE s)
{ {
std::visit( [](auto& lhs_blk, auto const& rhs_blk) { lhs_blk.first -= rhs_blk.first; } storage_->apply([&](auto& blk) { blk *= s; });
, storage_->data return *this;
, rhs.storage_->data }
);
return *this;
}
CLASSNAME& CLASSNAME::operator*=(CLASSNAME const& rhs) CLASSNAME& CLASSNAME::operator/=(TYPE s)
{ {
std::visit( [](auto& lhs_blk, auto const& rhs_blk) { lhs_blk.first *= rhs_blk.first; } storage_->apply([&](auto& blk) { blk /= s; });
, storage_->data return *this;
, rhs.storage_->data }
); #endif
return *this;
}
CLASSNAME& CLASSNAME::operator*=(TYPE s) SOURCENAME CLASSNAME::add(CLASSNAME const& rhs) const
{ {
storage_->apply([&](auto& blk) { blk *= s; }); SOURCENAME result;
return *this; result.storage()->assign(std::visit(
} [](auto const& lhs_blk, auto const& rhs_blk) {
return (lhs_blk.first + rhs_blk.first).eval();
},
storage_->data, rhs.storage_->data));
return result;
}
CLASSNAME& CLASSNAME::operator/=(TYPE s) SOURCENAME CLASSNAME::sub(CLASSNAME const& rhs) const
{ {
storage_->apply([&](auto& blk) { blk /= s; }); SOURCENAME result;
return *this; result.storage()->assign(std::visit(
} [](auto const& lhs_blk, auto const& rhs_blk) {
#endif return (lhs_blk.first - rhs_blk.first).eval();
},
storage_->data, rhs.storage_->data));
return result;
}
SOURCENAME CLASSNAME::add(CLASSNAME const& rhs) const SOURCENAME CLASSNAME::mul(CLASSNAME const& rhs) const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign( std::visit( [](auto const& lhs_blk, auto const& rhs_blk) result.storage()->assign(std::visit(
{ [](auto const& lhs_blk, auto const& rhs_blk) {
return (lhs_blk.first + rhs_blk.first).eval(); return (lhs_blk.first * rhs_blk.first).eval();
} },
, storage_->data storage_->data, rhs.storage_->data));
, rhs.storage_->data return result;
) }
);
return result;
}
SOURCENAME CLASSNAME::sub(CLASSNAME const& rhs) const SOURCENAME CLASSNAME::mul(TYPE s) const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign( std::visit( [](auto const& lhs_blk, auto const& rhs_blk) result.storage()->assign(
{ std::visit([s](auto const& lhs_blk) { return (lhs_blk.first * s).eval(); },
return (lhs_blk.first - rhs_blk.first).eval(); storage_->data));
} return result;
, storage_->data }
, rhs.storage_->data
)
);
return result;
}
SOURCENAME CLASSNAME::mul(CLASSNAME const& rhs) const SOURCENAME CLASSNAME::div(TYPE s) const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign( std::visit( [](auto const& lhs_blk, auto const& rhs_blk) result.storage()->assign(
{ std::visit([s](auto const& lhs_blk) { return (lhs_blk.first / s).eval(); },
return (lhs_blk.first * rhs_blk.first).eval(); storage_->data));
} return result;
, 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
)
);
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
)
);
return result;
}

View file

@ -14,14 +14,18 @@
namespace rotgen namespace rotgen
{ {
ioformat::ioformat( int p, int f ioformat::ioformat(int p,
, std::string const& cs, std::string const& rsp int f,
, std::string const& rp, std::string const& rs std::string const& cs,
, std::string const& mp, std::string const& ms std::string const& rsp,
, char fill std::string const& rp,
) std::string const& rs,
: storage_(std::make_unique<payload>(p,f,cs,rsp,rp,rs,mp,ms,fill)) std::string const& mp,
{} std::string const& ms,
char fill)
: storage_(std::make_unique<payload>(p, f, cs, rsp, rp, rs, mp, ms, fill))
{
}
ioformat::~ioformat() = default; ioformat::~ioformat() = default;
} }

View file

@ -12,7 +12,8 @@ namespace rotgen::detail
{ {
ROTGEN_EXPORT std::ostream& dynamic_info(std::ostream& os) ROTGEN_EXPORT std::ostream& dynamic_info(std::ostream& os)
{ {
if constexpr(rotgen::is_forcing_dynamic_status) return os << "[ROTGEN] - Fully Dynamic mode with:" << std::endl; if constexpr (rotgen::is_forcing_dynamic_status)
return os << "[ROTGEN] - Fully Dynamic mode with:" << std::endl;
else return os << "[ROTGEN] - Flexible mode with:" << std::endl; else return os << "[ROTGEN] - Flexible mode with:" << std::endl;
} }
} }

View file

@ -9,11 +9,11 @@
#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 TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl, SIZE, _col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
@ -23,11 +23,11 @@
#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 TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl, SIZE, _row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
@ -43,11 +43,11 @@
#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 TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_row) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _row)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl, SIZE, _col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
@ -57,11 +57,11 @@
#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 TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME,SIZE,_col) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(BASENAME, SIZE, _col)
#define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSSOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row) #define CLASSCONSTNAME ROTGEN_MATRIX_NAME(map_const_impl, SIZE, _row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME

View file

@ -13,19 +13,19 @@
namespace rotgen namespace rotgen
{ {
#define USE_CONST #define USE_CONST
#define CONST const #define CONST const
#define BASENAME map_const_impl #define BASENAME map_const_impl
#include "generate.cpp" #include "generate.cpp"
#undef BASENAME #undef BASENAME
#undef USE_CONST #undef USE_CONST
#undef CONST #undef CONST
#define CONST #define CONST
#define BASENAME map_impl #define BASENAME map_impl
#include "generate.cpp" #include "generate.cpp"
#undef BASENAME #undef BASENAME
#undef CONST #undef CONST
} }
#include "operators.cpp" #include "operators.cpp"

View file

@ -16,379 +16,465 @@
// Internal payload // Internal payload
//================================================================================================== //==================================================================================================
//================================================================================================== //==================================================================================================
// Constructors & Special Members // Constructors & Special Members
//================================================================================================== //==================================================================================================
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)
{} : 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, stride s)
: storage_(std::make_unique<payload>(ptr,r,c,payload::stride_type{s.outer(),s.inner()})) : storage_(std::make_unique<payload>(
{} ptr, r, c, payload::stride_type{s.outer(), s.inner()}))
{
}
CLASSNAME::CLASSNAME(CLASSNAME const& o) : storage_(std::make_unique<payload>(o.storage_->data)) CLASSNAME::CLASSNAME(CLASSNAME const& o)
{} : storage_(std::make_unique<payload>(o.storage_->data))
{
#if !defined(USE_CONST) }
CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
{
if (this != &o) storage_->data = o.storage_->data;
return *this;
}
CLASSNAME& CLASSNAME::operator=(CLASSNAME&& o)
{
if (this != &o) storage_->data = std::move(o.storage_->data);
return *this;
}
#endif
CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default;
CLASSNAME::~CLASSNAME() = default;
//==================================================================================================
// Matrix API
//==================================================================================================
rotgen::Index CLASSNAME::rows() const { return storage_->data.rows(); }
rotgen::Index CLASSNAME::cols() const { return storage_->data.cols(); }
rotgen::Index CLASSNAME::size() const { return storage_->data.size(); }
rotgen::Index CLASSNAME::innerStride() const { return storage_->data.innerStride(); }
rotgen::Index CLASSNAME::outerStride() const { return storage_->data.outerStride(); }
const TYPE* CLASSNAME::data() const { return storage_->data.data(); }
#if !defined(USE_CONST)
TYPE* CLASSNAME::data() { return storage_->data.data(); }
TYPE& CLASSNAME::operator()(Index i, Index j) { return storage_->data(i,j); }
TYPE& CLASSNAME::operator()(Index i) { return storage_->data.data()[i]; }
#endif
TYPE CLASSNAME::operator()(Index i, Index j) const { return storage_->data(i,j); }
TYPE CLASSNAME::operator()(Index i) const { return storage_->data.data()[i]; }
SOURCENAME CLASSNAME::normalized() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.normalized().eval());
return result;
}
SOURCENAME CLASSNAME::transpose() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.transpose().eval());
return result;
}
SOURCENAME CLASSNAME::conjugate() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.conjugate().eval());
return result;
}
SOURCENAME CLASSNAME::adjoint() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.adjoint().eval());
return result;
}
SOURCENAME CLASSNAME::cwiseAbs() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.cwiseAbs().eval());
return result;
}
SOURCENAME CLASSNAME::cwiseAbs2() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.cwiseAbs2().eval());
return result;
}
SOURCENAME CLASSNAME::cwiseInverse() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.cwiseInverse().eval());
return result;
}
SOURCENAME CLASSNAME::cwiseSqrt() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.cwiseSqrt().eval());
return result;
}
SOURCENAME CLASSNAME::cwiseMin(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data.cwiseMin(rhs.storage()->data).eval());
return result;
}
SOURCENAME CLASSNAME::cwiseMax(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data.cwiseMax(rhs.storage()->data).eval());
return result;
}
SOURCENAME CLASSNAME::cwiseProduct(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data.cwiseProduct(rhs.storage()->data).eval());
return result;
}
SOURCENAME CLASSNAME::cwiseQuotient(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data.cwiseQuotient(rhs.storage()->data).eval());
return result;
}
SOURCENAME CLASSNAME::cwiseMin(TYPE rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data.cwiseMin(rhs).eval());
return result;
}
SOURCENAME CLASSNAME::cwiseMax(TYPE rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data.cwiseMax(rhs).eval());
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() CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
{ {
storage_->data.normalize(); if (this != &o) storage_->data = o.storage_->data;
} return *this;
}
void CLASSNAME::transposeInPlace() CLASSNAME& CLASSNAME::operator=(CLASSNAME&& o)
{ {
storage_->data.transposeInPlace(); if (this != &o) storage_->data = std::move(o.storage_->data);
} return *this;
}
void CLASSNAME::adjointInPlace()
{
storage_->data.adjointInPlace();
}
#endif #endif
TYPE CLASSNAME::dot(CLASSNAME const& rhs) const CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default;
{
return storage_->data.reshaped().dot(rhs.storage()->data.reshaped());
}
TYPE CLASSNAME::dot(TRANSCLASSNAME const& rhs) const CLASSNAME::~CLASSNAME() = default;
{
return storage_->data.reshaped().dot(rhs.storage()->data.reshaped());
}
TYPE CLASSNAME::sum() const { return storage_->data.sum(); } //==================================================================================================
TYPE CLASSNAME::prod() const { return storage_->data.prod(); } // Matrix API
TYPE CLASSNAME::mean() const { return storage_->data.mean(); } //==================================================================================================
TYPE CLASSNAME::trace() const { return storage_->data.trace(); } rotgen::Index CLASSNAME::rows() const
{
return storage_->data.rows();
}
TYPE CLASSNAME::minCoeff() const { return storage_->data.minCoeff(); } rotgen::Index CLASSNAME::cols() const
TYPE CLASSNAME::maxCoeff() const { return storage_->data.maxCoeff(); } {
return storage_->data.cols();
}
TYPE CLASSNAME::minCoeff(Index* row, Index* col) const { return storage_->data.minCoeff(row, col); } rotgen::Index CLASSNAME::size() const
TYPE CLASSNAME::maxCoeff(Index* row, Index* col) const { return storage_->data.maxCoeff(row, col); } {
return storage_->data.size();
}
TYPE CLASSNAME::squaredNorm() const { return storage_->data.squaredNorm(); } rotgen::Index CLASSNAME::innerStride() const
TYPE CLASSNAME::norm() const { return storage_->data.norm(); } {
return storage_->data.innerStride();
}
TYPE CLASSNAME::lpNorm(int p) const rotgen::Index CLASSNAME::outerStride() const
{ {
if (p == 1) return storage_->data.lpNorm<1>(); return storage_->data.outerStride();
else if (p == 2) return storage_->data.lpNorm<2>(); }
else return storage_->data.lpNorm<Eigen::Infinity>();
}
#if !defined(USE_CONST) const TYPE* CLASSNAME::data() const
void CLASSNAME::setZero() {
{ return storage_->data.data();
storage_->data.setZero(); }
}
void CLASSNAME::setOnes() #if !defined(USE_CONST)
{ TYPE* CLASSNAME::data()
storage_->data.setOnes(); {
} return storage_->data.data();
}
void CLASSNAME::setIdentity() TYPE& CLASSNAME::operator()(Index i, Index j)
{ {
storage_->data.setIdentity(); return storage_->data(i, j);
} }
void CLASSNAME::setRandom() TYPE& CLASSNAME::operator()(Index i)
{ {
storage_->data.setRandom(); return storage_->data.data()[i];
} }
#endif
void CLASSNAME::setConstant(TYPE s) TYPE CLASSNAME::operator()(Index i, Index j) const
{ {
storage_->data.setConstant(s); return storage_->data(i, j);
} }
#endif
//================================================================================================== TYPE CLASSNAME::operator()(Index i) const
// Solvers {
//================================================================================================== return storage_->data.data()[i];
SOURCENAME CLASSNAME::qr_solve(CLASSNAME const& rhs) const }
{
SOURCENAME result;
result.storage()->assign(storage_->data.colPivHouseholderQr().solve(rhs.storage_->data).eval());
return result;
}
//================================================================================================== SOURCENAME CLASSNAME::normalized() const
// Operators {
//================================================================================================== SOURCENAME result;
ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os,CLASSNAME const& m) result.storage()->assign(storage_->data.normalized().eval());
{ return result;
return os << m.storage_->data; }
}
ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os,format<CLASSNAME> const& m) SOURCENAME CLASSNAME::transpose() const
{ {
return os << m.matrix_.storage_->data.format(m.format_.storage()->instance); SOURCENAME result;
} result.storage()->assign(storage_->data.transpose().eval());
return result;
}
ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs) SOURCENAME CLASSNAME::conjugate() const
{ {
return lhs.storage_->data == rhs.storage_->data; SOURCENAME result;
} result.storage()->assign(storage_->data.conjugate().eval());
return result;
}
ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs) SOURCENAME CLASSNAME::adjoint() const
{ {
return lhs.storage_->data != rhs.storage_->data; SOURCENAME result;
} result.storage()->assign(storage_->data.adjoint().eval());
return result;
}
SOURCENAME CLASSNAME::operator-() const SOURCENAME CLASSNAME::cwiseAbs() const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign(storage_->data); result.storage()->assign(storage_->data.cwiseAbs().eval());
return -result; return result;
} }
#if !defined(USE_CONST) SOURCENAME CLASSNAME::cwiseAbs2() const
CLASSNAME& CLASSNAME::operator+=(CLASSNAME const& rhs) {
{ SOURCENAME result;
storage_->data += rhs.storage_->data; result.storage()->assign(storage_->data.cwiseAbs2().eval());
return *this; return result;
} }
CLASSNAME& CLASSNAME::operator+=(CLASSCONSTNAME const& rhs) SOURCENAME CLASSNAME::cwiseInverse() const
{ {
storage_->data += rhs.storage()->data; SOURCENAME result;
return *this; result.storage()->assign(storage_->data.cwiseInverse().eval());
} return result;
}
CLASSNAME& CLASSNAME::operator-=(CLASSNAME const& rhs) SOURCENAME CLASSNAME::cwiseSqrt() const
{ {
storage_->data -= rhs.storage_->data; SOURCENAME result;
return *this; result.storage()->assign(storage_->data.cwiseSqrt().eval());
} return result;
}
CLASSNAME& CLASSNAME::operator-=(CLASSCONSTNAME const& rhs) SOURCENAME CLASSNAME::cwiseMin(CLASSNAME const& rhs) const
{ {
storage_->data -= rhs.storage()->data; SOURCENAME result;
return *this; result.storage()->assign(storage_->data.cwiseMin(rhs.storage()->data).eval());
} return result;
}
CLASSNAME& CLASSNAME::operator*=(CLASSNAME const& rhs) SOURCENAME CLASSNAME::cwiseMax(CLASSNAME const& rhs) const
{ {
storage_->data *= rhs.storage_->data; SOURCENAME result;
return *this; result.storage()->assign(storage_->data.cwiseMax(rhs.storage()->data).eval());
} return result;
}
CLASSNAME& CLASSNAME::operator*=(CLASSCONSTNAME const& rhs) SOURCENAME CLASSNAME::cwiseProduct(CLASSNAME const& rhs) const
{ {
storage_->data *= rhs.storage()->data; SOURCENAME result;
return *this; result.storage()->assign(
} storage_->data.cwiseProduct(rhs.storage()->data).eval());
return result;
}
CLASSNAME& CLASSNAME::operator*=(TYPE s) SOURCENAME CLASSNAME::cwiseQuotient(CLASSNAME const& rhs) const
{ {
storage_->data *= s; SOURCENAME result;
return *this; result.storage()->assign(
} storage_->data.cwiseQuotient(rhs.storage()->data).eval());
return result;
}
CLASSNAME& CLASSNAME::operator/=(TYPE s) SOURCENAME CLASSNAME::cwiseMin(TYPE rhs) const
{ {
storage_->data /= s; SOURCENAME result;
return *this; result.storage()->assign(storage_->data.cwiseMin(rhs).eval());
} return result;
#endif }
SOURCENAME CLASSNAME::add(CLASSNAME const& rhs) const SOURCENAME CLASSNAME::cwiseMax(TYPE rhs) const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign(storage_->data + rhs.storage_->data); result.storage()->assign(storage_->data.cwiseMax(rhs).eval());
return result; return result;
} }
SOURCENAME CLASSNAME::add(TRANSCLASSNAME const& rhs) const SOURCENAME CLASSNAME::inverse() const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign(storage_->data + rhs.storage()->data); result.storage()->assign(storage_->data.inverse().eval());
return result; return result;
} }
SOURCENAME CLASSNAME::sub(CLASSNAME const& rhs) const #if !defined(USE_CONST)
{ void CLASSNAME::normalize()
SOURCENAME result; {
result.storage()->assign(storage_->data - rhs.storage_->data); storage_->data.normalize();
return result; }
}
SOURCENAME CLASSNAME::sub(TRANSCLASSNAME const& rhs) const void CLASSNAME::transposeInPlace()
{ {
SOURCENAME result; storage_->data.transposeInPlace();
result.storage()->assign(storage_->data - rhs.storage()->data); }
return result;
}
SOURCENAME CLASSNAME::mul(CLASSNAME const& rhs) const void CLASSNAME::adjointInPlace()
{ {
SOURCENAME result; storage_->data.adjointInPlace();
result.storage()->assign(storage_->data * rhs.storage_->data); }
return result; #endif
}
SOURCENAME CLASSNAME::mul(TRANSCLASSNAME const& rhs) const TYPE CLASSNAME::dot(CLASSNAME const& rhs) const
{ {
SOURCENAME result; return storage_->data.reshaped().dot(rhs.storage()->data.reshaped());
result.storage()->assign(storage_->data * rhs.storage()->data); }
return result;
}
SOURCENAME CLASSNAME::mul(TYPE s) const TYPE CLASSNAME::dot(TRANSCLASSNAME const& rhs) const
{ {
SOURCENAME result; return storage_->data.reshaped().dot(rhs.storage()->data.reshaped());
result.storage()->assign(storage_->data * s); }
return result;
}
SOURCENAME CLASSNAME::div(TYPE s) const TYPE CLASSNAME::sum() const
{ {
SOURCENAME result; return storage_->data.sum();
result.storage()->assign(storage_->data / s); }
return result;
} TYPE CLASSNAME::prod() const
{
return storage_->data.prod();
}
TYPE CLASSNAME::mean() const
{
return storage_->data.mean();
}
TYPE CLASSNAME::trace() const
{
return storage_->data.trace();
}
TYPE CLASSNAME::minCoeff() const
{
return storage_->data.minCoeff();
}
TYPE CLASSNAME::maxCoeff() const
{
return storage_->data.maxCoeff();
}
TYPE CLASSNAME::minCoeff(Index* row, Index* col) const
{
return storage_->data.minCoeff(row, col);
}
TYPE CLASSNAME::maxCoeff(Index* row, Index* col) const
{
return storage_->data.maxCoeff(row, col);
}
TYPE CLASSNAME::squaredNorm() const
{
return storage_->data.squaredNorm();
}
TYPE CLASSNAME::norm() const
{
return storage_->data.norm();
}
TYPE CLASSNAME::lpNorm(int p) const
{
if (p == 1) return storage_->data.lpNorm<1>();
else if (p == 2) return storage_->data.lpNorm<2>();
else return storage_->data.lpNorm<Eigen::Infinity>();
}
#if !defined(USE_CONST)
void CLASSNAME::setZero()
{
storage_->data.setZero();
}
void CLASSNAME::setOnes()
{
storage_->data.setOnes();
}
void CLASSNAME::setIdentity()
{
storage_->data.setIdentity();
}
void CLASSNAME::setRandom()
{
storage_->data.setRandom();
}
void CLASSNAME::setConstant(TYPE s)
{
storage_->data.setConstant(s);
}
#endif
//==================================================================================================
// Solvers
//==================================================================================================
SOURCENAME CLASSNAME::qr_solve(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(
storage_->data.colPivHouseholderQr().solve(rhs.storage_->data).eval());
return result;
}
//==================================================================================================
// Operators
//==================================================================================================
ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os, CLASSNAME const& m)
{
return os << m.storage_->data;
}
ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os,
format<CLASSNAME> const& m)
{
return os << m.matrix_.storage_->data.format(m.format_.storage()->instance);
}
ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs)
{
return lhs.storage_->data == rhs.storage_->data;
}
ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs)
{
return lhs.storage_->data != rhs.storage_->data;
}
SOURCENAME CLASSNAME::operator-() const
{
SOURCENAME result;
result.storage()->assign(storage_->data);
return -result;
}
#if !defined(USE_CONST)
CLASSNAME& CLASSNAME::operator+=(CLASSNAME const& rhs)
{
storage_->data += rhs.storage_->data;
return *this;
}
CLASSNAME& CLASSNAME::operator+=(CLASSCONSTNAME const& rhs)
{
storage_->data += rhs.storage()->data;
return *this;
}
CLASSNAME& CLASSNAME::operator-=(CLASSNAME const& rhs)
{
storage_->data -= rhs.storage_->data;
return *this;
}
CLASSNAME& CLASSNAME::operator-=(CLASSCONSTNAME const& rhs)
{
storage_->data -= rhs.storage()->data;
return *this;
}
CLASSNAME& CLASSNAME::operator*=(CLASSNAME const& rhs)
{
storage_->data *= rhs.storage_->data;
return *this;
}
CLASSNAME& CLASSNAME::operator*=(CLASSCONSTNAME const& rhs)
{
storage_->data *= rhs.storage()->data;
return *this;
}
CLASSNAME& CLASSNAME::operator*=(TYPE s)
{
storage_->data *= s;
return *this;
}
CLASSNAME& CLASSNAME::operator/=(TYPE s)
{
storage_->data /= s;
return *this;
}
#endif
SOURCENAME CLASSNAME::add(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data + rhs.storage_->data);
return result;
}
SOURCENAME CLASSNAME::add(TRANSCLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data + rhs.storage()->data);
return result;
}
SOURCENAME CLASSNAME::sub(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data - rhs.storage_->data);
return result;
}
SOURCENAME CLASSNAME::sub(TRANSCLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data - rhs.storage()->data);
return result;
}
SOURCENAME CLASSNAME::mul(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data * rhs.storage_->data);
return result;
}
SOURCENAME CLASSNAME::mul(TRANSCLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data * rhs.storage()->data);
return result;
}
SOURCENAME CLASSNAME::mul(TYPE s) const
{
SOURCENAME result;
result.storage()->assign(storage_->data * s);
return result;
}
SOURCENAME CLASSNAME::div(TYPE s) const
{
SOURCENAME result;
result.storage()->assign(storage_->data / s);
return result;
}

View file

@ -10,28 +10,75 @@
#include <rotgen/detail/payload.hpp> #include <rotgen/detail/payload.hpp>
#include <Eigen/Dense> #include <Eigen/Dense>
#define ROTGEN_IMPL_OP(OP,FN,RET) \ #define ROTGEN_IMPL_OP(OP, FN, RET) \
RET operator OP(map_const_impl32_col const& a, map_impl32_col const& b ) { return FN(a, b); } \ RET operator OP(map_const_impl32_col const& a, map_impl32_col const& b) \
RET operator OP(map_const_impl32_col const& a, map_impl32_row const& b ) { return FN(a, b); } \ { \
RET operator OP(map_const_impl32_col const& a, map_const_impl32_row const& b ) { return FN(a, b); } \ return FN(a, b); \
RET operator OP(map_const_impl32_row const& a, map_impl32_row const& b ) { return FN(a, b); } \ } \
RET operator OP(map_const_impl32_row const& a, map_impl32_col const& b ) { return FN(a, b); } \ RET operator OP(map_const_impl32_col const& a, map_impl32_row const& b) \
RET operator OP(map_impl32_col const& a, map_impl32_row const& b ) { return FN(a, b); } \ { \
RET operator OP(map_const_impl64_col const& a, map_impl64_col const& b ) { return FN(a, b); } \ return FN(a, b); \
RET operator OP(map_const_impl64_col const& a, map_impl64_row const& b ) { return FN(a, b); } \ } \
RET operator OP(map_const_impl64_col const& a, map_const_impl64_row const& b ) { return FN(a, b); } \ RET operator OP(map_const_impl32_col const& a, \
RET operator OP(map_const_impl64_row const& a, map_impl64_row const& b ) { return FN(a, b); } \ map_const_impl32_row const& b) \
RET operator OP(map_const_impl64_row const& a, map_impl64_col const& b ) { return FN(a, b); } \ { \
RET operator OP(map_impl64_col const& a, map_impl64_row const& b ) { return FN(a, b); } \ return FN(a, b); \
} \
RET operator OP(map_const_impl32_row const& a, map_impl32_row const& b) \
{ \
return FN(a, b); \
} \
RET operator OP(map_const_impl32_row const& a, map_impl32_col const& b) \
{ \
return FN(a, b); \
} \
RET operator OP(map_impl32_col const& a, map_impl32_row const& b) \
{ \
return FN(a, b); \
} \
RET operator OP(map_const_impl64_col const& a, map_impl64_col const& b) \
{ \
return FN(a, b); \
} \
RET operator OP(map_const_impl64_col const& a, map_impl64_row const& b) \
{ \
return FN(a, b); \
} \
RET operator OP(map_const_impl64_col const& a, \
map_const_impl64_row const& b) \
{ \
return FN(a, b); \
} \
RET operator OP(map_const_impl64_row const& a, map_impl64_row const& b) \
{ \
return FN(a, b); \
} \
RET operator OP(map_const_impl64_row const& a, map_impl64_col const& b) \
{ \
return FN(a, b); \
} \
RET operator OP(map_impl64_col const& a, map_impl64_row const& b) \
{ \
return FN(a, b); \
}
/**/ /**/
namespace rotgen namespace rotgen
{ {
namespace namespace
{ {
bool equal(auto const& a, auto const& b) { return a.storage()->data == b.storage()->data; } bool equal(auto const& a, auto const& b)
bool not_equal(auto const& a, auto const& b) { return a.storage()->data != b.storage()->data; } {
return a.storage()->data == b.storage()->data;
}
bool not_equal(auto const& a, auto const& b)
{
return a.storage()->data != b.storage()->data;
}
} }
ROTGEN_IMPL_OP(==, equal , bool);
ROTGEN_IMPL_OP(==, equal, bool);
ROTGEN_IMPL_OP(!=, not_equal, bool); ROTGEN_IMPL_OP(!=, not_equal, bool);
} }

View file

@ -13,47 +13,47 @@
namespace rotgen namespace rotgen
{ {
#define SIZE 64 #define SIZE 64
#define TYPE double #define TYPE double
#define STORAGE_ORDER Eigen::ColMajor #define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#undef STORAGE_ORDER #undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor #define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#undef STORAGE_ORDER #undef STORAGE_ORDER
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
#define SIZE 32 #define SIZE 32
#define TYPE float #define TYPE float
#define STORAGE_ORDER Eigen::ColMajor #define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#undef STORAGE_ORDER #undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor #define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define TRANSCLASSNAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef TRANSCLASSNAME #undef TRANSCLASSNAME
#undef STORAGE_ORDER #undef STORAGE_ORDER
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
} }

View file

@ -15,31 +15,35 @@
//================================================================================================== //==================================================================================================
// Constructors & Special Members // Constructors & Special Members
//================================================================================================== //==================================================================================================
CLASSNAME::CLASSNAME() : storage_(std::make_unique<payload>(0,0)) {} CLASSNAME::CLASSNAME() : storage_(std::make_unique<payload>(0, 0)) {}
CLASSNAME::CLASSNAME(std::size_t r, std::size_t c) : storage_(std::make_unique<payload>(r,c)) {}
CLASSNAME::CLASSNAME(std::initializer_list<std::initializer_list<TYPE>> init) CLASSNAME::CLASSNAME(std::size_t r, std::size_t c)
: storage_(std::make_unique<payload>(init)) : storage_(std::make_unique<payload>(r, c))
{}
CLASSNAME::CLASSNAME(std::size_t r, std::size_t c,std::initializer_list<TYPE> init)
: CLASSNAME(r,c)
{ {
auto first = init.begin();
for(std::size_t i=0; i < init.size(); i++)
(*this)(i) = first[i];
} }
CLASSNAME::CLASSNAME(CLASSNAME const& o) CLASSNAME::CLASSNAME(std::initializer_list<std::initializer_list<TYPE>> init)
: CLASSNAME(o.rows(),o.cols()) : storage_(std::make_unique<payload>(init))
{
}
CLASSNAME::CLASSNAME(std::size_t r,
std::size_t c,
std::initializer_list<TYPE> init)
: CLASSNAME(r, c)
{
auto first = init.begin();
for (std::size_t i = 0; i < init.size(); i++) (*this)(i) = first[i];
}
CLASSNAME::CLASSNAME(CLASSNAME const& o) : CLASSNAME(o.rows(), o.cols())
{ {
storage_->data = o.storage_->data; storage_->data = o.storage_->data;
} }
CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default; CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default;
CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
{ {
if (this != &o) storage_->data = o.storage_->data; if (this != &o) storage_->data = o.storage_->data;
return *this; return *this;
@ -47,14 +51,25 @@ CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
CLASSNAME& CLASSNAME::operator=(CLASSNAME&&) noexcept = default; CLASSNAME& CLASSNAME::operator=(CLASSNAME&&) noexcept = default;
CLASSNAME::~CLASSNAME() = default; CLASSNAME::~CLASSNAME() = default;
//================================================================================================== //==================================================================================================
// Matrix API // Matrix API
//================================================================================================== //==================================================================================================
rotgen::Index CLASSNAME::rows() const { return storage_->data.rows(); } rotgen::Index CLASSNAME::rows() const
rotgen::Index CLASSNAME::cols() const { return storage_->data.cols(); } {
rotgen::Index CLASSNAME::size() const { return storage_->data.size(); } return storage_->data.rows();
}
rotgen::Index CLASSNAME::cols() const
{
return storage_->data.cols();
}
rotgen::Index CLASSNAME::size() const
{
return storage_->data.size();
}
void CLASSNAME::resize(std::size_t new_rows, std::size_t new_cols) void CLASSNAME::resize(std::size_t new_rows, std::size_t new_cols)
{ {
@ -66,14 +81,35 @@ void CLASSNAME::conservativeResize(std::size_t new_rows, std::size_t new_cols)
storage_->data.conservativeResize(new_rows, new_cols); storage_->data.conservativeResize(new_rows, new_cols);
} }
TYPE& CLASSNAME::operator()(std::size_t i, std::size_t j) { return storage_->data(i,j); } TYPE& CLASSNAME::operator()(std::size_t i, std::size_t j)
TYPE const& CLASSNAME::operator()(std::size_t i, std::size_t j) const { return storage_->data(i,j); } {
return storage_->data(i, j);
}
TYPE& CLASSNAME::operator()(std::size_t index) { return storage_->data(index); } TYPE const& CLASSNAME::operator()(std::size_t i, std::size_t j) const
TYPE const& CLASSNAME::operator()(std::size_t index) const { return storage_->data(index); } {
return storage_->data(i, j);
}
const TYPE* CLASSNAME::data() const { return storage_->data.data(); } TYPE& CLASSNAME::operator()(std::size_t index)
TYPE* CLASSNAME::data() { return storage_->data.data(); } {
return storage_->data(index);
}
TYPE const& CLASSNAME::operator()(std::size_t index) const
{
return storage_->data(index);
}
const TYPE* CLASSNAME::data() const
{
return storage_->data.data();
}
TYPE* CLASSNAME::data()
{
return storage_->data.data();
}
CLASSNAME CLASSNAME::normalized() const CLASSNAME CLASSNAME::normalized() const
{ {
@ -146,36 +182,73 @@ CLASSNAME CLASSNAME::cwiseSqrt() const
return result; return result;
} }
TYPE CLASSNAME::sum() const { return storage_->data.sum(); } TYPE CLASSNAME::sum() const
TYPE CLASSNAME::prod() const { return storage_->data.prod(); } {
TYPE CLASSNAME::mean() const { return storage_->data.mean(); } return storage_->data.sum();
TYPE CLASSNAME::trace() const { return storage_->data.trace(); } }
TYPE CLASSNAME::minCoeff() const { return storage_->data.minCoeff(); } TYPE CLASSNAME::prod() const
TYPE CLASSNAME::maxCoeff() const { return storage_->data.maxCoeff(); } {
return storage_->data.prod();
}
TYPE CLASSNAME::minCoeff(Index* row, Index* col) const { return storage_->data.minCoeff(row, col); } TYPE CLASSNAME::mean() const
TYPE CLASSNAME::maxCoeff(Index* row, Index* col) const { return storage_->data.maxCoeff(row, col); } {
return storage_->data.mean();
}
TYPE CLASSNAME::squaredNorm() const { return storage_->data.squaredNorm(); } TYPE CLASSNAME::trace() const
TYPE CLASSNAME::norm() const { return storage_->data.norm(); } {
return storage_->data.trace();
}
TYPE CLASSNAME::minCoeff() const
{
return storage_->data.minCoeff();
}
TYPE CLASSNAME::maxCoeff() const
{
return storage_->data.maxCoeff();
}
TYPE CLASSNAME::minCoeff(Index* row, Index* col) const
{
return storage_->data.minCoeff(row, col);
}
TYPE CLASSNAME::maxCoeff(Index* row, Index* col) const
{
return storage_->data.maxCoeff(row, col);
}
TYPE CLASSNAME::squaredNorm() const
{
return storage_->data.squaredNorm();
}
TYPE CLASSNAME::norm() const
{
return storage_->data.norm();
}
TYPE CLASSNAME::lp_norm(int p) const TYPE CLASSNAME::lp_norm(int p) const
{ {
if (p == 1) return storage_->data.lpNorm<1>(); if (p == 1) return storage_->data.lpNorm<1>();
else if (p == 2) return storage_->data.lpNorm<2>(); else if (p == 2) return storage_->data.lpNorm<2>();
else return storage_->data.lpNorm<Eigen::Infinity>(); else return storage_->data.lpNorm<Eigen::Infinity>();
} }
//================================================================================================== //==================================================================================================
// Operators // Operators
//================================================================================================== //==================================================================================================
ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os,CLASSNAME const& m) ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os, CLASSNAME const& m)
{ {
return os << m.storage_->data; return os << m.storage_->data;
} }
ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os,format<CLASSNAME> const& m) ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os,
format<CLASSNAME> const& m)
{ {
return os << m.matrix_.storage_->data.format(m.format_.storage()->instance); return os << m.matrix_.storage_->data.format(m.format_.storage()->instance);
} }
@ -248,20 +321,23 @@ CLASSNAME CLASSNAME::Zero(std::size_t rows, std::size_t cols)
CLASSNAME CLASSNAME::Constant(std::size_t rows, std::size_t cols, TYPE value) CLASSNAME CLASSNAME::Constant(std::size_t rows, std::size_t cols, TYPE value)
{ {
CLASSNAME m; CLASSNAME m;
m.storage_ = std::make_unique<payload>(payload::data_type::Constant(rows, cols, value)); m.storage_ =
std::make_unique<payload>(payload::data_type::Constant(rows, cols, value));
return m; return m;
} }
CLASSNAME CLASSNAME::Random(std::size_t rows, std::size_t cols) CLASSNAME CLASSNAME::Random(std::size_t rows, std::size_t cols)
{ {
CLASSNAME m; CLASSNAME m;
m.storage_ = std::make_unique<payload>(payload::data_type::Random(rows, cols)); m.storage_ =
std::make_unique<payload>(payload::data_type::Random(rows, cols));
return m; return m;
} }
CLASSNAME CLASSNAME::Identity(std::size_t rows, std::size_t cols) CLASSNAME CLASSNAME::Identity(std::size_t rows, std::size_t cols)
{ {
CLASSNAME m; CLASSNAME m;
m.storage_ = std::make_unique<payload>(payload::data_type::Identity(rows, cols)); m.storage_ =
std::make_unique<payload>(payload::data_type::Identity(rows, cols));
return m; return m;
} }

View file

@ -15,47 +15,47 @@
namespace rotgen namespace rotgen
{ {
#define SIZE 64 #define SIZE 64
#define TYPE double #define TYPE double
#define STORAGE_ORDER Eigen::ColMajor #define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl, SIZE, _col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#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(svd_impl,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl, SIZE, _row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#undef STORAGE_ORDER #undef STORAGE_ORDER
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
#define SIZE 32 #define SIZE 32
#define TYPE float #define TYPE float
#define STORAGE_ORDER Eigen::ColMajor #define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl,SIZE,_col) #define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl, SIZE, _col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _col)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#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(svd_impl,SIZE,_row) #define CLASSNAME ROTGEN_MATRIX_NAME(svd_impl, SIZE, _row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row) #define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl, SIZE, _row)
#include "model.cpp" #include "model.cpp"
#undef CLASSNAME #undef CLASSNAME
#undef SOURCENAME #undef SOURCENAME
#undef STORAGE_ORDER #undef STORAGE_ORDER
#undef SIZE #undef SIZE
#undef TYPE #undef TYPE
} }

View file

@ -17,28 +17,32 @@
//================================================================================================== //==================================================================================================
struct CLASSNAME::payload struct CLASSNAME::payload
{ {
using matrix_type = Eigen::Matrix<TYPE,Eigen::Dynamic,Eigen::Dynamic,STORAGE_ORDER>; using matrix_type =
Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic, STORAGE_ORDER>;
Eigen::JacobiSVD<matrix_type> data; Eigen::JacobiSVD<matrix_type> data;
payload(SOURCENAME const& src, int options) : data(src.storage()->data,options) {} payload(SOURCENAME const& src, int options)
: data(src.storage()->data, options)
{
}
}; };
//================================================================================================== //==================================================================================================
// Constructors & Special Members // Constructors & Special Members
//================================================================================================== //==================================================================================================
CLASSNAME::CLASSNAME(SOURCENAME const& m, int options) CLASSNAME::CLASSNAME(SOURCENAME const& m, int options)
: storage_(std::make_unique<payload>(m,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(CLASSNAME const& o)
: storage_(std::make_unique<payload>(*o.storage_))
{
}
CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o) CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default;
CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
{ {
if (this != &o) storage_->data = o.storage_->data; if (this != &o) storage_->data = o.storage_->data;
return *this; return *this;
@ -52,60 +56,64 @@ CLASSNAME& CLASSNAME::operator=(CLASSNAME&& o) noexcept
CLASSNAME::~CLASSNAME() = default; CLASSNAME::~CLASSNAME() = default;
int CLASSNAME::rank() const { return storage_->data.rank(); } int CLASSNAME::rank() const
{
return storage_->data.rank();
}
SOURCENAME CLASSNAME::U() const SOURCENAME CLASSNAME::U() const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign(storage_->data.matrixU()); result.storage()->assign(storage_->data.matrixU());
return result; return result;
} }
SOURCENAME CLASSNAME::U(int r) const SOURCENAME CLASSNAME::U(int r) const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign( storage_->data.matrixU().leftCols(r) ); result.storage()->assign(storage_->data.matrixU().leftCols(r));
return result; return result;
} }
SOURCENAME CLASSNAME::singular_values() const SOURCENAME CLASSNAME::singular_values() const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign(storage_->data.singularValues()); result.storage()->assign(storage_->data.singularValues());
return result; return result;
} }
SOURCENAME CLASSNAME::singular_values(int r) const SOURCENAME CLASSNAME::singular_values(int r) const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign(storage_->data.singularValues().head(r)); result.storage()->assign(storage_->data.singularValues().head(r));
return result; return result;
} }
SOURCENAME CLASSNAME::D() const SOURCENAME CLASSNAME::D() const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign(storage_->data.singularValues().asDiagonal()); result.storage()->assign(storage_->data.singularValues().asDiagonal());
return result; return result;
} }
SOURCENAME CLASSNAME::D(int r) const SOURCENAME CLASSNAME::D(int r) const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign(storage_->data.singularValues().head(r).asDiagonal()); result.storage()->assign(
storage_->data.singularValues().head(r).asDiagonal());
return result; return result;
} }
SOURCENAME CLASSNAME::V() const SOURCENAME CLASSNAME::V() const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign(storage_->data.matrixV()); result.storage()->assign(storage_->data.matrixV());
return result; return result;
} }
SOURCENAME CLASSNAME::V(int r) const SOURCENAME CLASSNAME::V(int r) const
{ {
SOURCENAME result; SOURCENAME result;
result.storage()->assign( storage_->data.matrixV().leftCols(r) ); result.storage()->assign(storage_->data.matrixV().leftCols(r));
return result; return result;
} }

View file

@ -8,40 +8,46 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("noalias behavior - dynamicallly sized", rotgen::tests::types) TTS_CASE_TPL("noalias behavior - dynamicallly sized",
<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{{1,2},{3,4}}; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> a{{1, 2},
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> ref{{7,10},{15,22}}; {3, 4}};
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> b(2,2),c(2,2),d(2,2); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> ref{{7, 10},
{15, 22}};
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> b(2, 2),
c(2, 2), d(2, 2);
rotgen::noalias(b) = a * a; rotgen::noalias(b) = a * a;
TTS_EQUAL(b, ref); TTS_EQUAL(b, ref);
auto e = rotgen::extract(c,0,0,2,2); auto e = rotgen::extract(c, 0, 0, 2, 2);
rotgen::noalias(e) = a * a; rotgen::noalias(e) = a * a;
TTS_EQUAL(c, ref); TTS_EQUAL(c, ref);
rotgen::map<rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>> m(d.data(),2,2); rotgen::map<rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>> m(
d.data(), 2, 2);
rotgen::noalias(m) = a * a; rotgen::noalias(m) = a * a;
TTS_EQUAL(m, ref); TTS_EQUAL(m, ref);
}; };
TTS_CASE_TPL("noalias behavior - statically sized", rotgen::tests::types) TTS_CASE_TPL("noalias behavior - statically sized",
<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,2,2,O::value> a{{1,2},{3,4}}; rotgen::matrix<T, 2, 2, O::value> a{{1, 2}, {3, 4}};
rotgen::matrix<T,2,2,O::value> ref{{7,10},{15,22}}; rotgen::matrix<T, 2, 2, O::value> ref{{7, 10}, {15, 22}};
rotgen::matrix<T,2,2,O::value> b,c,d; rotgen::matrix<T, 2, 2, O::value> b, c, d;
rotgen::noalias(b) = a * a; rotgen::noalias(b) = a * a;
TTS_EQUAL(b, ref); TTS_EQUAL(b, ref);
auto e = rotgen::extract(c,0,0,2,2); auto e = rotgen::extract(c, 0, 0, 2, 2);
rotgen::noalias(e) = a * a; rotgen::noalias(e) = a * a;
TTS_EQUAL(c, ref); TTS_EQUAL(c, ref);
rotgen::map<rotgen::matrix<T,2,2,O::value>> m(d.data()); rotgen::map<rotgen::matrix<T, 2, 2, O::value>> m(d.data());
rotgen::noalias(m) = a * a; rotgen::noalias(m) = a * a;
TTS_EQUAL(m, ref); TTS_EQUAL(m, ref);
}; };

View file

@ -8,63 +8,67 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Chains of extraction", rotgen::tests::types) TTS_CASE_TPL("Chains of extraction",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
constexpr int N = 8; constexpr int N = 8;
auto a = rotgen::matrix<T,N,N,O::value>::Random(); auto a = rotgen::matrix<T, N, N, O::value>::Random();
auto b = topLeftCorner(a,5,5); auto b = topLeftCorner(a, 5, 5);
TTS_EQUAL(b.startRow(), 0); TTS_EQUAL(b.startRow(), 0);
TTS_EQUAL(b.startCol(), 0); TTS_EQUAL(b.startCol(), 0);
setConstant(b,-7); setConstant(b, -7);
for(rotgen::Index r=0;r<5;r++) for (rotgen::Index r = 0; r < 5; r++)
for(rotgen::Index c=0;c<5;c++) for (rotgen::Index c = 0; c < 5; c++) TTS_EQUAL(a(r, c), -7);
TTS_EQUAL(a(r,c), -7);
auto bb = bottomRightCorner(b,3,3); auto bb = bottomRightCorner(b, 3, 3);
TTS_EQUAL(bb.startRow(), 2); TTS_EQUAL(bb.startRow(), 2);
TTS_EQUAL(bb.startCol(), 2); TTS_EQUAL(bb.startCol(), 2);
setConstant(bb,42); setConstant(bb, 42);
for(rotgen::Index r=2;r<5;r++) for (rotgen::Index r = 2; r < 5; r++)
for(rotgen::Index c=2;c<5;c++) for (rotgen::Index c = 2; c < 5; c++) TTS_EQUAL(a(r, c), 42);
TTS_EQUAL(a(r,c), 42);
auto bbb = row(bb,1); auto bbb = row(bb, 1);
TTS_EQUAL(bbb.startRow(), 1); TTS_EQUAL(bbb.startRow(), 1);
TTS_EQUAL(bbb.startCol(), 0); TTS_EQUAL(bbb.startCol(), 0);
setConstant(bbb,99.5); setConstant(bbb, 99.5);
for(rotgen::Index c=3;c<5;c++) for (rotgen::Index c = 3; c < 5; c++) TTS_EQUAL(a(3, c), 99.5);
TTS_EQUAL(a(3,c), 99.5);
auto bbbb = col(bbb,1); auto bbbb = col(bbb, 1);
TTS_EQUAL(bbbb.startRow(), 0); TTS_EQUAL(bbbb.startRow(), 0);
TTS_EQUAL(bbbb.startCol(), 1); TTS_EQUAL(bbbb.startCol(), 1);
setConstant(bbbb,0.125); setConstant(bbbb, 0.125);
TTS_EQUAL(a(3,3), 0.125); TTS_EQUAL(a(3, 3), 0.125);
}; };
auto ref_extract ( rotgen::ref<rotgen::matrix<float> > m) { return rotgen::extract(m,0,0,3,4); } auto ref_extract(rotgen::ref<rotgen::matrix<float>> m)
auto ref_cextract( rotgen::ref<const rotgen::matrix<float> > m) { return rotgen::extract(m,3,4,4,3); } {
return rotgen::extract(m, 0, 0, 3, 4);
}
auto ref_cextract(rotgen::ref<rotgen::matrix<float> const> m)
{
return rotgen::extract(m, 3, 4, 4, 3);
}
TTS_CASE("Extraction of ref/ref const") TTS_CASE("Extraction of ref/ref const")
{ {
auto m = rotgen::setRandom<rotgen::matrix<float,7,7>>(); auto m = rotgen::setRandom<rotgen::matrix<float, 7, 7>>();
auto extracted = ref_extract(m); auto extracted = ref_extract(m);
extracted = rotgen::setOnes<rotgen::matrix<float,3,4>>(); extracted = rotgen::setOnes<rotgen::matrix<float, 3, 4>>();
for(rotgen::Index r=0;r<3;r++) for (rotgen::Index r = 0; r < 3; r++)
for(rotgen::Index c=0;c<4;c++) for (rotgen::Index c = 0; c < 4; c++) TTS_EQUAL(m(r, c), 1.f);
TTS_EQUAL(m(r,c), 1.f);
auto sliced = ref_cextract(m); auto sliced = ref_cextract(m);
rotgen::extract(m,3,4,4,3) = rotgen::setConstant<rotgen::matrix<float,4,3>>(5); rotgen::extract(m, 3, 4, 4, 3) =
for(rotgen::Index r=0;r<4;r++) rotgen::setConstant<rotgen::matrix<float, 4, 3>>(5);
for(rotgen::Index c=0;c<3;c++) for (rotgen::Index r = 0; r < 4; r++)
TTS_EQUAL(sliced(r,c), 5.f); for (rotgen::Index c = 0; c < 3; c++) TTS_EQUAL(sliced(r, c), 5.f);
}; };

View file

@ -9,76 +9,81 @@
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
#include <sstream> #include <sstream>
TTS_CASE_TPL("I/O for matrix", rotgen::tests::types) TTS_CASE_TPL("I/O for matrix", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> x({ {1,2} , {3,4} }); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> x(
{{1, 2}, {3, 4}});
std::ostringstream os; std::ostringstream os;
os << x; os << x;
TTS_EQUAL(os.str(), std::string{"1 2\n3 4"}); TTS_EQUAL(os.str(), std::string{"1 2\n3 4"});
}; };
TTS_CASE_TPL("I/O for block", rotgen::tests::types) TTS_CASE_TPL("I/O for block", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base({ {1,2} , {3,4} }); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> base(
{{1, 2}, {3, 4}});
auto x = rotgen::extract(base,0,0,2,2); auto x = rotgen::extract(base, 0, 0, 2, 2);
std::ostringstream os; std::ostringstream os;
os << x; os << x;
TTS_EQUAL(os.str(), std::string{"1 2\n3 4"}); TTS_EQUAL(os.str(), std::string{"1 2\n3 4"});
}; };
TTS_CASE_TPL("I/O for map test", rotgen::tests::types) TTS_CASE_TPL("I/O for map test", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
using base = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>; using base = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
T data[] = {1,2,3,4}; T data[] = {1, 2, 3, 4};
rotgen::map<base> x(data,2,2); rotgen::map<base> x(data, 2, 2);
std::ostringstream os; std::ostringstream os;
os << x; os << x;
if constexpr(O::value) TTS_EQUAL(os.str(), std::string{"1 2\n3 4"}); if constexpr (O::value) TTS_EQUAL(os.str(), std::string{"1 2\n3 4"});
else TTS_EQUAL(os.str(), std::string{"1 3\n2 4"}); else TTS_EQUAL(os.str(), std::string{"1 3\n2 4"});
}; };
TTS_CASE_TPL("I/O using format", rotgen::tests::types) TTS_CASE_TPL("I/O using format", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
rotgen::ioformat io(rotgen::StreamPrecision, 0, ", ", ";\n", "<", ">", "[", "]"); rotgen::ioformat io(rotgen::StreamPrecision, 0, ", ", ";\n", "<", ">", "[",
"]");
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> x({ {1,2} , {3,4} }); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> x(
{{1, 2}, {3, 4}});
{ {
std::ostringstream os; std::ostringstream os;
os << rotgen::format(x,io); os << rotgen::format(x, io);
TTS_EQUAL(os.str(), std::string{"[<1, 2>;\n <3, 4>]"}); TTS_EQUAL(os.str(), std::string{"[<1, 2>;\n <3, 4>]"});
} }
rotgen::map<rotgen::matrix<T,2,2,O::value>> m{x.data()}; rotgen::map<rotgen::matrix<T, 2, 2, O::value>> m{x.data()};
{ {
std::ostringstream os; std::ostringstream os;
os << rotgen::format(m,io); os << rotgen::format(m, io);
TTS_EQUAL(os.str(), std::string{"[<1, 2>;\n <3, 4>]"}); TTS_EQUAL(os.str(), std::string{"[<1, 2>;\n <3, 4>]"});
} }
auto b = rotgen::extract(x,0,0,2,2); auto b = rotgen::extract(x, 0, 0, 2, 2);
{ {
std::ostringstream os; std::ostringstream os;
os << rotgen::format(b,io); os << rotgen::format(b, io);
TTS_EQUAL(os.str(), std::string{"[<1, 2>;\n <3, 4>]"}); TTS_EQUAL(os.str(), std::string{"[<1, 2>;\n <3, 4>]"});
} }
auto printer = [&](rotgen::ref<const rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>> r) auto printer =
{ [&](rotgen::ref<rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic,
std::ostringstream st; O::value> const> r) {
st << rotgen::format(r,io); std::ostringstream st;
return st.str(); st << rotgen::format(r, io);
}; return st.str();
};
TTS_EQUAL(printer(x), std::string{"[<1, 2>;\n <3, 4>]"}); TTS_EQUAL(printer(x), std::string{"[<1, 2>;\n <3, 4>]"});
TTS_EQUAL(printer(m), std::string{"[<1, 2>;\n <3, 4>]"}); TTS_EQUAL(printer(m), std::string{"[<1, 2>;\n <3, 4>]"});

View file

@ -9,75 +9,94 @@
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
#include <iostream> #include <iostream>
TTS_CASE_TPL("outer_stride<0> interactions", rotgen::tests::types) TTS_CASE_TPL("outer_stride<0> interactions",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
T contiguous[] = {1,2,3, 4,5,6, 7,8,9, 10,11,12}; T contiguous[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
rotgen::map<mat_t, 0, rotgen::outer_stride<0>> m(&contiguous[0], 4, 3); rotgen::map<mat_t, 0, rotgen::outer_stride<0>> m(&contiguous[0], 4, 3);
TTS_EQUAL(m.innerStride(), 1); TTS_EQUAL(m.innerStride(), 1);
TTS_EQUAL(m.outerStride(), O::value == rotgen::ColMajor ? 4 : 3); TTS_EQUAL(m.outerStride(), O::value == rotgen::ColMajor ? 4 : 3);
if constexpr(O::value == rotgen::ColMajor) if constexpr (O::value == rotgen::ColMajor)
{ {
T padded[] = {1,2,3,4, 99, 5,6,7,8, 99,9,10,11,12}; 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<5>> sp(&padded[0], 4, 3);
TTS_EQUAL(sp.innerStride(), 1); TTS_EQUAL(sp.innerStride(), 1);
TTS_EQUAL(sp.outerStride(), 5); TTS_EQUAL(sp.outerStride(), 5);
rotgen::map<mat_t, 0, rotgen::outer_stride<>> dp(&padded[0], 4, 3,rotgen::outer_stride(5)); rotgen::map<mat_t, 0, rotgen::outer_stride<>> dp(&padded[0], 4, 3,
rotgen::outer_stride(5));
TTS_EQUAL(dp.innerStride(), 1); TTS_EQUAL(dp.innerStride(), 1);
TTS_EQUAL(dp.outerStride(), 5); TTS_EQUAL(dp.outerStride(), 5);
TTS_EQUAL(m , sp); TTS_EQUAL(m, sp);
TTS_EQUAL(m , dp); TTS_EQUAL(m, dp);
TTS_EQUAL(dp, sp); TTS_EQUAL(dp, sp);
} }
else else
{ {
T padded[] = {1,2,3, 99, 4,5,6, 99, 7,8,9, 99, 10,11,12}; 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<4>> sp(&padded[0], 4, 3);
TTS_EQUAL(sp.innerStride(), 1); TTS_EQUAL(sp.innerStride(), 1);
TTS_EQUAL(sp.outerStride(), 4); TTS_EQUAL(sp.outerStride(), 4);
rotgen::map<mat_t, 0, rotgen::outer_stride<>> dp(&padded[0], 4, 3,rotgen::outer_stride(4)); rotgen::map<mat_t, 0, rotgen::outer_stride<>> dp(&padded[0], 4, 3,
rotgen::outer_stride(4));
TTS_EQUAL(dp.innerStride(), 1); TTS_EQUAL(dp.innerStride(), 1);
TTS_EQUAL(dp.outerStride(), 4); TTS_EQUAL(dp.outerStride(), 4);
TTS_EQUAL(m , sp); TTS_EQUAL(m, sp);
TTS_EQUAL(m , dp); TTS_EQUAL(m, dp);
TTS_EQUAL(dp, sp); TTS_EQUAL(dp, sp);
} }
}; };
void process_ref(rotgen::ref<const rotgen::matrix<float>> ) {} void process_ref(rotgen::ref<rotgen::matrix<float> const>) {}
void process_ref(rotgen::ref<const rotgen::matrix<double>>) {}
void process_ref(rotgen::ref<const rotgen::matrix<float , rotgen::Dynamic, rotgen::Dynamic, rotgen::RowMajor>>) {}
void process_ref(rotgen::ref<const rotgen::matrix<double, rotgen::Dynamic, rotgen::Dynamic, rotgen::RowMajor>>) {}
TTS_CASE_TPL("Extraction of outer_stride<?> blocks", rotgen::tests::types) void process_ref(rotgen::ref<rotgen::matrix<double> const>) {}
<typename T, typename O>( tts::type< tts::types<T,O>> )
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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
if constexpr(O::value == rotgen::ColMajor) if constexpr (O::value == rotgen::ColMajor)
{ {
T padded[] = {1,2,3,4, 99, 5,6,7,8, 99,9,10,11,12}; 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<5>> sp(&padded[0], 4, 3);
rotgen::map<mat_t, 0, rotgen::outer_stride<>> dp(&padded[0], 4, 3,rotgen::outer_stride(5)); 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(sp, { process_ref(extract(sp, 0, 0, 3, 2)); });
TTS_EXPECT_COMPILES(dp, { process_ref(extract(dp,0, 0, 3, 2)); } ); TTS_EXPECT_COMPILES(dp, { process_ref(extract(dp, 0, 0, 3, 2)); });
} }
else else
{ {
T padded[] = {1,2,3, 99, 4,5,6, 99, 7,8,9, 99, 10,11,12}; 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<4>> sp(&padded[0], 4, 3);
rotgen::map<mat_t, 0, rotgen::outer_stride<>> dp(&padded[0], 4, 3,rotgen::outer_stride(4)); 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(sp, { process_ref(extract(sp, 0, 0, 3, 2)); });
TTS_EXPECT_COMPILES(dp, { process_ref(extract(dp,0, 0, 3, 2)); } ); TTS_EXPECT_COMPILES(dp, { process_ref(extract(dp, 0, 0, 3, 2)); });
} }
}; };

View file

@ -8,7 +8,9 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
template<int size = rotgen::Dynamic, typename Scalar = float, int maxSize = size> template<int size = rotgen::Dynamic,
typename Scalar = float,
int maxSize = size>
using column = rotgen::matrix<Scalar, size, 1, rotgen::ColMajor, maxSize, 1>; using column = rotgen::matrix<Scalar, size, 1, rotgen::ColMajor, maxSize, 1>;
template<int size = rotgen::Dynamic, typename Scalar = float> template<int size = rotgen::Dynamic, typename Scalar = float>
@ -17,22 +19,27 @@ using column_ref = rotgen::ref<column<size, Scalar>>;
template<int size = rotgen::Dynamic, typename Scalar = float> template<int size = rotgen::Dynamic, typename Scalar = float>
using const_column_ref = rotgen::ref<column<size, Scalar> const>; using const_column_ref = rotgen::ref<column<size, Scalar> const>;
template<int N> void process(column_ref<N> v)
template<int N>
void process( column_ref<N> v )
{ {
v(0) = rotgen::sum(v); v(0) = rotgen::sum(v);
} }
auto process( column_ref<> v ) auto process(column_ref<> v)
{ {
auto sz = v.size(); auto sz = v.size();
switch(sz) switch (sz)
{ {
case 1 : process<1>(v); break; case 1:
case 2 : process<2>(v); break; process<1>(v);
case 3 : process<3>(v); break; break;
default: break; case 2:
process<2>(v);
break;
case 3:
process<3>(v);
break;
default:
break;
} }
return sz; return sz;
@ -40,9 +47,9 @@ auto process( column_ref<> v )
TTS_CASE("Reference of reference check") TTS_CASE("Reference of reference check")
{ {
auto v1 = rotgen::matrix<float,1,1>::Ones(); auto v1 = rotgen::matrix<float, 1, 1>::Ones();
auto v2 = rotgen::matrix<float,2,1>::Random(); auto v2 = rotgen::matrix<float, 2, 1>::Random();
auto v3 = rotgen::matrix<float,3,1>::Constant(6.66); auto v3 = rotgen::matrix<float, 3, 1>::Constant(6.66);
auto sum1 = v1(0); auto sum1 = v1(0);
auto sum2 = v2(0) + v2(1); auto sum2 = v2(0) + v2(1);

View file

@ -9,104 +9,104 @@
#include "unit/common/arithmetic.hpp" #include "unit/common/arithmetic.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic block transposition-like operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic block transposition-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_block_references<T,O>(); auto const cases = rotgen::tests::generate_block_references<T, O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases) for (auto const& [matrix_desc, i0, j0, ni, nj] : cases)
{ {
auto[rows,cols,fn] = matrix_desc; auto [rows, cols, fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract(m, i0, j0, ni, nj); auto input = rotgen::extract(m, i0, j0, ni, nj);
rotgen::tests::check_shape_functions(input); rotgen::tests::check_shape_functions(input);
} }
}; };
TTS_CASE_TPL("Test static block transposition-like operations", rotgen::tests::types) TTS_CASE_TPL("Test static block transposition-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_block_references<T,O>(); auto const cases = rotgen::tests::generate_static_block_references<T, O>();
auto process = []<typename D>(D const& d) auto process = []<typename D>(D const& d) {
{ auto [desc, i0, j0] = d;
auto[desc,i0,j0] = d; auto [rows, cols, fn] = desc;
auto[rows,cols,fn] = desc; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::tests::prepare(rows, cols, fn, m);
rotgen::tests::prepare(rows,cols,fn,m); auto input = rotgen::extract<D::ni, D::nj>(m, i0, j0);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
rotgen::tests::check_shape_functions(input); rotgen::tests::check_shape_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };
TTS_CASE_TPL("Test dynamic block reduction-like operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic block reduction-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_block_references<T,O>(); auto const cases = rotgen::tests::generate_block_references<T, O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases) for (auto const& [matrix_desc, i0, j0, ni, nj] : cases)
{ {
auto[rows,cols,fn] = matrix_desc; auto [rows, cols, fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract(m, i0, j0, ni, nj); auto input = rotgen::extract(m, i0, j0, ni, nj);
rotgen::tests::check_reduction_functions(input); rotgen::tests::check_reduction_functions(input);
} }
}; };
TTS_CASE_TPL("Test static block reduction-like operations", rotgen::tests::types) TTS_CASE_TPL("Test static block reduction-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_block_references<T,O>(); auto const cases = rotgen::tests::generate_static_block_references<T, O>();
auto process = []<typename D>(D const& d) auto process = []<typename D>(D const& d) {
{ auto [desc, i0, j0] = d;
auto[desc,i0,j0] = d; auto [rows, cols, fn] = desc;
auto[rows,cols,fn] = desc; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::tests::prepare(rows, cols, fn, m);
rotgen::tests::prepare(rows,cols,fn,m); auto input = rotgen::extract<D::ni, D::nj>(m, i0, j0);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
rotgen::tests::check_reduction_functions(input); rotgen::tests::check_reduction_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };
TTS_CASE_TPL("Test dot product", float, double)<typename T>(tts::type<T>){
{auto v = rotgen::setConstant<rotgen::matrix<T, 1, rotgen::Dynamic>>(1,
16,
2);
auto a = rotgen::head(v, 8);
auto b = rotgen::tail(v, 8);
TTS_EQUAL(rotgen::dot(a, b), 32);
}
TTS_CASE_TPL("Test dot product", float, double)
<typename T>( tts::type<T> )
{ {
{ auto v = rotgen::setConstant<rotgen::matrix<T, rotgen::Dynamic, 1>>(16, 1, 2);
auto v = rotgen::setConstant<rotgen::matrix<T,1,rotgen::Dynamic>>(1,16,2); auto a = rotgen::head(v, 8);
auto a = rotgen::head(v,8); auto b = rotgen::tail(v, 8);
auto b = rotgen::tail(v,8);
TTS_EQUAL(rotgen::dot(a,b), 32); TTS_EQUAL(rotgen::dot(a, b), 32);
} }
{ {
auto v = rotgen::setConstant<rotgen::matrix<T,rotgen::Dynamic,1>>(16,1,2); auto v = rotgen::setConstant<rotgen::matrix<T, 1, rotgen::Dynamic>>(1, 16, 2);
auto a = rotgen::head(v,8); auto a = rotgen::head<8>(v);
auto b = rotgen::tail(v,8); auto b = rotgen::tail<8>(v);
TTS_EQUAL(rotgen::dot(a,b), 32); TTS_EQUAL(rotgen::dot(a, b), 32);
} }
{ {
auto v = rotgen::setConstant<rotgen::matrix<T,1,rotgen::Dynamic>>(1,16,2); auto v = rotgen::setConstant<rotgen::matrix<T, rotgen::Dynamic, 1>>(16, 1, 2);
auto a = rotgen::head<8>(v); auto a = rotgen::head<8>(v);
auto b = rotgen::tail<8>(v); auto b = rotgen::tail<8>(v);
TTS_EQUAL(rotgen::dot(a,b), 32); TTS_EQUAL(rotgen::dot(a, b), 32);
} }
}
{ ;
auto v = rotgen::setConstant<rotgen::matrix<T,rotgen::Dynamic,1>>(16,1,2);
auto a = rotgen::head<8>(v);
auto b = rotgen::tail<8>(v);
TTS_EQUAL(rotgen::dot(a,b), 32);
}
};

View file

@ -12,109 +12,116 @@
// NB: This function must not be turned into a lambda, otherwise // NB: This function must not be turned into a lambda, otherwise
// `test-ubuntu-gcc-release` will not pass and the CI will fail. // `test-ubuntu-gcc-release` will not pass and the CI will fail.
// This is likely due to a compilation bug from GCC 13.3.0. // This is likely due to a compilation bug from GCC 13.3.0.
void fill(auto &m, int r, int c, auto data[]) { void fill(auto& m, int r, int c, auto data[])
for (int k = 0; k < r * c; ++k) {
m.data()[k] = data[k]; for (int k = 0; k < r * c; ++k) m.data()[k] = data[k];
} }
TTS_CASE_TPL("Function size", rotgen::tests::types) TTS_CASE_TPL("Function size", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>(tts::type<tts::types<T, O>>) tts::type<tts::types<T, O>>)
{ {
T data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; T data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// 1x12 dynamic block at (0,0) // 1x12 dynamic block at (0,0)
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> dm(1,12); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> dm(1, 12);
fill(dm,1,12,data); fill(dm, 1, 12, data);
auto b1 = rotgen::block<decltype(dm), rotgen::Dynamic, rotgen::Dynamic>(dm, 0,0,1,12); auto b1 = rotgen::block<decltype(dm), rotgen::Dynamic, rotgen::Dynamic>(
dm, 0, 0, 1, 12);
TTS_EQUAL(b1.rows(), rotgen::Index{1}); TTS_EQUAL(b1.rows(), rotgen::Index{1});
TTS_EQUAL(b1.cols(), rotgen::Index{12}); TTS_EQUAL(b1.cols(), rotgen::Index{12});
// 1x5 dynamic block at (0,2) // 1x5 dynamic block at (0,2)
auto b2 = rotgen::block<decltype(dm), rotgen::Dynamic, rotgen::Dynamic>(dm, 0,2,1,5); auto b2 = rotgen::block<decltype(dm), rotgen::Dynamic, rotgen::Dynamic>(
dm, 0, 2, 1, 5);
TTS_EQUAL(b2.rows(), rotgen::Index{1}); TTS_EQUAL(b2.rows(), rotgen::Index{1});
TTS_EQUAL(b2.cols(), rotgen::Index{5}); TTS_EQUAL(b2.cols(), rotgen::Index{5});
// 3x2 dynamic block at (1,4) in 4x6 // 3x2 dynamic block at (1,4) in 4x6
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> dm2(4,6); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> dm2(4, 6);
fill(dm2,4,6,data); fill(dm2, 4, 6, data);
auto b3 = rotgen::block<decltype(dm2), rotgen::Dynamic, rotgen::Dynamic>(dm2, 1,4,3,2); auto b3 = rotgen::block<decltype(dm2), rotgen::Dynamic, rotgen::Dynamic>(
dm2, 1, 4, 3, 2);
TTS_EQUAL(b3.rows(), rotgen::Index{3}); TTS_EQUAL(b3.rows(), rotgen::Index{3});
TTS_EQUAL(b3.cols(), rotgen::Index{2}); TTS_EQUAL(b3.cols(), rotgen::Index{2});
TTS_EQUAL(b3.size(), rotgen::Index{6}); TTS_EQUAL(b3.size(), rotgen::Index{6});
// 3x4 static block // 3x4 static block
rotgen::matrix<T,3,4,O::value> sm; rotgen::matrix<T, 3, 4, O::value> sm;
fill(sm,3,4,data); fill(sm, 3, 4, data);
auto b4 = rotgen::block<decltype(sm), 3, 4>(sm, 0,0); auto b4 = rotgen::block<decltype(sm), 3, 4>(sm, 0, 0);
TTS_EQUAL(b4.rows(), rotgen::Index{3}); TTS_EQUAL(b4.rows(), rotgen::Index{3});
TTS_EQUAL(b4.cols(), rotgen::Index{4}); TTS_EQUAL(b4.cols(), rotgen::Index{4});
TTS_EQUAL(b4.size(), rotgen::Index{12}); TTS_EQUAL(b4.size(), rotgen::Index{12});
// 6x2 static block // 6x2 static block
rotgen::matrix<T,6,2,O::value> sm2; rotgen::matrix<T, 6, 2, O::value> sm2;
fill(sm2,6,2,data); fill(sm2, 6, 2, data);
auto b5 = rotgen::block<decltype(sm2), 6, 2>(sm2, 0,0); auto b5 = rotgen::block<decltype(sm2), 6, 2>(sm2, 0, 0);
TTS_EQUAL(b5.rows(), rotgen::Index{6}); TTS_EQUAL(b5.rows(), rotgen::Index{6});
TTS_EQUAL(b5.cols(), rotgen::Index{2}); TTS_EQUAL(b5.cols(), rotgen::Index{2});
TTS_EQUAL(b5.size(), rotgen::Index{12}); TTS_EQUAL(b5.size(), rotgen::Index{12});
}; };
TTS_CASE_TPL("Test coefficient accessors", rotgen::tests::types) TTS_CASE_TPL("Test coefficient accessors",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
using base = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>; using base = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
T data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; T data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
base mat(4,3); base mat(4, 3);
for(int k=0;k<12;++k) mat.data()[k] = data[k]; for (int k = 0; k < 12; ++k) mat.data()[k] = data[k];
auto b = rotgen::block<base,rotgen::Dynamic,rotgen::Dynamic>(mat, 0, 0, 4, 3); auto b =
for(rotgen::Index i=0;i<4;i++) rotgen::block<base, rotgen::Dynamic, rotgen::Dynamic>(mat, 0, 0, 4, 3);
for (rotgen::Index i = 0; i < 4; i++)
{ {
for(rotgen::Index j=0;j<3;j++) for (rotgen::Index j = 0; j < 3; j++)
{ {
if constexpr(O::value) TTS_EQUAL(b(i,j), data[j+3*i]); if constexpr (O::value) TTS_EQUAL(b(i, j), data[j + 3 * i]);
else TTS_EQUAL(b(i,j), data[i+4*j]); else TTS_EQUAL(b(i, j), data[i + 4 * j]);
} }
} }
b(1, 1) = 42; b(1, 1) = 42;
TTS_EQUAL(b(1,1), 42); TTS_EQUAL(b(1, 1), 42);
T& ref = b(2, 2); T& ref = b(2, 2);
ref = 17; ref = 17;
TTS_EQUAL(b(2, 2), 17); TTS_EQUAL(b(2, 2), 17);
}; };
TTS_CASE_TPL("Test one index coefficient accessors", rotgen::tests::types) TTS_CASE_TPL("Test one index coefficient accessors",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto vs = [&]() auto vs = [&]() {
{ if constexpr (O::value == rotgen::ColMajor)
if constexpr(O::value == rotgen::ColMajor)
{ {
using base = rotgen::matrix<T,1,rotgen::Dynamic>; using base = rotgen::matrix<T, 1, rotgen::Dynamic>;
base m(12); base m(12);
for(int k=0;k<12;++k) m(k) = k+1; for (int k = 0; k < 12; ++k) m(k) = k + 1;
return std::tuple{m,rotgen::block<base,1,rotgen::Dynamic>(m, 0, 0, 1, 12)}; return std::tuple{
m, rotgen::block<base, 1, rotgen::Dynamic>(m, 0, 0, 1, 12)};
} }
else else
{ {
using base = rotgen::matrix<T,rotgen::Dynamic,1>; using base = rotgen::matrix<T, rotgen::Dynamic, 1>;
base m(12); base m(12);
for(int k=0;k<12;++k) m(k) = k+1; for (int k = 0; k < 12; ++k) m(k) = k + 1;
return std::tuple{m,rotgen::block<base,rotgen::Dynamic,1>(m, 0, 0, 12, 1)}; return std::tuple{
m, rotgen::block<base, rotgen::Dynamic, 1>(m, 0, 0, 12, 1)};
} }
}(); }();
auto mat = get<0>(vs); auto mat = get<0>(vs);
auto b = get<1>(vs); auto b = get<1>(vs);
TTS_EXPECT(b.IsVectorAtCompileTime); TTS_EXPECT(b.IsVectorAtCompileTime);
for(rotgen::Index i=0;i<b.size();i++) for (rotgen::Index i = 0; i < b.size(); i++)
TTS_EQUAL(b(i), mat(i)) << "Index: " << i << "\n"; TTS_EQUAL(b(i), mat(i)) << "Index: " << i << "\n";
for(rotgen::Index i=0;i<b.size();i++) for (rotgen::Index i = 0; i < b.size(); i++)
TTS_EQUAL(b[i], mat(i)) << "Index: " << i << "\n"; TTS_EQUAL(b[i], mat(i)) << "Index: " << i << "\n";
b(1) = 42; b(1) = 42;

View file

@ -9,34 +9,35 @@
#include "unit/common/cwise.hpp" #include "unit/common/cwise.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic block cwise operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic block cwise operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_block_references<T,O>(); auto const cases = rotgen::tests::generate_block_references<T, O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases) for (auto const& [matrix_desc, i0, j0, ni, nj] : cases)
{ {
auto[rows,cols,fn] = matrix_desc; auto [rows, cols, fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract(m, i0, j0, ni, nj); auto input = rotgen::extract(m, i0, j0, ni, nj);
rotgen::tests::check_cwise_functions(input); rotgen::tests::check_cwise_functions(input);
} }
}; };
TTS_CASE_TPL("Test static block cwise operations", rotgen::tests::types) TTS_CASE_TPL("Test static block cwise operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_block_references<T,O>(); auto const cases = rotgen::tests::generate_static_block_references<T, O>();
auto process = []<typename D>(D const& d) auto process = []<typename D>(D const& d) {
{ auto [desc, i0, j0] = d;
auto[desc,i0,j0] = d; auto [rows, cols, fn] = desc;
auto[rows,cols,fn] = desc; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::tests::prepare(rows, cols, fn, m);
rotgen::tests::prepare(rows,cols,fn,m); auto input = rotgen::extract<D::ni, D::nj>(m, i0, j0);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
rotgen::tests::check_cwise_functions(input); rotgen::tests::check_cwise_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };

View file

@ -11,41 +11,44 @@
template<typename EigenType, typename F> template<typename EigenType, typename F>
void for_each_element(EigenType const& m, F&& f) void for_each_element(EigenType const& m, F&& f)
{ {
for(rotgen::Index i = 0; i < m.rows(); ++i) for (rotgen::Index i = 0; i < m.rows(); ++i)
for(rotgen::Index j = 0; j < m.cols(); ++j) for (rotgen::Index j = 0; j < m.cols(); ++j) f(i, j, m(i, j));
f(i, j, m(i,j));
} }
template<typename EigenType, typename F> template<typename EigenType, typename F>
void for_each_element(EigenType& m, F&& f) void for_each_element(EigenType& m, F&& f)
{ {
for(rotgen::Index i = 0; i < m.rows(); ++i) for (rotgen::Index i = 0; i < m.rows(); ++i)
for(rotgen::Index j = 0; j < m.cols(); ++j) for (rotgen::Index j = 0; j < m.cols(); ++j) f(i, j, m(i, j));
f(i, j, m(i,j));
} }
template<typename MatrixType, typename T> template<typename MatrixType, typename T>
MatrixType make_initialized_matrix(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct) MatrixType make_initialized_matrix(
rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct)
{ {
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; MatrixType matrix;
if constexpr(MatrixType::RowsAtCompileTime == -1 &&MatrixType::ColsAtCompileTime == -1) if constexpr (MatrixType::RowsAtCompileTime == -1 &&
MatrixType::ColsAtCompileTime == -1)
rotgen::resize(matrix, r, c); 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)
matrix(i, j) = static_cast<T>(fn(i, j)); matrix(i, j) = static_cast<T>(fn(i, j));
return matrix; return matrix;
} }
template<typename MatrixType, typename BlockType> template<typename MatrixType, typename BlockType>
void validate_block_behavior(MatrixType& matrix, BlockType& block, void validate_block_behavior(MatrixType& matrix,
rotgen::Index block_i, rotgen::Index block_j, BlockType& block,
rotgen::Index block_m, rotgen::Index block_n) rotgen::Index block_i,
rotgen::Index block_j,
rotgen::Index block_m,
rotgen::Index block_n)
{ {
using T = typename MatrixType::value_type; using T = typename MatrixType::value_type;
TTS_EQUAL(block.rows(), block_m); TTS_EQUAL(block.rows(), block_m);
@ -58,12 +61,11 @@ void validate_block_behavior(MatrixType& matrix, BlockType& block,
}); });
// test aliasing if non immutable // test aliasing if non immutable
if constexpr(!BlockType::is_immutable) if constexpr (!BlockType::is_immutable)
{ {
T value = 1; T value = 1;
for_each_element(block, [&](auto i, auto j, auto&) { for_each_element(block,
block(i, j) = value++; [&](auto i, auto j, auto&) { block(i, j) = value++; });
});
value = 1; value = 1;
for_each_element(block, [&](auto i, auto j, auto&) { for_each_element(block, [&](auto i, auto j, auto&) {
@ -81,99 +83,140 @@ void validate_block_behavior(MatrixType& matrix, BlockType& block,
} }
template<typename MatrixType, typename T> template<typename MatrixType, typename T>
void test_dynamic_block_extraction(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct) void test_dynamic_block_extraction(
rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct)
{ {
MatrixType matrix = make_initialized_matrix<MatrixType, T>(matrix_construct); MatrixType matrix = make_initialized_matrix<MatrixType, T>(matrix_construct);
MatrixType const c_matrix = matrix; MatrixType const c_matrix = matrix;
auto c_block_main = rotgen::extract(c_matrix, matrix_construct.i0, matrix_construct.j0, auto c_block_main =
matrix_construct.ni, matrix_construct.nj); rotgen::extract(c_matrix, matrix_construct.i0, matrix_construct.j0,
auto c_block_top_left_corner = rotgen::topLeftCorner(c_matrix, matrix_construct.ni, matrix_construct.nj); matrix_construct.ni, matrix_construct.nj);
auto c_block_top_right_corner = rotgen::topRightCorner(c_matrix, matrix_construct.ni, matrix_construct.nj); auto c_block_top_left_corner =
auto c_block_bottom_left_corner = rotgen::bottomLeftCorner(c_matrix, matrix_construct.ni, matrix_construct.nj); rotgen::topLeftCorner(c_matrix, matrix_construct.ni, matrix_construct.nj);
auto c_block_bottom_right_corner = rotgen::bottomRightCorner(c_matrix, matrix_construct.ni, matrix_construct.nj); auto c_block_top_right_corner =
rotgen::topRightCorner(c_matrix, matrix_construct.ni, matrix_construct.nj);
auto c_block_bottom_left_corner = rotgen::bottomLeftCorner(
c_matrix, matrix_construct.ni, matrix_construct.nj);
auto c_block_bottom_right_corner = rotgen::bottomRightCorner(
c_matrix, matrix_construct.ni, matrix_construct.nj);
auto c_block_top_rows = rotgen::topRows(c_matrix, matrix_construct.ni); auto c_block_top_rows = rotgen::topRows(c_matrix, matrix_construct.ni);
auto c_block_middle_rows = rotgen::middleRows(c_matrix, matrix_construct.i0, matrix_construct.ni); auto c_block_middle_rows =
auto c_block_bottom_rows = rotgen::bottomRows(c_matrix, matrix_construct.ni); rotgen::middleRows(c_matrix, matrix_construct.i0, matrix_construct.ni);
auto c_block_bottom_rows = rotgen::bottomRows(c_matrix, matrix_construct.ni);
auto c_block_left_cols = rotgen::leftCols(c_matrix, matrix_construct.nj); auto c_block_left_cols = rotgen::leftCols(c_matrix, matrix_construct.nj);
auto c_block_middle_cols = rotgen::middleCols(c_matrix, matrix_construct.j0, matrix_construct.nj); auto c_block_middle_cols =
auto c_block_right_cols = rotgen::rightCols(c_matrix, matrix_construct.nj); rotgen::middleCols(c_matrix, matrix_construct.j0, matrix_construct.nj);
auto c_block_right_cols = rotgen::rightCols(c_matrix, matrix_construct.nj);
auto block_main = rotgen::extract(matrix, matrix_construct.i0, matrix_construct.j0, auto block_main =
matrix_construct.ni, matrix_construct.nj); rotgen::extract(matrix, matrix_construct.i0, matrix_construct.j0,
auto block_top_left_corner = rotgen::topLeftCorner(matrix, matrix_construct.ni, matrix_construct.nj); matrix_construct.ni, matrix_construct.nj);
auto block_top_right_corner = rotgen::topRightCorner(matrix, matrix_construct.ni, matrix_construct.nj); auto block_top_left_corner =
auto block_bottom_left_corner = rotgen::bottomLeftCorner(matrix, matrix_construct.ni, matrix_construct.nj); rotgen::topLeftCorner(matrix, matrix_construct.ni, matrix_construct.nj);
auto block_bottom_right_corner = rotgen::bottomRightCorner(matrix, matrix_construct.ni, matrix_construct.nj); auto block_top_right_corner =
rotgen::topRightCorner(matrix, matrix_construct.ni, matrix_construct.nj);
auto block_bottom_left_corner =
rotgen::bottomLeftCorner(matrix, matrix_construct.ni, matrix_construct.nj);
auto block_bottom_right_corner =
rotgen::bottomRightCorner(matrix, matrix_construct.ni, matrix_construct.nj);
auto block_top_rows = rotgen::topRows(matrix, matrix_construct.ni); auto block_top_rows = rotgen::topRows(matrix, matrix_construct.ni);
auto block_middle_rows = rotgen::middleRows(matrix, matrix_construct.i0, matrix_construct.ni); auto block_middle_rows =
auto block_bottom_rows = rotgen::bottomRows(matrix, matrix_construct.ni); rotgen::middleRows(matrix, matrix_construct.i0, matrix_construct.ni);
auto block_bottom_rows = rotgen::bottomRows(matrix, matrix_construct.ni);
auto block_left_cols = rotgen::leftCols(matrix, matrix_construct.nj); auto block_left_cols = rotgen::leftCols(matrix, matrix_construct.nj);
auto block_middle_cols = rotgen::middleCols(matrix, matrix_construct.j0, matrix_construct.nj); auto block_middle_cols =
auto block_right_cols = rotgen::rightCols(matrix, matrix_construct.nj); rotgen::middleCols(matrix, matrix_construct.j0, matrix_construct.nj);
auto block_right_cols = rotgen::rightCols(matrix, matrix_construct.nj);
auto blocks = std::make_tuple( auto blocks = std::make_tuple(
// --- CONST TESTS // --- CONST TESTS
std::make_tuple(c_block_main, matrix_construct.i0, matrix_construct.j0, matrix_construct.ni, matrix_construct.nj), std::make_tuple(c_block_main, matrix_construct.i0, matrix_construct.j0,
std::make_tuple(c_block_top_left_corner, 0, 0, matrix_construct.ni, matrix_construct.nj),
std::make_tuple(c_block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, matrix_construct.ni, matrix_construct.nj),
std::make_tuple(c_block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix_construct.nj),
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.ni, matrix_construct.nj),
std::make_tuple(c_block_top_left_corner, 0, 0, matrix_construct.ni,
matrix_construct.nj),
std::make_tuple(c_block_top_right_corner, 0,
matrix.cols() - matrix_construct.nj, matrix_construct.ni,
matrix_construct.nj),
std::make_tuple(c_block_bottom_left_corner,
matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni,
matrix_construct.nj),
std::make_tuple(c_block_bottom_right_corner,
matrix.rows() - matrix_construct.ni,
matrix.cols() - matrix_construct.nj, matrix_construct.ni,
matrix_construct.nj),
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()),
std::make_tuple(c_block_middle_rows, matrix_construct.i0, 0, matrix_construct.ni, matrix.cols()), std::make_tuple(c_block_middle_rows, matrix_construct.i0, 0,
std::make_tuple(c_block_bottom_rows, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix.cols()), matrix_construct.ni, matrix.cols()),
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), std::make_tuple(c_block_left_cols, 0, 0, matrix.rows(),
std::make_tuple(c_block_middle_cols, 0, matrix_construct.j0, matrix.rows(), matrix_construct.nj), matrix_construct.nj),
std::make_tuple(c_block_right_cols, 0, matrix.cols() - matrix_construct.nj, matrix.rows(), matrix_construct.nj), std::make_tuple(c_block_middle_cols, 0, matrix_construct.j0, matrix.rows(),
matrix_construct.nj),
std::make_tuple(c_block_right_cols, 0, matrix.cols() - matrix_construct.nj,
matrix.rows(), matrix_construct.nj),
// --- REGULAR TESTS // --- REGULAR TESTS
std::make_tuple(block_main, matrix_construct.i0, matrix_construct.j0, matrix_construct.ni, matrix_construct.nj), std::make_tuple(block_main, matrix_construct.i0, matrix_construct.j0,
std::make_tuple(block_top_left_corner, 0, 0, matrix_construct.ni, matrix_construct.nj),
std::make_tuple(block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, matrix_construct.ni, matrix_construct.nj),
std::make_tuple(block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix_construct.nj),
std::make_tuple(block_bottom_right_corner, matrix.rows() - matrix_construct.ni, matrix.cols() - matrix_construct.nj,
matrix_construct.ni, matrix_construct.nj), matrix_construct.ni, matrix_construct.nj),
std::make_tuple(block_top_left_corner, 0, 0, matrix_construct.ni,
matrix_construct.nj),
std::make_tuple(block_top_right_corner, 0,
matrix.cols() - matrix_construct.nj, matrix_construct.ni,
matrix_construct.nj),
std::make_tuple(block_bottom_left_corner,
matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni,
matrix_construct.nj),
std::make_tuple(block_bottom_right_corner,
matrix.rows() - matrix_construct.ni,
matrix.cols() - matrix_construct.nj, matrix_construct.ni,
matrix_construct.nj),
std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols()), std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols()),
std::make_tuple(block_middle_rows, matrix_construct.i0, 0, matrix_construct.ni, matrix.cols()), std::make_tuple(block_middle_rows, matrix_construct.i0, 0,
std::make_tuple(block_bottom_rows, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix.cols()), matrix_construct.ni, matrix.cols()),
std::make_tuple(block_bottom_rows, matrix.rows() - matrix_construct.ni, 0,
matrix_construct.ni, matrix.cols()),
std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj), std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj),
std::make_tuple(block_middle_cols, 0, matrix_construct.j0, matrix.rows(), matrix_construct.nj), std::make_tuple(block_middle_cols, 0, matrix_construct.j0, matrix.rows(),
std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj, matrix.rows(), matrix_construct.nj) matrix_construct.nj),
); std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj,
matrix.rows(), matrix_construct.nj));
std::apply([&](auto&&... block_entries) std::apply(
{ [&](auto&&... block_entries) {
(([&] (([&] {
{ auto&& [block, i_offset, j_offset, ni, nj] = block_entries;
auto&& [block, i_offset, j_offset, ni, nj] = block_entries; using block_t = std::remove_reference_t<decltype(block)>;
using block_t = std::remove_reference_t<decltype(block)>;
TTS_EQUAL(block_t::RowsAtCompileTime, rotgen::Dynamic); TTS_EQUAL(block_t::RowsAtCompileTime, rotgen::Dynamic);
TTS_EQUAL(block_t::ColsAtCompileTime, rotgen::Dynamic); TTS_EQUAL(block_t::ColsAtCompileTime, rotgen::Dynamic);
TTS_EQUAL(block_t::storage_order, MatrixType::storage_order); TTS_EQUAL(block_t::storage_order, MatrixType::storage_order);
validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj);
})(), ...);
}, blocks);
validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj);
})(),
...);
},
blocks);
} }
template<typename MatrixType, typename T, rotgen::Index NI, rotgen::Index NJ> template<typename MatrixType, typename T, rotgen::Index NI, rotgen::Index NJ>
void test_static_block_extraction(rotgen::tests::static_matrix_block_test_case<MatrixType, NI, NJ> const& matrix_construct) void test_static_block_extraction(
rotgen::tests::static_matrix_block_test_case<MatrixType, NI, NJ> const&
matrix_construct)
{ {
auto[d,i0,j0] = matrix_construct; auto [d, i0, j0] = matrix_construct;
auto[r,c,fn] = d; auto [r, c, fn] = d;
MatrixType matrix(r,c); MatrixType 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)
@ -181,177 +224,219 @@ void test_static_block_extraction(rotgen::tests::static_matrix_block_test_case<M
MatrixType const c_matrix = matrix; MatrixType const c_matrix = matrix;
auto c_block_main = rotgen::extract<NI, NJ>(c_matrix, i0, j0); auto c_block_main = rotgen::extract<NI, NJ>(c_matrix, i0, j0);
auto c_block_top_left_corner = rotgen::topLeftCorner<NI, NJ>(c_matrix); auto c_block_top_left_corner = rotgen::topLeftCorner<NI, NJ>(c_matrix);
auto c_block_top_right_corner = rotgen::topRightCorner<NI, NJ>(c_matrix); auto c_block_top_right_corner = rotgen::topRightCorner<NI, NJ>(c_matrix);
auto c_block_bottom_left_corner = rotgen::bottomLeftCorner<NI, NJ>(c_matrix); auto c_block_bottom_left_corner = rotgen::bottomLeftCorner<NI, NJ>(c_matrix);
auto c_block_bottom_right_corner = rotgen::bottomRightCorner<NI, NJ>(c_matrix); auto c_block_bottom_right_corner =
auto c_block_top_rows = rotgen::topRows<NI>(c_matrix); rotgen::bottomRightCorner<NI, NJ>(c_matrix);
auto c_block_middle_rows = rotgen::middleRows<NI>(c_matrix, i0); auto c_block_top_rows = rotgen::topRows<NI>(c_matrix);
auto c_block_bottom_rows = rotgen::bottomRows<NI>(c_matrix); auto c_block_middle_rows = rotgen::middleRows<NI>(c_matrix, i0);
auto c_block_left_cols = rotgen::leftCols<NJ>(c_matrix); auto c_block_bottom_rows = rotgen::bottomRows<NI>(c_matrix);
auto c_block_middle_cols = rotgen::middleCols<NJ>(c_matrix, j0); auto c_block_left_cols = rotgen::leftCols<NJ>(c_matrix);
auto c_block_right_cols = rotgen::rightCols<NJ>(c_matrix); auto c_block_middle_cols = rotgen::middleCols<NJ>(c_matrix, j0);
auto c_block_row = rotgen::row(c_matrix, i0); auto c_block_right_cols = rotgen::rightCols<NJ>(c_matrix);
auto c_block_col = rotgen::col(c_matrix, j0); auto c_block_row = rotgen::row(c_matrix, i0);
auto c_block_col = rotgen::col(c_matrix, j0);
auto block_main = rotgen::extract<NI, NJ>(matrix, i0, j0); auto block_main = rotgen::extract<NI, NJ>(matrix, i0, j0);
auto block_top_left_corner = rotgen::topLeftCorner<NI, NJ>(matrix); auto block_top_left_corner = rotgen::topLeftCorner<NI, NJ>(matrix);
auto block_top_right_corner = rotgen::topRightCorner<NI, NJ>(matrix); auto block_top_right_corner = rotgen::topRightCorner<NI, NJ>(matrix);
auto block_bottom_left_corner = rotgen::bottomLeftCorner<NI, NJ>(matrix); auto block_bottom_left_corner = rotgen::bottomLeftCorner<NI, NJ>(matrix);
auto block_bottom_right_corner = rotgen::bottomRightCorner<NI, NJ>(matrix); auto block_bottom_right_corner = rotgen::bottomRightCorner<NI, NJ>(matrix);
auto block_top_rows = rotgen::topRows<NI>(matrix); auto block_top_rows = rotgen::topRows<NI>(matrix);
auto block_middle_rows = rotgen::middleRows<NI>(matrix, i0); auto block_middle_rows = rotgen::middleRows<NI>(matrix, i0);
auto block_bottom_rows = rotgen::bottomRows<NI>(matrix); auto block_bottom_rows = rotgen::bottomRows<NI>(matrix);
auto block_left_cols = rotgen::leftCols<NJ>(matrix); auto block_left_cols = rotgen::leftCols<NJ>(matrix);
auto block_middle_cols = rotgen::middleCols<NJ>(matrix, j0); auto block_middle_cols = rotgen::middleCols<NJ>(matrix, j0);
auto block_right_cols = rotgen::rightCols<NJ>(matrix); auto block_right_cols = rotgen::rightCols<NJ>(matrix);
auto block_row = rotgen::row(matrix, i0); auto block_row = rotgen::row(matrix, i0);
auto block_col = rotgen::col(matrix, j0); auto block_col = rotgen::col(matrix, j0);
auto blocks = std::make_tuple( auto blocks = std::make_tuple(
// ----- TEST ON BLOCK FROM CONST MATRIX // ----- TEST ON BLOCK FROM CONST MATRIX
std::make_tuple(c_block_main, i0, j0, std::make_tuple(c_block_main, i0, j0, matrix_construct.ni,
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ)), matrix_construct.nj, int(NI), int(NJ)),
std::make_tuple(c_block_top_left_corner, 0, 0, std::make_tuple(c_block_top_left_corner, 0, 0, matrix_construct.ni,
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ)), matrix_construct.nj, int(NI), int(NJ)),
std::make_tuple(c_block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, std::make_tuple(c_block_top_right_corner, 0,
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ)), matrix.cols() - matrix_construct.nj, matrix_construct.ni,
std::make_tuple(c_block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, matrix_construct.nj, int(NI), int(NJ)),
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ)), std::make_tuple(c_block_bottom_left_corner,
std::make_tuple(c_block_bottom_right_corner, matrix.rows() - matrix_construct.ni, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni,
matrix_construct.nj, int(NI), int(NJ)),
std::make_tuple(c_block_bottom_right_corner,
matrix.rows() - matrix_construct.ni,
matrix.cols() - matrix_construct.nj, matrix_construct.ni, matrix.cols() - matrix_construct.nj, matrix_construct.ni,
matrix_construct.nj, int(NI), int(NJ)), matrix_construct.nj, int(NI), int(NJ)),
std::make_tuple(c_block_top_rows, 0, 0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic), std::make_tuple(c_block_top_rows, 0, 0, matrix_construct.ni, matrix.cols(),
int(NI), rotgen::Dynamic),
std::make_tuple(c_block_middle_rows, i0, 0, matrix_construct.ni, std::make_tuple(c_block_middle_rows, i0, 0, matrix_construct.ni,
matrix.cols(), int(NI), rotgen::Dynamic), matrix.cols(), int(NI), rotgen::Dynamic),
std::make_tuple(c_block_bottom_rows, matrix.rows() - matrix_construct.ni, std::make_tuple(c_block_bottom_rows, matrix.rows() - matrix_construct.ni, 0,
0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic), matrix_construct.ni, matrix.cols(), int(NI),
rotgen::Dynamic),
std::make_tuple(c_block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ)), std::make_tuple(c_block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj,
std::make_tuple(c_block_middle_cols, 0, j0, rotgen::Dynamic, int(NJ)),
matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ)), std::make_tuple(c_block_middle_cols, 0, j0, matrix.rows(),
matrix_construct.nj, rotgen::Dynamic, int(NJ)),
std::make_tuple(c_block_right_cols, 0, matrix.cols() - matrix_construct.nj, std::make_tuple(c_block_right_cols, 0, matrix.cols() - matrix_construct.nj,
matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ)), matrix.rows(), matrix_construct.nj, rotgen::Dynamic,
int(NJ)),
std::make_tuple(c_block_row, i0, 0, std::make_tuple(c_block_row, i0, 0, 1, matrix.cols(), 1, rotgen::Dynamic),
1, matrix.cols(), 1, rotgen::Dynamic), std::make_tuple(c_block_col, 0, j0, matrix.rows(), 1, rotgen::Dynamic, 1),
std::make_tuple(c_block_col, 0, j0,
matrix.rows(), 1, rotgen::Dynamic, 1),
// -- Block to NON CONST // -- Block to NON CONST
std::make_tuple(block_main, i0, j0, std::make_tuple(block_main, i0, j0, matrix_construct.ni,
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ)), matrix_construct.nj, int(NI), int(NJ)),
std::make_tuple(block_top_left_corner, 0, 0, std::make_tuple(block_top_left_corner, 0, 0, matrix_construct.ni,
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ)), matrix_construct.nj, int(NI), int(NJ)),
std::make_tuple(block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, std::make_tuple(block_top_right_corner, 0,
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ)), matrix.cols() - matrix_construct.nj, matrix_construct.ni,
std::make_tuple(block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, matrix_construct.nj, int(NI), int(NJ)),
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ)), std::make_tuple(block_bottom_left_corner,
std::make_tuple(block_bottom_right_corner, matrix.rows() - matrix_construct.ni, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni,
matrix_construct.nj, int(NI), int(NJ)),
std::make_tuple(block_bottom_right_corner,
matrix.rows() - matrix_construct.ni,
matrix.cols() - matrix_construct.nj, matrix_construct.ni, matrix.cols() - matrix_construct.nj, matrix_construct.ni,
matrix_construct.nj, int(NI), int(NJ)), matrix_construct.nj, int(NI), int(NJ)),
std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic), std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols(),
int(NI), rotgen::Dynamic),
std::make_tuple(block_middle_rows, i0, 0, matrix_construct.ni, std::make_tuple(block_middle_rows, i0, 0, matrix_construct.ni,
matrix.cols(), int(NI), rotgen::Dynamic), matrix.cols(), int(NI), rotgen::Dynamic),
std::make_tuple(block_bottom_rows, matrix.rows() - matrix_construct.ni, std::make_tuple(block_bottom_rows, matrix.rows() - matrix_construct.ni, 0,
0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic), matrix_construct.ni, matrix.cols(), int(NI),
rotgen::Dynamic),
std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ)), std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj,
std::make_tuple(block_middle_cols, 0, j0, rotgen::Dynamic, int(NJ)),
matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ)), std::make_tuple(block_middle_cols, 0, j0, matrix.rows(),
matrix_construct.nj, rotgen::Dynamic, int(NJ)),
std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj, std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj,
matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ)), matrix.rows(), matrix_construct.nj, rotgen::Dynamic,
int(NJ)),
std::make_tuple(block_row, i0, 0, std::make_tuple(block_row, i0, 0, 1, matrix.cols(), 1, rotgen::Dynamic),
1, matrix.cols(), 1, rotgen::Dynamic), std::make_tuple(block_col, 0, j0, matrix.rows(), 1, rotgen::Dynamic, 1));
std::make_tuple(block_col, 0, j0,
matrix.rows(), 1, rotgen::Dynamic, 1)
);
std::apply([&](auto&&... block_entries) std::apply(
{ [&](auto&&... block_entries) {
(([&] (([&] {
{ auto&& [block, i_offset, j_offset, ni, nj, rows_ct, cols_ct] =
auto&& [block, i_offset, j_offset, ni, nj, rows_ct, cols_ct] = block_entries; block_entries;
using block_t = std::remove_reference_t<decltype(block)>; using block_t = std::remove_reference_t<decltype(block)>;
TTS_EQUAL(block_t::RowsAtCompileTime, rows_ct); TTS_EQUAL(block_t::RowsAtCompileTime, rows_ct);
TTS_EQUAL(block_t::ColsAtCompileTime, cols_ct); TTS_EQUAL(block_t::ColsAtCompileTime, cols_ct);
validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj); validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj);
})(), ...); })(),
}, blocks); ...);
},
blocks);
} }
TTS_CASE_TPL("Check all dynamic block extractions on a dynamic row-major matrix", rotgen::tests::types) TTS_CASE_TPL(
<typename T, typename O>( tts::type< tts::types<T,O>> ) "Check all dynamic block extractions on a dynamic row-major matrix",
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>; using mat_t =
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value, 1>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> cases = { std::vector<rotgen::tests::matrix_block_test_case<mat_t>> cases = {
{ {6, 11, [](rotgen::Index i, rotgen::Index j) { return T(i * 10 + j); }}, 1, 2, 3, 2 }, {{6, 11, [](rotgen::Index i, rotgen::Index j) { return T(i * 10 + j); }},
{ {7, 10, [](rotgen::Index i, rotgen::Index j) { return T(std::sin(i + j)); }}, 4, 4, 3, 3 }, 1,
{ {5, 5, [](rotgen::Index i, rotgen::Index j) { return T((i + j) % 7); }}, 0, 0, 5, 5 }, 2,
{ {9, 14, [](rotgen::Index i, rotgen::Index j) { return T(i+j + 3*j); }}, 3, 7, 1, 1 } 3,
}; 2},
{{7, 10,
[](rotgen::Index i, rotgen::Index j) { return T(std::sin(i + j)); }},
4,
4,
3,
3},
{{5, 5, [](rotgen::Index i, rotgen::Index j) { return T((i + j) % 7); }},
0,
0,
5,
5},
{{9, 14, [](rotgen::Index i, rotgen::Index j) { return T(i + j + 3 * j); }},
3,
7,
1,
1}};
for (auto const& matrix_case : cases) { for (auto const& matrix_case : cases)
{
test_dynamic_block_extraction<mat_t, T>(matrix_case); test_dynamic_block_extraction<mat_t, T>(matrix_case);
} }
}; };
TTS_CASE_TPL("Check all dynamic block extractions on a static column-major matrix", rotgen::tests::types) TTS_CASE_TPL(
<typename T, typename O>( tts::type< tts::types<T,O>> ) "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, O::value, 0>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> cases = { 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); } }, 1, 2, 3, 2 }, {{4, 5, [](auto i, auto j) { return T(2 * i + j * j * j - 42); }},
{ {4, 5, [](auto i, auto j) { return T(std::tan(i*i*j)); } }, 0, 1, 2, 1 }, 1,
{ {4, 5, [](auto i, auto j) { return T((i*i + j*j) / 6); } }, 2, 0, 0, 0 } 2,
}; 3,
2},
{{4, 5, [](auto i, auto j) { return T(std::tan(i * i * j)); }}, 0, 1, 2, 1},
{{4, 5, [](auto i, auto j) { return T((i * i + j * j) / 6); }},
2,
0,
0,
0}};
for (auto const& matrix_case : cases) { for (auto const& matrix_case : cases)
{
test_dynamic_block_extraction<mat_t, T>(matrix_case); test_dynamic_block_extraction<mat_t, T>(matrix_case);
} }
}; };
TTS_CASE_TPL("Check all static block extractions", rotgen::tests::types) TTS_CASE_TPL("Check all static block extractions",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
test_static_block_extraction<mat_t, T, 1, 2>( test_static_block_extraction<mat_t, T, 1, 2>(
rotgen::tests::static_matrix_block_test_case<mat_t, 1, 2>{ rotgen::tests::static_matrix_block_test_case<mat_t, 1, 2>{
{11, 11, [](rotgen::Index i, rotgen::Index j) { return T(i*i*i + 3*j - 127); } }, {11, 11,
3, 2 [](rotgen::Index i, rotgen::Index j) {
} return T(i * i * i + 3 * j - 127);
); }},
3,
2});
test_static_block_extraction<mat_t, double, 4, 3>( test_static_block_extraction<mat_t, double, 4, 3>(
rotgen::tests::static_matrix_block_test_case<mat_t, 4, 3>{ rotgen::tests::static_matrix_block_test_case<mat_t, 4, 3>{
{14, 15,[](rotgen::Index i, rotgen::Index j) { return T(std::cos(i * j * 2)); }}, {14, 15,
5, 1 [](rotgen::Index i, rotgen::Index j) { return T(std::cos(i * j * 2)); }},
} 5,
); 1});
test_static_block_extraction<mat_t, double, 0, 0>( test_static_block_extraction<mat_t, double, 0, 0>(
rotgen::tests::static_matrix_block_test_case<mat_t, 0, 0>{ rotgen::tests::static_matrix_block_test_case<mat_t, 0, 0>{
{5, 5,[](rotgen::Index i, rotgen::Index j) { return T((i + j) % 9); }}, {5, 5, [](rotgen::Index i, rotgen::Index j) { return T((i + j) % 9); }},
0, 0 0,
} 0});
);
}; };
TTS_CASE_TPL("Check vector-only extractions", TTS_CASE_TPL("Check vector-only extractions",
rotgen::tests::types)<typename T, typename O>( rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>) { tts::type<tts::types<T, O>>)
auto run_case = [](auto &&matrix, auto &&block, int i_offset, int j_offset, {
int ni, int nj, auto const &rows_ct, auto const &cols_ct) { auto run_case = [](auto&& matrix, auto&& block, int i_offset, int j_offset,
int ni, int nj, auto const& rows_ct, auto const& cols_ct) {
using block_t = std::remove_reference_t<decltype(block)>; using block_t = std::remove_reference_t<decltype(block)>;
TTS_EQUAL(block_t::RowsAtCompileTime, rows_ct); TTS_EQUAL(block_t::RowsAtCompileTime, rows_ct);
@ -360,12 +445,12 @@ TTS_CASE_TPL("Check vector-only extractions",
validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj); validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj);
}; };
if constexpr (O::value == rotgen::RowMajor) { 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, O::value>;
mat_t m(1, 11); mat_t m(1, 11);
for (rotgen::Index i = 0; i < 11; ++i) for (rotgen::Index i = 0; i < 11; ++i) m(i) = 1 + i;
m(i) = 1 + i;
run_case(m, head(m, 1), 0, 0, 1, 1, 1, rotgen::Dynamic); run_case(m, head(m, 1), 0, 0, 1, 1, 1, rotgen::Dynamic);
run_case(m, head(m, 5), 0, 0, 1, 5, 1, rotgen::Dynamic); run_case(m, head(m, 5), 0, 0, 1, 5, 1, rotgen::Dynamic);
@ -385,12 +470,13 @@ TTS_CASE_TPL("Check vector-only extractions",
run_case(m, segment<11>(m, 0), 0, 0, 1, 11, 1, 11); run_case(m, segment<11>(m, 0), 0, 0, 1, 11, 1, 11);
run_case(m, segment<7>(m, 0), 0, 0, 1, 7, 1, 7); run_case(m, segment<7>(m, 0), 0, 0, 1, 7, 1, 7);
run_case(m, segment<6>(m, 5), 0, 5, 1, 6, 1, 6); run_case(m, segment<6>(m, 5), 0, 5, 1, 6, 1, 6);
} else { }
else
{
using mat_t = rotgen::matrix<T, rotgen::Dynamic, 1, O::value>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, 1, O::value>;
mat_t m(11, 1); mat_t m(11, 1);
for (rotgen::Index i = 0; i < 11; ++i) for (rotgen::Index i = 0; i < 11; ++i) m(i) = 1 + i;
m(i) = 1 + i;
run_case(m, head(m, 1), 0, 0, 1, 1, rotgen::Dynamic, 1); run_case(m, head(m, 1), 0, 0, 1, 1, rotgen::Dynamic, 1);
run_case(m, head(m, 5), 0, 0, 5, 1, rotgen::Dynamic, 1); run_case(m, head(m, 5), 0, 0, 5, 1, rotgen::Dynamic, 1);

View file

@ -8,261 +8,269 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
void test_value ( const auto& matrix, auto value void test_value(auto const& matrix,
, rotgen::Index i0, rotgen::Index j0 auto value,
, rotgen::Index rows, rotgen::Index cols rotgen::Index i0,
) rotgen::Index j0,
rotgen::Index rows,
rotgen::Index cols)
{ {
for(rotgen::Index r=0;r<rows;++r) for (rotgen::Index r = 0; r < rows; ++r)
for(rotgen::Index c=0;c<cols;++c) for (rotgen::Index c = 0; c < cols; ++c)
TTS_EQUAL(matrix(i0+r, j0+c), value); TTS_EQUAL(matrix(i0 + r, j0 + c), value);
} }
void test_identity( const auto& matrix void test_identity(auto const& matrix,
, rotgen::Index i0, rotgen::Index j0 rotgen::Index i0,
, rotgen::Index rows, rotgen::Index cols rotgen::Index j0,
) rotgen::Index rows,
rotgen::Index cols)
{ {
for(rotgen::Index r=0;r<rows;++r) for (rotgen::Index r = 0; r < rows; ++r)
for(rotgen::Index c=0;c<cols;++c) for (rotgen::Index c = 0; c < cols; ++c)
TTS_EQUAL(matrix(i0+r, j0+c), r==c ? 1 : 0); TTS_EQUAL(matrix(i0 + r, j0 + c), r == c ? 1 : 0);
} }
void test_random( const auto& matrix void test_random(auto const& matrix,
, rotgen::Index i0, rotgen::Index j0 rotgen::Index i0,
, rotgen::Index rows, rotgen::Index cols rotgen::Index j0,
) rotgen::Index rows,
rotgen::Index cols)
{ {
for(rotgen::Index r=0;r<rows;++r) for (rotgen::Index r = 0; r < rows; ++r)
for(rotgen::Index c=0;c<cols;++c) for (rotgen::Index c = 0; c < cols; ++c)
{ {
TTS_GREATER_EQUAL(matrix(i0+r, j0+c), -1.0); TTS_GREATER_EQUAL(matrix(i0 + r, j0 + c), -1.0);
TTS_LESS_EQUAL(matrix(i0+r, j0+c), 1.0); TTS_LESS_EQUAL(matrix(i0 + r, j0 + c), 1.0);
} }
} }
TTS_CASE_TPL("Test dynamic block::setZero", rotgen::tests::types) TTS_CASE_TPL("Test dynamic block::setZero",
<typename T, typename O>( tts::type< tts::types<T,O>>) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_block_references<T,O>(); auto const cases = rotgen::tests::generate_block_references<T, O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases) for (auto const& [matrix_desc, i0, j0, ni, nj] : cases)
{ {
auto[rows,cols,fn] = matrix_desc; auto [rows, cols, fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract(m, i0, j0, ni, nj); auto input = rotgen::extract(m, i0, j0, ni, nj);
input.setZero(); input.setZero();
test_value(m,T{0},i0,j0,ni,nj); test_value(m, T{0}, i0, j0, ni, nj);
using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj)); using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj));
auto values = input_type::Zero(ni,nj); auto values = input_type::Zero(ni, nj);
test_value(values,T{0},0,0,ni,nj); test_value(values, T{0}, 0, 0, ni, nj);
} }
}; };
TTS_CASE_TPL("Test static block:setZero", rotgen::tests::types) TTS_CASE_TPL("Test static block:setZero",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_block_references<T,O>(); auto const cases = rotgen::tests::generate_static_block_references<T, O>();
auto process = []<typename D>(D const& d) auto process = []<typename D>(D const& d) {
{ auto [desc, i0, j0] = d;
auto[desc,i0,j0] = d; auto [rows, cols, fn] = desc;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0); auto input = rotgen::extract<D::ni, D::nj>(m, i0, j0);
input.setZero(); input.setZero();
test_value(m,T{0},i0,j0,D::ni,D::nj); test_value(m, T{0}, i0, j0, D::ni, D::nj);
using input_type = decltype(rotgen::extract<D::ni,D::nj>(m, i0, j0)); using input_type = decltype(rotgen::extract<D::ni, D::nj>(m, i0, j0));
auto values = input_type::Zero(); auto values = input_type::Zero();
test_value(values,T{0},0,0,D::ni,D::nj); test_value(values, T{0}, 0, 0, D::ni, D::nj);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };
TTS_CASE_TPL("Test dynamic block::setOnes", rotgen::tests::types) TTS_CASE_TPL("Test dynamic block::setOnes",
<typename T, typename O>( tts::type< tts::types<T,O>>) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_block_references<T,O>(); auto const cases = rotgen::tests::generate_block_references<T, O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases) for (auto const& [matrix_desc, i0, j0, ni, nj] : cases)
{ {
auto[rows,cols,fn] = matrix_desc; auto [rows, cols, fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract(m, i0, j0, ni, nj); auto input = rotgen::extract(m, i0, j0, ni, nj);
input.setOnes(); input.setOnes();
test_value(m,T{1},i0,j0,ni,nj); test_value(m, T{1}, i0, j0, ni, nj);
using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj)); using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj));
auto values = input_type::Ones(ni,nj); auto values = input_type::Ones(ni, nj);
test_value(values,T{1},0,0,ni,nj); test_value(values, T{1}, 0, 0, ni, nj);
} }
}; };
TTS_CASE_TPL("Test static block:setOnes", rotgen::tests::types) TTS_CASE_TPL("Test static block:setOnes",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_block_references<T,O>(); auto const cases = rotgen::tests::generate_static_block_references<T, O>();
auto process = []<typename D>(D const& d) auto process = []<typename D>(D const& d) {
{ auto [desc, i0, j0] = d;
auto[desc,i0,j0] = d; auto [rows, cols, fn] = desc;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0); auto input = rotgen::extract<D::ni, D::nj>(m, i0, j0);
input.setOnes(); input.setOnes();
test_value(m,T{1},i0,j0,D::ni,D::nj); test_value(m, T{1}, i0, j0, D::ni, D::nj);
using input_type = decltype(rotgen::extract<D::ni,D::nj>(m, i0, j0)); using input_type = decltype(rotgen::extract<D::ni, D::nj>(m, i0, j0));
auto values = input_type::Ones(); auto values = input_type::Ones();
test_value(values,T{1},0,0,D::ni,D::nj); test_value(values, T{1}, 0, 0, D::ni, D::nj);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };
TTS_CASE_TPL("Test dynamic block::setConstant", rotgen::tests::types) TTS_CASE_TPL("Test dynamic block::setConstant",
<typename T, typename O>( tts::type< tts::types<T,O>>) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_block_references<T,O>(); auto const cases = rotgen::tests::generate_block_references<T, O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases) for (auto const& [matrix_desc, i0, j0, ni, nj] : cases)
{ {
auto[rows,cols,fn] = matrix_desc; auto [rows, cols, fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract(m, i0, j0, ni, nj); auto input = rotgen::extract(m, i0, j0, ni, nj);
input.setConstant(T{13.37f}); input.setConstant(T{13.37f});
test_value(m,T{13.37f},i0,j0,ni,nj); test_value(m, T{13.37f}, i0, j0, ni, nj);
using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj)); using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj));
auto values = input_type::Constant(ni,nj,T{13.37f}); auto values = input_type::Constant(ni, nj, T{13.37f});
test_value(values,T{13.37f},0,0,ni,nj); test_value(values, T{13.37f}, 0, 0, ni, nj);
} }
}; };
TTS_CASE_TPL("Test static block:setConstant", rotgen::tests::types) TTS_CASE_TPL("Test static block:setConstant",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_block_references<T,O>(); auto const cases = rotgen::tests::generate_static_block_references<T, O>();
auto process = []<typename D>(D const& d) auto process = []<typename D>(D const& d) {
{ auto [desc, i0, j0] = d;
auto[desc,i0,j0] = d; auto [rows, cols, fn] = desc;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0); auto input = rotgen::extract<D::ni, D::nj>(m, i0, j0);
input.setConstant(T{13.37f}); input.setConstant(T{13.37f});
test_value(m,T{13.37f},i0,j0,D::ni,D::nj); test_value(m, T{13.37f}, i0, j0, D::ni, D::nj);
using input_type = decltype(rotgen::extract<D::ni,D::nj>(m, i0, j0)); using input_type = decltype(rotgen::extract<D::ni, D::nj>(m, i0, j0));
auto values = input_type::Constant(T{13.37f}); auto values = input_type::Constant(T{13.37f});
test_value(values,T{13.37f},0,0,D::ni,D::nj); test_value(values, T{13.37f}, 0, 0, D::ni, D::nj);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };
TTS_CASE_TPL("Test dynamic block::setIdentity", rotgen::tests::types) TTS_CASE_TPL("Test dynamic block::setIdentity",
<typename T, typename O>( tts::type< tts::types<T,O>>) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_block_references<T,O>(); auto const cases = rotgen::tests::generate_block_references<T, O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases) for (auto const& [matrix_desc, i0, j0, ni, nj] : cases)
{ {
auto[rows,cols,fn] = matrix_desc; auto [rows, cols, fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract(m, i0, j0, ni, nj); auto input = rotgen::extract(m, i0, j0, ni, nj);
input.setIdentity(); input.setIdentity();
test_identity(m,i0,j0,ni,nj); test_identity(m, i0, j0, ni, nj);
using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj)); using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj));
auto values = input_type::Identity(ni,nj); auto values = input_type::Identity(ni, nj);
test_identity(values,0,0,ni,nj); test_identity(values, 0, 0, ni, nj);
} }
}; };
TTS_CASE_TPL("Test static block:setIdentity", rotgen::tests::types) TTS_CASE_TPL("Test static block:setIdentity",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_block_references<T,O>(); auto const cases = rotgen::tests::generate_static_block_references<T, O>();
auto process = []<typename D>(D const& d) auto process = []<typename D>(D const& d) {
{ auto [desc, i0, j0] = d;
auto[desc,i0,j0] = d; auto [rows, cols, fn] = desc;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0); auto input = rotgen::extract<D::ni, D::nj>(m, i0, j0);
input.setIdentity(); input.setIdentity();
test_identity(m,i0,j0,D::ni,D::nj); test_identity(m, i0, j0, D::ni, D::nj);
using input_type = decltype(rotgen::extract<D::ni,D::nj>(m, i0, j0)); using input_type = decltype(rotgen::extract<D::ni, D::nj>(m, i0, j0));
auto values = input_type::Identity(); auto values = input_type::Identity();
test_identity(values,0,0,D::ni,D::nj); test_identity(values, 0, 0, D::ni, D::nj);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };
TTS_CASE_TPL("Test dynamic block::setRandom", rotgen::tests::types) TTS_CASE_TPL("Test dynamic block::setRandom",
<typename T, typename O>( tts::type< tts::types<T,O>>) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_block_references<T,O>(); auto const cases = rotgen::tests::generate_block_references<T, O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases) for (auto const& [matrix_desc, i0, j0, ni, nj] : cases)
{ {
auto[rows,cols,fn] = matrix_desc; auto [rows, cols, fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract(m, i0, j0, ni, nj); auto input = rotgen::extract(m, i0, j0, ni, nj);
input.setRandom(); input.setRandom();
test_random(m,i0,j0,ni,nj); test_random(m, i0, j0, ni, nj);
using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj)); using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj));
auto values = input_type::Random(ni,nj); auto values = input_type::Random(ni, nj);
test_random(values,0,0,ni,nj); test_random(values, 0, 0, ni, nj);
} }
}; };
TTS_CASE_TPL("Test static block:setRandom",
TTS_CASE_TPL("Test static block:setRandom", rotgen::tests::types) rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_block_references<T,O>(); auto const cases = rotgen::tests::generate_static_block_references<T, O>();
auto process = []<typename D>(D const& d) auto process = []<typename D>(D const& d) {
{ auto [desc, i0, j0] = d;
auto[desc,i0,j0] = d; auto [rows, cols, fn] = desc;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0); auto input = rotgen::extract<D::ni, D::nj>(m, i0, j0);
input.setRandom(); input.setRandom();
test_random(m,i0,j0,D::ni,D::nj); test_random(m, i0, j0, D::ni, D::nj);
using input_type = decltype(rotgen::extract<D::ni,D::nj>(m, i0, j0)); using input_type = decltype(rotgen::extract<D::ni, D::nj>(m, i0, j0));
auto values = input_type::Random(); auto values = input_type::Random();
test_random(values,0,0,D::ni,D::nj); test_random(values, 0, 0, D::ni, D::nj);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };

View file

@ -9,34 +9,35 @@
#include "unit/common/norms.hpp" #include "unit/common/norms.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic block norm operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic block norm operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_block_references<T,O>(); auto const cases = rotgen::tests::generate_block_references<T, O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases) for (auto const& [matrix_desc, i0, j0, ni, nj] : cases)
{ {
auto[rows,cols,fn] = matrix_desc; auto [rows, cols, fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m); rotgen::tests::prepare(rows, cols, fn, m);
auto input = rotgen::extract(m, i0, j0, ni, nj); auto input = rotgen::extract(m, i0, j0, ni, nj);
rotgen::tests::check_norms_functions(input); rotgen::tests::check_norms_functions(input);
} }
}; };
TTS_CASE_TPL("Test static block norm operations", rotgen::tests::types) TTS_CASE_TPL("Test static block norm operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_block_references<T,O>(); auto const cases = rotgen::tests::generate_static_block_references<T, O>();
auto process = []<typename D>(D const& d) auto process = []<typename D>(D const& d) {
{ auto [desc, i0, j0] = d;
auto[desc,i0,j0] = d; auto [rows, cols, fn] = desc;
auto[rows,cols,fn] = desc; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> m(rows, cols);
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols); rotgen::tests::prepare(rows, cols, fn, m);
rotgen::tests::prepare(rows,cols,fn,m); auto input = rotgen::extract<D::ni, D::nj>(m, i0, j0);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
rotgen::tests::check_norms_functions(input); rotgen::tests::check_norms_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };

View file

@ -9,35 +9,38 @@
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
#include <Eigen/Dense> #include <Eigen/Dense>
template <typename MatrixType, typename T> template<typename MatrixType, typename T>
void test_block_matrix_operations(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct, void test_block_matrix_operations(
auto b_init_fn, auto ops, auto self_ops) rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct,
auto b_init_fn,
auto ops,
auto self_ops)
{ {
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>; using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
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 a(r, c); MatrixType a(r, c);
MatrixType b(r, c); MatrixType b(r, c);
EigenMatrix ref_a(r, c); EigenMatrix ref_a(r, c);
EigenMatrix ref_b(r, c); EigenMatrix ref_b(r, c);
TTS_EXPECT(verify_rotgen_reentrance(ops(a,b))); TTS_EXPECT(verify_rotgen_reentrance(ops(a, b)));
for (rotgen::Index rr = 0; rr < r; ++rr) for (rotgen::Index rr = 0; rr < r; ++rr)
{ {
for (rotgen::Index cc = 0; cc < c; ++cc) for (rotgen::Index cc = 0; cc < c; ++cc)
{ {
ref_a(rr,cc) = a(rr,cc) = static_cast<T>(fn(rr,cc)); ref_a(rr, cc) = a(rr, cc) = static_cast<T>(fn(rr, cc));
ref_b(rr,cc) = b(rr,cc) = static_cast<T>(b_init_fn(rr,cc)); ref_b(rr, cc) = b(rr, cc) = static_cast<T>(b_init_fn(rr, cc));
} }
} }
auto a_block = rotgen::extract(a, i0, j0,ni, nj); auto a_block = rotgen::extract(a, i0, j0, ni, nj);
auto b_block = rotgen::extract(b, i0, j0,ni, nj); auto b_block = rotgen::extract(b, i0, j0, ni, nj);
auto ref_a_block = ref_a.block(i0, j0,ni, nj); auto ref_a_block = ref_a.block(i0, j0, ni, nj);
auto ref_b_block = ref_b.block(i0, j0,ni, nj); auto ref_b_block = ref_b.block(i0, j0, ni, nj);
auto result_block = ops(a_block, b_block); auto result_block = ops(a_block, b_block);
auto ref_result_block = ops(ref_a_block, ref_b_block); auto ref_result_block = ops(ref_a_block, ref_b_block);
@ -46,7 +49,7 @@ void test_block_matrix_operations(rotgen::tests::matrix_block_test_case<MatrixTy
for (rotgen::Index cc = 0; cc < nj; ++cc) for (rotgen::Index cc = 0; cc < nj; ++cc)
TTS_EQUAL(result_block(rr, cc), ref_result_block(rr, cc)); TTS_EQUAL(result_block(rr, cc), ref_result_block(rr, cc));
self_ops(a_block,b_block); self_ops(a_block, b_block);
self_ops(ref_a_block, ref_b_block); self_ops(ref_a_block, ref_b_block);
for (rotgen::Index rr = 0; rr < ni; ++rr) for (rotgen::Index rr = 0; rr < ni; ++rr)
@ -63,26 +66,29 @@ void test_block_matrix_operations(rotgen::tests::matrix_block_test_case<MatrixTy
} }
} }
template <typename MatrixType, typename T> template<typename MatrixType, typename T>
void test_block_scalar_operations(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct, void test_block_scalar_operations(
auto scalar, auto ops, auto self_ops) rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct,
auto scalar,
auto ops,
auto self_ops)
{ {
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>; using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
auto[d,i0,j0,ni,nj] = matrix_construct; auto [d, i0, j0, ni, nj] = matrix_construct;
auto[rows,cols,fn] = d; auto [rows, cols, fn] = d;
MatrixType a(rows, cols); MatrixType a(rows, cols);
EigenMatrix ref_a(rows, cols); EigenMatrix ref_a(rows, cols);
TTS_EXPECT(verify_rotgen_reentrance(ops(a,scalar))); TTS_EXPECT(verify_rotgen_reentrance(ops(a, scalar)));
for (rotgen::Index r = 0; r < rows; ++r) for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(fn(r, c)); ref_a(r, c) = a(r, c) = static_cast<T>(fn(r, c));
auto a_block = rotgen::extract(a, i0, j0,ni, nj); auto a_block = rotgen::extract(a, i0, j0, ni, nj);
auto ref_a_block = ref_a.block(i0, j0,ni, nj); auto ref_a_block = ref_a.block(i0, j0, ni, nj);
auto result = ops(a_block, scalar); auto result = ops(a_block, scalar);
auto ref_result = ops(ref_a_block, scalar); auto ref_result = ops(ref_a_block, scalar);
@ -91,7 +97,7 @@ void test_block_scalar_operations(rotgen::tests::matrix_block_test_case<MatrixTy
for (rotgen::Index c = 0; c < nj; ++c) for (rotgen::Index c = 0; c < nj; ++c)
TTS_EQUAL(result(r, c), ref_result(r, c)); TTS_EQUAL(result(r, c), ref_result(r, c));
self_ops(a_block,scalar); self_ops(a_block, scalar);
self_ops(ref_a_block, scalar); self_ops(ref_a_block, scalar);
for (rotgen::Index r = 0; r < ni; ++r) for (rotgen::Index r = 0; r < ni; ++r)
@ -99,18 +105,18 @@ void test_block_scalar_operations(rotgen::tests::matrix_block_test_case<MatrixTy
TTS_EQUAL(a_block(r, c), ref_a_block(r, c)); TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (rotgen::Index r = 0; r < rows; ++r) for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c) TTS_EQUAL(a(r, c), ref_a(r, c));
TTS_EQUAL(a(r, c), ref_a(r, c));
} }
template <typename MatrixType, typename T> template<typename MatrixType, typename T>
void test_scalar_block_multiplications(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct, void test_scalar_block_multiplications(
T scalar) rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct,
T scalar)
{ {
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>; using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
auto[d,i0,j0,ni,nj] = matrix_construct; auto [d, i0, j0, ni, nj] = matrix_construct;
auto[rows,cols,fn] = d; auto [rows, cols, fn] = d;
MatrixType a(rows, cols); MatrixType a(rows, cols);
EigenMatrix ref_a(rows, cols); EigenMatrix ref_a(rows, cols);
@ -120,12 +126,10 @@ void test_scalar_block_multiplications(rotgen::tests::matrix_block_test_case<Mat
for (rotgen::Index r = 0; r < rows; ++r) for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(fn(r, c)); ref_a(r, c) = a(r, c) = static_cast<T>(fn(r, c));
auto a_block = rotgen::extract(a, i0, j0, auto a_block = rotgen::extract(a, i0, j0, ni, nj);
ni, nj); auto ref_a_block = ref_a.block(i0, j0, ni, nj);
auto ref_a_block = ref_a.block(i0, j0,
ni, nj);
auto a_scalar_multiplication = a_block * scalar; auto a_scalar_multiplication = a_block * scalar;
auto scalar_a_multiplication = scalar * a_block; auto scalar_a_multiplication = scalar * a_block;
@ -136,8 +140,10 @@ void test_scalar_block_multiplications(rotgen::tests::matrix_block_test_case<Mat
{ {
for (rotgen::Index c = 0; c < nj; ++c) for (rotgen::Index c = 0; c < nj; ++c)
{ {
TTS_EQUAL(a_scalar_multiplication (r, c), a_scalar_multiplication_ref(r, c)); TTS_EQUAL(a_scalar_multiplication(r, c),
TTS_EQUAL(scalar_a_multiplication(r, c), scalar_a_multiplication_ref(r, c)); a_scalar_multiplication_ref(r, c));
TTS_EQUAL(scalar_a_multiplication(r, c),
scalar_a_multiplication_ref(r, c));
} }
} }
@ -149,22 +155,21 @@ void test_scalar_block_multiplications(rotgen::tests::matrix_block_test_case<Mat
TTS_EQUAL(a_block(r, c), ref_a_block(r, c)); TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (rotgen::Index r = 0; r < rows; ++r) for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c) TTS_EQUAL(a(r, c), ref_a(r, c));
TTS_EQUAL(a(r, c), ref_a(r, c));
} }
template <typename MatrixType, typename T> template<typename MatrixType, typename T>
void test_block_multiplication(rotgen::tests::matrix_block_test_case<MatrixType> const& a_matrix_construct, void test_block_multiplication(
rotgen::tests::matrix_block_test_case<MatrixType> const& b_matrix_construct) rotgen::tests::matrix_block_test_case<MatrixType> const& a_matrix_construct,
rotgen::tests::matrix_block_test_case<MatrixType> const& b_matrix_construct)
{ {
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>; using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
auto[a_d,a_i0,a_j0,a_ni,a_nj] = a_matrix_construct; auto [a_d, a_i0, a_j0, a_ni, a_nj] = a_matrix_construct;
auto[a_rows,a_cols,a_fn] = a_d; auto [a_rows, a_cols, a_fn] = a_d;
auto[b_d,b_i0,b_j0,b_ni,b_nj] = b_matrix_construct;
auto[b_rows,b_cols,b_fn] = b_d;
auto [b_d, b_i0, b_j0, b_ni, b_nj] = b_matrix_construct;
auto [b_rows, b_cols, b_fn] = b_d;
MatrixType a(a_rows, a_cols); MatrixType a(a_rows, a_cols);
MatrixType b(b_rows, b_cols); MatrixType b(b_rows, b_cols);
@ -173,17 +178,16 @@ void test_block_multiplication(rotgen::tests::matrix_block_test_case<MatrixType>
for (rotgen::Index r = 0; r < a_rows; ++r) for (rotgen::Index r = 0; r < a_rows; ++r)
for (rotgen::Index c = 0; c < a_cols; ++c) for (rotgen::Index c = 0; c < a_cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(a_fn(r, c)); ref_a(r, c) = a(r, c) = static_cast<T>(a_fn(r, c));
for (rotgen::Index r = 0; r < b_rows; ++r) for (rotgen::Index r = 0; r < b_rows; ++r)
for (rotgen::Index c = 0; c < b_cols; ++c) for (rotgen::Index c = 0; c < b_cols; ++c)
ref_b(r,c) = b(r,c) = static_cast<T>(b_fn(r, c)); ref_b(r, c) = b(r, c) = static_cast<T>(b_fn(r, c));
auto a_block = rotgen::extract(a, a_i0, a_j0, a_ni, a_nj);
auto a_block = rotgen::extract(a, a_i0, a_j0,a_ni, a_nj); auto b_block = rotgen::extract(b, b_i0, b_j0, b_ni, b_nj);
auto b_block = rotgen::extract(b, b_i0, b_j0,b_ni, b_nj); auto ref_a_block = ref_a.block(a_i0, a_j0, a_ni, a_nj);
auto ref_a_block = ref_a.block(a_i0, a_j0,a_ni, a_nj); auto ref_b_block = ref_b.block(b_i0, b_j0, b_ni, b_nj);
auto ref_b_block = ref_b.block(b_i0, b_j0,b_ni, b_nj);
TTS_EXPECT(verify_rotgen_reentrance(a_block * b_block)); TTS_EXPECT(verify_rotgen_reentrance(a_block * b_block));
@ -192,7 +196,7 @@ void test_block_multiplication(rotgen::tests::matrix_block_test_case<MatrixType>
for (rotgen::Index r = 0; r < a_ni; ++r) for (rotgen::Index r = 0; r < a_ni; ++r)
for (rotgen::Index c = 0; c < a_nj; ++c) for (rotgen::Index c = 0; c < a_nj; ++c)
TTS_EQUAL(a_b_product_original (r, c), a_b_product_ref(r, c)); TTS_EQUAL(a_b_product_original(r, c), a_b_product_ref(r, c));
a_block *= b_block; a_block *= b_block;
ref_a_block *= ref_b_block; ref_a_block *= ref_b_block;
@ -202,106 +206,162 @@ void test_block_multiplication(rotgen::tests::matrix_block_test_case<MatrixType>
TTS_EQUAL(a_block(r, c), ref_a_block(r, c)); TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (rotgen::Index r = 0; r < a_rows; ++r) for (rotgen::Index r = 0; r < a_rows; ++r)
for (rotgen::Index c = 0; c < a_cols; ++c) for (rotgen::Index c = 0; c < a_cols; ++c) TTS_EQUAL(a(r, c), ref_a(r, c));
TTS_EQUAL(a(r, c), ref_a(r, c));
for (rotgen::Index r = 0; r < b_rows; ++r) for (rotgen::Index r = 0; r < b_rows; ++r)
for (rotgen::Index c = 0; c < b_cols; ++c) for (rotgen::Index c = 0; c < b_cols; ++c) TTS_EQUAL(b(r, c), ref_b(r, c));
TTS_EQUAL(b(r, c), ref_b(r, c));
} }
// Basic initializers // Basic initializers
inline constexpr auto init_a = [](auto r, auto c) { return 9.9*r*r*r - 6*c -12; }; inline constexpr auto init_a = [](auto r, auto c) {
inline constexpr auto init_b = [](auto r, auto c) { return 3.1*r + 4.2*c - 12.3; }; return 9.9 * r * r * r - 6 * c - 12;
inline constexpr auto init_0 = [](auto , auto ) { return 0; }; };
inline constexpr auto init_b = [](auto r, auto c) {
return 3.1 * r + 4.2 * c - 12.3;
};
inline constexpr auto init_0 = [](auto, auto) { return 0; };
TTS_CASE_TPL("Check block addition", rotgen::tests::types) TTS_CASE_TPL("Check block addition",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto op = [](auto a, auto b) { return a + b; }; auto op = [](auto a, auto b) { return a + b; };
auto s_op = [](auto& a, auto b) { return a += b; }; auto s_op = [](auto& a, auto b) { return a += b; };
test_block_matrix_operations<mat_t, T>({{ 1, 1, init_a}, 0, 0, 1, 1}, init_b, op, s_op); test_block_matrix_operations<mat_t, T>({{1, 1, init_a}, 0, 0, 1, 1}, init_b,
test_block_matrix_operations<mat_t, T>({{13, 15, init_a}, 1, 2, 3, 4}, init_b, op, s_op); op, s_op);
test_block_matrix_operations<mat_t, T>({{ 5, 9, init_a}, 2, 2, 2, 2}, init_b, op, s_op); test_block_matrix_operations<mat_t, T>({{13, 15, init_a}, 1, 2, 3, 4}, init_b,
test_block_matrix_operations<mat_t, T>({{15, 15, init_a}, 3, 4, 5, 5}, init_b, op, s_op); op, s_op);
test_block_matrix_operations<mat_t, T>({{ 5, 5, init_b}, 1, 0, 3, 2}, init_a, op, s_op); test_block_matrix_operations<mat_t, T>({{5, 9, init_a}, 2, 2, 2, 2}, init_b,
test_block_matrix_operations<mat_t, T>({{10, 1, init_a}, 0, 0, 5, 1}, init_b, op, s_op); op, s_op);
test_block_matrix_operations<mat_t, T>({{ 1, 10, init_a}, 0, 0, 1, 5}, init_b, op, s_op); test_block_matrix_operations<mat_t, T>({{15, 15, init_a}, 3, 4, 5, 5}, init_b,
test_block_matrix_operations<mat_t, T>({{21, 5, init_0}, 4, 4, 10, 1}, init_b, op, s_op); op, s_op);
test_block_matrix_operations<mat_t, T>({{11, 7, init_a}, 2, 0, 7, 5}, init_0, op, s_op); test_block_matrix_operations<mat_t, T>({{5, 5, init_b}, 1, 0, 3, 2}, init_a,
op, s_op);
test_block_matrix_operations<mat_t, T>({{10, 1, init_a}, 0, 0, 5, 1}, init_b,
op, s_op);
test_block_matrix_operations<mat_t, T>({{1, 10, init_a}, 0, 0, 1, 5}, init_b,
op, s_op);
test_block_matrix_operations<mat_t, T>({{21, 5, init_0}, 4, 4, 10, 1}, init_b,
op, s_op);
test_block_matrix_operations<mat_t, T>({{11, 7, init_a}, 2, 0, 7, 5}, init_0,
op, s_op);
}; };
TTS_CASE_TPL("Check block subtraction", rotgen::tests::types) TTS_CASE_TPL("Check block subtraction",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto op = [](auto a, auto b) { return a - b; }; auto op = [](auto a, auto b) { return a - b; };
auto s_op = [](auto& a, auto b) { return a -= b; }; auto s_op = [](auto& a, auto b) { return a -= b; };
test_block_matrix_operations<mat_t, T>({{ 1, 1, init_a}, 0, 0, 1, 1}, init_b, op, s_op); test_block_matrix_operations<mat_t, T>({{1, 1, init_a}, 0, 0, 1, 1}, init_b,
test_block_matrix_operations<mat_t, T>({{ 1, 1, init_a}, 0, 0, 1, 1}, init_b, op, s_op); op, s_op);
test_block_matrix_operations<mat_t, T>({{13, 15, init_a}, 1, 2, 3, 4}, init_b, op, s_op); test_block_matrix_operations<mat_t, T>({{1, 1, init_a}, 0, 0, 1, 1}, init_b,
test_block_matrix_operations<mat_t, T>({{ 5, 9, init_a}, 2, 2, 2, 2}, init_b, op, s_op); op, s_op);
test_block_matrix_operations<mat_t, T>({{15, 15, init_a}, 3, 4, 5, 5}, init_b, op, s_op); test_block_matrix_operations<mat_t, T>({{13, 15, init_a}, 1, 2, 3, 4}, init_b,
test_block_matrix_operations<mat_t, T>({{ 5, 5, init_b}, 1, 0, 3, 2}, init_a, op, s_op); op, s_op);
test_block_matrix_operations<mat_t, T>({{10, 1, init_a}, 0, 0, 5, 1}, init_b, op, s_op); test_block_matrix_operations<mat_t, T>({{5, 9, init_a}, 2, 2, 2, 2}, init_b,
test_block_matrix_operations<mat_t, T>({{ 1, 10, init_a}, 0, 0, 1, 5}, init_b,op, s_op); op, s_op);
test_block_matrix_operations<mat_t, T>({{21 , 5, init_0}, 4, 4, 10, 1}, init_b, op, s_op); test_block_matrix_operations<mat_t, T>({{15, 15, init_a}, 3, 4, 5, 5}, init_b,
test_block_matrix_operations<mat_t, T>({{11 , 7, init_a}, 2, 0, 7, 5}, init_0, op, s_op); op, s_op);
test_block_matrix_operations<mat_t, T>({{5, 5, init_b}, 1, 0, 3, 2}, init_a,
op, s_op);
test_block_matrix_operations<mat_t, T>({{10, 1, init_a}, 0, 0, 5, 1}, init_b,
op, s_op);
test_block_matrix_operations<mat_t, T>({{1, 10, init_a}, 0, 0, 1, 5}, init_b,
op, s_op);
test_block_matrix_operations<mat_t, T>({{21, 5, init_0}, 4, 4, 10, 1}, init_b,
op, s_op);
test_block_matrix_operations<mat_t, T>({{11, 7, init_a}, 2, 0, 7, 5}, init_0,
op, s_op);
}; };
TTS_CASE_TPL("Check block multiplications", rotgen::tests::types) TTS_CASE_TPL("Check block multiplications",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto init_id = [](rotgen::Index r, rotgen::Index c) { return r == c ? 1 : 0; }; auto init_id = [](rotgen::Index r, rotgen::Index c) {
return r == c ? 1 : 0;
};
test_block_multiplication<mat_t, T>({{ 1, 1, init_a }, 0, 0, 1, 1}, {{ 1, 1, init_b }, 0, 0, 1, 1}); test_block_multiplication<mat_t, T>({{1, 1, init_a}, 0, 0, 1, 1},
test_block_multiplication<mat_t, T>({{13, 15, init_b }, 1, 2, 4, 4}, {{13, 15, init_b }, 0, 1, 4, 4}); {{1, 1, init_b}, 0, 0, 1, 1});
test_block_multiplication<mat_t, T>({{ 6, 9, init_a }, 2, 2, 2, 2}, {{ 5, 9, init_b }, 2, 2, 2, 2}); test_block_multiplication<mat_t, T>({{13, 15, init_b}, 1, 2, 4, 4},
test_block_multiplication<mat_t, T>({{15, 15, init_a }, 3, 4, 5, 5}, {{15, 15, init_b }, 0, 0, 5, 5}); {{13, 15, init_b}, 0, 1, 4, 4});
test_block_multiplication<mat_t, T>({{ 5, 5, init_b }, 1, 0, 3, 3}, {{ 5, 5, init_a }, 0, 0, 3, 3}); test_block_multiplication<mat_t, T>({{6, 9, init_a}, 2, 2, 2, 2},
test_block_multiplication<mat_t, T>({{11, 3, init_id}, 2, 0, 2, 2}, {{18, 7, init_a }, 2, 0, 2, 2}); {{5, 9, init_b}, 2, 2, 2, 2});
test_block_multiplication<mat_t, T>({{10, 1, init_a }, 0, 0, 1, 1}, {{10, 1, init_a }, 0, 0, 1, 1}); test_block_multiplication<mat_t, T>({{15, 15, init_a}, 3, 4, 5, 5},
test_block_multiplication<mat_t, T>({{ 1, 10, init_a }, 0, 0, 1, 1}, {{ 1, 10, init_id}, 0, 0, 1, 1}); {{15, 15, init_b}, 0, 0, 5, 5});
test_block_multiplication<mat_t, T>({{21, 5, init_0 }, 1, 1, 3, 3}, {{12, 7, init_0 }, 4, 4, 3, 3}); test_block_multiplication<mat_t, T>({{5, 5, init_b}, 1, 0, 3, 3},
test_block_multiplication<mat_t, T>({{11, 7, init_a }, 2, 0, 7, 7}, {{11, 11, init_a }, 2, 1, 7, 7}); {{5, 5, init_a}, 0, 0, 3, 3});
test_block_multiplication<mat_t, T>({{11, 7, init_a }, 2, 0, 5, 5}, {{11, 12, init_id}, 0, 0, 5, 5}); test_block_multiplication<mat_t, T>({{11, 3, init_id}, 2, 0, 2, 2},
{{18, 7, init_a}, 2, 0, 2, 2});
test_block_multiplication<mat_t, T>({{10, 1, init_a}, 0, 0, 1, 1},
{{10, 1, init_a}, 0, 0, 1, 1});
test_block_multiplication<mat_t, T>({{1, 10, init_a}, 0, 0, 1, 1},
{{1, 10, init_id}, 0, 0, 1, 1});
test_block_multiplication<mat_t, T>({{21, 5, init_0}, 1, 1, 3, 3},
{{12, 7, init_0}, 4, 4, 3, 3});
test_block_multiplication<mat_t, T>({{11, 7, init_a}, 2, 0, 7, 7},
{{11, 11, init_a}, 2, 1, 7, 7});
test_block_multiplication<mat_t, T>({{11, 7, init_a}, 2, 0, 5, 5},
{{11, 12, init_id}, 0, 0, 5, 5});
}; };
TTS_CASE_TPL("Check block multiplication with scalar", rotgen::tests::types) TTS_CASE_TPL("Check block multiplication with scalar",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
test_scalar_block_multiplications<mat_t, T>({{ 1, 1, init_a}, 0, 0, 1, 1}, T{ 3.5}); test_scalar_block_multiplications<mat_t, T>({{1, 1, init_a}, 0, 0, 1, 1},
test_scalar_block_multiplications<mat_t, T>({{13, 15, init_a}, 1, 2, 3, 4}, T{ 0.}); T{3.5});
test_scalar_block_multiplications<mat_t, T>({{ 5 , 9, init_a}, 2, 2, 2, 2}, T{-2.5}); test_scalar_block_multiplications<mat_t, T>({{13, 15, init_a}, 1, 2, 3, 4},
test_scalar_block_multiplications<mat_t, T>({{15, 15, init_a}, 3, 4, 5, 5}, T{ 42. }); T{0.});
test_scalar_block_multiplications<mat_t, T>({{ 5, 5, init_b}, 1, 0, 3, 2}, T{-5. }); test_scalar_block_multiplications<mat_t, T>({{5, 9, init_a}, 2, 2, 2, 2},
test_scalar_block_multiplications<mat_t, T>({{10, 1, init_a}, 0, 0, 5, 1}, T{ 1. }); T{-2.5});
test_scalar_block_multiplications<mat_t, T>({{ 1, 10, init_a}, 0, 0, 1, 5}, T{ 6. }); test_scalar_block_multiplications<mat_t, T>({{15, 15, init_a}, 3, 4, 5, 5},
test_scalar_block_multiplications<mat_t, T>({{21, 5, init_0}, 4, 4, 10, 1}, T{ 10.1}); T{42.});
test_scalar_block_multiplications<mat_t, T>({{11, 7, init_a}, 2, 0, 7, 5}, T{-0.5}); test_scalar_block_multiplications<mat_t, T>({{5, 5, init_b}, 1, 0, 3, 2},
T{-5.});
test_scalar_block_multiplications<mat_t, T>({{10, 1, init_a}, 0, 0, 5, 1},
T{1.});
test_scalar_block_multiplications<mat_t, T>({{1, 10, init_a}, 0, 0, 1, 5},
T{6.});
test_scalar_block_multiplications<mat_t, T>({{21, 5, init_0}, 4, 4, 10, 1},
T{10.1});
test_scalar_block_multiplications<mat_t, T>({{11, 7, init_a}, 2, 0, 7, 5},
T{-0.5});
}; };
TTS_CASE_TPL("Check block division with scalar", rotgen::tests::types) TTS_CASE_TPL("Check block division with scalar",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto op = [](auto a, auto b) { return a / b; }; auto op = [](auto a, auto b) { return a / b; };
auto s_op = [](auto& a, auto b) { return a /= b; }; auto s_op = [](auto& a, auto b) { return a /= b; };
test_block_scalar_operations<mat_t, T>({{ 1, 1, init_a}, 0, 0, 1, 1}, T{ 3.5}, op, s_op); test_block_scalar_operations<mat_t, T>({{1, 1, init_a}, 0, 0, 1, 1}, T{3.5},
test_block_scalar_operations<mat_t, T>({{13, 15, init_a}, 1, 2, 3, 4}, T{-2.5}, op, s_op); op, s_op);
test_block_scalar_operations<mat_t, T>({{ 5, 9, init_a}, 2, 2, 2, 2}, T{ 42. }, op, s_op); test_block_scalar_operations<mat_t, T>({{13, 15, init_a}, 1, 2, 3, 4},
test_block_scalar_operations<mat_t, T>({{15, 15, init_a}, 3, 4, 5, 5}, T{-5. }, op, s_op); T{-2.5}, op, s_op);
test_block_scalar_operations<mat_t, T>({{ 5, 5, init_b}, 1, 0, 3, 2}, T{ 1. }, op, s_op); test_block_scalar_operations<mat_t, T>({{5, 9, init_a}, 2, 2, 2, 2}, T{42.},
test_block_scalar_operations<mat_t, T>({{10, 1, init_a}, 0, 0, 5, 1}, T{ 0. }, op, s_op); op, s_op);
test_block_scalar_operations<mat_t, T>({{ 1, 10, init_a}, 0, 0, 1, 5}, T{ 6. }, op, s_op); test_block_scalar_operations<mat_t, T>({{15, 15, init_a}, 3, 4, 5, 5}, T{-5.},
test_block_scalar_operations<mat_t, T>({{21, 5, init_0}, 4, 4, 10, 1}, T{ 10.}, op, s_op); op, s_op);
test_block_scalar_operations<mat_t, T>({{11, 7, init_a}, 2, 0, 7, 5}, T{-0.5}, op, s_op); test_block_scalar_operations<mat_t, T>({{5, 5, init_b}, 1, 0, 3, 2}, T{1.},
op, s_op);
test_block_scalar_operations<mat_t, T>({{10, 1, init_a}, 0, 0, 5, 1}, T{0.},
op, s_op);
test_block_scalar_operations<mat_t, T>({{1, 10, init_a}, 0, 0, 1, 5}, T{6.},
op, s_op);
test_block_scalar_operations<mat_t, T>({{21, 5, init_0}, 4, 4, 10, 1}, T{10.},
op, s_op);
test_block_scalar_operations<mat_t, T>({{11, 7, init_a}, 2, 0, 7, 5}, T{-0.5},
op, s_op);
}; };

View file

@ -12,21 +12,21 @@
namespace rotgen::tests namespace rotgen::tests
{ {
template<typename T> template<typename T> void check_shape_functions(T original)
void check_shape_functions(T original)
{ {
using mat_t = matrix<typename T::value_type,Dynamic,Dynamic,T::storage_order>; using mat_t =
matrix<typename T::value_type, Dynamic, Dynamic, T::storage_order>;
mat_t result(original.cols(), original.rows()); mat_t result(original.cols(), original.rows());
prepare([&](auto r, auto c) { return original(c,r); },result); prepare([&](auto r, auto c) { return original(c, r); }, result);
TTS_EQUAL(transpose(original) , result ); TTS_EQUAL(transpose(original), result);
TTS_EQUAL(conjugate(original) , original); TTS_EQUAL(conjugate(original), original);
TTS_EQUAL(adjoint(original) , result ); TTS_EQUAL(adjoint(original), result);
if constexpr(T::is_defined_static) if constexpr (T::is_defined_static)
{ {
if constexpr(T::RowsAtCompileTime == T::ColsAtCompileTime) if constexpr (T::RowsAtCompileTime == T::ColsAtCompileTime)
{ {
mat_t ref = original; mat_t ref = original;
transposeInPlace(original); transposeInPlace(original);
@ -49,37 +49,37 @@ namespace rotgen::tests
} }
} }
if constexpr(!rotgen::use_expression_templates) if constexpr (!rotgen::use_expression_templates)
{ {
TTS_EXPECT(verify_rotgen_reentrance( original.transpose()) ); TTS_EXPECT(verify_rotgen_reentrance(original.transpose()));
TTS_EXPECT(verify_rotgen_reentrance( original.conjugate()) ); TTS_EXPECT(verify_rotgen_reentrance(original.conjugate()));
TTS_EXPECT(verify_rotgen_reentrance( original.adjoint()) ); TTS_EXPECT(verify_rotgen_reentrance(original.adjoint()));
} }
} }
template<typename T> template<typename T> void check_reduction_functions(T const& input)
void check_reduction_functions(const T& input)
{ {
using EigenMatrix = Eigen::Matrix<typename T::value_type, Eigen::Dynamic, Eigen::Dynamic>; using EigenMatrix =
Eigen::Matrix<typename T::value_type, Eigen::Dynamic, Eigen::Dynamic>;
EigenMatrix ref(input.rows(), input.cols()); EigenMatrix ref(input.rows(), input.cols());
prepare([&](auto r, auto c) { return input(r,c); }, ref); prepare([&](auto r, auto c) { return input(r, c); }, ref);
TTS_ULP_EQUAL(sum(input) , ref.sum() , 2); TTS_ULP_EQUAL(sum(input), ref.sum(), 2);
TTS_ULP_EQUAL(prod(input) , ref.prod(), 2); TTS_ULP_EQUAL(prod(input), ref.prod(), 2);
TTS_ULP_EQUAL(mean(input) , ref.mean(), 2); TTS_ULP_EQUAL(mean(input), ref.mean(), 2);
TTS_EQUAL(trace(input) , ref.trace()); TTS_EQUAL(trace(input), ref.trace());
TTS_EQUAL(minCoeff(input) , ref.minCoeff()); TTS_EQUAL(minCoeff(input), ref.minCoeff());
TTS_EQUAL(maxCoeff(input) , ref.maxCoeff()); TTS_EQUAL(maxCoeff(input), ref.maxCoeff());
{ {
int row, col, ref_row, ref_col; int row, col, ref_row, ref_col;
TTS_EQUAL(minCoeff(input,&row, &col), ref.minCoeff(&ref_row, &ref_col)); TTS_EQUAL(minCoeff(input, &row, &col), ref.minCoeff(&ref_row, &ref_col));
TTS_EQUAL(row, ref_row); TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col); TTS_EQUAL(col, ref_col);
TTS_EQUAL(maxCoeff(input,&row, &col), ref.maxCoeff(&ref_row, &ref_col)); TTS_EQUAL(maxCoeff(input, &row, &col), ref.maxCoeff(&ref_row, &ref_col));
TTS_EQUAL(row, ref_row); TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col); TTS_EQUAL(col, ref_col);
} }

View file

@ -12,81 +12,82 @@
namespace rotgen::tests namespace rotgen::tests
{ {
template<typename T> template<typename T> void check_cwise_functions(T const& input)
void check_cwise_functions(const T& input)
{ {
using EigenMatrix = Eigen::Matrix<typename T::value_type, Eigen::Dynamic, Eigen::Dynamic>; using EigenMatrix =
using mat_t = matrix<typename T::value_type,Dynamic,Dynamic,T::storage_order>; Eigen::Matrix<typename T::value_type, Eigen::Dynamic, Eigen::Dynamic>;
using mat_t =
matrix<typename T::value_type, Dynamic, Dynamic, T::storage_order>;
TTS_WHEN("Unary Cwise operations") TTS_WHEN("Unary Cwise operations")
{ {
EigenMatrix e_ref(input.rows(), input.cols()); EigenMatrix e_ref(input.rows(), input.cols());
prepare([&](auto r, auto c) { return input(r,c); }, e_ref); prepare([&](auto r, auto c) { return input(r, c); }, e_ref);
mat_t ref(input.rows(), input.cols()); mat_t ref(input.rows(), input.cols());
TTS_AND_THEN(".cwiseAbs") TTS_AND_THEN(".cwiseAbs")
{ {
e_ref = e_ref.cwiseAbs(); e_ref = e_ref.cwiseAbs();
prepare([&](auto r, auto c) { return e_ref(r,c); }, ref); prepare([&](auto r, auto c) { return e_ref(r, c); }, ref);
TTS_EQUAL(input.cwiseAbs(), ref); TTS_EQUAL(input.cwiseAbs(), ref);
} }
TTS_AND_THEN(".cwiseAbs2") TTS_AND_THEN(".cwiseAbs2")
{ {
e_ref = e_ref.cwiseAbs2(); e_ref = e_ref.cwiseAbs2();
prepare([&](auto r, auto c) { return e_ref(r,c); }, ref); prepare([&](auto r, auto c) { return e_ref(r, c); }, ref);
TTS_EQUAL(input.cwiseAbs2(), ref); TTS_EQUAL(input.cwiseAbs2(), ref);
} }
TTS_AND_THEN(".cwiseInverse") TTS_AND_THEN(".cwiseInverse")
{ {
e_ref = e_ref.cwiseInverse(); e_ref = e_ref.cwiseInverse();
prepare([&](auto r, auto c) { return e_ref(r,c); }, ref); prepare([&](auto r, auto c) { return e_ref(r, c); }, ref);
TTS_EQUAL(input.cwiseInverse(), ref); TTS_EQUAL(input.cwiseInverse(), ref);
} }
TTS_AND_THEN(".cwiseSqrt") TTS_AND_THEN(".cwiseSqrt")
{ {
e_ref = e_ref.cwiseAbs().cwiseSqrt(); e_ref = e_ref.cwiseAbs().cwiseSqrt();
auto mat = input.cwiseAbs(); auto mat = input.cwiseAbs();
auto proper_input = mat.cwiseSqrt(); auto proper_input = mat.cwiseSqrt();
for(rotgen::Index r=0;r<input.rows();++r) for (rotgen::Index r = 0; r < input.rows(); ++r)
for(rotgen::Index c=0;c<input.cols();++c) for (rotgen::Index c = 0; c < input.cols(); ++c)
TTS_ULP_EQUAL(proper_input(r,c), e_ref(r,c), 1); TTS_ULP_EQUAL(proper_input(r, c), e_ref(r, c), 1);
} }
TTS_AND_THEN("abs()") TTS_AND_THEN("abs()")
{ {
e_ref = e_ref.cwiseAbs(); e_ref = e_ref.cwiseAbs();
prepare([&](auto r, auto c) { return e_ref(r,c); }, ref); prepare([&](auto r, auto c) { return e_ref(r, c); }, ref);
TTS_EQUAL(rotgen::abs(input), ref); TTS_EQUAL(rotgen::abs(input), ref);
} }
TTS_AND_THEN("abs2()") TTS_AND_THEN("abs2()")
{ {
e_ref = e_ref.cwiseAbs2(); e_ref = e_ref.cwiseAbs2();
prepare([&](auto r, auto c) { return e_ref(r,c); }, ref); prepare([&](auto r, auto c) { return e_ref(r, c); }, ref);
TTS_EQUAL(rotgen::abs2(input), ref); TTS_EQUAL(rotgen::abs2(input), ref);
} }
TTS_AND_THEN("rec") TTS_AND_THEN("rec")
{ {
e_ref = e_ref.cwiseInverse(); e_ref = e_ref.cwiseInverse();
prepare([&](auto r, auto c) { return e_ref(r,c); }, ref); prepare([&](auto r, auto c) { return e_ref(r, c); }, ref);
TTS_EQUAL(rotgen::rec(input), ref); TTS_EQUAL(rotgen::rec(input), ref);
} }
TTS_AND_THEN("sqrt") TTS_AND_THEN("sqrt")
{ {
e_ref = e_ref.cwiseAbs().cwiseSqrt(); e_ref = e_ref.cwiseAbs().cwiseSqrt();
auto mat = input.cwiseAbs(); auto mat = input.cwiseAbs();
auto proper_input = rotgen::sqrt(mat); auto proper_input = rotgen::sqrt(mat);
for(rotgen::Index r=0;r<input.rows();++r) for (rotgen::Index r = 0; r < input.rows(); ++r)
for(rotgen::Index c=0;c<input.cols();++c) for (rotgen::Index c = 0; c < input.cols(); ++c)
TTS_ULP_EQUAL(proper_input(r,c), e_ref(r,c), 1); TTS_ULP_EQUAL(proper_input(r, c), e_ref(r, c), 1);
} }
} }
} }

View file

@ -12,27 +12,29 @@
namespace rotgen::tests namespace rotgen::tests
{ {
template<typename T> template<typename T> void check_norms_functions(T const& input)
void check_norms_functions(const T& input)
{ {
using EigenMatrix = Eigen::Matrix<typename T::value_type, Eigen::Dynamic, Eigen::Dynamic>; using EigenMatrix =
Eigen::Matrix<typename T::value_type, Eigen::Dynamic, Eigen::Dynamic>;
EigenMatrix ref(input.rows(), input.cols()); EigenMatrix ref(input.rows(), input.cols());
prepare([&](auto r, auto c) { return input(r,c); }, ref); prepare([&](auto r, auto c) { return input(r, c); }, ref);
TTS_EQUAL(rotgen::norm(input) , ref.norm()); TTS_EQUAL(rotgen::norm(input), ref.norm());
TTS_EQUAL(rotgen::squaredNorm(input) , ref.squaredNorm()); TTS_EQUAL(rotgen::squaredNorm(input), ref.squaredNorm());
TTS_EQUAL(rotgen::lpNorm<1>(input) , ref.template lpNorm<1>()); TTS_EQUAL(rotgen::lpNorm<1>(input), ref.template lpNorm<1>());
TTS_EQUAL(rotgen::lpNorm<2>(input) , ref.template lpNorm<2>()); TTS_EQUAL(rotgen::lpNorm<2>(input), ref.template lpNorm<2>());
TTS_EQUAL(rotgen::lpNorm<rotgen::Infinity>(input) , ref.template lpNorm<Eigen::Infinity>()); TTS_EQUAL(rotgen::lpNorm<rotgen::Infinity>(input),
ref.template lpNorm<Eigen::Infinity>());
if constexpr(T::IsVectorAtCompileTime) if constexpr (T::IsVectorAtCompileTime)
{ {
EigenMatrix e_norm = ref.normalized(); EigenMatrix e_norm = ref.normalized();
using mat_t = rotgen::matrix<typename T::value_type,rotgen::Dynamic,rotgen::Dynamic,T::storage_order>; using mat_t = rotgen::matrix<typename T::value_type, rotgen::Dynamic,
rotgen::Dynamic, T::storage_order>;
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(rotgen::normalized(input), norm_ref); TTS_EQUAL(rotgen::normalized(input), norm_ref);

View file

@ -15,26 +15,25 @@ namespace rotgen::tests
{ {
struct matrix_descriptor struct matrix_descriptor
{ {
rotgen::Index rows, cols; rotgen::Index rows, cols;
std::function<double(std::size_t,std::size_t)> init_fn; std::function<double(std::size_t, std::size_t)> init_fn;
}; };
template<rotgen::Index Rows, rotgen::Index Cols> template<rotgen::Index Rows, rotgen::Index Cols>
struct static_matrix_descriptor struct static_matrix_descriptor
{ {
static constexpr rotgen::Index rows = Rows; static constexpr rotgen::Index rows = Rows;
static constexpr rotgen::Index cols = Cols; static constexpr rotgen::Index cols = Cols;
std::function<double(std::size_t,std::size_t)> init_fn; std::function<double(std::size_t, std::size_t)> init_fn;
}; };
template<typename MatrixType> template<typename MatrixType> struct matrix_block_test_case
struct matrix_block_test_case
{ {
matrix_descriptor matrix_desc; matrix_descriptor matrix_desc;
rotgen::Index i0, j0, ni, nj; rotgen::Index i0, j0, ni, nj;
}; };
template<typename MatrixType, rotgen::Index NI, rotgen::Index NJ> template<typename MatrixType, rotgen::Index NI, rotgen::Index NJ>
struct static_matrix_block_test_case struct static_matrix_block_test_case
{ {
matrix_descriptor matrix_desc; matrix_descriptor matrix_desc;
@ -43,25 +42,25 @@ namespace rotgen::tests
rotgen::Index i0, j0; rotgen::Index i0, j0;
}; };
void prepare(rotgen::Index rows, rotgen::Index cols, auto const &init_fn, auto& output) void prepare(rotgen::Index rows,
rotgen::Index cols,
auto const& init_fn,
auto& output)
{ {
for (rotgen::Index r = 0; r < rows; ++r) for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c) output(r, c) = init_fn(r, c);
output(r,c) = init_fn(r, c);
} }
void prepare(auto fn, auto& output) void prepare(auto fn, auto& output)
{ {
for (rotgen::Index r = 0; r < output.rows(); ++r) for (rotgen::Index r = 0; r < output.rows(); ++r)
for (rotgen::Index c = 0; c < output.cols(); ++c) for (rotgen::Index c = 0; c < output.cols(); ++c) output(r, c) = fn(r, c);
output(r,c) = fn(r, c);
} }
auto generate_matrix_references() auto generate_matrix_references()
{ {
auto fn = [](auto r, auto c) { return r + 3 * c - 2.5; }; auto fn = [](auto r, auto c) { return r + 3 * c - 2.5; };
std::vector<rotgen::tests::matrix_descriptor> cases = std::vector<rotgen::tests::matrix_descriptor> cases = {
{
// Singular matrix // Singular matrix
{1, 1, fn}, {1, 1, fn},
// Square matrix below MAX_SIZE // Square matrix below MAX_SIZE
@ -81,8 +80,7 @@ namespace rotgen::tests
// Thick matrix at MAX_SIZE // Thick matrix at MAX_SIZE
{2, 8, fn}, {2, 8, fn},
// Thick matrix above MAX_SIZE // Thick matrix above MAX_SIZE
{3, 10, fn} {3, 10, fn}};
};
return cases; return cases;
} }
@ -90,102 +88,96 @@ namespace rotgen::tests
auto generate_static_matrix_references() auto generate_static_matrix_references()
{ {
auto fn = [](auto r, auto c) { return r + 3 * c - 2.5; }; auto fn = [](auto r, auto c) { return r + 3 * c - 2.5; };
std::tuple cases = std::tuple cases = {// Singular matrix
{ static_matrix_descriptor<1, 1>{fn},
// Singular matrix // Square matrix below MAX_SIZE
static_matrix_descriptor< 1, 1>{fn}, static_matrix_descriptor<3, 3>{fn},
// Square matrix below MAX_SIZE // Square matrix at MAX_SIZE
static_matrix_descriptor< 3, 3>{fn}, static_matrix_descriptor<4, 4>{fn},
// Square matrix at MAX_SIZE // Square matrix above MAX_SIZE
static_matrix_descriptor< 4, 4>{fn}, static_matrix_descriptor<7, 7>{fn},
// Square matrix above MAX_SIZE // Tall matrix below MAX_SIZE
static_matrix_descriptor< 7, 7>{fn}, static_matrix_descriptor<5, 2>{fn},
// Tall matrix below MAX_SIZE // Tall matrix at MAX_SIZE
static_matrix_descriptor< 5, 2>{fn}, static_matrix_descriptor<8, 2>{fn},
// Tall matrix at MAX_SIZE // Tall matrix above MAX_SIZE
static_matrix_descriptor< 8, 2>{fn}, static_matrix_descriptor<10, 3>{fn},
// Tall matrix above MAX_SIZE // Thick matrix below MAX_SIZE
static_matrix_descriptor<10, 3>{fn}, static_matrix_descriptor<2, 5>{fn},
// Thick matrix below MAX_SIZE // Thick matrix at MAX_SIZE
static_matrix_descriptor< 2, 5>{fn}, static_matrix_descriptor<2, 8>{fn},
// Thick matrix at MAX_SIZE // Thick matrix above MAX_SIZE
static_matrix_descriptor< 2, 8>{fn}, static_matrix_descriptor<3, 10>{fn}};
// Thick matrix above MAX_SIZE
static_matrix_descriptor< 3,10>{fn}
};
return cases; return cases;
} }
template<typename T, typename O> template<typename T, typename O> auto generate_block_references()
auto generate_block_references()
{ {
rotgen::tests::matrix_descriptor base{16,16,[](auto r, auto c) { return r + 3 * c - 2.5; }}; rotgen::tests::matrix_descriptor base{
16, 16, [](auto r, auto c) { return r + 3 * c - 2.5; }};
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> cases = std::vector<rotgen::tests::matrix_block_test_case<mat_t>> cases = {
{
// Singular blocks // Singular blocks
{base, 0, 0, 1, 1}, {base, 0, 0, 1, 1},
{base, 3, 2, 1, 1}, {base, 3, 2, 1, 1},
{base, 4,11, 1, 1}, {base, 4, 11, 1, 1},
{base,15,15, 1, 1}, {base, 15, 15, 1, 1},
// Square block below MAX_SIZE // Square block below MAX_SIZE
{base,7,9, 3, 3}, {base, 7, 9, 3, 3},
// Square block at MAX_SIZE // Square block at MAX_SIZE
{base,6,3, 4, 4}, {base, 6, 3, 4, 4},
// Square block above MAX_SIZE // Square block above MAX_SIZE
{base,6,3, 6, 6}, {base, 6, 3, 6, 6},
// Tall block below MAX_SIZE // Tall block below MAX_SIZE
{base,6,3, 5, 2}, {base, 6, 3, 5, 2},
// Tall block at MAX_SIZE // Tall block at MAX_SIZE
{base,6,3, 8, 2}, {base, 6, 3, 8, 2},
// Tall block above MAX_SIZE // Tall block above MAX_SIZE
{base,6,3, 7, 3}, {base, 6, 3, 7, 3},
// Thick block below MAX_SIZE // Thick block below MAX_SIZE
{base,6,3, 2, 5}, {base, 6, 3, 2, 5},
// Thick block at MAX_SIZE // Thick block at MAX_SIZE
{base,6,3, 2, 8}, {base, 6, 3, 2, 8},
// Thick block above MAX_SIZE // Thick block above MAX_SIZE
{base,6,3, 3, 7} {base, 6, 3, 3, 7}};
};
return cases; return cases;
} }
template<typename T, typename O>
auto generate_static_block_references() template<typename T, typename O> auto generate_static_block_references()
{ {
rotgen::tests::matrix_descriptor base{16,16,[](auto r, auto c) { return r + 3 * c - 2.5; }}; rotgen::tests::matrix_descriptor base{
16, 16, [](auto r, auto c) { return r + 3 * c - 2.5; }};
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
std::tuple cases = std::tuple cases = {
{
// Singular blocks // Singular blocks
static_matrix_block_test_case<mat_t, 1, 1>{base, 0, 0}, static_matrix_block_test_case<mat_t, 1, 1>{base, 0, 0},
static_matrix_block_test_case<mat_t, 1, 1>{base, 3, 2}, static_matrix_block_test_case<mat_t, 1, 1>{base, 3, 2},
static_matrix_block_test_case<mat_t, 1, 1>{base, 4,11}, static_matrix_block_test_case<mat_t, 1, 1>{base, 4, 11},
static_matrix_block_test_case<mat_t, 1, 1>{base,15,15}, static_matrix_block_test_case<mat_t, 1, 1>{base, 15, 15},
// Square block below MAX_SIZE // Square block below MAX_SIZE
static_matrix_block_test_case<mat_t, 3, 3>{base,7,9}, static_matrix_block_test_case<mat_t, 3, 3>{base, 7, 9},
// Square block at MAX_SIZE // Square block at MAX_SIZE
static_matrix_block_test_case<mat_t, 4, 4>{base,6,3}, static_matrix_block_test_case<mat_t, 4, 4>{base, 6, 3},
// Square block above MAX_SIZE // Square block above MAX_SIZE
static_matrix_block_test_case<mat_t, 6, 6>{base,6,3}, static_matrix_block_test_case<mat_t, 6, 6>{base, 6, 3},
// Tall block below MAX_SIZE // Tall block below MAX_SIZE
static_matrix_block_test_case<mat_t, 5, 2>{base,6,3}, static_matrix_block_test_case<mat_t, 5, 2>{base, 6, 3},
// Tall block at MAX_SIZE // Tall block at MAX_SIZE
static_matrix_block_test_case<mat_t, 8, 2>{base,6,3}, static_matrix_block_test_case<mat_t, 8, 2>{base, 6, 3},
// Tall block above MAX_SIZE // Tall block above MAX_SIZE
static_matrix_block_test_case<mat_t, 7, 3>{base,6,3}, static_matrix_block_test_case<mat_t, 7, 3>{base, 6, 3},
// Thick block below MAX_SIZE // Thick block below MAX_SIZE
static_matrix_block_test_case<mat_t, 2, 5>{base,6,3}, static_matrix_block_test_case<mat_t, 2, 5>{base, 6, 3},
// Thick block at MAX_SIZE // Thick block at MAX_SIZE
static_matrix_block_test_case<mat_t, 2, 8>{base,6,3}, static_matrix_block_test_case<mat_t, 2, 8>{base, 6, 3},
// Thick block above MAX_SIZE // Thick block above MAX_SIZE
static_matrix_block_test_case<mat_t, 3, 7>{base,6,3} static_matrix_block_test_case<mat_t, 3, 7>{base, 6, 3}};
};
return cases; return cases;
} }

View file

@ -8,27 +8,28 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("System solver using QR", rotgen::tests::types) TTS_CASE_TPL("System solver using QR",
<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> rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic> a{{2.3, -1, 0.1},
a { { 2.3, -1, 0.1} {-1.6, 2.6, -1},
, {-1.6, 2.6, -1} {0.3, -1, 2}};
, { 0.3, -1, 2}
};
rotgen::matrix<T,rotgen::Dynamic,1> b(3,1); rotgen::matrix<T, rotgen::Dynamic, 1> b(3, 1);
b(0) = b(2) = 1; b(1) = 0; b(0) = b(2) = 1;
b(1) = 0;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic> r(3,1), error; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic> r(3, 1), error;
auto x = rotgen::extract(r,0,0,3,1); auto x = rotgen::extract(r, 0, 0, 3, 1);
rotgen::solver::qr(x, a, b); rotgen::solver::qr(x, a, b);
error = a * r - b; error = a * r - b;
auto eps = std::numeric_limits<T>::epsilon(); auto eps = std::numeric_limits<T>::epsilon();
TTS_LESS(rotgen::maxCoeff(rotgen::abs(error)) / eps, 5) TTS_LESS(rotgen::maxCoeff(rotgen::abs(error)) / eps, 5) << "Result:\n"
<< "Result:\n" << r << "\n" << r << "\n"
<< "Residuals:\n" << error << "\n"; << "Residuals:\n"
<< error << "\n";
}; };

View file

@ -8,47 +8,58 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("rowwise API", rotgen::tests::types) TTS_CASE_TPL("rowwise API", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
using e_t = Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic,O::value>; using e_t = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, O::value>;
e_t ref = e_t::Random(4,4); e_t ref = e_t::Random(4, 4);
auto ref_rw = ref.rowwise(); auto ref_rw = ref.rowwise();
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> mat(4,4); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> mat(4, 4);
rotgen::tests::prepare([&](auto r, auto c) { return ref(r,c); }, mat); rotgen::tests::prepare([&](auto r, auto c) { return ref(r, c); }, mat);
auto rw = rotgen::rowwise(mat); auto rw = rotgen::rowwise(mat);
for(rotgen::Index i=0;i<mat.rows();++i) TTS_EQUAL(rw.sum()(i) , ref_rw.sum()(i) ); for (rotgen::Index i = 0; i < mat.rows(); ++i)
for(rotgen::Index i=0;i<mat.rows();++i) TTS_EQUAL(rw.mean()(i) , ref_rw.mean()(i) ); TTS_EQUAL(rw.sum()(i), ref_rw.sum()(i));
for(rotgen::Index i=0;i<mat.rows();++i) TTS_EQUAL(rw.prod()(i) , ref_rw.prod()(i) ); for (rotgen::Index i = 0; i < mat.rows(); ++i)
for(rotgen::Index i=0;i<mat.rows();++i) TTS_EQUAL(rw.maxCoeff()(i) , ref_rw.maxCoeff()(i) ); TTS_EQUAL(rw.mean()(i), ref_rw.mean()(i));
for(rotgen::Index i=0;i<mat.rows();++i) TTS_EQUAL(rw.minCoeff()(i) , ref_rw.minCoeff()(i) ); for (rotgen::Index i = 0; i < mat.rows(); ++i)
for(rotgen::Index i=0;i<mat.rows();++i) TTS_EQUAL(rw.squaredNorm()(i) , ref_rw.squaredNorm()(i) ); TTS_EQUAL(rw.prod()(i), ref_rw.prod()(i));
for(rotgen::Index i=0;i<mat.rows();++i) TTS_EQUAL(rw.norm()(i) , ref_rw.norm()(i) ); for (rotgen::Index i = 0; i < mat.rows(); ++i)
TTS_EQUAL(rw.maxCoeff()(i), ref_rw.maxCoeff()(i));
for (rotgen::Index i = 0; i < mat.rows(); ++i)
TTS_EQUAL(rw.minCoeff()(i), ref_rw.minCoeff()(i));
for (rotgen::Index i = 0; i < mat.rows(); ++i)
TTS_EQUAL(rw.squaredNorm()(i), ref_rw.squaredNorm()(i));
for (rotgen::Index i = 0; i < mat.rows(); ++i)
TTS_EQUAL(rw.norm()(i), ref_rw.norm()(i));
}; };
TTS_CASE_TPL("colwise API", rotgen::tests::types) TTS_CASE_TPL("colwise API", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
using e_t = Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic,O::value>; using e_t = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, O::value>;
e_t ref = e_t::Random(4,4); e_t ref = e_t::Random(4, 4);
auto ref_rw = ref.colwise(); auto ref_rw = ref.colwise();
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> mat(4,4); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> mat(4, 4);
rotgen::tests::prepare([&](auto r, auto c) { return ref(r,c); }, mat); rotgen::tests::prepare([&](auto r, auto c) { return ref(r, c); }, mat);
auto rw = rotgen::colwise(mat); auto rw = rotgen::colwise(mat);
for(rotgen::Index i=0;i<mat.cols();++i) TTS_EQUAL(rw.sum()(i) , ref_rw.sum()(i) ); for (rotgen::Index i = 0; i < mat.cols(); ++i)
for(rotgen::Index i=0;i<mat.cols();++i) TTS_EQUAL(rw.mean()(i) , ref_rw.mean()(i) ); TTS_EQUAL(rw.sum()(i), ref_rw.sum()(i));
for(rotgen::Index i=0;i<mat.cols();++i) TTS_EQUAL(rw.prod()(i) , ref_rw.prod()(i) ); for (rotgen::Index i = 0; i < mat.cols(); ++i)
for(rotgen::Index i=0;i<mat.cols();++i) TTS_EQUAL(rw.maxCoeff()(i) , ref_rw.maxCoeff()(i) ); TTS_EQUAL(rw.mean()(i), ref_rw.mean()(i));
for(rotgen::Index i=0;i<mat.cols();++i) TTS_EQUAL(rw.minCoeff()(i) , ref_rw.minCoeff()(i) ); for (rotgen::Index i = 0; i < mat.cols(); ++i)
for(rotgen::Index i=0;i<mat.cols();++i) TTS_EQUAL(rw.squaredNorm()(i) , ref_rw.squaredNorm()(i) ); TTS_EQUAL(rw.prod()(i), ref_rw.prod()(i));
for(rotgen::Index i=0;i<mat.cols();++i) TTS_EQUAL(rw.norm()(i) , ref_rw.norm()(i) ); for (rotgen::Index i = 0; i < mat.cols(); ++i)
TTS_EQUAL(rw.maxCoeff()(i), ref_rw.maxCoeff()(i));
for (rotgen::Index i = 0; i < mat.cols(); ++i)
TTS_EQUAL(rw.minCoeff()(i), ref_rw.minCoeff()(i));
for (rotgen::Index i = 0; i < mat.cols(); ++i)
TTS_EQUAL(rw.squaredNorm()(i), ref_rw.squaredNorm()(i));
for (rotgen::Index i = 0; i < mat.cols(); ++i)
TTS_EQUAL(rw.norm()(i), ref_rw.norm()(i));
}; };

View file

@ -10,27 +10,28 @@
#include <functional> #include <functional>
#include <array> #include <array>
template <typename MatrixType> template<typename MatrixType> struct MatrixDescriptor
struct MatrixDescriptor
{ {
std::size_t rows, cols; std::size_t rows, cols;
std::function<void(MatrixType &, std::size_t, std::size_t)> init_fn; std::function<void(MatrixType&, std::size_t, std::size_t)> init_fn;
}; };
template <typename MatrixType, std::size_t N> template<typename MatrixType, std::size_t N>
void test_matrix_sizes(std::size_t rows, std::size_t cols, void test_matrix_sizes(
const std::function<void(MatrixType &, std::size_t, std::size_t)> &init_fn, std::size_t rows,
const std::array<std::pair<int, int>, N>& resize_dimensions) std::size_t cols,
std::function<void(MatrixType&, std::size_t, std::size_t)> const& init_fn,
std::array<std::pair<int, int>, N> const& resize_dimensions)
{ {
MatrixType matrix(rows, cols); MatrixType matrix(rows, cols);
for (std::size_t r = 0; r < rows; ++r) for (std::size_t r = 0; r < rows; ++r)
for (std::size_t c = 0; c < cols; ++c) for (std::size_t c = 0; c < cols; ++c) init_fn(matrix, r, c);
init_fn(matrix, r, c);
TTS_EQUAL(rotgen::size(matrix), rows*cols); TTS_EQUAL(rotgen::size(matrix), rows * cols);
for (std::size_t i = 0; i < N; ++i) { for (std::size_t i = 0; i < N; ++i)
{
int r = resize_dimensions[i].first; int r = resize_dimensions[i].first;
int c = resize_dimensions[i].second; int c = resize_dimensions[i].second;
@ -38,24 +39,22 @@ void test_matrix_sizes(std::size_t rows, std::size_t cols,
TTS_EQUAL(rotgen::rows(matrix), static_cast<size_t>(r)); TTS_EQUAL(rotgen::rows(matrix), static_cast<size_t>(r));
TTS_EQUAL(rotgen::cols(matrix), static_cast<size_t>(c)); TTS_EQUAL(rotgen::cols(matrix), static_cast<size_t>(c));
TTS_EQUAL(rotgen::size(matrix), static_cast<size_t>(r*c)); TTS_EQUAL(rotgen::size(matrix), static_cast<size_t>(r * c));
} }
rotgen::conservativeResize(matrix, rows, cols); rotgen::conservativeResize(matrix, rows, cols);
TTS_EQUAL(rotgen::size(matrix), rows*cols); TTS_EQUAL(rotgen::size(matrix), rows * cols);
int i = 1; int i = 1;
for(std::size_t r=0;r<rows;++r) for (std::size_t r = 0; r < rows; ++r)
for(std::size_t c=0;c<cols;++c) for (std::size_t c = 0; c < cols; ++c) matrix(r, c) = i++;
matrix(r, c) = i++;
rotgen::conservativeResize(matrix, rows + 3, cols + 2); rotgen::conservativeResize(matrix, rows + 3, cols + 2);
TTS_EQUAL(rotgen::size(matrix), (rows + 3)*(cols + 2)); TTS_EQUAL(rotgen::size(matrix), (rows + 3) * (cols + 2));
i = 1; i = 1;
for(std::size_t r=0;r<rows;++r) for (std::size_t r = 0; r < rows; ++r)
for(std::size_t c=0;c<cols;++c) for (std::size_t c = 0; c < cols; ++c) TTS_EQUAL(matrix(r, c), i++);
TTS_EQUAL(matrix(r,c),i++);
} }
TTS_CASE("Matrix size-related operations") TTS_CASE("Matrix size-related operations")
@ -63,18 +62,37 @@ TTS_CASE("Matrix size-related operations")
std::vector<MatrixDescriptor<rotgen::matrix<double>>> test_matrices = { std::vector<MatrixDescriptor<rotgen::matrix<double>>> test_matrices = {
{3, 3, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = r + c; }}, {3, 3, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = r + c; }},
{2, 3, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = 0.0; }}, {2, 3, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = 0.0; }},
{2, 7, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = -r*r*r - c*c - 1.23; }}, {2, 7,
{17, 3, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = r*c + 0.98; }}, [](auto& m, std::size_t r, std::size_t c) {
m(r, c) = -r * r * r - c * c - 1.23;
}},
{17, 3,
[](auto& m, std::size_t r, std::size_t c) { m(r, c) = r * c + 0.98; }},
{1, 1, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = 42.0; }}, {1, 1, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = 42.0; }},
{10, 11, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = std::tan(r + c); }}, {10, 11,
{1, 5, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = -1.5*r + 2.56*c + 3.33; }}, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = std::tan(r + c); }},
{7, 1, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = (r == c ? 1.0 : 0.0); }}, {1, 5,
{0, 0, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = (r == c ? 1.0 : 0.0); }}, [](auto& m, std::size_t r, std::size_t c) {
m(r, c) = -1.5 * r + 2.56 * c + 3.33;
}},
{7, 1,
[](auto& m, std::size_t r, std::size_t c) {
m(r, c) = (r == c ? 1.0 : 0.0);
}},
{0, 0,
[](auto& m, std::size_t r, std::size_t c) {
m(r, c) = (r == c ? 1.0 : 0.0);
}},
}; };
for (const auto& [rows, cols, init_fn] : test_matrices) for (auto const& [rows, cols, init_fn] : test_matrices)
test_matrix_sizes<rotgen::matrix<double>>(rows, cols, init_fn, std::array{ test_matrix_sizes<rotgen::matrix<double>>(rows, cols, init_fn,
std::pair{1, 2}, std::pair{11, 17}, std::pair{4, 5}, std::array{
std::pair{9, 1}, std::pair{3, 8}, std::pair{22, 0}, std::pair{1, 2},
}); std::pair{11, 17},
std::pair{4, 5},
std::pair{9, 1},
std::pair{3, 8},
std::pair{22, 0},
});
}; };

View file

@ -8,23 +8,24 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("SVD decomposition - Dynamic case", rotgen::tests::types) TTS_CASE_TPL("SVD decomposition - Dynamic case",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
int rank, i = 5; int rank, i = 5;
auto eps = std::numeric_limits<T>::epsilon(); auto eps = std::numeric_limits<T>::epsilon();
auto m = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>::Random(5,5); auto m =
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>::Random(5, 5);
auto decomp = rotgen::svd(m); auto decomp = rotgen::svd(m);
do do {
{ rank = decomp.rank();
rank = decomp.rank();
auto u = decomp.U(rank); auto u = decomp.U(rank);
auto d = decomp.singular_values(rank); auto d = decomp.singular_values(rank);
auto dd = decomp.D(rank); auto dd = decomp.D(rank);
auto v = decomp.V(rank); auto v = decomp.V(rank);
TTS_EQUAL(rank, i); TTS_EQUAL(rank, i);
@ -32,34 +33,36 @@ TTS_CASE_TPL("SVD decomposition - Dynamic case", rotgen::tests::types)
auto error = m - rec; auto error = m - rec;
TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 16.) TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 16.)
<< "Result:\n" << rec << "\n" << "Result:\n"
<< "Residuals:\n" << error << "\n"; << rec << "\n"
<< "Residuals:\n"
<< error << "\n";
// Reduce rank by duplicating one column // Reduce rank by duplicating one column
i--; i--;
col(m,i) = col(m,0); col(m, i) = col(m, 0);
decomp = rotgen::svd(m); decomp = rotgen::svd(m);
}while(rank != 1); } while (rank != 1);
}; };
TTS_CASE_TPL("SVD decomposition - Static case", rotgen::tests::types) TTS_CASE_TPL("SVD decomposition - Static case",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
int rank, i = 5; int rank, i = 5;
auto eps = std::numeric_limits<T>::epsilon(); auto eps = std::numeric_limits<T>::epsilon();
auto m = rotgen::matrix<T,5,5,O::value>::Random(); auto m = rotgen::matrix<T, 5, 5, O::value>::Random();
auto decomp = rotgen::svd(m); auto decomp = rotgen::svd(m);
do do {
{ rank = decomp.rank();
rank = decomp.rank();
auto u = decomp.U(rank); auto u = decomp.U(rank);
auto d = decomp.singular_values(rank); auto d = decomp.singular_values(rank);
auto dd = decomp.D(rank); auto dd = decomp.D(rank);
auto v = decomp.V(rank); auto v = decomp.V(rank);
TTS_EQUAL(rank, i); TTS_EQUAL(rank, i);
@ -67,13 +70,15 @@ TTS_CASE_TPL("SVD decomposition - Static case", rotgen::tests::types)
auto error = m - rec; auto error = m - rec;
TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 16.) TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 16.)
<< "Result:\n" << rec << "\n" << "Result:\n"
<< "Residuals:\n" << error << "\n"; << rec << "\n"
<< "Residuals:\n"
<< error << "\n";
// Reduce rank by duplicating one column // Reduce rank by duplicating one column
i--; i--;
col(m,i) = col(m,0); col(m, i) = col(m, 0);
decomp = rotgen::svd(m); decomp = rotgen::svd(m);
}while(rank != 1); } while (rank != 1);
}; };

View file

@ -9,101 +9,109 @@
#include "unit/common/arithmetic.hpp" #include "unit/common/arithmetic.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic map transposition-like operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic map transposition-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_matrix_references(); auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases) for (auto const& [rows, cols, fn] : cases)
{ {
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
mat_t base(rows, cols); mat_t base(rows, cols);
rotgen::tests::prepare(rows,cols,fn,base); rotgen::tests::prepare(rows, cols, fn, base);
rotgen::map<mat_t> input(base.data(),rows,cols); rotgen::map<mat_t> input(base.data(), rows, cols);
rotgen::tests::check_shape_functions(input); rotgen::tests::check_shape_functions(input);
} }
}; };
TTS_CASE_TPL("Test static map transposition-like operations", rotgen::tests::types) TTS_CASE_TPL("Test static map transposition-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_matrix_references(); auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc) auto process = []<typename D>(D const& desc) {
{ rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> base(D::rows,
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(D::rows,D::cols); D::cols);
rotgen::tests::prepare(base.rows(),base.cols(),desc.init_fn,base); rotgen::tests::prepare(base.rows(), base.cols(), desc.init_fn, base);
rotgen::map<rotgen::matrix<T,D::rows,D::cols,O::value>> input(base.data()); rotgen::map<rotgen::matrix<T, D::rows, D::cols, O::value>> input(
base.data());
rotgen::tests::check_shape_functions(input); rotgen::tests::check_shape_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };
TTS_CASE_TPL("Test dynamic map reduction-like operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic map reduction-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_matrix_references(); auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases) for (auto const& [rows, cols, fn] : cases)
{ {
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> base(rows,
rotgen::tests::prepare(rows,cols,fn,base); cols);
rotgen::tests::prepare(rows, cols, fn, base);
rotgen::map<rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>> input(base.data(),rows,cols); rotgen::map<rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>>
input(base.data(), rows, cols);
rotgen::tests::check_reduction_functions(input); rotgen::tests::check_reduction_functions(input);
} }
}; };
TTS_CASE_TPL("Test static map reduction-like operations", rotgen::tests::types) TTS_CASE_TPL("Test static map reduction-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_matrix_references(); auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc) auto process = []<typename D>(D const& desc) {
{ rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> base(D::rows,
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(D::rows,D::cols); D::cols);
rotgen::tests::prepare(base.rows(),base.cols(),desc.init_fn,base); rotgen::tests::prepare(base.rows(), base.cols(), desc.init_fn, base);
rotgen::map<rotgen::matrix<T,D::rows,D::cols,O::value>> input(base.data()); rotgen::map<rotgen::matrix<T, D::rows, D::cols, O::value>> input(
base.data());
rotgen::tests::check_reduction_functions(input); rotgen::tests::check_reduction_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };
TTS_CASE_TPL("Test dot product", float, double) TTS_CASE_TPL("Test dot product", float, double)<typename T>(tts::type<T>){
<typename T>( tts::type<T> ) {auto v = rotgen::setConstant<rotgen::matrix<T, 1, rotgen::Dynamic>>(1,
16,
2);
auto a = rotgen::map<decltype(v)>(v.data(), 1, 8);
auto b = rotgen::map<decltype(v)>(v.data() + 8, 1, 8);
TTS_EQUAL(rotgen::dot(a, b), 32);
}
{ {
{ auto v = rotgen::setConstant<rotgen::matrix<T, rotgen::Dynamic, 1>>(16, 1, 2);
auto v = rotgen::setConstant<rotgen::matrix<T,1,rotgen::Dynamic>>(1,16,2); auto a = rotgen::map<decltype(v)>(v.data(), 8, 1);
auto a = rotgen::map<decltype(v)>(v.data(),1,8); auto b = rotgen::map<decltype(v)>(v.data() + 8, 8, 1);
auto b = rotgen::map<decltype(v)>(v.data()+8,1,8);
TTS_EQUAL(rotgen::dot(a,b), 32); TTS_EQUAL(rotgen::dot(a, b), 32);
} }
{ {
auto v = rotgen::setConstant<rotgen::matrix<T,rotgen::Dynamic,1>>(16,1,2); auto v = rotgen::setConstant<rotgen::matrix<T, 1, rotgen::Dynamic>>(1, 16, 2);
auto a = rotgen::map<decltype(v)>(v.data(),8,1); auto a = rotgen::map<rotgen::matrix<T, 1, 8>>(v.data());
auto b = rotgen::map<decltype(v)>(v.data()+8,8,1); auto b = rotgen::map<rotgen::matrix<T, 1, 8>>(v.data() + 8);
TTS_EQUAL(rotgen::dot(a,b), 32); TTS_EQUAL(rotgen::dot(a, b), 32);
} }
{ {
auto v = rotgen::setConstant<rotgen::matrix<T,1,rotgen::Dynamic>>(1,16,2); auto v = rotgen::setConstant<rotgen::matrix<T, 1, rotgen::Dynamic>>(1, 16, 2);
auto a = rotgen::map<rotgen::matrix<T,1,8>>(v.data()); auto a = rotgen::map<rotgen::matrix<T, 8, 1>>(v.data());
auto b = rotgen::map<rotgen::matrix<T,1,8>>(v.data()+8); auto b = rotgen::map<rotgen::matrix<T, 8, 1>>(v.data() + 8);
TTS_EQUAL(rotgen::dot(a,b), 32); TTS_EQUAL(rotgen::dot(a, b), 32);
} }
}
{ ;
auto v = rotgen::setConstant<rotgen::matrix<T,1,rotgen::Dynamic>>(1,16,2);
auto a = rotgen::map<rotgen::matrix<T,8,1>>(v.data());
auto b = rotgen::map<rotgen::matrix<T,8,1>>(v.data()+8);
TTS_EQUAL(rotgen::dot(a,b), 32);
}
};

View file

@ -8,88 +8,90 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Function size", rotgen::tests::types) TTS_CASE_TPL("Function size", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
T data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; T data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
rotgen::map<rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>> dyn_map(data,1,12); rotgen::map<rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>>
dyn_map(data, 1, 12);
TTS_EQUAL(dyn_map.rows(), rotgen::Index{1}); TTS_EQUAL(dyn_map.rows(), rotgen::Index{1});
TTS_EQUAL(dyn_map.cols(), rotgen::Index{12}); TTS_EQUAL(dyn_map.cols(), rotgen::Index{12});
rotgen::map<rotgen::matrix<T,1,12,rotgen::RowMajor>> s112_map(data); rotgen::map<rotgen::matrix<T, 1, 12, rotgen::RowMajor>> s112_map(data);
TTS_EQUAL(s112_map.rows(), rotgen::Index{1}); TTS_EQUAL(s112_map.rows(), rotgen::Index{1});
TTS_EQUAL(s112_map.cols(), rotgen::Index{12}); TTS_EQUAL(s112_map.cols(), rotgen::Index{12});
TTS_EQUAL(s112_map.size(), rotgen::Index{12}); TTS_EQUAL(s112_map.size(), rotgen::Index{12});
rotgen::map<rotgen::matrix<T,12,1,rotgen::ColMajor>> s121_map(data); rotgen::map<rotgen::matrix<T, 12, 1, rotgen::ColMajor>> s121_map(data);
TTS_EQUAL(s121_map.rows(), rotgen::Index{12}); TTS_EQUAL(s121_map.rows(), rotgen::Index{12});
TTS_EQUAL(s121_map.cols(), rotgen::Index{1}); TTS_EQUAL(s121_map.cols(), rotgen::Index{1});
TTS_EQUAL(s121_map.size(), rotgen::Index{12}); TTS_EQUAL(s121_map.size(), rotgen::Index{12});
rotgen::map<rotgen::matrix<T,3,4,O::value>> s34_map(data); rotgen::map<rotgen::matrix<T, 3, 4, O::value>> s34_map(data);
TTS_EQUAL(s34_map.rows(), rotgen::Index{3}); TTS_EQUAL(s34_map.rows(), rotgen::Index{3});
TTS_EQUAL(s34_map.cols(), rotgen::Index{4}); TTS_EQUAL(s34_map.cols(), rotgen::Index{4});
TTS_EQUAL(s34_map.size(), rotgen::Index{12}); TTS_EQUAL(s34_map.size(), rotgen::Index{12});
rotgen::map<rotgen::matrix<T,6,2,O::value>> s62_map(data); rotgen::map<rotgen::matrix<T, 6, 2, O::value>> s62_map(data);
TTS_EQUAL(s62_map.rows(), rotgen::Index{6}); TTS_EQUAL(s62_map.rows(), rotgen::Index{6});
TTS_EQUAL(s62_map.cols(), rotgen::Index{2}); TTS_EQUAL(s62_map.cols(), rotgen::Index{2});
TTS_EQUAL(s62_map.size(), rotgen::Index{12}); TTS_EQUAL(s62_map.size(), rotgen::Index{12});
}; };
TTS_CASE_TPL("Test coefficient accessors", rotgen::tests::types) TTS_CASE_TPL("Test coefficient accessors",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
using base = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>; using base = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
T data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; T data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
rotgen::map<base> a(data,4,3); rotgen::map<base> a(data, 4, 3);
for(rotgen::Index i=0;i<4;i++) for (rotgen::Index i = 0; i < 4; i++)
{ {
for(rotgen::Index j=0;j<3;j++) for (rotgen::Index j = 0; j < 3; j++)
{ {
if constexpr(O::value) TTS_EQUAL(a(i,j), data[j+3*i]); if constexpr (O::value) TTS_EQUAL(a(i, j), data[j + 3 * i]);
else TTS_EQUAL(a(i,j), data[i+4*j]); else TTS_EQUAL(a(i, j), data[i + 4 * j]);
} }
} }
a(1, 1) = 42; a(1, 1) = 42;
TTS_EQUAL(a(1,1), 42); TTS_EQUAL(a(1, 1), 42);
T& ref = a(2, 2); T& ref = a(2, 2);
ref = 17; ref = 17;
TTS_EQUAL(a(2, 2), 17); TTS_EQUAL(a(2, 2), 17);
}; };
TTS_CASE_TPL("Test one index coefficient accessors", rotgen::tests::types) TTS_CASE_TPL("Test one index coefficient accessors",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
T data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; T data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
auto m = [&]() auto m = [&]() {
{ if constexpr (O::value == rotgen::ColMajor)
if constexpr(O::value == rotgen::ColMajor)
{ {
using base = rotgen::matrix<T,1,rotgen::Dynamic>; using base = rotgen::matrix<T, 1, rotgen::Dynamic>;
rotgen::map<base> a(data,12); rotgen::map<base> a(data, 12);
return a; return a;
} }
else else
{ {
using base = rotgen::matrix<T,rotgen::Dynamic,1>; using base = rotgen::matrix<T, rotgen::Dynamic, 1>;
rotgen::map<base> a(data,12); rotgen::map<base> a(data, 12);
return a; return a;
} }
}(); }();
TTS_EXPECT(m.IsVectorAtCompileTime); TTS_EXPECT(m.IsVectorAtCompileTime);
for(rotgen::Index i=0;i<m.size();i++) for (rotgen::Index i = 0; i < m.size(); i++)
TTS_EQUAL(m(i), data[i]) << "Index: " << i << "\n"; TTS_EQUAL(m(i), data[i]) << "Index: " << i << "\n";
for(rotgen::Index i=0;i<m.size();i++) for (rotgen::Index i = 0; i < m.size(); i++)
TTS_EQUAL(m[i], data[i]) << "Index: " << i << "\n"; TTS_EQUAL(m[i], data[i]) << "Index: " << i << "\n";
m(1) = 42; m(1) = 42;

View file

@ -8,82 +8,84 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("map constructor from pointer and single static size", rotgen::tests::types) TTS_CASE_TPL("map constructor from pointer and single static size",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
T data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; T data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
rotgen::map<rotgen::matrix<T,1,12,rotgen::RowMajor>> row_map(data); rotgen::map<rotgen::matrix<T, 1, 12, rotgen::RowMajor>> row_map(data);
for(rotgen::Index i=0;i<12;i++) for (rotgen::Index i = 0; i < 12; i++) TTS_EQUAL(row_map(i), data[i]);
TTS_EQUAL(row_map(i), data[i]);
rotgen::map<rotgen::matrix<T,1,12,rotgen::RowMajor> const> const_row_map(data); rotgen::map<rotgen::matrix<T, 1, 12, rotgen::RowMajor> const> const_row_map(
for(rotgen::Index i=0;i<12;i++) data);
TTS_EQUAL(const_row_map(i), data[i]); for (rotgen::Index i = 0; i < 12; i++) TTS_EQUAL(const_row_map(i), data[i]);
rotgen::map<rotgen::matrix<T,12,1,rotgen::ColMajor>> col_map(data); rotgen::map<rotgen::matrix<T, 12, 1, rotgen::ColMajor>> col_map(data);
for(rotgen::Index i=0;i<12;i++) for (rotgen::Index i = 0; i < 12; i++) TTS_EQUAL(col_map(i), data[i]);
TTS_EQUAL(col_map(i), data[i]);
rotgen::map<rotgen::matrix<T,12,1,rotgen::ColMajor> const> const_col_map(data); rotgen::map<rotgen::matrix<T, 12, 1, rotgen::ColMajor> const> const_col_map(
for(rotgen::Index i=0;i<12;i++) data);
TTS_EQUAL(const_col_map(i), data[i]); for (rotgen::Index i = 0; i < 12; i++) TTS_EQUAL(const_col_map(i), data[i]);
}; };
TTS_CASE_TPL("map constructor from pointer and static size", rotgen::tests::types) TTS_CASE_TPL("map constructor from pointer and static size",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
using base = rotgen::matrix<T,4,3,O::value>; using base = rotgen::matrix<T, 4, 3, O::value>;
T data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; T data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
rotgen::map<base> dyn_map(data); rotgen::map<base> dyn_map(data);
for(rotgen::Index i=0;i<4;i++) for (rotgen::Index i = 0; i < 4; i++)
{ {
for(rotgen::Index j=0;j<3;j++) for (rotgen::Index j = 0; j < 3; j++)
{ {
if constexpr(O::value) TTS_EQUAL(dyn_map(i,j), data[j+3*i]); if constexpr (O::value) TTS_EQUAL(dyn_map(i, j), data[j + 3 * i]);
else TTS_EQUAL(dyn_map(i,j), data[i+4*j]); else TTS_EQUAL(dyn_map(i, j), data[i + 4 * j]);
} }
} }
}; };
TTS_CASE_TPL("map constructor from pointer and single dynamic size", rotgen::tests::types) TTS_CASE_TPL("map constructor from pointer and single dynamic size",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
T data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; T data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
rotgen::map<rotgen::matrix<T,1,rotgen::Dynamic,rotgen::RowMajor>> row_map(data,12); rotgen::map<rotgen::matrix<T, 1, rotgen::Dynamic, rotgen::RowMajor>> row_map(
for(rotgen::Index i=0;i<12;i++) data, 12);
TTS_EQUAL(row_map(i), data[i]); for (rotgen::Index i = 0; i < 12; i++) TTS_EQUAL(row_map(i), data[i]);
rotgen::map<rotgen::matrix<T,1,rotgen::Dynamic,rotgen::RowMajor> const> const_row_map(data,12); rotgen::map<rotgen::matrix<T, 1, rotgen::Dynamic, rotgen::RowMajor> const>
for(rotgen::Index i=0;i<12;i++) const_row_map(data, 12);
TTS_EQUAL(const_row_map(i), data[i]); for (rotgen::Index i = 0; i < 12; i++) TTS_EQUAL(const_row_map(i), data[i]);
rotgen::map<rotgen::matrix<T,rotgen::Dynamic,1,rotgen::ColMajor>> col_map(data,12); rotgen::map<rotgen::matrix<T, rotgen::Dynamic, 1, rotgen::ColMajor>> col_map(
for(rotgen::Index i=0;i<12;i++) data, 12);
TTS_EQUAL(col_map(i), data[i]); for (rotgen::Index i = 0; i < 12; i++) TTS_EQUAL(col_map(i), data[i]);
rotgen::map<rotgen::matrix<T,rotgen::Dynamic,1,rotgen::ColMajor> const> const_col_map(data,12); rotgen::map<rotgen::matrix<T, rotgen::Dynamic, 1, rotgen::ColMajor> const>
for(rotgen::Index i=0;i<12;i++) const_col_map(data, 12);
TTS_EQUAL(const_col_map(i), data[i]); for (rotgen::Index i = 0; i < 12; i++) TTS_EQUAL(const_col_map(i), data[i]);
}; };
TTS_CASE_TPL("map constructor from pointer and dynamic size", rotgen::tests::types) TTS_CASE_TPL("map constructor from pointer and dynamic size",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
using base = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>; using base = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
T data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; T data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
rotgen::map<base> dyn_map(data,4,3); rotgen::map<base> dyn_map(data, 4, 3);
for(rotgen::Index i=0;i<4;i++) for (rotgen::Index i = 0; i < 4; i++)
{ {
for(rotgen::Index j=0;j<3;j++) for (rotgen::Index j = 0; j < 3; j++)
{ {
if constexpr(O::value) TTS_EQUAL(dyn_map(i,j), data[j+3*i]); if constexpr (O::value) TTS_EQUAL(dyn_map(i, j), data[j + 3 * i]);
else TTS_EQUAL(dyn_map(i,j), data[i+4*j]); else TTS_EQUAL(dyn_map(i, j), data[i + 4 * j]);
} }
} }
}; };

View file

@ -9,33 +9,38 @@
#include "unit/common/cwise.hpp" #include "unit/common/cwise.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic map cwise operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic map cwise operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_matrix_references(); auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases) for (auto const& [rows, cols, fn] : cases)
{ {
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> base(rows,
rotgen::tests::prepare(rows,cols,fn,base); cols);
rotgen::tests::prepare(rows, cols, fn, base);
rotgen::map<rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>> input(base.data(),rows,cols); rotgen::map<rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>>
input(base.data(), rows, cols);
rotgen::tests::check_cwise_functions(input); rotgen::tests::check_cwise_functions(input);
} }
}; };
TTS_CASE_TPL("Test static map cwise operations", rotgen::tests::types) TTS_CASE_TPL("Test static map cwise operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_matrix_references(); auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc) auto process = []<typename D>(D const& desc) {
{ rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> base(D::rows,
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(D::rows,D::cols); D::cols);
rotgen::tests::prepare(base.rows(),base.cols(),desc.init_fn,base); rotgen::tests::prepare(base.rows(), base.cols(), desc.init_fn, base);
rotgen::map<rotgen::matrix<T,D::rows,D::cols,O::value>> input(base.data()); rotgen::map<rotgen::matrix<T, D::rows, D::cols, O::value>> input(
base.data());
rotgen::tests::check_cwise_functions(input); rotgen::tests::check_cwise_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };

View file

@ -9,33 +9,38 @@
#include "unit/common/norms.hpp" #include "unit/common/norms.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic map norm operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic map norm operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_matrix_references(); auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases) for (auto const& [rows, cols, fn] : cases)
{ {
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> base(rows,
rotgen::tests::prepare(rows,cols,fn,base); cols);
rotgen::tests::prepare(rows, cols, fn, base);
rotgen::map<rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>> input(base.data(),rows,cols); rotgen::map<rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>>
input(base.data(), rows, cols);
rotgen::tests::check_norms_functions(input); rotgen::tests::check_norms_functions(input);
} }
}; };
TTS_CASE_TPL("Test static map norm operations", rotgen::tests::types) TTS_CASE_TPL("Test static map norm operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_matrix_references(); auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc) auto process = []<typename D>(D const& desc) {
{ rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> base(D::rows,
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(D::rows,D::cols); D::cols);
rotgen::tests::prepare(base.rows(),base.cols(),desc.init_fn,base); rotgen::tests::prepare(base.rows(), base.cols(), desc.init_fn, base);
rotgen::map<rotgen::matrix<T,D::rows,D::cols,O::value>> input(base.data()); rotgen::map<rotgen::matrix<T, D::rows, D::cols, O::value>> input(
base.data());
rotgen::tests::check_norms_functions(input); rotgen::tests::check_norms_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };

View file

@ -9,8 +9,13 @@
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
#include <vector> #include <vector>
template <typename MatrixType> template<typename MatrixType>
void test_map_operations(rotgen::Index rows, rotgen::Index cols, auto a_init_fn, auto b_init_fn, auto ops, auto self_ops) void test_map_operations(rotgen::Index rows,
rotgen::Index cols,
auto a_init_fn,
auto b_init_fn,
auto ops,
auto self_ops)
{ {
MatrixType a_data(rows, cols); MatrixType a_data(rows, cols);
MatrixType b_data(rows, cols); MatrixType b_data(rows, cols);
@ -19,8 +24,8 @@ void test_map_operations(rotgen::Index rows, rotgen::Index cols, auto a_init_fn,
for (rotgen::Index r = 0; r < rows; ++r) for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c)
{ {
a_data(r,c) = a_init_fn(r, c); a_data(r, c) = a_init_fn(r, c);
b_data(r,c) = b_init_fn(r, c); b_data(r, c) = b_init_fn(r, c);
} }
ref_data = ops(a_data, b_data); ref_data = ops(a_data, b_data);
@ -35,15 +40,19 @@ void test_map_operations(rotgen::Index rows, rotgen::Index cols, auto a_init_fn,
TTS_EXPECT(verify_rotgen_reentrance(self_ops(a_map, b_map))); TTS_EXPECT(verify_rotgen_reentrance(self_ops(a_map, b_map)));
} }
template <typename MatrixType> template<typename MatrixType>
void test_map_scalar_operations(rotgen::Index rows, rotgen::Index cols, auto fn, auto s, auto ops, auto self_ops) void test_map_scalar_operations(rotgen::Index rows,
rotgen::Index cols,
auto fn,
auto s,
auto ops,
auto self_ops)
{ {
MatrixType a_data(rows, cols); MatrixType a_data(rows, cols);
MatrixType ref_data; MatrixType ref_data;
for (rotgen::Index r = 0; r < rows; ++r) for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c) a_data(r, c) = fn(r, c);
a_data(r,c) = fn(r, c);
ref_data = ops(a_data, s); ref_data = ops(a_data, s);
rotgen::map<MatrixType> a_map(a_data.data(), rows, cols); rotgen::map<MatrixType> a_map(a_data.data(), rows, cols);
@ -56,15 +65,17 @@ void test_map_scalar_operations(rotgen::Index rows, rotgen::Index cols, auto fn,
TTS_EXPECT(verify_rotgen_reentrance(self_ops(a_map, s))); TTS_EXPECT(verify_rotgen_reentrance(self_ops(a_map, s)));
} }
template <typename MatrixType> template<typename MatrixType>
void test_map_scalar_multiplications(rotgen::Index rows, rotgen::Index cols, auto fn, auto s) void test_map_scalar_multiplications(rotgen::Index rows,
rotgen::Index cols,
auto fn,
auto s)
{ {
MatrixType a_data(rows, cols); MatrixType a_data(rows, cols);
MatrixType ref_data; MatrixType ref_data;
for (rotgen::Index r = 0; r < rows; ++r) for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c) a_data(r, c) = fn(r, c);
a_data(r,c) = fn(r, c);
ref_data = a_data * s; ref_data = a_data * s;
rotgen::map<MatrixType> a_map(a_data.data(), rows, cols); rotgen::map<MatrixType> a_map(a_data.data(), rows, cols);
@ -79,8 +90,11 @@ void test_map_scalar_multiplications(rotgen::Index rows, rotgen::Index cols, aut
TTS_EXPECT(verify_rotgen_reentrance(a_map *= s)); TTS_EXPECT(verify_rotgen_reentrance(a_map *= s));
} }
template <typename MatrixType> template<typename MatrixType>
void test_map_multiplication(rotgen::Index rows, rotgen::Index cols, auto a_init_fn, auto b_init_fn) void test_map_multiplication(rotgen::Index rows,
rotgen::Index cols,
auto a_init_fn,
auto b_init_fn)
{ {
MatrixType a_data(rows, cols); MatrixType a_data(rows, cols);
MatrixType b_data(cols, rows); MatrixType b_data(cols, rows);
@ -89,8 +103,8 @@ void test_map_multiplication(rotgen::Index rows, rotgen::Index cols, auto a_init
for (rotgen::Index r = 0; r < rows; ++r) for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c)
{ {
a_data(r,c) = a_init_fn(r,c); a_data(r, c) = a_init_fn(r, c);
b_data(c,r) = b_init_fn(c,r); b_data(c, r) = b_init_fn(c, r);
} }
ref_data = a_data * b_data; ref_data = a_data * b_data;
@ -100,103 +114,111 @@ void test_map_multiplication(rotgen::Index rows, rotgen::Index cols, auto a_init
TTS_EQUAL(a_map * b_map, ref_data); TTS_EQUAL(a_map * b_map, ref_data);
TTS_EXPECT(verify_rotgen_reentrance(a_map * b_map)); TTS_EXPECT(verify_rotgen_reentrance(a_map * b_map));
if(rows == cols) if (rows == cols)
{ {
a_map *= b_map; a_map *= b_map;
TTS_EQUAL(a_map, ref_data); TTS_EQUAL(a_map, ref_data);
TTS_EXPECT(verify_rotgen_reentrance(a_map *= b_map)); TTS_EXPECT(verify_rotgen_reentrance(a_map *= b_map));
} }
} }
inline constexpr auto init_a = [](auto r, auto c) { return 9.9*r*r*r - 6*c - 12; }; inline constexpr auto init_a = [](auto r, auto c) {
inline constexpr auto init_b = [](auto r, auto c) { return 3.1*r + 4.2*c - 12.3; }; return 9.9 * r * r * r - 6 * c - 12;
inline constexpr auto init_0 = [](auto , auto ) { return 0; }; };
inline constexpr auto init_b = [](auto r, auto c) {
return 3.1 * r + 4.2 * c - 12.3;
};
inline constexpr auto init_0 = [](auto, auto) { return 0; };
TTS_CASE_TPL("Check map addition", rotgen::tests::types) TTS_CASE_TPL("Check map addition",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto op = [](auto a, auto b) { return a + b; }; auto op = [](auto a, auto b) { return a + b; };
auto s_op = [](auto& a, auto b) { return a += b; }; auto s_op = [](auto& a, auto b) { return a += b; };
test_map_operations<mat_t>(1 , 1, init_a, init_b, op, s_op); test_map_operations<mat_t>(1, 1, init_a, init_b, op, s_op);
test_map_operations<mat_t>(3 , 5, init_a, init_b, op, s_op); test_map_operations<mat_t>(3, 5, init_a, init_b, op, s_op);
test_map_operations<mat_t>(5 , 3, init_a, init_b, op, s_op); test_map_operations<mat_t>(5, 3, init_a, init_b, op, s_op);
test_map_operations<mat_t>(5 , 5, init_a, init_b, op, s_op); test_map_operations<mat_t>(5, 5, init_a, init_b, op, s_op);
test_map_operations<mat_t>(5 , 5, init_b, init_a, op, s_op); test_map_operations<mat_t>(5, 5, init_b, init_a, op, s_op);
test_map_operations<mat_t>(10, 1, init_a, init_b, op, s_op); test_map_operations<mat_t>(10, 1, init_a, init_b, op, s_op);
test_map_operations<mat_t>(1 ,10, init_a, init_b, op, s_op); test_map_operations<mat_t>(1, 10, init_a, init_b, op, s_op);
test_map_operations<mat_t>(5 , 5, init_0, init_b, op, s_op); test_map_operations<mat_t>(5, 5, init_0, init_b, op, s_op);
test_map_operations<mat_t>(5 , 5, init_a, init_0, op, s_op); test_map_operations<mat_t>(5, 5, init_a, init_0, op, s_op);
}; };
TTS_CASE_TPL("Check map subtraction", rotgen::tests::types) TTS_CASE_TPL("Check map subtraction",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto op = [](auto a, auto b) { return a - b; }; auto op = [](auto a, auto b) { return a - b; };
auto s_op = [](auto& a, auto b) { return a -= b; }; auto s_op = [](auto& a, auto b) { return a -= b; };
test_map_operations<mat_t>(1 , 1, init_a, init_b, op, s_op); test_map_operations<mat_t>(1, 1, init_a, init_b, op, s_op);
test_map_operations<mat_t>(3 , 5, init_a, init_b, op, s_op); test_map_operations<mat_t>(3, 5, init_a, init_b, op, s_op);
test_map_operations<mat_t>(5 , 3, init_a, init_b, op, s_op); test_map_operations<mat_t>(5, 3, init_a, init_b, op, s_op);
test_map_operations<mat_t>(5 , 5, init_a, init_b, op, s_op); test_map_operations<mat_t>(5, 5, init_a, init_b, op, s_op);
test_map_operations<mat_t>(5 , 5, init_b, init_a, op, s_op); test_map_operations<mat_t>(5, 5, init_b, init_a, op, s_op);
test_map_operations<mat_t>(10, 1, init_a, init_b, op, s_op); test_map_operations<mat_t>(10, 1, init_a, init_b, op, s_op);
test_map_operations<mat_t>(1 ,10, init_a, init_b, op, s_op); test_map_operations<mat_t>(1, 10, init_a, init_b, op, s_op);
test_map_operations<mat_t>(5 , 5, init_0, init_b, op, s_op); test_map_operations<mat_t>(5, 5, init_0, init_b, op, s_op);
test_map_operations<mat_t>(5 , 5, init_a, init_0, op, s_op); test_map_operations<mat_t>(5, 5, init_a, init_0, op, s_op);
}; };
TTS_CASE_TPL("Check map multiplications", rotgen::tests::types) TTS_CASE_TPL("Check map multiplications",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto init_id = [](auto r, auto c) { return r == c ? 1 : 0; }; auto init_id = [](auto r, auto c) { return r == c ? 1 : 0; };
test_map_multiplication<mat_t>(1 , 1, init_a , init_b ); test_map_multiplication<mat_t>(1, 1, init_a, init_b);
test_map_multiplication<mat_t>(3 , 5, init_a , init_b ); test_map_multiplication<mat_t>(3, 5, init_a, init_b);
test_map_multiplication<mat_t>(5 , 3, init_a , init_b ); test_map_multiplication<mat_t>(5, 3, init_a, init_b);
test_map_multiplication<mat_t>(5 , 5, init_a , init_b ); test_map_multiplication<mat_t>(5, 5, init_a, init_b);
test_map_multiplication<mat_t>(5 , 5, init_b , init_a ); test_map_multiplication<mat_t>(5, 5, init_b, init_a);
test_map_multiplication<mat_t>(5 , 5, init_a , init_a ); test_map_multiplication<mat_t>(5, 5, init_a, init_a);
test_map_multiplication<mat_t>(5 , 5, init_a , init_id); test_map_multiplication<mat_t>(5, 5, init_a, init_id);
test_map_multiplication<mat_t>(5 , 5, init_id, init_a ); test_map_multiplication<mat_t>(5, 5, init_id, init_a);
test_map_multiplication<mat_t>(10, 1, init_a , init_b ); test_map_multiplication<mat_t>(10, 1, init_a, init_b);
test_map_multiplication<mat_t>(1 ,10, init_a , init_b ); test_map_multiplication<mat_t>(1, 10, init_a, init_b);
test_map_multiplication<mat_t>(5 , 5, init_0 , init_b ); test_map_multiplication<mat_t>(5, 5, init_0, init_b);
test_map_multiplication<mat_t>(5 , 5, init_a , init_0 ); test_map_multiplication<mat_t>(5, 5, init_a, init_0);
}; };
TTS_CASE_TPL("Check map multiplication with scalar", rotgen::tests::types) TTS_CASE_TPL("Check map multiplication with scalar",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
test_map_scalar_multiplications<mat_t>(1 , 1, init_a, T{ 3.5}); test_map_scalar_multiplications<mat_t>(1, 1, init_a, T{3.5});
test_map_scalar_multiplications<mat_t>(3 , 5, init_a, T{-2.5}); test_map_scalar_multiplications<mat_t>(3, 5, init_a, T{-2.5});
test_map_scalar_multiplications<mat_t>(5 , 3, init_a, T{ 4. }); test_map_scalar_multiplications<mat_t>(5, 3, init_a, T{4.});
test_map_scalar_multiplications<mat_t>(5 , 5, init_a, T{-5. }); test_map_scalar_multiplications<mat_t>(5, 5, init_a, T{-5.});
test_map_scalar_multiplications<mat_t>(5 , 5, init_a, T{ 1. }); test_map_scalar_multiplications<mat_t>(5, 5, init_a, T{1.});
test_map_scalar_multiplications<mat_t>(5 , 5, init_a, T{ 6. }); test_map_scalar_multiplications<mat_t>(5, 5, init_a, T{6.});
test_map_scalar_multiplications<mat_t>(10, 1, init_a, T{ 10.}); test_map_scalar_multiplications<mat_t>(10, 1, init_a, T{10.});
test_map_scalar_multiplications<mat_t>(1 ,10, init_a, T{-0.5}); test_map_scalar_multiplications<mat_t>(1, 10, init_a, T{-0.5});
}; };
TTS_CASE_TPL("Check map division with scalar", rotgen::tests::types) TTS_CASE_TPL("Check map division with scalar",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto op = [](auto a, auto b) { return a / b; }; auto op = [](auto a, auto b) { return a / b; };
auto s_op = [](auto& a, auto b) { return a /= b; }; auto s_op = [](auto& a, auto b) { return a /= b; };
test_map_scalar_operations<mat_t>(1 , 1, init_a, T{ 3.5}, op, s_op); test_map_scalar_operations<mat_t>(1, 1, init_a, T{3.5}, op, s_op);
test_map_scalar_operations<mat_t>(3 , 5, init_a, T{-2.5}, op, s_op); test_map_scalar_operations<mat_t>(3, 5, init_a, T{-2.5}, op, s_op);
test_map_scalar_operations<mat_t>(5 , 3, init_a, T{ 4. }, op, s_op); test_map_scalar_operations<mat_t>(5, 3, init_a, T{4.}, op, s_op);
test_map_scalar_operations<mat_t>(5 , 5, init_a, T{-5. }, op, s_op); test_map_scalar_operations<mat_t>(5, 5, init_a, T{-5.}, op, s_op);
test_map_scalar_operations<mat_t>(5 , 5, init_a, T{ 1. }, op, s_op); test_map_scalar_operations<mat_t>(5, 5, init_a, T{1.}, op, s_op);
test_map_scalar_operations<mat_t>(5 , 5, init_a, T{ 6. }, op, s_op); test_map_scalar_operations<mat_t>(5, 5, init_a, T{6.}, op, s_op);
test_map_scalar_operations<mat_t>(10, 1, init_a, T{ 10.}, op, s_op); test_map_scalar_operations<mat_t>(10, 1, init_a, T{10.}, op, s_op);
test_map_scalar_operations<mat_t>(1 ,10, init_a, T{-0.5}, op, s_op); test_map_scalar_operations<mat_t>(1, 10, init_a, T{-0.5}, op, s_op);
}; };

View file

@ -15,132 +15,138 @@ auto generate_data(int rows, int cols)
std::vector<float> buffer(rows * cols * 3); std::vector<float> buffer(rows * cols * 3);
for (size_t i = 0; i < buffer.size(); ++i) for (size_t i = 0; i < buffer.size(); ++i)
buffer[i] = static_cast<float>(1+i); buffer[i] = static_cast<float>(1 + i);
return buffer; return buffer;
} }
template<int O> template<int O>
using r_mat_t = rotgen::matrix<float,rotgen::Dynamic,rotgen::Dynamic,O>; using r_mat_t = rotgen::matrix<float, rotgen::Dynamic, rotgen::Dynamic, O>;
template<int O> template<int O>
using e_mat_t = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,O>; using e_mat_t = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, O>;
template<typename M, typename S = rotgen::stride> using r_map_t = rotgen::map<M,0,S>; template<typename M, typename S = rotgen::stride>
template<typename M, typename S = Eigen::Stride<0,0>> using e_map_t = Eigen::Map<M,0,S>; 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>;
TTS_CASE("Validate Column Major Map with regular stride behavior") TTS_CASE("Validate Column Major Map with regular stride behavior")
{ {
auto rows = 3; auto rows = 3;
auto cols = 4; auto cols = 4;
auto buffer = generate_data(rows,cols); auto buffer = generate_data(rows, cols);
r_map_t<r_mat_t<rotgen::ColMajor>> r_map(buffer.data(), rows, cols); r_map_t<r_mat_t<rotgen::ColMajor>> r_map(buffer.data(), rows, cols);
TTS_EQUAL(r_map.innerStride(), 1); TTS_EQUAL(r_map.innerStride(), 1);
TTS_EQUAL(r_map.outerStride(), 3); TTS_EQUAL(r_map.outerStride(), 3);
e_map_t<e_mat_t<Eigen::ColMajor>> e_map(buffer.data(), rows, cols); e_map_t<e_mat_t<Eigen::ColMajor>> e_map(buffer.data(), rows, cols);
for(std::ptrdiff_t r=0;r<rows;r++) for (std::ptrdiff_t r = 0; r < rows; r++)
for(std::ptrdiff_t c=0;c<cols;c++) for (std::ptrdiff_t c = 0; c < cols; c++)
TTS_EQUAL(r_map(r,c), e_map(r,c)); TTS_EQUAL(r_map(r, c), e_map(r, c));
}; };
TTS_CASE("Validate Column Major Map with specific outer stride behavior") TTS_CASE("Validate Column Major Map with specific outer stride behavior")
{ {
auto rows = 3; auto rows = 3;
auto cols = 4; auto cols = 4;
auto buffer = generate_data(rows,cols); auto buffer = generate_data(rows, cols);
r_map_t<r_mat_t<rotgen::ColMajor>, rotgen::outer_stride<>> r_map_t<r_mat_t<rotgen::ColMajor>, rotgen::outer_stride<>> r_map(
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.innerStride(), 1);
TTS_EQUAL(r_map.outerStride() , 4); TTS_EQUAL(r_map.outerStride(), 4);
e_map_t<e_mat_t<Eigen::ColMajor>, Eigen::OuterStride<>> e_map_t<e_mat_t<Eigen::ColMajor>, Eigen::OuterStride<>> e_map(
e_map(buffer.data(), rows, cols, Eigen::OuterStride<>(rows + 1)); buffer.data(), rows, cols, Eigen::OuterStride<>(rows + 1));
for(std::ptrdiff_t r=0;r<rows;r++) for (std::ptrdiff_t r = 0; r < rows; r++)
for(std::ptrdiff_t c=0;c<cols;c++) for (std::ptrdiff_t c = 0; c < cols; c++)
TTS_EQUAL(r_map(r,c), e_map(r,c)); TTS_EQUAL(r_map(r, c), e_map(r, c));
}; };
TTS_CASE("Validate Column Major Map with specific inner stride behavior") TTS_CASE("Validate Column Major Map with specific inner stride behavior")
{ {
auto rows = 3; auto rows = 3;
auto cols = 4; auto cols = 4;
auto buffer = generate_data(rows,cols); auto buffer = generate_data(rows, cols);
r_map_t<r_mat_t<rotgen::ColMajor>> r_map_t<r_mat_t<rotgen::ColMajor>> r_map(buffer.data(), rows, cols,
r_map(buffer.data(), rows, cols, rotgen::stride(rows, 2)); rotgen::stride(rows, 2));
TTS_EQUAL(r_map.innerStride(), 2); TTS_EQUAL(r_map.innerStride(), 2);
TTS_EQUAL(r_map.outerStride() , 3); TTS_EQUAL(r_map.outerStride(), 3);
e_map_t<e_mat_t<Eigen::ColMajor>,Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>> e_map_t<e_mat_t<Eigen::ColMajor>,
e_map(buffer.data(), rows, cols, Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>(rows,2)); Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>>
e_map(buffer.data(), rows, cols,
Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>(rows, 2));
for(std::ptrdiff_t r=0;r<rows;r++) for (std::ptrdiff_t r = 0; r < rows; r++)
for(std::ptrdiff_t c=0;c<cols;c++) for (std::ptrdiff_t c = 0; c < cols; c++)
TTS_EQUAL(r_map(r,c), e_map(r,c)); TTS_EQUAL(r_map(r, c), e_map(r, c));
}; };
TTS_CASE("Validate Row Major Map with regular stride behavior") TTS_CASE("Validate Row Major Map with regular stride behavior")
{ {
auto rows = 3; auto rows = 3;
auto cols = 4; auto cols = 4;
auto buffer = generate_data(rows,cols); auto buffer = generate_data(rows, cols);
r_map_t<r_mat_t<rotgen::RowMajor>> r_map(buffer.data(), rows, cols); r_map_t<r_mat_t<rotgen::RowMajor>> r_map(buffer.data(), rows, cols);
TTS_EQUAL(r_map.innerStride(), 1); TTS_EQUAL(r_map.innerStride(), 1);
TTS_EQUAL(r_map.outerStride(), 4); TTS_EQUAL(r_map.outerStride(), 4);
e_map_t<e_mat_t<Eigen::RowMajor>> e_map(buffer.data(), rows, cols); e_map_t<e_mat_t<Eigen::RowMajor>> e_map(buffer.data(), rows, cols);
for(std::ptrdiff_t r=0;r<rows;r++) for (std::ptrdiff_t r = 0; r < rows; r++)
for(std::ptrdiff_t c=0;c<cols;c++) for (std::ptrdiff_t c = 0; c < cols; c++)
TTS_EQUAL(r_map(r,c), e_map(r,c)); TTS_EQUAL(r_map(r, c), e_map(r, c));
}; };
TTS_CASE("Validate Row Major Map with specific outer stride behavior") TTS_CASE("Validate Row Major Map with specific outer stride behavior")
{ {
auto rows = 3; auto rows = 3;
auto cols = 4; auto cols = 4;
auto buffer = generate_data(rows,cols); auto buffer = generate_data(rows, cols);
r_map_t<r_mat_t<rotgen::RowMajor>, rotgen::outer_stride<>> r_map_t<r_mat_t<rotgen::RowMajor>, rotgen::outer_stride<>> r_map(
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.innerStride(), 1);
TTS_EQUAL(r_map.outerStride() , 5); TTS_EQUAL(r_map.outerStride(), 5);
e_map_t<e_mat_t<Eigen::RowMajor>, Eigen::OuterStride<>> e_map_t<e_mat_t<Eigen::RowMajor>, Eigen::OuterStride<>> e_map(
e_map(buffer.data(), rows, cols, Eigen::OuterStride<>(cols + 1)); buffer.data(), rows, cols, Eigen::OuterStride<>(cols + 1));
for(std::ptrdiff_t r=0;r<rows;r++) for (std::ptrdiff_t r = 0; r < rows; r++)
for(std::ptrdiff_t c=0;c<cols;c++) for (std::ptrdiff_t c = 0; c < cols; c++)
TTS_EQUAL(r_map(r,c), e_map(r,c)); TTS_EQUAL(r_map(r, c), e_map(r, c));
}; };
TTS_CASE("Validate Row Major Map with specific inner stride behavior") TTS_CASE("Validate Row Major Map with specific inner stride behavior")
{ {
auto rows = 3; auto rows = 3;
auto cols = 4; auto cols = 4;
auto buffer = generate_data(rows,cols); auto buffer = generate_data(rows, cols);
r_map_t<r_mat_t<rotgen::RowMajor>,rotgen::stride> r_map_t<r_mat_t<rotgen::RowMajor>, rotgen::stride> r_map(
r_map(buffer.data(), rows, cols, rotgen::stride(2, cols)); buffer.data(), rows, cols, rotgen::stride(2, cols));
TTS_EQUAL(r_map.innerStride(), 4); TTS_EQUAL(r_map.innerStride(), 4);
TTS_EQUAL(r_map.outerStride() , 2); TTS_EQUAL(r_map.outerStride(), 2);
e_map_t<e_mat_t<Eigen::RowMajor>,Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>> e_map_t<e_mat_t<Eigen::RowMajor>,
e_map(buffer.data(), rows, cols, Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>(2,cols)); Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>>
e_map(buffer.data(), rows, cols,
Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>(2, cols));
for(std::ptrdiff_t r=0;r<rows;r++) for (std::ptrdiff_t r = 0; r < rows; r++)
for(std::ptrdiff_t c=0;c<cols;c++) for (std::ptrdiff_t c = 0; c < cols; c++)
TTS_EQUAL(r_map(r,c), e_map(r,c)); TTS_EQUAL(r_map(r, c), e_map(r, c));
}; };

View file

@ -9,88 +9,90 @@
#include "unit/common/arithmetic.hpp" #include "unit/common/arithmetic.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic matrix transposition-like operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic matrix transposition-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_matrix_references(); auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases) for (auto const& [rows, cols, fn] : cases)
{ {
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> input(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> input(rows,
rotgen::tests::prepare(rows,cols,fn,input); cols);
rotgen::tests::prepare(rows, cols, fn, input);
rotgen::tests::check_shape_functions(input); rotgen::tests::check_shape_functions(input);
} }
}; };
TTS_CASE_TPL("Test static matrix transposition-like operations", rotgen::tests::types) TTS_CASE_TPL("Test static matrix transposition-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_matrix_references(); auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc) auto process = []<typename D>(D const& desc) {
{ rotgen::matrix<T, D::rows, D::cols, O::value> input;
rotgen::matrix<T,D::rows,D::cols,O::value> input; rotgen::tests::prepare(input.rows(), input.cols(), desc.init_fn, input);
rotgen::tests::prepare(input.rows(),input.cols(),desc.init_fn,input);
rotgen::tests::check_shape_functions(input); rotgen::tests::check_shape_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };
TTS_CASE_TPL("Test dynamic matrix reduction-like operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic matrix reduction-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_matrix_references(); auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases) for (auto const& [rows, cols, fn] : cases)
{ {
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> input(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> input(rows,
rotgen::tests::prepare(rows,cols,fn,input); cols);
rotgen::tests::prepare(rows, cols, fn, input);
rotgen::tests::check_reduction_functions(input); rotgen::tests::check_reduction_functions(input);
} }
}; };
TTS_CASE_TPL("Test static matrix reduction-like operations", rotgen::tests::types) TTS_CASE_TPL("Test static matrix reduction-like operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_matrix_references(); auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc) auto process = []<typename D>(D const& desc) {
{ rotgen::matrix<T, D::rows, D::cols, O::value> input;
rotgen::matrix<T,D::rows,D::cols,O::value> input; rotgen::tests::prepare(input.rows(), input.cols(), desc.init_fn, input);
rotgen::tests::prepare(input.rows(),input.cols(),desc.init_fn,input);
rotgen::tests::check_reduction_functions(input); rotgen::tests::check_reduction_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };
TTS_CASE_TPL("Test dot product", float, double) TTS_CASE_TPL("Test dot product", float, double)<typename T>(tts::type<T>){
<typename T>( tts::type<T> ) {auto a = rotgen::setConstant<rotgen::matrix<T, 1, rotgen::Dynamic>>(1, 8, 2);
auto b = rotgen::setConstant<rotgen::matrix<T, 1, rotgen::Dynamic>>(1, 8, 2);
TTS_EQUAL(rotgen::dot(a, b), 32);
}
{ {
{ auto a = rotgen::setConstant<rotgen::matrix<T, rotgen::Dynamic, 1>>(8, 1, 2);
auto a = rotgen::setConstant<rotgen::matrix<T,1,rotgen::Dynamic>>(1,8,2); auto b = rotgen::setConstant<rotgen::matrix<T, rotgen::Dynamic, 1>>(8, 1, 2);
auto b = rotgen::setConstant<rotgen::matrix<T,1,rotgen::Dynamic>>(1,8,2);
TTS_EQUAL(rotgen::dot(a,b), 32); TTS_EQUAL(rotgen::dot(a, b), 32);
} }
{ {
auto a = rotgen::setConstant<rotgen::matrix<T,rotgen::Dynamic,1>>(8,1,2); auto a = rotgen::setConstant<rotgen::matrix<T, 1, 8>>(2);
auto b = rotgen::setConstant<rotgen::matrix<T,rotgen::Dynamic,1>>(8,1,2); auto b = rotgen::setConstant<rotgen::matrix<T, 1, 8>>(2);
TTS_EQUAL(rotgen::dot(a,b), 32); TTS_EQUAL(rotgen::dot(a, b), 32);
} }
{ {
auto a = rotgen::setConstant<rotgen::matrix<T,1,8>>(2); auto a = rotgen::setConstant<rotgen::matrix<T, 8, 1>>(2);
auto b = rotgen::setConstant<rotgen::matrix<T,1,8>>(2); auto b = rotgen::setConstant<rotgen::matrix<T, 8, 1>>(2);
TTS_EQUAL(rotgen::dot(a,b), 32); TTS_EQUAL(rotgen::dot(a, b), 32);
} }
}
{ ;
auto a = rotgen::setConstant<rotgen::matrix<T,8,1>>(2);
auto b = rotgen::setConstant<rotgen::matrix<T,8,1>>(2);
TTS_EQUAL(rotgen::dot(a,b), 32);
}
};

View file

@ -8,13 +8,15 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Function size", rotgen::tests::types) TTS_CASE_TPL("Function size", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> empty_matrix; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> empty_matrix;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> matrix(3,4); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> matrix(3, 4);
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> row_vector(9,1); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> row_vector(9,
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> column_vector(1,5); 1);
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> column_vector(
1, 5);
TTS_EQUAL(empty_matrix.size(), rotgen::Index{0}); TTS_EQUAL(empty_matrix.size(), rotgen::Index{0});
TTS_EQUAL(matrix.size(), rotgen::Index{12}); TTS_EQUAL(matrix.size(), rotgen::Index{12});
@ -22,72 +24,69 @@ TTS_CASE_TPL("Function size", rotgen::tests::types)
TTS_EQUAL(column_vector.size(), rotgen::Index{5}); TTS_EQUAL(column_vector.size(), rotgen::Index{5});
}; };
TTS_CASE_TPL("Resizing dynamic matrix", rotgen::tests::types) TTS_CASE_TPL("Resizing dynamic matrix",
<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(2, 3); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> a(2, 3);
for(rotgen::Index r=0;r<a.rows();++r) for (rotgen::Index r = 0; r < a.rows(); ++r)
for(rotgen::Index c=0;c<a.cols();++c) for (rotgen::Index c = 0; c < a.cols(); ++c) a(r, c) = 42 + 2 * c + r;
a(r,c) = 42 + 2*c + r;
a.resize(3, 2); a.resize(3, 2);
TTS_EQUAL(a.rows(), rotgen::Index(3)); TTS_EQUAL(a.rows(), rotgen::Index(3));
TTS_EQUAL(a.cols(), rotgen::Index(2)); TTS_EQUAL(a.cols(), rotgen::Index(2));
for(rotgen::Index r=0;r<a.rows();++r) for (rotgen::Index r = 0; r < a.rows(); ++r)
for(rotgen::Index c=0;c<a.cols();++c) for (rotgen::Index c = 0; c < a.cols(); ++c) TTS_GREATER(a(r, c), 0);
TTS_GREATER(a(r,c),0);
a.resize(2,2); a.resize(2, 2);
TTS_EQUAL(a.rows(), rotgen::Index(2)); TTS_EQUAL(a.rows(), rotgen::Index(2));
TTS_EQUAL(a.cols(), rotgen::Index(2)); TTS_EQUAL(a.cols(), rotgen::Index(2));
}; };
TTS_CASE_TPL("Dynamix matrix conservative resizing", rotgen::tests::types) TTS_CASE_TPL("Dynamix matrix conservative resizing",
<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(2, 3); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> a(2, 3);
int i = 1; int i = 1;
for(rotgen::Index r=0;r<a.rows();++r) for (rotgen::Index r = 0; r < a.rows(); ++r)
for(rotgen::Index c=0;c<a.cols();++c) for (rotgen::Index c = 0; c < a.cols(); ++c) a(r, c) = i++;
a(r, c) = i++;
a.conservativeResize(2, 3); a.conservativeResize(2, 3);
TTS_EQUAL(a.rows(), rotgen::Index(2)); TTS_EQUAL(a.rows(), rotgen::Index(2));
TTS_EQUAL(a.cols(), rotgen::Index(3)); TTS_EQUAL(a.cols(), rotgen::Index(3));
i = 1; i = 1;
for(rotgen::Index r=0;r<a.rows();++r) for (rotgen::Index r = 0; r < a.rows(); ++r)
for(rotgen::Index c=0;c<a.cols();++c) for (rotgen::Index c = 0; c < a.cols(); ++c) TTS_EQUAL(a(r, c), i++);
TTS_EQUAL(a(r,c),i++);
a.conservativeResize(3, 2); a.conservativeResize(3, 2);
TTS_EQUAL(a.rows(), rotgen::Index(3)); TTS_EQUAL(a.rows(), rotgen::Index(3));
TTS_EQUAL(a.cols(), rotgen::Index(2)); TTS_EQUAL(a.cols(), rotgen::Index(2));
int expected[3][2] = { {1, 2}, {4, 5} }; int expected[3][2] = {{1, 2}, {4, 5}};
for(rotgen::Index r = 0; r < 2; ++r) for (rotgen::Index r = 0; r < 2; ++r)
for(rotgen::Index c = 0; c < 2; ++c) for (rotgen::Index c = 0; c < 2; ++c) TTS_EQUAL(a(r, c), expected[r][c]);
TTS_EQUAL(a(r, c), expected[r][c]);
a.conservativeResize(4, 4); a.conservativeResize(4, 4);
TTS_EQUAL(a.rows(), rotgen::Index(4)); TTS_EQUAL(a.rows(), rotgen::Index(4));
TTS_EQUAL(a.cols(), rotgen::Index(4)); TTS_EQUAL(a.cols(), rotgen::Index(4));
TTS_EQUAL(a(0,0), 1); TTS_EQUAL(a(0, 0), 1);
TTS_EQUAL(a(3,3), 0); TTS_EQUAL(a(3, 3), 0);
a.conservativeResize(2, 2); a.conservativeResize(2, 2);
TTS_EQUAL(a.rows(), rotgen::Index(2)); TTS_EQUAL(a.rows(), rotgen::Index(2));
TTS_EQUAL(a.cols(), rotgen::Index(2)); TTS_EQUAL(a.cols(), rotgen::Index(2));
TTS_EQUAL(a(0,0), 1); TTS_EQUAL(a(0, 0), 1);
TTS_EQUAL(a(1,1), 5); TTS_EQUAL(a(1, 1), 5);
a.conservativeResize(1, 2); a.conservativeResize(1, 2);
TTS_EQUAL(a.rows(), rotgen::Index(1)); TTS_EQUAL(a.rows(), rotgen::Index(1));
TTS_EQUAL(a.cols(), rotgen::Index(2)); TTS_EQUAL(a.cols(), rotgen::Index(2));
TTS_EQUAL(a(0,0), 1); TTS_EQUAL(a(0, 0), 1);
TTS_EQUAL(a(0,1), 2); TTS_EQUAL(a(0, 1), 2);
a.conservativeResize(0, 0); a.conservativeResize(0, 0);
TTS_EQUAL(a.rows(), rotgen::Index(0)); TTS_EQUAL(a.rows(), rotgen::Index(0));
@ -98,50 +97,48 @@ TTS_CASE_TPL("Dynamix matrix conservative resizing", rotgen::tests::types)
TTS_EQUAL(a.cols(), rotgen::Index(3)); TTS_EQUAL(a.cols(), rotgen::Index(3));
}; };
TTS_CASE_TPL("Test coefficient accessors", rotgen::tests::types) TTS_CASE_TPL("Test coefficient accessors",
<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, 5); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> a(3, 5);
for(rotgen::Index r=0;r<a.rows();++r) for (rotgen::Index r = 0; r < a.rows(); ++r)
for(rotgen::Index c=0;c<a.cols();++c) for (rotgen::Index c = 0; c < a.cols(); ++c) a(r, c) = r + 2 * c + 3;
a(r, c) = r + 2 * c + 3;
TTS_EQUAL(a(0,0), 3); TTS_EQUAL(a(0, 0), 3);
TTS_EQUAL(a(1,1), 6); TTS_EQUAL(a(1, 1), 6);
TTS_EQUAL(a(1,0), 4); TTS_EQUAL(a(1, 0), 4);
TTS_EQUAL(a(2,2), 9); TTS_EQUAL(a(2, 2), 9);
TTS_EQUAL(a(2,4), 13); TTS_EQUAL(a(2, 4), 13);
a(1, 1) = 42; a(1, 1) = 42;
TTS_EQUAL(a(1,1), 42); TTS_EQUAL(a(1, 1), 42);
T& ref = a(2, 2); T& ref = a(2, 2);
ref = 17; ref = 17;
TTS_EQUAL(a(2, 2), 17); TTS_EQUAL(a(2, 2), 17);
}; };
TTS_CASE_TPL("Test one index coefficient accessors", rotgen::tests::types) TTS_CASE_TPL("Test one index coefficient accessors",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto a = [&]() auto a = [&]() {
{ if constexpr (O::value == rotgen::ColMajor)
if constexpr(O::value == rotgen::ColMajor) return rotgen::matrix<T,1,rotgen::Dynamic>(1,8); return rotgen::matrix<T, 1, rotgen::Dynamic>(1, 8);
else return rotgen::matrix<T,rotgen::Dynamic,1>(8,1); else return rotgen::matrix<T, rotgen::Dynamic, 1>(8, 1);
}(); }();
TTS_EXPECT(a.IsVectorAtCompileTime); TTS_EXPECT(a.IsVectorAtCompileTime);
for(rotgen::Index s=0;s<a.size();++s) for (rotgen::Index s = 0; s < a.size(); ++s) a(s) = s + 1;
a(s) = s+1;
int i = 1; int i = 1;
for(rotgen::Index s=0;s<a.size();++s) for (rotgen::Index s = 0; s < a.size(); ++s) TTS_EQUAL(a(s), i++) << a;
TTS_EQUAL(a(s), i++) << a;
i = 1; i = 1;
for(rotgen::Index s=0;s<a.size();++s) for (rotgen::Index s = 0; s < a.size(); ++s) TTS_EQUAL(a[s], i++) << a;
TTS_EQUAL(a[s], i++) << a;
T& ref = a(2); T& ref = a(2);
ref = 999.5; ref = 999.5;

View file

@ -8,38 +8,42 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Default matrix dynamic constructor", rotgen::tests::types) TTS_CASE_TPL("Default matrix dynamic constructor",
<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; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> matrix;
TTS_EQUAL(matrix.rows(), rotgen::Index{0}); TTS_EQUAL(matrix.rows(), rotgen::Index{0});
TTS_EQUAL(matrix.cols(), rotgen::Index{0}); TTS_EQUAL(matrix.cols(), rotgen::Index{0});
}; };
TTS_CASE_TPL("Default matrix static constructor", rotgen::tests::types) TTS_CASE_TPL("Default matrix static constructor",
<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,4,9,O::value> matrix; rotgen::matrix<T, 4, 9, O::value> matrix;
TTS_EQUAL(matrix.rows(), rotgen::Index{4}); TTS_EQUAL(matrix.rows(), rotgen::Index{4});
TTS_EQUAL(matrix.cols(), rotgen::Index{9}); TTS_EQUAL(matrix.cols(), rotgen::Index{9});
}; };
TTS_CASE_TPL("Dynamic matrix constructor with row and columns", rotgen::tests::types) TTS_CASE_TPL("Dynamic matrix constructor with row and columns",
<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); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> matrix(10, 5);
TTS_EQUAL(matrix.rows(), rotgen::Index{10}); TTS_EQUAL(matrix.rows(), rotgen::Index{10});
TTS_EQUAL(matrix.cols(), rotgen::Index{5}); TTS_EQUAL(matrix.cols(), rotgen::Index{5});
}; };
TTS_CASE_TPL("Static matrix constructor with row and columns", float, double) TTS_CASE_TPL("Static matrix constructor with row and columns",
<typename T>( tts::type<T> ) float,
double)<typename T>(tts::type<T>)
{ {
rotgen::matrix<T,1,2> v2(6, 11); rotgen::matrix<T, 1, 2> v2(6, 11);
rotgen::matrix<T,2,1> w2(6, 11); rotgen::matrix<T, 2, 1> w2(6, 11);
TTS_EQUAL(v2(0), T{6}); TTS_EQUAL(v2(0), T{6});
TTS_EQUAL(v2(1), T{11}); TTS_EQUAL(v2(1), T{11});
@ -47,8 +51,8 @@ TTS_CASE_TPL("Static matrix constructor with row and columns", float, double)
TTS_EQUAL(w2(0), T{6}); TTS_EQUAL(w2(0), T{6});
TTS_EQUAL(w2(1), T{11}); TTS_EQUAL(w2(1), T{11});
rotgen::matrix<T,1,3> v3(6, 11, 125); rotgen::matrix<T, 1, 3> v3(6, 11, 125);
rotgen::matrix<T,3,1> w3(6, 11, 125); rotgen::matrix<T, 3, 1> w3(6, 11, 125);
TTS_EQUAL(v3(0), T{6}); TTS_EQUAL(v3(0), T{6});
TTS_EQUAL(v3(1), T{11}); TTS_EQUAL(v3(1), T{11});
@ -59,52 +63,54 @@ TTS_CASE_TPL("Static matrix constructor with row and columns", float, double)
TTS_EQUAL(w3(2), T{125}); 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",
<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); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> a(3, 3);
for(rotgen::Index r=0;r<a.rows();r++) for (rotgen::Index r = 0; r < a.rows(); r++)
for(rotgen::Index c=0;c<a.cols();c++) for (rotgen::Index c = 0; c < a.cols(); c++) a(r, c) = r + c;
a(r,c) = r + c;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> b = a; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> b = a;
TTS_EQUAL(b.rows(), a.rows()); TTS_EQUAL(b.rows(), a.rows());
TTS_EQUAL(b.cols(), a.cols()); TTS_EQUAL(b.cols(), a.cols());
for(rotgen::Index r=0;r<a.rows();r++) for (rotgen::Index r = 0; r < a.rows(); r++)
for(rotgen::Index c=0;c<a.cols();c++) for (rotgen::Index c = 0; c < a.cols(); c++) TTS_EQUAL(b(r, c), a(r, c));
TTS_EQUAL(b(r,c), a(r,c));
TTS_EQUAL(b(0, 0), 0.0); TTS_EQUAL(b(0, 0), 0.0);
TTS_EQUAL(b(1, 0), 1.0); TTS_EQUAL(b(1, 0), 1.0);
TTS_EQUAL(b(2, 1), 3.0); TTS_EQUAL(b(2, 1), 3.0);
a(0,0) = 42.0; a(0, 0) = 42.0;
TTS_NOT_EQUAL(b(0,0), a(0,0)); TTS_NOT_EQUAL(b(0, 0), a(0, 0));
}; };
TTS_CASE_TPL("Copy constructor on default matrix", rotgen::tests::types) TTS_CASE_TPL("Copy constructor on default matrix",
<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; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> a;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> b = a; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> b = a;
TTS_EQUAL(b.rows(), rotgen::Index{0}); TTS_EQUAL(b.rows(), rotgen::Index{0});
TTS_EQUAL(b.cols(), rotgen::Index{0}); TTS_EQUAL(b.cols(), rotgen::Index{0});
}; };
TTS_CASE_TPL("Copy constructor from const matrix", rotgen::tests::types) TTS_CASE_TPL("Copy constructor from const matrix",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
const rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> a(2, 2); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> const a(2, 2);
auto b = a; auto b = a;
TTS_EQUAL(b.rows(), rotgen::Index{2}); TTS_EQUAL(b.rows(), rotgen::Index{2});
TTS_EQUAL(b.cols(), rotgen::Index{2}); TTS_EQUAL(b.cols(), rotgen::Index{2});
}; };
TTS_CASE_TPL("Copy constructor on static matrix", rotgen::tests::types) TTS_CASE_TPL("Copy constructor on static matrix",
<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, 2, 5> a; rotgen::matrix<T, 2, 5> a;
rotgen::matrix<T, 2, 5> b = a; rotgen::matrix<T, 2, 5> b = a;
@ -112,93 +118,100 @@ TTS_CASE_TPL("Copy constructor on static matrix", rotgen::tests::types)
TTS_EQUAL(b.cols(), rotgen::Index{5}); TTS_EQUAL(b.cols(), rotgen::Index{5});
}; };
TTS_CASE_TPL("Copy constructor on static/dynamic matrix", rotgen::tests::types) TTS_CASE_TPL("Copy constructor on static/dynamic matrix",
<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, 11, 4,O::value> a; rotgen::matrix<T, 11, 4, O::value> a;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> b = a; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> b = a;
TTS_EQUAL(b.rows(), 11); TTS_EQUAL(b.rows(), 11);
TTS_EQUAL(b.cols(), 4); TTS_EQUAL(b.cols(), 4);
}; };
TTS_CASE_TPL("Copy constructor on dynamic/static matrix", rotgen::tests::types) TTS_CASE_TPL("Copy constructor on dynamic/static matrix",
<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(5, 7); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> a(5, 7);
rotgen::matrix<T, 5, 7,O::value> b = a; rotgen::matrix<T, 5, 7, O::value> b = a;
TTS_EQUAL(b.rows(), 5); TTS_EQUAL(b.rows(), 5);
TTS_EQUAL(b.cols(), 7); TTS_EQUAL(b.cols(), 7);
}; };
TTS_CASE_TPL("Move constructor transfers contents", rotgen::tests::types) TTS_CASE_TPL("Move constructor transfers contents",
<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); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> a(3, 3);
a(1,1) = 7; a(1, 1) = 7;
auto ptr = a.data(); auto ptr = a.data();
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> b = std::move(a); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> b =
std::move(a);
TTS_EQUAL(b(1,1), 7); TTS_EQUAL(b(1, 1), 7);
TTS_EQUAL(b.rows(), rotgen::Index{3}); TTS_EQUAL(b.rows(), rotgen::Index{3});
TTS_EQUAL(b.cols(), rotgen::Index{3}); TTS_EQUAL(b.cols(), rotgen::Index{3});
TTS_EXPECT(b.data() == ptr); TTS_EXPECT(b.data() == ptr);
}; };
TTS_CASE_TPL("Move constructor from Rvalue", rotgen::tests::types) TTS_CASE_TPL("Move constructor from Rvalue",
<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> b = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>(2, 2); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> b =
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>(2, 2);
TTS_EQUAL(b.rows(), rotgen::Index{2}); TTS_EQUAL(b.rows(), rotgen::Index{2});
TTS_EQUAL(b.cols(), rotgen::Index{2}); TTS_EQUAL(b.cols(), rotgen::Index{2});
}; };
TTS_CASE_TPL("Constructor from Initializer list", rotgen::tests::types) TTS_CASE_TPL("Constructor from Initializer list",
<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,1,1,O::value> b1{3.5}; rotgen::matrix<T, 1, 1, O::value> b1{3.5};
TTS_EQUAL(b1.rows(), rotgen::Index{1}); TTS_EQUAL(b1.rows(), rotgen::Index{1});
TTS_EQUAL(b1.cols(), rotgen::Index{1}); TTS_EQUAL(b1.cols(), rotgen::Index{1});
TTS_EQUAL(b1(0) , 3.5); TTS_EQUAL(b1(0), 3.5);
rotgen::matrix<T,5,1,rotgen::ColMajor> b9{0.25, 0.5, 1, 2, 4}; rotgen::matrix<T, 5, 1, rotgen::ColMajor> b9{0.25, 0.5, 1, 2, 4};
TTS_EQUAL(b9.rows(), rotgen::Index{5}); TTS_EQUAL(b9.rows(), rotgen::Index{5});
TTS_EQUAL(b9.cols(), rotgen::Index{1}); TTS_EQUAL(b9.cols(), rotgen::Index{1});
T i = 0.25; T i = 0.25;
for(rotgen::Index r=0;r<b9.rows();++r) for (rotgen::Index r = 0; r < b9.rows(); ++r)
{ {
TTS_EQUAL(b9(r,0), i); TTS_EQUAL(b9(r, 0), i);
i *= 2; i *= 2;
} }
rotgen::matrix<T,1,3,rotgen::RowMajor> b13{1.2,2.3,3.4}; rotgen::matrix<T, 1, 3, rotgen::RowMajor> b13{1.2, 2.3, 3.4};
TTS_EQUAL(b13.rows(), rotgen::Index{1}); TTS_EQUAL(b13.rows(), rotgen::Index{1});
TTS_EQUAL(b13.cols(), rotgen::Index{3}); TTS_EQUAL(b13.cols(), rotgen::Index{3});
TTS_EQUAL(b13(0) , T(1.2)); TTS_EQUAL(b13(0), T(1.2));
TTS_EQUAL(b13(1) , T(2.3)); TTS_EQUAL(b13(1), T(2.3));
TTS_EQUAL(b13(2) , T(3.4)); TTS_EQUAL(b13(2), T(3.4));
}; };
TTS_CASE_TPL("Constructor from Initializer list of rows", rotgen::tests::types) TTS_CASE_TPL("Constructor from Initializer list of rows",
<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> b1{{3.5}}; rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> b1{{3.5}};
TTS_EQUAL(b1.rows(), rotgen::Index{1}); TTS_EQUAL(b1.rows(), rotgen::Index{1});
TTS_EQUAL(b1.cols(), rotgen::Index{1}); TTS_EQUAL(b1.cols(), rotgen::Index{1});
TTS_EQUAL(b1(0,0) , T(3.5)); TTS_EQUAL(b1(0, 0), T(3.5));
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> b23{
b23 { {1.2,2.3,3.4} {1.2, 2.3, 3.4},
, {10,200,3000} {10, 200, 3000}};
};
TTS_EQUAL(b23.rows(), rotgen::Index{2}); TTS_EQUAL(b23.rows(), rotgen::Index{2});
TTS_EQUAL(b23.cols(), rotgen::Index{3}); TTS_EQUAL(b23.cols(), rotgen::Index{3});
TTS_EQUAL(b23(0,0) , T(1.2)); TTS_EQUAL(b23(0, 0), T(1.2));
TTS_EQUAL(b23(0,1) , T(2.3)); TTS_EQUAL(b23(0, 1), T(2.3));
TTS_EQUAL(b23(0,2) , T(3.4)); TTS_EQUAL(b23(0, 2), T(3.4));
TTS_EQUAL(b23(1,0) , T(10)); TTS_EQUAL(b23(1, 0), T(10));
TTS_EQUAL(b23(1,1) , T(200)); TTS_EQUAL(b23(1, 1), T(200));
TTS_EQUAL(b23(1,2) , T(3000)); TTS_EQUAL(b23(1, 2), T(3000));
}; };

View file

@ -9,29 +9,31 @@
#include "unit/common/cwise.hpp" #include "unit/common/cwise.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic matrix cwise operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic matrix cwise operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_matrix_references(); auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases) for (auto const& [rows, cols, fn] : cases)
{ {
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> input(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> input(rows,
rotgen::tests::prepare(rows,cols,fn,input); cols);
rotgen::tests::prepare(rows, cols, fn, input);
rotgen::tests::check_cwise_functions(input); rotgen::tests::check_cwise_functions(input);
} }
}; };
TTS_CASE_TPL("Test static matrix cwise operations", rotgen::tests::types) TTS_CASE_TPL("Test static matrix cwise operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_matrix_references(); auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc) auto process = []<typename D>(D const& desc) {
{ rotgen::matrix<T, D::rows, D::cols, O::value> input;
rotgen::matrix<T,D::rows,D::cols,O::value> input; rotgen::tests::prepare(input.rows(), input.cols(), desc.init_fn, input);
rotgen::tests::prepare(input.rows(),input.cols(),desc.init_fn,input);
rotgen::tests::check_cwise_functions(input); rotgen::tests::check_cwise_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };

View file

@ -8,134 +8,141 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
void test_value(const auto& matrix, std::size_t rows, std::size_t cols, auto constant) void test_value(auto const& matrix,
std::size_t rows,
std::size_t cols,
auto constant)
{ {
TTS_EXPECT(verify_rotgen_reentrance(matrix)); TTS_EXPECT(verify_rotgen_reentrance(matrix));
for(std::size_t r=0;r<rows;++r) for (std::size_t r = 0; r < rows; ++r)
for(std::size_t c=0;c<cols;++c) for (std::size_t c = 0; c < cols; ++c) TTS_EQUAL(matrix(r, c), constant);
TTS_EQUAL(matrix(r, c), constant);
} }
void test_random(const auto& matrix, std::size_t rows, std::size_t cols) void test_random(auto const& matrix, std::size_t rows, std::size_t cols)
{ {
TTS_EXPECT(verify_rotgen_reentrance(matrix)); TTS_EXPECT(verify_rotgen_reentrance(matrix));
for(std::size_t r=0;r<rows;++r) for (std::size_t r = 0; r < rows; ++r)
for(std::size_t c=0;c<cols;++c) for (std::size_t c = 0; c < cols; ++c)
{ {
TTS_GREATER_EQUAL(matrix(r, c), -1.0); TTS_GREATER_EQUAL(matrix(r, c), -1.0);
TTS_LESS_EQUAL(matrix(r, c), 1.0); TTS_LESS_EQUAL(matrix(r, c), 1.0);
} }
} }
void test_identity(const auto& matrix, std::size_t rows, std::size_t cols) void test_identity(auto const& matrix, std::size_t rows, std::size_t cols)
{ {
TTS_EXPECT(verify_rotgen_reentrance(matrix)); TTS_EXPECT(verify_rotgen_reentrance(matrix));
for(std::size_t r=0;r<rows;++r) for (std::size_t r = 0; r < rows; ++r)
for(std::size_t c=0;c<cols;++c) for (std::size_t c = 0; c < cols; ++c)
TTS_EQUAL(matrix(r, c), r==c ? 1 : 0); TTS_EQUAL(matrix(r, c), r == c ? 1 : 0);
} }
TTS_CASE_TPL("Test zero", rotgen::tests::types) TTS_CASE_TPL("Test zero", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
using namespace rotgen; using namespace rotgen;
test_value(setZero<matrix<T, 3, 4, O::value> >(), 3, 4, 0); test_value(setZero<matrix<T, 3, 4, O::value>>(), 3, 4, 0);
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), 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);
test_value(setZero(matrix<T, 3, 4, O::value>{} ), 3, 4, 0); test_value(setZero(matrix<T, 3, 4, O::value>{}), 3, 4, 0);
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, 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);
}; };
TTS_CASE_TPL("Test ones", rotgen::tests::types) TTS_CASE_TPL("Test ones", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
using namespace rotgen; using namespace rotgen;
test_value(setOnes<matrix<T, 3, 4, O::value> >(), 3, 4, 1); test_value(setOnes<matrix<T, 3, 4, O::value>>(), 3, 4, 1);
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), 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);
test_value(setOnes(matrix<T, 3, 4, O::value>{} ), 3, 4, 1); test_value(setOnes(matrix<T, 3, 4, O::value>{}), 3, 4, 1);
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, 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);
}; };
TTS_CASE_TPL("Test constant", rotgen::tests::types) TTS_CASE_TPL("Test constant", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
using namespace rotgen; using namespace rotgen;
test_value(setConstant<matrix<T, 3, 4, O::value> >(T(5.12)), 3, 4, T(5.12)); test_value(setConstant<matrix<T, 3, 4, O::value>>(T(5.12)), 3, 4, 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, 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,
test_value(setConstant<matrix<T,Dynamic,Dynamic, O::value>>(3, 4, T(5.12)), 3, 4, T(5.12)); 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, Dynamic, Dynamic, O::value>>(3, 4, T(5.12)),
test_value(setConstant<matrix<T, 9,Dynamic> >(9, 3, T(5.12)), 9, 3, T(5.12)); 3, 4, 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, 7, 5, O::value>>(7, 5, 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, Dynamic, 3>>(2, 3, T(5.12)), 2, 3, T(5.12));
test_value(setConstant(matrix<T, 3, 4, O::value>{} , T(5.12)), 3, 4, T(5.12)); test_value(setConstant(matrix<T, 3, 4, O::value>{}, T(5.12)), 3, 4, 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, 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,
test_value(setConstant(matrix<T,Dynamic,Dynamic, O::value>{3, 4}, T(5.12)), 3, 4, T(5.12)); 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, Dynamic, Dynamic, O::value>{3, 4}, T(5.12)),
test_value(setConstant(matrix<T, 9,Dynamic>{9, 3} , T(5.12)), 9, 3, T(5.12)); 3, 4, 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, 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, Dynamic, 3>{2, 3}, T(5.12)), 2, 3, T(5.12));
}; };
TTS_CASE_TPL("Test random", rotgen::tests::types) TTS_CASE_TPL("Test random", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
using namespace rotgen; using namespace rotgen;
test_random(setRandom<matrix<T, 3, 4, O::value> >(), 3, 4); test_random(setRandom<matrix<T, 3, 4, O::value>>(), 3, 4);
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), 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);
test_random(setRandom(matrix<T, 3, 4, O::value>{} ), 3, 4); test_random(setRandom(matrix<T, 3, 4, O::value>{}), 3, 4);
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); 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);
}; };
TTS_CASE_TPL("Test identity", rotgen::tests::types) TTS_CASE_TPL("Test identity", rotgen::tests::types)<typename T, typename O>(
<typename T, typename O>( tts::type< tts::types<T,O>> ) tts::type<tts::types<T, O>>)
{ {
using namespace rotgen; using namespace rotgen;
test_identity(setIdentity<matrix<T, 3, 4, O::value> >(), 3, 4); test_identity(setIdentity<matrix<T, 3, 4, O::value>>(), 3, 4);
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), 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);
test_identity(setIdentity(matrix<T, 3, 4, O::value>{} ), 3, 4); test_identity(setIdentity(matrix<T, 3, 4, O::value>{}), 3, 4);
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); 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

@ -9,54 +9,59 @@
#include "unit/common/arithmetic.hpp" #include "unit/common/arithmetic.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic matrix inverse", rotgen::tests::types) TTS_CASE_TPL("Test dynamic matrix inverse",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto eps = std::numeric_limits<T>::epsilon(); auto eps = std::numeric_limits<T>::epsilon();
auto const cases = rotgen::tests::generate_matrix_references(); auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [r, c, fn] : cases) for (auto const& [r, c, fn] : cases)
{ {
if(r == c) if (r == c)
{ {
auto input = mat_t::Random(r, c); auto input = mat_t::Random(r, c);
auto inv = rotgen::inverse(input); auto inv = rotgen::inverse(input);
auto rec = input * inv; auto rec = input * inv;
auto id = mat_t::Identity(rotgen::rows(rec),rotgen::cols(rec)); auto id = mat_t::Identity(rotgen::rows(rec), rotgen::cols(rec));
auto error = rec - id; auto error = rec - id;
TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 64.) TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 64.)
<< "Result:\n" << rec << "\n" << "Result:\n"
<< "Residuals:\n" << error << "\n"; << rec << "\n"
<< "Residuals:\n"
<< error << "\n";
} }
} }
}; };
TTS_CASE_TPL("Test static matrix inverse", rotgen::tests::types) TTS_CASE_TPL("Test static matrix inverse",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto eps = std::numeric_limits<T>::epsilon(); auto eps = std::numeric_limits<T>::epsilon();
auto const cases = rotgen::tests::generate_static_matrix_references(); auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = [&]<typename D>(D const&) auto process = [&]<typename D>(D const&) {
{ if constexpr (D::rows == D::cols)
if constexpr(D::rows == D::cols)
{ {
auto input = rotgen::matrix<T,D::rows,D::cols,O::value>::Random(); auto input = rotgen::matrix<T, D::rows, D::cols, O::value>::Random();
auto inv = rotgen::inverse(input); auto inv = rotgen::inverse(input);
auto rec = input * inv; auto rec = input * inv;
auto id = mat_t::Identity(rotgen::rows(rec),rotgen::cols(rec)); auto id = mat_t::Identity(rotgen::rows(rec), rotgen::cols(rec));
auto error = rec - id; auto error = rec - id;
TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 64.) TTS_LESS_EQUAL(rotgen::maxCoeff(rotgen::abs(error)) / eps, 64.)
<< "Result:\n" << rec << "\n" << "Result:\n"
<< "Residuals:\n" << error << "\n"; << rec << "\n"
<< "Residuals:\n"
<< error << "\n";
} }
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };

View file

@ -9,29 +9,31 @@
#include "unit/common/norms.hpp" #include "unit/common/norms.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic matrix norm operations", rotgen::tests::types) TTS_CASE_TPL("Test dynamic matrix norm operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_matrix_references(); auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases) for (auto const& [rows, cols, fn] : cases)
{ {
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> input(rows, cols); rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> input(rows,
rotgen::tests::prepare(rows,cols,fn,input); cols);
rotgen::tests::prepare(rows, cols, fn, input);
rotgen::tests::check_norms_functions(input); rotgen::tests::check_norms_functions(input);
} }
}; };
TTS_CASE_TPL("Test static matrix norm operations", rotgen::tests::types) TTS_CASE_TPL("Test static matrix norm operations",
<typename T, typename O>( tts::type< tts::types<T,O>> ) rotgen::tests::types)<typename T, typename O>(
tts::type<tts::types<T, O>>)
{ {
auto const cases = rotgen::tests::generate_static_matrix_references(); auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc) auto process = []<typename D>(D const& desc) {
{ rotgen::matrix<T, D::rows, D::cols, O::value> input;
rotgen::matrix<T,D::rows,D::cols,O::value> input; rotgen::tests::prepare(input.rows(), input.cols(), desc.init_fn, input);
rotgen::tests::prepare(input.rows(),input.cols(),desc.init_fn,input);
rotgen::tests::check_norms_functions(input); rotgen::tests::check_norms_functions(input);
}; };
std::apply([&](auto const&... d) { (process(d),...);}, cases); std::apply([&](auto const&... d) { (process(d), ...); }, cases);
}; };

View file

@ -8,8 +8,13 @@
#include "unit/tests.hpp" #include "unit/tests.hpp"
#include <rotgen/rotgen.hpp> #include <rotgen/rotgen.hpp>
template <typename MatrixType> template<typename MatrixType>
void test_matrix_operations(rotgen::Index rows, rotgen::Index cols, auto a_init_fn, auto b_init_fn, auto ops, auto self_ops) void test_matrix_operations(rotgen::Index rows,
rotgen::Index cols,
auto a_init_fn,
auto b_init_fn,
auto ops,
auto self_ops)
{ {
MatrixType a(rows, cols); MatrixType a(rows, cols);
MatrixType b(rows, cols); MatrixType b(rows, cols);
@ -19,22 +24,27 @@ void test_matrix_operations(rotgen::Index rows, rotgen::Index cols, auto a_init_
{ {
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c)
{ {
a(r,c) = a_init_fn(r, c); a(r, c) = a_init_fn(r, c);
b(r,c) = b_init_fn(r, c); b(r, c) = b_init_fn(r, c);
ref(r, c) = ops(a(r,c),b(r,c)); ref(r, c) = ops(a(r, c), b(r, c));
} }
} }
TTS_EQUAL(ops(a, b), ref); TTS_EQUAL(ops(a, b), ref);
self_ops(a,b); self_ops(a, b);
TTS_EQUAL(a, ref); TTS_EQUAL(a, ref);
TTS_EXPECT(verify_rotgen_reentrance(ops(a, b))); TTS_EXPECT(verify_rotgen_reentrance(ops(a, b)));
TTS_EXPECT(verify_rotgen_reentrance(self_ops(a, b))); TTS_EXPECT(verify_rotgen_reentrance(self_ops(a, b)));
} }
template <typename MatrixType> template<typename MatrixType>
void test_scalar_operations(rotgen::Index rows, rotgen::Index cols, auto a_init_fn, auto s, auto ops, auto self_ops) void test_scalar_operations(rotgen::Index rows,
rotgen::Index cols,
auto a_init_fn,
auto s,
auto ops,
auto self_ops)
{ {
MatrixType a(rows, cols); MatrixType a(rows, cols);
MatrixType ref(rows, cols); MatrixType ref(rows, cols);
@ -43,21 +53,24 @@ void test_scalar_operations(rotgen::Index rows, rotgen::Index cols, auto a_init_
{ {
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c)
{ {
a(r,c) = a_init_fn(r, c); a(r, c) = a_init_fn(r, c);
ref(r, c) = ops(a(r,c),s); ref(r, c) = ops(a(r, c), s);
} }
} }
TTS_EQUAL(ops(a, s), ref); TTS_EQUAL(ops(a, s), ref);
self_ops(a,s); self_ops(a, s);
TTS_EQUAL(a, ref); TTS_EQUAL(a, ref);
TTS_EXPECT(verify_rotgen_reentrance(ops(a, s))); TTS_EXPECT(verify_rotgen_reentrance(ops(a, s)));
TTS_EXPECT(verify_rotgen_reentrance(self_ops(a, s))); TTS_EXPECT(verify_rotgen_reentrance(self_ops(a, s)));
} }
template <typename MatrixType> template<typename MatrixType>
void test_scalar_multiplications(rotgen::Index rows, rotgen::Index cols, auto fn, auto s) void test_scalar_multiplications(rotgen::Index rows,
rotgen::Index cols,
auto fn,
auto s)
{ {
MatrixType a(rows, cols); MatrixType a(rows, cols);
MatrixType ref(rows, cols); MatrixType ref(rows, cols);
@ -66,8 +79,8 @@ void test_scalar_multiplications(rotgen::Index rows, rotgen::Index cols, auto fn
{ {
for (rotgen::Index c = 0; c < cols; ++c) for (rotgen::Index c = 0; c < cols; ++c)
{ {
a(r,c) = fn(r, c); a(r, c) = fn(r, c);
ref(r, c) = a(r,c) * s; ref(r, c) = a(r, c) * s;
} }
} }
@ -76,25 +89,26 @@ void test_scalar_multiplications(rotgen::Index rows, rotgen::Index cols, auto fn
a *= s; a *= s;
TTS_EQUAL(a, ref); TTS_EQUAL(a, ref);
TTS_EXPECT(verify_rotgen_reentrance(a*s)); TTS_EXPECT(verify_rotgen_reentrance(a * s));
TTS_EXPECT(verify_rotgen_reentrance(s*a)); TTS_EXPECT(verify_rotgen_reentrance(s * a));
TTS_EXPECT(verify_rotgen_reentrance(a*=s)); TTS_EXPECT(verify_rotgen_reentrance(a *= s));
} }
template <typename MatrixType> template<typename MatrixType>
void test_matrix_multiplication(rotgen::Index rows, rotgen::Index cols, auto a_init_fn, auto b_init_fn) void test_matrix_multiplication(rotgen::Index rows,
rotgen::Index cols,
auto a_init_fn,
auto b_init_fn)
{ {
MatrixType a(rows, cols); MatrixType a(rows, cols);
MatrixType b(cols, rows); MatrixType b(cols, rows);
MatrixType ref(rows, rows); MatrixType ref(rows, rows);
for (rotgen::Index r = 0; r < a.rows(); ++r) for (rotgen::Index r = 0; r < a.rows(); ++r)
for (rotgen::Index c = 0; c < a.cols(); ++c) for (rotgen::Index c = 0; c < a.cols(); ++c) a(r, c) = a_init_fn(r, c);
a(r,c) = a_init_fn(r, c);
for (rotgen::Index r = 0; r < b.rows(); ++r) for (rotgen::Index r = 0; r < b.rows(); ++r)
for (rotgen::Index c = 0; c < b.cols(); ++c) for (rotgen::Index c = 0; c < b.cols(); ++c) b(r, c) = b_init_fn(r, c);
b(r,c) = b_init_fn(r, c);
for (rotgen::Index i = 0; i < a.rows(); ++i) for (rotgen::Index i = 0; i < a.rows(); ++i)
{ {
@ -107,98 +121,107 @@ void test_matrix_multiplication(rotgen::Index rows, rotgen::Index cols, auto a_i
} }
TTS_EQUAL(a * b, ref); TTS_EQUAL(a * b, ref);
TTS_EXPECT(verify_rotgen_reentrance(a*b)); TTS_EXPECT(verify_rotgen_reentrance(a * b));
} }
// Basic initializers // Basic initializers
inline constexpr auto init_a = [](auto r, auto c) { return 9.9*r*r*r - 6*c -12; }; inline constexpr auto init_a = [](auto r, auto c) {
inline constexpr auto init_b = [](auto r, auto c) { return 3.1*r + 4.2*c - 12.3; }; return 9.9 * r * r * r - 6 * c - 12;
inline constexpr auto init_0 = [](auto , auto ) { return 0; }; };
inline constexpr auto init_b = [](auto r, auto c) {
return 3.1 * r + 4.2 * c - 12.3;
};
inline constexpr auto init_0 = [](auto, auto) { return 0; };
TTS_CASE_TPL("Check matrix addition", rotgen::tests::types) TTS_CASE_TPL("Check matrix addition",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto op = [](auto a, auto b) { return a + b; }; auto op = [](auto a, auto b) { return a + b; };
auto s_op = [](auto& a, auto b) { return a += b; }; auto s_op = [](auto& a, auto b) { return a += b; };
test_matrix_operations<mat_t>(1 , 1, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(1, 1, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(3 , 5, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(3, 5, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(5 , 3, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(5, 3, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(5 , 5, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(5, 5, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(5 , 5, init_b, init_a, op, s_op); test_matrix_operations<mat_t>(5, 5, init_b, init_a, op, s_op);
test_matrix_operations<mat_t>(10, 1, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(10, 1, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(1 ,10, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(1, 10, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(5 , 5, init_0, init_b, op, s_op); test_matrix_operations<mat_t>(5, 5, init_0, init_b, op, s_op);
test_matrix_operations<mat_t>(5 , 5, init_a, init_0, op, s_op); test_matrix_operations<mat_t>(5, 5, init_a, init_0, op, s_op);
}; };
TTS_CASE_TPL("Check matrix substraction", rotgen::tests::types) TTS_CASE_TPL("Check matrix substraction",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto op = [](auto a, auto b) { return a - b; }; auto op = [](auto a, auto b) { return a - b; };
auto s_op = [](auto& a, auto b) { return a -= b; }; auto s_op = [](auto& a, auto b) { return a -= b; };
test_matrix_operations<mat_t>(1 , 1, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(1, 1, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(3 , 5, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(3, 5, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(5 , 3, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(5, 3, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(5 , 5, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(5, 5, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(5 , 5, init_b, init_a, op, s_op); test_matrix_operations<mat_t>(5, 5, init_b, init_a, op, s_op);
test_matrix_operations<mat_t>(10, 1, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(10, 1, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(1 ,10, init_a, init_b, op, s_op); test_matrix_operations<mat_t>(1, 10, init_a, init_b, op, s_op);
test_matrix_operations<mat_t>(5 , 5, init_0, init_b, op, s_op); test_matrix_operations<mat_t>(5, 5, init_0, init_b, op, s_op);
test_matrix_operations<mat_t>(5 , 5, init_a, init_0, op, s_op); test_matrix_operations<mat_t>(5, 5, init_a, init_0, op, s_op);
}; };
TTS_CASE_TPL("Check matrix multiplications", rotgen::tests::types) TTS_CASE_TPL("Check matrix multiplications",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto init_id = [](auto r, auto c) { return r == c ? 1 : 0; }; auto init_id = [](auto r, auto c) { return r == c ? 1 : 0; };
test_matrix_multiplication<mat_t>(1 , 1, init_a , init_b ); test_matrix_multiplication<mat_t>(1, 1, init_a, init_b);
test_matrix_multiplication<mat_t>(3 , 5, init_a , init_b ); test_matrix_multiplication<mat_t>(3, 5, init_a, init_b);
test_matrix_multiplication<mat_t>(5 , 3, init_a , init_b ); test_matrix_multiplication<mat_t>(5, 3, init_a, init_b);
test_matrix_multiplication<mat_t>(5 , 5, init_a , init_b ); test_matrix_multiplication<mat_t>(5, 5, init_a, init_b);
test_matrix_multiplication<mat_t>(5 , 5, init_b , init_a ); test_matrix_multiplication<mat_t>(5, 5, init_b, init_a);
test_matrix_multiplication<mat_t>(5 , 5, init_a , init_a ); test_matrix_multiplication<mat_t>(5, 5, init_a, init_a);
test_matrix_multiplication<mat_t>(5 , 5, init_a , init_id); test_matrix_multiplication<mat_t>(5, 5, init_a, init_id);
test_matrix_multiplication<mat_t>(5 , 5, init_id, init_a ); test_matrix_multiplication<mat_t>(5, 5, init_id, init_a);
test_matrix_multiplication<mat_t>(10, 1, init_a , init_b ); test_matrix_multiplication<mat_t>(10, 1, init_a, init_b);
test_matrix_multiplication<mat_t>(1 ,10, init_a , init_b ); test_matrix_multiplication<mat_t>(1, 10, init_a, init_b);
test_matrix_multiplication<mat_t>(5 , 5, init_0 , init_b ); test_matrix_multiplication<mat_t>(5, 5, init_0, init_b);
test_matrix_multiplication<mat_t>(5 , 5, init_a , init_0 ); test_matrix_multiplication<mat_t>(5, 5, init_a, init_0);
}; };
TTS_CASE_TPL("Check matrix multiplication with scalar", rotgen::tests::types) TTS_CASE_TPL("Check matrix multiplication with scalar",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
test_scalar_multiplications<mat_t>(1 , 1, init_a, T{ 3.5}); test_scalar_multiplications<mat_t>(1, 1, init_a, T{3.5});
test_scalar_multiplications<mat_t>(3 , 5, init_a, T{-2.5}); test_scalar_multiplications<mat_t>(3, 5, init_a, T{-2.5});
test_scalar_multiplications<mat_t>(5 , 3, init_a, T{ 4. }); test_scalar_multiplications<mat_t>(5, 3, init_a, T{4.});
test_scalar_multiplications<mat_t>(5 , 5, init_a, T{-5. }); test_scalar_multiplications<mat_t>(5, 5, init_a, T{-5.});
test_scalar_multiplications<mat_t>(5 , 5, init_a, T{ 1. }); test_scalar_multiplications<mat_t>(5, 5, init_a, T{1.});
test_scalar_multiplications<mat_t>(5 , 5, init_a, T{ 6. }); test_scalar_multiplications<mat_t>(5, 5, init_a, T{6.});
test_scalar_multiplications<mat_t>(10, 1, init_a, T{ 10.}); test_scalar_multiplications<mat_t>(10, 1, init_a, T{10.});
test_scalar_multiplications<mat_t>(1 ,10, init_a, T{-0.5}); test_scalar_multiplications<mat_t>(1, 10, init_a, T{-0.5});
}; };
TTS_CASE_TPL("Check matrix division with scalar", rotgen::tests::types) TTS_CASE_TPL("Check matrix division with scalar",
<typename T, typename O>( tts::type< tts::types<T,O>> ) 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>; using mat_t = rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value>;
auto op = [](auto a, auto b) { return a / b; }; auto op = [](auto a, auto b) { return a / b; };
auto s_op = [](auto& a, auto b) { return a /= b; }; auto s_op = [](auto& a, auto b) { return a /= b; };
test_scalar_operations<mat_t>(1 , 1, init_a, T{ 3.5}, op, s_op); test_scalar_operations<mat_t>(1, 1, init_a, T{3.5}, op, s_op);
test_scalar_operations<mat_t>(3 , 5, init_a, T{-2.5}, op, s_op); test_scalar_operations<mat_t>(3, 5, init_a, T{-2.5}, op, s_op);
test_scalar_operations<mat_t>(5 , 3, init_a, T{ 4. }, op, s_op); test_scalar_operations<mat_t>(5, 3, init_a, T{4.}, op, s_op);
test_scalar_operations<mat_t>(5 , 5, init_a, T{-5. }, op, s_op); test_scalar_operations<mat_t>(5, 5, init_a, T{-5.}, op, s_op);
test_scalar_operations<mat_t>(5 , 5, init_a, T{ 1. }, op, s_op); test_scalar_operations<mat_t>(5, 5, init_a, T{1.}, op, s_op);
test_scalar_operations<mat_t>(5 , 5, init_a, T{ 6. }, op, s_op); test_scalar_operations<mat_t>(5, 5, init_a, T{6.}, op, s_op);
test_scalar_operations<mat_t>(10, 1, init_a, T{ 10.}, op, s_op); test_scalar_operations<mat_t>(10, 1, init_a, T{10.}, op, s_op);
test_scalar_operations<mat_t>(1 ,10, init_a, T{-0.5}, op, s_op); test_scalar_operations<mat_t>(1, 10, init_a, T{-0.5}, op, s_op);
}; };

View file

@ -15,40 +15,41 @@
namespace rotgen::tests namespace rotgen::tests
{ {
template<auto N> struct constant { static constexpr auto value = N; }; template<auto N> struct constant
{
static constexpr auto value = N;
};
using scalar = tts::types<float,double>; using scalar = tts::types<float, double>;
using order = tts::types<constant<ColMajor>,constant<RowMajor>>; using order = tts::types<constant<ColMajor>, constant<RowMajor>>;
using types = tts::types< tts::types<float ,constant<ColMajor>> using types = tts::types<tts::types<float, constant<ColMajor>>,
, tts::types<double,constant<ColMajor>> tts::types<double, constant<ColMajor>>,
, tts::types<float ,constant<RowMajor>> tts::types<float, constant<RowMajor>>,
, tts::types<double,constant<RowMajor>> tts::types<double, constant<RowMajor>>>;
>;
} }
#include <iostream> #include <iostream>
template<typename T> template<typename T> constexpr bool verify_rotgen_reentrance(T const&)
constexpr bool verify_rotgen_reentrance(T const&)
{ {
if constexpr(rotgen::use_expression_templates) return true; if constexpr (rotgen::use_expression_templates) return true;
else return rotgen::concepts::entity<T>; else return rotgen::concepts::entity<T>;
} }
int main(int argc, char const **argv) int main(int argc, char const** argv)
{ {
::tts::initialize(argc,argv); ::tts::initialize(argc, argv);
#ifdef NDEBUG #ifdef NDEBUG
constexpr auto assert_status = "Disabled"; constexpr auto assert_status = "Disabled";
#else #else
constexpr auto assert_status = "Enabled"; constexpr auto assert_status = "Enabled";
#endif #endif
std::cout << "[ROTGEN] - Assertions: " << assert_status << std::endl; std::cout << "[ROTGEN] - Assertions: " << assert_status << std::endl;
rotgen::setup_summary(std::cout); rotgen::setup_summary(std::cout);
rotgen_main(argc, argv); rotgen_main(argc, argv);
return tts::report(0,0); return tts::report(0, 0);
} }