* Compound operators were not usable properly. * std::size_t was used in the API in places where Index should have been used.
348 lines
8.9 KiB
C++
348 lines
8.9 KiB
C++
//==================================================================================================
|
|
/*
|
|
ROTGEN - Runtime Overlay for Eigen
|
|
Copyright : CODE RECKONS
|
|
SPDX-License-Identifier: BSL-1.0
|
|
*/
|
|
//==================================================================================================
|
|
#pragma once
|
|
|
|
#include <rotgen/detail/helpers.hpp>
|
|
|
|
namespace rotgen
|
|
{
|
|
//-----------------------------------------------------------------------------------------------
|
|
// Infos & Shape
|
|
//-----------------------------------------------------------------------------------------------
|
|
Index rows(auto const& m)
|
|
requires(requires { m.rows(); })
|
|
{
|
|
return m.rows();
|
|
}
|
|
|
|
Index cols(auto const& m)
|
|
requires(requires { m.cols(); })
|
|
{
|
|
return m.cols();
|
|
}
|
|
|
|
Index size(auto const& m)
|
|
requires(requires { m.size(); })
|
|
{
|
|
return m.size();
|
|
}
|
|
|
|
void resize(auto& a, int s)
|
|
requires requires { a.resize(s); }
|
|
{
|
|
a.resize(s);
|
|
}
|
|
|
|
void resize(auto& a, int r, int c)
|
|
requires requires { a.resize(r, c); }
|
|
{
|
|
a.resize(r, c);
|
|
}
|
|
|
|
void conservativeResize(auto& a, int s)
|
|
requires requires { a.conservativeResize(s); }
|
|
{
|
|
a.conservativeResize(s);
|
|
}
|
|
|
|
void conservativeResize(auto& a, int r, int c)
|
|
requires requires { a.conservativeResize(r, c); }
|
|
{
|
|
a.conservativeResize(r, c);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------------------------
|
|
// Global operations
|
|
//-----------------------------------------------------------------------------------------------
|
|
decltype(auto) normalized(auto const& m)
|
|
requires(requires { m.normalized(); })
|
|
{
|
|
return m.normalized();
|
|
}
|
|
|
|
decltype(auto) transpose(auto const& m)
|
|
requires(requires { m.transpose(); })
|
|
{
|
|
return m.transpose();
|
|
}
|
|
|
|
decltype(auto) conjugate(auto const& m)
|
|
requires(requires { m.conjugate(); })
|
|
{
|
|
return m.conjugate();
|
|
}
|
|
|
|
decltype(auto) adjoint(auto const& m)
|
|
requires(requires { m.adjoint(); })
|
|
{
|
|
return m.adjoint();
|
|
}
|
|
|
|
void normalize(auto& a)
|
|
requires(requires { a.normalize(); })
|
|
{
|
|
a.normalize();
|
|
}
|
|
|
|
void transposeInPlace(auto& a)
|
|
requires(requires { a.transposeInPlace(); })
|
|
{
|
|
a.transposeInPlace();
|
|
}
|
|
|
|
void adjointInPlace(auto& a)
|
|
requires(requires { a.adjointInPlace(); })
|
|
{
|
|
a.adjointInPlace();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------------------------
|
|
// Component-wise functions
|
|
//-----------------------------------------------------------------------------------------------
|
|
auto abs(auto const& arg)
|
|
requires(requires { arg.cwiseAbs(); })
|
|
{
|
|
return arg.cwiseAbs();
|
|
}
|
|
|
|
auto abs2(auto const& arg)
|
|
requires(requires { arg.cwiseAbs2(); })
|
|
{
|
|
return arg.cwiseAbs2();
|
|
}
|
|
|
|
auto rec(auto const& arg)
|
|
requires(requires { arg.cwiseInverse(); })
|
|
{
|
|
return arg.cwiseInverse();
|
|
}
|
|
|
|
auto sqrt(auto const& arg)
|
|
requires(requires { arg.cwiseSqrt(); })
|
|
{
|
|
return arg.cwiseSqrt();
|
|
}
|
|
|
|
template<concepts::entity A, concepts::entity B>
|
|
auto min(A const& a, B const& b)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return min(generalize_t<A const>(a), generalize_t<B const>(b));
|
|
else return base_of(a).cwiseMin(base_of(b));
|
|
}
|
|
|
|
template<concepts::entity A>
|
|
auto min(A const& a, std::convertible_to<typename A::value_type> auto b)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return min(generalize_t<A const>(a), b);
|
|
else return base_of(a).cwiseMin(b);
|
|
}
|
|
|
|
template<concepts::entity B>
|
|
auto min(std::convertible_to<typename B::value_type> auto a, B const& b)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return min(a, generalize_t<B const>(b));
|
|
else return base_of(b).cwiseMin(a);
|
|
}
|
|
|
|
template<concepts::entity A, concepts::entity B>
|
|
auto max(A const& a, B const& b)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return max(generalize_t<A const>(a), generalize_t<B const>(b));
|
|
else return base_of(a).cwiseMax(base_of(b));
|
|
}
|
|
|
|
template<concepts::entity A>
|
|
auto max(A const& a, std::convertible_to<typename A::value_type> auto b)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return max(generalize_t<A const>(a), b);
|
|
else return base_of(a).cwiseMax(b);
|
|
}
|
|
|
|
template<concepts::entity B>
|
|
auto max(std::convertible_to<typename B::value_type> auto a, B const& b)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return max(a, generalize_t<B const>(b));
|
|
else return base_of(b).cwiseMax(a);
|
|
}
|
|
|
|
template<concepts::entity A, concepts::entity B>
|
|
auto mul(A const& a, B const& b)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return mul(generalize_t<A const>(a), generalize_t<B const>(b));
|
|
else return base_of(a).cwiseProduct(base_of(b));
|
|
}
|
|
|
|
template<concepts::entity A>
|
|
auto mul(A const& a, std::convertible_to<typename A::value_type> auto b)
|
|
{
|
|
return a * b;
|
|
}
|
|
|
|
template<concepts::entity B>
|
|
auto mul(std::convertible_to<typename B::value_type> auto a, B const& b)
|
|
{
|
|
return a * b;
|
|
}
|
|
|
|
template<concepts::entity A, concepts::entity B>
|
|
auto div(A const& a, B const& b)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return div(generalize_t<A const>(a), generalize_t<B const>(b));
|
|
else return base_of(a).array() / base_of(b).array();
|
|
}
|
|
|
|
template<concepts::entity A>
|
|
auto div(A const& a, std::convertible_to<typename A::value_type> auto b)
|
|
{
|
|
return a / b;
|
|
}
|
|
|
|
template<concepts::entity A> auto square(A const& a)
|
|
{
|
|
return mul(a, a);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------------------------
|
|
// Reductions
|
|
//-----------------------------------------------------------------------------------------------
|
|
auto trace(auto const& arg)
|
|
requires requires { arg.trace(); }
|
|
{
|
|
return arg.trace();
|
|
}
|
|
|
|
auto squaredNorm(auto const& arg)
|
|
requires requires { arg.squaredNorm(); }
|
|
{
|
|
return arg.squaredNorm();
|
|
}
|
|
|
|
auto norm(auto const& arg)
|
|
requires requires { arg.norm(); }
|
|
{
|
|
return arg.norm();
|
|
}
|
|
|
|
auto sum(auto const& arg)
|
|
requires requires { arg.sum(); }
|
|
{
|
|
return arg.sum();
|
|
}
|
|
|
|
auto prod(auto const& arg)
|
|
requires requires { arg.prod(); }
|
|
{
|
|
return arg.prod();
|
|
}
|
|
|
|
auto mean(auto const& arg)
|
|
requires requires { arg.mean(); }
|
|
{
|
|
return arg.mean();
|
|
}
|
|
|
|
template<concepts::entity A, concepts::entity B>
|
|
auto dot(A const& a, B const& b)
|
|
requires(detail::has_same_vector_size<A, B> &&
|
|
std::same_as<typename A::value_type, typename B::value_type>)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return dot(generalize_t<A const>(a), generalize_t<B const>(b));
|
|
else return base_of(a).dot(base_of(b));
|
|
}
|
|
|
|
auto maxCoeff(auto const& arg)
|
|
requires(requires { arg.maxCoeff(); })
|
|
{
|
|
return arg.maxCoeff();
|
|
}
|
|
|
|
auto minCoeff(auto const& arg)
|
|
requires(requires { arg.minCoeff(); })
|
|
{
|
|
return arg.minCoeff();
|
|
}
|
|
|
|
template<std::integral IndexType>
|
|
auto maxCoeff(auto const& arg, IndexType* row, IndexType* col)
|
|
requires(requires { arg.maxCoeff(row, col); })
|
|
{
|
|
return arg.maxCoeff(row, col);
|
|
}
|
|
|
|
template<std::integral IndexType>
|
|
auto minCoeff(auto const& arg, IndexType* row, IndexType* col)
|
|
requires(requires { arg.minCoeff(row, col); })
|
|
{
|
|
return arg.minCoeff(row, col);
|
|
}
|
|
|
|
template<int P, typename T>
|
|
auto lpNorm(T const& arg)
|
|
requires(requires { arg.template lpNorm<P>(); })
|
|
{
|
|
static_assert(P == 1 || P == 2 || P == Infinity);
|
|
return arg.template lpNorm<P>();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------------------------
|
|
// Expression handling
|
|
//-----------------------------------------------------------------------------------------------
|
|
template<typename T>
|
|
decltype(auto) noalias(T&& t)
|
|
requires(requires { std::forward<T>(t).noalias(); })
|
|
{
|
|
return std::forward<T>(t).noalias();
|
|
}
|
|
|
|
template<typename T>
|
|
auto evaluate(T&& t)
|
|
requires(requires { std::forward<T>(t).evaluate(); })
|
|
{
|
|
return std::forward<T>(t).evaluate();
|
|
}
|
|
|
|
template<typename T>
|
|
auto evaluate(T&& t)
|
|
requires(requires { std::forward<T>(t).eval(); })
|
|
{
|
|
return std::forward<T>(t).eval();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------------------------
|
|
// Others
|
|
// TODO: Adapt other functions ot behave as inverse and limit code in
|
|
// non-ref/non-map containers
|
|
//-----------------------------------------------------------------------------------------------
|
|
template<typename A> auto inverse(A const& a)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return inverse(generalize_t<A const>(a));
|
|
else return base_of(a).inverse();
|
|
}
|
|
|
|
template<concepts::vectorND<3> L, concepts::vectorND<3> R>
|
|
auto cross(L const& l, R const& r)
|
|
{
|
|
if constexpr (!use_expression_templates)
|
|
return cross(generalize_t<R const>(l), generalize_t<R const>(r));
|
|
else if constexpr (
|
|
requires { typename L::rotgen_tag; } ||
|
|
requires { typename R::rotgen_tag; })
|
|
return base_of(l).cross(base_of(r));
|
|
else return l.cross(r);
|
|
}
|
|
}
|