Created
October 24, 2017 04:11
-
-
Save rygorous/2244bcdca457936fbda86514a6d6332f to your computer and use it in GitHub Desktop.
Reference conjugate-pair split-radix FFT impl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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