如何有效地提取Eigen3库中复杂矩阵的实部/虚部? [英] How to efficiently extract real/imaginary parts of complex matrix in Eigen3 library?
问题描述
我在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屋!