Я использую FFTW3 для вычисления 2D реального FFT в C ++. Я прочитал руководство, но у меня есть несколько вопросов. Из руководства: http://www.fftw.org/fftw3_doc/One_002dDimensional-DFTs-of-Real-Data.html#One_002dDimensional-DFTs-of-Real-Data
В обмен на эти преимущества скорости и пространства пользователь жертвует
некоторые из простоты сложных преобразований FFTW. Прежде всего,
входные и выходные массивы имеют разные размеры и типы: входные
n действительных чисел, в то время как на выходе получается n / 2 + 1 комплексных чисел (
не избыточные выходы); это также требует небольшого «дополнения»
входной массив для преобразований на месте. Во-вторых, обратное преобразование
(сложный к реальному) имеет побочный эффект перезаписи входного массива,
по умолчанию. Ни одно из этих неудобств не должно вызывать серьезного
проблема для пользователей, но важно знать о них.
Я понимаю, что мне нужно преобразовать входную двумерную матрицу в одномерный вектор порядка строк. Но как выглядит результат? Что означают числа n / 2 + 1? Другими словами, как мне изменить порядок вывода, чтобы получить 2D матрицу?
Что конкретно я должен сделать, чтобы создать этот «отступ»?
Если ваш ввод уже находится в обычном двумерном массиве C ++, все, что вам нужно сделать, это ввести его:
double twoDarray[10][10];
double *oneDarrayPointer = (double *)twoDarray;
Если ваш ввод равен 100 (как в приведенном выше примере), ваш выходной массив будет 51 комплексным числом. Формат этих чисел должен быть описан вашей библиотекой, но, вероятно, это массив из 102 doubles
— 51 раз записи 2 (реальные / мнимые части).
Изменить: подтверждено — fftw_complex
определяется как:
typedef double fftw_complex[2];
Так что они просто последовательные пары doubles
представляющие действительные и мнимые части комплексного числа.
Если вы не хотите делать это на месте, вам не нужно ничего дополнять — просто выделите выходной массив соответствующего размера. если ты делать необходимо сделать это на месте, ваш буфер ввода должен иметь место для 2 дополнительных двойных по сравнению с размером ввода. Предполагая, что объявления выше, вы хотели бы что-то вроде:
double *inPlaceFFTPointer = malloc(sizeof twoDarray + 2*sizeof(double));
memcpy(inPlaceFFTPointer, oneDarrayPointer, sizeof twoDarray);
Я не уверен, нужно ли вам обязательно иметь 0.0
в последних двух записях или нет, но это достаточно легко добавить.
Вы можете взглянуть на реальные преобразования в FFTW3, которые делают именно то, что вы просили. Они не требуют заполнения и принимают во внимание, что как волновое число 0, так и значение, представляющее частоту Найквиста, имеют только реальный компонент. Посмотрите здесь:
FFTW3 Преобразование из реального в реальное
и для макета в памяти: