如何有效地提取Eigen3库中复杂矩阵的实部/虚部? [英] How to efficiently extract real/imaginary parts of complex matrix in Eigen3 library?

查看:458
本文介绍了如何有效地提取Eigen3库中复杂矩阵的实部/虚部?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have some complex, dense vectors/matrices in the Eigen3 library, and I want to extract the real and imaginary parts into separate arrays. In Matlab, I could do something like

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函数之类的东西?

Is there anything like the real() and imag() Matlab functions in Eigen3?

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

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.

我想做的是包裹几个Map<MatrixXd>,并围绕cplxFoo进行适当的调整,以获得真实的和虚构的部分.但是问题是MatrixXcd的元素是std::complex<double>,我不确定它的布局是什么.我的 guess std::complex<T>本质上像struct {T real; T imag;};那样布置,因此当您制作std::complex<T>数组时,实部和虚部都紧密包装和交织在一起(而且这似乎也是此SO问题)达成共识,但C ++对此有保证标准? AFAICT,一种兼容的C ++编译器,可以像struct {T imag; T real;};(注意更改的顺序)那样进行布局,也可以像

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. But the problem is that the elements of MatrixXcd are std::complex<double>, and I'm not sure what the layout of that is. My guess is that std::complex<T> is essentially laid out like 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? AFAICT, a compliant C++ compiler could lay it out like 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); }
    /* ... */
};

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

So, is it ok to wrap a couple of Map<MatrixXd> with appropriate strides around cplxFoo? If so, how do I set up the strides correctly?

或者,是否有任何方法可以让Eigen的复杂数据类型为实部和虚部使用单独的内存块?

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库与MATLAB接口,后者只能处理实部和虚部的单独数组,而不能以任何方式进行交织.

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.

推荐答案

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

That's easy, just use the .real() and .imag() views:

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

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

Note that you can use M.real() into an expression without copying it into a MatrixXd.

这篇关于如何有效地提取Eigen3库中复杂矩阵的实部/虚部?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆