如何在 Eigen3 库中高效提取复矩阵的实部/虚部?

How to efficiently extract real/imaginary parts of complex matrix in Eigen3 library?

本文关键字:实部 虚部 提取 Eigen3 高效      更新时间:2023-10-16

我在 Eigen3 库中有一些复杂、密集的向量/矩阵,我想将实部和虚部提取到单独的数组中。在 Matlab 中,我可以做类似的事情

cplxFoo = [1, 1i; -1i -1]
re = real(cplxFoo)
im = imag(cplxFoo)

期待地产生

cplxFoo =
1.0000 + 0.0000i   0.0000 + 1.0000i
0.0000 - 1.0000i  -1.0000 + 0.0000i
re =
1     0
0    -1
im =
0     1
-1     0

有没有类似 Eigen3 中的real()imag()Matlab 函数?

现在,我唯一知道会起作用的是类似于

MatrixXcd cplxFoo = ...;
MatrixXd re(cplxFoo.rows(), cplxFoo.cols());
MatrixXd im(cplxFoo.rows(), cplxFoo.cols());
for(size_t j=0; j<cplxFoo.cols(); ++j) {
for(size_t i=0; i<cplxFoo.rows(); ++i) {
re(i, j) = cplxFoo(i,j).real();
im(i, j) = cplxFoo(i,j).imag();
}
}

它可以工作,我甚至可以把它放在一个函数中,但是我不得不做我自己的循环矢量化、展开等,我必须制作一个额外的副本。

我希望能够做的是用适当的cplxFoo步伐包裹几个Map<MatrixXd>,以获得真实和虚构的部分。但问题是MatrixXcd的元素是std::complex<double>的,我不确定它的布局是什么。我的猜测是,std::complex<T>基本上是像struct {T real; T imag;};一样布置的,因此当您进行一系列std::complex<T>时,真实和虚构的部分紧密包装和交错(这似乎也是这个SO问题的共识),但这是由C++标准保证的吗?AFAICT,一个兼容的C++编译器可以像struct {T imag; T real;};一样布置它(注意更改的顺序),或者更奇特的东西,如

class {
T radius;
T angle;
public:
T real() const { return radius * cos(angle); }
T imag() const { return radius * sin(angle); }
/* ... */
};

那么,可以用适当的步伐包裹几Map<MatrixXd>cplxFoo吗?如果是这样,如何正确设置步幅?

或者,有没有办法让 Eigen 的复杂数据类型为实部和虚部使用单独的内存块?

就其价值而言,我需要这样做的原因是因为我需要将特征库与 MATLAB 接口,MATLAB 只能处理实部和虚部的单独数组,不能以任何方式交错。

这很简单,只需使用.real().imag()视图:

MatrixXcd M;
MatrixXd r, i;
r = M.real();
i = M.imag();

请注意,您可以在表达式中使用M.real(),而无需将其复制到MatrixXd中。