rotgen/include/rotgen/functions/functions.hpp
Joel Falcou c7aa4a0afa Fix some operations API mismatch
* Compound operators were not usable properly.
* std::size_t was used in the API in places where Index should have been used.
2025-10-29 20:33:59 +01:00

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);
}
}