11

我在 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();
    }
}

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

我希望能够做的是Map<MatrixXd>用适当的步幅包裹几个cplxFoo以获得真实和想象的部分。但问题是MatrixXcdare的元素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 的复杂数据类型为实部和虚部使用单独的内存块?

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

4

1 回答 1

13

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

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

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

于 2014-03-12T07:57:45.163 回答