1

Let say I have an ArrayXXf (or MatrixXf) m. In each iteration of a for loop, I want to fill m row-wise with a VectorXf.

Eigen::ArrayXXf m(5, 5);

for (int i = 0; i < 5; i++)
{
    Eigen::VectorXf vec(5);
    vec << i, i + 1, i + 2, i+3, i+4;

    //fill m row wise
    // in matlab I will do something like m(i,:) = vec; 
    // in numpy this will looks like m[i:] = vec;
    // that means when i is 0 m looks like 
    //          [ 0 1 2 3 4 5
    //           -  - - - - -
    //           -  - - - - -
    //           -  - - - - -
    //           -  - - - - -]
}

How can I achieve that in Eigen?

Gaetan
  • 577
  • 2
  • 7
  • 20

2 Answers2

5

To simplify @Kunal's answer, you can directly modify rows (or columns) of an Array (or Matrix) without creating a temporary vector. In your example you can use .setLinSpaced():

Eigen::ArrayXXf m(5, 5);

for (int i = 0; i < 5; i++) {
    m.row(i).setLinSpaced(i,i+4); //.col(i) would be slightly more efficient
}

or use the comma initializer:

for (int i = 0; i < 5; i++) {
    m.row(i) << i, i+1, i+2, i+3, i+4;
}
chtz
  • 17,329
  • 4
  • 26
  • 56
  • I think the OP's question included filling `Eigen::ArrayXXf` using `VectorXf`. I haven't created any temporary vector. – Kunal Puri Dec 21 '18 at 11:48
  • 1
    @KunalPuri IMO, it is a bit unclear what the OP really needs. The `vec` variable in the question is a temporary which, as it is, is not necessary. If actually some complicated calculations happen with `vec` it could very likely be worth having a temporary for that. – chtz Dec 21 '18 at 12:21
  • This would not have solve my problem, because in my real case scenario, the array `m` must be filled using a vector which is created by vertically concatenating column of a image. Creating the vector using `i` was for demonstration purposes. – Gaetan Dec 21 '18 at 15:41
1

Use block() function.

#include <iostream>
#include <Eigen/Dense>

using namespace std;

int main()
{
    Eigen::ArrayXXf m(5, 5);

    for (int i = 0; i < 5; i++) {
        Eigen::VectorXf vec(5);
        vec << i, i + 1, i + 2, i+3, i+4;

        m.block(i, 0, 1, 5) << vec.transpose();
    }

    std::cout << m << std::endl;
    return 0;
}

Output:

0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8

Edit:

There is one simpler alternative also: row() function.

#include <iostream>
#include <Eigen/Dense>

using namespace std;

int main()
{
    Eigen::ArrayXXf m(5, 5);

    for (int i = 0; i < 5; i++) {
        Eigen::VectorXf vec(5);
        vec << i, i + 1, i + 2, i+3, i+4;

        m.row(i) = vec.transpose();
    }

    std::cout << m << std::endl;
    return 0;
}

Output:

0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8

P.S. transpose() is required because Eigen::VectorXf by default is a column vector, not a row vector.

Kunal Puri
  • 3,419
  • 1
  • 10
  • 22