Reputation: 10750
How can I avoid dynamic allocation for small Diagonal Matrices in Eigen?
I'm using Eigen 3.4. I have a N by N Diagonal Matrix W:
auto W = Eigen::DiagonalMatrix<double, Dynamic>(N);
I'd like to avoid allocation if N <= 512 by using a buffer on the stack:
double W_buffer[512];
With normal vectors and matricies, I know I can use Map
:
double y_buff[512];
auto y = Eigen::Map<VectorXd>( y_buff, N );
However, when I try the same thing with a Diagonal Matrix, it gives me an error because InnerStrideAtCompileTime
isn't a member of Eigen::DiagonalMatrix
.
In file included from eigen/Eigen/Core:311,
from eigen/Eigen/Dense:1,
from build/release/CMakeFiles/bench.dir/cmake_pch.hxx:5,
from <command-line>:
eigen/Eigen/src/Core/Map.h: In instantiation of ‘struct Eigen::internal::traits<Eigen::Map<Eigen::DiagonalMatrix<double, -1> > >’:
eigen/Eigen/src/Core/util/ForwardDeclarations.h:34:48: required from ‘struct Eigen::internal::accessors_level<Eigen::Map<Eigen::DiagonalMatrix<double, -1> > >’
eigen/Eigen/src/Core/util/ForwardDeclarations.h:101:75: required from ‘class Eigen::Map<Eigen::DiagonalMatrix<double, -1> >’
include/volar/estimators.hpp:203:18: required from ‘static volar::R volar::PolyLE<Degree>::estimate(volar::R, volar::ViewR, volar::ViewR, const Kernel&) [with Kernel = volar::UniformK; int Degree = 1; volar::R = double; volar::ViewR = volar::View<double>]’
include/volar/kernel_smoothing.hpp:81:64: required from ‘volar::R volar::LocalRFT<Estimator, Kernel>::operator()(volar::R) const [with Estimator = volar::EigenLinearLE; Kernel = volar::UniformK; volar::R = double]’
bench/core.cpp:43:23: required from ‘void localRF(benchmark::State&) [with Method = volar::EigenLinearLE; Kernel = volar::UniformK]’
bench/core.cpp:96:1: required from here
eigen/Eigen/src/Core/Map.h:30:53: error: ‘InnerStrideAtCompileTime’ is not a member of ‘Eigen::DiagonalMatrix<double, -1>’
30 | ? int(PlainObjectType::InnerStrideAtCompileTime)
| ^~~~~~~~~~~~~~~~~~~~~~~~
In file included from eigen/Eigen/Core:163,
from eigen/Eigen/Dense:1,
from build/release/CMakeFiles/bench.dir/cmake_pch.hxx:5,
from <command-line>:
Upvotes: 2
Views: 113
Reputation: 59
Instead of trying to Map
a DiagonalMatrix
you can do it the "normal" way that you describe and use the asDiagonal()
method.
Maybe slightly less clean to have to type y.asDiagonal()
instead of just y
...Maybe you could do something with Eigen::Ref
to keep a reference to the diagonal matrix that came from your vector but I'm not sure if that would work.
asDiagonal()
:
https://eigen.tuxfamily.org/dox/classEigen_1_1MatrixBase.html#a14235b62c90f93fe910070b4743782d0
Upvotes: 1
Reputation:
The third template parameter of Eigen::DiagonalMatrix
, MaxSizeAtCompileTime
lets you do just that.
When combined with Eigen::Dynamic
, the DiagonalMatrix
will have an internal buffer large enough for MaxSizeAtCompileTime
, but it will still be dynamically sized.
For example, the following is the equivalent of what you were trying to do with an external buffer:
auto W = Eigen::DiagonalMatrix<double, Eigen::Dynamic, 512>(N)
Obviously, attempting to initialize it with a size greater than MaxSizeAtCompileTime
will fail at runtime (with an assert), but that's not any worse than what you have to deal with when using Map
.
Upvotes: 2