我在Eigen3库中有一些复杂的密集 vector/矩阵,我想将实部和虚部提取到单独的数组中。在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();
    }
}

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

我想做的是将Map<MatrixXd>包裹在cplxFoo周围适当的步幅上,以获得真实和虚构的部分。但是问题是MatrixXcd的元素是std::complex<double>,我不确定它的布局是什么。我的猜测是std::complex<T>本质上像struct {T real; T imag;};一样布置,因此当您制作std::complex<T>数组时,实部和虚部紧密地包装和交织在一起(并且这在this SO question上似乎也是共识),但这是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的复杂数据类型为实部和虚部使用单独的内存块?

出于其值(value),我需要执行此操作的原因是因为我需要将Eigen库与MATLAB接口(interface),该MATLAB仅能处理实部和虚部的单独数组,而不能以任何方式进行交织。

最佳答案

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

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

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

07-24 14:28