Implement normalize and normalized

See merge request oss/rotgen!24
This commit is contained in:
Joel Falcou 2025-09-18 16:25:51 +02:00
parent e7cf89a903
commit 3e2e6f253c
14 changed files with 169 additions and 65 deletions

View file

@ -132,26 +132,23 @@ namespace rotgen
decltype(auto) noalias() const { return *this; } decltype(auto) noalias() const { return *this; }
decltype(auto) noalias() { return *this; } decltype(auto) noalias() { return *this; }
concrete_type transpose() const concrete_type normalized() const requires(IsVectorAtCompileTime)
{ {
return concrete_type(static_cast<parent const &>(*this).transpose()); return concrete_type(base().normalized());
}
concrete_type conjugate() const
{
return concrete_type(static_cast<parent const &>(*this).conjugate());
}
concrete_type adjoint() const
{
return concrete_type(static_cast<parent const&>(*this).adjoint());
} }
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 cwiseAbs() const { return concrete_type(base().cwiseAbs()); }
concrete_type cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); } concrete_type cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); }
concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); } concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); }
concrete_type cwiseSqrt() const { return concrete_type(base().cwiseSqrt()); } 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 transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); }
void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); } void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); }

View file

@ -123,26 +123,24 @@ namespace rotgen
decltype(auto) noalias() const { return *this; } decltype(auto) noalias() const { return *this; }
decltype(auto) noalias() { return *this; } decltype(auto) noalias() { return *this; }
concrete_type transpose() const concrete_type normalized() const requires(IsVectorAtCompileTime)
{ {
return concrete_type(static_cast<parent const &>(*this).transpose()); return concrete_type(base().normalized());
} }
concrete_type conjugate() const concrete_type transpose() const { return concrete_type(base().transpose()); }
{ concrete_type conjugate() const { return concrete_type(base().conjugate()); }
return concrete_type(static_cast<parent const &>(*this).conjugate()); concrete_type adjoint() const { return concrete_type(base().adjoint()); }
}
concrete_type adjoint() const
{
return concrete_type(static_cast<parent const &>(*this).adjoint());
}
concrete_type cwiseAbs() const { return concrete_type(base().cwiseAbs()); } concrete_type cwiseAbs() const { return concrete_type(base().cwiseAbs()); }
concrete_type cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); } concrete_type cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); }
concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); } concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); }
concrete_type cwiseSqrt() const { return concrete_type(base().cwiseSqrt()); } 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 transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); }
void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); } void adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); }

View file

@ -112,6 +112,11 @@ namespace rotgen
parent::conservativeResize(new_rows, new_cols); parent::conservativeResize(new_rows, new_cols);
} }
matrix normalized() const requires(IsVectorAtCompileTime)
{
return matrix(base().normalized());
}
matrix transpose() const matrix transpose() const
{ {
return matrix(base().transpose()); return matrix(base().transpose());
@ -127,6 +132,11 @@ namespace rotgen
return matrix(base().adjoint()); return matrix(base().adjoint());
} }
void normalize() requires(IsVectorAtCompileTime)
{
parent::normalize();
}
void transposeInPlace() { parent::transposeInPlace(); } void transposeInPlace() { parent::transposeInPlace(); }
void adjointInPlace() { parent::adjointInPlace(); } void adjointInPlace() { parent::adjointInPlace(); }

View file

@ -126,11 +126,11 @@ namespace rotgen
} }
parent& base() { return static_cast<parent&>(*this); } parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<const parent&>(*this); } parent const& base() const { return static_cast<parent const&>(*this); }
auto evaluate() const auto evaluate() const
{ {
auto res = static_cast<parent const &>(*this).eval(); auto res = base().eval();
return as_concrete_type<decltype(res)>(res); return as_concrete_type<decltype(res)>(res);
} }
@ -146,22 +146,33 @@ namespace rotgen
else return *this; else return *this;
} }
auto transpose() const auto normalized() const requires(IsVectorAtCompileTime)
{ {
auto res = static_cast<parent const &>(*this).transpose(); if constexpr(use_expression_templates) return base().normalized();
return as_concrete_type<decltype(res)>(res); else return as_concrete_type<decltype(base().normalized())>(base().normalized());
} }
auto conjugate() const auto transpose() const
{ {
auto res = static_cast<parent const &>(*this).conjugate(); if constexpr(use_expression_templates) return base().transpose();
return as_concrete_type<decltype(res)>(res); else return as_concrete_type<decltype(base().transpose())>(base().transpose());
} }
auto adjoint() const auto adjoint() const
{ {
auto res = static_cast<parent const &>(*this).adjoint(); if constexpr(use_expression_templates) return base().adjoint();
return as_concrete_type<decltype(res)>(res); else return as_concrete_type<decltype(base().adjoint())>(base().adjoint());
}
auto conjugate() const
{
if constexpr(use_expression_templates) return base().conjugate();
else return as_concrete_type<decltype(base().conjugate())>(base().conjugate());
}
void normalize() requires(!is_immutable && IsVectorAtCompileTime)
{
parent::normalize();
} }
void transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); } void transposeInPlace() requires(!is_immutable) { parent::transposeInPlace(); }

View file

@ -185,6 +185,12 @@ namespace rotgen
else return base().cwiseSqrt(); else return base().cwiseSqrt();
} }
auto normalized() const requires(IsVectorAtCompileTime)
{
if constexpr(use_expression_templates) return base().normalized();
else return as_concrete_type<decltype(base().normalized())>(base().normalized());
}
auto transpose() const auto transpose() const
{ {
if constexpr(use_expression_templates) return base().transpose(); if constexpr(use_expression_templates) return base().transpose();
@ -203,6 +209,11 @@ namespace rotgen
else return as_concrete_type<decltype(base().conjugate())>(base().conjugate()); else return as_concrete_type<decltype(base().conjugate())>(base().conjugate());
} }
void normalize() requires(IsVectorAtCompileTime)
{
base().normalize();
}
void transposeInPlace() { base().transposeInPlace(); } void transposeInPlace() { base().transposeInPlace(); }
void adjointInPlace() { base().adjointInPlace(); } void adjointInPlace() { base().adjointInPlace(); }

View file

@ -126,11 +126,11 @@ namespace rotgen
} }
parent& base() { return static_cast<parent&>(*this); } parent& base() { return static_cast<parent&>(*this); }
parent const& base() const { return static_cast<const parent&>(*this); } parent const& base() const { return static_cast<parent const&>(*this); }
auto evaluate() const auto evaluate() const
{ {
auto res = static_cast<parent const &>(*this).eval(); auto res = base().eval();
return as_concrete_type<decltype(res)>(res); return as_concrete_type<decltype(res)>(res);
} }
@ -146,28 +146,43 @@ namespace rotgen
else return *this; else return *this;
} }
auto normalized() const requires(IsVectorAtCompileTime)
{
if constexpr(use_expression_templates) return base().normalized();
else
{
auto res = base().normalized();
return as_concrete_type<decltype(res)>(res);
}
}
auto transpose() const auto transpose() const
{ {
if constexpr(use_expression_templates) return base().transpose(); if constexpr(use_expression_templates) return base().transpose();
else else
{ {
auto res = static_cast<parent const &>(*this).transpose(); auto res = base().transpose();
return as_concrete_type<decltype(res)>(res); return as_concrete_type<decltype(res)>(res);
} }
} }
auto conjugate() const auto conjugate() const
{ {
auto res = static_cast<parent const &>(*this).conjugate(); auto res = base().conjugate();
return as_concrete_type<decltype(res)>(res); return as_concrete_type<decltype(res)>(res);
} }
auto adjoint() const auto adjoint() const
{ {
auto res = static_cast<parent const &>(*this).adjoint(); auto res = base().adjoint();
return as_concrete_type<decltype(res)>(res); return as_concrete_type<decltype(res)>(res);
} }
void normalize() requires(IsVectorAtCompileTime)
{
parent::normalize();
}
void transposeInPlace() { parent::transposeInPlace(); } void transposeInPlace() { parent::transposeInPlace(); }
void adjointInPlace() { parent::adjointInPlace(); } void adjointInPlace() { parent::adjointInPlace(); }
@ -380,24 +395,24 @@ namespace rotgen
matrix& operator+=(matrix const& rhs) matrix& operator+=(matrix const& rhs)
{ {
static_cast<parent&>(*this) += static_cast<parent const&>(rhs); static_cast<parent&>(*this) += rhs.base();
return *this; return *this;
} }
matrix& operator-=(matrix const& rhs) matrix& operator-=(matrix const& rhs)
{ {
static_cast<parent&>(*this) -= static_cast<parent const&>(rhs); static_cast<parent&>(*this) -= rhs.base();
return *this; return *this;
} }
matrix operator-() const matrix operator-() const
{ {
return matrix(static_cast<parent const&>(*this).operator-()); return matrix(base()(*this).operator-());
} }
matrix& operator*=(matrix const& rhs) matrix& operator*=(matrix const& rhs)
{ {
static_cast<parent&>(*this) *= static_cast<parent const&>(rhs); static_cast<parent&>(*this) *= rhs.base();
return *this; return *this;
} }

View file

@ -27,10 +27,12 @@ namespace rotgen
arg.conservativeResize(new_rows, new_cols); arg.conservativeResize(new_rows, new_cols);
} }
decltype(auto) normalized(concepts::entity auto const& arg) { return arg.normalized(); }
decltype(auto) transpose (concepts::entity auto const& arg) { return arg.transpose(); } decltype(auto) transpose (concepts::entity auto const& arg) { return arg.transpose(); }
decltype(auto) conjugate (concepts::entity auto const& arg) { return arg.conjugate(); } decltype(auto) conjugate (concepts::entity auto const& arg) { return arg.conjugate(); }
decltype(auto) adjoint (concepts::entity auto const& arg) { return arg.adjoint(); } decltype(auto) adjoint (concepts::entity auto const& arg) { return arg.adjoint(); }
void normalize(concepts::entity auto& arg) { arg.normalize(); }
void transposeInPlace(concepts::entity auto& arg) { arg.transposeInPlace(); } void transposeInPlace(concepts::entity auto& arg) { arg.transposeInPlace(); }
void adjointInPlace(concepts::entity auto& arg) { arg.adjointInPlace(); } void adjointInPlace(concepts::entity auto& arg) { arg.adjointInPlace(); }

View file

@ -46,6 +46,7 @@ class ROTGEN_EXPORT CLASSNAME
Index startRow() const; Index startRow() const;
Index startCol() const; Index startCol() const;
SOURCENAME normalized() const;
SOURCENAME transpose() const; SOURCENAME transpose() const;
SOURCENAME conjugate() const; SOURCENAME conjugate() const;
SOURCENAME adjoint() const; SOURCENAME adjoint() const;
@ -56,6 +57,7 @@ class ROTGEN_EXPORT CLASSNAME
SOURCENAME cwiseSqrt() const; SOURCENAME cwiseSqrt() const;
#if !defined(USE_CONST) #if !defined(USE_CONST)
void normalize();
void transposeInPlace(); void transposeInPlace();
void adjointInPlace(); void adjointInPlace();
#endif #endif

View file

@ -36,6 +36,7 @@ class ROTGEN_EXPORT CLASSNAME
Index innerStride() const; Index innerStride() const;
Index outerStride() const; Index outerStride() const;
SOURCENAME normalized() const;
SOURCENAME transpose() const; SOURCENAME transpose() const;
SOURCENAME conjugate() const; SOURCENAME conjugate() const;
SOURCENAME adjoint() const; SOURCENAME adjoint() const;
@ -46,6 +47,7 @@ class ROTGEN_EXPORT CLASSNAME
SOURCENAME cwiseSqrt() const; SOURCENAME cwiseSqrt() const;
#if !defined(USE_CONST) #if !defined(USE_CONST)
void normalize();
void transposeInPlace(); void transposeInPlace();
void adjointInPlace(); void adjointInPlace();
#endif #endif

View file

@ -35,6 +35,7 @@ class ROTGEN_EXPORT CLASSNAME
void resize(std::size_t new_rows, std::size_t new_cols); void resize(std::size_t new_rows, std::size_t new_cols);
void conservativeResize(std::size_t new_rows, std::size_t new_cols); void conservativeResize(std::size_t new_rows, std::size_t new_cols);
CLASSNAME normalized() const;
CLASSNAME transpose() const; CLASSNAME transpose() const;
CLASSNAME conjugate() const; CLASSNAME conjugate() const;
CLASSNAME adjoint() const; CLASSNAME adjoint() const;
@ -44,6 +45,7 @@ class ROTGEN_EXPORT CLASSNAME
CLASSNAME cwiseInverse() const; CLASSNAME cwiseInverse() const;
CLASSNAME cwiseSqrt() const; CLASSNAME cwiseSqrt() const;
void normalize();
void transposeInPlace(); void transposeInPlace();
void adjointInPlace(); void adjointInPlace();

View file

@ -225,6 +225,13 @@ struct CLASSNAME::payload
//================================================================================================== //==================================================================================================
// Matrix operations // Matrix operations
//================================================================================================== //==================================================================================================
SOURCENAME CLASSNAME::normalized() const
{
SOURCENAME result;
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.normalized().eval()); });
return result;
}
SOURCENAME CLASSNAME::transpose() const SOURCENAME CLASSNAME::transpose() const
{ {
SOURCENAME result; SOURCENAME result;
@ -239,6 +246,13 @@ struct CLASSNAME::payload
return result; return result;
} }
SOURCENAME CLASSNAME::adjoint() const
{
SOURCENAME result;
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.adjoint().eval()); });
return result;
}
SOURCENAME CLASSNAME::cwiseAbs() const SOURCENAME CLASSNAME::cwiseAbs() const
{ {
SOURCENAME result; SOURCENAME result;
@ -267,14 +281,12 @@ struct CLASSNAME::payload
return result; return result;
} }
SOURCENAME CLASSNAME::adjoint() const #if !defined(USE_CONST)
void CLASSNAME::normalize()
{ {
SOURCENAME result; storage_->apply([](auto& blk) { blk.normalize(); });
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.adjoint().eval()); });
return result;
} }
#if !defined(USE_CONST)
void CLASSNAME::transposeInPlace() void CLASSNAME::transposeInPlace()
{ {
storage_->apply([](auto& blk) { blk.transposeInPlace(); }); storage_->apply([](auto& blk) { blk.transposeInPlace(); });

View file

@ -62,6 +62,13 @@
TYPE CLASSNAME::operator()(Index i, Index j) const { return storage_->data(i,j); } TYPE CLASSNAME::operator()(Index i, Index j) const { return storage_->data(i,j); }
TYPE CLASSNAME::operator()(Index i) const { return storage_->data.data()[i]; } TYPE CLASSNAME::operator()(Index i) const { return storage_->data.data()[i]; }
SOURCENAME CLASSNAME::normalized() const
{
SOURCENAME result;
result.storage()->assign(storage_->data.normalized().eval());
return result;
}
SOURCENAME CLASSNAME::transpose() const SOURCENAME CLASSNAME::transpose() const
{ {
SOURCENAME result; SOURCENAME result;
@ -112,6 +119,11 @@
} }
#if !defined(USE_CONST) #if !defined(USE_CONST)
void CLASSNAME::normalize()
{
storage_->data.normalize();
}
void CLASSNAME::transposeInPlace() void CLASSNAME::transposeInPlace()
{ {
storage_->data.transposeInPlace(); storage_->data.transposeInPlace();

View file

@ -75,12 +75,18 @@ TYPE const& CLASSNAME::operator()(std::size_t index) const { return storage_->da
const TYPE* CLASSNAME::data() const { return storage_->data.data(); } const TYPE* CLASSNAME::data() const { return storage_->data.data(); }
TYPE* CLASSNAME::data() { return storage_->data.data(); } TYPE* CLASSNAME::data() { return storage_->data.data(); }
CLASSNAME CLASSNAME::normalized() const
{
CLASSNAME result(*this);
result.storage_->data.normalize();
return result;
}
CLASSNAME CLASSNAME::transpose() const CLASSNAME CLASSNAME::transpose() const
{ {
CLASSNAME result(*this); CLASSNAME result(*this);
result.storage_->data.transposeInPlace(); result.storage_->data.transposeInPlace();
return result; return result;
} }
CLASSNAME CLASSNAME::conjugate() const CLASSNAME CLASSNAME::conjugate() const
@ -97,6 +103,11 @@ CLASSNAME CLASSNAME::adjoint() const
return result; return result;
} }
void CLASSNAME::normalize()
{
storage_->data.normalize();
}
void CLASSNAME::transposeInPlace() void CLASSNAME::transposeInPlace()
{ {
storage_->data.transposeInPlace(); storage_->data.transposeInPlace();

View file

@ -18,6 +18,7 @@ namespace rotgen::tests
using EigenMatrix = Eigen::Matrix<typename T::value_type, Eigen::Dynamic, Eigen::Dynamic>; using EigenMatrix = Eigen::Matrix<typename T::value_type, Eigen::Dynamic, Eigen::Dynamic>;
EigenMatrix ref(input.rows(), input.cols()); EigenMatrix ref(input.rows(), input.cols());
prepare([&](auto r, auto c) { return input(r,c); }, ref); prepare([&](auto r, auto c) { return input(r,c); }, ref);
TTS_EQUAL(input.norm() , ref.norm()); TTS_EQUAL(input.norm() , ref.norm());
@ -31,5 +32,23 @@ namespace rotgen::tests
TTS_EQUAL(lpNorm<1>(input) , ref.template lpNorm<1>()); TTS_EQUAL(lpNorm<1>(input) , ref.template lpNorm<1>());
TTS_EQUAL(lpNorm<2>(input) , ref.template lpNorm<2>()); TTS_EQUAL(lpNorm<2>(input) , ref.template lpNorm<2>());
TTS_EQUAL(lpNorm<rotgen::Infinity>(input) , ref.template lpNorm<Eigen::Infinity>()); TTS_EQUAL(lpNorm<rotgen::Infinity>(input) , ref.template lpNorm<Eigen::Infinity>());
if constexpr(T::IsVectorAtCompileTime)
{
EigenMatrix e_norm = ref.normalized();
using mat_t = rotgen::matrix<typename T::value_type,rotgen::Dynamic,rotgen::Dynamic,T::storage_order>;
mat_t norm_ref(input.rows(), input.cols());
prepare([&](auto r, auto c) { return e_norm(r,c); }, norm_ref);
TTS_EQUAL(input.normalized(), norm_ref);
TTS_EQUAL(normalized(input), norm_ref);
auto m_norm = input;
m_norm.normalize();
TTS_EQUAL(m_norm, norm_ref);
auto f_norm = input;
normalize(f_norm);
TTS_EQUAL(f_norm, norm_ref);
}
} }
} }