FFT¶
Each FFT object owns one plan and is reused across calls. Multiple
instances of different sizes or signs coexist with no global state.
1-D FFT¶
from doppler.spectral import FFT
import numpy as np
rng = np.random.default_rng(0)
x32 = (rng.standard_normal(1024) + 1j * rng.standard_normal(1024)).astype(np.complex64)
f = FFT(1024)
X32 = f.execute_cf32(x32) # complex64 in → complex64 out
print(X32.dtype)
# Parseval: Σ|x|² == Σ|X|² / N
err = abs(np.sum(np.abs(x32)**2) - np.sum(np.abs(X32)**2) / 1024)
print(f"Parseval error: {err:.3e}")
CF64 input auto-selects the double-precision path:
x64 = rng.standard_normal(1024) + 1j * rng.standard_normal(1024)
X64 = f.execute_cf64(x64) # complex128 in → complex128 out
print(X64.dtype)
Reusing a plan¶
Plan once, transform many times — no reallocation on repeated calls:
f = FFT(1024)
for _ in range(1000):
out = f.execute_cf32(x32) # out-of-place, returns new array
out = f.execute_inplace_cf32(x32) # uses internal buffer, same result