I am trying to compile my code, which has matrix multiplication, with intel C++ compiler. For the matrix multiplication, I am using Eigen library. This is the sample code. I am using VS2013 with the latest version of Eigen library.
#define EIGEN_USE_MKL_ALL
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix<double, 1, 200, RowMajor> y_pred;
y_pred.setRandom(); // Eigen library function
double learning_rate = 0.5;
cout << learning_rate * y_pred << endl;
return 1;
}
When I am using intel C++ compiler I get the following error:
1>error : more than one operator "*" matches these operands:
1> function "Eigen::operator*(const double &, const Eigen::MatrixBase<Eigen::Matrix<double, 1, 200, 1, 1, 200>> &)"
1> function "Eigen::operator*(const std::complex<double> &, const Eigen::MatrixBase<Eigen::Matrix<double, 1, 200, 1, 1, 200>> &)"
1> function "Eigen::internal::operator*(const float &, const Eigen::Matrix<std::complex<float>, -1, -1, 0, -1, -1> &)"
1> function "Eigen::internal::operator*(const float &, const Eigen::Matrix<std::complex<float>, -1, 1, 0, -1, 1> &)"
1> function "Eigen::internal::operator*(const float &, const Eigen::Matrix<std::complex<float>, 1, -1, 1, 1, -1> &)"
1> function "Eigen::internal::operator*(const float &, const Eigen::Matrix<Eigen::scomplex, -1, -1, 1, -1, -1> &)"
1> operand types are: float * Eigen::Matrix<double, 1, 200, 1, 1, 200>
1> y_pred = learning_rate * y_pred;
You can explicitly perform a scalar computation:
cout << learning_rate * y_pred.array() << endl;
Related
I would like to use MatrixXd class for meshes with offsets (0.5, 0) and (0, 0.5). In mathematical formulas, velocity is calculated between cells i,i+1, and this is written as vel(i+0.5,j). I would like to introduce syntax like this one:
#include <Eigen/Dense>
int main() {
Eigen::MatrixXd m = Eigen::MatrixXd::Zero(5,5);
// Want to use similar syntax:
// m(0, 1.5) = 1.0;
// and
// m(3.5, 1) = 2.0;
// Instead of:
m(0, 2) = 1.0;
m(4, 1) = 2.0;
}
Using EIGEN_MATRIXBASE_PLUGIN like this one:
inline Scalar& operator()(int r, int c) {
return Base::operator()(r, c);
}
inline Scalar& operator()(double r, int c) {
return Base::operator()(int(r + 0.5), c);
}
inline Scalar& operator()(int r, double c) {
return Base::operator()(r, int(c + 0.5));
}
However, this approach:
Works only for only X-axis or only Y-axis offset, not both at the same time.
Works only for specific offset hardcoded into plugin.
Breaks some internal Eigen convections, which can be demostrated by trying to compile BiCG example with IncompleteLUT preconditioner:
int n = 10000;
VectorXd x(n), b(n);
SparseMatrix<double> A(n,n);
/* ... fill A and b ... */
BiCGSTAB<SparseMatrix<double>,IncompleteLUT<double>> solver;
solver.compute(A);
x = solver.solve(b);
Causes following errors:
term does not evaluate to a function taking 1 arguments
'Eigen::SparseMatrix<double,1,int>::insertBackByOuterInnerUnordered': function does not take 1 arguments
Adding operator()(double offset_col, double offset_row) to adress second issue like this:
double r_offset = -0.5, c_offset = -0.5;
inline void set_r_offset(double val) { r_offset = val; }
inline void set_c_offset(double val) { c_offset = val; }
inline double get_r_offset() { return r_offset; }
inline double get_c_offset() { return c_offset; }
inline Scalar& operator()(double r, double c) {
// double r_offset = -0.5, c_offset = -0.5;
return Base::operator()(int(r - r_offset), int(c - c_offset));
}
This causes illegal free:
==6035== Invalid free() / delete / delete[] / realloc()
==6035== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6035== by 0x4E4224A: aligned_free (Memory.h:177)
==6035== by 0x4E4224A: conditional_aligned_free<true> (Memory.h:230)
==6035== by 0x4E4224A: conditional_aligned_delete_auto<double, true> (Memory.h:416)
==6035== by 0x4E4224A: resize (DenseStorage.h:406)
==6035== by 0x4E4224A: resize (PlainObjectBase.h:293)
==6035== by 0x4E4224A: resize_if_allowed<Eigen::Matrix<double, -1, -1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> >, double, double> (AssignEvaluator.h:720)
==6035== by 0x4E4224A: call_dense_assignment_loop<Eigen::Matrix<double, -1, -1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> >, Eigen::internal::assign_op<double, double> > (AssignEvaluator.h:734)
==6035== by 0x4E4224A: run (AssignEvaluator.h:879)
==6035== by 0x4E4224A: call_assignment_no_alias<Eigen::Matrix<double, -1, -1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> >, Eigen::internal::assign_op<double, double> > (AssignEvaluator.h:836)
==6035== by 0x4E4224A: call_assignment<Eigen::Matrix<double, -1, -1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> >, Eigen::internal::assign_op<double, double> > (AssignEvaluator.h:804)
==6035== by 0x4E4224A: call_assignment<Eigen::Matrix<double, -1, -1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> > > (AssignEvaluator.h:782)
==6035== by 0x4E4224A: _set<Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> > > (PlainObjectBase.h:710)
==6035== by 0x4E4224A: operator=<Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> > > (Matrix.h:225)
==6035== by 0x11044C: main (Runner.cpp:16)
==6035== Address 0x2e642f73726573 is not stack'd, malloc'd or (recently) free'd
If offsets are not introduced as class members, but are local variables in operator(), no errors are detected by valgrind.
Is it possible to implement new MatrixXd::operator()(double, double) with settable offsets?
EDIT:
Operator() is defined in a parent class DenseCoeffsBase:
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType operator()(Index row, Index col) const
{
eigen_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
return coeff(row, col);
}
Perhaps, I see one problem with your operator which returns reference to temporary object of Scalar:
inline Scalar& operator()(double r, double c) {
// double r_offset = -0.5, c_offset = -0.5;
return Base::operator()(int(r - r_offset), int(c - c_offset));
}
So you should return Scalar by copy.
Could you share code of Base::operator()(int(r - r_offset), int(c - c_offset));?
I am writing a module to write data to a file which uses by convention only row-major storage. I would like my function to be able to allow both column-major and row-major Eigen objects as input.
Currently I first use Eigen to copy a column-major object to a row-major object, before I write. My code works well for most cases, but for Eigen::VectorXi compiling fails with an assertion that I don't understand. How do I solve this? Can I avoid creating many cases?
The code (writing is mimicked by outputting a std::vector):
#include <vector>
#include <iostream>
#include <Eigen/Eigen>
template <class T, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
std::vector<T> write(const Eigen::Matrix<T,Rows,Cols,Options,MaxRows,MaxCols>& matrix)
{
std::vector<T> data(static_cast<size_t>(matrix.size()));
if (matrix.IsRowMajor) {
std::copy(matrix.data(), matrix.data()+matrix.size(), data.begin());
return data;
} else {
Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix;
return write(tmp);
}
}
int main()
{
Eigen::VectorXi matrix = Eigen::VectorXi::LinSpaced(10, 0, 9);
std::vector<int> output = write(matrix);
}
The compilation error:
In file included from test.cpp:3:
In file included from /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/Eigen:1:
In file included from /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/Dense:1:
In file included from /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/Core:457:
/usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/PlainObjectBase.h:903:7: error: static_assert failed "INVALID_MATRIX_TEMPLATE_PARAMETERS"
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/util/StaticAssert.h:33:40: note: expanded from macro 'EIGEN_STATIC_ASSERT'
#define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
^ ~
/usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/PlainObjectBase.h:535:7: note: in instantiation of member function 'Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 1, -1, 1>
>::_check_template_params' requested here
_check_template_params();
^
/usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/Matrix.h:377:9: note: in instantiation of function template specialization 'Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 1, -1, 1>
>::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >' requested here
: Base(other.derived())
^
test.cpp:14:79: note: in instantiation of function template specialization 'Eigen::Matrix<int, -1, 1, 1, -1, 1>::Matrix<Eigen::Matrix<int, -1, 1, 0, -1, 1> >' requested here
Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix;
^
test.cpp:23:31: note: in instantiation of function template specialization 'write<int, -1, 1, 0, -1, 1>' requested here
std::vector<int> output = write(matrix);
^
1 error generated.
Understanding the static assertion
Unfortunately the assertion is really not self-explanatory and the only thing you can get from it is the hint, that something is wrong with your template parameters. If we look into Eigen's source code we find the following beginning on line 903:
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
&& EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0)
&& ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0))
&& ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0))
&& ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0))
&& ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0))
&& (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic)
&& (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic)
&& (Options & (DontAlign|RowMajor)) == Options),
INVALID_MATRIX_TEMPLATE_PARAMETERS)
Even though the compiler indicates that
EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
causes the error, the following line really does:
EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0)
Understanding what triggers the assertion
You provide Eigen::VectorXi as an input for write. Eigen::VectorXi is really just a typedef for
Eigen::Matrix<int, Eigen::Dynamic, 1, Eigen::ColMajor, Eigen::Dynamic, 1>
Therefore the line
Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix;
in write expands to
Eigen::Matrix<int, Eigen::Dynamic, 1, Eigen::RowMajor, Eigen::Dynamic, 1> tmp = matrix;
which triggers the assertion, since a matrix with MaxColsAtCompileTime==1 and MaxRowsAtCompileTime!=1 must not be RowMajor.
Solve your problem
The problem now is that even though you can check if your input matrix is a vector, row-major or column-major, you cannot declare
Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols>
if it is no legal to do so at compile-time (and it isn't due to the static assertion).
You have the following options to make your code work:
1. if constexpr (C++17)
C++17 offers a way for detecting at compile-time if a certain conditional branch will be taken or not. The downside of this approach (beside the requirement for a C++17 compiler) is that you can only test for constant expressions.
In the concrete example this looks like this:
template <class T, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
std::vector<T> write(const Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols>& matrix)
{
typedef Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols> MatrixType;
std::vector<T> data(static_cast<size_t>(matrix.size()));
if constexpr (MatrixType::MaxRowsAtCompileTime == 1 ||
MatrixType::MaxColsAtCompileTime ==1 ||
(MatrixType::Options&Eigen::RowMajor) == Eigen::RowMajor) {
std::copy(matrix.data(), matrix.data() + matrix.size(), data.begin());
return data;
} else {
Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix;
return write(tmp);
}
}
2. SFINAE
You can dispatch the call to write at compile-time using SFINAE by using std::enable_if. The following example uses a slightly modified version of your original code but everything should be clear from context:
// matrix is either a vector or in row-major
template <typename Derived>
std::vector<typename Derived::Scalar> write(const Eigen::MatrixBase<Derived>& matrix,
typename std::enable_if<Derived::MaxRowsAtCompileTime == 1 ||
Derived::MaxColsAtCompileTime == 1 ||
(Derived::Options & Eigen::RowMajor) == Eigen::RowMajor,
Derived>::type* = 0)
{
std::vector<typename Derived::Scalar> data(
static_cast<size_t>(matrix.size()));
std::copy(matrix.derived().data(), matrix.derived().data() + matrix.size(),
data.begin());
return data;
}
// matrix is neither a vector nor in row-major
template <typename Derived>
std::vector<typename Derived::Scalar> write(const Eigen::MatrixBase<Derived>& matrix,
typename std::enable_if<Derived::MaxRowsAtCompileTime != 1 &&
Derived::MaxColsAtCompileTime != 1 &&
(Derived::Options & Eigen::RowMajor) == 0,
Derived>::type* = 0)
{
Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime,
Derived::ColsAtCompileTime, Eigen::RowMajor,
Derived::MaxRowsAtCompileTime, Derived::MaxColsAtCompileTime> tmp = matrix;
return write(tmp);
}
This works using a C++11 compiler.
Other options would be to specialise the template but it will get even more lengthy than the SFINAE approach.
Some test cases:
Eigen::Matrix<int, 3, 3, Eigen::RowMajor> m;
m << 1, 2, 3,
1, 2, 3,
1, 2, 3;
std::vector<int> output = write(m);
for (const auto& element : output) {
std::cout << element << " ";
}
Output: 1 2 3 1 2 3 1 2 3
Eigen::Matrix<int, 3, 3, Eigen::ColMajor> m;
m << 1, 2, 3,
1, 2, 3,
1, 2, 3;
std::vector<int> output = write(m);
for (const auto& element : output) {
std::cout << element << " ";
}
Output: 1 2 3 1 2 3 1 2 3
Eigen::VectorXi m = Eigen::VectorXi::LinSpaced(10, 0, 9);
std::vector<int> output = write(m);
for (const auto& element : output) {
std::cout << element << " ";
}
Output: 0 1 2 3 4 5 6 7 8 9
Eigen::RowVectorXi m = Eigen::RowVectorXi::LinSpaced(10, 0, 9);
std::vector<int> output = write(m);
for (const auto& element : output) {
std::cout << element << " ";
}
Output: 0 1 2 3 4 5 6 7 8 9
A simpler solution is to let Eigen::Ref does all the job for you:
Ref<const Matrix<T,Rows,Cols,Cols==1?ColMajor:RowMajor,MaxRows,MaxCols>,0, InnerStride<1> > row_maj(matrix);
Then row_maj will be guaranteed to be sequentially stored in row-major order. If matrix is compatible, then no copy occurs. No branch, no SFINAE, etc.
Here matrix can be any expression, not only a Matrix<...> but also sub-matrices, Map, another Ref, etc.
To handle any expressions, just replace Rows and the likes with XprType::RowsAtCompileTime where XprType is the type of matrix.
template <class XprType>
std::vector<typename XprType::Scalar> write(const Eigen::MatrixBase<XprType>& matrix)
{...}
I'm trying to implement the activation function tanh on my CNN, but it doesn't work, the result is always "NaN". So i created a simple application where i have a randomized matrix and try to apply the tanh(x) function thus to understand where's the problem?
Here's my implementation :
Eigen::MatrixXd A = Eigen::MatrixXd::Random(10,1000);
Eigen::MatrixXd result, deriv;
result = A.array().tanh();
deriv = 1.0 - result*result;
and the only result to this is this error :
no match for ‘operator-’ (operand types are ‘double’ and ‘const Eigen::Product<Eigen::Matrix<double, -1, -1>, Eigen::Matrix<double, -1, -1>, 0>’)
deriv = (1.0 - result*result );
~~~~^~~~~~~~~~~~~~~
Could you please help me ?
The product result*result does not have the right dimensions for a matrix multiplication. We can use result*result.transpose() instead (unless a coefficient-wise multiplication is intended, in which case one could use result.array()*result.array()).
To subtract the values of the resulting matrix from a matrix full of ones, the .array() method can be used:
deriv = 1. - (result*result.transpose()).array();
I used openCV to create a matrix of ones
like this :
cv::Mat sum;
Eigen::MatrixXd SUM, Acv;
cv::eigen2cv(A,Acv)
sum=Mat::ones(Acv.rows,Acv.cols, CV_32FC1);
cv::cv2eigen(sum,SUM);
so :
deriv = SUM - result*result;
and now, here's another problem :(
/usr/include/eigen3/Eigen/src/Core/CwiseBinaryOp.h :110 : Eigen::CwiseBinaryOp<BinaryOp, Lhs, Rhs>::CwiseBinaryOp(const Lhs&, const Rhs&, const BinaryOp&) [with BinaryOp = Eigen::internal::scalar_difference_op<double, double>; LhsType = const Eigen::Matrix<double, -1, -1>; RhsType = const Eigen::Product<Eigen::Matrix<double, -1, -1>, Eigen::Matrix<double, -1, -1>, 0>; Eigen::CwiseBinaryOp<BinaryOp, Lhs, Rhs>::Lhs = Eigen::Matrix<double, -1, -1>; Eigen::CwiseBinaryOp<BinaryOp, Lhs, Rhs>::Rhs = Eigen::Product<Eigen::Matrix<double, -1, -1>, Eigen::Matrix<double, -1, -1>, 0>]: l'assertion « aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols() » a échoué.
I can't get this to compile:
Eigen::Map<Eigen::Matrix<const T, EA::ColsAtCompileTime, 1>> x(vec);
auto result = a_ * x - b_; // a(60r,1200c) * x(1200r,1c) - b(60r,1c)
The two errors (about 1000 lines each) eventually conclude that the * and - operators can't be "overloaded" (their term, not mine).
a_ is of this type: typedef Eigen::Map<Eigen::Matrix<double, ROWS, COLS>> EA;
b_ is of this type: typedef Eigen::Map<Eigen::Matrix<double, ROWS, 1>> EB;
T is the Ceres Solver Jet type. The errors seem to bespeak a column/row mismatch rather than a type problem. I could be wrong, though; the output is entirely too verbose. Did I misunderstand how the rows and columns work with Eigen matrix operators?
Update: I followed the "fatal-errors" suggestion:
In file included from /usr/include/eigen3/Eigen/Core:437:0,
from /usr/local/include/ceres/jet.h:165,
from /usr/local/include/ceres/internal/autodiff.h:145,
from /usr/local/include/ceres/autodiff_cost_function.h:132,
from /usr/local/include/ceres/ceres.h:37,
from /home/brannon/Workspace/Solver/music_solver.cpp:3:
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h: In instantiation of ‘class Eigen::PlainObjectBase<Eigen::Matrix<const double, 1200, 1, 0, 1200, 1> >’:
/usr/include/eigen3/Eigen/src/Core/Matrix.h:178:7: required from ‘class Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>’
/usr/include/eigen3/Eigen/src/Core/Map.h:24:32: required from ‘struct Eigen::internal::traits<Eigen::Map<Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>, 0, Eigen::Stride<0, 0> > >’
/usr/include/eigen3/Eigen/src/Core/util/ForwardDeclarations.h:32:54: required from ‘struct Eigen::internal::accessors_level<Eigen::Map<Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>, 0, Eigen::Stride<0, 0> > >’
/usr/include/eigen3/Eigen/src/Core/util/ForwardDeclarations.h:113:75: required from ‘class Eigen::Map<Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>, 0, Eigen::Stride<0, 0> >’
/home/brannon/Workspace/Solver/music_solver.cpp:18:72: required from ‘bool MusicCostFunctor<MATRIX_A, MATRIX_B>::operator()(const T*, T*) const [with T = double; MATRIX_A = Eigen::Map<Eigen::Matrix<double, 60, 1200, 0, 60, 1200>, 0, Eigen::Stride<0, 0> >; MATRIX_B = Eigen::Map<Eigen::Matrix<double, 60, 1, 0, 60, 1>, 0, Eigen::Stride<0, 0> >]’
/usr/local/include/ceres/internal/variadic_evaluate.h:175:19: required from ‘static bool ceres::internal::VariadicEvaluate<Functor, T, N0, 0, 0, 0, 0, 0, 0, 0, 0, 0>::Call(const Functor&, const T* const*, T*) [with Functor = MusicCostFunctor<Eigen::Map<Eigen::Matrix<double, 60, 1200, 0, 60, 1200>, 0, Eigen::Stride<0, 0> >, Eigen::Map<Eigen::Matrix<double, 60, 1, 0, 60, 1>, 0, Eigen::Stride<0, 0> > >; T = double; int N0 = 1200]’
/usr/local/include/ceres/autodiff_cost_function.h:208:17: required from ‘bool ceres::AutoDiffCostFunction<CostFunctor, kNumResiduals, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Evaluate(const double* const*, double*, double**) const [with CostFunctor = MusicCostFunctor<Eigen::Map<Eigen::Matrix<double, 60, 1200, 0, 60, 1200>, 0, Eigen::Stride<0, 0> >, Eigen::Map<Eigen::Matrix<double, 60, 1, 0, 60, 1>, 0, Eigen::Stride<0, 0> > >; int kNumResiduals = 1; int N0 = 1200; int N1 = 0; int N2 = 0; int N3 = 0; int N4 = 0; int N5 = 0; int N6 = 0; int N7 = 0; int N8 = 0; int N9 = 0]’
/home/brannon/Workspace/Solver/music_solver.cpp:115:1: required from here
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:585:27: error: ‘static Eigen::PlainObjectBase<Derived>::MapType Eigen::PlainObjectBase<Derived>::Map(Eigen::PlainObjectBase<Derived>::Scalar*) [with Derived = Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>; Eigen::PlainObjectBase<Derived>::MapType = Eigen::Map<Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>, 0, Eigen::Stride<0, 0> >; Eigen::PlainObjectBase<Derived>::Scalar = const double]’ cannot be overloaded
static inline MapType Map(Scalar* data)
^~~
You need to tell Eigen how to mix your scalar types through Eigen:: ScalarBinaryOpTraits. See similar questions with solutions there:
https://forum.kde.org/viewtopic.php?f=74&t=141467
Transform matrix of 3D positions with corresponding transformation matrix
After looking again at this example:
https://groups.google.com/d/msg/ceres-solver/7ZH21XX6HWU/Z3E-k2fbAwAJ
I realized that I put the const in the wrong spot. It's supposed to be Map<const... rather than <const T.
I've been converting RGBDSLAM to armhf (https://github.com/felixendres/rgbdslam_v2) and I've been encountering errors with this function:
template <typename T >
QMatrix4x4 eigenTF2QMatrix(const T& transf)
{
Eigen::Matrix<double, 4, 4, Eigen::RowMajor> m = transf.matrix();
//QMatrix4x4 qmat( static_cast<qreal*>( m.data() ) ); (original line)
QMatrix4x4 qmat( m.data() );
printQMatrix4x4("From Eigen::Transform", qmat);
return qmat;
}
The line:
QMatrix4x4 qmat( m.data() );
as well as the original:
QMatrix4x4 qmat( static_cast<qreal*>( m.data() ) );
Gives me the error:
error: invalid conversion from 'Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 1> >::Scalar* {aka double*}' to 'int' [-fpermissive]
How can I fix this function to work on arm?
You cannot cast a pointer and expect it to work. There is the cast method of Eigen, but it does not work with temporaries, so you will have to perform a copy:
using Eigen;
Matrix<qreal, 4, 4, RowMajor> mcopy = m.cast<qreal>();
QMatrix4x4 qmat(mcopy.data());