Implements block typs and related functions - First part

Co-authored-by: Karen <kkaspar@codereckons.com>
Co-authored-by: Joel FALCOU <jfalcou@codereckons.com>

See merge request oss/rotgen!9
This commit is contained in:
Joel Falcou 2025-06-12 13:38:31 +02:00
commit b868398a77
28 changed files with 1814 additions and 114 deletions

View file

@ -30,6 +30,7 @@ endif()
##======================================================================================================================
set ( SOURCES
src/matrix.cpp
src/block.cpp
)
##======================================================================================================================

197
include/rotgen/block.hpp Normal file
View file

@ -0,0 +1,197 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/impl/block.hpp>
#include <rotgen/matrix.hpp>
#include <initializer_list>
#include <cassert>
namespace rotgen
{
template<typename Ref, int Rows = Dynamic, int Cols = Dynamic, bool Inner = false, int ForceStorageOrder = -1>
class block : public find_block<Ref>
{
using parent = find_block<Ref>;
public:
using scalar_type = typename Ref::scalar_type;
static constexpr int storage_order = (ForceStorageOrder == -1) ? Ref::storage_order : ForceStorageOrder;
using concrete_type = matrix<scalar_type,Rows,Cols,storage_order>;
static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols;
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)
{}
block(Ref& r, std::size_t i0, std::size_t j0) requires(Rows != -1 && Cols != -1)
: parent(r,i0,j0,Rows,Cols)
{}
block(parent const& base) : parent(base) {}
/*
block transpose() const
{
return block(static_cast<parent const&>(*this).transpose());
}
block conjugate() const
{
return block(static_cast<parent const&>(*this).conjugate());
}
block adjoint() const
{
return block(static_cast<parent const&>(*this).adjoint());
}
*/
friend bool operator==(block const& lhs, block const& rhs)
{
return static_cast<parent const&>(lhs) == static_cast<parent const&>(rhs);
}
block& operator+=(block const& rhs)
{
static_cast<parent&>(*this) += static_cast<parent const&>(rhs);
return *this;
}
block& operator-=(block const& rhs)
{
static_cast<parent&>(*this) -= static_cast<parent const&>(rhs);
return *this;
}
concrete_type operator-() const
{
return concrete_type(static_cast<parent const&>(*this).operator-());
}
block& operator*=(block const& rhs)
{
static_cast<parent&>(*this) *= static_cast<parent const&>(rhs);
return *this;
}
block& operator*=(scalar_type rhs)
{
static_cast<parent&>(*this) *= rhs;
return *this;
}
block& operator/=(scalar_type rhs)
{
static_cast<parent&>(*this) /= rhs;
return *this;
}
static concrete_type Zero()
requires (Rows != -1 && Cols != -1)
{
return parent::Zero(Rows, Cols);
}
static concrete_type Zero(int rows, int cols)
{
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size");
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size");
return parent::Zero(rows, cols);
}
static concrete_type Constant(scalar_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)
{
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<double>(value));
}
static concrete_type Random()
requires (Rows != -1 && Cols != -1)
{
return parent::Random(Rows, Cols);
}
static concrete_type Random(int rows, int cols)
{
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size");
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size");
return parent::Random(rows, cols);
}
static concrete_type Identity()
requires (Rows != -1 && Cols != -1)
{
return parent::Identity(Rows, Cols);
}
static concrete_type Identity(int rows, int cols)
{
if constexpr(Rows != -1) assert(rows == Rows && "Mismatched between dynamic and static row size");
if constexpr(Cols != -1) assert(cols == Cols && "Mismatched between dynamic and static column size");
return parent::Identity(rows, cols);
}
template<int P>
double lpNorm() const
{
assert(P == 1 || P == 2 || P == Infinity);
return parent::lpNorm(P);
}
};
/*
template<typename S, int R, int C, int O, int MR, int MC>
block<S,R,C,O,MR,MC> operator+(block<S,R,C,O,MR,MC> const& lhs, block<S,R,C,O,MR,MC> const& rhs)
{
block<S,R,C,O,MR,MC> that(lhs);
return that += rhs;
}
template<typename S, int R, int C, int O, int MR, int MC>
block<S,R,C,O,MR,MC> operator-(block<S,R,C,O,MR,MC> const& lhs, block<S,R,C,O,MR,MC> const& rhs)
{
block<S,R,C,O,MR,MC> that(lhs);
return that -= rhs;
}
template<typename S, int R, int C, int O, int MR, int MC>
block<S,R,C,O,MR,MC> operator*(block<S,R,C,O,MR,MC> const& lhs, block<S,R,C,O,MR,MC> const& rhs)
{
block<S,R,C,O,MR,MC> that(lhs);
return that *= rhs;
}
template<typename S, int R, int C, int O, int MR, int MC>
block<S,R,C,O,MR,MC> operator*(block<S,R,C,O,MR,MC> const& lhs, double rhs)
{
block<S,R,C,O,MR,MC> that(lhs);
return that *= rhs;
}
template<typename S, int R, int C, int O, int MR, int MC>
block<S,R,C,O,MR,MC> operator*(double lhs, block<S,R,C,O,MR,MC> const& rhs)
{
return rhs * lhs;
}
template<typename S, int R, int C, int O, int MR, int MC>
block<S,R,C,O,MR,MC> operator/(block<S,R,C,O,MR,MC> const& lhs, double rhs)
{
block<S,R,C,O,MR,MC> that(lhs);
return that /= rhs;
}
*/
}

235
include/rotgen/extract.hpp Normal file
View file

@ -0,0 +1,235 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/matrix.hpp>
#include <rotgen/block.hpp>
namespace rotgen
{
template< typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto extract(matrix<S,R,C,Opts,MaxR,MaxC>& m, int i0, int j0,int ni, int nj)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m, i0,j0,ni,nj);
}
template< int NI, int NJ
, typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto extract(matrix<S,R,C,Opts,MaxR,MaxC>& m, int i0, int j0)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,NI,NJ>(m,i0,j0);
}
template< typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto topLeftCorner(matrix<S,R,C,Opts,MaxR,MaxC>& m, int ni, int nj)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m,0,0,ni,nj);
}
template< typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto topRightCorner(matrix<S,R,C,Opts,MaxR,MaxC>& m, int ni, int nj)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m,0,m.cols()-nj,ni,nj);
}
template< typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto bottomLeftCorner(matrix<S,R,C,Opts,MaxR,MaxC>& m, int ni, int nj)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m,m.rows()-ni,0,ni,nj);
}
template< typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto bottomRightCorner(matrix<S,R,C,Opts,MaxR,MaxC>& m, int ni, int nj)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m,m.rows()-ni,m.cols()-nj,ni,nj);
}
template< typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto topRows(matrix<S,R,C,Opts,MaxR,MaxC>& m, int ni)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m,0,0,ni,m.cols());
}
template< typename S, int R , int C,
int Opts , int MaxR, int MaxC
>
auto middleRows(matrix<S,R,C,Opts,MaxR,MaxC>& m, int i0, int ni)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m,i0,0,ni,m.cols());
}
template< typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto bottomRows(matrix<S,R,C,Opts,MaxR,MaxC>& m, int ni)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m,m.rows()-ni,0,ni,m.cols());
}
template< typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto leftCols(matrix<S,R,C,Opts,MaxR,MaxC>& m, int nj)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m,0,0,m.rows(),nj);
}
template< typename S, int R , int C,
int Opts , int MaxR, int MaxC
>
auto middleCols(matrix<S,R,C,Opts,MaxR,MaxC>& m, int j0, int nj)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m,0,j0,m.rows(),nj);
}
template< typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto rightCols(matrix<S,R,C,Opts,MaxR,MaxC>& m, int nj)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base>(m,0,m.cols()-nj,m.rows(),nj);
}
template< typename S, int R, int C
, int Opts , int MaxR, int MaxC
>
auto row(matrix<S,R,C,Opts,MaxR,MaxC>& m, int i0)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,1, -1, false, 1>(m,i0,0, 1, m.cols());
}
template< typename S, int R, int C
, int Opts , int MaxR, int MaxC
>
auto col(matrix<S,R,C,Opts,MaxR,MaxC>& m, int j0)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,-1,1, false, 0>(m,0,j0, m.rows(), 1);
}
template< int NI, typename S, int R, int C,
int Opts, int MaxR, int MaxC
>
auto topRows(matrix<S,R,C,Opts,MaxR,MaxC>& m)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,NI,-1>(m,0,0, NI, m.cols());
}
template< int NI, typename S, int R, int C,
int Opts, int MaxR, int MaxC
>
auto bottomRows(matrix<S,R,C,Opts,MaxR,MaxC>& m)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,NI,-1>(m,m.rows()-NI,0, NI, m.cols());
}
template< int NI, typename S, int R, int C,
int Opts , int MaxR, int MaxC
>
auto middleRows(matrix<S,R,C,Opts,MaxR,MaxC>& m, int i0)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,NI,-1>(m,i0,0, NI, m.cols());
}
template< int NJ, typename S, int R, int C,
int Opts, int MaxR, int MaxC
>
auto leftCols(matrix<S,R,C,Opts,MaxR,MaxC>& m)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,-1,NJ>(m,0,0, m.rows(), NJ);
}
template< int NJ, typename S, int R, int C,
int Opts, int MaxR, int MaxC
>
auto rightCols(matrix<S,R,C,Opts,MaxR,MaxC>& m)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,-1,NJ>(m,0,m.cols()-NJ, m.rows(), NJ);
}
template< int NJ, typename S, int R, int C,
int Opts , int MaxR, int MaxC
>
auto middleCols(matrix<S,R,C,Opts,MaxR,MaxC>& m, int j0)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,-1,NJ>(m,0,j0, m.rows(), NJ);
}
template< int NI, int NJ
, typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto topLeftCorner(matrix<S,R,C,Opts,MaxR,MaxC>& m)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,NI,NJ>(m,0,0);
}
template< int NI, int NJ
, typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto topRightCorner(matrix<S,R,C,Opts,MaxR,MaxC>& m)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,NI,NJ>(m,0,m.cols()-NJ);
}
template< int NI, int NJ
, typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto bottomLeftCorner(matrix<S,R,C,Opts,MaxR,MaxC>& m)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,NI,NJ>(m,m.rows()-NI,0);
}
template< int NI, int NJ
, typename S, int R , int C
, int Opts , int MaxR, int MaxC
>
auto bottomRightCorner(matrix<S,R,C,Opts,MaxR,MaxC>& m)
{
using base = matrix<S,R,C,Opts,MaxR,MaxC>;
return block<base,NI,NJ>(m,m.rows()-NI,m.cols()-NJ);
}
}

View file

@ -0,0 +1,64 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/detail/generators.hpp>
#include <rotgen/detail/static_info.hpp>
#include <rotgen/impl/matrix.hpp>
#include <initializer_list>
#include <cstddef>
#include <memory>
namespace rotgen
{
#define SIZE 64
#define TYPE double
#define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/block_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/block_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#undef SIZE
#undef TYPE
#define SIZE 32
#define TYPE float
#define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/block_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/block_model.hpp>
#undef CLASSNAME
#undef SOURCENAME
#undef SIZE
#undef TYPE
template<typename Scalar,int Options> struct find_block_impl;
template<> struct find_block_impl<float , ColMajor> { using type = block_impl32_col; };
template<> struct find_block_impl<float , RowMajor> { using type = block_impl32_row; };
template<> struct find_block_impl<double, ColMajor> { using type = block_impl64_col; };
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;
}

View file

@ -0,0 +1,81 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
//==================================================================================================
/*
This file is a X-File to generate various block_impl_* declarations variant
*/
//==================================================================================================
class CLASSNAME
{
public:
CLASSNAME(SOURCENAME& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj);
CLASSNAME(CLASSNAME const& other);
CLASSNAME(CLASSNAME&&) noexcept;
CLASSNAME& operator=(CLASSNAME const& other);
CLASSNAME& operator=(CLASSNAME&&) noexcept;
~CLASSNAME();
std::size_t rows() const;
std::size_t cols() const;
std::size_t size() const;
// CLASSNAME transpose() const;
// CLASSNAME conjugate() const;
// CLASSNAME adjoint() const;
// void transposeInPlace();
// void adjointInPlace();
TYPE sum() const;
TYPE prod() const;
TYPE mean() const;
TYPE trace() const;
TYPE maxCoeff() const;
TYPE minCoeff() const;
TYPE maxCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const;
TYPE minCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const;
TYPE squaredNorm() const;
TYPE norm() const;
TYPE lpNorm(int p) const;
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;
CLASSNAME& operator+=(CLASSNAME const& rhs);
CLASSNAME& operator-=(CLASSNAME const& rhs);
SOURCENAME operator-() const;
CLASSNAME& operator*=(CLASSNAME const& rhs);
CLASSNAME& operator*=(TYPE d);
CLASSNAME& operator/=(TYPE d);
friend std::ostream& operator<<(std::ostream&,CLASSNAME const&);
friend bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs);
const TYPE* data() const;
static SOURCENAME Zero(std::size_t r, std::size_t c) { return SOURCENAME::Zero(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); }
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

@ -18,13 +18,13 @@ namespace rotgen
#define SIZE 64
#define TYPE double
#define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/matrix_model.hpp>
#undef MATRIX
#undef CLASSNAME
#define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/matrix_model.hpp>
#undef MATRIX
#undef CLASSNAME
#undef SIZE
#undef TYPE
@ -32,13 +32,13 @@ namespace rotgen
#define SIZE 32
#define TYPE float
#define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include <rotgen/impl/matrix_model.hpp>
#undef MATRIX
#undef CLASSNAME
#define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include <rotgen/impl/matrix_model.hpp>
#undef MATRIX
#undef CLASSNAME
#undef SIZE
#undef TYPE

View file

@ -8,24 +8,24 @@
//==================================================================================================
/*
This file is a X-File to generate various matrix_impl_* definitions variant
This file is a X-File to generate various matrix_impl_* declarations variant
*/
//==================================================================================================
class MATRIX
class CLASSNAME
{
public:
MATRIX(std::size_t rows = 0, std::size_t cols = 0);
MATRIX(std::size_t rows, std::size_t cols,std::initializer_list<TYPE> init);
CLASSNAME(std::size_t rows = 0, std::size_t cols = 0);
CLASSNAME(std::size_t rows, std::size_t cols,std::initializer_list<TYPE> init);
MATRIX(std::initializer_list<std::initializer_list<TYPE>> init);
CLASSNAME(std::initializer_list<std::initializer_list<TYPE>> init);
MATRIX(MATRIX const& other);
MATRIX(MATRIX&&) noexcept;
CLASSNAME(CLASSNAME const& other);
CLASSNAME(CLASSNAME&&) noexcept;
MATRIX& operator=(MATRIX const& other);
MATRIX& operator=(MATRIX&&) noexcept;
CLASSNAME& operator=(CLASSNAME const& other);
CLASSNAME& operator=(CLASSNAME&&) noexcept;
~MATRIX();
~CLASSNAME();
std::size_t rows() const;
std::size_t cols() const;
@ -34,9 +34,9 @@ class MATRIX
void resize(std::size_t new_rows, std::size_t new_cols);
void conservativeResize(std::size_t new_rows, std::size_t new_cols);
MATRIX transpose() const;
MATRIX conjugate() const;
MATRIX adjoint() const;
CLASSNAME transpose() const;
CLASSNAME conjugate() const;
CLASSNAME adjoint() const;
void transposeInPlace();
void adjointInPlace();
@ -60,24 +60,28 @@ class MATRIX
TYPE& operator()(std::size_t index);
TYPE const& operator()(std::size_t index) const;
MATRIX& operator+=(MATRIX const& rhs);
MATRIX& operator-=(MATRIX const& rhs);
MATRIX operator-() const;
MATRIX& operator*=(MATRIX const& rhs);
MATRIX& operator*=(TYPE d);
MATRIX& operator/=(TYPE d);
CLASSNAME& operator+=(CLASSNAME const& rhs);
CLASSNAME& operator-=(CLASSNAME const& rhs);
CLASSNAME operator-() const;
CLASSNAME& operator*=(CLASSNAME const& rhs);
CLASSNAME& operator*=(TYPE d);
CLASSNAME& operator/=(TYPE d);
friend std::ostream& operator<<(std::ostream&,MATRIX const&);
friend bool operator==(MATRIX const& lhs, MATRIX const& rhs);
friend std::ostream& operator<<(std::ostream&,CLASSNAME const&);
friend bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs);
const TYPE* data() const;
static MATRIX Zero(std::size_t rows, std::size_t cols);
static MATRIX Constant(std::size_t rows, std::size_t cols, TYPE value);
static MATRIX Random(std::size_t rows, std::size_t cols);
static MATRIX Identity(std::size_t rows, std::size_t cols);
static CLASSNAME Zero(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);
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,67 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <cstddef>
#include <memory>
#include <rotgen/impl/matrix.hpp>
#include <Eigen/Dense>
namespace rotgen
{
//==================================================================================================
// Internal payload - Requried for cross-referencing from block_impl*
//==================================================================================================
struct matrix_impl64_col::payload
{
using data_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>;
data_type data;
payload(std::size_t r=0, std::size_t c=0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<double>> init) : data(init) {}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> ref) { data = ref; }
};
struct matrix_impl64_row::payload
{
using data_type = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>;
data_type data;
payload(std::size_t r=0, std::size_t c=0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<double>> init) : data(init) {}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> ref) { data = ref; }
};
struct matrix_impl32_col::payload
{
using data_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor>;
data_type data;
payload(std::size_t r=0, std::size_t c=0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<float>> init) : data(init) {}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> ref) { data = ref; }
};
struct matrix_impl32_row::payload
{
using data_type = Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>;
data_type data;
payload(std::size_t r=0, std::size_t c=0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<float>> init) : data(init) {}
payload(data_type&& matrix) : data(std::move(matrix)) {}
void assign(Eigen::Block<data_type> ref) { data = ref; }
};
}

View file

@ -20,10 +20,11 @@ namespace rotgen
>
class matrix : public find_matrix<Scalar,Options>
{
using parent = find_matrix<Scalar,Options>;
using parent = find_matrix<Scalar,Options>;
public:
using value_type = Scalar;
using scalar_type = Scalar;
static constexpr auto storage_order = Options & 1;
matrix() : parent(Rows==-1?0:Rows,Cols==-1?0:Cols) {}

12
include/rotgen/rotgen.hpp Normal file
View file

@ -0,0 +1,12 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/matrix.hpp>
#include <rotgen/block.hpp>
#include <rotgen/extract.hpp>

58
src/block.cpp Normal file
View file

@ -0,0 +1,58 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include <rotgen/detail/generators.hpp>
#include <rotgen/impl/block.hpp>
#include <rotgen/impl/payload.hpp>
#include <Eigen/Dense>
namespace rotgen
{
#define SIZE 64
#define TYPE double
#define STORAGE_ORDER Eigen::ColMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "block_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "block_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(block_impl,SIZE,_col)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "block_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor
#define CLASSNAME ROTGEN_MATRIX_NAME(block_impl,SIZE,_row)
#define SOURCENAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "block_model.cpp"
#undef CLASSNAME
#undef SOURCENAME
#undef STORAGE_ORDER
#undef SIZE
#undef TYPE
}

172
src/block_model.cpp Normal file
View file

@ -0,0 +1,172 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
//==================================================================================================
/*
This file is a X-File to generate various block_impl_* definitions variant
*/
//==================================================================================================
//==================================================================================================
// Internal payload
//==================================================================================================
struct CLASSNAME::payload
{
using base_type = Eigen::Matrix<TYPE,Eigen::Dynamic,Eigen::Dynamic,STORAGE_ORDER>;
using data_type = Eigen::Block<base_type>;
data_type data;
payload (data_type const& o) : data(o) {}
payload (base_type& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
: data(r,i0,j0,ni,nj)
{}
};
//==================================================================================================
// Constructors & Special Members
//==================================================================================================
CLASSNAME::CLASSNAME(SOURCENAME& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
: storage_(std::make_unique<payload>(r.storage()->data,i0,j0,ni,nj))
{}
CLASSNAME::CLASSNAME(CLASSNAME const& o) : storage_(std::make_unique<payload>(o.storage_->data))
{}
CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
{
if (this != &o) storage_->data = o.storage_->data;
return *this;
}
CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default;
CLASSNAME& CLASSNAME::operator=(CLASSNAME&&) noexcept = default;
CLASSNAME::~CLASSNAME() = default;
//==================================================================================================
// Matrix API
//==================================================================================================
std::size_t CLASSNAME::rows() const { return static_cast<std::size_t>(storage_->data.rows()); }
std::size_t CLASSNAME::cols() const { return static_cast<std::size_t>(storage_->data.cols()); }
std::size_t CLASSNAME::size() const { return static_cast<std::size_t>(storage_->data.size()); }
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); }
*/
const TYPE* CLASSNAME::data() const { return storage_->data.data(); }
/*
CLASSNAME CLASSNAME::transpose() const
{
CLASSNAME result(*this);
result.storage_->data.transposeInPlace();
return result;
}
CLASSNAME CLASSNAME::conjugate() const
{
CLASSNAME result(*this);
result.storage_->data = storage_->data.conjugate();
return result;
}
CLASSNAME CLASSNAME::adjoint() const
{
CLASSNAME result(*this);
result.storage_->data.adjointInPlace();
return result;
}
void CLASSNAME::transposeInPlace()
{
storage_->data.transposeInPlace();
}
void CLASSNAME::adjointInPlace()
{
storage_->data.adjointInPlace();
}
*/
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(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.minCoeff(row, col); }
TYPE CLASSNAME::maxCoeff(std::ptrdiff_t* row, std::ptrdiff_t* 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>();
}
//==================================================================================================
// 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;
}
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;
}
SOURCENAME CLASSNAME::operator-() const
{
SOURCENAME result;
result.storage()->assign(storage_->data);
return -result;
}
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;
}

View file

@ -7,6 +7,7 @@
//==================================================================================================
#include <rotgen/detail/generators.hpp>
#include <rotgen/impl/matrix.hpp>
#include <rotgen/impl/payload.hpp>
#include <Eigen/Dense>
namespace rotgen
@ -15,15 +16,15 @@ namespace rotgen
#define TYPE double
#define STORAGE_ORDER Eigen::ColMajor
#define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "matrix_model.cpp"
#undef MATRIX
#undef CLASSNAME
#undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor
#define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "matrix_model.cpp"
#undef MATRIX
#undef CLASSNAME
#undef STORAGE_ORDER
#undef SIZE
@ -33,15 +34,15 @@ namespace rotgen
#define TYPE float
#define STORAGE_ORDER Eigen::ColMajor
#define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_col)
#include "matrix_model.cpp"
#undef MATRIX
#undef CLASSNAME
#undef STORAGE_ORDER
#define STORAGE_ORDER Eigen::RowMajor
#define MATRIX ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#define CLASSNAME ROTGEN_MATRIX_NAME(matrix_impl,SIZE,_row)
#include "matrix_model.cpp"
#undef MATRIX
#undef CLASSNAME
#undef STORAGE_ORDER
#undef SIZE

View file

@ -12,127 +12,114 @@
*/
//==================================================================================================
//==================================================================================================
// Internal payload
//==================================================================================================
struct MATRIX::payload
{
using data_type = Eigen::Matrix<TYPE,Eigen::Dynamic,Eigen::Dynamic,STORAGE_ORDER>;
data_type data;
payload(std::size_t r=0, std::size_t c=0) : data(r, c) {}
payload(std::initializer_list<std::initializer_list<TYPE>> init) : data(init) {}
payload(data_type&& matrix) : data(std::move(matrix)) {}
};
//==================================================================================================
// Constructors & Special Members
//==================================================================================================
MATRIX::MATRIX(std::size_t r, std::size_t c) : storage_(std::make_unique<payload>(r,c)) {}
CLASSNAME::CLASSNAME(std::size_t r, std::size_t c) : storage_(std::make_unique<payload>(r,c)) {}
MATRIX::MATRIX(std::initializer_list<std::initializer_list<TYPE>> init)
CLASSNAME::CLASSNAME(std::initializer_list<std::initializer_list<TYPE>> init)
: storage_(std::make_unique<payload>(init))
{}
MATRIX::MATRIX(std::size_t r, std::size_t c,std::initializer_list<TYPE> init)
: MATRIX(r,c)
CLASSNAME::CLASSNAME(std::size_t r, std::size_t c,std::initializer_list<TYPE> init)
: CLASSNAME(r,c)
{
auto first = init.begin();
for(std::size_t i=0; i < init.size(); i++)
(*this)(i) = first[i];
}
MATRIX::MATRIX(MATRIX const& o)
: MATRIX(o.rows(),o.cols())
CLASSNAME::CLASSNAME(CLASSNAME const& o)
: CLASSNAME(o.rows(),o.cols())
{
storage_->data = o.storage_->data;
}
MATRIX::MATRIX(MATRIX&&) noexcept = default;
CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default;
MATRIX& MATRIX::operator=(MATRIX const& o)
CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o)
{
if (this != &o) storage_->data = o.storage_->data;
return *this;
}
MATRIX& MATRIX::operator=(MATRIX&&) noexcept = default;
CLASSNAME& CLASSNAME::operator=(CLASSNAME&&) noexcept = default;
MATRIX::~MATRIX() = default;
CLASSNAME::~CLASSNAME() = default;
//==================================================================================================
// Matrix API
//==================================================================================================
std::size_t MATRIX::rows() const { return static_cast<std::size_t>(storage_->data.rows()); }
std::size_t MATRIX::cols() const { return static_cast<std::size_t>(storage_->data.cols()); }
std::size_t MATRIX::size() const { return static_cast<std::size_t>(storage_->data.size()); }
std::size_t CLASSNAME::rows() const { return static_cast<std::size_t>(storage_->data.rows()); }
std::size_t CLASSNAME::cols() const { return static_cast<std::size_t>(storage_->data.cols()); }
std::size_t CLASSNAME::size() const { return static_cast<std::size_t>(storage_->data.size()); }
void MATRIX::resize(std::size_t new_rows, std::size_t new_cols)
void CLASSNAME::resize(std::size_t new_rows, std::size_t new_cols)
{
storage_->data.resize(new_rows, new_cols);
}
void MATRIX::conservativeResize(std::size_t new_rows, std::size_t new_cols)
void CLASSNAME::conservativeResize(std::size_t new_rows, std::size_t new_cols)
{
storage_->data.conservativeResize(new_rows, new_cols);
}
TYPE& MATRIX::operator()(std::size_t i, std::size_t j) { return storage_->data(i,j); }
TYPE const& MATRIX::operator()(std::size_t i, std::size_t j) const { return storage_->data(i,j); }
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& MATRIX::operator()(std::size_t index) { return storage_->data(index); }
TYPE const& MATRIX::operator()(std::size_t index) const { return storage_->data(index); }
TYPE& CLASSNAME::operator()(std::size_t index) { return storage_->data(index); }
TYPE const& CLASSNAME::operator()(std::size_t index) const { return storage_->data(index); }
const TYPE* MATRIX::data() const { return storage_->data.data(); }
const TYPE* CLASSNAME::data() const { return storage_->data.data(); }
MATRIX MATRIX::transpose() const
CLASSNAME CLASSNAME::transpose() const
{
MATRIX result(*this);
CLASSNAME result(*this);
result.storage_->data.transposeInPlace();
return result;
}
MATRIX MATRIX::conjugate() const
CLASSNAME CLASSNAME::conjugate() const
{
MATRIX result(*this);
CLASSNAME result(*this);
result.storage_->data = storage_->data.conjugate();
return result;
}
MATRIX MATRIX::adjoint() const
CLASSNAME CLASSNAME::adjoint() const
{
MATRIX result(*this);
CLASSNAME result(*this);
result.storage_->data.adjointInPlace();
return result;
}
void MATRIX::transposeInPlace()
void CLASSNAME::transposeInPlace()
{
storage_->data.transposeInPlace();
}
void MATRIX::adjointInPlace()
void CLASSNAME::adjointInPlace()
{
storage_->data.adjointInPlace();
}
TYPE MATRIX::sum() const { return storage_->data.sum(); }
TYPE MATRIX::prod() const { return storage_->data.prod(); }
TYPE MATRIX::mean() const { return storage_->data.mean(); }
TYPE MATRIX::trace() const { return storage_->data.trace(); }
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 MATRIX::minCoeff() const { return storage_->data.minCoeff(); }
TYPE MATRIX::maxCoeff() const { return storage_->data.maxCoeff(); }
TYPE CLASSNAME::minCoeff() const { return storage_->data.minCoeff(); }
TYPE CLASSNAME::maxCoeff() const { return storage_->data.maxCoeff(); }
TYPE MATRIX::minCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.minCoeff(row, col); }
TYPE MATRIX::maxCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.maxCoeff(row, col); }
TYPE CLASSNAME::minCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.minCoeff(row, col); }
TYPE CLASSNAME::maxCoeff(std::ptrdiff_t* row, std::ptrdiff_t* col) const { return storage_->data.maxCoeff(row, col); }
TYPE MATRIX::squaredNorm() const { return storage_->data.squaredNorm(); }
TYPE MATRIX::norm() const { return storage_->data.norm(); }
TYPE CLASSNAME::squaredNorm() const { return storage_->data.squaredNorm(); }
TYPE CLASSNAME::norm() const { return storage_->data.norm(); }
TYPE MATRIX::lp_norm(int p) const
TYPE CLASSNAME::lp_norm(int p) const
{
if (p == 1) return storage_->data.lpNorm<1>();
else if (p == 2) return storage_->data.lpNorm<2>();
@ -142,48 +129,48 @@ TYPE MATRIX::lp_norm(int p) const
//==================================================================================================
// Operators
//==================================================================================================
std::ostream& operator<<(std::ostream& os,MATRIX const& m)
std::ostream& operator<<(std::ostream& os,CLASSNAME const& m)
{
return os << m.storage_->data;
}
bool operator==(MATRIX const& lhs, MATRIX const& rhs)
bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs)
{
return lhs.storage_->data == rhs.storage_->data;
}
MATRIX& MATRIX::operator+=(MATRIX const& rhs)
CLASSNAME& CLASSNAME::operator+=(CLASSNAME const& rhs)
{
storage_->data += rhs.storage_->data;
return *this;
}
MATRIX& MATRIX::operator-=(MATRIX const& rhs)
CLASSNAME& CLASSNAME::operator-=(CLASSNAME const& rhs)
{
storage_->data -= rhs.storage_->data;
return *this;
}
MATRIX MATRIX::operator-() const
CLASSNAME CLASSNAME::operator-() const
{
MATRIX result(*this);
CLASSNAME result(*this);
result.storage_->data = -result.storage_->data;
return result;
}
MATRIX& MATRIX::operator*=(MATRIX const& rhs)
CLASSNAME& CLASSNAME::operator*=(CLASSNAME const& rhs)
{
storage_->data *= rhs.storage_->data;
return *this;
}
MATRIX& MATRIX::operator*=(TYPE s)
CLASSNAME& CLASSNAME::operator*=(TYPE s)
{
storage_->data *= s;
return *this;
}
MATRIX& MATRIX::operator/=(TYPE s)
CLASSNAME& CLASSNAME::operator/=(TYPE s)
{
storage_->data /= s;
return *this;
@ -193,30 +180,30 @@ MATRIX& MATRIX::operator/=(TYPE s)
// Static functions
//==================================================================================================
MATRIX MATRIX::Zero(std::size_t rows, std::size_t cols)
CLASSNAME CLASSNAME::Zero(std::size_t rows, std::size_t cols)
{
MATRIX m;
CLASSNAME m;
m.storage_ = std::make_unique<payload>(payload::data_type::Zero(rows, cols));
return m;
}
MATRIX MATRIX::Constant(std::size_t rows, std::size_t cols, TYPE value)
CLASSNAME CLASSNAME::Constant(std::size_t rows, std::size_t cols, TYPE value)
{
MATRIX m;
CLASSNAME m;
m.storage_ = std::make_unique<payload>(payload::data_type::Constant(rows, cols, value));
return m;
}
MATRIX MATRIX::Random(std::size_t rows, std::size_t cols)
CLASSNAME CLASSNAME::Random(std::size_t rows, std::size_t cols)
{
MATRIX m;
CLASSNAME m;
m.storage_ = std::make_unique<payload>(payload::data_type::Random(rows, cols));
return m;
}
MATRIX MATRIX::Identity(std::size_t rows, std::size_t cols)
CLASSNAME CLASSNAME::Identity(std::size_t rows, std::size_t cols)
{
MATRIX m;
CLASSNAME m;
m.storage_ = std::make_unique<payload>(payload::data_type::Identity(rows, cols));
return m;
}

View file

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

View file

@ -0,0 +1,97 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/block.hpp>
#include <rotgen/matrix.hpp>
#include <rotgen/extract.hpp>
#include <Eigen/Dense>
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 (std::size_t r = 0; r < matrix_construct.rows; ++r)
for (std::size_t 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);
}
TTS_CASE_TPL("Test dynamic block reductions", 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 =
{
{6, 5, [](auto r, auto c) {return r + c; }, 1, 2, 3, 2},
{9, 11, [](auto r, auto c) {return r + c; }, 0, 1, 4, 9},
{3, 3, [](auto , auto ) {return 0.0; }, 1, 1, 1, 1},
{1, 4, [](auto r, auto c) {return -r -c*c - 1234; }, 0, 0, 1, 1},
{4, 1, [](auto , auto ) {return 7.0; }, 2, 0, 2, 1},
{1, 1, [](auto , auto ) {return 42.0; }, 0, 0, 1, 1},
{12, 13, [](auto r, auto c) {return std::sin(r + c); }, 2, 3, 4, 5 },
{4, 9, [](auto r, auto c) {return -1.5 * r + 2.56 * c; }, 0, 1, 2, 3 },
{2, 5, [](auto r, auto c) {return (r == c ? 1.0 : 0.0); }, 1, 1, 1, 1},
};
for (const auto& test_case : test_cases)
test_dynamic_block_reductions<mat_t, T>(test_case);
};

266
test/unit/block/extract.cpp Normal file
View file

@ -0,0 +1,266 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/matrix.hpp>
#include <rotgen/extract.hpp>
template<typename EigenType, typename F>
void for_each_element(EigenType const& m, F&& f)
{
for(std::size_t i = 0; i < m.rows(); ++i)
for(std::size_t j = 0; j < m.cols(); ++j)
f(i, j, m(i,j));
}
template<typename EigenType, typename F>
void for_each_element(EigenType& m, F&& f)
{
for(std::size_t i = 0; i < m.rows(); ++i)
for(std::size_t j = 0; j < m.cols(); ++j)
f(i, j, m(i,j));
}
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);
for(std::size_t i = 0; i < matrix_construct.rows; ++i)
for(std::size_t j = 0; j < matrix_construct.cols; ++j)
matrix(i, j) = static_cast<T>(matrix_construct.init_fn(i, j));
return matrix;
}
template<typename MatrixType, typename BlockType, typename T>
void validate_block_behavior(MatrixType& matrix, BlockType& block,
std::size_t i0, std::size_t j0,
std::size_t ni, std::size_t nj)
{
TTS_EQUAL(block.rows(), ni);
TTS_EQUAL(block.cols(), nj);
TTS_EQUAL(block.size(), ni * nj);
// test block values
for_each_element(block, [&](auto i, auto j, auto val) {
TTS_EQUAL(val, matrix(i0 + i, j0 + j));
});
// test aliasing
T value = 1;
for_each_element(block, [&](auto i, auto j, auto&) {
block(i, j) = value++;
});
value = 1;
for_each_element(block, [&](auto i, auto j, auto&) {
TTS_EQUAL(matrix(i0 + i, j0 + j), value++);
});
for_each_element(block, [&](auto i, auto j, auto&) {
matrix(i0 + i, j0 + j) = T(42);
});
for_each_element(block, [&](auto&, auto&, auto val) {
TTS_EQUAL(val, T(42));
});
}
template<typename MatrixType, typename T>
void test_dynamic_block_extraction(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct)
{
MatrixType matrix = make_initialized_matrix<MatrixType, T>(matrix_construct);
auto block_main = rotgen::extract(matrix, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto block_top_left_corner = rotgen::topLeftCorner(matrix, matrix_construct.ni, matrix_construct.nj);
auto block_top_right_corner = rotgen::topRightCorner(matrix, matrix_construct.ni, matrix_construct.nj);
auto block_bottom_left_corner = rotgen::bottomLeftCorner(matrix, matrix_construct.ni, matrix_construct.nj);
auto block_bottom_right_corner = rotgen::bottomRightCorner(matrix, matrix_construct.ni, matrix_construct.nj);
auto block_top_rows = rotgen::topRows(matrix, matrix_construct.ni);
auto block_middle_rows = rotgen::middleRows(matrix, matrix_construct.i0, matrix_construct.ni);
auto block_bottom_rows = rotgen::bottomRows(matrix, matrix_construct.ni);
auto block_left_cols = rotgen::leftCols(matrix, matrix_construct.nj);
auto block_middle_cols = rotgen::middleCols(matrix, matrix_construct.j0, matrix_construct.nj);
auto block_right_cols = rotgen::rightCols(matrix, matrix_construct.nj);
auto blocks = std::make_tuple(
std::make_tuple(block_main, matrix_construct.i0, matrix_construct.j0, matrix_construct.ni, matrix_construct.nj),
std::make_tuple(block_top_left_corner, 0, 0, matrix_construct.ni, matrix_construct.nj),
std::make_tuple(block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, matrix_construct.ni, matrix_construct.nj),
std::make_tuple(block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix_construct.nj),
std::make_tuple(block_bottom_right_corner, matrix.rows() - matrix_construct.ni, matrix.cols() - matrix_construct.nj,
matrix_construct.ni, matrix_construct.nj),
std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols()),
std::make_tuple(block_middle_rows, matrix_construct.i0, 0, matrix_construct.ni, matrix.cols()),
std::make_tuple(block_bottom_rows, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix.cols()),
std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj),
std::make_tuple(block_middle_cols, 0, matrix_construct.j0, matrix.rows(), matrix_construct.nj),
std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj, matrix.rows(), matrix_construct.nj)
);
std::apply([&](auto&&... block_entries)
{
(([&]
{
auto&& [block, i_offset, j_offset, ni, nj] = block_entries;
using block_t = std::remove_reference_t<decltype(block)>;
TTS_EQUAL(block_t::RowsAtCompileTime, rotgen::Dynamic);
TTS_EQUAL(block_t::ColsAtCompileTime, rotgen::Dynamic);
TTS_EQUAL(block_t::storage_order, MatrixType::storage_order);
validate_block_behavior<MatrixType, block_t, T>(matrix, block, i_offset, j_offset, ni, nj);
})(), ...);
}, blocks);
}
template<typename MatrixType, typename T, std::size_t NI, std::size_t 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);
for (std::size_t i = 0; i < matrix_construct.rows; ++i)
for (std::size_t j = 0; j < matrix_construct.cols; ++j)
matrix(i, j) = static_cast<T>(matrix_construct.init_fn(i, j));
auto block_main = rotgen::extract<NI, NJ>(matrix, matrix_construct.i0, matrix_construct.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_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_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 blocks = std::make_tuple(
std::make_tuple(block_main, matrix_construct.i0, matrix_construct.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),
std::make_tuple(block_top_right_corner, 0, matrix.cols() - matrix_construct.nj,
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1),
std::make_tuple(block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0,
matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1),
std::make_tuple(block_bottom_right_corner, matrix.rows() - matrix_construct.ni,
matrix.cols() - matrix_construct.nj, matrix_construct.ni,
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,
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,
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,
1, matrix.cols(), 1, rotgen::Dynamic, 1),
std::make_tuple(block_col, 0, matrix_construct.j0,
matrix.rows(), 1, rotgen::Dynamic, 1, 0)
);
std::apply([&](auto&&... block_entries)
{
(([&]
{
auto&& [block, i_offset, j_offset, ni, nj, rows_ct, cols_ct, storage_order] = block_entries;
using block_t = std::remove_reference_t<decltype(block)>;
TTS_EQUAL(block_t::RowsAtCompileTime, rows_ct);
TTS_EQUAL(block_t::ColsAtCompileTime, cols_ct);
auto expected_storage_order = (storage_order == -1) ? MatrixType::storage_order : storage_order;
TTS_EQUAL(block_t::storage_order, expected_storage_order);
validate_block_behavior<MatrixType, block_t, T>(matrix, block, i_offset, j_offset, ni, nj);
})(), ...);
}, blocks);
}
TTS_CASE_TPL("Check all dynamic block extractions on a dynamic row-major matrix", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value, 1>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> cases = {
{ 6, 11, [](std::size_t i, std::size_t j) { return T(i * 10 + j); }, 1, 2, 3, 2 },
{ 7, 10, [](std::size_t i, std::size_t j) { return T(std::sin(i + j)); }, 4, 4, 3, 3 },
{ 5, 5, [](std::size_t i, std::size_t j) { return T((i + j) % 7); }, 0, 0, 5, 5 },
{ 9, 14, [](std::size_t i, std::size_t 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)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
using mat_t = rotgen::matrix<T,4,5,O::value, 0>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> cases = {
{ 4, 5, [](std::size_t i, std::size_t j) { return T(2*i + j*j*j - 42); }, 1, 2, 3, 2 },
{ 4, 5, [](std::size_t i, std::size_t j) { return T(std::tan(i*i*j)); }, 0, 1, 2, 1 },
{ 4, 5, [](std::size_t i, std::size_t j) { return T((i*i + j*j) / 6); }, 2, 0, 0, 0 }
};
for (auto const& matrix_case : cases) {
test_dynamic_block_extraction<mat_t, T>(matrix_case);
}
};
TTS_CASE_TPL("Check all static block extractions", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
using mat_t = rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value, 1>;
test_static_block_extraction<mat_t, T, 1, 2>(
rotgen::tests::static_matrix_block_test_case<mat_t, 1, 2>{
11, 11,
[](std::size_t i, std::size_t 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,
[](std::size_t i, std::size_t 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,
[](std::size_t i, std::size_t j) { return T((i + j) % 9); },
0, 0
}
);
};

49
test/unit/block/norms.cpp Normal file
View file

@ -0,0 +1,49 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/matrix.hpp>
#include <rotgen/extract.hpp>
#include <Eigen/Dense>
TTS_CASE_TPL("Matrix norm-related 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 =
{
{6, 5, [](auto r, auto c) {return r + c; }, 1, 2, 3, 2},
{9, 11, [](auto r, auto c) {return r + c; }, 0, 1, 4, 9},
{3, 3, [](auto , auto ) {return 0.0; }, 1, 1, 1, 1},
{1, 4, [](auto r, auto c) {return -r -c*c - 1234; }, 0, 0, 1, 1},
{4, 1, [](auto , auto ) {return 7.0; }, 2, 0, 2, 1},
{1, 1, [](auto , auto ) {return 42.0; }, 0, 0, 1, 1},
{12, 13, [](auto r, auto c) {return std::sin(r + c); }, 2, 3, 4, 5 },
{4, 9, [](auto r, auto c) {return -1.5 * r + 2.56 * c; }, 0, 1, 2, 3 },
{2, 5, [](auto r, auto 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 (std::size_t r = 0; r < rows; ++r)
for (std::size_t 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>());
}
};

View file

@ -0,0 +1,274 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/matrix.hpp>
#include <rotgen/extract.hpp>
#include <Eigen/Dense>
template <typename MatrixType, typename T>
void test_block_matrix_operations(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct,
auto b_init_fn, auto self_ops)
{
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);
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
{
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
{
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));
}
}
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 result_block = ops(a_block, b_block);
auto ref_result_block = ops(ref_a_block, ref_b_block);
for (std::size_t r = 0; r < matrix_construct.ni; ++r)
for (std::size_t c = 0; c < matrix_construct.nj; ++c)
TTS_EQUAL(result_block(r, c), ref_result_block(r, c));*/
self_ops(a_block,b_block);
self_ops(ref_a_block, ref_b_block);
for (std::size_t r = 0; r < matrix_construct.ni; ++r)
for (std::size_t c = 0; c < matrix_construct.nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
{
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
{
TTS_EQUAL(a(r, c), ref_a(r, c));
TTS_EQUAL(b(r, c), ref_b(r, c));
}
}
}
template <typename MatrixType, typename T>
void test_block_scalar_operations(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct,
auto scalar, auto self_ops)
{
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);
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(matrix_construct.init_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);
//TTS_EQUAL(ops(a, s), ref);
self_ops(a_block,scalar);
self_ops(ref_a_block, scalar);
for (std::size_t r = 0; r < matrix_construct.ni; ++r)
for (std::size_t c = 0; c < matrix_construct.nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
TTS_EQUAL(a(r, c), ref_a(r, c));
}
template <typename MatrixType, typename T>
void test_scalar_block_multiplications(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct,
T scalar)
{
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);
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(matrix_construct.init_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);
//TTS_EQUAL(a * s, ref);
//TTS_EQUAL(s * a, ref);
a_block *= scalar;
ref_a_block *= scalar;
for (std::size_t r = 0; r < matrix_construct.ni; ++r)
for (std::size_t c = 0; c < matrix_construct.nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
TTS_EQUAL(a(r, c), ref_a(r, c));
}
template <typename MatrixType, typename T>
void test_block_multiplication(rotgen::tests::matrix_block_test_case<MatrixType> const& a_matrix_construct,
rotgen::tests::matrix_block_test_case<MatrixType> const& b_matrix_construct)
{
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
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);
for (std::size_t r = 0; r < a_matrix_construct.rows; ++r)
for (std::size_t 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 (std::size_t r = 0; r < b_matrix_construct.rows; ++r)
for (std::size_t 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 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);
// a * b
a_block *= b_block;
ref_a_block *= ref_b_block;
for (std::size_t r = 0; r < a_matrix_construct.ni; ++r)
for (std::size_t c = 0; c < a_matrix_construct.nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (std::size_t r = 0; r < a_matrix_construct.rows; ++r)
for (std::size_t c = 0; c < a_matrix_construct.cols; ++c)
TTS_EQUAL(a(r, c), ref_a(r, c));
for (std::size_t r = 0; r < b_matrix_construct.rows; ++r)
for (std::size_t c = 0; c < b_matrix_construct.cols; ++c)
TTS_EQUAL(b(r, c), ref_b(r, c));
}
// Basic initializers
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 block 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_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, s_op);
test_block_matrix_operations<mat_t, T>({13 , 15, init_a, 1, 2, 3, 4}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({5 , 9, init_a, 2, 2, 2, 2}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({15 , 15, init_a, 3, 4, 5, 5}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({5 , 5, init_b, 1, 0, 3, 2}, init_a, s_op);
test_block_matrix_operations<mat_t, T>({10, 1, init_a, 0, 0, 5, 1}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({1 , 10, init_a, 0, 0, 1, 5}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({21 , 5, init_0, 4, 4, 10, 1}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({11 , 7, init_a, 2, 0, 7, 5}, init_0, s_op);
};
TTS_CASE_TPL("Check block 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_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, s_op);
test_block_matrix_operations<mat_t, T>({13 , 15, init_a, 1, 2, 3, 4}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({5 , 9, init_a, 2, 2, 2, 2}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({15 , 15, init_a, 3, 4, 5, 5}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({5 , 5, init_b, 1, 0, 3, 2}, init_a, s_op);
test_block_matrix_operations<mat_t, T>({10, 1, init_a, 0, 0, 5, 1}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({1 , 10, init_a, 0, 0, 1, 5}, init_b,s_op);
test_block_matrix_operations<mat_t, T>({21 , 5, init_0, 4, 4, 10, 1}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({11 , 7, init_a, 2, 0, 7, 5}, init_0, 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 = [](auto r, auto 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});
};
TTS_CASE_TPL("Check block 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_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)
<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_block_scalar_operations<mat_t, T>({1 , 1, init_a, 0, 0, 1, 1}, T{ 3.5}, op, s_op);
test_block_scalar_operations<mat_t, T>({1 , 1, init_a, 0, 0, 1, 1}, T{ 3.5}, s_op);
test_block_scalar_operations<mat_t, T>({13 , 15, init_a, 1, 2, 3, 4}, T{-2.5}, s_op);
test_block_scalar_operations<mat_t, T>({5 , 9, init_a, 2, 2, 2, 2}, T{ 42. }, s_op);
test_block_scalar_operations<mat_t, T>({15 , 15, init_a, 3, 4, 5, 5}, T{-5. }, s_op);
test_block_scalar_operations<mat_t, T>({5 , 5, init_b, 1, 0, 3, 2}, T{ 1. }, s_op);
test_block_scalar_operations<mat_t, T>({10, 1, init_a, 0, 0, 5, 1}, T{ 0. }, s_op);
test_block_scalar_operations<mat_t, T>({1 , 10, init_a, 0, 0, 1, 5}, T{ 6. },s_op);
test_block_scalar_operations<mat_t, T>({21 , 5, init_0, 4, 4, 10, 1}, T{ 10.}, s_op);
test_block_scalar_operations<mat_t, T>({11 , 7, init_a, 2, 0, 7, 5}, T{-0.5}, s_op);
};

View file

@ -0,0 +1,115 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/block.hpp>
#include <rotgen/matrix.hpp>
void test_size(const auto& matrix, std::size_t rows, std::size_t cols)
{
TTS_EQUAL(matrix.rows(), rows);
TTS_EQUAL(matrix.cols(), cols);
TTS_EQUAL(matrix.size(), rows*cols);
}
void test_value(const auto& matrix, std::size_t rows, std::size_t cols, auto constant)
{
test_size(matrix, rows, cols);
for(std::size_t r=0;r<rows;++r)
for(std::size_t c=0;c<cols;++c)
TTS_EQUAL(matrix(r, c), constant);
}
void test_random(const auto& matrix, std::size_t rows, std::size_t cols)
{
test_size(matrix, rows, cols);
for(std::size_t r=0;r<rows;++r)
for(std::size_t 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, std::size_t rows, std::size_t cols)
{
test_size(matrix, rows, cols);
for(std::size_t r=0;r<rows;++r)
for(std::size_t 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

@ -59,7 +59,7 @@ TTS_CASE_TPL("Test transpotion related operations", rotgen::tests::types)
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::value_type, Eigen::Dynamic, Eigen::Dynamic>;
using EigenMatrix = Eigen::Matrix<typename MatrixType::scalar_type, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType original(rows, cols);
EigenMatrix ref(rows, cols);

View file

@ -28,4 +28,22 @@ namespace rotgen::tests
std::size_t rows, cols;
std::function<double(std::size_t,std::size_t)> init_fn;
};
template<typename MatrixType>
struct matrix_block_test_case
{
std::size_t rows, cols;
std::function<typename MatrixType::scalar_type(std::size_t, std::size_t)> init_fn;
std::size_t i0, j0, ni, nj;
};
template<typename MatrixType, std::size_t NI, std::size_t NJ>
struct static_matrix_block_test_case
{
std::size_t rows, cols;
std::function<typename MatrixType::scalar_type(std::size_t, std::size_t)> init_fn;
static constexpr std::size_t ni = NI;
static constexpr std::size_t nj = NJ;
std::size_t i0, j0;
};
}