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() { return *this; }
concrete_type transpose() const
concrete_type normalized() const requires(IsVectorAtCompileTime)
{
return concrete_type(static_cast<parent const &>(*this).transpose());
}
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());
return concrete_type(base().normalized());
}
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 cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); }
concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); }
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 adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); }

View file

@ -123,26 +123,24 @@ namespace rotgen
decltype(auto) noalias() const { 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 cwiseAbs2() const { return concrete_type(base().cwiseAbs2()); }
concrete_type cwiseInverse() const { return concrete_type(base().cwiseInverse()); }
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 adjointInPlace() requires(!is_immutable) { parent::adjointInPlace(); }

View file

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

View file

@ -126,11 +126,11 @@ namespace rotgen
}
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 res = static_cast<parent const &>(*this).eval();
auto res = base().eval();
return as_concrete_type<decltype(res)>(res);
}
@ -146,22 +146,33 @@ namespace rotgen
else return *this;
}
auto transpose() const
auto normalized() const requires(IsVectorAtCompileTime)
{
auto res = static_cast<parent const &>(*this).transpose();
return as_concrete_type<decltype(res)>(res);
if constexpr(use_expression_templates) return base().normalized();
else return as_concrete_type<decltype(base().normalized())>(base().normalized());
}
auto conjugate() const
auto transpose() const
{
auto res = static_cast<parent const &>(*this).conjugate();
return as_concrete_type<decltype(res)>(res);
if constexpr(use_expression_templates) return base().transpose();
else return as_concrete_type<decltype(base().transpose())>(base().transpose());
}
auto adjoint() const
{
auto res = static_cast<parent const &>(*this).adjoint();
return as_concrete_type<decltype(res)>(res);
if constexpr(use_expression_templates) return base().adjoint();
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(); }

View file

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

View file

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

View file

@ -27,10 +27,12 @@ namespace rotgen
arg.conservativeResize(new_rows, new_cols);
}
decltype(auto) transpose(concepts::entity auto const& arg) { return arg.transpose(); }
decltype(auto) conjugate(concepts::entity auto const& arg) { return arg.conjugate(); }
decltype(auto) normalized(concepts::entity auto const& arg) { return arg.normalized(); }
decltype(auto) transpose (concepts::entity auto const& arg) { return arg.transpose(); }
decltype(auto) conjugate (concepts::entity auto const& arg) { return arg.conjugate(); }
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 adjointInPlace(concepts::entity auto& arg) { arg.adjointInPlace(); }

View file

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

View file

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

View file

@ -35,6 +35,7 @@ class ROTGEN_EXPORT CLASSNAME
void resize(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 conjugate() const;
CLASSNAME adjoint() const;
@ -44,6 +45,7 @@ class ROTGEN_EXPORT CLASSNAME
CLASSNAME cwiseInverse() const;
CLASSNAME cwiseSqrt() const;
void normalize();
void transposeInPlace();
void adjointInPlace();

View file

@ -225,6 +225,13 @@ struct CLASSNAME::payload
//==================================================================================================
// 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 result;
@ -239,6 +246,13 @@ struct CLASSNAME::payload
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 result;
@ -267,14 +281,12 @@ struct CLASSNAME::payload
return result;
}
SOURCENAME CLASSNAME::adjoint() const
#if !defined(USE_CONST)
void CLASSNAME::normalize()
{
SOURCENAME result;
storage_->apply([&](const auto& blk) { result.storage()->assign(blk.adjoint().eval()); });
return result;
storage_->apply([](auto& blk) { blk.normalize(); });
}
#if !defined(USE_CONST)
void CLASSNAME::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) 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 result;
@ -112,6 +119,11 @@
}
#if !defined(USE_CONST)
void CLASSNAME::normalize()
{
storage_->data.normalize();
}
void CLASSNAME::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(); }
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 result(*this);
result.storage_->data.transposeInPlace();
return result;
}
CLASSNAME CLASSNAME::conjugate() const
@ -97,6 +103,11 @@ CLASSNAME CLASSNAME::adjoint() const
return result;
}
void CLASSNAME::normalize()
{
storage_->data.normalize();
}
void CLASSNAME::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>;
EigenMatrix ref(input.rows(), input.cols());
prepare([&](auto r, auto c) { return input(r,c); }, ref);
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<2>(input) , ref.template lpNorm<2>());
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);
}
}
}