Skip to content

Instantly share code, notes, and snippets.

@amb
Created May 12, 2022 12:43
Show Gist options
  • Save amb/4f70bcbea897024452d683b40d18be1f to your computer and use it in GitHub Desktop.
Save amb/4f70bcbea897024452d683b40d18be1f to your computer and use it in GitHub Desktop.
Simple Nim FFT
# OTFFT library
# http://wwwa.pikara.ne.jp/okojisan/otfft-en/optimization1.html
# This is +20-50% improvement
const thetaLutSize = 2048
const thetaLut = static:
var arr: array[thetaLutSize, Complex[float]]
let step = 2.0*PI/float(thetaLutSize)
for k, v in mpairs(arr):
v = complex(cos(step * float(k)), -sin(step * float(k)))
arr
proc fft0(n: int, s: int, eo: bool, x: var seq[Complex[float]], y: var seq[Complex[float]]) =
## Fast Fourier Transform
##
## Inputs:
## - `n` Sequence length. **Must be power of two**
## - `s` Stride
## - `eo` x is output if eo == 0, y is output if eo == 1
## - `x` Input sequence(or output sequence if eo == 0)
## - `y` Work area(or output sequence if eo == 1)
##
## Returns:
## - Output sequence, either `x` or `y`
let m: int = n div 2
let theta0: float = 2.0*PI/float(n)
# let theta0: float = float(thetaLutSize)/float(n)
if n == 1:
if eo:
for q in 0..<s:
y[q] = x[q]
else:
for p in 0..<m:
let fp = float(p)*theta0
let wp = complex(cos(fp), -sin(fp))
# let fp = int(float(p)*theta0)
# let wp = thetaLut[fp]
for q in 0..<s:
let a = x[q + s*(p+0)]
let b = x[q + s*(p+m)]
y[q + s*(2*p+0)] = a + b
y[q + s*(2*p+1)] = (a - b) * wp
fft0(n div 2, 2 * s, not eo, y, x)
proc fft*(x: var seq[Complex[float]]) =
# n : sequence length
# x : input/output sequence
# Input length has to be a power of two
assert x.len > 0
assert x.len.isPowerOfTwo()
var y: seq[Complex[float]] = newSeq[Complex[float]](x.len)
fft0(x.len, 1, false, x, y)
proc ifft*(x: var seq[Complex[float]]) =
# n : sequence length
# x : input/output sequence
var n: int = x.len
let fn = complex(1.0/float(n))
for p in 0..<n:
x[p] = (x[p]*fn).conjugate
var y: seq[Complex[float]] = newSeq[Complex[float]](n)
fft0(n, 1, false, x, y)
for p in 0..<n:
x[p] = x[p].conjugate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment