Eigen-Block块操作

块是矩阵或数组的矩形部分。块表达式既可以用作右值,也可以用作左值。与通常的Eigen表达式一样,只要让编译器进行优化,这种抽象的运行时成本为零。优化都是自动的无需我们考虑太多。

一、使用块操作

Eigen中最通用的块操作称为.block()。有两个版本,语法如下:

块操作动态大小的块表达式固定大小块表达式
大小为(p,q)的块,从(i,j)开始matrix.block (i, j, p, q);matrix.block < p, q > (i, j);

在Eigen中,索引从0开始。

这两个版本都可以用于固定大小和动态大小的矩阵和数组。这两个表达式在语义上是等价的。唯一的区别是,如果块大小很小,固定大小的版本通常会提供更快的代码,但需要在编译时知道这个大小。

下面的程序使用动态大小和固定大小的版本打印矩阵中几个块的值。

#include <Eigen/Dense>
#include <iostream>
 
using namespace std;
 
int main()
{
  Eigen::MatrixXf m(4,4);
  m <<  1, 2, 3, 4,
        5, 6, 7, 8,
        9,10,11,12,
       13,14,15,16;
  cout << "Block in the middle" << endl;
  cout << m.block<2,2>(1,1) << endl << endl;
  for (int i = 1; i <= 3; ++i)
  {
    cout << "Block of size " << i << "x" << i << endl;
    cout << m.block(0,0,i,i) << endl << endl;
  }
}

输出

Block in the middle
 6  7
10 11

Block of size 1x1
1

Block of size 2x2
1 2
5 6

Block of size 3x3
 1  2  3
 5  6  7
 9 10 11

在上面的例子中,.block()函数被用作右值,也就是说,它只能作为只读。但是,块也可以用作左值,这意味着您可以对块进行赋值。

下面的示例说明了这一点。这个示例还演示了数组中的块,其工作原理与上面演示的矩阵中的块完全相同。

#include <Eigen/Dense>
#include <iostream>
 
int main()
{
  Eigen::Array22f m;
  m << 1,2,
       3,4;
  Eigen::Array44f a = Eigen::Array44f::Constant(0.6);
  std::cout << "Here is the array a:\n" << a << "\n\n";
  a.block<2,2>(1,1) = m;
  std::cout << "Here is now a with m copied into its central 2x2 block:\n" << a << "\n\n";
  a.block(0,0,2,3) = a.block(2,1,2,3);
  std::cout << "Here is now a with bottom-right 2x3 block copied into top-left 2x3 block:\n" << a << "\n\n";
}

输出

Here is the array a:
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6

Here is now a with m copied into its central 2x2 block:
0.6 0.6 0.6 0.6
0.6   1   2 0.6
0.6   3   4 0.6
0.6 0.6 0.6 0.6

Here is now a with bottom-right 2x3 block copied into top-left 2x3 block:
  3   4 0.6 0.6
0.6 0.6 0.6 0.6
0.6   3   4 0.6
0.6 0.6 0.6 0.6

虽然 .block()方法可用于任何块操作,但还有其他方法用于特殊情况,提供更专门的API和/或更好的性能。关于性能的话题,最重要的是在编译时向Eigen提供尽可能多的信息。例如,如果您的块是矩阵中的单个完整列,那么使用下面描述的专门的 .col() 函数可以让Eigen知道这一点,这可以为其提供优化机会。

本页的其余部分将描述这些专门的方法。

二、列和行

单独的列和行是块的特殊情况。Eigen提供了方便地解决这些问题的方法:.col()和.row()。

块操作方法
第 i 行*matrix.row( i );
第 j 列*matrix.col ( j );

col()和row()的参数是要访问的列或行的索引。在Eigen中,索引从0开始。

#include <Eigen/Dense>
#include <iostream>
 
using namespace std;
 
int main()
{
  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

该示例还演示了块表达式(这里是列)可以像任何其他表达式一样用于算术。

三、Corner-related操作

Eigen还为在矩阵或数组的一个角或边上刷新的块提供了特殊方法。例如,. topleftcorner()可用于引用矩阵左上角的块。

不同的可能性总结如下表:

块操作动态大小的块表达式固定大小块表达式
Top-left p by q block *matrix.topLeftCorner(p,q);matrix.topLeftCorner<p,q>();
Bottom-left p by q block *matrix.bottomLeftCorner(p,q);matrix.bottomLeftCorner<p,q>();
Top-right p by q block *matrix.topRightCorner(p,q);matrix.topRightCorner<p,q>();
Bottom-right p by q block *matrix.bottomRightCorner(p,q);matrix.bottomRightCorner<p,q>();
Block containing the first q rows *matrix.topRows(q);matrix.topRows<q>();
Block containing the last q rows *matrix.bottomRows( q );matrix.bottomRows<q>();
Block containing the first p columns *matrix.leftCols( p );matrix.leftCols<p>();
Block containing the last q columns *matrix.rightCols(q);matrix.rightCols<q>();
Block containing the q columns starting from i *matrix.middleCols(i,q);matrix.middleCols<q>(i);
Block containing the q rows starting from i *matrix.middleRows(i,q);matrix.middleRows<q>(i);

下面是一个简单的例子,说明上述操作的用法:

#include <Eigen/Dense>
#include <iostream>
 
using namespace std;
 
int main()
{
  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

四、向量的块运算

Eigen还提供了一组专门为向量和一维数组的特殊情况设计的块操作:

块操作动态大小的块表达式固定大小块表达式
包含前n个元素的块*vector.head (n);vector.head < n > ();
包含最后n个元素的块*vector.tail (n);vector.tail < n > ();
包含n个元素的块,从位置i *开始vector.segment (n);vector.segment < n >(i);

下面是一个例子:

#include <Eigen/Dense>
#include <iostream>
 
using namespace std;
 
int main()
{
  Eigen::ArrayXf v(6);
  v << 1, 2, 3, 4, 5, 6;
  cout << "v.head(3) =" << endl << v.head(3) << endl << endl;
  cout << "v.tail<3>() = " << endl << v.tail<3>() << endl << endl;
  v.segment(1,4) *= 2;
  cout << "after 'v.segment(1,4) *= 2', v =" << endl << v << endl;
}

输出

v.head(3) =
1
2
3

v.tail<3>() = 
4
5
6

after 'v.segment(1,4) *= 2', v =
 1
 4
 6
 8
10
 6
<think>好的,用户想查找Eigen::Array所有支持的操作函数列表,并且需要参考官方文档中的C++部分。首先,我需要回忆Eigen库的结构,特别是Array类的相关功能。Eigen主要有两个核心类:Matrix和Array,Array主要用于元素级操作,而Matrix用于线性代数运算。 首先,用户可能需要了解Array的基本操作,比如加减乘除等元素级运算。此外,Array还支持各种数学函数,如sin、cos、abs等,这些函数也是逐元素应用的。需要确认Eigen::Array是否支持这些函数,并引用官方文档中的说明。 接下来,考虑Array的初始化方法,比如使用Random、Constant、LinSpaced等静态函数创建数组。这些在文档中应该会有详细说明,需要提到这些方法并正确引用。 然后,比较和逻辑操作也是用户可能关心的部分,比如逐元素的比较运算符(>、<、==)以及逻辑函数如all()、any()。这些操作返回布尔数组,对条件判断很有用。 还有,Array的操作和索引功能,类似于Matrix类,用户可能想知道如何提取子数组或特定元素。这部分可能需要参考DenseBase类中的方法,比如使用operator()来索引,引用用户提供的参考内容中的信息。 此外,Array的广播功能也很重要,允许将行或列向量与数组进行逐元素操作。需要解释rowwise和colwise的使用方法,并可能引用相关的文档部分。 用户可能还想知道Array与Matrix之间的转换,如何使用matrix()方法将Array转换为Matrix进行线性代数运算,反之亦然。这通常在混合使用时需要注意。 最后,需要确保回答的结构清晰,分点列出操作类型,每个部分给出示例代码,并正确添加引用标识。同时,生成的相关问题应覆盖用户可能进一步询问的方向,如性能优化、与Matrix的区别、数学函数应用、广播机制和官方文档资源等。 检查LaTeX格式是否正确,所有行内公式使用$...$,独立公式用$$...$$,但在这个问题中可能数学公式较少,主要关注代码和函数列表。确保所有引用来自用户提供的参考内容,如引用[^1]和[^2],并正确标注。 总结回答结构:基本操作、数学函数、初始化方法、比较与逻辑操作操作与索引、广播、与Matrix的交互,以及官方文档资源。每个部分简要说明并附上代码示例,最后生成相关问题。</think>### Eigen::Array 支持的操作函数列表 Eigen::Array 是 Eigen 库中用于**逐元素操作**的类,适用于标量计算而非线性代数运算。以下是其主要支持的操作函数及示例: --- #### 1. **基本算术操作** - 逐元素加减乘除、取模等: ```cpp Eigen::ArrayXXf a = Eigen::ArrayXXf::Random(2, 2); Eigen::ArrayXXf b = Eigen::ArrayXXf::Constant(2, 2, 3.0); Eigen::ArrayXXf c = a + b; // 逐元素加法 Eigen::ArrayXXf d = a * b; // 逐元素乘法 ``` 所有运算符(`+`, `-`, `*`, `/`, `%`)均支持逐元素操作[^1]。 --- #### 2. **数学函数** - 逐元素数学函数(需包含 `<Eigen/Array>`): ```cpp Eigen::ArrayXXf arr = Eigen::ArrayXXf::Random(3, 3); arr = arr.abs(); // 绝对值 arr = arr.sqrt(); // 平方根 arr = arr.exp(); // 指数函数 arr = arr.log(); // 自然对数 ``` 支持常见函数如 `sin`, `cos`, `pow`, `tanh` 等[^2]。 --- #### 3. **初始化与生成方法** - 静态方法生成特定数组: ```cpp Eigen::ArrayXXf r = Eigen::ArrayXXf::Random(3, 3); // 随机数组 Eigen::ArrayXXf z = Eigen::ArrayXXf::Zero(3, 3); // 全零数组 Eigen::ArrayXXf l = Eigen::ArrayXXf::LinSpaced(5, 0, 10); // 线性间隔数组 ``` --- #### 4. **比较与逻辑操作** - 逐元素比较返回布尔值数组: ```cpp Eigen::ArrayXXf a = ...; Eigen::ArrayXXf b = ...; Eigen::ArrayXXb cmp = (a > b); // 逐元素比较 bool all_positive = (a > 0).all(); // 检查所有元素是否满足条件 ``` --- #### 5. **操作与索引** - 使用 `operator()` 提取子数组: ```cpp Eigen::ArrayXXf arr(4, 4); Eigen::ArrayXXf block = arr(seq(1, 3), seqN(0, 2)); // 提取第2-4行、第1-2列 ``` 支持通过整数、算术序列(`seq`, `seqN`)或布尔数组索引。 --- #### 6. **广播(Broadcasting)** - 将行/列向量广播到整个数组: ```cpp Eigen::ArrayXXf arr(3, 3); Eigen::ArrayXf v(3); arr.colwise() += v; // 每列加上向量v ``` --- #### 7. **与 Matrix 的交互** - 通过 `.matrix()` 转换为 `Matrix` 类型以执行线性代数操作: ```cpp Eigen::ArrayXXf arr = ...; Eigen::MatrixXf mat = arr.matrix(); ``` --- #### 官方文档资源 - **操作函数列表**:参考 [Eigen::Array Class Reference](https://eigen.tuxfamily.org/dox/classEigen_1_1Array.html)。 - **代码示例**:见 [Eigen 入门指南](https://eigen.tuxfamily.org/dox/GettingStarted.html)[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太阳风暴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值