C ++ Eigen3 matrix weird behavior

I am trying to get a random symmetric matrix with a library of linear algebras C ++ Eigen3. I do it like this:

Eigen::MatrixXd m(3, 3);
m.setRandom();
m = 0.5 * (m + m.transpose());

But the result is completely wrong. But if I do not rewrite the variable m and just print it to the console as follows:

Eigen::MatrixXd m(3, 3);
m.setRandom();
cout << 0.5 * (m + m.transpose()) << endl;

Everything seems to be working fine. I do not understand what the problem is. Is this because methods such as transpose and operations of type * and + do not create a new matrix, but instead do it in a lazy way and keep a reference to the matrix m? But how then can I find out from official documentation? And isn’t behavior like this in most cases prone to errors?

UPDATE: Yes, I think my guess about lazy computing is correct. It is mentioned in the documentation of the method transpose:

/** \returns an expression of the transpose of *this.
  *
  * Example: \include MatrixBase_transpose.cpp
  * Output: \verbinclude MatrixBase_transpose.out
  *
  * \warning If you want to replace a matrix by its own transpose, do \b NOT do this:
  * \code
  * m = m.transpose(); // bug!!! caused by aliasing effect
  * \endcode
  * Instead, use the transposeInPlace() method:
  * \code
  * m.transposeInPlace();
  * \endcode
  * which gives Eigen good opportunities for optimization, or alternatively you can also do:
  * \code
  * m = m.transpose().eval();
  * \endcode
  *
  * \sa transposeInPlace(), adjoint() */

, , , ? , .eval()? , .

+4
2

" , ".

, . . :

Eigen , . [...]

- , . , , . - . : -, ; -, , , : matrix = matrix*matrix , , - , .

", , , ?"

, , /, , , , matrix.transpose() . .eval() .noalias() , :

  • : matrix1.noalias() = matrix2 * matrix2; - 1 2

  • : matrix1 = matrix1.transpose().eval()

.eval():

m = 0.5 * (m + m.transpose()).eval();
+3

pingul , , , , . , , :

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

int main() {
    Eigen::Matrix4f M;
    M.setRandom();
    std::cout << "M:\n" << M << '\n';
    // for comparison, evaluate into other matrix (similar to using .eval()):
    Eigen::Matrix4f M2 = 0.5f*(M+M.transpose());
    // in place operation, only assing to lower half, then to upper half:
    M.triangularView<Eigen::StrictlyLower>() = 0.5f*(M + M.transpose());
    M.triangularView<Eigen::StrictlyUpper>() = M.transpose();
    std::cout << "M2:\n" << M2 << "\nM:\n" << M << '\n';
}

, " " M, ( ):

    M.triangularView<Eigen::StrictlyLower>() = M.transpose();
+1

Source: https://habr.com/ru/post/1684204/


All Articles