Преобразование плоского массива в сложный собственный тип - PullRequest
0 голосов
/ 10 февраля 2020

Как я могу изменить data размера 1×2N в комплексную форму в Eigen в форму P×Q комплексной матрицы с N комплексными числами P×Q=N? В data действительная и воображаемая части находятся рядом друг с другом. Я хотел бы динамически изменить data, поскольку данные могут иметь разные размеры. Я пытаюсь предотвратить копирование и просто сопоставить данные со сложным типом.

int N = 9;
int P = 3;
int Q = 6;
float *data = new float[2*N];
for(int i = 0; i < 2*N; i++)
    data[i] = i + 1; // data = {1, 2, 3, 4, ..., 17, 18};

Eigen::Map<Eigen::MatrixXcf> A(data, P, Q); // trying to have something like this.

// Desired reshaping:
// A = [
//      1 + 2i     7 + 8i     13 + 14i
//      3 + 4i     9 + 10i    15 + 16i
//      5 + 6i    11 + 12i    17 + 18i
//      ]

Я пытался сначала преобразовать data в сложный массив Eigen (чтобы в конечном итоге преобразовать в MatrixXcf), что не работать либо:

Eigen::Map<Eigen::ArrayXf> Arr(data, N); // this works
Eigen::Map<Eigen::ArrayXcf> Arrc(A.data(), N); // trying to map data to an Eigen complex array.

Может ли stride в Eigen::Map быть полезным?

Самое простое решение - l oop через все элементы и преобразовать data в массив std::complex<float> *datac = new std::complex<float>[N];. Мне было интересно, может ли Эйген сопоставить data с datac. Заранее спасибо.

1 Ответ

2 голосов
/ 12 февраля 2020

Вот ответ MCVE ( онлайн-пример ) с некоторыми дополнительными примерами того, как вы можете использовать шаг, чтобы получить разные результаты:

#include "Eigen/Core"
#include <iostream>
#include <complex>

int main()
{
    int N = 9;
    int P = 3;
    int Q = 6;
    float *data = new float[20*N];
    for(int i = 0; i < 20*N; i++)
        data[i] = i + 1; // data = {1, 2, 3, 4, ..., 170, 180};

    // Produces the output of the "Desired reshaping"
    Eigen::Map<Eigen::MatrixXcf> 
               A((std::complex<float>*)(data), P, P);
    std::cout << A << "\n\n";

    // Produces what you originally wrote (plus a cast so it works)
    Eigen::Map<Eigen::MatrixXcf>
               B((std::complex<float>*)(data), P, Q);
    std::cout << B << "\n\n";

    // Start each column at the 10xJ position
    Eigen::Map<Eigen::MatrixXcf, 0, Eigen::OuterStride<>> 
               C((std::complex<float>*)(data), P, Q, Eigen::OuterStride<>(10));
    std::cout << C << "\n\n";

    // Skip every other value
    Eigen::Map<Eigen::MatrixXcf, 0, Eigen::InnerStride<>> 
               D((std::complex<float>*)(data), P, Q, Eigen::InnerStride<>(2));
    std::cout << D << "\n\n";

    delete [] data;
    return 0;
}

Вывод:

(1,2) (7,8) (13,14)
(3,4) (9,10) (15,16)
(5,6) (11, 12) (17,18)

(1,2) (7,8) (13,14) (19,20) (25,26) (31,32)
(3,4 ) (9,10) (15,16) (21,22) (27,28) (33,34)
(5,6) (11,12) (17,18) (23,24) ( 29,30) (35,36)

(1,2) (21,22) (41,42) (61,62) (81,82) (101,102)
(3,4 ) (23,24) (43,44) (63,64) (83,84) (103,104)
(5,6) (25,26) (45,46) (65,66) (85, 86) (105,106)

(1,2) (13,14) (25,26) (37,38) (49,50) (61,62)
(5,6) ( 17,18) (29,30) (41,42) (53,54) (65,66)
(9,10) (21,22) (33,34) (45,46) (57, 58) (69,70)

...