本节来讲Matrix和Vector的一些算术运算。
一、简介
Eigen提供对C++常见的运算符进行了重载运算,如加减乘除;除此还有一些特殊的方法如dot corss等。需要注意Matlab不一样地方,这里支持的只是常规的线性代数运算,如matrix1*matrix2是支持的,matrix+scalar不支持(matlab支持,表示所有的元素都加上一个常数,但是乘上一个常数支持)。如果你想支持所有的数组元素,请看下一节。
二、加法、乘法
- 二元运算符 a+b
- 二元运算符 a-b
- 一元运算符 -a
- 复合运算符 += -=
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d a;
a << 1, 2,
3, 4;
MatrixXd b(2,2);
b << 2, 3,
1, 4;
std::cout << "a + b =\n" << a + b << std::endl;
std::cout << "a - b =\n" << a - b << std::endl;
std::cout << "Doing a += b;" << std::endl;
a += b;
std::cout << "Now a =\n" << a << std::endl;
Vector3d v(1,2,3);
Vector3d w(1,0,0);
std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}
三、标量乘和除法
- 二元运算符 矩阵*scalar
- 二元运算符 scalar*矩阵
- 二元运算符 矩阵/scalar
- 复合运算符 matrix*=scalar
- 复合运算符 matrix=scalar
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d a;
a << 1, 2,
3, 4;
Vector3d v(1,2,3);
std::cout << "a * 2.5 =\n" << a * 2.5 << std::endl;
std::cout << "0.1 * v =\n" << 0.1 * v << std::endl;
std::cout << "Doing v *= 2;" << std::endl;
v *= 2;
std::cout << "Now v =\n" << v << std::endl;
}
三、不要害怕维度大的矩阵运算
VectorXf a(50), b(50), c(50), d(50);
...
a = 3*b + 4*c + 5*d;
这种运算将会被Eigen优化成:
for(int i = 0; i < 50; ++i)
a[i] = 3*b[i] + 4*c[i] + 5*d[i];
大的运算将会基于Eigen更多的优化空间。
四、转置和共轭
转置 a T a^T aT(transpose)、共轭 a ˉ \bar a aˉ(conjugation)和伴随矩(adjoint) a ∗ a^* a∗。
MatrixXcf a = MatrixXcf::Random(2,2);
cout << "Here is the matrix a\n" << a << endl;
cout << "Here is the matrix a^T\n" << a.transpose() << endl;
cout << "Here is the conjugate of a\n" << a.conjugate() << endl;
cout << "Here is the matrix a^*\n" << a.adjoint() << endl;
注意,在使用transpose的时候,不要赋值给同一个值a = a.transpose();
,如果你要对本身进行转置并存于本身,那么请用transposeInPlace
五、矩阵和矩阵 矩阵和向量乘法
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d mat;
mat << 1, 2,
3, 4;
Vector2d u(-1,1), v(2,0);
std::cout << "Here is mat*mat:\n" << mat*mat << std::endl;
std::cout << "Here is mat*u:\n" << mat*u << std::endl;
std::cout << "Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
std::cout << "Here is u^T*v:\n" << u.transpose()*v << std::endl;
std::cout << "Here is u*v^T:\n" << u*v.transpose() << std::endl;
std::cout << "Let's multiply mat by itself" << std::endl;
mat = mat*mat;
std::cout << "Now mat is mat:\n" << mat << std::endl;
}
Effective C++条款11,自我赋值的问题这里也会出现,如果不确定是否有这样的行为,那么请使用c.noalias()+=a*b;
六、点积和叉积
点积的结果是一个数字,叉积则是一个向量。
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
Vector3d v(1,2,3);
Vector3d w(0,1,2);
cout << "Dot product: " << v.dot(w) << endl;
double dp = v.adjoint()*w; // automatic conversion of the inner product to a scalar
cout << "Dot product via a matrix product: " << dp << endl;
cout << "Cross product:\n" << v.cross(w) << endl;
}
七、其他运算
累加值,累积值,平均值,最小值,最大值和迹。
#include <iostream>
#include <Eigen/Dense>
using namespace std;
int main()
{
Eigen::Matrix2d mat;
mat << 1, 2,
3, 4;
cout << "Here is mat.sum(): " << mat.sum() << endl;
cout << "Here is mat.prod(): " << mat.prod() << endl;
cout << "Here is mat.mean(): " << mat.mean() << endl;
cout << "Here is mat.minCoeff(): " << mat.minCoeff() << endl;
cout << "Here is mat.maxCoeff(): " << mat.maxCoeff() << endl;
cout << "Here is mat.trace(): " << mat.trace() << endl;
}