我在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
中。