本文最后更新于:2024年1月14日 晚上

Eigen 是开源的C++线性代数库,常用在计算机图形学中,之前我们记录了 安装使用方法,本文记录常用功能使用方法。

动态矩阵、静态二维矩阵

  • Eigen 官方代码支持的最高维度为二维矩阵,后文的矩阵、数组均为二维。
  • Eigen 在编译期间确定尺寸的矩阵为静态矩阵,运行期间确定尺寸的为动态矩阵(数据类型中带有X)
  • 选用原则:
    • 对于非常小尺寸的矩阵,尽可能使用固定尺寸,特别是小于(大约)16的尺寸,使用固定尺寸对性能非常有益,因为它允许 Eigen 避免动态内存分配和展开循环; 对于小尺寸在内部,一个固定大小的特征矩阵只是一个普通的数组。
    • 对于较大尺寸,或者在必须使用动态尺寸的地方,尽量使用动态尺寸。当矩阵尺寸大于(大约)32时,静态矩阵的性能收益变得可以忽略,而且对于动态矩阵,Eigen 更倾向于尝试使用 SIMD 指令集加速运算。

模板类

  • Eigen 中有几个基础数据结构模板类

Matrix类

  • 所有矩阵和向量都是Matrix模板类的对象,Matrix类有6个模板参数,主要使用前三个,剩下的使用默认值。
  • MaxRowsAtCompileTimeMaxColsAtCompileTime 在已知动态矩阵的尺寸上界时是可以提升工作效率的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Matrix<typename Scalar, 
int RowsAtCompileTime,
int ColsAtCompileTime,
int Options = 0,
int MaxRowsAtCompileTime = RowsAtCompileTime,
int MaxColsAtCompileTime = ColsAtCompileTime>
# Scalar 元素类型
# RowsAtCompileTime 行
# ColsAtCompileTime 列
# 例 typedef Matrix<int, 3, 3> Matrix3i;
# Options 比特标志位
# MaxRowsAtCompileTime和MaxColsAtCompileTime表示在编译阶段矩阵的上限。

# 列向量
typedef Matrix<double, 3, 1> Vector3d;
# 行向量
typedef Matrix<float, 1, 3> RowVector3f;

# 动态大小
typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
typedef Matrix<float, Dynamic, 1> VectorXf;
type
  • 默认构造时,指定大小的矩阵,只分配相应大小的空间,不进行初始化。动态大小的矩阵,则未分配空间。

  • []操作符可以用于向量元素的获取,但不能用于matrix

  • matrix的大小可以通过rows(), cols(), size()获取,resize()可以重新调整矩阵大小。

  • Matrix 定义的矩阵为静态矩阵,在编译时确定尺寸、分配内存,随机初始化:

1
2
3
4
5
6
7
Matrix<int, 3, 3> a;
cout << a;

-->
1284850368 32759 1
32759 31 0
1284845929 0 0
  • MatrixX 开头的为动态矩阵,两个维度都可以变化,本质为 Matrix<Type, Dynamic, Dynamic> 定义的类型

    例如: MatrixXd 为 double 类型的动态矩阵

    1
    2
    3
    4
    5
    6
    7
    MatrixXd  a(3, 3);
    cout << a;

    -->
    0 0 0
    0 0 0
    0 0 0
  • 静态矩阵运算很快,但是有 128k 的堆栈尺寸限制,常用的还是动态矩阵类型

  • 仅变化一个维度的动态矩阵为动态向量 typedef Matrix<float, Dynamic, 1> VectorXf,使用方法类似

Array类

  • Array是类模板,前三个参数必须指定,后三个参数可选。
1
2
3
4
5
6
7
8
9
10
11
12
13
Array<typename Scalar,
int RowsAtCompileTime,
int ColsAtCompileTime>
# 常见类定义
typedef Array<float, Dynamic, 1> ArrayXf
typedef Array<float, 3, 1> Array3f
typedef Array<double, Dynamic, Dynamic> ArrayXXd
typedef Array<double, 3, 3> Array33d

ArrayXf a = ArrayXf::Random(5);
a.abs(); # 绝对值
a.sqrt(); # 平方根
a.min(a.abs().sqrt()); # 两个array相应元素的最小值
  • 类似于 Matrix 类,Array 默认仍会产生静态数组

    1
    2
    3
    4
    5
    6
    7
    Array<int, 3, 3> a;
    cout << a;

    -->
    -412990784 32758 1
    32758 31 0
    -412995223 0 0
  • 一维动态数组为 ArrayX 开头,二维动态数组为 ArrayXX 开头

    1
    2
    3
    4
    5
    6
    7
    ArrayXXi  a(3, 3);
    cout << a;

    -->
    6357107 7471220 4522044
    7929971 6422621 6029371
    7667805 7209066 7471185

Array 和 Martix 的区别

  • Martix 表示的是矩阵,运算为矩阵运算,运算时尺寸需要遵循矩阵运算规则
  • Array 和 Matrix 数据组成相同,但运算规则为逐元素运算,需要相同尺寸数据进行运算

Array 和 Martix 的转换

  • Matrix对象——>Array对象:.array()函数
  • Array对象——>Matrix对象:.matrix()函数

初始化

建议矩阵数据都要初始化,不然是十分危险的。

默认初始化

  • 默认初始化为随机数:
1
2
3
4
5
6
ArrayXXi  a(2, 4);
cout << a;

-->
7602273 7209025 7209071 3014707
6029409 6488161 6357092 3014712

赋值初始化

  • 赋值初始化

    1
    2
    3
    4
    5
    6
    7
    Matrix<int, 5, 1> b {1, 2, 3, 4, 5};
    Matrix<double, 2, 3> b {
    {2, 3, 4},
    {5, 6, 7},
    };
    VectorXd a {{1.5, 2.5, 3.5}};
    RowVectorXd b {{1.0, 2.0, 3.0, 4.0}};

对象初始化

  • 可以用其他对象初始化新的相同内容对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Eigen::MatrixXf m(4, 4);

    m << 1, 2, 3, 4,
    5, 6, 7, 8,
    9, 10, 11, 12,
    13, 14, 15, 16;
    MatrixXf n(m);
    m.block(0, 0, 2, 2).swap(n.block(2, 2, 2, 2));

    cout << m;

    -->

    11 12 3 4
    15 16 7 8
    9 10 11 12
    13 14 15 16

逗号初始化

  • 为矩阵元素赋值,顺序是从左到右,从上到下,数目必须匹配。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ArrayXXi  a(2, 3);
a << 1, 2, 3, 4, 5, 6;
cout << a << endl << endl;

ArrayXXi b(2, 2);
b << 7, 8, 9, 10;
cout << b << endl << endl;

ArrayXXi c(4, 7);
c << b, a, b, a, b, b;
cout << c << endl << endl;

-->
1 2 3
4 5 6

7 8
9 10

7 8 1 2 3 7 8
9 10 4 5 6 9 10
1 2 3 7 8 7 8
4 5 6 9 10 9 10

特殊矩阵初始化

静态矩阵

一下几个函数均为静态矩阵调用的初始化函数,动态矩阵调用会报错:

1
YOU CALLED A_FIXED SIZE METHOD ON A DYNAMIC SIZE MATRIX OR VECTOR
  • 零阵:类静态成员函数Zero()
  • 常量矩阵:Constant(rows, cols, value)
  • 随机矩阵:Random()
  • 单位矩阵:Identity()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Matrix<int, 3, 3> a;
cout << a << endl << endl;

a = a.Zero();
cout << a << endl << endl;

a = a.Constant(3, 3, 7);
cout << a << endl << endl;

a = a.Random();
cout << a << endl << endl;

a = a.Identity();
cout << a << endl << endl;

-->
1028866792 32759 1
32759 31 0
1028862809 0 0

0 0 0
0 0 0
0 0 0

7 7 7
7 7 7
7 7 7

-16343 10116 -4906
2083 2785 12974
-10050 -660 10578

1 0 0
0 1 0
0 0 1
动态矩阵
函数 含义
setZero() 矩阵归零
setConstant() 矩阵归常数
setIdentity() 矩阵归单位阵
setOnes() 矩阵归一
setRandom() 矩阵随机数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
MatrixXi a(3, 3);
cout << a << endl << endl;
a.setZero();
cout << a << endl << endl;
a.setConstant(2);
cout << a << endl << endl;
a.setIdentity();
cout << a << endl << endl;
a.setOnes();
cout << a << endl << endl;
a.setRandom();
cout << a << endl << endl;

-->
5701724 7536759 6619252
7209065 5439580 3342445
7274596 7536761 6029362

0 0 0
0 0 0
0 0 0

2 2 2
2 2 2
2 2 2

1 0 0
0 1 0
0 0 1

1 1 1
1 1 1
1 1 1

-16343 10116 -4906
2083 2785 12974
-10050 -660 10578
动态向量函数
  • 仅能在向量类型数据中使用
函数 含义
setLinSpaced() 填充线性间隔的数据
setUnit() 指定向量位置数据置1,其余为0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
RowVectorXf b(8);
cout << b << endl << endl;
b.setLinSpaced(0, 14);
cout << b << endl << endl;
b.setUnit(3);
cout << b << endl << endl;
b.setOnes();
cout << b << endl << endl;
b.setConstant(2);
cout << b << endl << endl;

-->
9.91839e-39 9.64288e-39 8.44903e-39 7.80611e-39 5.9694e-39 1.08367e-38 4.50001e-39 4.5e-39

0 2 4 6 8 10 12 14

0 0 0 1 0 0 0 0

1 1 1 1 1 1 1 1

2 2 2 2 2 2 2 2

索引数据

单个数据

  • 主要数据的存取和修改都是通过重载的括号运算符完成的

  • 对于二维矩阵,下标顺序为 row col

  • 对于向量,则只有向量下标需要传入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    MatrixXd m(2,2);
    m(0,0) = 3;
    m(1,0) = 2.5;
    m(0,1) = -1;
    m(1,1) = m(1,0) + m(0,1);
    cout << m;

    -->
    3 -1
    2.5 1.5

块操作

  • 语法:
动态矩阵 静态矩阵
尺寸 (p, q) 左上角坐标 (i, j) matrix.block(i,j,p,q); matrix.block<p,q>(i,j);
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Eigen::MatrixXf m(4, 4);
    m << 1, 2, 3, 4,
    5, 6, 7, 8,
    9, 10, 11, 12,
    13, 14, 15, 16;

    m.block<2, 2>(0, 0) = m.block<2, 2>(0, 0) * 3;
    m.block<2, 2>(2, 2).setConstant(0);
    cout << m << endl << endl;

    -->
    18 21 3 4
    30 33 7 8
    9 10 0 0
    13 14 0 0

行列操作

  • 语法:
操作 方法
第 i 行 matrix.row(i);
第 i 列 matrix.col(j);
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    Eigen::MatrixXf m(3, 3);
    m << 1, 2, 3,
    4, 5, 6,
    7, 8, 9;
    cout << "Here is the matrix m:" << endl << m << endl;
    cout << "2nd Row: " << m.row(1) << endl;
    m.col(2) += 3 * m.col(0);
    cout << "After adding 3 times the first column into the third column, the matrix m is:\n";
    cout << m << endl;

    -->
    Here is the matrix m:
    1 2 3
    4 5 6
    7 8 9
    2nd Row: 4 5 6
    After adding 3 times the first column into the third column, the matrix m is:
    1 2 6
    4 5 18
    7 8 30

角操作

  • 语法:
块操作 动态矩阵语法 静态矩阵语法
左上角 p 行 q 列 matrix.topLeftCorner(p,q); matrix.topLeftCorner<p,q>();
左下角 p 行 q 列 matrix.bottomLeftCorner(p,q); matrix.bottomLeftCorner<p,q>();
右上角 p 行 q 列 matrix.topRightCorner(p,q); matrix.topRightCorner<p,q>();
右下角 p 行 q 列 matrix.bottomRightCorner(p,q); matrix.bottomRightCorner<p,q>();
前 q 行 matrix.topRows(q); matrix.topRows<q>();
后 q 行 matrix.bottomRows(q); matrix.bottomRows<q>();
前 p 列 matrix.leftCols(p); matrix.leftCols<p>();
后 p 列 matrix.rightCols(q); matrix.rightCols<q>();
第 i 列开始取 q 列 matrix.middleCols(i,q); matrix.middleCols<q>(i);
第 i 行开始取 q 行 matrix.middleRows(i,q); matrix.middleRows<q>(i);
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    Eigen::Matrix4f m;
    m << 1, 2, 3, 4,
    5, 6, 7, 8,
    9, 10,11,12,
    13,14,15,16;
    cout << "m.leftCols(2) =" << endl << m.leftCols(2) << endl << endl;
    cout << "m.bottomRows<2>() =" << endl << m.bottomRows<2>() << endl << endl;
    m.topLeftCorner(1,3) = m.bottomRightCorner(3,1).transpose();
    cout << "After assignment, m = " << endl << m << endl;

    -->
    m.leftCols(2) =
    1 2
    5 6
    9 10
    13 14

    m.bottomRows<2>() =
    9 10 11 12
    13 14 15 16

    After assignment, m =
    8 12 16 4
    5 6 7 8
    9 10 11 12
    13 14 15 16

向量块操作

块操作 动态矩阵语法 静态矩阵语法
向量前 n 个数据 vector.head(n); vector.head<n>();
向量后 n 个数据 vector.tail(n); vector.tail<n>();
向量从下标 i 开始的 n 个数据 vector.segment(i,n); vector.segment<n>(i);

常用操作

  • 大多数情况下,Eigen 要求操作的数据类型一致

布尔归约

操作 语法 示例
转置 .transpose() v.transpose()
所有元素为 true(非0),返回 bool 值 all() m.all()
存在元素为 true(非0),返回 bool 值 any() m.any()
统计 true(非0) 的个数 count() m.count()

数据类型转换

操作 语法 示例
数据类型转换为 double .cast<double>() A.cast<double>()
数据类型转换为 float .cast<float>() A.cast<float>()
数据类型转换为 int .cast<int>() A.cast<int>()
数据类型转换为实部 .real() A.real()
数据类型转换为虚部 .imag() A.imag()
内存数据转 Eigen Map<>() Map<Matrix3i>(array)
  • 内存数据转 Eigen:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int array[9];
    for (int i = 0; i < 9; ++i) {
    array[i] = i;
    }
    cout << Map<Matrix3i>(array).transpose() << endl;

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

Vector 向量操作

操作 语法 示例
点乘 dot() v.dot(w)
叉乘 .cross() v.cross(w)
元素个数 .size() v.size()
生成对角阵 .asDiagonal() v.asDiagonal()
向量平方和 .squaredNorm() v.squaredNorm()
向量模长 .norm() v.norm()

Matrix 矩阵操作

操作 语法 示例
转置 .transpose() v.transpose()
共轭 .conjugate() a.conjugate()
共轭转置 .adjoint() a.adjoint()
元素个数 .size() a.size()
行数 .rows() a.rows()
列数 .rols() a.rols()
填充 .fill() a.fill(6)
交换行/列 .swap() m.block(0, 0, 2, 2).swap(n.block(2, 2, 2, 2));
获取对角线 .diagonal() a.diagonal()
列向操作 .colwise() m.colwise().sum()
元素颠倒 .reverse() m.reverse()
  • 赋值经过优化:

    行可以给列赋值,这个其实还是挺可怕的,需要格外小心。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Eigen::MatrixXf m(4, 4);
    m << 1, 2, 3, 4,
    5, 6, 7, 8,
    9, 10, 11, 12,
    13, 14, 15, 16;
    m.row(0) = m.col(3);
    cout << m;

    -->
    4 8 12 16
    5 6 7 8
    9 10 11 12
    13 14 15 16
  • 列向操作相当于 numpy 中的 axis=1,只对列方向做某种操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Eigen::MatrixXf m(4, 4);
    m << 1, 2, 3, 4,
    5, 6, 7, 8,
    9, 10, 11, 12,
    13, 14, 15, 16;

    cout << "Here is the matrix m:" << endl << m << endl;
    cout << "Here is the sum of each column:" << endl << m.colwise().sum() << endl;
    cout << "Here is the maximum absolute value of each column:"
    << endl << m.cwiseAbs().colwise().maxCoeff() << endl;

    -->
    Here is the matrix m:
    1 2 3 4
    5 6 7 8
    9 10 11 12
    13 14 15 16
    Here is the sum of each column:
    28 32 36 40
    Here is the maximum absolute value of each column:
    13 14 15 16

Matrix 矩阵运算

操作 语法 示例
矩阵相加 + a + b
矩阵相减 - a - b
负号 - - a
复合算子加 += a += b
复合算子减 -= a -= b
标量乘法 * matrix*scalar / scalar*matrix
标量除法 / matrix/scalar
复合算子乘 *= matrix*=scalar
复合算子除 /= matrix/=scalar
矩阵\向量乘法 * matrix*matrix, matrix*vector
矩阵求和 .sum() mat.sum()
所有元素乘积 .prod() mat.prod()
矩阵均值 .mean() mat.mean()
矩阵最小值 .minCoeff() mat.minCoeff()
矩阵最大值 .maxCoeff() mat.maxCoeff()
矩阵最小值,带位置 .minCoeff(&r, &c) mat.minCoeff(&r, &c)
矩阵最大值,带位置 .maxCoeff(&r, &c) mat.maxCoeff(&r, &c)
.trace() mat.trace()
逐元素绝对值 .cwiseAbs() mat.cwiseAbs()
逐元素相乘 .cwiseProduct() mat = mat.cwiseProduct(mat)
逐元素相除 .cwiseQuotient() mat = mat.cwiseQuotient(mat)
逐元素取倒数 .cwiseInverse() mat.cwiseInverse()
逐元素开根号 .cwiseSqrt() mat.cwiseSqrt()
逐元素最大值 .cwiseMax(m) mat.cwiseMax(mat2)
逐元素最小值 .cwiseMin(m) mat.cwiseMin(mat2)
元素平方和 .squaredNorm() mat.squaredNorm()
矩阵二阶范数 .norm() mat.norm()
p 阶范数 .lpNorm<p>() mat.lpNorm<3>()
  • 最大值、最小值

    返回最大、最小值,同时定位位置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    Matrix3f m = Matrix3f::Random();
    std::ptrdiff_t i, j;
    float minOfM = m.minCoeff(&i,&j);
    cout << "Here is the matrix m:\n" << m << endl;
    cout << "Its minimum coefficient (" << minOfM
    << ") is at position (" << i << "," << j << ")\n\n";

    RowVector4i v = RowVector4i::Random();
    int maxOfV = v.maxCoeff(&i);
    cout << "Here is the vector v: " << v << endl;
    cout << "Its maximum coefficient (" << maxOfV
    << ") is at position " << i << endl;

    -->

    Here is the matrix m:
    -0.997497 0.617481 -0.299417
    0.127171 0.170019 0.791925
    -0.613392 -0.0402539 0.64568
    Its minimum coefficient (-0.997497) is at position (0,0)

    Here is the vector v: 8080 -10679 11761 6897
    Its maximum coefficient (11761) is at position 2

Array 数组运算

操作 语法 示例
逐元素相乘 * a * b
逐元素相除 / a * b
矩阵相加 + a + b
矩阵相减 - a - b
负号 - - a
复合算子加 += a += b
复合算子减 -= a -= b
逐元素比较 <, >, >=, <=, == a < b
逐元素标量计算 +, -, *, / a + 3
逐元素标量复合计算 +=, -=, *=, /= a /= 3
逐元素取倒数 .inverse() a.inverse()
逐元素 sin .sin() a.sin()
逐元素 cos .cos() a.cos()
逐元素乘方 .pow(s) a.pow(3)
逐元素平方 .square() a.square()
逐元素立方 .cube() a.cube()
逐元素开根号 .sqrt() a.sqrt()
逐元素计算自然指数 .exp() a.exp()
逐元素计算自然对数 .log() a.log()
逐元素最小值 .min() a.min(b)
逐元素最大值 .max() a.max(b)
逐元素绝对值 .abs() a.abs()
逐元素选择 .select() (R.array() < s).select(P,Q)
  • 逐元素比较:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Eigen::MatrixXf m(4, 4);
    m << 1, 2, 3, 4,
    5, 6, 7, 8,
    9, 10, 11, 12,
    13, 14, 15, 16;

    cout << (m.array() > m.reverse().array());

    -->
    0 0 0 0
    0 0 0 0
    1 1 1 1
    1 1 1 1
  • 逐元素选择:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Eigen::MatrixXf m(4, 4);
    m << 1, 2, 3, 4,
    5, 6, 7, 8,
    9, 10, 11, 12,
    13, 14, 15, 16;

    MatrixXf n(4, 4), p(4, 4);
    n.setZero();

    p = (m.array() < 10).select(m, n);
    cout << p;

    -->
    1 2 3 4
    5 6 7 8
    9 0 0 0
    0 0 0 0

矩阵分解与解线性方程组

矩阵分解

分解方法 语法 输出
柯列斯基分解 .ldlt() .matrixL() and .matrixD()
LLT 分解 .llt() .matrixL()
部分旋转的 LU分解 .lu() .matrixL() and .matrixU()
QR 分解 .qr() .matrixQ() and .matrixR()
SVD 分解 .svd() .matrixU(), .singularValues(), and .matrixV()

求解线性方程组

  • 对应不同矩阵分解方式,有不同的解方程组的方法
语法 描述
x = A.ldlt().solve(b)); A sym. p.s.d. #include <Eigen/Cholesky>
x = A.llt() .solve(b)); A sym. p.d. #include <Eigen/Cholesky>
x = A.lu() .solve(b)); Stable and fast. #include <Eigen/LU>
x = A.qr() .solve(b)); No pivoting. #include <Eigen/QR>
x = A.svd() .solve(b)); Stable, slowest. #include <Eigen/SVD>

特征值特征向量

  • 特征值:

    1
    A.eigenvalues();
  • 特征向量:

    1
    eig.eigenvectors();  

混淆问题

  • 使用eval()函数解决把右值赋值为一个临时矩阵,再赋给左值时可能有造成的混淆。如:
1
2
3
MatrixXi mat(3,3);
mat << 1,2,3, 4,5,6, 7,8,9;
mat.bottomRightCorner(2,2) = mat.topLeftCorner(2,2).eval();
  • 原地操作的一类函数:
普通函数 inplace函数
MatrixBase::adjoint() MatrixBase::adjointInPlace()
DenseBase::reverse() DenseBase::reverseInPlace()
LDLT::solve() LDLT::solveInPlace()
LLT::solve() LLT::solveInPlace()
TriangularView::solve() TriangularView::solveInPlace()
DenseBase::transpose() DenseBase::transposeInPlace()
  1. 当相同的矩阵或array出现在等式左右时,容易出现混淆
  2. 当确定不会出现混淆时,可以使用noalias()
  3. 混淆出现时,可以使用eval()xxxInPlace()函数解决

参考资料



文章链接:
https://www.zywvvd.com/notes/coding/cpp/eigen/eigen-usage/


“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付

Eigen 使用教程
https://www.zywvvd.com/notes/coding/cpp/eigen/eigen-usage/
作者
Yiwei Zhang
发布于
2023年1月12日
许可协议