Как эффективно извлекать реальные / мнимые части комплексной матрицы в библиотеке Eigen3?

у меня есть некоторые сложные, плотные векторы/матрицы в библиотеке 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

есть ли что-нибудь подобное real() и imag() функции Matlab в Eigen3?

сейчас, единственное, что я знаю получится что-то вроде

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 are std::complex<double> и я не уверен, что макет это. Мой Угадай это std::complex<T> по существу выложен как struct {T real; T imag;}; так что реальные и мнимые части плотно упакованы и чередуются, когда вы делаете массив std::complex<T> (и это также, кажется, консенсус в это так вопрос), но гарантируется ли это стандартом 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, которая может обрабатывать только отдельные массивы для реальных и мнимых частей, никак не чередующихся.

1 ответов


Это легко, просто используйте .real() и .imag() вид:

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

обратите внимание, что вы можете использовать M.real() В выражение без копирования его в MatrixXd.