La FFT,  ou   transformée  de Fourier   rapide,   est un    des quelques
algorithmes dont la publication a provoqué une véritable révolution dans
le champ technique.  Généralement  associé  aux noms de  J.W. Cooley  et
J.W. Tuckey  qui l'ont publié en  1965, cet  algorithme  de calcul de la
transformée de Fourier discrète avait été maintes fois << redécouvert >>
depuis Gauss, notamment par Danielson et Lanczos en 1942.  La FFT permet
de ramener le calcul  de la transformée de Fourier  discrète de  
   à
 
  opérations  ; cette  réduction  de complexité suffit  à  faire
passer d'impossibles à facilement résolubles nombre de problèmes.
La  transformée de Fourier discrète  d'un n-uplet de nombres complexes
 
  est le  n-uplet  
  défini par
 
 
où  
 .  Notons que  
  et
que pour n=1, ceci se réduit en  
 . La transformée inverse
se calcule ainsi :
 
 
Supposons que n=2m et séparons les éléments de a d'indices pairs de ceux d'indices impairs :
 
 
Alors, en séparant la somme en deux termes regroupant d'une part les
p=2j et d'autre part les p=2j+1, et en utilisant l'égalité
 
  :
 
 
Ainsi, pour calculer la transformée de Fourier sur n points, il suffit
de calculer deux transformées de Fourier sur  n/2 points, de faire n
multiplications et n additions.  Si n est  une puissance de 2, cette
décomposition peut s'appliquer récursivement, ce qui donne pour équation
de complexité  :  
 .    Il en  résulte  une
complexité en  
   opérations.
   
 
Figure: Arbre des appels de la FFT sur 8 points
La figure 
 représente  l'arbre  des appels de ce  calcul
récursif pour n=8 points : aux  feuilles, la FFT  sur 1 point, qui est
l'identité.   L'ordre dans  lequel    les   
  sont rangés   dans  les
feuilles,  de gauche à  droite, est << l'inverse binaire  >> de p.  La
fonction bit_rev(h,p)  renverse la représentation  binaire  de
n,  pour  
  ;  par  exemple,  
  ; on utilise
l'opérateur  dyadique << (non  décrit  dans ce  cours, comme  les
autres opérateurs  dyadiques  &, |,  ^ et  ~)
pour calculer  
  :
int bit_rev(int h, int p) {
  int y = 0;
  int n = 1 << h;        /* n = 2 puissance h */      
  int r;
  while (h>0) {
    h = h-1;
    n = n/2;
    r = p%2;
    p = p/2;
    if (r == 1) {
      y = n + y;
    }
  }
  return y;
}
On va donc commencer par permuter le n-uplet a pour ranger ses éléments dans cet ordre :
void bit_rev_array(int h, const int a[], int b[]) {
  int p;
  for (p=0; p < 1<<h; p++) {
    b[bit_rev(h,p)] = a[p];
  }
}
Cela va permettre de construire un algorithme itératif, qui parcourt l'arbre des feuilles vers la racine.
En utilisant la  périodicité de la  transformée de Fourier, et l'égalité
 
 , on peut réécrire la  dernière expression de  
 
:
 
 
Cette  transformation, de la  forme  
 , est appelée un papillon  (en anglais, butterfly) ; on
l'appliquera  successivement avec    
 ,  
 ,   
 ,
...,  
 .
Plutôt que de programmer cette transformation  sur des nombres complexes
(ce qui est   légèrement plus ennuyeux),   on va écrire  le programme en
arithmétique modulo N, où    
 ,  et  t est  un entier
quelconque, en  posant   
 ,   qui  est une  racine  n-ème
principale de  l'unité dans    
  ; on   a toujours
 
 .   Par  exemple, quand t=2  et    
 , on a  N=257,  et
 
  ; un n-uplet et sa transformée sont :
 
 
La fonction butterfly modulo N s'écrit :
void butterfly(int a[], int j, int k, int alpha, int N) {
  int u = a[j];
  int v = (alpha * a[k]) % N;
  a[j] = (u+v) % N;
  a[k] = (u-v+N) % N;
}
void fft(int h, int N, int omega, const int a[], int fft_a[]) {
  int n = 1<<h;
  int l;
  bit_rev_array(h, a, fft_a);
  for (l=1; l<=h; l++) {
    int i;
    int alpha = 1;
    int omega_l = expmod(omega, 1<<(h-l),N);
    int m = 1 << l;
    for (i=0; i<m/2; i++) {
      int j;
      for (j=i; j<n; j = j+m) {
        butterfly(fft_a, j, j+m/2, alpha, N);
      }
      alpha = (alpha * omega_l) % N;
    }
  }
}