rotgen/include/rotgen/dynamic/block.hpp
2025-09-28 16:15:15 +02:00

368 lines
No EOL
12 KiB
C++

//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once
#include <rotgen/concepts.hpp>
#include <rotgen/impl/block.hpp>
#include <rotgen/dynamic/matrix.hpp>
#include <initializer_list>
#include <cassert>
namespace rotgen
{
template<typename T, int Options = T::storage_order, typename Stride = stride>
class ref;
template<typename Ref, int Rows = Dynamic, int Cols = Dynamic, bool Inner = false>
class block : public find_block<Ref>
{
public:
static_assert ( concepts::entity<Ref>
, "[ROTGEN][CRITICAL] - Block of non-rotgen type instanciated"
);
using parent = find_block<Ref>;
using rotgen_tag = void;
using rotgen_block_tag = void;
using value_type = typename std::remove_const_t<Ref>::value_type;
static constexpr int storage_order = Ref::storage_order;
static constexpr bool is_immutable = std::is_const_v<Ref>;
using concrete_type = matrix<value_type,Rows,Cols,storage_order>;
using concrete_dynamic_type = matrix<value_type,Dynamic,Dynamic,storage_order>;
static constexpr int RowsAtCompileTime = Rows;
static constexpr int ColsAtCompileTime = Cols;
static constexpr bool IsVectorAtCompileTime = Ref::IsVectorAtCompileTime;
static constexpr int Options = Ref::Options;
static constexpr bool IsRowMajor = (storage_order & RowMajor) == RowMajor;
static constexpr bool is_defined_static = false;
static constexpr bool has_static_storage = false;
using parent::operator=;
block& operator=(concepts::entity auto const& other) requires(!is_immutable)
{
assert(parent::rows() == other.rows() && parent::cols() == other.cols());
for (rotgen::Index r = 0; r < parent::rows(); ++r)
for (rotgen::Index c = 0; c < parent::cols(); ++c)
(*this)(r, c) = other(r, c);
return *this;
}
block(Ref const& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
requires( !requires{typename Ref::rotgen_block_tag; } && is_immutable)
: parent(r.base(),i0,j0,ni,nj)
{}
block(Ref const& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
requires( requires{typename Ref::rotgen_block_tag; } && is_immutable)
: parent(*r.storage(),i0,j0,ni,nj)
{}
block(Ref const& r, std::size_t i0, std::size_t j0)
requires(!requires{typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && is_immutable)
: parent(r.base(),i0,j0,Rows,Cols)
{}
block(Ref const& r, std::size_t i0, std::size_t j0)
requires(requires{typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && is_immutable)
: parent(*r.storage(),i0,j0,Rows,Cols)
{}
block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
requires( !requires{typename Ref::rotgen_block_tag; } && !is_immutable)
: parent(r.base(),i0,j0,ni,nj)
{}
block(Ref& r, std::size_t i0, std::size_t j0, std::size_t ni, std::size_t nj)
requires( requires{typename Ref::rotgen_block_tag; } && !is_immutable)
: parent(*r.storage(),i0,j0,ni,nj)
{}
block(Ref& r, std::size_t i0, std::size_t j0)
requires(!requires{typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && !is_immutable)
: parent(r.base(),i0,j0,Rows,Cols)
{}
block(Ref& r, std::size_t i0, std::size_t j0)
requires(requires{typename Ref::rotgen_block_tag; } && Rows != -1 && Cols != -1 && !is_immutable)
: parent(*r.storage(),i0,j0,Rows,Cols)
{}
block(parent const& base) : parent(base) {}
bool is_contiguous_linear() const
{
if(parent::innerStride() != 1) return false;
if constexpr(storage_order) return parent::outerStride() == parent::cols();
else return parent::outerStride() == parent::rows();
}
value_type& operator()(Index i, Index j) requires(!is_immutable) { return parent::operator()(i,j); }
value_type& operator()(Index i) requires(!is_immutable && IsVectorAtCompileTime)
{
assert(is_contiguous_linear());
return parent::operator()(i);
}
value_type& operator[](Index i) requires(!is_immutable && IsVectorAtCompileTime)
{
return (*this)(i);
}
value_type operator()(Index i, Index j) const { return parent::operator()(i,j); }
value_type operator()(Index i) const requires(IsVectorAtCompileTime)
{
assert(is_contiguous_linear());
return parent::operator()(i);
}
value_type operator[](Index i) const requires(IsVectorAtCompileTime)
{
return (*this)(i);
}
auto evaluate() const { return *this; }
decltype(auto) noalias() const { return *this; }
decltype(auto) noalias() { return *this; }
concrete_type normalized() const requires(IsVectorAtCompileTime)
{
return concrete_type(base().normalized());
}
concrete_type transpose() const { return concrete_type(base().transpose());}
concrete_type conjugate() const { return concrete_type(base().conjugate());}
concrete_type adjoint() const { return concrete_type(base().adjoint());}
concrete_type cwiseAbs() const { return concrete_type(base().cwiseAbs()); }
concrete_type cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); }
concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); }
concrete_type cwiseSqrt() const { return concrete_type(base().cwiseSqrt()); }
void normalize() requires(!is_immutable && IsVectorAtCompileTime)
{
parent::normalize();
}
void transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); }
void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); }
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) requires(!is_immutable)
{
base() += static_cast<parent const&>(rhs);
return *this;
}
block& operator-=(block const& rhs) requires(!is_immutable)
{
base() -= 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) requires(!is_immutable)
{
base() *= static_cast<parent const&>(rhs);
return *this;
}
block& operator*=(value_type rhs) requires(!is_immutable)
{
base() *= rhs;
return *this;
}
block& operator/=(value_type rhs) requires(!is_immutable)
{
base() /= rhs;
return *this;
}
auto minCoeff() const { return parent::minCoeff(); }
auto maxCoeff() const { return parent::maxCoeff(); }
template<std::integral IndexType>
auto minCoeff(IndexType* row, IndexType* col) const
{
Index r,c;
auto result = parent::minCoeff(&r, &c);
*row = r;
*col = c;
return result;
}
template<std::integral IndexType>
auto maxCoeff(IndexType* row, IndexType* col) const
{
Index r,c;
auto result = parent::maxCoeff(&r, &c);
*row = r;
*col = c;
return result;
}
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 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, 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<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);
}
block& setOnes() requires(!is_immutable)
{
parent::assign(parent::Ones(parent::rows(), parent::cols()));
return *this;
}
block& setZero() requires(!is_immutable)
{
parent::assign(parent::Zero(parent::rows(), parent::cols()));
return *this;
}
block& setConstant(value_type value) requires(!is_immutable)
{
parent::assign(parent::Constant(parent::rows(), parent::cols(), value));
return *this;
}
block& setRandom() requires(!is_immutable)
{
parent::assign(parent::Random(parent::rows(), parent::cols()));
return *this;
}
block& setIdentity() requires(!is_immutable)
{
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>
auto operator+(block<Ref, R, C, I> const& lhs, block<Ref, R, C, I> const& rhs)
{
using concrete_type = typename block<Ref, R, C, I>::concrete_type;
return concrete_type(lhs.base().add(rhs));
}
template<typename Ref, int R, int C, bool I>
auto operator-(block<Ref, R, C, I> const& lhs, block<Ref, R, C, I> const& rhs)
{
using concrete_type = typename block<Ref, R, C, I>::concrete_type;
return concrete_type(lhs.base().sub(rhs));
}
template<typename Ref, int R, int C, bool I>
auto operator*(block<Ref, R, C, I> const& lhs, block<Ref, R, C, I> const& rhs)
{
using concrete_type = typename block<Ref, R, C, I>::concrete_type;
return concrete_type(lhs.base().mul(rhs));
}
template<typename Ref, int R, int C, bool I>
auto operator*(block<Ref, R, C, I> const& lhs, double rhs)
{
using concrete_type = typename block<Ref, R, C, I>::concrete_type;
return concrete_type(lhs.base().mul(rhs));
}
template<typename Ref, int R, int C, bool I>
auto operator*(double lhs, block<Ref, R, C, I> const& rhs)
{
using concrete_type = typename block<Ref, R, C, I>::concrete_type;
return concrete_type(rhs.base().mul(lhs));
}
template<typename Ref, int R, int C, bool I>
auto operator/(block<Ref, R, C, I> const& lhs, double rhs)
{
using concrete_type = typename block<Ref, R, C, I>::concrete_type;
return concrete_type(lhs.base().div(rhs));
}
}