简体   繁体   English

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

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

I have some complex, dense vectors/matrices in the Eigen3 library, and I want to extract the real and imaginary parts into separate arrays.我在 Eigen3 库中有一些复杂的、密集的向量/矩阵,我想将实部和虚部提取到单独的数组中。 In Matlab, I could do something like在 Matlab 中,我可以做类似的事情

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

which expectantly yields预期会产生

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

Is there anything like the real() and imag() Matlab functions in Eigen3? Eigen3 中是否有类似real()imag() Matlab 函数的东西?

Right now, the only thing I know will work is something akin to现在,我唯一知道会起作用的是类似于

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

It works, and I can put it in a function even, but then I'm stuck having to do my own loop vectorizing, unrolling, etc., and I have to make an extra copy.它有效,我什至可以把它放在一个函数中,但是我不得不做我自己的循环矢量化、展开等,我必须制作一个额外的副本。

What I would like to be able to do is wrap a couple of Map<MatrixXd> with appropriate strides around cplxFoo to get the real and imaginary parts.我希望能够做的是围绕cplxFoo以适当的步幅包裹几个Map<MatrixXd>以获得实部和虚部。 But the problem is that the elements of MatrixXcd are std::complex<double> , and I'm not sure what the layout of that is.但问题是MatrixXcd的元素是std::complex<double> ,我不确定它的布局是什么。 My guess is that std::complex<T> is essentially laid out like struct {T real; T imag;};我的猜测std::complex<T>基本上像struct {T real; T imag;}; struct {T real; T imag;}; so that real and imaginary parts are tightly packed and interleaved when you make an array of std::complex<T> (and that also seems to be the consensus at this SO question ), but is that guaranteed by the C++ standard?因此,当您制作std::complex<T>数组时,实部和虚部会紧密包装和交错(这似乎也是这个 SO question的共识),但是 C++ 标准是否保证了这一点? AFAICT, a compliant C++ compiler could lay it out like struct {T imag; T real;}; AFAICT,一个兼容的 C++ 编译器可以像struct {T imag; T real;}; struct {T imag; T real;}; (note the changed order), or something more exotic like (注意更改的顺序),或者更奇特的东西,比如

class {
    T radius;
    T angle;

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

So, is it ok to wrap a couple of Map<MatrixXd> with appropriate strides around cplxFoo ?那么,可以在cplxFoo周围以适当的步幅包裹几个Map<MatrixXd>吗? If so, how do I set up the strides correctly?如果是这样,我如何正确设置步幅?

Alternatively, is there any way to get Eigen's complex data types to use separate chunks of memory for the real and imaginary parts?或者,有没有办法让 Eigen 的复杂数据类型为实部和虚部使用单独的内存块?

For what it's worth, the reason I need to do this is because I need to interface the Eigen library with MATLAB which can only handle separate arrays for real and imaginary parts, not interleaved in any way.就其价值而言,我需要这样做的原因是因为我需要将 Eigen 库与 MATLAB 连接,MATLAB 只能处理实部和虚部的单独数组,不能以任何方式交错。

That's easy, just use the .real() and .imag() views:这很简单,只需使用.real().imag()的观点:

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

Note that you can use M.real() into an expression without copying it into a MatrixXd .请注意,您可以将M.real()用于表达式,而无需将其复制到MatrixXd

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM