Distributed real transforms land, and auto-tuning finally does what its name promises.
Today we released OxiFFT 0.4.0 — a release that adds distributed real (r2c/c2r) FFTs to the MPI adapter, wires the wisdom cache into MEASURE/PATIENT/EXHAUSTIVE planning so those flags genuinely benchmark competing algorithms, and cleans up a batch of dead code and packaging debt along the way.
No C. No Fortran. No FFTW. No FFI. OxiFFT is Pure Rust to the core, with default features that are 100% Rust — it compiles to a single static binary or to WASM, and displaces FFTW3 and rustfft for in-process transforms (and FFTW-MPI for distributed ones). The spectral backbone for the SciRS2 signal and audio stack, and now for 21 other COOLJAPAN projects, carries no native baggage.
Why 0.4.0 matters
This release ships one major capability, one long-standing correctness gap closed, and a breaking cleanup that’s overdue:
- Distributed real FFTs land in
oxifft-adapter-mpi—MpiRealPlan2D/MpiRealPlan3Dscale r2c/c2r across MPI ranks in the FFTW half-complex layout, joining the crate’s existing distributed complex transforms. - Auto-tuning is real now —
Flags::MEASURE/PATIENT/EXHAUSTIVEactually benchmark competing candidate algorithms (radix-4/8, split-radix, Stockham, cache-oblivious, Rader, mixed-radix, …) and cache the winner via the wisdom system, instead of just timing whatever the heuristic had already picked. Flags::WISDOM_ONLYarrives, matching FFTW’sFFTW_WISDOM_ONLY— plan construction fails cleanly (None) when no matching wisdom exists, instead of silently falling back to a fresh plan.- The MSRV claim is now actually true — corrected from an aspirational
1.75to an empirically-verified1.87, checked against six rustup toolchains. - A breaking cleanup: dead planner code removed,
auto_tune::tune_sizegained a requiredflags: Flagsparameter, and the wisdom binary format moved to v2 to stop silently truncating longMixedRadixfactor lists.
Technical Deep Dive
Distributed real transforms
MpiRealPlan2D and MpiRealPlan3D bring slab-decomposed r2c/c2r to oxifft-adapter-mpi, in the same half-complex layout FFTW-MPI uses: a real last dimension of size n is stored as n/2 + 1 complex coefficients, with odd last dimensions supported. c2r is normalized by 1 / product(dims) — deliberately unlike FFTW, which leaves c2r unnormalized — so an r2c → c2r round trip is the identity without any manual scaling. r2c honors MpiFlags::transposed_out, and new local_size_2d_r2c / local_size_3d_r2c helpers size your buffers correctly for the half-complex layout, mirroring fftw_mpi_local_size_*. Alongside this, MpiPlanND::distributed_fft_dim0 moved from one blocking all_gather_v per fiber to a single alltoallv-based transpose — two collectives total regardless of fiber count — validated under mpirun -n 1/2/3/4.
Wisdom-driven auto-tuning
Plan::dft_1d is now flag-aware and wisdom-cached. ESTIMATE keeps the pure heuristic, but MEASURE/PATIENT/EXHAUSTIVE now consult the runtime wisdom cache first, and on a miss, actually benchmark real candidate algorithms and cache the winner — so repeated MEASURE planning of the same size no longer re-benchmarks on every call. algorithm_from_solver_name was extended to reconstruct all stateful solvers, so imported or measured wisdom genuinely feeds back into plan selection rather than being recorded and ignored. Two new algorithms — Algorithm::Rader and Algorithm::CacheOblivious — are part of that candidate set, and Rader is now selected automatically by the ESTIMATE heuristic for prime sizes in 17..=1021.
Breaking cleanup and MSRV correction
oxifft::kernel::{Solver, ProblemHash, hash_problem} — dead code with zero implementors — is gone; kernel::planner::Planner / kernel::wisdom::WisdomEntry are the real, wired-in model. The wisdom binary format moved to v2 (BINARY_FORMAT_VERSION = 2): the v1 layout used a fixed 30-byte entry and a u16-bounded factor count, which could silently truncate MixedRadix solver names with many factors; v2 uses variable-length factor lists with an explicit u32 count, and from_binary still reads old v1 files. Separately, the workspace rust-version was corrected from 1.75 to 1.87 — hashbrown 0.17 alone requires edition2024/1.85 at dependency-resolution time, and oxifft’s own ntt/nufft modules use u32::is_multiple_of, stabilized in 1.87. This was verified empirically across rustup 1.75.0 through 1.88.0, not asserted.
Getting Started
cargo add oxifft
A minimal forward FFT — unchanged from prior releases:
use oxifft::{Complex, Direction, Flags, Plan};
let plan = Plan::dft_1d(1024, Direction::Forward, Flags::MEASURE)
.expect("1024-pt plan");
let input = vec![Complex::new(1.0_f64, 0.0); 1024];
let mut output = vec![Complex::new(0.0_f64, 0.0); 1024];
plan.execute(&input, &mut output);
A distributed real forward transform, new in 0.4.0 (oxifft-adapter-mpi, requires a system MPI implementation):
use oxifft::kernel::Complex;
use oxifft_adapter_mpi::{local_size_2d_r2c, MpiFlags, MpiPool, MpiRealPlan2D};
let universe = mpi::initialize().expect("MPI_Init failed");
let pool = MpiPool::new(universe.world());
let (n0, n1) = (64, 32);
let (local_n0, local_0_start, real_alloc, complex_alloc) =
local_size_2d_r2c(n0, n1, &pool);
let mut r2c = MpiRealPlan2D::<f64, _>::r2c(n0, n1, MpiFlags::estimate(), &pool)
.expect("failed to create distributed r2c plan");
// Fill this rank's local_n0 rows of n1 real samples, starting at global
// row local_0_start, then:
let input = vec![0.0f64; real_alloc];
let mut spectrum = vec![Complex::new(0.0, 0.0); complex_alloc];
r2c.execute_r2c(&input, &mut spectrum)
.expect("distributed r2c failed");
What’s New in 0.4.0
- Added: Distributed real transforms (
MpiRealPlan2D,MpiRealPlan3D) inoxifft-adapter-mpi, pluslocal_size_2d_r2c/local_size_3d_r2callocation helpers. - Changed:
Plan::dft_1dis flag-aware and wisdom-cached;Algorithm::Rader/Algorithm::CacheObliviousadded and wired into wisdom reconstruction;MpiPlanND::distributed_fft_dim0now uses a singlealltoallvtranspose instead of per-fiberall_gather_v. - Breaking: dead
kernel::{Solver, ProblemHash, hash_problem}removed;auto_tune::tune_sizerequires aflags: Flagsargument;Flags::WISDOM_ONLYadded; wisdom binary format bumped to v2; workspacerust-versioncorrected to1.87. - Dependencies:
oxicuda-driver/oxicuda-fft/oxicuda-metal(optional GPU backends) bumped0.1.8→0.5.1. - Fixed / Hygiene: workspace-root
deny.tomladded enforcing the COOLJAPAN banned-crate policy; deadseahash/libcdependencies removed;docs.rsmetadata and a realREADME.mdadded foroxifft-adapter-mpi; every publishable crate now ships its ownLICENSE;no_stdSIMD compilation fixed across generated and hand-written AVX-512 paths; a release-mode-only test tolerance bug in the twiddle-table SoA/AoS parity tests fixed (no production code affected). 1,730 tests passing workspace-wide;cargo deny checkclean.
Tips
- Passed flags to
tune_sizebefore?auto_tune::tune_sizenow requires aflags: Flagsargument — passFlags::MEASUREto get the same widened candidate search you had implicitly before. - Re-measure your wisdom.
MEASURE/PATIENT/EXHAUSTIVEnow genuinely compare Rader/Stockham/cache-oblivious/mixed-radix candidates against each other, so wisdom cached under 0.3.x may no longer reflect the fastest plan.from_binarystill reads old v1 files — but re-measuring is worth it. - Reach for
Flags::WISDOM_ONLYwhen a build must never silently fall back to a slow first-touch plan: precompute wisdom offline (OXIFFT_TUNE=1), ship it, then load in production withWISDOM_ONLYset so a missing entry fails loudly instead of re-benchmarking at runtime. - Size distributed real buffers with the new helpers —
local_size_2d_r2c/local_size_3d_r2ccompute the half-complex allocation for you; don’t hand-rolln1/2 + 1. - Rader now kicks in automatically for prime transform sizes
17..=1021under the defaultESTIMATEheuristic — no flag change needed to benefit. - Pin CI to rust-version 1.87. The workspace declaration now matches what the crate actually requires; anything older fails at dependency resolution because of
hashbrown0.17 alone.
The foundation
OxiFFT is the spectral layer of the COOLJAPAN ecosystem. As of this release it’s a direct dependency of 21 other COOLJAPAN projects — including SciRS2, NumRS2, OxiBLAS, OxiCUDA (its GPU backend), ToRSh, OxiWhisper, SkleaRS, TenfloweRS, OxiMedia, and OxiPhysics — every transform staying Pure Rust from a single laptop to an MPI cluster. The new distributed real transforms extend that reach directly into MPI-scale signal and image pipelines that were previously complex-only.
Repository: https://github.com/cool-japan/oxifft
Star the repo if Pure Rust spectral computing belongs in your stack — and tell us how the new distributed real transforms perform on your cluster.
Pure Rust spectral computing — fast, safe, and sovereign, from a laptop to an MPI cluster.
— KitaSan at COOLJAPAN OÜ July 27, 2026