Eigen矩阵切片与索引报错:如何正确索引矩阵末尾列?
问题背景
现有尺寸为11行×15列的Eigen复数矩阵u,需要分别对矩阵前5列、最后5列执行赋值操作。目前前5列的索引逻辑可正常运行,但最后5列的索引代码始终触发断言报错,相关代码如下:
static const int nx = 10; static const int ny = 10; static const int mm = nx* 3/2; Eigen::Matrix<std::complex<double>, (ny+1), mm> u; u.setZero(); u(all,seqN(0,nx/2)) // 前5列索引,可正常运行 u(all,seqN(last-nx/2,last)) // 最后5列索引,运行报错
运行时触发的断言错误信息:
Eigen::Block<XprType, BlockRows, BlockCols, InnerPanel>::Block(XprType&, Eigen::Index, Eigen::Index, Eigen::Index, Eigen::Index) [with XprType = Eigen::Matrix<std::complex<double>, 11, 15>; int BlockRows = 11; int BlockCols = -1; bool InnerPanel = true; Eigen::Index = long int]: Assertion `startRow >= 0 && blockRows >= 0 && startRow <= xpr.rows() - blockRows && startCol >= 0 && blockCols >= 0 && startCol <= xpr.cols() - blockCols' failed.
错误原因
Eigen的seqN函数参数规则为:第一个参数是序列起始位置,第二个参数是序列的长度,不接受位置占位符作为长度参数。
你写的seqN(last-nx/2,last)存在两个问题:
- 第二个参数错误传入了代表末尾位置的占位符
last,而非固定长度值,导致Eigen解析列块参数时得到非法的负长度(报错信息里的BlockCols = -1就是这个问题导致的) - 即使把第二个参数换成数值
nx/2,起始位置计算也存在偏差:last对应矩阵最后一列的0基索引(15列矩阵对应值为14),last-nx/2计算结果为9,从该位置取5列会覆盖9~13列,漏掉最后1列。
正确索引写法
两种合法写法均可实现最后5列的访问,推荐第二种写法,可读性更强且不容易出现计算错误:
- 修正
seqN的参数,调整起始位置并传入正确长度:
// 最后5列起始索引为10,长度为5,刚好覆盖10~14列 u(all, seqN(last - nx/2 + 1, nx/2)) = 待赋值的表达式;
- 直接使用Eigen内置的末尾N个元素索引占位符
lastN,无需手动计算起始位置:
u(all, lastN(nx/2)) = 待赋值的表达式;
补充提示:原有代码中的索引语句后缺少赋值操作,实际运行时需要在索引表达式后通过=连接赋值内容,否则不会执行实际的赋值逻辑。
内容的提问来源于stack exchange,提问作者Jamie
相关产品推荐
相关产品推荐

