Implements map and ref for both static & dynamic mode

See merge request oss/rotgen!12
This commit is contained in:
Joel Falcou 2025-08-13 17:43:57 +02:00
parent aacae1cbb1
commit 6c2b260229
58 changed files with 4121 additions and 1205 deletions

View file

@ -29,20 +29,23 @@ endif()
## Handle options
##======================================================================================================================
option(ROTGEN_FORCE_DYNAMIC "Force dynamic configuration for rotgen" OFF)
option(ROTGEN_DISABLE_EXPRESSION_TEMPLATES "Disable expression templates" OFF)
option(ROTGEN_ENABLE_EXPRESSION_TEMPLATES "Enable expression templates" OFF)
set(ROTGEN_MAX_SIZE "" CACHE STRING "Max matrix number of elements for rotgen (integer)")
include(${ROTGEN_SOURCE_DIR}/cmake/options.cmake)
handle_option(ROTGEN_COMPILE_DEFS)
message(STATUS "[ROGEN] - Compiling with ${ROTGEN_COMPILE_DEFS}")
##======================================================================================================================
## Sources & Public Headers lists
##======================================================================================================================
if(ROTGEN_FORCE_DYNAMIC)
set ( SOURCES
src/map.cpp
src/matrix.cpp
src/block.cpp
src/info.cpp
src/operators.cpp
)
else()
set ( SOURCES

View file

@ -48,7 +48,7 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/release-static",
"cacheVariables": {
"ROTGEN_MAX_SIZE": "4"
"ROTGEN_MAX_SIZE": "16"
}
},
{
@ -58,7 +58,7 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/debug-static",
"cacheVariables": {
"ROTGEN_MAX_SIZE": "4"
"ROTGEN_MAX_SIZE": "16"
}
},
{
@ -68,7 +68,8 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/release-et",
"cacheVariables": {
"ROTGEN_DISABLE_EXPRESSION_TEMPLATES": "ON"
"ROTGEN_ENABLE_EXPRESSION_TEMPLATES": "ON",
"ROTGEN_MAX_SIZE": "16"
}
},
{
@ -78,7 +79,8 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/debug-et",
"cacheVariables": {
"ROTGEN_DISABLE_EXPRESSION_TEMPLATES": "ON"
"ROTGEN_ENABLE_EXPRESSION_TEMPLATES": "ON",
"ROTGEN_MAX_SIZE": "16"
}
}
],

View file

@ -20,21 +20,24 @@ function(check_force_dynamic_and_sizes FORCE_DYNAMIC_VAR MAX_SIZE_VAR)
endif()
endfunction()
function(infer_force_dynamic FORCE_DYNAMIC_VAR MAX_SIZE_VAR OUT_FORCE_DYNAMIC_INFERRED)
function(infer_force_dynamic FORCE_DYNAMIC_VAR MAX_SIZE_VAR ET_VAR OUT_FORCE_DYNAMIC_INFERRED)
set(${OUT_FORCE_DYNAMIC_INFERRED} OFF PARENT_SCOPE)
if(${FORCE_DYNAMIC_VAR})
if(NOT ${MAX_SIZE_VAR} STREQUAL "")
message(FATAL_ERROR "ROTGEN_FORCE_DYNAMIC cannot be used together with MAX_SIZE.")
message(FATAL_ERROR "ROTGEN_FORCE_DYNAMIC cannot be used together with ROTGEN_MAX_SIZE.")
endif()
elseif(${MAX_SIZE_VAR} STREQUAL "")
if(NOT ${ET_VAR} STREQUAL "")
message(FATAL_ERROR "ROTGEN_FORCE_DYNAMIC cannot be used together with ROTGEN_ENABLE_EXPRESSION_TEMPLATES.")
endif()
elseif(NOT ${MAX_SIZE_VAR} AND NOT ${ET_VAR})
# None set, enable force_dynamic
set(${OUT_FORCE_DYNAMIC_INFERRED} ON PARENT_SCOPE)
set(${FORCE_DYNAMIC_VAR} ON PARENT_SCOPE) # update caller variable!
endif()
endfunction()
function(build_compile_definitions FORCE_DYNAMIC_VAR MAX_SIZE_VAR OUT_DEFS)
function(build_compile_definitions FORCE_DYNAMIC_VAR MAX_SIZE_VAR ENABLE_ET OUT_DEFS)
set(defs "")
if(${FORCE_DYNAMIC_VAR})
list(APPEND defs "ROTGEN_FORCE_DYNAMIC")
@ -42,6 +45,9 @@ function(build_compile_definitions FORCE_DYNAMIC_VAR MAX_SIZE_VAR OUT_DEFS)
if(NOT ${MAX_SIZE_VAR} STREQUAL "")
list(APPEND defs "ROTGEN_MAX_SIZE=${${MAX_SIZE_VAR}}")
endif()
if(${ENABLE_ET})
list(APPEND defs "ROTGEN_ENABLE_EXPRESSION_TEMPLATES")
endif()
endif()
set(${OUT_DEFS} "${defs}" PARENT_SCOPE)
endfunction()
@ -49,15 +55,14 @@ endfunction()
function(print_configuration_summary FORCE_DYNAMIC_VAR FORCE_CONFIG_REASON MAX_SIZE_VAR COMPILE_DEFS)
message(STATUS "==================== Rotgen Configuration Summary ====================")
if(DEFINED ROTGEN_DISABLE_EXPRESSION_TEMPLATES AND ROTGEN_DISABLE_EXPRESSION_TEMPLATES)
message(STATUS " Configuration mode: DISABLE_EXPRESSION_TEMPLATES (overrides other settings)")
elseif(${FORCE_DYNAMIC_VAR})
if(${FORCE_DYNAMIC_VAR})
message(STATUS " Configuration mode: DYNAMIC")
if(${FORCE_CONFIG_REASON})
message(STATUS " Reason : No static size options were provided")
endif()
else()
message(STATUS " Configuration mode: STATIC")
message(STATUS " Expression Templates: ${ROTGEN_ENABLE_EXPRESSION_TEMPLATES}")
endif()
set(PREPROCESSOR_FLAGS "")
@ -70,20 +75,9 @@ endfunction()
function(handle_option OUT_DEFS)
# Early-out if disabling expression templates
if(NOT DEFINED ROTGEN_DISABLE_EXPRESSION_TEMPLATES)
if(NOT DEFINED ROTGEN_ENABLE_EXPRESSION_TEMPLATES)
set(ROTGEN_DISABLE_EXPRESSION_TEMPLATES OFF)
endif()
if(ROTGEN_DISABLE_EXPRESSION_TEMPLATES)
# Pass only the disable flag
set(${OUT_DEFS} "ROTGEN_DISABLE_EXPRESSION_TEMPLATES" PARENT_SCOPE)
message(STATUS "==================== Rotgen Configuration Summary ====================")
message(STATUS " Configuration mode: DISABLE_EXPRESSION_TEMPLATES (overrides other settings)")
message(STATUS " Preprocessor flags: -DROTGEN_DISABLE_EXPRESSION_TEMPLATES")
message(STATUS "======================================================================")
# Propagate to parent
set(ROTGEN_DISABLE_EXPRESSION_TEMPLATES ${ROTGEN_DISABLE_EXPRESSION_TEMPLATES} PARENT_SCOPE)
return()
endif()
# Defaults for other options
if(NOT DEFINED ROTGEN_FORCE_DYNAMIC)
@ -95,12 +89,16 @@ function(handle_option OUT_DEFS)
assert_integer("ROTGEN_MAX_SIZE")
check_force_dynamic_and_sizes("ROTGEN_FORCE_DYNAMIC" "ROTGEN_MAX_SIZE")
infer_force_dynamic("ROTGEN_FORCE_DYNAMIC" "ROTGEN_MAX_SIZE" _force_dynamic_inferred)
infer_force_dynamic ( "ROTGEN_FORCE_DYNAMIC" "ROTGEN_MAX_SIZE"
"ROTGEN_ENABLE_EXPRESSION_TEMPLATES" _force_dynamic_inferred
)
build_compile_definitions("ROTGEN_FORCE_DYNAMIC" "ROTGEN_MAX_SIZE" defs)
build_compile_definitions("ROTGEN_FORCE_DYNAMIC" "ROTGEN_MAX_SIZE" "ROTGEN_ENABLE_EXPRESSION_TEMPLATES" defs)
print_configuration_summary("ROTGEN_FORCE_DYNAMIC" "_force_dynamic_inferred" "ROTGEN_MAX_SIZE" "${defs}")
set(${OUT_DEFS} "${defs}" PARENT_SCOPE)
set(ROTGEN_FORCE_DYNAMIC ${ROTGEN_FORCE_DYNAMIC} PARENT_SCOPE)
set(ROTGEN_MAX_SIZE ${ROTGEN_MAX_SIZE} PARENT_SCOPE)
set(ROTGEN_ENABLE_EXPRESSION_TEMPLATES ${ROTGEN_ENABLE_EXPRESSION_TEMPLATES} PARENT_SCOPE)
endfunction()

40
include/rotgen/alias.hpp Normal file
View file

@ -0,0 +1,40 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
namespace rotgen
{
// matrix aliases (float and double, fixed and dynamic)
using matrix2f = rotgen::matrix<float, 2, 2>;
using matrix3f = rotgen::matrix<float, 3, 3>;
using matrix4f = rotgen::matrix<float, 4, 4>;
using matrix2d = rotgen::matrix<double, 2, 2>;
using matrix3d = rotgen::matrix<double, 3, 3>;
using matrix4d = rotgen::matrix<double, 4, 4>;
using matrixXf = rotgen::matrix<float, rotgen::Dynamic, rotgen::Dynamic>;
using matrixXd = rotgen::matrix<double, rotgen::Dynamic, rotgen::Dynamic>;
using matrixXi = rotgen::matrix<int, rotgen::Dynamic, rotgen::Dynamic>;
// Column vector aliases
using vector2f = rotgen::matrix<float, 2, 1>;
using vector3f = rotgen::matrix<float, 3, 1>;
using vector4f = rotgen::matrix<float, 4, 1>;
using vector2d = rotgen::matrix<double, 2, 1>;
using vector3d = rotgen::matrix<double, 3, 1>;
using vector4d = rotgen::matrix<double, 4, 1>;
using vectorXf = rotgen::matrix<float, rotgen::Dynamic, 1>;
using vectorXd = rotgen::matrix<double, rotgen::Dynamic, 1>;
// Row vector aliases
using row_vector2f = rotgen::matrix<float, 1, 2>;
using row_vector3f = rotgen::matrix<float, 1, 3>;
using row_vector4f = rotgen::matrix<float, 1, 4>;
using row_vector2d = rotgen::matrix<double, 1, 2>;
using row_vector3d = rotgen::matrix<double, 1, 3>;
using row_vector4d = rotgen::matrix<double, 1, 4>;
using row_vectorXf = rotgen::matrix<float, 1, rotgen::Dynamic>;
using row_vectorXd = rotgen::matrix<double, 1, rotgen::Dynamic>;
}

View file

@ -0,0 +1,284 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <type_traits>
#include <cassert>
#if !defined(ROTGEN_FORCE_DYNAMIC)
#include <Eigen/Dense>
#endif
namespace rotgen
{
// Primary template: mutable ref
template<typename T, int Options = T::storage_order>
class ref : private map<T, Options>
{
public:
using parent = map<T, Options>;
using value_type = typename T::value_type;
using rotgen_tag = void;
using parent::operator();
using parent::rows;
using parent::cols;
using parent::size;
using parent::data;
using parent::sum;
using parent::prod;
using parent::mean;
using parent::trace;
using parent::maxCoeff;
using parent::minCoeff;
using parent::norm;
using parent::squaredNorm;
using parent::lpNorm;
using parent::operator+=;
using parent::operator-=;
using parent::operator*=;
using parent::operator/=;
using parent::Zero;
using parent::Constant;
using parent::Random;
using parent::Identity;
using parent::operator=;
using stride_type = typename parent::stride_type;
parent const& base() const { return static_cast<parent const&>(*this); }
parent& base() { return static_cast<parent&>(*this); }
template<std::same_as<value_type> S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC>& m)
: parent(m.data(), m.rows(), m.cols(), strides(m))
{
static_assert((O & 1) == Options, "ref: Incompatible storage layout");
}
template<typename Ref, int R, int C, bool I, int FS>
ref(block<Ref,R,C,I,FS>& b) : parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()})
{
static_assert((Ref::Options & 1) == Options, "ref: Incompatible storage layout");
}
template<typename Ref, int O, typename S>
ref(map<Ref,O,S>& b) : parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()})
{
static_assert((Ref::Options & 1) == Options, "ref: Incompatible storage layout");
}
// #if !defined(ROTGEN_FORCE_DYNAMIC)
// template<typename OtherDerived>
// ref(const Eigen::MatrixBase<OtherDerived>& b)
// : parent(b.data(), b.rows(), b.cols()/*, stride_type{b.outerStride(),b.innerStride()}*/)
// {
// using Str = typename parent::stride_type;
// std::cerr << "Stride compile-time: Outer=" << Str::OuterStrideAtCompileTime
// << " Inner=" << Str::InnerStrideAtCompileTime <<std::endl;
// std::cerr << "runtime: outer=" << b.outerStride() << " inner=" << b.innerStride() << std::endl;
// }
// #endif
ref(parent& m) : parent(m.data(), m.rows(), m.cols()) {}
friend std::ostream& operator<<(std::ostream& os, ref const& r)
{
return os << r.base() << "\n";
}
};
// Specialization for const matrix type
template<typename T, int Options>
class ref<const T, Options> : private map<const T, Options>
{
public:
using parent = map<const T, Options>;
using value_type = typename T::value_type;
using rotgen_tag = void;
using parent::operator();
using parent::rows;
using parent::cols;
using parent::size;
using parent::data;
using parent::sum;
using parent::prod;
using parent::mean;
using parent::trace;
using parent::maxCoeff;
using parent::minCoeff;
using parent::norm;
using parent::squaredNorm;
using parent::lpNorm;
using parent::operator+=;
using parent::operator-=;
using parent::operator*=;
using parent::operator/=;
using parent::Zero;
using parent::Constant;
using parent::Random;
using parent::Identity;
using parent::operator=;
using stride_type = typename parent::stride_type;
static constexpr bool has_static_storage = parent::has_static_storage;
parent const& base() const { return static_cast<parent const&>(*this); }
template<std::same_as<value_type> S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC> const& m)
: parent(m.data(), m.rows(), m.cols(), strides(m))
{
static_assert((O & 1) == Options, "ref: Incompatible storage layout");
}
template<typename Ref, int R, int C, bool I, int FS>
ref(block<Ref,R,C,I,FS> const& b) : parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()})
{
static_assert((Ref::Options & 1) == Options, "ref: Incompatible storage layout");
}
template<typename Ref, int O, typename S>
ref(map<Ref,O,S> const& b) : parent(b.data(), b.rows(), b.cols(), stride_type{b.outerStride(),b.innerStride()})
{
static_assert((Ref::Options & 1) == Options, "ref: Incompatible storage layout");
}
// #if !defined(ROTGEN_FORCE_DYNAMIC)
// template<typename OtherDerived>
// ref(const Eigen::MatrixBase<OtherDerived>& b)
// : parent(b.data(), b.rows(), b.cols())//, stride_type{b.outerStride(),b.innerStride()})
// {
// using Str = typename parent::stride_type;
// std::cerr << "Stride compile-time: Outer=" << Str::OuterStrideAtCompileTime
// << " Inner=" << Str::InnerStrideAtCompileTime <<std::endl;
// std::cerr << "runtime: outer=" << b.outerStride() << " inner=" << b.innerStride() << std::endl;
// }
// #endif
ref(parent const& m) : parent(m.data(), m.rows(), m.cols()) {}
// // From raw const buffer
// ref(value_type const* ptr, int r, int c) : parent(ptr, r, c) {}
friend std::ostream& operator<<(std::ostream& os, ref const& r)
{
return os << r.base() << "\n";
}
};
template<typename S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC>&) -> ref<matrix<S>>;
template<typename Ref, int R, int C, bool I, int FS>
ref(block<Ref,R,C,I,FS>& b) -> ref<Ref>;
template<typename S, int R, int C, int O, int MR, int MC>
ref(matrix<S, R, C, O, MR, MC> const&) -> ref<matrix<S> const>;
template<typename Ref, int R, int C, bool I, int FS>
ref(block<Ref,R,C,I,FS> const& b) -> ref<Ref const>;
template<typename A, typename B>
bool operator==(ref<A> lhs, ref<B> rhs)
{
return lhs.base() == rhs.base();
}
template<typename A, typename B>
bool operator!=(ref<A> lhs, ref<B> rhs)
{
return lhs.base() != rhs.base();
}
template<typename A, typename B>
auto operator+(ref<A> lhs, ref<B> rhs) -> decltype(lhs.base() + rhs.base())
{
return lhs.base() + rhs.base();
}
template<typename A, typename B>
auto operator-(ref<A> lhs, ref<B> rhs)
{
return lhs.base() - rhs.base();
}
template<typename A, typename B>
auto operator*(ref<A> lhs, ref<B> rhs)
{
return lhs.base() * rhs.base();
}
template<typename A>
auto operator*(ref<A> lhs, std::convertible_to<typename A::value_type> auto s)
{
return lhs.base() * s;
}
template<typename A>
auto operator*(std::convertible_to<typename A::value_type> auto s, ref<A> rhs)
{
return s * rhs.base();
}
template<typename A>
auto operator/(ref<A> lhs, std::convertible_to<typename A::value_type> auto s)
{
return lhs.base() / s;
}
template<typename T> struct generalize;
template<typename T>
requires(std::is_arithmetic_v<std::remove_cvref_t<T>>)
struct generalize<T>
{
using type = std::remove_cvref_t<T>;
};
template<typename T>
using generalize_t = typename generalize<T>::type;
template<concepts::entity T> struct generalize<T>
{
static constexpr bool is_const = std::is_const_v<T>;
using base = matrix<typename T::value_type,Dynamic,Dynamic,T::storage_order>;
using type = std::conditional_t<is_const,ref<base const>, ref<base>>;
};
template<concepts::entity T>
typename T::parent const& base_of(T const& a)
{
return a.base();
}
template<typename T>
T base_of(T a) requires(std::is_arithmetic_v<T>)
{
return a;
}
#if !defined(ROTGEN_FORCE_DYNAMIC)
template<concepts::eigen_compatible T> struct generalize<T>
{
static constexpr bool is_const = std::is_const_v<T>;
using concrete_type = decltype(std::declval<T>().eval());
using base = matrix<typename T::Scalar,Dynamic,Dynamic,concrete_type::Options&1>;
using type = std::conditional_t<is_const,ref<base const>, ref<base>>;
};
template<concepts::eigen_compatible T>
T const& base_of(T const& a)
{
return a;
}
#endif
}

View file

@ -0,0 +1,37 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/detail/static_info.hpp>
#include <rotgen/concepts.hpp>
#if !defined(ROTGEN_FORCE_DYNAMIC)
#include <Eigen/Dense>
#endif
namespace rotgen
{
#if !defined(ROTGEN_FORCE_DYNAMIC)
using stride = Eigen::Stride<-1,-1>;
#else
struct stride { Index outer, inner; };
#endif
template<int Order>
stride strides(Index r, Index c)
{
if constexpr (Order == RowMajor) return {c,1};
else return {r,1};
}
template<concepts::entity E>
auto strides(const E& e)
{
return strides<E::storage_order>(e.rows(), e.cols());
}
}

View file

@ -0,0 +1,28 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
namespace rotgen
{
template< typename EigenType
, template<typename,int,int,int,int,int> typename Wrapper
>
struct as_concrete
{
using type = Wrapper< typename EigenType::value_type
, EigenType::RowsAtCompileTime, EigenType::ColsAtCompileTime
, EigenType::Flags & 1
, EigenType::MaxRowsAtCompileTime, EigenType::MaxColsAtCompileTime
>;
};
template<typename EigenType
, template<typename,int,int,int,int,int> typename Wrapper
>
using as_concrete_t = typename as_concrete<std::remove_cvref_t<EigenType>,Wrapper>::type;
}

View file

@ -9,10 +9,29 @@
namespace rotgen::concepts
{
//================================================================================================
//! @brief Check if a type is a ROTGEN type.
//================================================================================================
template<typename T>
concept entity = requires(T const&)
{
typename T::rotgen_tag;
typename T::parent;
};
//================================================================================================
//! @brief Check if a type is an EIGEN type.
//================================================================================================
template<typename T>
concept eigen_compatible = requires(T const& a)
{
typename T::Scalar;
{ T::RowsAtCompileTime } -> std::convertible_to<int>;
{ T::ColsAtCompileTime } -> std::convertible_to<int>;
{ T::MaxRowsAtCompileTime } -> std::convertible_to<int>;
{ T::MaxColsAtCompileTime } -> std::convertible_to<int>;
{ a.eval() };
};
}

View file

@ -8,15 +8,15 @@
#pragma once
#include <cstddef>
#include <iosfwd>
#include <iostream>
namespace rotgen
{
using Index = std::ptrdiff_t;
}
#if defined(ROTGEN_DISABLE_EXPRESSION_TEMPLATES)
#define ROTGEN_MAX_SIZE 0
#if !defined(ROTGEN_MAX_SIZE) && defined(ROTGEN_ENABLE_EXPRESSION_TEMPLATES)
#define ROTGEN_MAX_SIZE 0
#endif
#if !defined(ROTGEN_FORCE_DYNAMIC)
@ -33,10 +33,19 @@ namespace rotgen
namespace rotgen
{
#if defined(ROTGEN_ENABLE_EXPRESSION_TEMPLATES)
inline constexpr bool use_expression_templates = true;
#else
inline constexpr bool use_expression_templates = false;
#endif
inline constexpr bool has_static_limit = ROTGEN_HAS_STATIC_LIMIT;
inline constexpr bool is_forcing_dynamic_status = !has_static_limit;
std::ostream& setup_summary(std::ostream& os);
namespace detail
{
std::ostream& dynamic_info(std::ostream& os);
}
}
#if defined(ROTGEN_FORCE_DYNAMIC)
@ -51,12 +60,37 @@ namespace rotgen
namespace rotgen
{
inline constexpr Index max_static_size = ROTGEN_MAX_SIZE;
template<int Rows, int Cols>
inline constexpr bool storage_status = (Rows > 0 && Cols > 0) && ((Rows*Cols) <= max_static_size);
template<int Rows, int Cols, int MaxRows, int MaxCols>
inline constexpr bool storage_status =
[]()
{
// Actual static size
if(Rows > 0 && Cols > 0) return (Rows*Cols) <= max_static_size;
// Dynamic size but static Max Size
else if(MaxRows > 0 && MaxCols > 0) return (MaxRows*MaxCols) <= max_static_size;
// Everything dynamic already
else return false;
}();
}
#endif
namespace rotgen
{
inline constexpr bool use_expression_templates = max_static_size > 0;
inline std::ostream& setup_summary(std::ostream& os)
{
detail::dynamic_info(os);
if(!is_forcing_dynamic_status)
{
if constexpr(use_expression_templates)
os << "[ROTGEN] - Expression templates : Enabled." << std::endl;
else
os << "[ROTGEN] - Expression templates : Disabled." << std::endl;
if constexpr(rotgen::max_static_size)
os << "[ROTGEN] - Static/Dynamic mode with maximum size: " << rotgen::max_static_size << std::endl;
}
return os;
}
}

View file

@ -25,12 +25,28 @@ namespace rotgen
using parent = find_block<Ref>;
using rotgen_tag = void;
using scalar_type = typename Ref::scalar_type;
using value_type = typename Ref::value_type;
static constexpr int storage_order = (ForceStorageOrder == -1) ? Ref::storage_order : ForceStorageOrder;
using concrete_type = matrix<scalar_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>;
static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols;
static constexpr int Options = Ref::Options;
static constexpr bool is_defined_static = false;
static constexpr bool has_static_storage = false;
using parent::operator=;
block& operator=(concepts::entity auto const& other)
{
assert(parent::rows() == other.rows() && parent::cols() == other.cols());
for (rotgen::Index r = 0; r < parent::rows(); ++r)
for (rotgen::Index c = 0; c < parent::cols(); ++c)
(*this)(r, c) = other(r, c);
return *this;
}
block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj) : parent(r,i0,j0,ni,nj)
{}
@ -41,6 +57,30 @@ namespace rotgen
block(parent const& base) : parent(base) {}
bool is_contiguous_linear() const
{
if(parent::innerStride() != 1) return false;
// outerstride must equal the “innerdimension length”
if constexpr(storage_order) return parent::outerStride() == parent::cols();
else return parent::outerStride() == parent::rows();
}
value_type& operator()(Index i, Index j) { return parent::operator()(i,j); }
value_type& operator()(Index i)
{
assert(is_contiguous_linear());
return parent::operator()(i);
}
value_type operator()(Index i, Index j) const { return parent::operator()(i,j); }
value_type operator()(Index i) const
{
assert(is_contiguous_linear());
return parent::operator()(i);
}
concrete_type transpose() const
{
return concrete_type(static_cast<parent const &>(*this).transpose());
@ -67,13 +107,13 @@ namespace rotgen
block& operator+=(block const& rhs)
{
static_cast<parent&>(*this) += static_cast<parent const&>(rhs);
base() += static_cast<parent const&>(rhs);
return *this;
}
block& operator-=(block const& rhs)
{
static_cast<parent&>(*this) -= static_cast<parent const&>(rhs);
base() -= static_cast<parent const&>(rhs);
return *this;
}
@ -82,46 +122,21 @@ namespace rotgen
return concrete_type(static_cast<parent const&>(*this).operator-());
}
concrete_type matrix_addition(block const& rhs) const
{
return concrete_type(static_cast<parent const&>(*this).matrix_addition(rhs));
}
concrete_type matrix_subtraction(block const& rhs) const
{
return concrete_type(static_cast<parent const&>(*this).matrix_subtraction(rhs));
}
concrete_type matrix_multiplication(block const& rhs) const
{
return concrete_type(static_cast<parent const&>(*this).matrix_multiplication(rhs));
}
concrete_type matrix_multiplication(scalar_type rhs) const
{
return concrete_type(static_cast<parent const&>(*this).matrix_multiplication(rhs));
}
concrete_type matrix_division(scalar_type rhs) const
{
return concrete_type(static_cast<parent const&>(*this).matrix_division(rhs));
}
block& operator*=(block const& rhs)
{
static_cast<parent&>(*this) *= static_cast<parent const&>(rhs);
base() *= static_cast<parent const&>(rhs);
return *this;
}
block& operator*=(scalar_type rhs)
block& operator*=(value_type rhs)
{
static_cast<parent&>(*this) *= rhs;
base() *= rhs;
return *this;
}
block& operator/=(scalar_type rhs)
block& operator/=(value_type rhs)
{
static_cast<parent&>(*this) /= rhs;
base() /= rhs;
return *this;
}
@ -138,13 +153,26 @@ namespace rotgen
return parent::Zero(rows, cols);
}
static concrete_type Constant(scalar_type value)
static concrete_type Ones()
requires (Rows != -1 && Cols != -1)
{
return parent::Ones(Rows, 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(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size");
return parent::Ones(rows, cols);
}
static concrete_type Constant(value_type value)
requires (Rows != -1 && Cols != -1)
{
return parent::Constant(Rows, Cols, static_cast<double>(value));
}
static concrete_type Constant(int rows, int cols, scalar_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(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size");
@ -177,47 +205,86 @@ namespace rotgen
return parent::Identity(rows, cols);
}
block& setOnes()
{
parent::assign(parent::Ones(parent::rows(), parent::cols()));
return *this;
}
block& setZero()
{
parent::assign(parent::Zero(parent::rows(), parent::cols()));
return *this;
}
block& setConstant(value_type value)
{
parent::assign(parent::Constant(parent::rows(), parent::cols(), value));
return *this;
}
block& setRandom()
{
parent::assign(parent::Random(parent::rows(), parent::cols()));
return *this;
}
block& setIdentity()
{
parent::assign(parent::Identity(parent::rows(), parent::cols()));
return *this;
}
template<int P>
double lpNorm() const
{
assert(P == 1 || P == 2 || P == Infinity);
return parent::lpNorm(P);
}
parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
};
template<typename Ref, int R, int C, bool I, int F>
typename block<Ref, R, C, I, F>::concrete_type operator+(block<Ref, R, C, I, F> const& lhs, block<Ref, R, C, I, F> const& rhs)
auto operator+(block<Ref, R, C, I, F> const& lhs, block<Ref, R, C, I, F> const& rhs)
{
return lhs.matrix_addition(rhs);
using concrete_type = typename block<Ref, R, C, I, F>::concrete_type;
return concrete_type(lhs.base().add(rhs));
}
template<typename Ref, int R, int C, bool I, int F>
typename block<Ref, R, C, I, F>::concrete_type operator-(block<Ref, R, C, I, F> const& lhs, block<Ref, R, C, I, F> const& rhs)
auto operator-(block<Ref, R, C, I, F> const& lhs, block<Ref, R, C, I, F> const& rhs)
{
return lhs.matrix_subtraction(rhs);
using concrete_type = typename block<Ref, R, C, I, F>::concrete_type;
return concrete_type(lhs.base().sub(rhs));
}
template<typename Ref, int R, int C, bool I, int F>
typename block<Ref, R, C, I, F>::concrete_type operator*(block<Ref, R, C, I, F> const& lhs, block<Ref, R, C, I, F> const& rhs)
auto operator*(block<Ref, R, C, I, F> const& lhs, block<Ref, R, C, I, F> const& rhs)
{
return lhs.matrix_multiplication(rhs);
using concrete_type = typename block<Ref, R, C, I, F>::concrete_type;
return concrete_type(lhs.base().mul(rhs));
}
template<typename Ref, int R, int C, bool I, int F>
typename block<Ref, R, C, I, F>::concrete_type operator*(block<Ref, R, C, I, F> const& lhs, double rhs)
auto operator*(block<Ref, R, C, I, F> const& lhs, double rhs)
{
return lhs.matrix_multiplication(rhs);
using concrete_type = typename block<Ref, R, C, I, F>::concrete_type;
return concrete_type(lhs.base().mul(rhs));
}
template<typename Ref, int R, int C, bool I, int F>
typename block<Ref, R, C, I, F>::concrete_type operator*(double lhs, block<Ref, R, C, I, F> const& rhs)
auto operator*(double lhs, block<Ref, R, C, I, F> const& rhs)
{
return rhs.matrix_multiplication(lhs);
using concrete_type = typename block<Ref, R, C, I, F>::concrete_type;
return concrete_type(rhs.base().mul(lhs));
}
template<typename Ref, int R, int C, bool I, int F>
typename block<Ref, R, C, I, F>::concrete_type operator/(block<Ref, R, C, I, F> const& lhs, double rhs)
auto operator/(block<Ref, R, C, I, F> const& lhs, double rhs)
{
return lhs.matrix_division(rhs);
using concrete_type = typename block<Ref, R, C, I, F>::concrete_type;
return concrete_type(lhs.base().div(rhs));
}
}

View file

@ -0,0 +1,280 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/concepts.hpp>
#include <rotgen/impl/map.hpp>
#include <cassert>
namespace rotgen
{
template<typename Ref, int Options = ColMajor, typename = void>
class map : public find_map<Ref>
{
public:
static_assert ( concepts::entity<Ref>
, "[ROTGEN][CRITICAL] - Map of non-rotgen type instanciated"
);
using parent = find_map<Ref>;
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;
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_defined_static = false;
using ptr_type = std::conditional_t<is_immutable, value_type const*, value_type*>;
using stride_type = stride;
static constexpr Index RowsAtCompileTime = Ref::RowsAtCompileTime;
static constexpr Index ColsAtCompileTime = Ref::ColsAtCompileTime;
map(ptr_type ptr, Index r, Index c, stride_type s) : parent(ptr, r, c,s) {}
map(ptr_type ptr, Index r, Index c) : map(ptr, r, c, strides<storage_order>(r,c)) {}
map(ptr_type ptr, stride_type s) requires(RowsAtCompileTime!=-1 && ColsAtCompileTime!=-1)
: parent(ptr,RowsAtCompileTime,ColsAtCompileTime, s)
{}
map(ptr_type ptr, Index size) requires(RowsAtCompileTime==1 || ColsAtCompileTime==1)
: map( ptr, RowsAtCompileTime==1?1:size, ColsAtCompileTime==1?1:size)
{}
map(ptr_type ptr) requires(RowsAtCompileTime!=-1 && ColsAtCompileTime!=-1)
: map( ptr, RowsAtCompileTime, ColsAtCompileTime )
{}
template<typename R2, int O2, typename S2>
map(map<R2,O2,S2> const& other) : map ( other.data(), other.rows(), other.cols()
, stride{other.outerStride(),other.innerStride()}
)
{}
map(parent const& base) : parent(base) {}
map(map const& other) : parent(other)
{}
map& operator=(map const& other) requires(!is_immutable)
{
base() = static_cast<parent const &>(*other);
return *this;
}
value_type& operator()(Index i, Index j) requires(!is_immutable) { return parent::operator()(i,j); }
value_type& operator()(Index i) requires(!is_immutable)
{
assert( parent::innerStride() == 1
&& parent::outerStride() ==(storage_order == RowMajor ? parent::cols() : parent::rows())
);
return parent::operator()(i);
}
value_type operator()(Index i, Index j) const { return parent::operator()(i,j); }
value_type operator()(Index i) const
{
assert( parent::innerStride() == 1
&& parent::outerStride() ==(storage_order == RowMajor ? parent::cols() : parent::rows())
);
return parent::operator()(i);
}
concrete_type transpose() const
{
return concrete_type(static_cast<parent const &>(*this).transpose());
}
concrete_type conjugate() const
{
return concrete_type(static_cast<parent const &>(*this).conjugate());
}
concrete_type adjoint() const
{
return concrete_type(static_cast<parent const &>(*this).adjoint());
}
void transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); }
void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); }
map& operator+=(map const& rhs) requires(!is_immutable)
{
base() += static_cast<parent const&>(rhs);
return *this;
}
map& operator-=(map const& rhs) requires(!is_immutable)
{
base() -= static_cast<parent const&>(rhs);
return *this;
}
concrete_type operator-() const
{
return concrete_type(base().operator-());
}
map& operator*=(map const& rhs) requires(!is_immutable)
{
base() *= static_cast<parent const&>(rhs);
return *this;
}
map& operator*=(value_type rhs) requires(!is_immutable)
{
base() *= rhs;
return *this;
}
map& operator/=(value_type rhs) requires(!is_immutable)
{
base() /= rhs;
return *this;
}
static auto Zero() requires( requires {Ref::Zero();} )
{
return Ref::Zero();
}
static auto Zero(int rows, int cols)
{
return Ref::Zero(rows,cols);
}
static auto Constant(value_type value) requires( requires {Ref::Constant(value);} )
{
return Ref::Constant(value);
}
static auto Constant(int rows, int cols, value_type value)
{
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& setZero() requires(!is_immutable)
{
parent::setZero();
return *this;
}
map& setOnes() requires(!is_immutable)
{
parent::setOnes();
return *this;
}
map& setIdentity() requires(!is_immutable)
{
parent::setIdentity();
return *this;
}
map& setRandom() requires(!is_immutable)
{
parent::setRandom();
return *this;
}
map& setConstant(value_type s) requires(!is_immutable)
{
parent::setConstant(s);
return *this;
}
template<int P>
double lpNorm() const
{
assert(P == 1 || P == 2 || P == Infinity);
return parent::lpNorm(P);
}
parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this); }
};
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)
{
using concrete_type = typename map<R1,O1,S1>::concrete_type;
return concrete_type(lhs.base().add(map<R1,O1,S1>(rhs)));
}
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)
{
using concrete_type = typename map<R1,O1,S1>::concrete_type;
return concrete_type(lhs.base().sub(map<R1,O1,S1>(rhs)));
}
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)
{
using concrete_type = typename map<R1,O1,S1>::concrete_type;
return concrete_type(lhs.base().mul(map<R1,O1,S1>(rhs)));
}
template<typename R, int O, typename S>
typename map<R,O,S>::concrete_type
operator*(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;
return concrete_type(lhs.base().mul(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, map<R,O,S> const& rhs)
{
using concrete_type = typename map<R,O,S>::concrete_type;
return concrete_type(rhs.base().mul(s));
}
template<typename R, int O, typename S>
typename map<R,O,S>::concrete_type
operator/(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;
return concrete_type(lhs.base().div(s));
}
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)
{
return lhs.base() == rhs.base();
}
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)
{
return lhs.base() != rhs.base();
}
}

View file

@ -15,20 +15,23 @@ namespace rotgen
{
template< typename Scalar
, int Rows = Dynamic , int Cols = Dynamic
, int Options = ColMajor
, int Opts = ColMajor
, int MaxRows = Rows , int MaxCols = Cols
>
class matrix : public find_matrix<Scalar,Options>
class matrix : public find_matrix<Scalar,Opts>
{
public:
using parent = find_matrix<Scalar,Options>;
using parent = find_matrix<Scalar,Opts>;
using rotgen_tag = void;
using concrete_type = matrix;
using scalar_type = Scalar;
static constexpr auto storage_order = Options & 1;
using value_type = Scalar;
static constexpr auto storage_order = Opts & 1;
static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols;
static constexpr int Options = Opts;
static constexpr bool is_defined_static = false;
static constexpr bool has_static_storage = false;
matrix() : parent(Rows==-1?0:Rows,Cols==-1?0:Cols) {}
@ -57,6 +60,15 @@ namespace rotgen
: parent(Rows, Cols, {s0,static_cast<Scalar>(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");
for (rotgen::Index r = 0; r < e.rows(); ++r)
for (rotgen::Index c = 0; c < e.cols(); ++c)
(*this)(r, c) = e(r, c);
}
void resize(int new_rows, int new_cols) requires(Rows == -1 && Cols == -1)
{
parent::resize(new_rows, new_cols);
@ -69,17 +81,17 @@ namespace rotgen
matrix transpose() const
{
return matrix(static_cast<parent const&>(*this).transpose());
return matrix(base().transpose());
}
matrix conjugate() const
{
return matrix(static_cast<parent const&>(*this).conjugate());
return matrix(base().conjugate());
}
matrix adjoint() const
{
return matrix(static_cast<parent const&>(*this).adjoint());
return matrix(base().adjoint());
}
void transposeInPlace() { parent::transposeInPlace(); }
@ -92,39 +104,51 @@ namespace rotgen
matrix& operator+=(matrix const& rhs)
{
static_cast<parent&>(*this) += static_cast<parent const&>(rhs);
base() += static_cast<parent const&>(rhs);
return *this;
}
matrix& operator-=(matrix const& rhs)
{
static_cast<parent&>(*this) -= static_cast<parent const&>(rhs);
base() -= static_cast<parent const&>(rhs);
return *this;
}
matrix operator-() const
{
return matrix(static_cast<parent const&>(*this).operator-());
return matrix(base().operator-());
}
matrix& operator*=(matrix const& rhs)
{
static_cast<parent&>(*this) *= static_cast<parent const&>(rhs);
base() *= static_cast<parent const&>(rhs);
return *this;
}
matrix& operator*=(Scalar rhs)
{
static_cast<parent&>(*this) *= rhs;
base() *= rhs;
return *this;
}
matrix& operator/=(Scalar rhs)
{
static_cast<parent&>(*this) /= rhs;
base() /= rhs;
return *this;
}
static matrix Ones() requires (Rows != -1 && Cols != -1)
{
return parent::Ones(Rows, Cols);
}
static matrix Ones(int rows, int cols)
{
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size");
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size");
return parent::Ones(rows, cols);
}
static matrix Zero() requires (Rows != -1 && Cols != -1)
{
return parent::Zero(Rows, Cols);
@ -173,6 +197,66 @@ namespace rotgen
return parent::Identity(rows, cols);
}
matrix& setOnes()
{
*this = parent::Ones(Rows, Cols);
return *this;
}
matrix& setOnes(int rows, int cols)
{
*this = parent::Ones(rows, cols);
return *this;
}
matrix& setZero()
{
*this = parent::Zero(Rows, Cols);
return *this;
}
matrix& setZero(int rows, int cols)
{
*this = parent::Zero(rows, cols);
return *this;
}
matrix& setConstant(Scalar value)
{
*this = parent::Constant(Rows, Cols, static_cast<Scalar>(value));
return *this;
}
matrix& setConstant(int rows, int cols, Scalar value)
{
*this = parent::Constant(rows, cols, static_cast<Scalar>(value));
return *this;
}
matrix& setRandom()
{
*this = parent::Random(Rows, Cols);
return *this;
}
matrix& setRandom(int rows, int cols)
{
*this = parent::Random(rows, cols);
return *this;
}
matrix& setIdentity()
{
*this = parent::Identity(Rows, Cols);
return *this;
}
matrix& setIdentity(int rows, int cols)
{
*this = parent::Identity(rows, cols);
return *this;
}
template<int P>
Scalar lpNorm() const
{
@ -180,6 +264,8 @@ namespace rotgen
return parent::lp_norm(P);
}
parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<parent const&>(*this);; }
};
template<typename S, int R, int C, int O, int MR, int MC>
@ -204,20 +290,20 @@ namespace rotgen
}
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, S 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);
return that *= rhs;
}
template<typename S, int R, int C, int O, int MR, int MC>
matrix<S,R,C,O,MR,MC> operator*(S 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;
}
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, S 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);
return that /= rhs;

View file

@ -8,7 +8,6 @@
#pragma once
#include <rotgen/detail/static_info.hpp>
#include <rotgen/fixed/common.hpp>
#include <Eigen/Dense>
#include <iostream>
@ -17,7 +16,7 @@ namespace rotgen
namespace detail
{
template<typename Ref, int Rows, int Cols, bool Inner>
using block_type = std::conditional_t < storage_status<Rows,Cols>
using block_type = std::conditional_t < storage_status<Rows,Cols,Rows,Cols>
, Eigen::Block<typename Ref::parent, Rows, Cols, Inner>
, Eigen::Block<typename Ref::parent, Eigen::Dynamic, Eigen::Dynamic, Inner>
>;
@ -25,7 +24,7 @@ namespace rotgen
template< typename Ref
, int Rows = Dynamic, int Cols = Dynamic
, bool Inner = false, int ForceStorageOrder = -1
, bool Inner = false , int ForceStorageOrder = -1
>
class block : private detail::block_type<Ref, Rows, Cols, Inner>
{
@ -37,21 +36,21 @@ namespace rotgen
using rotgen_tag = void;
using parent = detail::block_type<Ref, Rows, Cols, Inner>;
using value_type = typename parent::value_type;
using scalar_type = typename parent::value_type;
using Index = typename parent::Index;
static constexpr int storage_order = (ForceStorageOrder == -1) ? Ref::storage_order : ForceStorageOrder;
using concrete_type = matrix<scalar_type,Rows,Cols,storage_order>;
using concrete_dynamic_type = matrix<scalar_type>;
using concrete_type = matrix<value_type,Rows,Cols,storage_order>;
using concrete_dynamic_type = matrix<value_type,Dynamic,Dynamic,storage_order>;
template<typename ET>
using as_concrete_type = as_concrete_t<ET, matrix>;
static constexpr auto Flags = Ref::Flags;
static constexpr int Options = Ref::Options;
static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols;
private:
static constexpr bool has_static_storage = storage_status<Rows,Cols>;
static constexpr bool is_defined_static = Rows!=-1 && Cols!=-1;
static constexpr bool has_static_storage = storage_status<Rows,Cols,Rows,Cols>;
public:
@ -67,6 +66,10 @@ namespace rotgen
: parent(r.base(),i0,j0,Rows,Cols)
{}
template<typename B, int R, int C, bool I, int FS>
block(block<B,R,C,I,FS> const& other) : parent(other.base())
{}
template<typename OtherDerived>
block(const Eigen::MatrixBase<OtherDerived>& other) : parent(other) {}
@ -90,34 +93,38 @@ namespace rotgen
parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<const parent&>(*this); }
concrete_type transpose() const
auto transpose() const
{
return concrete_type(static_cast<parent const &>(*this).transpose());
auto res = static_cast<parent const &>(*this).transpose();
return as_concrete_type<decltype(res)>(res);
}
concrete_type conjugate() const
auto conjugate() const
{
return concrete_type(static_cast<parent const &>(*this).conjugate());
auto res = static_cast<parent const &>(*this).conjugate();
return as_concrete_type<decltype(res)>(res);
}
concrete_type adjoint() const
auto adjoint() const
{
return concrete_type(static_cast<parent const &>(*this).adjoint());
auto res = static_cast<parent const &>(*this).adjoint();
return as_concrete_type<decltype(res)>(res);
}
void transposeInPlace() { parent::transposeInPlace(); }
void adjointInPlace() { parent::adjointInPlace(); }
static concrete_type Constant(scalar_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<scalar_type>(value));
return parent::Constant(Rows, Cols, static_cast<value_type>(value));
}
static concrete_type Constant(int rows, int cols, scalar_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(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size");
return parent::Constant(rows, cols, static_cast<scalar_type>(value));
return parent::Constant(rows, cols, static_cast<value_type>(value));
}
static concrete_type Identity() requires (Rows != -1 && Cols != -1)
@ -144,6 +151,18 @@ namespace rotgen
return parent::Zero(rows, cols);
}
static concrete_type Ones() requires (Rows != -1 && Cols != -1)
{
return parent::Ones(Rows, 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(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size");
return parent::Ones(rows, cols);
}
static concrete_type Random() requires (Rows != -1 && Cols != -1)
{
return parent::Random(Rows, Cols);
@ -156,14 +175,98 @@ namespace rotgen
return parent::Random(rows, cols);
}
block& setOnes()
{
*this = parent::Ones(rows(), cols());
return *this;
}
block& setOnes(int r, int c)
{
*this = parent::Ones(r, c);
return *this;
}
block& setZero()
{
*this = parent::Zero(rows(), cols());
return *this;
}
block& setZero(int r, int c)
{
*this = parent::Zero(r,c);
return *this;
}
block& setConstant(value_type value)
{
*this = parent::Constant(rows(), cols(), value);
return *this;
}
block& setConstant(int r, int c, value_type value)
{
*this = parent::Constant(r,c, value);
return *this;
}
block& setRandom()
{
*this = parent::Random(rows(),cols());
return *this;
}
block& setRandom(int r, int c)
{
*this = parent::Random(r,c);
return *this;
}
block& setIdentity()
{
*this = parent::Identity(rows(),cols());
return *this;
}
block& setIdentity(int r, int c)
{
*this = parent::Identity(r,c);
return *this;
}
template<int P>
scalar_type lpNorm() const
value_type lpNorm() const
{
static_assert(P == 1 || P == 2 || P == Infinity);
return parent::template lpNorm<P>();
}
using parent::operator();
bool is_contiguous_linear() const
{
if(parent::innerStride() != 1) return false;
// outerstride must equal the “innerdimension length”
if constexpr(storage_order) return parent::outerStride() == parent::cols();
else return parent::outerStride() == parent::rows();
}
value_type& operator()(Index i, Index j) { return base()(i,j); }
value_type operator()(Index i, Index j) const { return base()(i,j); }
value_type& operator()(Index i)
{
assert(is_contiguous_linear());
return base().data()[i];
}
value_type operator()(Index i) const
{
assert(is_contiguous_linear());
return base().data()[i];
}
using parent::innerStride;
using parent::outerStride;
using parent::rows;
using parent::cols;
using parent::size;
@ -200,25 +303,16 @@ namespace rotgen
return *this;
}
block& operator*=(scalar_type rhs)
block& operator*=(value_type rhs)
{
static_cast<parent&>(*this) *= rhs;
return *this;
}
block& operator/=(scalar_type rhs)
block& operator/=(value_type rhs)
{
static_cast<parent&>(*this) /= rhs;
return *this;
}
static void print_storage_info()
{
std::cout << "Block " << Rows << "x" << Cols
<< " - Storage: " << (has_static_storage ? "Static" : "Dynamic")
<< " (from: ";
Ref::print_storage_info();
std::cout << ")" << std::endl;
}
};
}

View file

@ -1,86 +0,0 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/concepts.hpp>
#include <concepts>
#include <iosfwd>
namespace rotgen
{
template<typename EigenType
, template<typename,int,int,int,int,int> typename Wrapper
>
struct as_concrete
{
using type = Wrapper< typename EigenType::value_type
, EigenType::RowsAtCompileTime, EigenType::ColsAtCompileTime
, EigenType::Flags
, EigenType::MaxRowsAtCompileTime, EigenType::MaxColsAtCompileTime
>;
};
template<typename EigenType
, template<typename,int,int,int,int,int> typename Wrapper
>
using as_concrete_t = typename as_concrete<EigenType,Wrapper>::type;
template<concepts::entity E1, concepts::entity E2>
bool operator==(E1 const& lhs, E2 const& rhs)
{
return lhs.base() == rhs.base();
}
template<concepts::entity E>
std::ostream& operator<<(std::ostream& os, E const& arg)
{
return os << arg.base();
}
template<concepts::entity E1, concepts::entity E2>
auto operator+(E1 const& lhs, E2 const& rhs)
{
using type = E1::template as_concrete_type<decltype(lhs.base() + rhs.base())>;
return type(lhs.base() + rhs.base());
}
template<concepts::entity E1, concepts::entity E2>
auto operator-(E1 const& lhs, E2 const& rhs)
{
using type = E1::template as_concrete_type<decltype(lhs.base() - rhs.base())>;
return type(lhs.base() - rhs.base());
}
template<concepts::entity E1, concepts::entity E2>
auto operator*(E1 const& lhs, E2 const& rhs)
{
using type = typename E1::concrete_dynamic_type;
return type(lhs.base() * rhs.base());
}
template<concepts::entity E, std::convertible_to<typename E::scalar_type> S>
auto operator*(E const& lhs, S rhs)
{
using type = E::template as_concrete_type<decltype(lhs.base() * rhs)>;
return type(lhs.base() * rhs);
}
template<concepts::entity E, std::convertible_to<typename E::scalar_type> S>
auto operator*(S lhs, E const& rhs )
{
using type = E::template as_concrete_type<decltype(lhs * rhs.base())>;
return type(lhs * rhs.base());
}
template<concepts::entity E, std::convertible_to<typename E::scalar_type> S>
auto operator/(E const& lhs, S rhs)
{
using type = E::template as_concrete_type<decltype(lhs.base() / rhs)>;
return type(lhs.base() / rhs);
}
}

View file

@ -0,0 +1,328 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/detail/static_info.hpp>
#include <Eigen/Dense>
#include <iostream>
namespace rotgen
{
namespace detail
{
template<typename Ref, int Options, bool isConst>
struct compute_map_type
{
using base = Eigen::Matrix< typename Ref::value_type
, Ref::RowsAtCompileTime, Ref::ColsAtCompileTime
, Ref::storage_order
>;
using ref_t = std::conditional_t<isConst, base const, base>;
using type = Eigen::Map<ref_t, Options, Eigen::Stride<-1,-1>>;
};
template<typename Ref, int Options, bool isConst>
using map_type = typename compute_map_type<Ref,Options,isConst>::type;
template<typename T> struct map_stride;
template<typename PlainObjectType, int MapOptions, typename Stride>
struct map_stride<Eigen::Map<PlainObjectType, MapOptions, Stride>>
{
using type = Stride;
};
}
template<typename Ref, int Options = ColMajor, typename = void>
class map : private detail::map_type<std::remove_const_t<Ref>, Options, std::is_const_v<Ref>>
{
public:
using rotgen_tag = void;
using parent = 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;
static constexpr auto Flags = Ref::Flags;
static constexpr Index RowsAtCompileTime = Ref::RowsAtCompileTime;
static constexpr Index ColsAtCompileTime = Ref::ColsAtCompileTime;
static constexpr bool has_static_storage = Ref::has_static_storage;
static constexpr int storage_order = Ref::storage_order;
static constexpr bool is_immutable = std::is_const_v<Ref>;
static constexpr bool is_defined_static = Ref::is_defined_static;
template<typename ET>
using as_concrete_type = as_concrete_t<ET, matrix>;
using ptr_type = std::conditional_t<is_immutable, value_type const*, value_type*>;
using stride_type = typename detail::map_stride<parent>::type;
map(const map&) = default;
map(map&&) = default;
map& operator=(const map&) = default;
map& operator=(map&&) = default;
map(ptr_type ptr, Index r, Index c, stride_type s) : parent(ptr, r, c, s) {}
map(ptr_type ptr, Index r, Index c) : map(ptr, r, c, strides<storage_order>(r,c)) {}
map(ptr_type ptr, stride_type s) requires(RowsAtCompileTime!=-1 && ColsAtCompileTime!=-1)
: parent(ptr, s)
{}
map(ptr_type ptr, Index 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, RowsAtCompileTime, ColsAtCompileTime )
{}
parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<const parent&>(*this); }
value_type& operator()(Index i, Index j) { return base()(i, j); }
value_type operator()(Index i, Index j) const { return base()(i, j); }
value_type& operator()(Index i) requires(!is_immutable)
{
assert(is_contiguous_linear());
return base().data()[i];
}
value_type operator()(Index i) const
{
assert(is_contiguous_linear());
return base().data()[i];
}
map& operator+=(map const& rhs)
{
base() += rhs.base();
return *this;
}
map& operator-=(map const& rhs)
{
base() -= rhs.base();
return *this;
}
map& operator*=(map const& rhs)
{
base() *= rhs;
return *this;
}
map& operator*=(value_type rhs)
{
base() *= rhs;
return *this;
}
map& operator/=(value_type rhs)
{
base() /= rhs;
return *this;
}
auto transpose() const
{
if constexpr(use_expression_templates) return base().transpose();
else return as_concrete_type<decltype(base().transpose())>(base().transpose());
}
auto adjoint() const
{
if constexpr(use_expression_templates) return base().adjoint();
else return as_concrete_type<decltype(base().adjoint())>(base().adjoint());
}
auto conjugate() const
{
if constexpr(use_expression_templates) return base().conjugate();
else return as_concrete_type<decltype(base().conjugate())>(base().conjugate());
}
void transposeInPlace() { base().transposeInPlace(); }
void adjointInPlace() { base().adjointInPlace(); }
static auto Zero() requires( requires {Ref::Zero();} ) { return Ref::Zero(); }
static auto Zero(int rows, int cols) { return Ref::Zero(rows,cols); }
static auto Ones() requires( requires {Ref::Ones();} ) { return Ref::Ones(); }
static auto Ones(int rows, int cols) { return Ref::Ones(rows,cols); }
static auto Constant(value_type value) requires( requires {Ref::Constant(value);} )
{ return Ref::Constant(value); }
static auto Constant(int rows, int cols, value_type value) { 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()
{
base() = parent::Ones(base().rows(), base().cols());
return *this;
}
map& setZero()
{
base() = parent::Zero(base().rows(), base().cols());
return *this;
}
map& setConstant(value_type value)
{
base() = parent::Constant(base().rows(), base().cols(), value);
return *this;
}
map& setRandom()
{
base() = parent::Random(base().rows(), base().cols());
return *this;
}
map& setIdentity()
{
base() = parent::Identity(base().rows(), base().cols());
return *this;
}
bool is_contiguous_linear() const
{
if(base().innerStride() != 1) return false;
if constexpr(storage_order == rotgen::RowMajor) return base().outerStride() == base().cols();
else return base().outerStride() == base().rows();
}
using parent::innerStride;
using parent::outerStride;
using parent::rows;
using parent::cols;
using parent::size;
using parent::data;
using parent::sum;
using parent::mean;
using parent::prod;
using parent::trace;
using parent::maxCoeff;
using parent::minCoeff;
using parent::norm;
using parent::squaredNorm;
template<int P> value_type lpNorm() const
{
static_assert(P == 1 || P == 2 || P == Infinity);
return parent::template lpNorm<P>();
}
};
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)
{
return lhs.base() == rhs.base();
}
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)
{
return lhs.base() != rhs.base();
}
#if defined(ROTGEN_ENABLE_EXPRESSION_TEMPLATES)
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)
{
return lhs.base() + rhs.base();
}
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)
{
return lhs.base() - rhs.base();
}
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)
{
return lhs.base() * rhs.base();
}
template<typename R, int O, typename S>
auto operator*( map<R, O, S> const& lhs, std::convertible_to<typename R::value_type> auto s)
{
return lhs.base() * 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)
{
return s * rhs.base();
}
template<typename R, int O, typename S>
auto operator/(map<R, O, S> const& lhs, std::convertible_to<typename R::value_type> auto s)
{
return lhs.base() / s;
}
#else
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)
{
using concrete_type = typename map<R1,O1,S1>::concrete_type;
return concrete_type(lhs.base() + rhs.base());
}
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)
{
using concrete_type = typename map<R1,O1,S1>::concrete_type;
return concrete_type(lhs.base() - rhs.base());
}
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)
{
using concrete_type = typename map<R1,O1,S1>::concrete_type;
return concrete_type(lhs.base() * rhs.base());
}
template<typename R, int O, typename S>
typename map<R,O,S>::concrete_type operator*( 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;
return concrete_type(lhs.base() * 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
, map<R, O, S> const& rhs
)
{
using concrete_type = typename map<R,O,S>::concrete_type;
return concrete_type(rhs.base() * s);
}
template<typename R, int O, typename S>
typename map<R,O,S>::concrete_type operator/( 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;
return concrete_type(lhs.base() / s);
}
#endif
}

View file

@ -8,7 +8,6 @@
#pragma once
#include <rotgen/detail/static_info.hpp>
#include <rotgen/fixed/common.hpp>
#include <Eigen/Dense>
#include <iostream>
@ -17,7 +16,7 @@ namespace rotgen
namespace detail
{
template<typename Scalar, int Rows, int Cols, int Opts,int MaxRows, int MaxCols>
using storage_type = std::conditional_t < storage_status<Rows,Cols>
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>
>;
@ -25,27 +24,31 @@ namespace rotgen
template< typename Scalar
, int Rows = Dynamic , int Cols = Dynamic
, int Options = ColMajor
, int Opts = ColMajor
, int MaxRows = Rows , int MaxCols = Cols
>
class matrix : private detail::storage_type<Scalar, Rows, Cols, Options, MaxRows, MaxCols>
class matrix : private detail::storage_type<Scalar, Rows, Cols, Opts, MaxRows, MaxCols>
{
public:
using rotgen_tag = void;
using parent = detail::storage_type<Scalar, Rows, Cols, Options, MaxRows, MaxCols>;
using parent = detail::storage_type<Scalar, Rows, Cols, Opts, MaxRows, MaxCols>;
using value_type = Scalar;
using scalar_type = Scalar;
using Index = typename parent::Index;
static constexpr auto storage_order = Options & 1;
static constexpr auto storage_order = Opts & 1;
using concrete_type = matrix;
using concrete_dynamic_type = matrix<scalar_type>;
using concrete_dynamic_type = matrix<value_type>;
static constexpr auto Flags = parent::Flags;
static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols;
static constexpr int Options = parent::Options;
template<typename ET>
using as_concrete_type = as_concrete_t<ET, matrix>;
private:
static constexpr bool has_static_storage = storage_status<Rows,Cols>;
static constexpr bool is_defined_static = Rows!=-1 && Cols!=-1;
static constexpr bool has_static_storage = storage_status<Rows,Cols,MaxRows,MaxCols>;
public:
@ -58,7 +61,6 @@ namespace rotgen
matrix& operator=(const matrix&) = default;
matrix& operator=(matrix&&) = default;
matrix(std::initializer_list<std::initializer_list<Scalar>> init) : parent(init)
{}
@ -82,10 +84,17 @@ namespace rotgen
}
}
matrix(concepts::entity auto const& other) : parent(other.base())
{}
template<typename OtherDerived>
matrix(const Eigen::MatrixBase<OtherDerived>& other) : parent(other)
{}
template<typename OtherDerived>
matrix(const Eigen::EigenBase<OtherDerived>& other) : parent(other)
{}
template<typename OtherDerived>
matrix& operator=(const Eigen::MatrixBase<OtherDerived>& other)
{
@ -100,22 +109,31 @@ namespace rotgen
return *this;
}
matrix& operator=(concepts::entity auto const& other)
{
parent::operator=(other.base());
return *this;
}
parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<const parent&>(*this); }
concrete_type transpose() const
auto transpose() const
{
return concrete_type(static_cast<parent const &>(*this).transpose());
auto res = static_cast<parent const &>(*this).transpose();
return as_concrete_type<decltype(res)>(res);
}
concrete_type conjugate() const
auto conjugate() const
{
return concrete_type(static_cast<parent const &>(*this).conjugate());
auto res = static_cast<parent const &>(*this).conjugate();
return as_concrete_type<decltype(res)>(res);
}
concrete_type adjoint() const
auto adjoint() const
{
return concrete_type(static_cast<parent const &>(*this).adjoint());
auto res = static_cast<parent const &>(*this).adjoint();
return as_concrete_type<decltype(res)>(res);
}
void transposeInPlace() { parent::transposeInPlace(); }
@ -155,6 +173,18 @@ namespace rotgen
return parent::Identity(rows, cols);
}
static matrix Ones() requires (Rows != -1 && Cols != -1)
{
return parent::Ones(Rows, Cols);
}
static matrix Ones(int rows, int cols)
{
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size");
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size");
return parent::Ones(rows, cols);
}
static matrix Zero() requires (Rows != -1 && Cols != -1)
{
return parent::Zero(Rows, Cols);
@ -180,7 +210,7 @@ namespace rotgen
}
template<int P>
scalar_type lpNorm() const
value_type lpNorm() const
{
static_assert(P == 1 || P == 2 || P == Infinity);
return parent::template lpNorm<P>();
@ -200,6 +230,66 @@ namespace rotgen
using parent::sum;
using parent::data;
matrix& setOnes()
{
*this = parent::Ones(rows(),cols());
return *this;
}
matrix& setOnes(int r, int c)
{
*this = parent::Ones(r, c);
return *this;
}
matrix& setZero()
{
*this = parent::Zero(rows(),cols());
return *this;
}
matrix& setZero(int r, int c)
{
*this = parent::Zero(r, c);
return *this;
}
matrix& setConstant(Scalar value)
{
*this = parent::Constant(rows(),cols(), static_cast<Scalar>(value));
return *this;
}
matrix& setConstant(int r, int c, Scalar value)
{
*this = parent::Constant(r, c, static_cast<Scalar>(value));
return *this;
}
matrix& setRandom()
{
*this = parent::Random(rows(),cols());
return *this;
}
matrix& setRandom(int r, int c)
{
*this = parent::Random(r, c);
return *this;
}
matrix& setIdentity()
{
*this = parent::Identity(rows(),cols());
return *this;
}
matrix& setIdentity(int r, int c)
{
*this = parent::Identity(r, c);
return *this;
}
matrix& operator+=(matrix const& rhs)
{
static_cast<parent&>(*this) += static_cast<parent const&>(rhs);
@ -234,13 +324,5 @@ namespace rotgen
static_cast<parent&>(*this) /= rhs;
return *this;
}
static void print_storage_info()
{
std::cout << "Matrix " << Rows << "x" << Cols
<< " - Storage: " << (has_static_storage ? "Static" : "Dynamic")
<< " (Max. size=" << max_static_size << ")"
<< std::endl;
}
};
}

View file

@ -9,134 +9,52 @@
namespace rotgen
{
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
std::size_t rows(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
std::size_t rows(concepts::entity auto const& arg) { return arg.rows(); }
std::size_t cols(concepts::entity auto const& arg) { return arg.cols(); }
std::size_t size(concepts::entity auto const& arg) { return arg.size(); }
template<concepts::entity E>
void resize(E& arg, int new_rows, int new_cols)
requires(E::RowsAtCompileTime == -1 && E::ColsAtCompileTime == -1)
{
return matrix.rows();
arg.resize(new_rows, new_cols);
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
std::size_t cols(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
template<concepts::entity E>
void conservativeResize(E& arg, int new_rows, int new_cols)
requires(E::RowsAtCompileTime == -1 && E::ColsAtCompileTime == -1)
{
return matrix.cols();
arg.conservativeResize(new_rows, new_cols);
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
std::size_t size(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
decltype(auto) transpose(concepts::entity auto const& arg) { return arg.transpose(); }
decltype(auto) conjugate(concepts::entity auto const& arg) { return arg.conjugate(); }
decltype(auto) adjoint (concepts::entity auto const& arg) { return arg.adjoint(); }
void transposeInPlace(concepts::entity auto& arg) { arg.transposeInPlace(); }
void adjointInPlace(concepts::entity auto& arg) { arg.adjointInPlace(); }
auto trace(concepts::entity auto const& arg) { return arg.trace(); }
auto squaredNorm(concepts::entity auto const& arg) { return arg.squaredNorm(); }
auto norm(concepts::entity auto const& arg) { return arg.norm(); }
auto sum(concepts::entity auto const& arg) { return arg.sum(); }
auto prod(concepts::entity auto const& arg) { return arg.prod(); }
auto mean(concepts::entity auto const& arg) { return arg.mean(); }
auto maxCoeff(concepts::entity auto const& arg) { return arg.maxCoeff(); }
auto minCoeff(concepts::entity auto const& arg) { return arg.minCoeff(); }
auto maxCoeff(concepts::entity auto const& arg, Index* row, Index* col)
{
return matrix.size();
return arg.maxCoeff(row, col);
}
auto minCoeff(concepts::entity auto const& arg, Index* row, Index* col)
{
return arg.minCoeff(row, col);
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
void resize(rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix, int new_rows, int new_cols)
requires(Rows == -1 && Cols == -1)
{
matrix.resize(new_rows, new_cols);
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
void conservativeResize(rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix, int new_rows, int new_cols)
requires(Rows == -1 && Cols == -1)
{
matrix.conservativeResize(new_rows, new_cols);
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
rotgen::matrix<Scalar, Cols, Rows, Options, MaxCols, MaxRows> transpose(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.transpose();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> conjugate(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.conjugate();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
rotgen::matrix<Scalar, Cols, Rows, Options, MaxCols, MaxRows> adjoint(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.adjoint();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
void transposeInPlace(rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
matrix.transposeInPlace();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
void adjointInPlace(rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
matrix.adjointInPlace();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double squaredNorm(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.squaredNorm();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double norm(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.norm();
}
template< int P, typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double lpNorm(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
template<int P>
auto lpNorm(concepts::entity auto const& arg)
{
static_assert(P == 1 || P == 2 || P == Infinity);
return matrix.template lpNorm<P>();
return arg.template lpNorm<P>();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double sum(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.sum();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double prod(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.prod();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double mean(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.mean();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double maxCoeff(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.maxCoeff();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double maxCoeff(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix, std::ptrdiff_t* row, std::ptrdiff_t* col)
{
return matrix.maxCoeff(row, col);
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double minCoeff(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.minCoeff();
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double minCoeff(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix, std::ptrdiff_t* row, std::ptrdiff_t* col)
{
return matrix.minCoeff(row, col);
}
template< typename Scalar, int Rows = -1, int Cols = 1, int Options = 0, int MaxRows = Rows, int MaxCols = Cols >
double trace(const rotgen::matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &matrix)
{
return matrix.trace();
}
}

View file

@ -8,7 +8,6 @@
#pragma once
#include <rotgen/detail/generators.hpp>
#include <rotgen/detail/static_info.hpp>
#include <rotgen/impl/matrix.hpp>
#include <initializer_list>
#include <cstddef>
@ -60,5 +59,5 @@ namespace rotgen
template<> struct find_block_impl<double, RowMajor> { using type = block_impl64_row; };
template<typename Ref>
using find_block = typename find_block_impl<typename Ref::scalar_type, Ref::storage_order>::type;
using find_block = typename find_block_impl<typename Ref::value_type, Ref::storage_order>::type;
}

View file

@ -24,10 +24,15 @@ class CLASSNAME
~CLASSNAME();
void assign(SOURCENAME const&);
Index rows() const;
Index cols() const;
Index size() const;
Index innerStride() const;
Index outerStride() const;
SOURCENAME transpose() const;
SOURCENAME conjugate() const;
SOURCENAME adjoint() const;
@ -51,8 +56,8 @@ class CLASSNAME
TYPE& operator()(std::size_t i, std::size_t j);
TYPE const& operator()(std::size_t i, std::size_t j) const;
// TYPE& operator()(std::size_t index);
// TYPE const& operator()(std::size_t index) const;
TYPE& operator()(std::size_t index);
TYPE const& operator()(std::size_t index) const;
CLASSNAME& operator+=(CLASSNAME const& rhs);
CLASSNAME& operator-=(CLASSNAME const& rhs);
@ -61,18 +66,21 @@ class CLASSNAME
CLASSNAME& operator*=(TYPE d);
CLASSNAME& operator/=(TYPE d);
SOURCENAME matrix_addition(CLASSNAME const& rhs) const;
SOURCENAME matrix_subtraction(CLASSNAME const& rhs) const;
SOURCENAME matrix_multiplication(CLASSNAME const& rhs) const;
SOURCENAME matrix_multiplication(TYPE s) const;
SOURCENAME matrix_division(TYPE s) const;
SOURCENAME add(CLASSNAME const& rhs) const;
SOURCENAME sub(CLASSNAME const& rhs) const;
SOURCENAME mul(CLASSNAME const& rhs) const;
SOURCENAME mul(TYPE s) const;
SOURCENAME div(TYPE s) const;
friend std::ostream& operator<<(std::ostream&,CLASSNAME const&);
friend bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs);
friend bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs);
const TYPE* data() const;
TYPE* data();
static SOURCENAME Zero(std::size_t r, std::size_t c) { return SOURCENAME::Zero(r,c); }
static SOURCENAME Ones(std::size_t r, std::size_t c) { return SOURCENAME::Ones(r,c); }
static SOURCENAME Constant(std::size_t r, std::size_t c, TYPE v) { return SOURCENAME::Constant(r,c,v); }
static SOURCENAME Random(std::size_t r, std::size_t c) { return SOURCENAME::Random(r,c); }
static SOURCENAME Identity(std::size_t r, std::size_t c) { return SOURCENAME::Identity(r,c); }

115
include/rotgen/impl/map.hpp Normal file
View file

@ -0,0 +1,115 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/detail/generators.hpp>
#include <rotgen/impl/matrix.hpp>
#include <rotgen/common/strides.hpp>
#include <initializer_list>
#include <cstddef>
#include <memory>
namespace rotgen
{
#define USE_CONST
#define CONST const
#define SIZE 64
#define TYPE double
#define CLASSNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/map_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#define CLASSNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/map_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#undef SIZE
#undef TYPE
#define SIZE 32
#define TYPE float
#define CLASSNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/map_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#define CLASSNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/map_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#undef SIZE
#undef TYPE
#undef CONST
#undef USE_CONST
#define SIZE 64
#define TYPE double
#define CONST
#define CLASSNAME ROTGEN_MATRIX_NAME(map_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/map_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#define CLASSNAME ROTGEN_MATRIX_NAME(map_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/map_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#undef SIZE
#undef TYPE
#define SIZE 32
#define TYPE float
#define CLASSNAME ROTGEN_MATRIX_NAME(map_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/map_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#define CLASSNAME ROTGEN_MATRIX_NAME(map_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/map_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#undef SIZE
#undef TYPE
#undef CONST
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 , RowMajor, true> { 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>
using find_map = typename find_map_impl < typename std::remove_const_t<Ref>::value_type
, Ref::storage_order
, std::is_const_v<Ref>
>::type;
}
#include <rotgen/impl/map_operators.hpp>

View file

@ -0,0 +1,106 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
//==================================================================================================
/*
This file is a X-File to generate various map_impl_* declarations variant
*/
//==================================================================================================
class CLASSNAME
{
public:
CLASSNAME(TYPE CONST* ptr, Index r, Index c);
CLASSNAME(TYPE CONST* ptr, Index r, Index c, stride s);
CLASSNAME(CLASSNAME const& other);
#if !defined(USE_CONST)
CLASSNAME& operator=(CLASSNAME const& other);
#endif
CLASSNAME(CLASSNAME&&) noexcept;
CLASSNAME& operator=(CLASSNAME&&) noexcept;
~CLASSNAME();
Index rows() const;
Index cols() const;
Index size() const;
Index innerStride() const;
Index outerStride() const;
SOURCENAME transpose() const;
SOURCENAME conjugate() const;
SOURCENAME adjoint() const;
#if !defined(USE_CONST)
void transposeInPlace();
void adjointInPlace();
#endif
TYPE sum() const;
TYPE prod() const;
TYPE mean() const;
TYPE trace() const;
TYPE maxCoeff() const;
TYPE minCoeff() const;
TYPE maxCoeff(Index* row, Index* col) const;
TYPE minCoeff(Index* row, Index* col) const;
TYPE squaredNorm() const;
TYPE norm() const;
TYPE lpNorm(int p) const;
#if !defined(USE_CONST)
TYPE& operator()(Index i, Index j);
TYPE& operator()(Index i);
#endif
TYPE operator()(Index i, Index j) const;
TYPE operator()(Index i) const;
#if !defined(USE_CONST)
CLASSNAME& operator+=(CLASSNAME const& rhs);
CLASSNAME& operator-=(CLASSNAME const& rhs);
CLASSNAME& operator*=(CLASSNAME const& rhs);
CLASSNAME& operator*=(TYPE d);
CLASSNAME& operator/=(TYPE d);
#endif
SOURCENAME operator-() const;
SOURCENAME add(CLASSNAME const& rhs) const;
SOURCENAME sub(CLASSNAME const& rhs) const;
SOURCENAME mul(CLASSNAME const& rhs) const;
SOURCENAME mul(TYPE s) const;
SOURCENAME div(TYPE s) const;
friend std::ostream& operator<<(std::ostream&,CLASSNAME const&);
const TYPE* data() const;
#if !defined(USE_CONST)
void setZero();
void setOnes();
void setRandom();
void setIdentity();
void setConstant(TYPE);
#endif
friend bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs);
friend bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs);
private:
struct payload;
std::unique_ptr<payload> storage_;
public:
std::unique_ptr<payload>& storage() { return storage_; }
std::unique_ptr<payload> const& storage() const { return storage_; }
};

View file

@ -0,0 +1,39 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#define ROTGEN_DEF_RELOP_PAIR(OP, T1, T2) \
bool operator OP (T1 const&, T2 const&); \
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) \
/**/
namespace rotgen
{
ROTGEN_DEF_RELOP(==)
ROTGEN_DEF_RELOP(!=)
// ROTGEN_DEF_RELOP(+)
// ROTGEN_DEF_RELOP(-)
}
#undef ROTGEN_DEF_RELOP_PAIR
#undef ROTGEN_DEF_RELOP

View file

@ -69,10 +69,13 @@ class CLASSNAME
friend std::ostream& operator<<(std::ostream&,CLASSNAME const&);
friend bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs);
friend bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs);
const TYPE* data() const;
TYPE* data();
static CLASSNAME Zero(std::size_t rows, std::size_t cols);
static CLASSNAME Ones(std::size_t rows, std::size_t cols);
static CLASSNAME Constant(std::size_t rows, std::size_t cols, TYPE value);
static CLASSNAME Random(std::size_t rows, std::size_t cols);
static CLASSNAME Identity(std::size_t rows, std::size_t cols);

View file

@ -10,12 +10,13 @@
#include <cstddef>
#include <memory>
#include <rotgen/impl/matrix.hpp>
#include <rotgen/impl/map.hpp>
#include <Eigen/Dense>
namespace rotgen
{
//==================================================================================================
// Internal payload - Requried for cross-referencing from block_impl*
// Internal payload - Required for cross-referencing from block_impl*
//==================================================================================================
struct matrix_impl64_col::payload
{
@ -72,4 +73,112 @@ namespace rotgen
void assign(data_type const& mat) { data = mat; }
void assign(data_type&& mat) { data = std::move(mat); }
};
//==================================================================================================
// Internal payload - Required for cross-referencing from mixed order on map operators
//==================================================================================================
struct map_const_impl32_col::payload
{
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>;
using base_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>;
using data_type = Eigen::Map<base_type const,Eigen::ColMajor,stride_type>;
data_type data;
payload (data_type const& o) : data(o) {}
payload (float const* ptr, Index r, Index c) : data(ptr,r,c) {}
payload (float const* ptr, Index r, Index c, stride_type s) : data(ptr,r,c,s) {}
};
struct map_const_impl32_row::payload
{
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>;
using base_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>;
using data_type = Eigen::Map<base_type const,Eigen::RowMajor,stride_type>;
data_type data;
payload (data_type const& o) : data(o) {}
payload (float const* ptr, Index r, Index c) : data(ptr,r,c) {}
payload (float const* ptr, Index r, Index c, stride_type s) : data(ptr,r,c,s) {}
};
struct map_impl32_col::payload
{
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>;
using base_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>;
using data_type = Eigen::Map<base_type,Eigen::ColMajor,stride_type>;
data_type data;
payload (data_type const& o) : data(o) {}
payload (float* ptr, Index r, Index c) : data(ptr,r,c) {}
payload (float* ptr, Index r, Index c, stride_type s) : data(ptr,r,c,s) {}
};
struct map_impl32_row::payload
{
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>;
using base_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>;
using data_type = Eigen::Map<base_type,Eigen::RowMajor,stride_type>;
data_type data;
payload (data_type const& o) : data(o) {}
payload (float* ptr, Index r, Index c) : data(ptr,r,c) {}
payload (float* ptr, Index r, Index c, stride_type s) : data(ptr,r,c,s) {}
};
struct map_const_impl64_col::payload
{
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>;
using base_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>;
using data_type = Eigen::Map<base_type const,Eigen::ColMajor,stride_type>;
data_type data;
payload (data_type const& o) : data(o) {}
payload (double const* ptr, Index r, Index c) : data(ptr,r,c) {}
payload (double const* ptr, Index r, Index c, stride_type s) : data(ptr,r,c,s) {}
};
struct map_const_impl64_row::payload
{
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>;
using base_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>;
using data_type = Eigen::Map<base_type const,Eigen::RowMajor,stride_type>;
data_type data;
payload (data_type const& o) : data(o) {}
payload (double const* ptr, Index r, Index c) : data(ptr,r,c) {}
payload (double const* ptr, Index r, Index c, stride_type s) : data(ptr,r,c,s) {}
};
struct map_impl64_col::payload
{
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>;
using base_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>;
using data_type = Eigen::Map<base_type,Eigen::ColMajor,stride_type>;
data_type data;
payload (data_type const& o) : data(o) {}
payload (double* ptr, Index r, Index c) : data(ptr,r,c) {}
payload (double* ptr, Index r, Index c, stride_type s) : data(ptr,r,c,s) {}
};
struct map_impl64_row::payload
{
using stride_type = Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic>;
using base_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>;
using data_type = Eigen::Map<base_type,Eigen::RowMajor,stride_type>;
data_type data;
payload (data_type const& o) : data(o) {}
payload (double* ptr, Index r, Index c) : data(ptr,r,c) {}
payload (double* ptr, Index r, Index c, stride_type s) : data(ptr,r,c,s) {}
};
}

View file

@ -0,0 +1,71 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/concepts.hpp>
#include <cassert>
#include <iosfwd>
namespace rotgen
{
template<concepts::entity E>
std::ostream& operator<<(std::ostream& os, E const& arg)
{
return os << arg.base();
}
template<typename A, typename B>
constexpr bool operator==(A const& a, B const& b) noexcept
requires(concepts::entity<A> || concepts::entity<B>)
{
static_assert ( std::same_as<typename A::value_type,typename B::value_type>
, "[ROTGEN] Incompatible type in operator=="
);
if constexpr(!use_expression_templates) return generalize_t<A const>(a) == generalize_t<B const>(b);
else return base_of(a) == base_of(b);
}
template<typename A, typename B>
constexpr bool operator!=(A const& a, B const& b) noexcept
requires(concepts::entity<A> || concepts::entity<B>)
{
static_assert ( std::same_as<typename A::value_type,typename B::value_type>
, "[ROTGEN] Incompatible type in operator!="
);
if constexpr(!use_expression_templates) return generalize_t<A const>(a) != generalize_t<B const>(b);
else return base_of(a) != base_of(b);
}
template<typename A, typename 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);
else return base_of(a) + base_of(b);
}
template<typename A, typename 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);
else return base_of(a) - base_of(b);
}
template<typename A, typename 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);
else return base_of(a) * base_of(b);
}
template<typename A, typename 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;
else return base_of(a) / b;
}
}

View file

@ -9,14 +9,21 @@
#include <rotgen/config.hpp>
#include <rotgen/concepts.hpp>
#include <rotgen/common/traits.hpp>
#include <rotgen/common/strides.hpp>
#if defined(ROTGEN_FORCE_DYNAMIC)
#include <rotgen/dynamic/matrix.hpp>
#include <rotgen/dynamic/block.hpp>
#include <rotgen/dynamic/map.hpp>
#else
#include <rotgen/fixed/matrix.hpp>
#include <rotgen/fixed/block.hpp>
#include <rotgen/fixed/map.hpp>
#endif
#include <rotgen/common/ref.hpp>
#include <rotgen/extract.hpp>
#include <rotgen/functions.hpp>
#include <rotgen/operators.hpp>
#include <rotgen/alias.hpp>

View file

@ -50,21 +50,27 @@ struct CLASSNAME::payload
CLASSNAME::~CLASSNAME() = default;
void CLASSNAME::assign(SOURCENAME const& m)
{
storage_->data = m.storage()->data;
}
//==================================================================================================
// 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(); }
TYPE& CLASSNAME::operator()(std::size_t i, std::size_t j) { return storage_->data(i,j); }
TYPE const& CLASSNAME::operator()(std::size_t i, std::size_t j) const { return storage_->data(i,j); }
/*
TYPE& CLASSNAME::operator()(std::size_t index) { return storage_->data(index); }
TYPE const& CLASSNAME::operator()(std::size_t index) const { return storage_->data(index); }
*/
TYPE& CLASSNAME::operator()(std::size_t index) { return storage_->data.data()[index]; }
TYPE const& CLASSNAME::operator()(std::size_t index) const { return storage_->data.data()[index]; }
TYPE* CLASSNAME::data() { return storage_->data.data(); }
const TYPE* CLASSNAME::data() const { return storage_->data.data(); }
SOURCENAME CLASSNAME::transpose() const
@ -130,6 +136,11 @@ struct CLASSNAME::payload
return lhs.storage_->data == rhs.storage_->data;
}
bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs)
{
return lhs.storage_->data != rhs.storage_->data;
}
CLASSNAME& CLASSNAME::operator+=(CLASSNAME const& rhs)
{
storage_->data += rhs.storage_->data;
@ -167,35 +178,35 @@ struct CLASSNAME::payload
return *this;
}
SOURCENAME CLASSNAME::matrix_addition(CLASSNAME const& rhs) const
SOURCENAME CLASSNAME::add(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data + rhs.storage_->data);
return result;
}
SOURCENAME CLASSNAME::matrix_subtraction(CLASSNAME const& rhs) const
SOURCENAME CLASSNAME::sub(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data - rhs.storage_->data);
return result;
}
SOURCENAME CLASSNAME::matrix_multiplication(CLASSNAME const& rhs) const
SOURCENAME CLASSNAME::mul(CLASSNAME const& rhs) const
{
SOURCENAME result;
result.storage()->assign(storage_->data * rhs.storage_->data);
return result;
}
SOURCENAME CLASSNAME::matrix_multiplication(TYPE s) const
SOURCENAME CLASSNAME::mul(TYPE s) const
{
SOURCENAME result;
result.storage()->assign(storage_->data * s);
return result;
}
SOURCENAME CLASSNAME::matrix_division(TYPE s) const
SOURCENAME CLASSNAME::div(TYPE s) const
{
SOURCENAME result;
result.storage()->assign(storage_->data / s);

View file

@ -7,24 +7,12 @@
*/
//==================================================================================================
#include <rotgen/config.hpp>
#include <iostream>
namespace rotgen
namespace rotgen::detail
{
std::ostream& setup_summary(std::ostream& os)
std::ostream& dynamic_info(std::ostream& os)
{
if constexpr(rotgen::is_forcing_dynamic_status)
{
os << "[ROTGEN] - Fully Dynamic mode" << std::endl;
}
else
{
if constexpr(use_expression_templates)
os << "[ROTGEN] - Expression templates : Disabled." << std::endl;
else
os << "[ROTGEN] - Static/Dynamic mode with maximum size: " << rotgen::max_static_size << std::endl;
}
return os;
if constexpr(rotgen::is_forcing_dynamic_status) return os << "[ROTGEN] - Fully Dynamic mode" << std::endl;
else return os << "[ROTGEN] - Flexible mode with" << std::endl;
}
}

110
src/map.cpp Normal file
View file

@ -0,0 +1,110 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/detail/generators.hpp>
#include <rotgen/impl/map.hpp>
#include <rotgen/impl/payload.hpp>
#include <Eigen/Dense>
namespace rotgen
{
#define USE_CONST
#define CONST const
#define SIZE 64
#define TYPE double
#define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "map_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "map_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#undef SIZE
#undef TYPE
#define SIZE 32
#define TYPE float
#define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "map_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(map_const_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "map_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#undef SIZE
#undef TYPE
#undef USE_CONST
#undef CONST
#define CONST
#define SIZE 64
#define TYPE double
#define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(map_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "map_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(map_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "map_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#undef SIZE
#undef TYPE
#define SIZE 32
#define TYPE float
#define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(map_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "map_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(map_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "map_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#undef SIZE
#undef TYPE
#undef CONST
}

236
src/map_model.cpp Normal file
View file

@ -0,0 +1,236 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
//==================================================================================================
/*
This file is a X-File to generate various map_impl_* definitions variant
*/
//==================================================================================================
//==================================================================================================
// Internal payload
//==================================================================================================
//==================================================================================================
// 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, stride s)
: 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))
{}
#if !defined(USE_CONST)
CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
{
if (this != &o) storage_->data = o.storage_->data;
return *this;
}
#endif
CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default;
CLASSNAME& CLASSNAME::operator=(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(); }
#if !defined(USE_CONST)
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]; }
const TYPE* CLASSNAME::data() const { return storage_->data.data(); }
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;
}
#if !defined(USE_CONST)
void CLASSNAME::transposeInPlace()
{
storage_->data.transposeInPlace();
}
void CLASSNAME::adjointInPlace()
{
storage_->data.adjointInPlace();
}
#endif
TYPE CLASSNAME::sum() const { return storage_->data.sum(); }
TYPE CLASSNAME::prod() const { return storage_->data.prod(); }
TYPE CLASSNAME::mean() const { return storage_->data.mean(); }
TYPE CLASSNAME::trace() const { return storage_->data.trace(); }
TYPE CLASSNAME::minCoeff() const { return storage_->data.minCoeff(); }
TYPE CLASSNAME::maxCoeff() const { return storage_->data.maxCoeff(); }
TYPE CLASSNAME::minCoeff(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
//==================================================================================================
// Operators
//==================================================================================================
std::ostream& operator<<(std::ostream& os,CLASSNAME const& m)
{
return os << m.storage_->data;
}
bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs)
{
return lhs.storage_->data == rhs.storage_->data;
}
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-=(CLASSNAME 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*=(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::sub(CLASSNAME 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(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

@ -72,6 +72,7 @@ TYPE& CLASSNAME::operator()(std::size_t index) { return storage_->da
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::transpose() const
{
@ -139,6 +140,11 @@ bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs)
return lhs.storage_->data == rhs.storage_->data;
}
bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs)
{
return lhs.storage_->data != rhs.storage_->data;
}
CLASSNAME& CLASSNAME::operator+=(CLASSNAME const& rhs)
{
storage_->data += rhs.storage_->data;
@ -180,6 +186,13 @@ CLASSNAME& CLASSNAME::operator/=(TYPE s)
// Static functions
//==================================================================================================
CLASSNAME CLASSNAME::Ones(std::size_t rows, std::size_t cols)
{
CLASSNAME m;
m.storage_ = std::make_unique<payload>(payload::data_type::Ones(rows, cols));
return m;
}
CLASSNAME CLASSNAME::Zero(std::size_t rows, std::size_t cols)
{
CLASSNAME m;

40
src/operators.cpp Normal file
View file

@ -0,0 +1,40 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/impl/map.hpp>
#include <rotgen/impl/payload.hpp>
#include <Eigen/Dense>
#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_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); } \
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
{
auto add(auto const& a, auto const& b) { return a.storage()->data + b.storage()->data; }
auto sub(auto const& a, auto const& b) { return a.storage()->data - b.storage()->data; }
bool equal(auto const& a, auto const& b) { 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(!=, not_equal, bool);
}

View file

@ -17,6 +17,7 @@ target_link_libraries(rotgen_test INTERFACE rotgen Eigen3::Eigen)
##======================================================================================================================
## Unit Tests registration
##======================================================================================================================
rotgen_glob_unit(PATTERN "unit/free_functions/*.cpp" INTERFACE rotgen_test)
rotgen_glob_unit(PATTERN "unit/*.cpp" INTERFACE rotgen_test)
rotgen_glob_unit(PATTERN "unit/matrix/*.cpp" INTERFACE rotgen_test)
rotgen_glob_unit(PATTERN "unit/block/*.cpp" INTERFACE rotgen_test)
rotgen_glob_unit(PATTERN "unit/map/*.cpp" INTERFACE rotgen_test)

View file

@ -6,128 +6,69 @@
*/
//==================================================================================================
#include "unit/tests.hpp"
#include "unit/common/arithmetic.hpp"
#include <rotgen/rotgen.hpp>
#include <Eigen/Dense>
template<typename Type1, typename Type2>
void test_comparison(const Type1& t1, const Type2& t2)
{
TTS_EQUAL(static_cast<std::ptrdiff_t>(t1.rows()), static_cast<std::ptrdiff_t>(t2.rows()));
TTS_EQUAL(static_cast<std::ptrdiff_t>(t1.cols()), static_cast<std::ptrdiff_t>(t2.cols()));
for (rotgen::Index r = 0; r < static_cast<rotgen::Index>(t1.rows()); ++r)
for (rotgen::Index c = 0; c < static_cast<rotgen::Index>(t1.cols()); ++c)
TTS_EQUAL(t1(r, c), t2(r, c));
}
template<typename Matrix1, typename Matrix2, typename Block1, typename Block2>
void test_block_unary_ops(const Matrix1& original_matrix, const Matrix2& ref_matrix,
Block1 original_block, Block2 ref_block)
{
TTS_EXPECT(verify_rotgen_reentrance(original_block.transpose()));
TTS_EXPECT(verify_rotgen_reentrance(original_block.conjugate()));
TTS_EXPECT(verify_rotgen_reentrance(original_block.adjoint()));
test_comparison(original_block.transpose(), ref_block.transpose());
test_comparison(original_block.conjugate(), ref_block.conjugate());
test_comparison(original_block.adjoint(), ref_block.adjoint());
if (original_block.rows() == original_block.cols()) {
original_block.transposeInPlace();
ref_block.transposeInPlace();
test_comparison(original_block, ref_block);
test_comparison(original_matrix, ref_matrix);
original_block.adjointInPlace();
ref_block.adjointInPlace();
test_comparison(original_block, ref_block);
test_comparison(original_matrix, ref_matrix);
}
}
template<typename Block1, typename Block2>
void compare_reductions(const Block1& block, const Block2& ref)
{
constexpr double epsilon = 0.0001;
TTS_RELATIVE_EQUAL(block.sum(), ref.sum(), epsilon);
TTS_RELATIVE_EQUAL(block.prod(), ref.prod(), epsilon);
TTS_RELATIVE_EQUAL(block.mean(), ref.mean(), epsilon);
TTS_EQUAL(block.trace(), ref.trace());
TTS_EQUAL(block.minCoeff(), ref.minCoeff());
TTS_EQUAL(block.maxCoeff(), ref.maxCoeff());
std::ptrdiff_t row, col, ref_row, ref_col;
TTS_EQUAL(block.minCoeff(&row, &col), ref.minCoeff(&ref_row, &ref_col));
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
TTS_EQUAL(block.maxCoeff(&row, &col), ref.maxCoeff(&ref_row, &ref_col));
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
}
template <typename MatrixType, typename T>
void test_dynamic_block_reductions(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct)
{
using EigenMatrix = Eigen::Matrix<typename MatrixType::scalar_type, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType original(matrix_construct.rows, matrix_construct.cols);
EigenMatrix ref(matrix_construct.rows, matrix_construct.cols);
for (rotgen::Index r = 0; r < matrix_construct.rows; ++r)
for (rotgen::Index c = 0; c < matrix_construct.cols; ++c)
ref(r, c) = original(r,c) = static_cast<T>(matrix_construct.init_fn(r, c));
std::vector<std::pair<rotgen::block<MatrixType>, Eigen::Block<EigenMatrix>>> test_cases {
{ rotgen::extract(original, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj),
ref.block(matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj) },
{ rotgen::topLeftCorner(original, matrix_construct.ni, matrix_construct.nj),
ref.topLeftCorner(matrix_construct.ni, matrix_construct.nj) },
{ rotgen::topRightCorner(original, matrix_construct.ni, matrix_construct.nj),
ref.topRightCorner(matrix_construct.ni, matrix_construct.nj) },
{ rotgen::bottomLeftCorner(original, matrix_construct.ni, matrix_construct.nj),
ref.bottomLeftCorner(matrix_construct.ni, matrix_construct.nj) },
{ rotgen::bottomRightCorner(original, matrix_construct.ni, matrix_construct.nj),
ref.bottomRightCorner(matrix_construct.ni, matrix_construct.nj) },
{ rotgen::topRows(original, matrix_construct.ni),
ref.topRows(matrix_construct.ni) },
{ rotgen::middleRows(original, matrix_construct.i0, matrix_construct.ni),
ref.middleRows(matrix_construct.i0, matrix_construct.ni) },
{ rotgen::bottomRows(original, matrix_construct.ni),
ref.bottomRows(matrix_construct.ni) },
};
for (const auto& [original_block, ref_block] : test_cases) {
compare_reductions(original_block, ref_block);
test_block_unary_ops(original, ref, original_block, ref_block);
}
}
TTS_CASE_TPL("Test dynamic block reductions", rotgen::tests::types)
TTS_CASE_TPL("Test dynamic block transposition-like operations", 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>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> test_cases =
auto const cases = rotgen::tests::generate_block_references<T,O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases)
{
{6, 5, [](rotgen::Index r, rotgen::Index c) { return T(r + c); }, 1, 2, 3, 2},
{9, 11, [](rotgen::Index r, rotgen::Index c) {return T(r + c); }, 0, 1, 4, 9},
{3, 3, [](rotgen::Index , rotgen::Index ) {return T(0.0); }, 1, 1, 1, 1},
{1, 4, [](rotgen::Index r, rotgen::Index c) {return T(-r -c*c - 1234); }, 0, 0, 1, 1},
{9, 9, [](rotgen::Index r, rotgen::Index c) {return T(-r + 2*c); }, 0, 1, 3, 3},
{11, 13, [](rotgen::Index r, rotgen::Index c) {return T(std::tan(r+c)); }, 1, 1, 2, 2},
{4, 1, [](rotgen::Index , rotgen::Index ) {return T(7.0); }, 2, 0, 2, 1},
{1, 1, [](rotgen::Index , rotgen::Index ) {return T(42.0); }, 0, 0, 1, 1},
{12, 13, [](rotgen::Index r, rotgen::Index c) {return T(std::sin(r + c)); }, 2, 3, 4, 5 },
{4, 9, [](rotgen::Index r, rotgen::Index c) {return T(-1.5 * r + 2.56 * c); }, 0, 1, 2, 3 },
{2, 5, [](rotgen::Index r, rotgen::Index c) {return T(r == c ? 1.0 : 0.0); }, 1, 1, 1, 1},
auto[rows,cols,fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract(m, i0, j0, ni, nj);
rotgen::tests::check_shape_functions(input);
}
};
TTS_CASE_TPL("Test static block transposition-like operations", 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 process = []<typename D>(D const& d)
{
auto[desc,i0,j0] = d;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
rotgen::tests::check_shape_functions(input);
};
for (const auto& test_case : test_cases)
test_dynamic_block_reductions<mat_t, T>(test_case);
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};
TTS_CASE_TPL("Test dynamic block reduction-like operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
auto const cases = rotgen::tests::generate_block_references<T,O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases)
{
auto[rows,cols,fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract(m, i0, j0, ni, nj);
rotgen::tests::check_reduction_functions(input);
}
};
TTS_CASE_TPL("Test static block reduction-like operations", 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 process = []<typename D>(D const& d)
{
auto[desc,i0,j0] = d;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
rotgen::tests::check_reduction_functions(input);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};

View file

@ -0,0 +1,104 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Function size", 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};
// Helper: fill matrix from raw data
auto fill = [&](auto& m, int r, int c) {
for(int k = 0; k < r * c; ++k) m.data()[k] = data[k];
};
// 1x12 dynamic block at (0,0)
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> dm(1,12);
fill(dm,1,12);
auto b1 = rotgen::block<decltype(dm), rotgen::Dynamic, rotgen::Dynamic, false, O::value>(dm, 0,0,1,12);
TTS_EQUAL(b1.rows(), rotgen::Index{1});
TTS_EQUAL(b1.cols(), rotgen::Index{12});
// 1x5 dynamic block at (0,2)
auto b2 = rotgen::block<decltype(dm), rotgen::Dynamic, rotgen::Dynamic, false, O::value>(dm, 0,2,1,5);
TTS_EQUAL(b2.rows(), rotgen::Index{1});
TTS_EQUAL(b2.cols(), rotgen::Index{5});
// 3x2 dynamic block at (1,4) in 4x6
rotgen::matrix<T, rotgen::Dynamic, rotgen::Dynamic, O::value> dm2(4,6);
fill(dm2,4,6);
auto b3 = rotgen::block<decltype(dm2), rotgen::Dynamic, rotgen::Dynamic, false, O::value>(dm2, 1,4,3,2);
TTS_EQUAL(b3.rows(), rotgen::Index{3});
TTS_EQUAL(b3.cols(), rotgen::Index{2});
TTS_EQUAL(b3.size(), rotgen::Index{6});
// 3x4 static block
rotgen::matrix<T,3,4,O::value> sm;
fill(sm,3,4);
auto b4 = rotgen::block<decltype(sm), 3, 4, false, O::value>(sm, 0,0);
TTS_EQUAL(b4.rows(), rotgen::Index{3});
TTS_EQUAL(b4.cols(), rotgen::Index{4});
TTS_EQUAL(b4.size(), rotgen::Index{12});
// 6x2 static block
rotgen::matrix<T,6,2,O::value> sm2;
fill(sm2,6,2);
auto b5 = rotgen::block<decltype(sm2), 6, 2, false, O::value>(sm2, 0,0);
TTS_EQUAL(b5.rows(), rotgen::Index{6});
TTS_EQUAL(b5.cols(), rotgen::Index{2});
TTS_EQUAL(b5.size(), rotgen::Index{12});
};
TTS_CASE_TPL("Test coefficient accessors", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
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};
base mat(4,3);
for(int k=0;k<12;++k) mat.data()[k] = data[k];
auto b = rotgen::block<base,rotgen::Dynamic,rotgen::Dynamic,false,O::value>(mat, 0, 0, 4, 3);
for(rotgen::Index i=0;i<4;i++)
{
for(rotgen::Index j=0;j<3;j++)
{
if constexpr(O::value) TTS_EQUAL(b(i,j), data[j+3*i]);
else TTS_EQUAL(b(i,j), data[i+4*j]);
}
}
b(1, 1) = 42;
TTS_EQUAL(b(1,1), 42);
T& ref = b(2, 2);
ref = 17;
TTS_EQUAL(b(2, 2), 17);
};
TTS_CASE_TPL("Test one index coefficient accessors", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
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};
base mat(4,3);
for(int k=0;k<12;++k) mat.data()[k] = data[k];
auto b = rotgen::block<base,rotgen::Dynamic,rotgen::Dynamic,false,O::value>(mat, 0, 0, 4, 3);
for(rotgen::Index i=0;i<b.size();i++)
TTS_EQUAL(b(i), data[i]) << "Index: " << i << "\n";
b(1) = 42;
TTS_EQUAL(mat.data()[1], 42);
T& ref = b(2);
ref = 17;
TTS_EQUAL(mat.data()[2], 17);
};

View file

@ -27,11 +27,14 @@ void for_each_element(EigenType& m, F&& f)
template<typename MatrixType, typename T>
MatrixType make_initialized_matrix(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct)
{
MatrixType matrix(matrix_construct.rows, matrix_construct.cols);
auto[d,i0,j0,ni,nj] = matrix_construct;
auto[r,c,fn] = d;
for(rotgen::Index i = 0; i < matrix_construct.rows; ++i)
for(rotgen::Index j = 0; j < matrix_construct.cols; ++j)
matrix(i, j) = static_cast<T>(matrix_construct.init_fn(i, j));
MatrixType matrix(r, c);
for(rotgen::Index i = 0; i < r; ++i)
for(rotgen::Index j = 0; j < c; ++j)
matrix(i, j) = static_cast<T>(fn(i, j));
return matrix;
}
@ -127,31 +130,34 @@ void test_dynamic_block_extraction(rotgen::tests::matrix_block_test_case<MatrixT
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)
{
MatrixType matrix(matrix_construct.rows, matrix_construct.cols);
auto[d,i0,j0] = matrix_construct;
auto[r,c,fn] = d;
for (rotgen::Index i = 0; i < matrix_construct.rows; ++i)
for (rotgen::Index j = 0; j < matrix_construct.cols; ++j)
matrix(i, j) = static_cast<T>(matrix_construct.init_fn(i, j));
MatrixType matrix(r,c);
auto block_main = rotgen::extract<NI, NJ>(matrix, matrix_construct.i0, matrix_construct.j0);
for (rotgen::Index i = 0; i < r; ++i)
for (rotgen::Index j = 0; j < c; ++j)
matrix(i, j) = static_cast<T>(fn(i, j));
auto block_main = rotgen::extract<NI, NJ>(matrix, i0, j0);
auto block_top_left_corner = rotgen::topLeftCorner<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_right_corner = rotgen::bottomRightCorner<NI, NJ>(matrix);
auto block_top_rows = rotgen::topRows<NI>(matrix);
auto block_middle_rows = rotgen::middleRows<NI>(matrix, matrix_construct.i0);
auto block_middle_rows = rotgen::middleRows<NI>(matrix, i0);
auto block_bottom_rows = rotgen::bottomRows<NI>(matrix);
auto block_left_cols = rotgen::leftCols<NJ>(matrix);
auto block_middle_cols = rotgen::middleCols<NJ>(matrix, matrix_construct.j0);
auto block_middle_cols = rotgen::middleCols<NJ>(matrix, j0);
auto block_right_cols = rotgen::rightCols<NJ>(matrix);
auto block_row = rotgen::row(matrix, matrix_construct.i0);
auto block_col = rotgen::col(matrix, matrix_construct.j0);
auto block_row = rotgen::row(matrix, i0);
auto block_col = rotgen::col(matrix, j0);
auto blocks = std::make_tuple(
std::make_tuple(block_main, matrix_construct.i0, matrix_construct.j0,
std::make_tuple(block_main, i0, j0,
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1),
std::make_tuple(block_top_left_corner, 0, 0,
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1),
@ -164,20 +170,20 @@ void test_static_block_extraction(rotgen::tests::static_matrix_block_test_case<M
matrix_construct.nj, int(NI), int(NJ), -1),
std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic, -1),
std::make_tuple(block_middle_rows, matrix_construct.i0, 0, matrix_construct.ni,
std::make_tuple(block_middle_rows, i0, 0, matrix_construct.ni,
matrix.cols(), int(NI), rotgen::Dynamic, -1),
std::make_tuple(block_bottom_rows, matrix.rows() - matrix_construct.ni,
0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic, -1),
std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ), -1),
std::make_tuple(block_middle_cols, 0, matrix_construct.j0,
std::make_tuple(block_middle_cols, 0, j0,
matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ), -1),
std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj,
matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ), -1),
std::make_tuple(block_row, matrix_construct.i0, 0,
std::make_tuple(block_row, i0, 0,
1, matrix.cols(), 1, rotgen::Dynamic, 1),
std::make_tuple(block_col, 0, matrix_construct.j0,
std::make_tuple(block_col, 0, j0,
matrix.rows(), 1, rotgen::Dynamic, 1, 0)
);
@ -205,16 +211,15 @@ TTS_CASE_TPL("Check all dynamic block extractions on a dynamic row-major matrix"
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value, 1>;
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 },
{ 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 }
{ {6, 11, [](rotgen::Index i, rotgen::Index j) { return T(i * 10 + j); }}, 1, 2, 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) {
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)
@ -223,9 +228,9 @@ TTS_CASE_TPL("Check all dynamic block extractions on a static column-major matri
using mat_t = rotgen::matrix<T,4,5,O::value, 0>;
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(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 }
{ {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(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) {
@ -241,24 +246,21 @@ TTS_CASE_TPL("Check all static block extractions", rotgen::tests::types)
test_static_block_extraction<mat_t, 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, [](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>(
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,[](rotgen::Index i, rotgen::Index j) { return T(std::cos(i * j * 2)); }},
5, 1
}
);
test_static_block_extraction<mat_t, double, 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
}
);

View file

@ -0,0 +1,268 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
void test_value ( const auto& matrix, auto value
, rotgen::Index i0, rotgen::Index j0
, rotgen::Index rows, rotgen::Index cols
)
{
for(rotgen::Index r=0;r<rows;++r)
for(rotgen::Index c=0;c<cols;++c)
TTS_EQUAL(matrix(i0+r, j0+c), value);
}
void test_identity( const auto& matrix
, rotgen::Index i0, rotgen::Index j0
, rotgen::Index rows, rotgen::Index cols
)
{
for(rotgen::Index r=0;r<rows;++r)
for(rotgen::Index c=0;c<cols;++c)
TTS_EQUAL(matrix(i0+r, j0+c), r==c ? 1 : 0);
}
void test_random( const auto& matrix
, rotgen::Index i0, rotgen::Index j0
, rotgen::Index rows, rotgen::Index cols
)
{
for(rotgen::Index r=0;r<rows;++r)
for(rotgen::Index c=0;c<cols;++c)
{
TTS_GREATER_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)
<typename T, typename O>( tts::type< tts::types<T,O>>)
{
auto const cases = rotgen::tests::generate_block_references<T,O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases)
{
auto[rows,cols,fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract(m, i0, j0, ni, nj);
input.setZero();
test_value(m,T{0},i0,j0,ni,nj);
using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj));
auto values = input_type::Zero(ni,nj);
test_value(values,T{0},0,0,ni,nj);
}
};
TTS_CASE_TPL("Test static block:setZero", 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 process = []<typename D>(D const& d)
{
auto[desc,i0,j0] = d;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
input.setZero();
test_value(m,T{0},i0,j0,D::ni,D::nj);
using input_type = decltype(rotgen::extract<D::ni,D::nj>(m, i0, j0));
auto values = input_type::Zero();
test_value(values,T{0},0,0,D::ni,D::nj);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};
TTS_CASE_TPL("Test dynamic block::setOnes", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>>)
{
auto const cases = rotgen::tests::generate_block_references<T,O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases)
{
auto[rows,cols,fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract(m, i0, j0, ni, nj);
input.setOnes();
test_value(m,T{1},i0,j0,ni,nj);
using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj));
auto values = input_type::Ones(ni,nj);
test_value(values,T{1},0,0,ni,nj);
}
};
TTS_CASE_TPL("Test static block:setOnes", 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 process = []<typename D>(D const& d)
{
auto[desc,i0,j0] = d;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
input.setOnes();
test_value(m,T{1},i0,j0,D::ni,D::nj);
using input_type = decltype(rotgen::extract<D::ni,D::nj>(m, i0, j0));
auto values = input_type::Ones();
test_value(values,T{1},0,0,D::ni,D::nj);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};
TTS_CASE_TPL("Test dynamic block::setConstant", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>>)
{
auto const cases = rotgen::tests::generate_block_references<T,O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases)
{
auto[rows,cols,fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract(m, i0, j0, ni, nj);
input.setConstant(T{13.37f});
test_value(m,T{13.37f},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});
test_value(values,T{13.37f},0,0,ni,nj);
}
};
TTS_CASE_TPL("Test static block:setConstant", 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 process = []<typename D>(D const& d)
{
auto[desc,i0,j0] = d;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
input.setConstant(T{13.37f});
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));
auto values = input_type::Constant(T{13.37f});
test_value(values,T{13.37f},0,0,D::ni,D::nj);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};
TTS_CASE_TPL("Test dynamic block::setIdentity", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>>)
{
auto const cases = rotgen::tests::generate_block_references<T,O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases)
{
auto[rows,cols,fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract(m, i0, j0, ni, nj);
input.setIdentity();
test_identity(m,i0,j0,ni,nj);
using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj));
auto values = input_type::Identity(ni,nj);
test_identity(values,0,0,ni,nj);
}
};
TTS_CASE_TPL("Test static block:setIdentity", 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 process = []<typename D>(D const& d)
{
auto[desc,i0,j0] = d;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
input.setIdentity();
test_identity(m,i0,j0,D::ni,D::nj);
using input_type = decltype(rotgen::extract<D::ni,D::nj>(m, i0, j0));
auto values = input_type::Identity();
test_identity(values,0,0,D::ni,D::nj);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};
TTS_CASE_TPL("Test dynamic block::setRandom", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>>)
{
auto const cases = rotgen::tests::generate_block_references<T,O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases)
{
auto[rows,cols,fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract(m, i0, j0, ni, nj);
input.setRandom();
test_random(m,i0,j0,ni,nj);
using input_type = decltype(rotgen::extract(m, i0, j0, ni, nj));
auto values = input_type::Random(ni,nj);
test_random(values,0,0,ni,nj);
}
};
TTS_CASE_TPL("Test static block:setRandom", 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 process = []<typename D>(D const& d)
{
auto[desc,i0,j0] = d;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
input.setRandom();
test_random(m,i0,j0,D::ni,D::nj);
using input_type = decltype(rotgen::extract<D::ni,D::nj>(m, i0, j0));
auto values = input_type::Random();
test_random(values,0,0,D::ni,D::nj);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};

View file

@ -6,43 +6,37 @@
*/
//==================================================================================================
#include "unit/tests.hpp"
#include "unit/common/norms.hpp"
#include <rotgen/rotgen.hpp>
#include <Eigen/Dense>
TTS_CASE_TPL("Matrix norm-related operations", rotgen::tests::types)
TTS_CASE_TPL("Test dynamic block norm operations", 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>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> test_cases =
auto const cases = rotgen::tests::generate_block_references<T,O>();
for (const auto& [matrix_desc, i0, j0, ni, nj] : cases)
{
{6, 5, [](rotgen::Index r, rotgen::Index c) {return r + c; }, 1, 2, 3, 2},
{9, 11, [](rotgen::Index r, rotgen::Index c) {return r + c; }, 0, 1, 4, 9},
{3, 3, [](rotgen::Index , rotgen::Index ) {return 0.0; }, 1, 1, 1, 1},
{1, 4, [](rotgen::Index r, rotgen::Index c) {return -r -c*c - 1234; }, 0, 0, 1, 1},
{4, 1, [](rotgen::Index , rotgen::Index ) {return 7.0; }, 2, 0, 2, 1},
{1, 1, [](rotgen::Index , rotgen::Index ) {return 42.0; }, 0, 0, 1, 1},
{12, 13, [](rotgen::Index r, rotgen::Index c) {return std::sin(r + c); }, 2, 3, 4, 5 },
{4, 9, [](rotgen::Index r, rotgen::Index c) {return -1.5 * r + 2.56 * c; }, 0, 1, 2, 3 },
{2, 5, [](rotgen::Index r, rotgen::Index c) {return (r == c ? 1.0 : 0.0); }, 1, 1, 1, 1},
};
for (const auto& [rows, cols, fn, i0, j0, ni, nj] : test_cases)
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> original_matrix(rows, cols);
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic,O::value> ref_matrix(rows, cols);
for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c)
ref_matrix(r, c) = original_matrix(r, c) = fn(r,c);
auto original_block = rotgen::extract(original_matrix, i0, j0, ni, nj);
auto ref_block = ref_matrix.block(i0, j0, ni, nj);
TTS_EQUAL(original_block.norm(), ref_block.norm());
TTS_EQUAL(original_block.squaredNorm(), ref_block.squaredNorm());
TTS_EQUAL(original_block.template lpNorm<1>() , ref_block.template lpNorm<1>());
TTS_EQUAL(original_block.template lpNorm<2>() , ref_block.template lpNorm<2>());
TTS_EQUAL(original_block.template lpNorm<rotgen::Infinity>(), ref_block.template lpNorm<Eigen::Infinity>());
auto[rows,cols,fn] = matrix_desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract(m, i0, j0, ni, nj);
rotgen::tests::check_norms_functions(input);
}
};
TTS_CASE_TPL("Test static block norm operations", 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 process = []<typename D>(D const& d)
{
auto[desc,i0,j0] = d;
auto[rows,cols,fn] = desc;
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> m(rows, cols);
rotgen::tests::prepare(rows,cols,fn,m);
auto input = rotgen::extract<D::ni,D::nj>(m, i0, j0);
rotgen::tests::check_norms_functions(input);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};

View file

@ -15,51 +15,50 @@ void test_block_matrix_operations(rotgen::tests::matrix_block_test_case<MatrixTy
{
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType a(matrix_construct.rows, matrix_construct.cols);
MatrixType b(matrix_construct.rows, matrix_construct.cols);
EigenMatrix ref_a(matrix_construct.rows, matrix_construct.cols);
EigenMatrix ref_b(matrix_construct.rows, matrix_construct.cols);
auto[d,i0,j0,ni,nj] = matrix_construct;
auto[r,c,fn] = d;
MatrixType a(r, c);
MatrixType b(r, c);
EigenMatrix ref_a(r, c);
EigenMatrix ref_b(r, c);
TTS_EXPECT(verify_rotgen_reentrance(ops(a,b)));
for (rotgen::Index r = 0; r < matrix_construct.rows; ++r)
for (rotgen::Index rr = 0; rr < r; ++rr)
{
for (rotgen::Index c = 0; c < matrix_construct.cols; ++c)
for (rotgen::Index cc = 0; cc < c; ++cc)
{
ref_a(r,c) = a(r,c) = static_cast<T>(matrix_construct.init_fn(r, c));
ref_b(r,c) = b(r,c) = static_cast<T>(b_init_fn(r, c));
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));
}
}
auto a_block = rotgen::extract(a, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto b_block = rotgen::extract(b, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto ref_a_block = ref_a.block(matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto ref_b_block = ref_b.block(matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto a_block = rotgen::extract(a, 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_b_block = ref_b.block(i0, j0,ni, nj);
auto result_block = ops(a_block, b_block);
auto ref_result_block = ops(ref_a_block, ref_b_block);
for (rotgen::Index r = 0; r < matrix_construct.ni; ++r)
for (rotgen::Index c = 0; c < matrix_construct.nj; ++c)
TTS_EQUAL(result_block(r, c), ref_result_block(r, c));
for (rotgen::Index rr = 0; rr < ni; ++rr)
for (rotgen::Index cc = 0; cc < nj; ++cc)
TTS_EQUAL(result_block(rr, cc), ref_result_block(rr, cc));
self_ops(a_block,b_block);
self_ops(ref_a_block, ref_b_block);
for (rotgen::Index r = 0; r < matrix_construct.ni; ++r)
for (rotgen::Index c = 0; c < matrix_construct.nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (rotgen::Index rr = 0; rr < ni; ++rr)
for (rotgen::Index cc = 0; cc < nj; ++cc)
TTS_EQUAL(a_block(rr, cc), ref_a_block(rr, cc));
for (rotgen::Index r = 0; r < matrix_construct.rows; ++r)
for (rotgen::Index rr = 0; rr < ni; ++rr)
{
for (rotgen::Index c = 0; c < matrix_construct.cols; ++c)
for (rotgen::Index cc = 0; cc < nj; ++cc)
{
TTS_EQUAL(a(r, c), ref_a(r, c));
TTS_EQUAL(b(r, c), ref_b(r, c));
TTS_EQUAL(a(rr, cc), ref_a(rr, cc));
TTS_EQUAL(b(rr, cc), ref_b(rr, cc));
}
}
}
@ -70,36 +69,37 @@ void test_block_scalar_operations(rotgen::tests::matrix_block_test_case<MatrixTy
{
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType a(matrix_construct.rows, matrix_construct.cols);
EigenMatrix ref_a(matrix_construct.rows, matrix_construct.cols);
auto[d,i0,j0,ni,nj] = matrix_construct;
auto[rows,cols,fn] = d;
MatrixType a(rows, cols);
EigenMatrix ref_a(rows, cols);
TTS_EXPECT(verify_rotgen_reentrance(ops(a,scalar)));
for (rotgen::Index r = 0; r < matrix_construct.rows; ++r)
for (rotgen::Index c = 0; c < matrix_construct.cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(matrix_construct.init_fn(r, c));
for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(fn(r, c));
auto a_block = rotgen::extract(a, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto ref_a_block = ref_a.block(matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto a_block = rotgen::extract(a, i0, j0,ni, nj);
auto ref_a_block = ref_a.block(i0, j0,ni, nj);
auto result = ops(a_block, scalar);
auto ref_result = ops(ref_a_block, scalar);
for (rotgen::Index r = 0; r < matrix_construct.ni; ++r)
for (rotgen::Index c = 0; c < matrix_construct.nj; ++c)
for (rotgen::Index r = 0; r < ni; ++r)
for (rotgen::Index c = 0; c < nj; ++c)
TTS_EQUAL(result(r, c), ref_result(r, c));
self_ops(a_block,scalar);
self_ops(ref_a_block, scalar);
for (rotgen::Index r = 0; r < matrix_construct.ni; ++r)
for (rotgen::Index c = 0; c < matrix_construct.nj; ++c)
for (rotgen::Index r = 0; r < ni; ++r)
for (rotgen::Index c = 0; c < nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (rotgen::Index r = 0; r < matrix_construct.rows; ++r)
for (rotgen::Index c = 0; c < matrix_construct.cols; ++c)
for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c)
TTS_EQUAL(a(r, c), ref_a(r, c));
}
@ -109,29 +109,32 @@ void test_scalar_block_multiplications(rotgen::tests::matrix_block_test_case<Mat
{
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType a(matrix_construct.rows, matrix_construct.cols);
EigenMatrix ref_a(matrix_construct.rows, matrix_construct.cols);
auto[d,i0,j0,ni,nj] = matrix_construct;
auto[rows,cols,fn] = d;
MatrixType a(rows, cols);
EigenMatrix ref_a(rows, cols);
TTS_EXPECT(verify_rotgen_reentrance(a * scalar));
TTS_EXPECT(verify_rotgen_reentrance(scalar * a));
for (rotgen::Index r = 0; r < matrix_construct.rows; ++r)
for (rotgen::Index c = 0; c < matrix_construct.cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(matrix_construct.init_fn(r, c));
for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(fn(r, c));
auto a_block = rotgen::extract(a, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto ref_a_block = ref_a.block(matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto a_block = rotgen::extract(a, i0, j0,
ni, nj);
auto ref_a_block = ref_a.block(i0, j0,
ni, nj);
auto a_scalar_multiplication = a_block * scalar;
auto scalar_a_multiplication = scalar * a_block;
auto a_scalar_multiplication_ref = ref_a_block * scalar;
auto scalar_a_multiplication_ref = scalar * ref_a_block;
for (rotgen::Index r = 0; r < matrix_construct.ni; ++r)
for (rotgen::Index r = 0; r < ni; ++r)
{
for (rotgen::Index c = 0; c < matrix_construct.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(scalar_a_multiplication(r, c), scalar_a_multiplication_ref(r, c));
@ -141,12 +144,12 @@ void test_scalar_block_multiplications(rotgen::tests::matrix_block_test_case<Mat
a_block *= scalar;
ref_a_block *= scalar;
for (rotgen::Index r = 0; r < matrix_construct.ni; ++r)
for (rotgen::Index c = 0; c < matrix_construct.nj; ++c)
for (rotgen::Index r = 0; r < ni; ++r)
for (rotgen::Index c = 0; c < nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (rotgen::Index r = 0; r < matrix_construct.rows; ++r)
for (rotgen::Index c = 0; c < matrix_construct.cols; ++c)
for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c)
TTS_EQUAL(a(r, c), ref_a(r, c));
}
@ -156,51 +159,54 @@ void test_block_multiplication(rotgen::tests::matrix_block_test_case<MatrixType>
{
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType a(a_matrix_construct.rows, a_matrix_construct.cols);
MatrixType b(b_matrix_construct.rows, b_matrix_construct.cols);
EigenMatrix ref_a(a_matrix_construct.rows, a_matrix_construct.cols);
EigenMatrix ref_b(b_matrix_construct.rows, b_matrix_construct.cols);
auto[a_d,a_i0,a_j0,a_ni,a_nj] = a_matrix_construct;
auto[a_rows,a_cols,a_fn] = a_d;
for (rotgen::Index r = 0; r < a_matrix_construct.rows; ++r)
for (rotgen::Index c = 0; c < a_matrix_construct.cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(a_matrix_construct.init_fn(r, c));
for (rotgen::Index r = 0; r < b_matrix_construct.rows; ++r)
for (rotgen::Index c = 0; c < b_matrix_construct.cols; ++c)
ref_b(r,c) = b(r,c) = static_cast<T>(b_matrix_construct.init_fn(r, c));
auto[b_d,b_i0,b_j0,b_ni,b_nj] = b_matrix_construct;
auto[b_rows,b_cols,b_fn] = b_d;
auto a_block = rotgen::extract(a, a_matrix_construct.i0, a_matrix_construct.j0,
a_matrix_construct.ni, a_matrix_construct.nj);
auto b_block = rotgen::extract(b, b_matrix_construct.i0, b_matrix_construct.j0,
b_matrix_construct.ni, b_matrix_construct.nj);
auto ref_a_block = ref_a.block(a_matrix_construct.i0, a_matrix_construct.j0,
a_matrix_construct.ni, a_matrix_construct.nj);
auto ref_b_block = ref_b.block(b_matrix_construct.i0, b_matrix_construct.j0,
b_matrix_construct.ni, b_matrix_construct.nj);
MatrixType a(a_rows, a_cols);
MatrixType b(b_rows, b_cols);
EigenMatrix ref_a(a_rows, a_cols);
EigenMatrix ref_b(b_rows, b_cols);
for (rotgen::Index r = 0; r < a_rows; ++r)
for (rotgen::Index c = 0; c < a_cols; ++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 c = 0; c < b_cols; ++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 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_b_block = ref_b.block(b_i0, b_j0,b_ni, b_nj);
TTS_EXPECT(verify_rotgen_reentrance(a_block * b_block));
auto a_b_product_original = a_block * b_block;
auto a_b_product_ref = ref_a_block * ref_b_block;
for (rotgen::Index r = 0; r < a_matrix_construct.ni; ++r)
for (rotgen::Index c = 0; c < a_matrix_construct.nj; ++c)
for (rotgen::Index r = 0; r < a_ni; ++r)
for (rotgen::Index c = 0; c < a_nj; ++c)
TTS_EQUAL(a_b_product_original (r, c), a_b_product_ref(r, c));
a_block *= b_block;
ref_a_block *= ref_b_block;
for (rotgen::Index r = 0; r < a_matrix_construct.ni; ++r)
for (rotgen::Index c = 0; c < a_matrix_construct.nj; ++c)
for (rotgen::Index r = 0; r < a_ni; ++r)
for (rotgen::Index c = 0; c < a_nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (rotgen::Index r = 0; r < a_matrix_construct.rows; ++r)
for (rotgen::Index c = 0; c < a_matrix_construct.cols; ++c)
for (rotgen::Index r = 0; r < a_rows; ++r)
for (rotgen::Index c = 0; c < a_cols; ++c)
TTS_EQUAL(a(r, c), ref_a(r, c));
for (rotgen::Index r = 0; r < b_matrix_construct.rows; ++r)
for (rotgen::Index c = 0; c < b_matrix_construct.cols; ++c)
for (rotgen::Index r = 0; r < b_rows; ++r)
for (rotgen::Index c = 0; c < b_cols; ++c)
TTS_EQUAL(b(r, c), ref_b(r, c));
}
@ -216,18 +222,17 @@ TTS_CASE_TPL("Check block addition", rotgen::tests::types)
auto 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>({13 , 15, init_a, 1, 2, 3, 4}, init_b, 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>({15 , 15, init_a, 3, 4, 5, 5}, init_b, 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);
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>({{13, 15, init_a}, 1, 2, 3, 4}, init_b, 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>({{15, 15, init_a}, 3, 4, 5, 5}, init_b, 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)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
@ -235,36 +240,35 @@ TTS_CASE_TPL("Check block subtraction", rotgen::tests::types)
auto 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, 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>({5 , 9, init_a, 2, 2, 2, 2}, init_b, 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>({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);
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, 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>({{ 5, 9, init_a}, 2, 2, 2, 2}, init_b, 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>({{ 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)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
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; };
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>({13 , 15, init_b, 1, 2, 4, 4}, {13 , 15, init_b, 0, 1, 4, 4});
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>({15 , 15, init_a, 3, 4, 5, 5}, {15 , 15, init_b, 0, 0, 5, 5});
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>({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});
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>({{13, 15, init_b }, 1, 2, 4, 4}, {{13, 15, init_b }, 0, 1, 4, 4});
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>({{15, 15, init_a }, 3, 4, 5, 5}, {{15, 15, init_b }, 0, 0, 5, 5});
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>({{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)
@ -272,15 +276,15 @@ TTS_CASE_TPL("Check block multiplication with scalar", rotgen::tests::types)
{
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>({13 , 15, init_a, 1, 2, 3, 4}, T{ 0.});
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>({15 , 15, init_a, 3, 4, 5, 5}, T{ 42. });
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});
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>({{13, 15, init_a}, 1, 2, 3, 4}, T{ 0.});
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>({{15, 15, init_a}, 3, 4, 5, 5}, T{ 42. });
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)
@ -290,13 +294,14 @@ TTS_CASE_TPL("Check block division with scalar", rotgen::tests::types)
auto 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>({13 , 15, init_a, 1, 2, 3, 4}, T{-2.5}, 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>({15 , 15, init_a, 3, 4, 5, 5}, T{-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);
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>({{13, 15, init_a}, 1, 2, 3, 4}, T{-2.5}, 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>({{15, 15, init_a}, 3, 4, 5, 5}, T{-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

@ -1,117 +0,0 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
void test_size(const auto& matrix, rotgen::Index rows, rotgen::Index cols)
{
TTS_EQUAL(matrix.rows(), rows);
TTS_EQUAL(matrix.cols(), cols);
TTS_EQUAL(matrix.size(), rows*cols);
}
void test_value(const auto& matrix, rotgen::Index rows, rotgen::Index cols, auto constant)
{
TTS_EXPECT(verify_rotgen_reentrance(matrix));
test_size(matrix, rows, cols);
for(rotgen::Index r=0;r<rows;++r)
for(rotgen::Index c=0;c<cols;++c)
TTS_EQUAL(matrix(r, c), constant);
}
void test_random(const auto& matrix, rotgen::Index rows, rotgen::Index cols)
{
TTS_EXPECT(verify_rotgen_reentrance(matrix));
test_size(matrix, rows, cols);
for(rotgen::Index r=0;r<rows;++r)
for(rotgen::Index c=0;c<cols;++c)
{
TTS_GREATER_EQUAL(matrix(r, c), -1.0);
TTS_LESS_EQUAL(matrix(r, c), 1.0);
}
}
void test_identity(const auto& matrix, rotgen::Index rows, rotgen::Index cols)
{
TTS_EXPECT(verify_rotgen_reentrance(matrix));
test_size(matrix, rows, cols);
for(rotgen::Index r=0;r<rows;++r)
for(rotgen::Index c=0;c<cols;++c)
TTS_EQUAL(matrix(r, c), r==c ? 1 : 0);
}
TTS_CASE_TPL("Test zero", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>>)
{
test_value(rotgen::block<rotgen::matrix<T, 7, 8>, 3, 4>::Zero(), 3, 4, 0);
test_value(rotgen::block<rotgen::matrix<T, 72, 2>, 1, 1>::Zero(), 1, 1, 0);
test_value(rotgen::block<rotgen::matrix<T, 21, 33>, 10, 10>::Zero(), 10, 10, 0);
test_value(rotgen::block<rotgen::matrix<T, 3, 4>, 3, 4>::Zero(3, 4), 3, 4, 0);
test_value(rotgen::block<rotgen::matrix<T, 17, 4>, 3, 3>::Zero(3, 3), 3, 3, 0);
test_value(rotgen::block<rotgen::matrix<T, 2, 2>, 2, 2>::Zero(2, 2), 2, 2, 0);
test_value(rotgen::block<rotgen::matrix<T, 8, 7>, rotgen::Dynamic, rotgen::Dynamic>::Zero(2, 3), 2, 3, 0);
test_value(rotgen::block<rotgen::matrix<T, 3, 4>, 0, 0>::Zero(0, 0), 0, 0, 0);
test_value(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Identity(2, 7)),
rotgen::Dynamic, 7>::Zero(3, 7), 3, 7, 0);
test_value(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Random(14, 3)),
4, rotgen::Dynamic>::Zero(4, 3), 4, 3, 0);
};
TTS_CASE_TPL("Test constant", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_value(rotgen::block<rotgen::matrix<T, 3, 4>, 3, 4>::Constant(5.12), 3, 4, T(5.12));
test_value(rotgen::block<rotgen::matrix<T, 88, 81>, 1, 1>::Constant(2.2), 1, 1, T(2.2));
test_value(rotgen::block<rotgen::matrix<T, 21, 33>, 10, 10>::Constant(13), 10, 10, T(13));
test_value(rotgen::block<rotgen::matrix<T, 3, 4>, rotgen::Dynamic, rotgen::Dynamic>::Constant(2, 7, 5.6), 2, 7, T(5.6));
test_value(rotgen::block<rotgen::matrix<T, 17, 5>, 2, 2>::Constant(2, 2, 2.0), 2, 2, T(2.0));
test_value(rotgen::block<rotgen::matrix<T, 144, 109>, rotgen::Dynamic, 9>::Constant(9, 9, 1.1), 9, 9, T(1.1));
test_value(rotgen::block<rotgen::matrix<T, 8, 11>, 5, rotgen::Dynamic>::Constant(5, 9, 42), 5, 9, T(42));
test_value(rotgen::block<rotgen::matrix<T, 4, 3>, 4, 3>::Constant(4, 3, 0), 4, 3, 0);
test_value(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Identity(3, 7)),
rotgen::Dynamic, 7>::Constant(3, 7, 88), 3, 7, T(88));
test_value(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Random(14, 3)),
4, rotgen::Dynamic>::Constant(4, 3, 3.99), 4, 3, T(3.99));
};
TTS_CASE_TPL("Test random", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_random(rotgen::block<rotgen::matrix<T, 3, 4>, 3, 3>::Random(), 3, 3);
test_random(rotgen::block<rotgen::matrix<T, 1, 1>, 1, 1>::Random(), 1, 1);
test_random(rotgen::block<rotgen::matrix<T, 13, 12>, 3, 4>::Random(), 3, 4);
test_random(rotgen::block<rotgen::matrix<T, 3, 4>, rotgen::Dynamic, rotgen::Dynamic>::Random(1, 5), 1, 5);
test_random(rotgen::block<rotgen::matrix<T, 17, 11>, 2, 1>::Random(2, 1), 2, 1);
test_random(rotgen::block<rotgen::matrix<T, 109, 117>, rotgen::Dynamic, 9>::Random(3, 9), 3, 9);
test_random(rotgen::block<rotgen::matrix<T, 9, 11>, 5, rotgen::Dynamic>::Random(5, 2), 5, 2);
test_random(rotgen::block<rotgen::matrix<T, 4, 3>, 4, 3>::Random(4, 3), 4, 3);
test_random(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Identity(3, 7)),
rotgen::Dynamic, 7>::Random(3, 7), 3, 7);
test_random(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Random(14, 15)),
4, rotgen::Dynamic>::Random(4, 11), 4, 11);
};
TTS_CASE_TPL("Test identity", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_identity(rotgen::block<rotgen::matrix<T, 3, 4>, 3, 3>::Identity(), 3, 3);
test_identity(rotgen::block<rotgen::matrix<T, 1, 1>, 1, 1>::Identity(), 1, 1);
test_identity(rotgen::block<rotgen::matrix<T, 13, 12>, 3, 4>::Identity(), 3, 4);
test_identity(rotgen::block<rotgen::matrix<T, 3, 4>, rotgen::Dynamic, rotgen::Dynamic>::Identity(1, 5), 1, 5);
test_identity(rotgen::block<rotgen::matrix<T, 17, 11>, 2, 1>::Identity(2, 1), 2, 1);
test_identity(rotgen::block<rotgen::matrix<T, 109, 117>, rotgen::Dynamic, 9>::Identity(3, 9), 3, 9);
test_identity(rotgen::block<rotgen::matrix<T, 9, 11>, 5, rotgen::Dynamic>::Identity(5, 2), 5, 2);
test_identity(rotgen::block<rotgen::matrix<T, 4, 3>, 4, 3>::Identity(4, 3), 4, 3);
test_identity(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Identity(3, 7)),
rotgen::Dynamic, 7>::Identity(3, 7), 3, 7);
test_identity(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Random(14, 15)),
4, rotgen::Dynamic>::Identity(4, 11), 4, 11);
};

View file

@ -0,0 +1,126 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/rotgen.hpp>
#include <Eigen/Dense>
#include <vector>
#include <tuple>
namespace rotgen::tests
{
template<typename T>
void check_shape_functions(T original)
{
using mat_t = matrix<typename T::value_type,Dynamic,Dynamic,T::storage_order>;
mat_t result(original.cols(), original.rows());
prepare([&](auto r, auto c) { return original(c,r); },result);
TTS_EQUAL(original.transpose(), result );
TTS_EQUAL(original.conjugate(), original);
TTS_EQUAL(original.adjoint() , result );
TTS_EQUAL(transpose(original) , result );
TTS_EQUAL(conjugate(original) , original);
TTS_EQUAL(adjoint(original) , result );
if constexpr(T::is_defined_static)
{
if constexpr(T::RowsAtCompileTime == T::ColsAtCompileTime)
{
mat_t ref = original;
original.transposeInPlace();
TTS_EQUAL(original, result);
original.adjointInPlace();
TTS_EQUAL(original, ref);
transposeInPlace(original);
TTS_EQUAL(original, result);
adjointInPlace(original);
TTS_EQUAL(original, ref);
}
}
else
{
if (original.rows() == original.cols())
{
mat_t ref = original;
original.transposeInPlace();
TTS_EQUAL(original, result);
original.adjointInPlace();
TTS_EQUAL(original, ref);
transposeInPlace(original);
TTS_EQUAL(original, result);
adjointInPlace(original);
TTS_EQUAL(original, ref);
}
}
if constexpr(!rotgen::use_expression_templates)
{
TTS_EXPECT(verify_rotgen_reentrance( original.transpose()) );
TTS_EXPECT(verify_rotgen_reentrance( original.conjugate()) );
TTS_EXPECT(verify_rotgen_reentrance( original.adjoint()) );
}
}
template<typename T>
void check_reduction_functions(const T& input)
{
using EigenMatrix = Eigen::Matrix<typename T::value_type, Eigen::Dynamic, Eigen::Dynamic>;
EigenMatrix ref(input.rows(), input.cols());
prepare([&](auto r, auto c) { return input(r,c); }, ref);
TTS_ULP_EQUAL(input.sum(), ref.sum() , 2);
TTS_ULP_EQUAL(sum(input) , ref.sum() , 2);
TTS_ULP_EQUAL(input.prod(), ref.prod(), 2);
TTS_ULP_EQUAL(prod(input) , ref.prod(), 2);
TTS_ULP_EQUAL(input.mean(), ref.mean(), 2);
TTS_ULP_EQUAL(mean(input) , ref.mean(), 2);
TTS_EQUAL(input.trace(), ref.trace());
TTS_EQUAL(trace(input) , ref.trace());
TTS_EQUAL(input.minCoeff(), ref.minCoeff());
TTS_EQUAL(minCoeff(input) , ref.minCoeff());
TTS_EQUAL(input.maxCoeff(), ref.maxCoeff());
TTS_EQUAL(maxCoeff(input) , ref.maxCoeff());
{
rotgen::Index row, col, ref_row, ref_col;
TTS_EQUAL(input.minCoeff(&row, &col), ref.minCoeff(&ref_row, &ref_col));
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
TTS_EQUAL(input.maxCoeff(&row, &col), ref.maxCoeff(&ref_row, &ref_col));
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
}
{
rotgen::Index row, col, ref_row, ref_col;
TTS_EQUAL(minCoeff(input,&row, &col), ref.minCoeff(&ref_row, &ref_col));
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
TTS_EQUAL(maxCoeff(input,&row, &col), ref.maxCoeff(&ref_row, &ref_col));
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
}
}
}

View file

@ -0,0 +1,35 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/rotgen.hpp>
#include <Eigen/Dense>
#include <vector>
#include <tuple>
namespace rotgen::tests
{
template<typename T>
void check_norms_functions(const T& input)
{
using EigenMatrix = Eigen::Matrix<typename T::value_type, Eigen::Dynamic, Eigen::Dynamic>;
EigenMatrix ref(input.rows(), input.cols());
prepare([&](auto r, auto c) { return input(r,c); }, ref);
TTS_EQUAL(input.norm() , ref.norm());
TTS_EQUAL(input.squaredNorm() , ref.squaredNorm());
TTS_EQUAL(input.template lpNorm<1>() , ref.template lpNorm<1>());
TTS_EQUAL(input.template lpNorm<2>() , ref.template lpNorm<2>());
TTS_EQUAL(input.template lpNorm<rotgen::Infinity>() , ref.template lpNorm<Eigen::Infinity>());
TTS_EQUAL(norm(input) , ref.norm());
TTS_EQUAL(squaredNorm(input) , ref.squaredNorm());
TTS_EQUAL(lpNorm<1>(input) , ref.template lpNorm<1>());
TTS_EQUAL(lpNorm<2>(input) , ref.template lpNorm<2>());
TTS_EQUAL(lpNorm<rotgen::Infinity>(input) , ref.template lpNorm<Eigen::Infinity>());
}
}

View file

@ -0,0 +1,192 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/rotgen.hpp>
#include <Eigen/Dense>
#include <vector>
#include <tuple>
namespace rotgen::tests
{
struct matrix_descriptor
{
rotgen::Index rows, cols;
std::function<double(std::size_t,std::size_t)> init_fn;
};
template<rotgen::Index Rows, rotgen::Index Cols>
struct static_matrix_descriptor
{
static constexpr rotgen::Index rows = Rows;
static constexpr rotgen::Index cols = Cols;
std::function<double(std::size_t,std::size_t)> init_fn;
};
template<typename MatrixType>
struct matrix_block_test_case
{
matrix_descriptor matrix_desc;
rotgen::Index i0, j0, ni, nj;
};
template<typename MatrixType, rotgen::Index NI, rotgen::Index NJ>
struct static_matrix_block_test_case
{
matrix_descriptor matrix_desc;
static constexpr rotgen::Index ni = NI;
static constexpr rotgen::Index nj = NJ;
rotgen::Index i0, j0;
};
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 c = 0; c < cols; ++c)
output(r,c) = init_fn(r, c);
}
void prepare(auto fn, auto& output)
{
for (rotgen::Index r = 0; r < output.rows(); ++r)
for (rotgen::Index c = 0; c < output.cols(); ++c)
output(r,c) = fn(r, c);
}
auto generate_matrix_references()
{
auto fn = [](auto r, auto c) { return r + 3 * c - 2.5; };
std::vector<rotgen::tests::matrix_descriptor> cases =
{
// Singular matrix
{1, 1, fn},
// Square matrix below MAX_SIZE
{3, 3, fn},
// Square matrix at MAX_SIZE
{4, 4, fn},
// Square matrix above MAX_SIZE
{7, 7, fn},
// Tall matrix below MAX_SIZE
{5, 2, fn},
// Tall matrix at MAX_SIZE
{8, 2, fn},
// Tall matrix above MAX_SIZE
{10, 3, fn},
// Thick matrix below MAX_SIZE
{2, 5, fn},
// Thick matrix at MAX_SIZE
{2, 8, fn},
// Thick matrix above MAX_SIZE
{3, 10, fn}
};
return cases;
}
auto generate_static_matrix_references()
{
auto fn = [](auto r, auto c) { return r + 3 * c - 2.5; };
std::tuple cases =
{
// Singular matrix
static_matrix_descriptor< 1, 1>{fn},
// Square matrix below MAX_SIZE
static_matrix_descriptor< 3, 3>{fn},
// Square matrix at MAX_SIZE
static_matrix_descriptor< 4, 4>{fn},
// Square matrix above MAX_SIZE
static_matrix_descriptor< 7, 7>{fn},
// Tall matrix below MAX_SIZE
static_matrix_descriptor< 5, 2>{fn},
// Tall matrix at MAX_SIZE
static_matrix_descriptor< 8, 2>{fn},
// Tall matrix above MAX_SIZE
static_matrix_descriptor<10, 3>{fn},
// Thick matrix below MAX_SIZE
static_matrix_descriptor< 2, 5>{fn},
// Thick matrix at MAX_SIZE
static_matrix_descriptor< 2, 8>{fn},
// Thick matrix above MAX_SIZE
static_matrix_descriptor< 3,10>{fn}
};
return cases;
}
template<typename T, typename O>
auto generate_block_references()
{
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>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> cases =
{
// Singular blocks
{base, 0, 0, 1, 1},
{base, 3, 2, 1, 1},
{base, 4,11, 1, 1},
{base,15,15, 1, 1},
// Square block below MAX_SIZE
{base,7,9, 3, 3},
// Square block at MAX_SIZE
{base,6,3, 4, 4},
// Square block above MAX_SIZE
{base,6,3, 6, 6},
// Tall block below MAX_SIZE
{base,6,3, 5, 2},
// Tall block at MAX_SIZE
{base,6,3, 8, 2},
// Tall block above MAX_SIZE
{base,6,3, 7, 3},
// Thick block below MAX_SIZE
{base,6,3, 2, 5},
// Thick block at MAX_SIZE
{base,6,3, 2, 8},
// Thick block above MAX_SIZE
{base,6,3, 3, 7}
};
return cases;
}
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; }};
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>;
std::tuple cases =
{
// Singular blocks
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, 4,11},
static_matrix_block_test_case<mat_t, 1, 1>{base,15,15},
// Square block below MAX_SIZE
static_matrix_block_test_case<mat_t, 3, 3>{base,7,9},
// Square block at MAX_SIZE
static_matrix_block_test_case<mat_t, 4, 4>{base,6,3},
// Square block above MAX_SIZE
static_matrix_block_test_case<mat_t, 6, 6>{base,6,3},
// Tall block below MAX_SIZE
static_matrix_block_test_case<mat_t, 5, 2>{base,6,3},
// Tall block at MAX_SIZE
static_matrix_block_test_case<mat_t, 8, 2>{base,6,3},
// Tall block above MAX_SIZE
static_matrix_block_test_case<mat_t, 7, 3>{base,6,3},
// Thick block below MAX_SIZE
static_matrix_block_test_case<mat_t, 2, 5>{base,6,3},
// Thick block at MAX_SIZE
static_matrix_block_test_case<mat_t, 2, 8>{base,6,3},
// Thick block above MAX_SIZE
static_matrix_block_test_case<mat_t, 3, 7>{base,6,3}
};
return cases;
}
}

View file

@ -1,124 +0,0 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
#include <Eigen/Dense>
template <typename MatrixType>
struct MatrixDescriptor
{
std::size_t rows, cols;
std::function<void(MatrixType &, std::size_t, std::size_t)> init_fn;
};
template <typename MatrixType>
void test_matrix_unary_ops(std::size_t rows, std::size_t cols,
const std::function<void(MatrixType &, std::size_t, std::size_t)> &init_fn)
{
MatrixType original(rows, cols);
MatrixType transposed_matrix(cols, rows);
for (std::size_t r = 0; r < rows; ++r)
for (std::size_t c = 0; c < cols; ++c)
init_fn(original, r, c);
for (std::size_t r = 0; r < rows; ++r)
for (std::size_t c = 0; c < cols; ++c)
transposed_matrix(c, r) = original(r, c);
TTS_EQUAL(rotgen::transpose(original), transposed_matrix);
TTS_EQUAL(rotgen::conjugate(original), original);
TTS_EQUAL(rotgen::adjoint(original), transposed_matrix);
TTS_EXPECT(verify_rotgen_reentrance(rotgen::transpose(original)));
TTS_EXPECT(verify_rotgen_reentrance(rotgen::conjugate(original)));
TTS_EXPECT(verify_rotgen_reentrance(rotgen::adjoint(original)));
rotgen::transposeInPlace(original);
TTS_EQUAL(original, transposed_matrix);
rotgen::transposeInPlace(original);
rotgen::adjointInPlace(original);
TTS_EQUAL(original, transposed_matrix);
}
template <typename MatrixType>
void test_matrix_scalar_reductions(std::size_t rows, std::size_t cols,
const std::function<void(MatrixType&, std::size_t, std::size_t)>& init_fn)
{
using EigenMatrix = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType original(rows, cols);
EigenMatrix ref(rows, cols);
for (std::size_t r = 0; r < rows; ++r)
for (std::size_t c = 0; c < cols; ++c)
{
init_fn(original, r, c);
ref(r, c) = original(r, c);
}
TTS_EQUAL(rotgen::sum(original), ref.sum());
TTS_EQUAL(rotgen::prod(original), ref.prod());
TTS_EQUAL(rotgen::mean(original), ref.mean());
TTS_EQUAL(rotgen::maxCoeff(original), ref.maxCoeff());
TTS_EQUAL(rotgen::minCoeff(original), ref.minCoeff());
TTS_EQUAL(rotgen::trace(original), ref.trace());
std::ptrdiff_t row, col, ref_row, ref_col;
double cmin = rotgen::minCoeff(original, &row, &col);
double rmin = ref.minCoeff(&ref_row, &ref_col);
TTS_EQUAL(cmin, rmin);
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
double cmax = rotgen::maxCoeff(original, &row, &col);
double rmax = ref.maxCoeff(&ref_row, &ref_col);
TTS_EQUAL(cmax, rmax);
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
}
TTS_CASE("Matrix unary operations: transpose, adjoint, conjugate")
{
std::vector<MatrixDescriptor<rotgen::matrix<double>>> test_matrices = {
{3, 3, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = r + 3 * c - 2.5; }},
{4, 9, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = r*r + 3.12 * c + 6.87; }},
{2, 7, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = 1.1 * (r - c); }},
{1, 5, [](auto &m, std::size_t r, std::size_t c) { m(r, c) = 9.99; }},
{4, 2, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = 0.0; }},
{3, 3, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = (r == c) ? 1.0 : 0.0; }},
{2, 2, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = (r + c) * 1e-10; }},
{2, 2, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = (r + 1) * 1e+10; }},
};
for (auto const &desc : test_matrices)
test_matrix_unary_ops<rotgen::matrix<double>>(desc.rows, desc.cols, desc.init_fn);
};
TTS_CASE("Basic arithmetic reduction operations")
{
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) = 0.0; }},
{2, 4, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = -r -c*c - 1234; }},
{4, 4, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = 7.0; }},
{1, 1, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = 42.0; }},
{4, 2, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = std::sin(r + c); }},
{1, 5, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = -1.5 * r + 2.56 * c; }},
{5, 7, [](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)
test_matrix_scalar_reductions<rotgen::matrix<double>>(rows, cols, init_fn);
};

View file

@ -1,60 +0,0 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
#include <Eigen/Dense>
template <typename MatrixType>
struct MatrixDescriptor
{
std::size_t rows, cols;
std::function<void(MatrixType &, std::size_t, std::size_t)> init_fn;
};
template <typename MatrixType>
void test_matrix_norms(std::size_t rows, std::size_t cols,
const std::function<void(MatrixType &, std::size_t, std::size_t)> &init_fn)
{
MatrixType matrix(rows, cols);
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> ref(rows, cols);
for (std::size_t r = 0; r < rows; ++r)
for (std::size_t c = 0; c < cols; ++c)
{
init_fn(matrix, r, c);
ref(r, c) = matrix(r, c);
}
constexpr double epsilon = 1e-10;
TTS_RELATIVE_EQUAL(rotgen::norm(matrix), ref.norm(), epsilon);
TTS_RELATIVE_EQUAL(rotgen::squaredNorm(matrix), ref.squaredNorm(), epsilon);
TTS_RELATIVE_EQUAL(rotgen::lpNorm<1>(matrix), ref.lpNorm<1>(), epsilon);
TTS_RELATIVE_EQUAL(rotgen::lpNorm<2>(matrix), ref.lpNorm<2>(), epsilon);
TTS_RELATIVE_EQUAL(rotgen::lpNorm<-1>(matrix), ref.lpNorm<Eigen::Infinity>(), epsilon);
}
TTS_CASE("Matrix norm-related operations")
{
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; }},
{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; }},
{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; }},
{10, 11, [](auto& m, std::size_t r, std::size_t c) { m(r, c) = std::tan(r + c); }},
{1, 5, [](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)
test_matrix_norms<rotgen::matrix<double>>(rows, cols, init_fn);
};

47
test/unit/io.cpp Normal file
View file

@ -0,0 +1,47 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
#include <sstream>
TTS_CASE_TPL("I/O for matrix", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> x({ {1,2} , {3,4} });
std::ostringstream os;
os << x;
TTS_EQUAL(os.str(), std::string{"1 2\n3 4"});
};
TTS_CASE_TPL("I/O for block", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base({ {1,2} , {3,4} });
auto x = rotgen::extract(base,0,0,2,2);
std::ostringstream os;
os << x;
TTS_EQUAL(os.str(), std::string{"1 2\n3 4"});
};
TTS_CASE_TPL("I/O for map test", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
using base = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>;
T data[] = {1,2,3,4};
rotgen::map<base> x(data,2,2);
std::ostringstream os;
os << x;
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"});
};

View file

@ -0,0 +1,73 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include "unit/common/arithmetic.hpp"
#include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic map transposition-like operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases)
{
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>;
mat_t base(rows, cols);
rotgen::tests::prepare(rows,cols,fn,base);
rotgen::map<mat_t> input(base.data(),rows,cols);
rotgen::tests::check_shape_functions(input);
}
};
TTS_CASE_TPL("Test static map transposition-like operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc)
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(D::rows,D::cols);
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::tests::check_shape_functions(input);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};
TTS_CASE_TPL("Test dynamic map reduction-like operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases)
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(rows, 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::tests::check_reduction_functions(input);
}
};
TTS_CASE_TPL("Test static map reduction-like operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc)
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(D::rows,D::cols);
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::tests::check_reduction_functions(input);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};

View file

@ -0,0 +1,83 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Function size", 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};
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.cols(), rotgen::Index{12});
rotgen::map<rotgen::matrix<T,1,12,rotgen::RowMajor>> s112_map(data);
TTS_EQUAL(s112_map.rows(), rotgen::Index{1});
TTS_EQUAL(s112_map.cols(), rotgen::Index{12});
TTS_EQUAL(s112_map.size(), rotgen::Index{12});
rotgen::map<rotgen::matrix<T,12,1,rotgen::ColMajor>> s121_map(data);
TTS_EQUAL(s121_map.rows(), rotgen::Index{12});
TTS_EQUAL(s121_map.cols(), rotgen::Index{1});
TTS_EQUAL(s121_map.size(), rotgen::Index{12});
rotgen::map<rotgen::matrix<T,3,4,O::value>> s34_map(data);
TTS_EQUAL(s34_map.rows(), rotgen::Index{3});
TTS_EQUAL(s34_map.cols(), rotgen::Index{4});
TTS_EQUAL(s34_map.size(), rotgen::Index{12});
rotgen::map<rotgen::matrix<T,6,2,O::value>> s62_map(data);
TTS_EQUAL(s62_map.rows(), rotgen::Index{6});
TTS_EQUAL(s62_map.cols(), rotgen::Index{2});
TTS_EQUAL(s62_map.size(), rotgen::Index{12});
};
TTS_CASE_TPL("Test coefficient accessors", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
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};
rotgen::map<base> a(data,4,3);
for(rotgen::Index i=0;i<4;i++)
{
for(rotgen::Index j=0;j<3;j++)
{
if constexpr(O::value) TTS_EQUAL(a(i,j), data[j+3*i]);
else TTS_EQUAL(a(i,j), data[i+4*j]);
}
}
a(1, 1) = 42;
TTS_EQUAL(a(1,1), 42);
T& ref = a(2, 2);
ref = 17;
TTS_EQUAL(a(2, 2), 17);
};
TTS_CASE_TPL("Test one index coefficient accessors", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
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};
rotgen::map<base> a(data,4,3);
for(rotgen::Index i=0;i<a.size();i++)
TTS_EQUAL(a(i), data[i]) << "Index: " << i << "\n";
a(1) = 42;
TTS_EQUAL(data[1], 42);
T& ref = a(2);
ref = 17;
TTS_EQUAL(data[2], 17);
};

View file

@ -0,0 +1,89 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
TTS_CASE_TPL("map constructor from pointer and single static size", 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};
rotgen::map<rotgen::matrix<T,1,12,rotgen::RowMajor>> row_map(data);
for(rotgen::Index i=0;i<12;i++)
TTS_EQUAL(row_map(i), data[i]);
rotgen::map<rotgen::matrix<T,1,12,rotgen::RowMajor> const> const_row_map(data);
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);
for(rotgen::Index i=0;i<12;i++)
TTS_EQUAL(col_map(i), data[i]);
rotgen::map<rotgen::matrix<T,12,1,rotgen::ColMajor> const> const_col_map(data);
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)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
using base = rotgen::matrix<T,4,3,O::value>;
T data[] = {1,2,3,4,5,6,7,8,9,10,11,12};
rotgen::map<base> dyn_map(data);
for(rotgen::Index i=0;i<4;i++)
{
for(rotgen::Index j=0;j<3;j++)
{
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]);
}
}
};
TTS_CASE_TPL("map constructor from pointer and single dynamic size", 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};
rotgen::map<rotgen::matrix<T,1,rotgen::Dynamic,rotgen::RowMajor>> row_map(data,12);
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);
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);
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);
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)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
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};
rotgen::map<base> dyn_map(data,4,3);
for(rotgen::Index i=0;i<4;i++)
{
for(rotgen::Index j=0;j<3;j++)
{
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]);
}
}
};

41
test/unit/map/norms.cpp Normal file
View file

@ -0,0 +1,41 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include "unit/common/norms.hpp"
#include <rotgen/rotgen.hpp>
TTS_CASE_TPL("Test dynamic map norm operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases)
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(rows, 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::tests::check_norms_functions(input);
}
};
TTS_CASE_TPL("Test static map norm operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc)
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> base(D::rows,D::cols);
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::tests::check_norms_functions(input);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};

202
test/unit/map/operators.cpp Normal file
View file

@ -0,0 +1,202 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
#include <vector>
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)
{
MatrixType a_data(rows, cols);
MatrixType b_data(rows, cols);
MatrixType ref_data;
for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c)
{
a_data(r,c) = a_init_fn(r, c);
b_data(r,c) = b_init_fn(r, c);
}
ref_data = ops(a_data, b_data);
rotgen::map<MatrixType> a_map(a_data.data(), rows, cols);
rotgen::map<MatrixType> b_map(b_data.data(), rows, cols);
TTS_EQUAL(ops(a_map, b_map), ref_data);
self_ops(a_map, b_map);
TTS_EQUAL(a_map, ref_data);
TTS_EXPECT(verify_rotgen_reentrance(ops(a_map, b_map)));
TTS_EXPECT(verify_rotgen_reentrance(self_ops(a_map, b_map)));
}
template <typename MatrixType>
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 ref_data;
for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c)
a_data(r,c) = fn(r, c);
ref_data = ops(a_data, s);
rotgen::map<MatrixType> a_map(a_data.data(), rows, cols);
TTS_EQUAL(ops(a_map, s), ref_data);
self_ops(a_map, s);
TTS_EQUAL(a_map, ref_data);
TTS_EXPECT(verify_rotgen_reentrance(ops(a_map, s)));
TTS_EXPECT(verify_rotgen_reentrance(self_ops(a_map, s)));
}
template <typename MatrixType>
void test_map_scalar_multiplications(rotgen::Index rows, rotgen::Index cols, auto fn, auto s)
{
MatrixType a_data(rows, cols);
MatrixType ref_data;
for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c)
a_data(r,c) = fn(r, c);
ref_data = a_data * s;
rotgen::map<MatrixType> a_map(a_data.data(), rows, cols);
TTS_EQUAL(a_map * s, ref_data);
TTS_EQUAL(s * a_map, ref_data);
a_map *= s;
TTS_EQUAL(a_map, ref_data);
TTS_EXPECT(verify_rotgen_reentrance(a_map * s));
TTS_EXPECT(verify_rotgen_reentrance(s * a_map));
TTS_EXPECT(verify_rotgen_reentrance(a_map *= s));
}
template <typename MatrixType>
void test_map_multiplication(rotgen::Index rows, rotgen::Index cols, auto a_init_fn, auto b_init_fn)
{
MatrixType a_data(rows, cols);
MatrixType b_data(cols, rows);
MatrixType ref_data;
for (rotgen::Index r = 0; r < rows; ++r)
for (rotgen::Index c = 0; c < cols; ++c)
{
a_data(r,c) = a_init_fn(r,c);
b_data(c,r) = b_init_fn(c,r);
}
ref_data = a_data * b_data;
rotgen::map<MatrixType> a_map(a_data.data(), rows, cols);
rotgen::map<MatrixType> b_map(b_data.data(), cols, rows);
TTS_EQUAL(a_map * b_map, ref_data);
TTS_EXPECT(verify_rotgen_reentrance(a_map * b_map));
if(rows == cols)
{
a_map *= b_map;
TTS_EQUAL(a_map, ref_data);
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_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)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>;
auto 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>(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 , 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>(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>(5 , 5, init_0, init_b, 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)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>;
auto 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>(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 , 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>(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>(5 , 5, init_0, init_b, 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)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>;
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>(3 , 5, 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_b , 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_id, init_a );
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>(5 , 5, init_0 , init_b );
test_map_multiplication<mat_t>(5 , 5, init_a , init_0 );
};
TTS_CASE_TPL("Check map multiplication with scalar", 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>;
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>(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{ 1. });
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>(1 ,10, init_a, T{-0.5});
};
TTS_CASE_TPL("Check map division with scalar", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>;
auto 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>(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 , 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{ 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>(1 ,10, init_a, T{-0.5}, op, s_op);
};

View file

@ -6,113 +6,59 @@
*/
//==================================================================================================
#include "unit/tests.hpp"
#include "unit/common/arithmetic.hpp"
#include <rotgen/rotgen.hpp>
#include <Eigen/Dense>
template<typename MatrixType>
void test_matrix_unary_ops(std::size_t rows, std::size_t cols, auto const &init_fn)
{
MatrixType original(rows, cols);
MatrixType transposed_matrix(cols, rows);
for (std::size_t r = 0; r < rows; ++r)
for (std::size_t c = 0; c < cols; ++c)
original(r,c) = init_fn(r, c);
for (std::size_t r = 0; r < rows; ++r)
for (std::size_t c = 0; c < cols; ++c)
transposed_matrix(c, r) = original(r, c);
TTS_EQUAL(original.transpose(), transposed_matrix);
TTS_EQUAL(original.conjugate(), original);
TTS_EQUAL(original.adjoint(), transposed_matrix);
TTS_EXPECT(verify_rotgen_reentrance(original.transpose()));
TTS_EXPECT(verify_rotgen_reentrance(original.conjugate()));
TTS_EXPECT(verify_rotgen_reentrance(original.adjoint()));
original.transposeInPlace();
TTS_EQUAL(original, transposed_matrix);
original.transposeInPlace();
original.adjointInPlace();
TTS_EQUAL(original, transposed_matrix);
}
TTS_CASE_TPL("Test transpotion related operations", rotgen::tests::types)
TTS_CASE_TPL("Test dynamic matrix transposition-like operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
std::vector<rotgen::tests::matrix_descriptor> test_matrices =
auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases)
{
{3, 3, [](auto r, auto c) { return r + 3 * c - 2.5; }},
{4, 9, [](auto r, auto c) { return r*r + 3.12 * c + 6.87; }},
{2, 7, [](auto r, auto c) { return 1.1 * (r - c); }},
{1, 5, [](auto , auto ) { return 9.99; }},
{4, 2, [](auto , auto ) { return 0.0; }},
{3, 3, [](auto r, auto c) { return (r == c) ? 1.0 : 0.0; }},
{2, 2, [](auto r, auto c) { return (r + c) * 1e-10; }},
{2, 2, [](auto r, auto ) { return (r + 1) * 1e+10; }}
};
for (const auto& [rows, cols, fn] : test_matrices)
{
test_matrix_unary_ops<rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>>(rows, cols, fn);
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> input(rows, cols);
rotgen::tests::prepare(rows,cols,fn,input);
rotgen::tests::check_shape_functions(input);
}
};
template <typename MatrixType>
void test_matrix_reductions(std::size_t rows, std::size_t cols, auto const& init_fn)
{
using EigenMatrix = Eigen::Matrix<typename MatrixType::scalar_type, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType original(rows, cols);
EigenMatrix ref(rows, cols);
for (std::size_t r = 0; r < rows; ++r)
for (std::size_t c = 0; c < cols; ++c)
ref(r, c) = original(r,c) = init_fn(r, c);
TTS_EQUAL(original.sum(), ref.sum());
TTS_EQUAL(original.prod(), ref.prod());
TTS_EQUAL(original.mean(), ref.mean());
TTS_EQUAL(original.maxCoeff(), ref.maxCoeff());
TTS_EQUAL(original.minCoeff(), ref.minCoeff());
TTS_EQUAL(original.trace(), ref.trace());
std::ptrdiff_t row, col, ref_row, ref_col;
double cmin = original.minCoeff(&row, &col);
double rmin = ref.minCoeff(&ref_row, &ref_col);
TTS_EQUAL(cmin, rmin);
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
double cmax = original.maxCoeff(&row, &col);
double rmax = ref.maxCoeff(&ref_row, &ref_col);
TTS_EQUAL(cmax, rmax);
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
}
TTS_CASE_TPL("Test reductions", rotgen::tests::types)
TTS_CASE_TPL("Test static matrix transposition-like operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
std::vector<rotgen::tests::matrix_descriptor> test_matrices =
auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc)
{
{3, 3, [](auto r, auto c) {return r + c; }},
{3, 3, [](auto , auto ) {return 0.0; }},
{2, 4, [](auto r, auto c) {return -r -c*c - 1234; }},
{4, 4, [](auto , auto ) {return 7.0; }},
{1, 1, [](auto , auto ) {return 42.0; }},
{4, 2, [](auto r, auto c) {return std::sin(r + c); }},
{1, 5, [](auto r, auto c) {return -1.5 * r + 2.56 * c; }},
{5, 7, [](auto r, auto c) {return (r == c ? 1.0 : 0.0); }}
rotgen::matrix<T,D::rows,D::cols,O::value> input;
rotgen::tests::prepare(input.rows(),input.cols(),desc.init_fn,input);
rotgen::tests::check_shape_functions(input);
};
for (const auto& [rows, cols, fn] : test_matrices)
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};
TTS_CASE_TPL("Test dynamic matrix reduction-like operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases)
{
test_matrix_reductions<rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value>>(rows, cols, fn);
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> input(rows, cols);
rotgen::tests::prepare(rows,cols,fn,input);
rotgen::tests::check_reduction_functions(input);
}
};
TTS_CASE_TPL("Test static matrix reduction-like operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc)
{
rotgen::matrix<T,D::rows,D::cols,O::value> input;
rotgen::tests::prepare(input.rows(),input.cols(),desc.init_fn,input);
rotgen::tests::check_reduction_functions(input);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};

View file

@ -132,7 +132,7 @@ TTS_CASE_TPL("Test coefficient accessors", rotgen::tests::types)
T& ref = a(2, 2);
ref = 17;
assert(a(2, 2) == 17);
TTS_EQUAL(a(2, 2), 17);
};
TTS_CASE_TPL("Test one index coefficient accessors", rotgen::tests::types)

View file

@ -97,7 +97,6 @@ TTS_CASE_TPL("Copy constructor on static matrix", rotgen::tests::types)
TTS_EQUAL(b.cols(), rotgen::Index{5});
};
/*
TTS_CASE_TPL("Copy constructor on static/dynamic matrix", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
@ -114,7 +113,7 @@ TTS_CASE_TPL("Copy constructor on dynamic/static matrix", rotgen::tests::types)
rotgen::matrix<T, 5, 7,O::value> b = a;
TTS_EQUAL(b.rows(), 5);
TTS_EQUAL(b.cols(), 7);
};*/
};
TTS_CASE_TPL("Move constructor transfers contents", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )

View file

@ -38,6 +38,14 @@ void test_identity(const auto& matrix, std::size_t rows, std::size_t cols)
TTS_CASE_TPL("Test zero", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_value(rotgen::matrix<T, 3, 4, O::value>{}.setZero(), 3, 4, 0);
test_value(rotgen::matrix<T, 1, 1, O::value>{}.setZero(), 1, 1, 0);
test_value(rotgen::matrix<T, 10, 10, O::value>{}.setZero(), 10, 10, 0);
test_value(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>(1,1).setZero(3,4), 3, 4, 0);
test_value(rotgen::matrix<T, 7, 5, O::value>().setZero(7, 5), 7, 5, 0);
test_value(rotgen::matrix<T, 9,rotgen::Dynamic, O::value>(9,1).setZero(9, 3), 9, 3, 0);
test_value(rotgen::matrix<T,rotgen::Dynamic, 3, O::value>(1,3).setZero(2, 3), 2, 3, 0);
test_value(rotgen::matrix<T, 3, 4, O::value>::Zero(), 3, 4, 0);
test_value(rotgen::matrix<T, 1, 1, O::value>::Zero(), 1, 1, 0);
test_value(rotgen::matrix<T, 10, 10, O::value>::Zero(), 10, 10, 0);
@ -47,9 +55,37 @@ TTS_CASE_TPL("Test zero", rotgen::tests::types)
test_value(rotgen::matrix<T,rotgen::Dynamic, 3, O::value>::Zero(2, 3), 2, 3, 0);
};
TTS_CASE_TPL("Test ones", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_value(rotgen::matrix<T, 3, 4, O::value>{}.setOnes(), 3, 4, 1);
test_value(rotgen::matrix<T, 1, 1, O::value>{}.setOnes(), 1, 1, 1);
test_value(rotgen::matrix<T, 10, 10, O::value>{}.setOnes(), 10, 10, 1);
test_value(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>(1,1).setOnes(3, 4), 3, 4, 1);
test_value(rotgen::matrix<T, 7, 5, O::value>{}.setOnes(7, 5), 7, 5, 1);
test_value(rotgen::matrix<T, 9,rotgen::Dynamic, O::value>(9,1).setOnes(9, 3), 9, 3, 1);
test_value(rotgen::matrix<T,rotgen::Dynamic, 3, O::value>(1,3).setOnes(2, 3), 2, 3, 1);
test_value(rotgen::matrix<T, 3, 4, O::value>::Ones(), 3, 4, 1);
test_value(rotgen::matrix<T, 1, 1, O::value>::Ones(), 1, 1, 1);
test_value(rotgen::matrix<T, 10, 10, O::value>::Ones(), 10, 10, 1);
test_value(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Ones(3, 4), 3, 4, 1);
test_value(rotgen::matrix<T, 7, 5, O::value>::Ones(7, 5), 7, 5, 1);
test_value(rotgen::matrix<T, 9,rotgen::Dynamic, O::value>::Ones(9, 3), 9, 3, 1);
test_value(rotgen::matrix<T,rotgen::Dynamic, 3, O::value>::Ones(2, 3), 2, 3, 1);
};
TTS_CASE_TPL("Test constant", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_value(rotgen::matrix<T, 3, 8, O::value>{}.setConstant(5.12), 3, 8, T(5.12));
test_value(rotgen::matrix<T, 1, 1, O::value>{}.setConstant(2.2), 1, 1, T(2.2));
test_value(rotgen::matrix<T, 11, 12, O::value>{}.setConstant(13), 11, 12, T(13));
test_value(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>(1,1).setConstant(2, 7, 5.6), 2, 7, T(5.6));
test_value(rotgen::matrix<T, 2, 2, O::value>{}.setConstant(2, 2, 2.0), 2, 2, T(2.0));
test_value(rotgen::matrix<T, 9,rotgen::Dynamic, O::value>(9,1).setConstant(9, 3, 1.1), 9, 3, T(1.1));
test_value(rotgen::matrix<T,rotgen::Dynamic, 9, O::value>(1,9).setConstant(5, 9, 42), 5, 9,T(42));
test_value(rotgen::matrix<T, 3, 8, O::value>::Constant(5.12), 3, 8, T(5.12));
test_value(rotgen::matrix<T, 1, 1, O::value>::Constant(2.2), 1, 1, T(2.2));
test_value(rotgen::matrix<T, 11, 12, O::value>::Constant(13), 11, 12, T(13));
@ -62,6 +98,14 @@ TTS_CASE_TPL("Test constant", rotgen::tests::types)
TTS_CASE_TPL("Test random", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_random(rotgen::matrix<T, 2, 3, O::value>{}.setRandom(), 2, 3);
test_random(rotgen::matrix<T, 1, 1, O::value>{}.setRandom(), 1, 1);
test_random(rotgen::matrix<T, 11, 17, O::value>{}.setRandom(), 11, 17);
test_random(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>{1,1}.setRandom(7, 3), 7, 3);
test_random(rotgen::matrix<T, 2, 2, O::value>{}.setRandom(2, 2), 2, 2);
test_random(rotgen::matrix<T, 4,rotgen::Dynamic, O::value>{4,1}.setRandom(4, 3), 4, 3);
test_random(rotgen::matrix<T,rotgen::Dynamic, 5, O::value>{1,5}.setRandom(5, 5), 5, 5);
test_random(rotgen::matrix<T, 2, 3, O::value>::Random(), 2, 3);
test_random(rotgen::matrix<T, 1, 1, O::value>::Random(), 1, 1);
test_random(rotgen::matrix<T, 11, 17, O::value>::Random(), 11, 17);
@ -74,6 +118,14 @@ TTS_CASE_TPL("Test random", rotgen::tests::types)
TTS_CASE_TPL("Test identity", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_identity(rotgen::matrix<T, 4, 5, O::value>{}.setIdentity(), 4, 5);
test_identity(rotgen::matrix<T, 1, 1, O::value>{}.setIdentity(), 1, 1);
test_identity(rotgen::matrix<T, 21, 3, O::value>{}.setIdentity(), 21, 3);
test_identity(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>{1,1}.setIdentity(2, 7), 2, 7);
test_identity(rotgen::matrix<T, 2, 2, O::value>{}.setIdentity(2, 2), 2, 2);
test_identity(rotgen::matrix<T, 3,rotgen::Dynamic, O::value>{3,1}.setIdentity(3, 3), 3, 3);
test_identity(rotgen::matrix<T,rotgen::Dynamic, 11, O::value>{1,11}.setIdentity(5, 11), 5, 11);
test_identity(rotgen::matrix<T, 4, 5, O::value>::Identity(), 4, 5);
test_identity(rotgen::matrix<T, 1, 1, O::value>::Identity(), 1, 1);
test_identity(rotgen::matrix<T, 21, 3, O::value>::Identity(), 21, 3);

View file

@ -1,20 +0,0 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/rotgen.hpp>
#include <sstream>
TTS_CASE_TPL("Sample test", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> x({ {1,2} , {3,4} });
std::ostringstream os;
os << x;
TTS_EQUAL(os.str(), std::string{"1 2\n3 4"});
};

View file

@ -6,42 +6,32 @@
*/
//==================================================================================================
#include "unit/tests.hpp"
#include "unit/common/norms.hpp"
#include <rotgen/rotgen.hpp>
#include <Eigen/Dense>
TTS_CASE_TPL("Matrix norm-related operations", rotgen::tests::types)
TTS_CASE_TPL("Test dynamic matrix norm operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
std::vector<rotgen::tests::matrix_descriptor> test_matrices =
auto const cases = rotgen::tests::generate_matrix_references();
for (const auto& [rows, cols, fn] : cases)
{
{ 3, 3, [](int r, int c) { return r + c; }},
{ 2, 3, [](int , int ) { return T{0}; }},
{ 2, 7, [](int r, int c) { return -r*r*r - c*c - T(1.23); }},
{17, 3, [](int r, int c) { return r*c + T(0.98); }},
{ 1, 1, [](int , int ) { return 42; }},
{10, 11, [](int r, int c) { return std::tan(T(r + c)); }},
{ 1, 5, [](int r, int c) { return T(-1.5)*r + T(2.56)*c + T(3.33); }},
{ 7, 1, [](int r, int c) { return r == c ? T(1) : T(0); }},
{ 0, 0, [](int r, int c) { return r == c ? T(1) : T(0); }},
};
for (const auto& [rows, cols, fn] : test_matrices)
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> matrix(rows, cols);
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic,O::value> ref(rows, cols);
for (rotgen::Index r = 0; r < rows; ++r)
{
for (rotgen::Index c = 0; c < cols; ++c)
{
ref(r, c) = matrix(r, c) = fn(r,c);
}
}
TTS_EQUAL(matrix.norm(), ref.norm());
TTS_EQUAL(matrix.squaredNorm(), ref.squaredNorm());
TTS_EQUAL(matrix.template lpNorm<1>() , ref.template lpNorm<1>());
TTS_EQUAL(matrix.template lpNorm<2>() , ref.template lpNorm<2>());
TTS_EQUAL(matrix.template lpNorm<rotgen::Infinity>(), ref.template lpNorm<Eigen::Infinity>());
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> input(rows, cols);
rotgen::tests::prepare(rows,cols,fn,input);
rotgen::tests::check_norms_functions(input);
}
};
TTS_CASE_TPL("Test static matrix norm operations", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
auto const cases = rotgen::tests::generate_static_matrix_references();
auto process = []<typename D>(D const& desc)
{
rotgen::matrix<T,D::rows,D::cols,O::value> input;
rotgen::tests::prepare(input.rows(),input.cols(),desc.init_fn,input);
rotgen::tests::check_norms_functions(input);
};
std::apply([&](auto const&... d) { (process(d),...);}, cases);
};

View file

@ -8,6 +8,7 @@
#define TTS_MAIN
#define TTS_CUSTOM_DRIVER_FUNCTION rotgen_main
#include "tts.hpp"
#include "unit/common/references.hpp"
#include <rotgen/detail/static_info.hpp>
#include <rotgen/config.hpp>
#include <rotgen/concepts.hpp>
@ -25,30 +26,6 @@ namespace rotgen::tests
, tts::types<float ,constant<RowMajor>>
, tts::types<double,constant<RowMajor>>
>;
struct matrix_descriptor
{
rotgen::Index rows, cols;
std::function<double(std::size_t,std::size_t)> init_fn;
};
template<typename MatrixType>
struct matrix_block_test_case
{
rotgen::Index rows, cols;
std::function<typename MatrixType::scalar_type(std::size_t, rotgen::Index)> init_fn;
rotgen::Index i0, j0, ni, nj;
};
template<typename MatrixType, rotgen::Index NI, rotgen::Index NJ>
struct static_matrix_block_test_case
{
rotgen::Index rows, cols;
std::function<typename MatrixType::scalar_type(std::size_t, rotgen::Index)> init_fn;
static constexpr rotgen::Index ni = NI;
static constexpr rotgen::Index nj = NJ;
rotgen::Index i0, j0;
};
}
#include <iostream>
@ -56,7 +33,8 @@ namespace rotgen::tests
template<typename T>
constexpr bool verify_rotgen_reentrance(T const&)
{
return rotgen::concepts::entity<T>;
if constexpr(rotgen::use_expression_templates) return true;
else return rotgen::concepts::entity<T>;
}
int main(int argc, char const **argv)