Skip to content

Instantly share code, notes, and snippets.

@rygorous
Created October 24, 2017 04:11
Show Gist options
  • Save rygorous/2244bcdca457936fbda86514a6d6332f to your computer and use it in GitHub Desktop.
Save rygorous/2244bcdca457936fbda86514a6d6332f to your computer and use it in GitHub Desktop.
Reference conjugate-pair split-radix FFT impl
#include <complex>
static size_t const kMaxN = 2048; // This is the largest straight FFT we support
typedef std::complex<float> complexf; // or use whatever other complex number type you prefer
// This is a "mip chain" of precomputed twiddle factors
// Twiddles for length-1 start at index 1,
// twiddles for length-2 start at index 2,
// ...,
// twiddles for length-256 start at index 256,
// etc.
static complexf s_twiddles[(kMaxN / 4) * 2];
// Reference conjugate split-radix pow2 FFT (DIT) - recursion
static void conj_fft_rec(complexf out[], complexf const in[], size_t offs, size_t mask, size_t stride, size_t N)
{
if (N == 1)
out[0] = in[offs & mask];
else if (N == 2)
{
complexf a = in[offs & mask];
complexf b = in[(offs + stride) & mask];
out[0] = a + b;
out[1] = a - b;
}
else
{
conj_fft_rec(out, in, offs, mask, stride * 2, N / 2);
conj_fft_rec(out + N/2, in, offs + stride, mask, stride * 4, N / 4);
conj_fft_rec(out + 3*N/4, in, offs - stride, mask, stride * 4, N / 4);
complexf const *twiddle = s_twiddles + N/4;
for (size_t k = 0; k < N/4; k++)
{
complexf Uk = out[k];
complexf Zk = out[k + N/2];
complexf Uk2 = out[k + N/4];
complexf Zdk = out[k + 3*N/4];
complexf const &w = twiddle[k];
// Twiddle
Zk *= w;
Zdk *= std::conj(w);
// Z butterflies
complexf Zsum = Zk + Zdk;
complexf Zdif = Zk - Zdk;
out[k] = Uk + Zsum;
out[k+N/2] = Uk - Zsum;
out[k+N/4] = Uk2 - complexf(0.0f, 1.0f)*Zdif;
out[k+3*N/4] = Uk2 + complexf(0.0f, 1.0f)*Zdif;
}
}
}
// Call this
static void conj_fft(complexf out[], complexf const in[], size_t N)
{
conj_fft_rec(out, in, 0, N - 1, 1, N);
}
static void twiddle_init()
{
for (size_t N = 1; N <= kMaxN / 4; N *= 2)
{
double const kPi = 3.1415926535897932384626433832795;
double step = -2.0 * kPi / (double)(N * 4);
complexf *twiddle = s_twiddles + N;
for (size_t k = 0; k < N; k++)
{
double phase = step * (double)k;
twiddle[k] = complexf((float)cos(phase), (float)sin(phase));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment