




/*! ****************************************************************************
\ingroup DFT_GROUP
\struct fft_t
\brief Структура данных объекта быстрого преобразования Фурье

Структура хранит указатели на массивы поворотных коэффициентов 
и массивы промежуточных данных алгоритма быстрого преобразования Фурье.

Библиотека DSPL использует для БПФ алгоритм для составной длины


\param  n
Размер вектора БПФ, для которого выделена память в массивах структуры.  \n
Парметр `n` должен быть равен целой степени двойки. \n \n


\param  w
Указатель на вектор поворотных коэффициентов алгоритма БПФ. \n
Размер вектора `[n x 1]`.  \n
Память должна быть выделена и массив поворотных коэффициентов 
должен быть заполнен функцией \ref fft_create.  \n \n


\param  t0
Указатель на вектор промежуточных вычислений алгоритма БПФ. \n
Размер вектора `[n x 1]`. \n
Память должна быть выделена функцией \ref fft_create. \n \n


\param  t1
Указатель на вектор промежуточных вычислений алгоритма БПФ. \n
Размер вектора `[n x 1]`. \n
Память должна быть выделена функцией \ref fft_create. \n \n
Структура заполняется функцией \ref fft_create один раз 
до использования алгоритма БПФ.  \n
Указатель на объект данной структуры может быть 
многократно использован при вызове функций БПФ. \n
Перед выходом из программы выделенную память под поворотные 
коэффициенты и массивы промежуточных данных
необходимо очистить функцией \ref fft_free. Например:
\code
fft_t pfft;     /* объявляем объект fft_t */
int n = 64;     /* Размер БПФ */

/*
обнуляем все поля и указатели. 
Данные шаг рекомендуется ввиду того, что некоторые
при создании переменной не инициализируют ее нулем.
*/

memset(&pfft, 0, sizeof(fft_t));

int err;

/* создаем объект для 64-точечного БПФ */
err = fft_create(&pfft, n);

/* Вызов БПФ функции*/
/* Еще раз вызов БПФ функции    */
/* ...  */

/* очистить память объекта БПФ  */
fft_free(&pfft);
\endcode

\note
Важно отметить, что если объект `fft_t` был создан для размера БПФ равного `n`, 
то он может быть использован только для БПФ размера `n`.  \n\n
Также необходимо заметить, что функции БПФ самостоятельно контролируют размер, 
и самостоятельно выделяют память объекта БПФ при необходимости. 
Так если вызвать любую функцию использующую структуру `fft_t` с заполненными 
данными для длины БПФ `k` для расчета БПФ длины `n`, 
то массивы структуры будут автоматически пересозданы для длины `n`.

\author
Бахурин Сергей.
www.dsplib.org 
***************************************************************************** */










/*! ****************************************************************************
\ingroup DFT_GROUP
\fn int ifft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y)
\brief Обратное быстрое преобразование Фурье

Функция рассчитывает \f$ n \f$-точечное обратное быстрое преобразование Фурье 
от \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n
\f[
  Y(k) = \frac{1}{N} \sum_{m = 0}^{n-1} x(m)   \exp 
   \left( j   \frac{2\pi}{n}    m    k \right),
\f]
где \f$ k = 0 \ldots n-1 \f$.

Для расчета используется алгоритм БПФ составной длины.

\param[in]  x
Указатель на входной комплексный вектор \f$x(m)\f$, 
\f$ m = 0 \ldots n-1 \f$.  \n
Размер вектора `[n x 1]`.  \n \n

\param[in]  n
Размер ОБПФ \f$n\f$. \n
Размер ОБПФ может быть составным вида 
\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$,
где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- 
произвольный простой множитель не превосходящий 46340
(см. описание функции \ref fft_create). \n \n

\param[in]  pfft
Указатель на структуру `fft_t`.  \n
Указатель не должен быть `NULL`.  \n
Структура \ref fft_t должна быть предварительно однократно
заполнена функцией  \ref fft_create, и память должна быть 
очищена перед выходом функцией \ref fft_free. \n \n

\param[out] y
Указатель на вектор результата ОБПФ \f$Y(k)\f$, 
\f$ k = 0 \ldots n-1 \f$. Размер вектора `[n x 1]`.  \n
Память должна быть выделена. \n \n

\return
`RES_OK` если расчет произведен успешно.  \n
В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n

Пример использования функции `fft`:

\include ifft_cmplx_test.c

Результат работы программы:

\verbatim
| x[ 0] =  1.000   0.000 | y[ 0] = -0.517   0.686 | z[ 0] =   1.000   0.000 |
| x[ 1] =  0.540   0.841 | y[ 1] = -0.943   0.879 | z[ 1] =   0.540   0.841 |
| x[ 2] = -0.416   0.909 | y[ 2] = -2.299   1.492 | z[ 2] =  -0.416   0.909 |
| x[ 3] = -0.990   0.141 | y[ 3] = 16.078  -6.820 | z[ 3] =  -0.990   0.141 |
| x[ 4] = -0.654  -0.757 | y[ 4] =  2.040  -0.470 | z[ 4] =  -0.654  -0.757 |
| x[ 5] =  0.284  -0.959 | y[ 5] =  1.130  -0.059 | z[ 5] =   0.284  -0.959 |
| x[ 6] =  0.960  -0.279 | y[ 6] =  0.786   0.097 | z[ 6] =   0.960  -0.279 |
| x[ 7] =  0.754   0.657 | y[ 7] =  0.596   0.183 | z[ 7] =   0.754   0.657 |
| x[ 8] = -0.146   0.989 | y[ 8] =  0.470   0.240 | z[ 8] =  -0.146   0.989 |
| x[ 9] = -0.911   0.412 | y[ 9] =  0.375   0.283 | z[ 9] =  -0.911   0.412 |
| x[10] = -0.839  -0.544 | y[10] =  0.297   0.318 | z[10] =  -0.839  -0.544 |
| x[11] =  0.004  -1.000 | y[11] =  0.227   0.350 | z[11] =   0.004  -1.000 |
| x[12] =  0.844  -0.537 | y[12] =  0.161   0.380 | z[12] =   0.844  -0.537 |
| x[13] =  0.907   0.420 | y[13] =  0.094   0.410 | z[13] =   0.907   0.420 |
| x[14] =  0.137   0.991 | y[14] =  0.023   0.442 | z[14] =   0.137   0.991 |
| x[15] = -0.760   0.650 | y[15] = -0.059   0.479 | z[15] =  -0.760   0.650 |
| x[16] = -0.958  -0.288 | y[16] = -0.161   0.525 | z[16] =  -0.958  -0.288 |
| x[17] = -0.275  -0.961 | y[17] = -0.300   0.588 | z[17] =  -0.275  -0.961 |
\endverbatim

\author
Бахурин Сергей
www.dsplib.org 
***************************************************************************** */




/*! ****************************************************************************
\ingroup DFT_GROUP
\fn int fft(double* x, int n, fft_t* pfft, complex_t* y)
\brief Быстрое преобразование Фурье вещественного сигнала

Функция рассчитывает \f$ n \f$-точечное  быстрое преобразование Фурье 
вещественного сигнала \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n
\f[
  Y(k) = \sum_{m = 0}^{n-1} x(m)   \exp 
  \left( -j   \frac{2\pi}{n}    m    k \right),
\f]
где \f$ k = 0 \ldots n-1 \f$.

Для расчета используется алгоритм БПФ составной длины.

\param[in]  x
Указатель на вектор вещественного входного сигнала \f$x(m)\f$, 
\f$ m = 0 \ldots n-1 \f$.  \n
Размер вектора `[n x 1]`.  \n \n

\param[in]  n
Размер БПФ \f$n\f$. \n
Размер БПФ может быть составным вида 
\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$,
где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- 
произвольный простой множитель не превосходящий 46340
(см. описание функции \ref fft_create). \n \n

\param[in]  pfft
Указатель на структуру `fft_t`. \n
Указатель не должен быть `NULL`. \n
Структура \ref fft_t должна быть предварительно однократно
заполнена функцией  \ref fft_create, и память должна быть 
очищена перед выходом функцией \ref fft_free. \n \n

\param[out] y
Указатель на комплексный вектор результата БПФ \f$Y(k)\f$, 
\f$ k = 0 \ldots n-1 \f$. \n
Размер вектора `[n x 1]`. \n
Память должна быть выделена. \n \n

\return
`RES_OK` если расчет произведен успешно.  \n
 В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n

Пример использования функции `fft`:

\include fft_test.c

Результат работы программы:

\verbatim
y[ 0] =    91.000    0.000
y[ 1] =    -7.000   30.669
y[ 2] =    -7.000   14.536
y[ 3] =    -7.000    8.778
y[ 4] =    -7.000    5.582
y[ 5] =    -7.000    3.371
y[ 6] =    -7.000    1.598
y[ 7] =    -7.000    0.000
y[ 8] =    -7.000   -1.598
y[ 9] =    -7.000   -3.371
y[10] =    -7.000   -5.582
y[11] =    -7.000   -8.778
y[12] =    -7.000  -14.536
y[13] =    -7.000  -30.669
\endverbatim

\author
Бахурин Сергей
www.dsplib.org 
***************************************************************************** */






/*! ****************************************************************************
\ingroup DFT_GROUP
\fn int fft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y)
\brief Быстрое преобразование Фурье комплексного сигнала

Функция рассчитывает \f$ n \f$-точечное  быстрое преобразование Фурье 
комплексного сигнала \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n
\f[
  Y(k) = \sum_{m = 0}^{n-1} x(m)   \exp 
   \left( -j   \frac{2\pi}{n}    m    k \right),
\f]
где \f$ k = 0 \ldots n-1 \f$.

Для расчета используется алгоритм БПФ составной длины.

\param[in]  x
Указатель на вектор комплексного 
входного сигнала \f$x(m)\f$, \f$ m = 0 \ldots n-1 \f$.  \n
Размер вектора `[n x 1]`. \n \n

\param[in]  n
Размер БПФ \f$n\f$. \n
Размер БПФ может быть составным вида 
\f$n = n_0 \times n_1 \times n_2 \times n_3 \times \ldots \times n_p \times m\f$,
где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- 
произвольный простой множитель не превосходящий 46340
(см. описание функции \ref fft_create). \n \n

\param[in]  pfft
Указатель на структуру `fft_t`. \n
Указатель не должен быть `NULL`.  \n
Структура \ref fft_t должна быть предварительно однократно
заполнена функцией  \ref fft_create, и память должна быть 
очищена перед выходом функцией \ref fft_free. \n \n

\param[out] y
Указатель на комплексный вектор 
результата БПФ \f$Y(k)\f$, 
\f$ k = 0 \ldots n-1 \f$. 
Размер вектора `[n x 1]`.  \n
Память должна быть выделена. \n \n

\return
`RES_OK` если расчет произведен успешно.  \n
 В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n

Пример использования функции `fft`:

\include fft_cmplx_test.c

Результат работы программы:

\verbatim
y[ 0] =    -0.517    0.686
y[ 1] =    -0.943    0.879
y[ 2] =    -2.299    1.492
y[ 3] =    16.078   -6.820
y[ 4] =     2.040   -0.470
y[ 5] =     1.130   -0.059
y[ 6] =     0.786    0.097
y[ 7] =     0.596    0.183
y[ 8] =     0.470    0.240
y[ 9] =     0.375    0.283
y[10] =     0.297    0.318
y[11] =     0.227    0.350
y[12] =     0.161    0.380
y[13] =     0.094    0.410
y[14] =     0.023    0.442
y[15] =    -0.059    0.479
y[16] =    -0.161    0.525
y[17] =    -0.300    0.588
\endverbatim

\author
Бахурин Сергей
www.dsplib.org 
***************************************************************************** */




/*! ****************************************************************************
\ingroup DFT_GROUP
\fn int fft_create(fft_t* pfft, int n)
\brief Заполнение структуры `fft_t` для алгоритма БПФ

Функция производит выделение памяти и рассчет векторов 
поворотных коэффициентов `n`-точечного БПФ для структуры `fft_t`.

\param[in,out]  pfft
Указатель на структуру `fft_t`.  \n
Указатель не должен быть `NULL`.  \n \n

\param[in]  n
Размер БПФ \f$n\f$. \n
Размер БПФ может быть составным вида 
\f$n = n_0 \times n_1 \times n_2 \ldots \times n_p \times m\f$,
где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- 
произвольный простой множитель не превосходящий 46340. \n
Таким образом алгоритм БПФ поддерживает произвольные длины, равные целой 
степени чисел 2,3,5,7, а также различные их комбинации.  \n
Так например, при \f$ n = 725760 \f$ структура будет успешно заполнена, 
потому что 
\f$725760 = 2 \cdot 3 \cdot 4 \cdot 5 \cdot 6 \cdot 7 \cdot 9 \cdot 16 \f$, 
т.е. получается как произведение множителей 2,3,5,7. \n
При \f$ n = 172804 = 43201 \cdot 4 \f$ структура также будет успешно заполнена, 
потому что простой множитель входящий в \f$n\f$ не превосходит 46340. \n
Для размера \f$ n = 13 \cdot 17 \cdot 23 \cdot 13 = 66079 \f$ 
функция вернет ошибку, поскольку 66079 больше 46340 и не является результатом 
произведения чисел 2,3,5,7. \n \n

\return
`RES_OK` если структура заполнена успешно. \n
В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n

\note
Некоторые компиляторы при создании структуры не обнуляют ее содержимое. 
Поэтому рекомендуется произвести обнуление структуры после ее объявления:
\code{.cpp}
fft_t pfft;     /* объявляем объект fft_t */
int n = 64;     /* Размер БПФ             */

/*
бнуляем все поля и указатели. 
Данные шаг рекомендуется ввиду того, что некоторые 
компиляторы при создании переменной не инициализируют ее нулем.
*/

memset(&pfft, 0, sizeof(fft_t));

int err;

/* создаем объект для 64-точечного БПФ */

err = fft_create(&pfft, n);

/* ................................... */

/* очистить память объекта БПФ         */

fft_free(&pfft);
\endcode

Перед выходом из программы выделенную в структуре память 
необходимо очистить функцией \ref fft_free . \n \n

\note
Магия числа 46340 заключается в том, что \f$\sqrt{2^{31}} = 46340.95\f$. \n

\author
Бахурин Сергей
www.dsplib.org 
***************************************************************************** */









/*! ****************************************************************************
\ingroup DFT_GROUP
\fn void fft_free(fft_t *pfft)
\brief Очистить структуру `fft_t` алгоритма БПФ

Функция производит очищение памяти промежуточных данных 
и векторов поворотных коэффициентов структуры `fft_t`.

\param[in] pfft
Указатель на структуру `fft_t`. \n

\author
Бахурин Сергей
www.dsplib.org 
***************************************************************************** */








/*! ****************************************************************************
\ingroup DFT_GROUP
\fn int fft_shift(double* x, int n, double* y)
\brief Перестановка спектральных отсчетов дискретного преобразования Фурье

Функция производит 
<a href="http://ru.dsplib.org/content/dft_freq/dft_freq.html">
перестановку спектральных отсчетов ДПФ
</a> и переносит нулевую частоту в центр вектора ДПФ.  \n
Данная функция обрабатывает вещественные входные и выходные вектора 
и может применяться для перестановки 
амплитудного или фазового спектра.

\param[in]  x
Указатель на исходный вектор ДПФ.  \n
Размер вектора `[n x 1]`.  \n \n

\param[in]  n
Размер ДПФ \f$n\f$ (размер векторов до и после перестановки). \n \n

\param[out] y
Указатель на вектор результата перестановки. \n
Размер вектора `[n x 1]`.  \n
Память должна быть выделена. \n \n


\return
`RES_OK` если перестановка произведена успешно.  \n
В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n

\author
Бахурин Сергей 
www.dsplib.org 
***************************************************************************** */
