Home > Mobile >  Assigning Eigen Block to a Matrix gives wrong elements
Assigning Eigen Block to a Matrix gives wrong elements

Time:08-04

When I'm using block method of Eigen Matrix and assigning the return values to the MatrixXd variable itself , the element of the matrix changed weirdly.

Here is a simple example to reproduce this problem.

  Eigen::MatrixXd temp(3, 5);
  temp << 60, 1.44583e-14, 2.90553e-14, 59.9308, 60, 
          60, 60, -2.90553e-14, 0.140057, 80, 
           1, 1, 1, 1, 1;
  std::cout << "Temp:\n" << temp << "\n";
  std::cout << "Temp.block(0,0,2,5):\n" << temp.block(0, 0, 2, 5) << "\n";
  temp = temp.block(0, 0, 2, 5);
  std::cout << "Temp=Temp.block(0,0,2,5):\n" << temp << "\n";

the output would be like

Temp:

   60  1.44583e-14  2.90553e-14      59.9308           60
   60           60 -2.90553e-14     0.140057           80
   1            1            1            1            1

Temp.block(0,0,2,5):

  60  1.44583e-14  2.90553e-14      59.9308           60
  60           60 -2.90553e-14     0.140057           80

Temp=Temp.block(0,0,2,5):

4.64591e-310 1.44583e-14 2.90553e-14 59.9308 60
4.64591e-310 60 -2.90553e-14 0.140057 80

Just like the output of the code the first column changed after the assignment. I know it is better to create a new MatrixXd to get the block but I just want to know why this kind of situation happens?

CodePudding user response:

It happens because the left side aliases the right side of the assignment. In general, Eigen does not guard against this in the interest of performance. Exceptions are made for matrix multiplication, where the noalias() method indicates that you, the programmer, has made the assessment. You can read the Aliasing chapter in the manual.

Under the hood, you requested an assignment with resizing. So the assignment operator allocated new memory. At this point the Block references a dangling pointer to the old, released memory. The memory allocator uses part of that memory for its own metadata. That is what you see in the first two entries.

To shrink to the top left corner without reassignment, please use the conservativeResize().

In more general expressions where you know aliasing is an issue, use the pattern leftSide = rightSide.eval() to separate the computation from the assignment. Performance will suffer slightly.

  • Related