/* * FFT.c * PRICE * * Created by Riccardo Mottola on Sat Sep 13 2003. * Copyright (c) 2002-2005 Carduus. All rights reserved. * */ // This program is free software; you can redistribute it and/or modify it under the terms of the version 2 of the GNU General Public License as published by the Free Software Foundation. // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. #include "FFT.h" double *cosinus; double *sinus; unsigned int *bitRevIndex; int initTrigonometrics(int num, unsigned int bitNumber) /* we init here the trigonometric arrays but we also init the bit reerse array */ { int i; double alpha; alpha = (2 * PI) / num; for (i = 0; i < num; i++) { cosinus[i] = cos(-alpha * i); sinus[i] = sin(-alpha * i); } for (i = 0; i < num; i++) bitRevIndex[i] = bitrev(i, bitNumber); return 0; } unsigned int binaryLog(unsigned int a) /* returns the smallest 2 power that contains the a */ { unsigned int i; unsigned int j; i = 1; j = 1; while (i < a) { i = i << 1; j++; } return j - 1; } unsigned int binpow(unsigned int n) { return 1 << n; } unsigned int bitrev(unsigned int i, unsigned int len) /* returns the bit-reverse of i given the bit number to work on */ { unsigned int r; unsigned int j; r = 0; for (j = 0; j < len-1; j++) /* we don't have to shift for the last position */ { r = r | (i & 1); r = r << 1; i = i >> 1; } r = r | (i & 1); return r; } int fft(int num, unsigned int bitNumber, double Ar[], double Ai[], double yr[], double yi[]) { unsigned int i; unsigned int s; unsigned int m; unsigned int j; unsigned int k; register double omega_r, omega_i; /* current unity root */ register unsigned int gamma; register double t_r, t_i; register double u_r, u_i; for (i = 0; i < num; i++) /* exponents are 0 to n-1 for n bits */ { yr[bitRevIndex[i]] = Ar[i]; yi[bitRevIndex[i]] = Ai[i]; } for (s = 1; s <= bitNumber; s++) { m = binpow(s); for (j = 0; j < m/2; j++) { gamma = ((num / m) * j) % num; omega_r = cosinus[gamma]; omega_i = sinus[gamma]; for (k = j; k < num; k += m) { t_r = omega_r * yr[k + m/2] - omega_i * yi[k + m/2]; t_i = omega_r * yi[k + m/2] + omega_i * yr[k + m/2]; u_r = yr[k]; u_i = yi[k]; yr[k] = u_r + t_r; yi[k] = u_i + t_i; yr[k + m/2] = u_r - t_r; yi[k + m/2] = u_i - t_i; } } } return 0; } int ifft(int num, unsigned int bitNumber, double Ar[], double Ai[], double yr[], double yi[]) { unsigned int i; unsigned int s; unsigned int m; unsigned int j; unsigned int k; register double omega_r, omega_i; /* current unity root */ register unsigned int gamma; register double t_r, t_i; register double u_r, u_i; for (i = 0; i < num; i++) /* exponents are 0 to n-1 for n bits */ { yr[bitRevIndex[i]] = Ar[i]; yi[bitRevIndex[i]] = Ai[i]; } for (s = 1; s <= bitNumber; s++) { m = binpow(s); for (j = 0; j < m/2; j++) { /* we follow the unity roots in the opposite direction */ /* but since sin(-a) = -sin(a) but cos(-a)=cos(a) just a sign is needed */ gamma = ((num / m) * j) % num; omega_r = cosinus[gamma]; omega_i = -sinus[gamma]; for (k = j; k < num; k += m) { t_r = omega_r * yr[k + m/2] - omega_i * yi[k + m/2]; t_i = omega_r * yi[k + m/2] + omega_i * yr[k + m/2]; u_r = yr[k]; u_i = yi[k]; yr[k] = u_r + t_r; yi[k] = u_i + t_i; yr[k + m/2] = u_r - t_r; yi[k + m/2] = u_i - t_i; } } } for (i = 0; i < num; i++) { yr[i] = yr[i]/num; yi[i] = yi[i]/num; } return 0; }