Making a reshape function in Eigen

岁酱吖の 提交于 2019-12-22 00:11:08

问题


Here's the code for a reshape function in Eigen. It works.

typedef MatrixXd mat;
typedef VectorXd vec;

Map<mat> reshape (vec b, const uint n, const uint m) {
    return Map<mat>(b.data(), n, m);
}

I was trying to decide the right type for the first argument.

vec & b still works, but I get strange errors with const vec & b or const vec b:

error: invalid conversion from 'const Scalar* {aka const double*}' to 'Eigen::Map<Eigen::Matrix<double, -1, -1> >::PointerArgType {aka double*}' [-fpermissive]
     return Map<mat>(b.data(), n, m);
                 ~~~~~~^~

I suspect this is due to mutability and the fact that the reshape function doesn't allocate new memory, but I would like to learn a more detailed explanation.

Hmm, it seems that vec && b is the right type for this, but I'm out of my depth.


回答1:


You are right that it is a mutability issue. If you use const vec&, you can only map it to a const mat as

Map<const mat> reshape (const vec& b, const uint n, const uint m) {
    return Map<const mat>(b.data(), n, m);
}

otherwise you can modify the components of a const vec via the mapped matrix. It has nothing to do with allocating memory.

Actually both vec and const vec are wrong. Both of them mean mapping to a temp copy of the original vector, whose life ends after the function call, as Avi Ginsburg said, resulting in an undefined behavior.

Please note the above code is only correct when the input is an Eigen::VectorXd.

In fact both vec& and const vec& can be wrong, if your input b is an expression. Using vec& will fail compiling as the components of an expression are not mutable. Using const vec& will force the expression to be evaluated into a temp const vector during the function call and you are mapping to a temp vector again.

Map<mat> reshape (vec& b, const uint n, const uint m) {
    return Map<const mat>(b.data(), n, m);
}

Map<const mat> reshape_const (const vec& b, const uint n, const uint m) {
    return Map<const mat>(b.data(), n, m);
}

vec a(100), b(100);
Map<mat> c1 = reshap(a, 10, 10);                  // ok
Map<mat> c2 = reshap(a + b, 10, 10);              // error, expression not mutable
Map<const mat> c3 = reshap_const(a, 10, 10);      // ok
Map<const mat> c4 = reshap_const(a + b, 10, 10);  // error, mapping to temp vec

In this case you need to use the expression type as the parameter type, although you probably do not plan to use your reshape with expressions. You could find more details here.

http://eigen.tuxfamily.org/dox-devel/TopicFunctionTakingEigenTypes.html




回答2:


It's just a matter of scope. Let's create a MCVE and use that to explain:

#include <Eigen/Core>
#include <iostream>

using namespace Eigen;

typedef MatrixXd mat;
typedef VectorXd vec;

Map<mat> reshapeCopy (vec b, const size_t n, const size_t m) {
    return Map<mat>(b.data(), n, m);
}

Map<mat> reshape (vec &b, const size_t n, const size_t m) {
    return Map<mat>(b.data(), n, m);
}

int main()
{
    vec tr;
    tr.setLinSpaced(4,1,4);
    std::cout << tr << "\n\n";
    Map<mat> m = reshape(tr, 2,2);
    std::cout << m << "\n\n";
    return 0;
}

Using g++ 4.9.3 on Ubuntu outputs:

1
2
3
4

4.94066e-324 3
4.94066e-324 4

1 3
2 4

In reshapeCopy,b is a copy of tr. Its lifetime is until the end of the reshapeCopy function. Therefore, when used in main, the output is gibberish/undefined behavior. In the reshape function tr is passed by reference and therefore the bs lifetime is as long as tr and the output is as expected.

kangshiyin is correct in pointing out that the specific error you're getting is when you define the function with const vec b or const vec &b that b is const, i.e. not mutable, and the return type is a mutable Map<mat>.



来源:https://stackoverflow.com/questions/38288447/making-a-reshape-function-in-eigen

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!