Shrinking matrix with Eigen using block () in assignment

I have the following code that compresses the Eigen MatrixXd by removing the last line. Anyway, it seems to distort the matrix. Also valgrind is very frustrated with this code. What is the correct way to accomplish this task?

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

int main() {
    Eigen::MatrixXd A(3, 4);
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 4; j++)
            A(i, j) = i * j + i + j + 5;
    std::cout << "A = \n" << A << std::endl;

    A = A.block(0, 0, 2, 4);

    std::cout << "A = \n" << A << std::endl;
    return 0;
}

      

This code produces the following output on my machine (note 5 became 0)

A = 
 5  6  7  8
 6  8 10 12
 7 10 13 16
A = 
 0  6  7  8
 6  8 10 12

      

+3


source to share


1 answer


Eigen::Block<...>

(which the member function returns block()

) does not make a copy of the values, but acts as a reference to part of the matrix. You can see this with

A.block(0, 0, 2, 4) *= 2; // this will change A

      

Because of this, the object Eigen::Block

remains in effect only until the base matrix moves its values, which would be if you assign something to it with a different geometry (for example A.block(0, 0, 2, 4)

). After the underlying matrix has released its pre- Block

task memory, using the object is using after-care and invoking undefined behavior, and the assignment operator will of course try to read values ​​from a non-existent one Block

.

As you yourself learned, you can use



A.conservativeResize(2, 4);

      

for your specific case, because you want to shrink in the upper left corner. In general, you can use (for example)

A = A.block(1, 1, 2, 3).eval();

      

.eval()

forces an immediate rather than lazy evaluation, which in this case essentially means a temporary copy of the block is created and then assigned to the matrix. More details on all of this can be found here in the Eigen documentation.

+3


source







All Articles