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

@ -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
}