Sometime ago user ggael gave an answer to the
problem of mapping a eigen::vectorXf to an eigen::matrixXf.
Now, i need to do something similar, but to an existing matrix,
e.g i know i can:
for(int i=0;i<p;++i){
VectorXf vec=q.col(i);
/*q is a p**2 by n matrix*/
Map<MatrixXf> qi(vec.data(),p,p);
/*run function that uses qi to produce a scalare and store that scalar*/
}
but (it seems to me) it would be more efficient to
create qi once and for all outside the loop and then
use the same qi over and over again (is that right?)
Also, i wonder whether the intermediate step where
i map q.col(i) to vec is really necessary...
A recent answer proposes to do:
qi=Map<MatrixXd>(vec.data(),p,p);
but doing that yields:
In function ‘Eigen::VectorXi DepType(const MatrixXf&, const MatrixXf&, const int&)’:
DeC.cpp:279:34: error: no matching function for call to ‘Eigen::Map<Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001> >::Map(Eigen::PlainObjectBase<Eigen::Matrix<float, -0x00000000000000001, 1> >::Scalar*, int&, int&)’
DeC.cpp:279:34: note: candidates are:
/eigen/Eigen/src/Core/Map.h:179:12: note: Eigen::Map<MatrixType, MapOptions, StrideType>::Map(Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType, Eigen::Map<MatrixType, MapOptions, StrideType>::Index, Eigen::Map<MatrixType, MapOptions, StrideType>::Index, const StrideType&) [with PlainObjectType = Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001>, int MapOptions = 0, StrideType = Eigen::Stride<0, 0>, Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType = double*, Eigen::Map<MatrixType, MapOptions, StrideType>::Index = long int]
/home/kaveh/Desktop/work/p1/geqw4/vi3/out/sp/ccode/eigen/Eigen/src/Core/Map.h:179:12: note: no known conversion for argument 1 from ‘Eigen::PlainObjectBase<Eigen::Matrix<float, -0x00000000000000001, 1> >::Scalar* {aka float*}’ to ‘double*’
/eigen/Eigen/src/Core/Map.h:166:12: note: Eigen::Map<MatrixType, MapOptions, StrideType>::Map(Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType, Eigen::Map<MatrixType, MapOptions, StrideType>::Index, const StrideType&) [with PlainObjectType = Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001>, int MapOptions = 0, StrideType = Eigen::Stride<0, 0>, Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType = double*, Eigen::Map<MatrixType, MapOptions, StrideType>::Index = long int]
/eigen/Eigen/src/Core/Map.h:166:12: note: no known conversion for argument 1 from ‘Eigen::PlainObjectBase<Eigen::Matrix<float, -0x00000000000000001, 1> >::Scalar* {aka float*}’ to ‘double*’
/eigen/Eigen/src/Core/Map.h:154:12: note: Eigen::Map<MatrixType, MapOptions, StrideType>::Map(Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType, const StrideType&) [with PlainObjectType = Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001>, int MapOptions = 0, StrideType = Eigen::Stride<0, 0>, Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType = double*]
/eigen/Eigen/src/Core/Map.h:154:12: note: candidate expects 2 arguments, 3 provided
/eigen/Eigen/src/Core/Map.h:119:79: note: Eigen::Map<Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001> >::Map(const Eigen::Map<Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001> >&)
/eigen/Eigen/src/Core/Map.h:119:79: note: candidate expects 1 argument, 3 provided
e.g. it seems Eigen thinks qi is a vector....:(
The following:
qi=Map<MatrixXd>(vec.data(),p,p);
means that you want to copy the coefficients of Map(vec.data(),p,p) into the matrix referenced by qi. However, what you actually want is to re-initialize the Map<> object. To do so you must call the constructor again using the construct new syntax of C++:
new (&qi) Map<MatrixXd>(vec.data(),p,p);
Moreover, I must say that a Map<> object is extremely lightweight: it is only one pointer and 2 integers that are statically allocated on the stack. So moving the declaration of Map<> qi outside the loop will have zero effect on the performance. On the other hand, note that you do not need to copy q.col(i) into a temporary buffer. If q is column major, you can directly do:
Map<MatrixXf> qi(q.col(i).data(),p,p);
Related
I would like to swap parts of two maps using a standard algorithm, but somehow iterators on map do not seem to be swappable. I am surely missing something.
Example
#include<map>
#include<algorithm>
auto function(std::map<int,int> m1, std::map<int,int> m2)
{
auto first = m1.begin();
auto last = first;
std::advance(last, 3);
std::swap_ranges(first, last, m2.begin());
}
Error
See it on compiler explorer: https://godbolt.org/z/6bn1xYTTr
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/stl_tree.h:63,
from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/map:60,
from <source>:1:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/stl_algobase.h: In instantiation of 'void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = _Rb_tree_iterator<pair<const int, int> >; _ForwardIterator2 = _Rb_tree_iterator<pair<const int, int> >]':
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/stl_algobase.h:212:16: required from '_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = _Rb_tree_iterator<pair<const int, int> >; _ForwardIterator2 = _Rb_tree_iterator<pair<const int, int> >]'
<source>:9:21: required from here
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/stl_algobase.h:182:11: error: use of deleted function 'typename std::enable_if<(! std::__and_<std::__is_swappable<_T1>, std::__is_swappable<_T2> >::value)>::type std::swap(pair<_T1, _T2>&, pair<_T1, _T2>&) [with _T1 = const int; _T2 = int; typename enable_if<(! __and_<__is_swappable<_T1>, __is_swappable<_T2> >::value)>::type = void]'
182 | swap(*__a, *__b);
| ~~~~^~~~~~~~~~~~
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/stl_algobase.h:64:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/stl_pair.h:715:5: note: declared here
715 | swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;
| ^~~~
Compiler returned: 1
std::map is implemented as some sort of binary search tree, and its structure depends on each item's key never changing. Thus the type returned by *m1.begin() is std::pair<const int, int>&. Note that the first int is const. You cannot modify it.
std::swap_ranges tries to swap each element of the first range with its corresponding element in the second range, but std::pair<const int, int>s can't be swapped due to the constness of their first element.
I want to use "reshape()" fuction in Eigen unsupported tensor, but my source code cannot be compiled.
The compilation was done as follows.
g++ -std=c++14 -I (path to Eigen) eigen_practice.cpp -o eigen_practice
and here is my source code.
# include "unsupported/Eigen/CXX11/Tensor"
using namespace Eigen;
int main(){
Tensor<float, 2> input(7, 11);
Eigen::array<int, 3> three_dims{{7, 11, 1}};
Tensor<float, 3> result = input.reshape(three_dims);
return 0;
}
And here is the error messeage.
In file included from eigen_practice.cpp:12:
In file included from /Users/yamamototatsuto/Dropbox/include_for_C++/eigen/unsupported/Eigen/CXX11/Tensor:145:
/Users/yamamototatsuto/Dropbox/include_for_C++/eigen/unsupported/Eigen/CXX11/src/Tensor/Tensor.h:397:7: error:
no matching member function for call to 'resize'
resize(TensorEvaluator<const Assign, DefaultDevice>(assign, Defaul...
^~~~~~
eigen_practice.cpp:63:28: note: in instantiation of function template
specialization 'Eigen::Tensor<float, 3, 0,
long>::Tensor<Eigen::TensorReshapingOp<const std::__1::array<int, 3>,
Eigen::Tensor<float, 2, 0, long> > >' requested here
Tensor<float, 3> result = input.reshape(three_dims);
^
/Users/yamamototatsuto/Dropbox/include_for_C++/eigen/unsupported/Eigen/CXX11/src/Tensor/Tensor.h:423:10: note:
candidate function template not viable: no known conversion from 'const
Eigen::TensorEvaluator<const Eigen::TensorAssignOp<Eigen::Tensor<float, 3,
0, long>, const Eigen::TensorReshapingOp<const std::__1::array<int, 3>,
Eigen::Tensor<float, 2, 0, long> > >, Eigen::DefaultDevice>::Dimensions'
(aka 'const std::__1::array<int, 3>') to 'Eigen::Tensor<float, 3, 0,
long>::Index' (aka 'long') for 1st argument
void resize(Index firstDimension, IndexTypes... otherDimensions)
^
/Users/yamamototatsuto/Dropbox/include_for_C++/eigen/unsupported/Eigen/CXX11/src/Tensor/Tensor.h:432:28: note:
candidate function not viable: no known conversion from
'array<int, [...]>' to 'const array<long, [...]>' for 1st argument
EIGEN_DEVICE_FUNC void resize(const array<Index, NumIndices>& dimensions)
^
/Users/yamamototatsuto/Dropbox/include_for_C++/eigen/unsupported/Eigen/CXX11/src/Tensor/Tensor.h:450:28: note:
candidate function not viable: no known conversion from 'const
Eigen::TensorEvaluator<const Eigen::TensorAssignOp<Eigen::Tensor<float, 3,
0, long>, const Eigen::TensorReshapingOp<const std::__1::array<int, 3>,
Eigen::Tensor<float, 2, 0, long> > >, Eigen::DefaultDevice>::Dimensions'
(aka 'const std::__1::array<int, 3>') to 'const
DSizes<Eigen::Tensor<float, 3, 0, long>::Index, NumIndices>' (aka 'const
DSizes<long, NumIndices>') for 1st argument
EIGEN_DEVICE_FUNC void resize(const DSizes<Index, NumIndices>& dimensions) {
^
/Users/yamamototatsuto/Dropbox/include_for_C++/eigen/unsupported/Eigen/CXX11/src/Tensor/Tensor.h:479:10: note:
candidate template ignored: could not match 'Sizes' against 'array'
void resize(const Sizes<Indices...>& dimensions) {
^
/Users/yamamototatsuto/Dropbox/include_for_C++/eigen/unsupported/Eigen/CXX11/src/Tensor/Tensor.h:459:10: note:
candidate function not viable: requires 0 arguments, but 1 was provided
void resize()
^
1 error generated.
This source code is just a copy of what is in the documentation.
(https://eigen.tuxfamily.org/dox/unsupported/eigen_tensors.html)
So it should compile, but it doesn't.
How can I solve it?
And why the error message mentions about "resize()" function?
template <typename T>
bool operator()(const T* parameters, T* residuals) const
{
Eigen::Matrix<T, 3, 1> pose(parameters[0],parameters[1],parameters[2]);
Eigen::Vector3f pose1 = pose.cast<float>();
Eigen::Affine2f transform = occ->getTransformForState(pose1); // transform: rotation->translation
Eigen::Vector3f tmp1 = occ->interpMapValueWithDerivatives( transform * currPoint);
Eigen::Matrix<T, 3, 1> transformedPointData(tmp1.cast<T>()); /// {M,dM/dx,dM/dy}
T funVal = T(1) - transformedPointData[0];
residuals[0] = funVal;
return true;
}
I have a template member function like above. During compilation, it reports
error: expected primary-expression before ‘float’
Eigen::Vector3f pose1 = pose.cast<float>();
I have to cast to type "float" to make it consistent with "getTransformForState" function's input and output.
I compared with other examples provided by Eigen Library but couldnt find anything wrong.
Any ideas are highly appreciated !
-------------------- update ------------------------
By changing as pose.template cast<float>()
The error is changed as:
/usr/include/eigen3/Eigen/src/Core/MathFunctions.h: In instantiation of ‘static NewType Eigen::internal::cast_impl<OldType, NewType>::run(const OldType&) [with OldType = ceres::Jet<double, 3>; NewType = float]’:
/usr/include/eigen3/Eigen/src/Core/MathFunctions.h:328:44: required from ‘NewType Eigen::internal::cast(const OldType&) [with OldType = ceres::Jet<double, 3>; NewType = float]’
/usr/include/eigen3/Eigen/src/Core/Functors.h:351:104: required from ‘const NewType Eigen::internal::scalar_cast_op<Scalar, NewType>::operator()(const Scalar&) const [with Scalar = ceres::Jet<double, 3>; NewType = float]’
/usr/include/eigen3/Eigen/src/Core/CwiseUnaryOp.h:114:75: required from ‘const Scalar Eigen::CwiseUnaryOpImpl<UnaryOp, XprType, Eigen::Dense>::coeff(Eigen::CwiseUnaryOpImpl<UnaryOp, XprType, Eigen::Dense>::Index) const [with UnaryOp = Eigen::internal::scalar_cast_op<ceres::Jet<double, 3>, float>; XprType = const Eigen::Matrix<ceres::Jet<double, 3>, 3, 1, 0, 3, 1>; Eigen::CwiseUnaryOpImpl<UnaryOp, XprType, Eigen::Dense>::Scalar = float; Eigen::CwiseUnaryOpImpl<UnaryOp, XprType, Eigen::Dense>::Index = long int]’
/usr/include/eigen3/Eigen/src/Core/DenseCoeffsBase.h:495:33: required from ‘void Eigen::DenseCoeffsBase<Derived, 1>::copyCoeff(Eigen::DenseCoeffsBase<Derived, 1>::Index, const Eigen::DenseBase<OtherDerived>&) [with OtherDerived = Eigen::CwiseUnaryOp<Eigen::internal::scalar_cast_op<ceres::Jet<double, 3>, float>, const Eigen::Matrix<ceres::Jet<double, 3>, 3, 1, 0, 3, 1> >; Derived = Eigen::Matrix<float, 3, 1>; Eigen::DenseCoeffsBase<Derived, 1>::Index = long int]’
/usr/include/eigen3/Eigen/src/Core/Assign.h:180:5: required from ‘static void Eigen::internal::assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Index, Stop>::run(Derived1&, const Derived2&) [with Derived1 = Eigen::Matrix<float, 3, 1>; Derived2 = Eigen::CwiseUnaryOp<Eigen::internal::scalar_cast_op<ceres::Jet<double, 3>, float>, const Eigen::Matrix<ceres::Jet<double, 3>, 3, 1, 0, 3, 1> >; int Index = 0; int Stop = 3]’
/usr/include/eigen3/Eigen/src/Core/Assign.h:314:21: [ skipping 5 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/eigen3/Eigen/src/Core/Matrix.h:281:31: required from ‘Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Matrix(const Eigen::MatrixBase<OtherDerived>&) [with OtherDerived = Eigen::CwiseUnaryOp<Eigen::internal::scalar_cast_op<ceres::Jet<double, 3>, float>, const Eigen::Matrix<ceres::Jet<double, 3>, 3, 1, 0, 3, 1> >; _Scalar = float; int _Rows = 3; int _Cols = 1; int _Options = 0; int _MaxRows = 3; int _MaxCols = 1]’
The error message means the compiler doesn't know that pose.cast is a template. There are three basic options for what a class member .foo can be:
A value (e.g. a data member or an enum value)
A type name (e.g. something defined with typedef)
A template for one of the above.
In your case, pose is of type Eigen::Matrix<T, 3, 1>. The compiler doesn't yet know what Eigen::Matrix<T, 3, 1> looks like because it depends on what T is (someone could have specialized Eigen::Matrix differently for different types).
So when you access a member of an unknown class (as with pose.cast), the compiler assumes it's option #1 (a value). This leads to it parsing pose.cast < as the beginning of a less-than comparison. The next token (float) triggers an error because the compiler was expecting another value, not a type name.
The fix is to tell the compiler explicitly that .cast is a template:
Eigen::Vector3f pose1 = pose.template cast<float>();
(The fix for case #2 is to use the typename keyword to force interpretation as a type name.)
I'm trying to convert a Matrix3d rotation to a Quaternion<double>, but I got only weird compiler errors so far. The code I'm using is:
Quaternion<double> getQuaternionFromRotationMatrix(const Matrix3d& mat)
{
AngleAxisd aa;
aa = mat;
Quaternion<double> q = aa;// conversion error
return q;
}
And the compiler errors:
path/src/Utils.cpp: In function ‘Eigen::Quaternion<double> Utils::getQuaternionFromRotationMatrix(const Matrix3d&)’:
path/src/Utils.cpp:55:26: error: conversion from ‘Eigen::AngleAxisd {aka Eigen::AngleAxis<double>}’ to non-scalar type ‘Eigen::Quaternion<double>’ requested
In file included from /usr/local/include/eigen3/Eigen/Core:283:0,
from /usr/local/include/eigen3/Eigen/Dense:1,
from path/include/Utils.h:4,
from path/src/Utils.cpp:1:
/usr/local/include/eigen3/Eigen/src/Core/Assign.h: In member function ‘Derived& Eigen::DenseBase<Derived>::lazyAssign(const Eigen::DenseBase<OtherDerived>&) [with OtherDerived = Eigen::Matrix<double, 3, 1>, Derived = Eigen::Block<Eigen::Matrix<double, 4, 4>, 4, -0x00000000000000001, true, true>]’:
/usr/local/include/eigen3/Eigen/src/Core/Assign.h:534:123: instantiated from ‘static Derived& Eigen::internal::assign_selector<Derived, OtherDerived, false, false>::run(Derived&, const OtherDerived&) [with Derived = Eigen::Block<Eigen::Matrix<double, 4, 4>, 4, -0x00000000000000001, true, true>, OtherDerived = Eigen::Matrix<double, 3, 1>]’
/usr/local/include/eigen3/Eigen/src/Core/Assign.h:574:89: instantiated from ‘Derived& Eigen::MatrixBase<Derived>::operator=(const Eigen::DenseBase<OtherDerived>&) [with OtherDerived = Eigen::Matrix<double, 3, 1>, Derived = Eigen::Block<Eigen::Matrix<double, 4, 4>, 4, -0x00000000000000001, true, true>]’
path/src/Utils.cpp:34:20: instantiated from here
/usr/local/include/eigen3/Eigen/src/Core/Assign.h:504:3: error: static assertion failed: "YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES"
Does someone know how to convert between both representations?
The constructors from an AngleAxis or Matrix are explicit meaning you have to write the conversion as follow:
Matrix3f mat;
Quaternionf q(mat);
or
Quaternionf q;
q = mat;
Same for AngleAxis.
I have this which works fine:
MatrixXf Sig(p,p);
Sig.selfadjointView<Lower>().rankUpdate(xSub.adjoint());
Now, i need to also get the upper triangular
part of Sig. This answer seems to suggest
to do
Sig.triangularView<StrictUpper>()=Sig.adjoint().triangularView<StrictUpper>();
But doing that causes mayhem --or as the compiler calls it:
DetMCD_1.cpp: In function ‘float CStep(const MatrixXf&, Eigen::VectorXi&, const int&, const int&)’:
DetMCD_1.cpp:263:21: error: ‘StrictUpper’ was not declared in this scope
DetMCD_1.cpp:263:34: error: no matching function for call to ‘Eigen::Matrix<float, -0x00000000000000001, -0x00000000000000001>::triangularView()’
DetMCD_1.cpp:263:34: note: candidates are:
/home/kaveh/R/x86_64-pc-linux-gnu-library/2.15/RcppEigen/include/Eigen/src/Core/MatrixBase.h:248:79: note: template<unsigned int Mode> typename Eigen::MatrixBase<Derived>::TriangularViewReturnType<Mode>::Type Eigen::MatrixBase::triangularView() [with unsigned int Mode = Mode, Derived = Eigen::Matrix<float, -0x00000000000000001, -0x00000000000000001>, typename Eigen::MatrixBase<Derived>::TriangularViewReturnType<Mode>::Type = <type error>]
/home/kaveh/R/x86_64-pc-linux-gnu-library/2.15/RcppEigen/include/Eigen/src/Core/MatrixBase.h:249:84: note: template<unsigned int Mode> typename Eigen::MatrixBase<Derived>::ConstTriangularViewReturnType<Mode>::Type Eigen::MatrixBase::triangularView() const [with unsigned int Mode = Mode, Derived = Eigen::Matrix<float, -0x00000000000000001, -0x00000000000000001>, typename Eigen::MatrixBase<Derived>::ConstTriangularViewReturnType<Mode>::Type = <type error>]
DetMCD_1.cpp:263:78: error: no matching function for call to ‘Eigen::Transpose<const Eigen::Matrix<float, -0x00000000000000001, -0x00000000000000001> >::triangularView() const’
DetMCD_1.cpp:263:78: note: candidates are:
/home/kaveh/R/x86_64-pc-linux-gnu-library/2.15/RcppEigen/include/Eigen/src/Core/MatrixBase.h:248:79: note: template<unsigned int Mode> typename Eigen::MatrixBase<Derived>::TriangularViewReturnType<Mode>::Type Eigen::MatrixBase::triangularView() [with unsigned int Mode = Mode, Derived = Eigen::Transpose<const Eigen::Matrix<float, -0x00000000000000001, -0x00000000000000001> >, typename Eigen::MatrixBase<Derived>::TriangularViewReturnType<Mode>::Type = <type error>]
/home/kaveh/R/x86_64-pc-linux-gnu-library/2.15/RcppEigen/include/Eigen/src/Core/MatrixBase.h:249:84: note: template<unsigned int Mode> typename Eigen::MatrixBase<Derived>::ConstTriangularViewReturnType<Mode>::Type Eigen::MatrixBase::triangularView() const [with unsigned int Mode = Mode, Derived = Eigen::Transpose<const Eigen::Matrix<float, -0x00000000000000001, -0x00000000000000001> >, typename Eigen::MatrixBase<Derived>::ConstTriangularViewReturnType<Mode>::Type = <type error>]
make: *** [DetMCD_1.o] Error 1
My question is this: given that i have
the lower triangular part of Sig, how
to convince eigen to return me the full
matrix?
This is because there is typo, it's StrictlyUpper, and not StrictUpper. See the respective doc. The following two lines are equivalent:
Long version:
M.triangularView<StrictlyUpper>()=M.adjoint().triangularView<StrictlyUpper>();
Short version:
M.triangularView<StrictlyUpper>()=M.adjoint();
Please, also not that in most cases you do not need to explicitly compute the upper triangular part.