The fastest FFT in the world is worthless if a typo crashes your pipeline at runtime. So we moved the crash to compile time.
Today we released OxiFFT 0.2.0 — a minor release with breaking changes that retypes the 2D/3D and real-FFT plan APIs so the wrong shape no longer compiles, and adds a drop-in FFTW-style compatibility surface for porting C code.
No C. No Fortran. No FFTW. No FFI. OxiFFT is Pure Rust to the core: its default features are 100% Rust, and it compiles to a single static binary — or to WASM — with nothing to link against and nothing to pkg-config. It is a Pure Rust port of FFTW3 — the “Fastest Fourier Transform in the West” — without inheriting FFTW’s build system, and it displaces rustfft for the Rust niche at the same time. It is the spectral backbone of the SciRS2 / signal / audio stack.
Why OxiFFT 0.2.0 is a step up
FFTW is a C API, and C APIs make their mistakes at runtime. Hand fftw_plan_dft_2d the wrong dimensions, execute a real plan as if it were complex, or ignore a null plan, and the failure shows up as a crash — in production, on someone else’s data, far from where the bug lives. OxiFFT 0.2.0 takes a different stance: the type system catches the mistake at compile time, and for teams coming from FFTW there is now a migration on-ramp that keeps your existing call sites almost verbatim.
Concretely, this release delivers:
- Honest plan types.
dft_2d()returnsOption<Plan2D<T>>anddft_3d()returnsOption<Plan3D<T>>— not a one-size-fits-allOption<Plan<T>>. The dimensionality is in the type, so a 2D plan can’t be misused as 3D. - Real plans that can’t be confused with complex ones.
r2c_1d()andc2r_1d()returnOption<RealPlan<T>>. The real/complex distinction is now load-bearing in the signature. - Failures you can’t ignore.
#[must_use]on every plan-creation method turns a silently droppedNoneinto a compiler warning. - An FFTW migration path. The new
fftw-compatfeature exposesoxifft::compatwith FFTW-shaped names, so C code ports with minimal edits. - Fewer ways to panic. Six runtime panics reachable from the public API — four
todo!()and twounimplemented!()— are gone.
Technical Deep Dive
Type-safe plans. The headline change is that the multidimensional and real planners now return the type they always built. Previously, dft_2d(), dft_3d(), r2c_1d(), and c2r_1d() all funneled through Option<Plan<T>>, and a mismatched shape was a runtime-panic path waiting to be hit. In 0.2.0 the signatures are honest:
Plan::dft_2d()→Option<Plan2D<T>>Plan::dft_3d()→Option<Plan3D<T>>Plan::r2c_1d()→Option<RealPlan<T>>Plan::c2r_1d()→Option<RealPlan<T>>
The value was always 2D, 3D, or real under the hood — this just makes the type system tell the truth about it. A wrong-shape call that used to compile and then panic now simply doesn’t compile. Every plan-creation method carries #[must_use], so ignoring a returned None is a warning rather than a silent foot-gun, and Debug is now implemented on all public plan types so you can print and inspect a plan while debugging.
#[non_exhaustive] enums. All public enums are now #[non_exhaustive]. This future-proofs the ABI: we can add new variants in a later minor release without it being a breaking change. The cost is small and explicit — any downstream match over an OxiFFT public enum needs a wildcard _ => arm. While auditing the enums we also removed the IndirectStrategy enum and its IndexArray variant, which were dead code that was never constructed.
FFTW Compatibility API. Behind the new fftw-compat feature, the oxifft::compat module mirrors the FFTW C API with FFTW-style names, so existing FFTW code ports almost line for line:
fftw_plan_dft_1d(n, direction, flags) -> Option<Plan<f64>>and its single-precision twinfftwf_plan_dft_1d(...) -> Option<Plan<f32>>fftw_plan_dft_2d(...)andfftw_plan_dft_3d(...)fftw_plan_dft_r2c_1d(n, flags) -> Option<RealPlan<f64>>andfftw_plan_dft_c2r_1d(...)fftw_plan_many_dft(...)for batched transformsfftw_execute(plan, input, output)andfftw_destroy_plan(plan)fftw_export_wisdom_to_string() -> Option<String>andfftw_import_wisdom_from_string(s: &str) -> bool
It is Pure Rust underneath — the FFTW shape is purely an ergonomic on-ramp, not an FFI binding.
Getting Started
cargo add oxifft
use oxifft::{Complex, Direction, Flags, Plan2D};
// 2D forward FFT — now returns Option<Plan2D<f64>>: wrong shapes won't compile
let plan = Plan2D::new(64, 64, Direction::Forward, Flags::ESTIMATE)
.expect("64x64 plan");
let input = vec![Complex::new(0.0_f64, 0.0); 64 * 64];
let mut output = vec![Complex::new(0.0_f64, 0.0); 64 * 64];
plan.execute(&input, &mut output);
The FFTW-compatibility surface is behind a feature flag — enable it with cargo add oxifft --features fftw-compat when you are porting existing FFTW code.
What’s New in 0.2.0
- Type-safe multidimensional and real plans —
dft_2d()→Option<Plan2D<T>>,dft_3d()→Option<Plan3D<T>>, andr2c_1d()/c2r_1d()→Option<RealPlan<T>>, replacing the old one-sizeOption<Plan<T>>that could panic on a shape mismatch. - FFTW Compatibility API (
fftw-compatfeature) — theoxifft::compatmodule with FFTW-style names (fftw_plan_dft_1d,fftw_plan_dft_2d,fftw_execute, and the rest), so C code ports nearly verbatim. #[must_use]on every plan-creation method that returns anOption<Plan...>, so a dropped plan is a warning.Debugon all public plan types, for printable, inspectable plans.#[non_exhaustive]on all public enums, future-proofing the ABI (downstreammatchneeds a_ =>arm).- Removed dead code — the
IndirectStrategyenum and itsIndexArrayvariant, plus stale#[allow(dead_code)]attributes in production code. - Six runtime panics eliminated from the public API — four
todo!()and twounimplemented!(). - A cleaner lint baseline — crate-level
#[allow(clippy::...)]cut from 60 to under 30 by fixing the underlying lint sites. - Hardened sparse FFT — the FFAST sparse-FFT peeling decoder now handles edge cases (
k=0,k=n, pure noise), with new property-based tests for sparse FFT and every DCT/DST variant. - 858 tests passing for this release.
Tips
-
Migrating
dft_2d/dft_3d: change your binding type fromPlantoPlan2D/Plan3D. The value was always 2D/3D under the hood — this change just makes the type honest, so the migration is a one-line annotation update at each call site, not a logic change. The same applies tor2c_1d/c2r_1d, which now hand back aRealPlan. -
#[non_exhaustive]enums: add a wildcard arm to anymatchover an OxiFFT public enum, or it won’t compile:match direction { Direction::Forward => { /* ... */ } Direction::Inverse => { /* ... */ } _ => { /* required: enums are now #[non_exhaustive] */ } } -
Porting FFTW C code: enable the
fftw-compatfeature and keep yourfftw_plan_dft_1d/fftw_executecall sites almost as they were:use oxifft::compat::{fftw_plan_dft_1d, fftw_execute}; let plan = fftw_plan_dft_1d(1024, oxifft::Direction::Forward, oxifft::Flags::MEASURE).unwrap(); // fftw_execute(plan, &input, &mut output);Wisdom round-trips too:
fftw_export_wisdom_to_string()andfftw_import_wisdom_from_string()mirror the FFTW calls you already have. -
Don’t drop a plan-returning call. With
#[must_use]in place, a barePlan2D::new(...)whose result you ignore is now a compiler warning — bind it (or.expect(...)it) so aNoneplan can’t be silently discarded. -
r2candc2rare real plans now. If you were matching on or storing the oldPlan<T>for real transforms, switch the type toRealPlan<T>; the compiler will point at every site that needs the change.
The foundation
OxiFFT is the spectral layer of the COOLJAPAN ecosystem, and an FFT is a dependency almost every scientific and ML pipeline reaches for sooner or later. By mid-April 2026 it sits beside mature siblings — SciRS2 for scientific computing, NumRS2 for arrays, OxiBLAS for linear algebra, ToRSh for tensors, SkleaRS for classical ML, TenfloweRS and TrustformeRS for deep learning, and OxiWhisper for speech — and every spectral transform underneath them can now rest on a plan API that fails at compile time instead of at 3 a.m.
Repository: https://github.com/cool-japan/oxifft
Star the repo if a Pure Rust FFT — one that catches your mistakes before they ship and lets you bring your FFTW code with you — is something you want to build on.
Pure Rust spectral computing is here — fast, safe, and sovereign.
— KitaSan at COOLJAPAN OÜ April 14, 2026