//================================================================================================== /* ROTGEN - Runtime Overlay for Eigen Copyright : CODE RECKONS SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== //================================================================================================== /* This file is a X-File to generate various block_impl_* definitions variant */ //================================================================================================== //================================================================================================== // Internal payload //================================================================================================== struct CLASSNAME::payload { using stride_type = Eigen::Stride; using matrix_type = Eigen::Matrix; using matrix_block_type = Eigen::Block; using matrix_storage_t = std::pair; using map_type = Eigen::Map; using map_block_type = Eigen::Block; using map_storage_t = std::pair; using data_type = std::variant; data_type data; rotgen::Index abs_i0 = 0; // absolute start row in original matrix rotgen::Index abs_j0 = 0; // absolute start col in original matrix rotgen::Index rel_i0 = 0; // relative start row in original matrix rotgen::Index rel_j0 = 0; // relative start col in original matrix template void apply(Func f) { std::visit([&](auto& blk) { return f(blk.first); }, data); } template void apply(Func f) const { std::visit([&](auto const& blk) { return f(blk.first); }, data); } payload (data_type const& o) : data(o) {} payload (SOURCENAME CONST& o, rotgen::Index i0, rotgen::Index j0, rotgen::Index ni, rotgen::Index nj) : data(matrix_storage_t{matrix_block_type{o.storage()->data,i0,j0,ni,nj},&o.storage()->data}) , abs_i0(i0), abs_j0(j0), rel_i0(i0), rel_j0(j0) {} payload (MAPNAME CONST& o, rotgen::Index i0, rotgen::Index j0, rotgen::Index ni, rotgen::Index nj) : data(map_storage_t{map_block_type{o.storage()->data,i0,j0,ni,nj},&o.storage()->data}) , abs_i0(i0), abs_j0(j0), rel_i0(i0), rel_j0(j0) {} }; //================================================================================================== // Constructors & Special Members //================================================================================================== CLASSNAME::CLASSNAME(SOURCENAME CONST& r, Index i0, Index j0, Index ni, Index nj) : storage_(std::make_unique(r, i0,j0,ni,nj)) {} CLASSNAME::CLASSNAME(MAPNAME CONST& r, Index i0, Index j0, Index ni, Index nj) : storage_(std::make_unique(r, i0,j0,ni,nj)) {} // We're building a block from a block - So we have to dig around the internals CLASSNAME::CLASSNAME(payload const& o, Index i0, Index j0, Index ni, Index nj) { // Compute absolute indices from the parent stored block Index abs_i0 = 0; Index abs_j0 = 0; std::visit( [&](auto const& blk) { abs_i0 = blk.first.startRow() + i0; abs_j0 = blk.first.startCol() + j0; } , o.data ); // Build a payload::data_type that holds the child block using absolute indices payload::data_type new_data = std::visit([&](T const& blk) -> payload::data_type { auto& [parent_block, ref] = blk; using block_type = typename T::first_type; return T{ block_type{ *ref, abs_i0, abs_j0, ni, nj }, ref }; }, o.data); storage_ = std::make_unique(new_data); storage_->abs_i0 = abs_i0; storage_->abs_j0 = abs_j0; storage_->rel_i0 = i0; storage_->rel_j0 = j0; } CLASSNAME::CLASSNAME(CLASSNAME const& o) : storage_(std::make_unique(o.storage_->data)) {} CLASSNAME::CLASSNAME(CLASSNAME&&) noexcept = default; #if !defined(USE_CONST) CLASSNAME& CLASSNAME::operator=(CLASSNAME const& o) { if (this != &o) { storage_->data = o.storage_->data; } return *this; } CLASSNAME& CLASSNAME::operator=(CLASSNAME&& o) noexcept { if (this != &o) { storage_->data = std::move(o.storage_->data); } return *this; } #endif CLASSNAME::~CLASSNAME() = default; #if !defined(USE_CONST) void CLASSNAME::assign(SOURCENAME const& m) { storage_->apply([&](auto& blk) { blk = m.storage()->data; }); } #endif //================================================================================================== // Matrix API //================================================================================================== rotgen::Index CLASSNAME::rows() const { rotgen::Index that; storage_->apply([&](const auto& blk) { that = blk.rows(); }); return that; } rotgen::Index CLASSNAME::cols() const { rotgen::Index that; storage_->apply([&](const auto& blk) { that = blk.cols(); }); return that; } rotgen::Index CLASSNAME::size() const { rotgen::Index that; storage_->apply([&](const auto& blk) { that = blk.size(); }); return that; } rotgen::Index CLASSNAME::innerStride() const { rotgen::Index that; storage_->apply([&](const auto& blk) { that = blk.innerStride(); }); return that; } rotgen::Index CLASSNAME::outerStride() const { rotgen::Index that; storage_->apply([&](const auto& blk) { that = blk.outerStride(); }); return that; } rotgen::Index CLASSNAME::startRow() const { return storage_->rel_i0; } rotgen::Index CLASSNAME::startCol() const { return storage_->rel_j0; } // Element access by (i,j) #if !defined(USE_CONST) TYPE& CLASSNAME::operator()(Index i, Index j) { TYPE* ptr = nullptr; storage_->apply([&](auto& blk) { ptr = &blk(i,j); }); return *ptr; } #endif TYPE CLASSNAME::operator()(Index i, Index j) const { TYPE ptr; storage_->apply([&](auto const& blk) { ptr = blk(i,j); }); return ptr; } // Element access by linear index #if !defined(USE_CONST) TYPE& CLASSNAME::operator()(Index index) { TYPE* ptr = nullptr; storage_->apply([&](auto& blk) { ptr = blk.data() + index; }); return *ptr; } #endif TYPE CLASSNAME::operator()(Index index) const { TYPE ptr; storage_->apply([&](auto const& blk) { ptr = *(blk.data() + index); }); return ptr; } // Raw pointer access #if !defined(USE_CONST) TYPE* CLASSNAME::data() { TYPE* ptr = nullptr; storage_->apply([&](auto& blk) { ptr = blk.data(); }); return ptr; } #endif TYPE const* CLASSNAME::data() const { TYPE const* ptr = nullptr; storage_->apply([&](auto const& blk) { ptr = blk.data(); }); return ptr; } //================================================================================================== // Matrix operations //================================================================================================== SOURCENAME CLASSNAME::normalized() const { SOURCENAME result; storage_->apply([&](const auto& blk) { result.storage()->assign(blk.normalized().eval()); }); return result; } TRANSSOURCENAME CLASSNAME::transpose() const { TRANSSOURCENAME result; storage_->apply([&](const auto& blk) { result.storage()->assign(blk.transpose().eval()); }); return result; } SOURCENAME CLASSNAME::conjugate() const { SOURCENAME result; storage_->apply([&](const auto& blk) { result.storage()->assign(blk.conjugate().eval()); }); return result; } TRANSSOURCENAME CLASSNAME::adjoint() const { TRANSSOURCENAME result; storage_->apply([&](const auto& blk) { result.storage()->assign(blk.adjoint().eval()); }); return result; } SOURCENAME CLASSNAME::cwiseAbs() const { SOURCENAME result; storage_->apply([&](const auto& blk) { result.storage()->assign(blk.cwiseAbs().eval()); }); return result; } SOURCENAME CLASSNAME::cwiseAbs2() const { SOURCENAME result; storage_->apply([&](const auto& blk) { result.storage()->assign(blk.cwiseAbs2().eval()); }); return result; } SOURCENAME CLASSNAME::cwiseInverse() const { SOURCENAME result; storage_->apply([&](const auto& blk) { result.storage()->assign(blk.cwiseInverse().eval()); }); return result; } SOURCENAME CLASSNAME::cwiseSqrt() const { SOURCENAME result; storage_->apply([&](const auto& blk) { result.storage()->assign(blk.cwiseSqrt().eval()); }); return result; } #if !defined(USE_CONST) void CLASSNAME::normalize() { storage_->apply([](auto& blk) { blk.normalize(); }); } void CLASSNAME::transposeInPlace() { storage_->apply([](auto& blk) { blk.transposeInPlace(); }); } void CLASSNAME::adjointInPlace() { storage_->apply([](auto& blk) { blk.adjointInPlace(); }); } #endif //================================================================================================== // Reductions //================================================================================================== TYPE CLASSNAME::sum() const { TYPE val{}; storage_->apply([&](const auto& blk) { val = blk.sum(); }); return val; } TYPE CLASSNAME::prod() const { TYPE val{}; storage_->apply([&](const auto& blk) { val = blk.prod(); }); return val; } TYPE CLASSNAME::mean() const { TYPE val{}; storage_->apply([&](const auto& blk) { val = blk.mean(); }); return val; } TYPE CLASSNAME::trace() const { TYPE val{}; storage_->apply([&](const auto& blk) { val = blk.trace(); }); return val; } TYPE CLASSNAME::minCoeff() const { TYPE val{}; storage_->apply([&](const auto& blk) { val = blk.minCoeff(); }); return val; } TYPE CLASSNAME::maxCoeff() const { TYPE val{}; storage_->apply([&](const auto& blk) { val = blk.maxCoeff(); }); return val; } TYPE CLASSNAME::minCoeff(Index* row, Index* col) const { TYPE val{}; storage_->apply([&](const auto& blk) { val = blk.minCoeff(row, col); }); return val; } TYPE CLASSNAME::maxCoeff(Index* row, Index* col) const { TYPE val{}; storage_->apply([&](const auto& blk) { val = blk.maxCoeff(row, col); }); return val; } TYPE CLASSNAME::squaredNorm() const { TYPE val{}; storage_->apply([&](const auto& blk) { val = blk.squaredNorm(); }); return val; } TYPE CLASSNAME::norm() const { TYPE val{}; storage_->apply([&](const auto& blk) { val = blk.norm(); }); return val; } TYPE CLASSNAME::lpNorm(int p) const { TYPE val{}; storage_->apply([&](const auto& blk) { if (p == 1) val = blk.template lpNorm<1>(); else if (p == 2) val = blk.template lpNorm<2>(); else val = blk.template lpNorm(); }); return val; } //================================================================================================== // Operators //================================================================================================== ROTGEN_EXPORT std::ostream& operator<<(std::ostream& os, CLASSNAME const& m) { m.storage_->apply([&](const auto& blk) { os << blk; }); return os; } ROTGEN_EXPORT bool operator==(CLASSNAME const& lhs, CLASSNAME const& rhs) { return std::visit ( [](auto const& lhs_blk, auto const& rhs_blk) { return lhs_blk.first == rhs_blk.first; } , lhs.storage_->data , rhs.storage_->data ); } ROTGEN_EXPORT bool operator!=(CLASSNAME const& lhs, CLASSNAME const& rhs) { return std::visit ( [](auto const& lhs_blk, auto const& rhs_blk) { return lhs_blk.first != rhs_blk.first; } , lhs.storage_->data , rhs.storage_->data ); } SOURCENAME CLASSNAME::operator-() const { SOURCENAME result; storage_->apply([&](const auto& blk) { result.storage()->assign(blk); }); return -result; } #if !defined(USE_CONST) CLASSNAME& CLASSNAME::operator+=(CLASSNAME const& rhs) { std::visit( [](auto& lhs_blk, auto const& rhs_blk) { lhs_blk.first += rhs_blk.first; } , storage_->data , rhs.storage_->data ); return *this; } CLASSNAME& CLASSNAME::operator-=(CLASSNAME const& rhs) { std::visit( [](auto& lhs_blk, auto const& rhs_blk) { lhs_blk.first -= rhs_blk.first; } , storage_->data , rhs.storage_->data ); return *this; } CLASSNAME& CLASSNAME::operator*=(CLASSNAME const& rhs) { std::visit( [](auto& lhs_blk, auto const& rhs_blk) { lhs_blk.first *= rhs_blk.first; } , storage_->data , rhs.storage_->data ); return *this; } CLASSNAME& CLASSNAME::operator*=(TYPE s) { storage_->apply([&](auto& blk) { blk *= s; }); return *this; } CLASSNAME& CLASSNAME::operator/=(TYPE s) { storage_->apply([&](auto& blk) { blk /= s; }); return *this; } #endif SOURCENAME CLASSNAME::add(CLASSNAME const& rhs) const { SOURCENAME result; result.storage()->assign( std::visit( [](auto const& lhs_blk, auto const& rhs_blk) { return (lhs_blk.first + rhs_blk.first).eval(); } , storage_->data , rhs.storage_->data ) ); return result; } SOURCENAME CLASSNAME::sub(CLASSNAME const& rhs) const { SOURCENAME result; result.storage()->assign( std::visit( [](auto const& lhs_blk, auto const& rhs_blk) { return (lhs_blk.first - rhs_blk.first).eval(); } , storage_->data , rhs.storage_->data ) ); return result; } SOURCENAME CLASSNAME::mul(CLASSNAME const& rhs) const { SOURCENAME result; result.storage()->assign( std::visit( [](auto const& lhs_blk, auto const& rhs_blk) { return (lhs_blk.first * rhs_blk.first).eval(); } , storage_->data , rhs.storage_->data ) ); return result; } SOURCENAME CLASSNAME::mul(TYPE s) const { SOURCENAME result; result.storage()->assign( std::visit( [s](auto const& lhs_blk) { return (lhs_blk.first * s).eval(); } , storage_->data ) ); return result; } SOURCENAME CLASSNAME::div(TYPE s) const { SOURCENAME result; result.storage()->assign( std::visit( [s](auto const& lhs_blk) { return (lhs_blk.first / s).eval(); } , storage_->data ) ); return result; }