Как использовать FFTW plan many dft для транспонированного массива данных?
у меня есть 2D-массив данных, хранящихся в формате column-major (Fortran-style), и я хотел бы взять БПФ каждого строка. Я хотел бы избежать транспонирования массива (это не квадрат). Например, мой массив
fftw_complex* data = new fftw_complex[21*256];
содержит записи [r0_val0, r1_val0,..., r20_val0, r0_val1,...,r20_val255]
.
я могу использовать fftw_plan_many_dft
составить план решения каждого из 21 БПФ на месте в data
массив, если это строка-майор, например,[r0_val0, r0_val1,..., r0_val255, r1_val0,...,r20_val255]
:
int main() {
int N = 256;
int howmany = 21;
fftw_complex* data = new fftw_complex[N*howmany];
fftw_plan p;
// this plan is OK
p = fftw_plan_many_dft(1,&N,howmany,data,NULL,1,N,data,NULL,1,N,FFTW_FORWARD,FFTW_MEASURE);
// do stuff...
return 0;
}
по данным документация (раздел 4.4.1 руководства FFTW), подпись для функции
fftw_plan fftw_plan_many_dft(int rank, const int *n, int howmany,
fftw_complex *in, const int *inembed,
int istride, int idist,
fftw_complex *out, const int *onembed,
int ostride, int odist,
int sign, unsigned flags);
и я должен иметь возможность использовать stride
и dist
параметры для настройки индексирования. Из того, что я могу понять из документации, записи в массиве для преобразования индексируются как in + j*istride + k*idist
здесь j=0..n-1
и k=0..howmany-1
. (Мои массивы 1D и есть howmany
из них). Однако следующий код приводит к seg. ошибка ( edit: длина шага составляет неправильно см. обновление ниже):
int main() {
int N = 256;
int howmany = 21;
fftw_complex* data = new fftw_complex[N*howmany];
fftw_plan p;
// this call results in a seg. fault.
p = fftw_plan_many_dft(1,&N,howmany,data,NULL,N,1,data,NULL,N,1,FFTW_FORWARD,FFTW_MEASURE);
return 0;
}
обновление:
я сделал ошибку, выбрав длину шага. Правильный вызов (правильная длина шага -howmany
, а не N
):
int main() {
int N = 256;
int howmany = 21;
fftw_complex* data = new fftw_complex[N*howmany];
fftw_plan p;
// OK
p = fftw_plan_many_dft(1,&N,howmany,data,NULL,howmany,1,data,NULL,howmany,1,FFTW_FORWARD,FFTW_MEASURE);
// do stuff
return 0;
}
1 ответов
функция работает как описано. Я сделал ошибку с длиной шага, которая на самом деле должна быть howmany
в этом случае. Я обновил вопрос, чтобы отразить это.
я нахожу документацию для FFTW несколько трудной для понимания без примеров (я мог бы просто быть неграмотным...), поэтому я публикую более подробный пример ниже, сравнивая обычное использование fftw_plan_dft_1d
С fftw_plan_many_dft
. Напомним, в случае howmany
массивы с длиной N
, которые хранятся в непрерывный блок памяти, на который ссылаются как in
, массив j
для каждого преобразования k
are
*(in + j*istride + k*idist)
следующие две части кода эквивалентны. В первом преобразование из некоторого 2D массива выполняется явно, а во втором fftw_plan_many_dft
вызов используется, чтобы сделать все на месте.
Явная Копия
int N, howmany;
// ...
fftw_complex* data = (fftw_complex*) fftw_malloc(N*howmany*sizeof(fftw_complex));
// ... load data with howmany arrays of length N
int istride, idist;
// ... if data is column-major, set istride=howmany, idist=1
// if data is row-major, set istride=1, idist=N
fftw_complex* in = (fftw_complex*) fftw_malloc(N*sizeof(fftw_complex));
fftw_complex* out = (fftw_complex*) fftw_malloc(N*sizeof(fftw_complex));
fftw_plan p = fftw_plan_dft_1d(N,in,out,FFTW_FORWARD,FFTW_MEASURE);
for (int k = 0; k < howmany; ++k) {
for (int j = 0; j < N; ++j) {
in[j] = data[j*istride + k*idist];
}
fftw_execute(p);
// do something with out
}
План Много
int N, howmany;
// ...
fftw_complex* data = (fftw_complex*) fftw_malloc(N*howmany*sizeof(fftw_complex));
// ... load data with howmany arrays of length N
int istride, idist;
// ... if data is column-major, set istride=howmany, idist=1
// if data is row-major, set istride=1, idist=N
fftw_plan p = fftw_plan_many_dft(1,&N,howmany,data,NULL,howmany,1,data,NULL,howmany,1,FFTW_FORWARD,FFTW_MEASURE);
fftw_execute(p);