Article 10 — Appendix A.2
Fast Fourier transform — FFT — source code
fft.cpp
#include "fft.h"
#include <math.h>
bool CFFT::Forward(const complex *const Input, complex *const Output,
const unsigned int N)
{
if (!Input || !Output || N < 1 || N & (N - 1))
return false;
Rearrange(Input, Output, N);
Perform(Output, N);
return true;
}
bool CFFT::Forward(complex *const Data, const unsigned int N)
{
if (!Data || N < 1 || N & (N - 1))
return false;
Rearrange(Data, N);
Perform(Data, N);
return true;
}
bool CFFT::Inverse(const complex *const Input, complex *const Output,
const unsigned int N, const bool Scale )
{
if (!Input || !Output || N < 1 || N & (N - 1))
return false;
Rearrange(Input, Output, N);
Perform(Output, N, true);
if (Scale)
CFFT::Scale(Output, N);
return true;
}
bool CFFT::Inverse(complex *const Data, const unsigned int N,
const bool Scale )
{
if (!Data || N < 1 || N & (N - 1))
return false;
Rearrange(Data, N);
Perform(Data, N, true);
if (Scale)
CFFT::Scale(Data, N);
return true;
}
void CFFT::Rearrange(const complex *const Input, complex *const Output,
const unsigned int N)
{
unsigned int Target = 0;
for (unsigned int Position = 0; Position < N; ++Position)
{
Output[Target] = Input[Position];
unsigned int Mask = N;
while (Target & (Mask >>= 1))
Target &= ~Mask;
Target |= Mask;
}
}
void CFFT::Rearrange(complex *const Data, const unsigned int N)
{
unsigned int Target = 0;
for (unsigned int Position = 0; Position < N; ++Position)
{
if (Target > Position)
{
const complex Temp(Data[Target]);
Data[Target] = Data[Position];
Data[Position] = Temp;
}
unsigned int Mask = N;
while (Target & (Mask >>= 1))
Target &= ~Mask;
Target |= Mask;
}
}
void CFFT::Perform(complex *const Data, const unsigned int N,
const bool Inverse )
{
const double pi = Inverse ? 3.14159265358979323846 : -3.14159265358979323846;
for (unsigned int Step = 1; Step < N; Step <<= 1)
{
const unsigned int Jump = Step << 1;
const double delta = pi / double(Step);
const double Sine = sin(delta * .5);
const complex Multiplier(-2. * Sine * Sine, sin(delta));
complex Factor(1.);
for (unsigned int Group = 0; Group < Step; ++Group)
{
for (unsigned int Pair = Group; Pair < N; Pair += Jump)
{
const unsigned int Match = Pair + Step;
const complex Product(Factor * Data[Match]);
Data[Match] = Data[Pair] - Product;
Data[Pair] += Product;
}
Factor = Multiplier * Factor + Factor;
}
}
}
void CFFT::Scale(complex *const Data, const unsigned int N)
{
const double Factor = 1. / double(N);
for (unsigned int Position = 0; Position < N; ++Position)
Data[Position] *= Factor;
}
|