Implements map and ref for both static & dynamic mode
See merge request oss/rotgen!12
This commit is contained in:
parent
aacae1cbb1
commit
6c2b260229
58 changed files with 4121 additions and 1205 deletions
284
include/rotgen/common/ref.hpp
Normal file
284
include/rotgen/common/ref.hpp
Normal 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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue