Skip to main content

oxifft/
lib.rs

1//! # OxiFFT
2//!
3//! Pure Rust implementation of FFTW - the Fastest Fourier Transform in the West.
4//!
5//! OxiFFT provides high-performance FFT routines with:
6//! - Complex DFT (forward and inverse)
7//! - Real FFT (R2C/C2R)
8//! - DCT/DST transforms
9//! - Multi-dimensional transforms
10//! - Batch processing
11//! - SIMD optimization
12//! - Threading support
13//! - Wisdom system for plan caching
14//!
15//! ## Quick Start
16//!
17//! ```ignore
18//! use oxifft::{Complex, Direction, Flags, Plan};
19//!
20//! // Create a plan for 256-point forward FFT
21//! let plan = Plan::dft_1d(256, Direction::Forward, Flags::MEASURE)?;
22//!
23//! // Execute the transform
24//! let mut input = vec![Complex::new(1.0, 0.0); 256];
25//! let mut output = vec![Complex::zero(); 256];
26//! plan.execute(&mut input, &mut output);
27//! ```
28
29// Allow pedantic/nursery warnings that are intentional in FFT code:
30#![allow(clippy::similar_names)] // fwd/bwd, real/imag pairs are intentionally similar
31#![allow(clippy::many_single_char_names)] // FFT math uses i, j, k, n, m by convention
32#![allow(clippy::cast_precision_loss)] // FFT size computations use float for math
33#![allow(clippy::cast_sign_loss)] // stride/offset calculations need signed/unsigned
34#![allow(clippy::cast_possible_wrap)] // stride calculations need careful wrapping
35#![allow(clippy::missing_panics_doc)] // many internal functions assert preconditions
36#![allow(clippy::must_use_candidate)] // internal helpers don't need must_use
37#![allow(clippy::doc_markdown)] // allow flexibility in documentation formatting
38#![allow(clippy::incompatible_msrv)] // allow using newer features when available
39#![allow(clippy::needless_range_loop)] // explicit loops are clearer for FFT indices
40#![allow(clippy::wildcard_imports)] // use super::* in submodules is fine
41#![allow(clippy::too_many_arguments)] // FFT plans legitimately need many params
42#![allow(clippy::assign_op_pattern)] // a = a op b in codelet math avoids confusion
43#![allow(clippy::ptr_as_ptr)] // casting raw pointers in FFT is pervasive
44#![allow(clippy::suboptimal_flops)] // manual FMA control may be intentional
45#![allow(clippy::imprecise_flops)] // sqrt of squares may be intentional
46#![allow(clippy::not_unsafe_ptr_arg_deref)] // FFT internal ops are safe
47#![allow(clippy::unnecessary_wraps)] // wrapping for API consistency
48#![allow(clippy::too_many_lines)] // FFT functions can be long
49#![allow(clippy::suspicious_arithmetic_impl)] // complex arithmetic is intentional
50#![allow(clippy::only_used_in_recursion)] // recursive FFT is intentional
51#![allow(clippy::float_cmp)] // intentional float comparison in tests
52#![allow(clippy::cast_possible_truncation)] // deliberate truncation
53#![allow(clippy::ptr_cast_constness)] // pointer const casting common in FFT
54#![allow(clippy::significant_drop_tightening)] // locking patterns are intentional
55#![allow(clippy::missing_errors_doc)] // FFT error handling is self-explanatory
56#![allow(clippy::type_complexity)] // complex return types are needed for FFT APIs
57#![allow(clippy::duplicate_mod)] // conditional compilation requires this
58#![allow(clippy::suspicious_operation_groupings)] // FFT math has specific operator groupings
59#![allow(clippy::missing_const_for_fn)] // many fns could be const but don't need to be
60#![allow(clippy::return_self_not_must_use)] // builder patterns don't need must_use everywhere
61#![allow(clippy::use_self)] // explicit type names preferred for clarity in FFT code
62#![allow(clippy::option_if_let_else)] // if-let-else is clearer than map_or in some cases
63#![allow(clippy::redundant_else)] // explicit else improves readability
64#![allow(clippy::if_not_else)] // negated conditions are sometimes clearer
65#![allow(clippy::unnested_or_patterns)] // flat patterns are easier to read
66#![allow(clippy::unreadable_literal)] // FFT constants appear as hex/long literals
67#![allow(clippy::unused_self)] // some trait methods require &self but don't use it
68#![allow(clippy::redundant_closure_for_method_calls)] // explicit closures can be clearer
69#![allow(clippy::unnecessary_cast)] // casts explicit for type documentation
70#![allow(clippy::inline_always)] // FFT codelets need inline(always) for performance
71#![allow(clippy::approx_constant)] // FFT constants may approximate std consts intentionally
72#![allow(clippy::manual_let_else)] // let-else not always clearer in FFT context
73#![allow(clippy::iter_without_into_iter)] // not all iterators need IntoIterator
74#![allow(clippy::implicit_clone)] // cloning via deref is idiomatic
75#![allow(clippy::cast_lossless)] // explicit casting preferred for documentation
76#![allow(clippy::trivially_copy_pass_by_ref)] // API consistency for small types
77#![allow(clippy::map_unwrap_or)] // map().unwrap_or() is clearer sometimes
78#![allow(clippy::explicit_iter_loop)] // explicit .iter() is clear
79#![allow(clippy::derive_partial_eq_without_eq)] // not all PartialEq types need Eq
80#![allow(clippy::single_match_else)] // single match + else is sometimes clearer
81#![allow(clippy::match_same_arms)] // identical arms for documentation/future changes
82#![allow(clippy::items_after_statements)] // local items near usage is fine
83#![allow(clippy::manual_assert)] // manual if + panic is sometimes clearer
84#![allow(clippy::std_instead_of_core)] // std re-exports are fine
85#![allow(clippy::separated_literal_suffix)] // literal suffixes may be detached
86#![allow(clippy::used_underscore_binding)] // underscore bindings used intentionally
87#![allow(clippy::manual_div_ceil)] // manual div_ceil for clarity
88#![allow(clippy::if_then_some_else_none)] // explicit if/else preferred sometimes
89#![allow(clippy::struct_field_names)] // field names may match struct name
90#![allow(clippy::default_trait_access)] // Default::default() is fine
91#![allow(clippy::expl_impl_clone_on_copy)] // explicit Clone for Copy types is intentional
92#![allow(clippy::format_push_string)] // format! appended to String is fine
93#![allow(clippy::needless_pass_by_value)] // pass by value for API ergonomics
94#![allow(clippy::copy_iterator)] // iterators may impl Copy
95#![allow(clippy::manual_clamp)] // manual clamp for clarity
96#![allow(clippy::manual_is_variant_and)] // explicit matching is fine
97#![allow(clippy::unseparated_literal_suffix)] // literal suffixes style choice
98#![allow(clippy::checked_conversions)] // explicit conversion checks preferred
99#![allow(clippy::semicolon_if_nothing_returned)] // statement style
100#![allow(clippy::ref_as_ptr)] // ref as pointer for low-level FFT
101#![allow(clippy::ptr_eq)] // raw pointer comparison
102#![cfg_attr(not(feature = "std"), no_std)]
103#![cfg_attr(feature = "portable_simd", feature(portable_simd))]
104
105#[cfg(not(feature = "std"))]
106extern crate alloc;
107
108// Internal prelude for no_std compatibility
109pub(crate) mod prelude;
110
111pub mod api;
112#[cfg(feature = "fftw-compat")]
113pub mod compat;
114#[cfg(feature = "const-fft")]
115pub mod const_fft;
116pub mod dft;
117#[cfg(any(feature = "gpu", feature = "cuda", feature = "metal"))]
118pub mod gpu;
119pub mod kernel;
120#[cfg(feature = "mpi")]
121pub mod mpi;
122#[cfg(feature = "pruned")]
123pub mod pruned;
124pub mod rdft;
125pub mod reodft;
126#[cfg(feature = "signal")]
127pub mod signal;
128pub mod simd;
129#[cfg(feature = "sparse")]
130pub mod sparse;
131#[cfg(feature = "streaming")]
132pub mod streaming;
133pub mod support;
134pub mod threading;
135#[cfg(feature = "wasm")]
136pub mod wasm;
137
138// Advanced FFT transforms
139pub mod autodiff;
140pub mod conv;
141#[cfg(feature = "std")]
142pub mod frft;
143#[cfg(feature = "std")]
144pub mod nufft;
145
146// Re-export commonly used types
147pub use api::{
148    fft, fft2d, fft2d_split, fft3d_split, fft_batch, fft_nd, fft_nd_split, fft_split, ifft, ifft2d,
149    ifft2d_split, ifft3d_split, ifft_batch, ifft_nd, ifft_nd_split, ifft_split, irfft, irfft2d,
150    irfft3d, irfft_batch, irfft_nd, rfft, rfft2d, rfft3d, rfft_batch, rfft_nd, Direction, Flags,
151    GuruPlan, Plan, Plan2D, Plan3D, PlanND, R2rKind, R2rPlan, RealPlan, RealPlan2D, RealPlan3D,
152    RealPlanKind, RealPlanND, SplitPlan, SplitPlan2D, SplitPlan3D, SplitPlanND,
153};
154pub use kernel::{Complex, Float, IoDim, Tensor};
155
156// Re-export F128 when f128-support feature is enabled
157#[cfg(feature = "f128-support")]
158pub use kernel::F128;
159
160// Re-export F16 when f16-support feature is enabled
161#[cfg(feature = "f16-support")]
162pub use kernel::F16;
163
164// Re-export sparse FFT when sparse feature is enabled
165#[cfg(feature = "sparse")]
166pub use sparse::{sparse_fft, sparse_ifft, SparsePlan, SparseResult};
167
168// Re-export pruned FFT when pruned feature is enabled
169#[cfg(feature = "pruned")]
170pub use pruned::{
171    fft_pruned_input, fft_pruned_output, goertzel, goertzel_multi, PrunedPlan, PruningMode,
172};
173
174// Re-export WASM bindings when wasm feature is enabled
175#[cfg(feature = "wasm")]
176pub use wasm::{fft_f32, fft_f64, ifft_f32, ifft_f64, rfft_f64, WasmFft, WasmSimdF32, WasmSimdF64};
177
178// Re-export streaming FFT when streaming feature is enabled
179#[cfg(feature = "streaming")]
180pub use streaming::{
181    blackman, build_mel_filterbank, cola_normalization, hamming, hann, istft, istft_overlap_save,
182    kaiser, magnitude_spectrogram, mel_spectrogram, mfcc, phase_spectrogram, power_spectrogram,
183    rectangular, stft, stft_overlap_save, MelConfig, RingBuffer, StreamingFft, WindowFunction,
184};
185
186// Re-export compile-time FFT when const-fft feature is enabled
187#[cfg(feature = "const-fft")]
188pub use const_fft::{
189    const_cos, const_sin, fft_fixed, fft_fixed_inplace, ifft_fixed, ifft_fixed_inplace,
190    twiddle_factor, ConstFft, ConstFftImpl,
191};
192
193// Re-export GPU FFT when gpu/cuda/metal feature is enabled
194#[cfg(any(feature = "gpu", feature = "cuda", feature = "metal"))]
195pub use gpu::{
196    best_backend, is_gpu_available, query_capabilities, GpuBackend, GpuBuffer, GpuCapabilities,
197    GpuDirection, GpuError, GpuFft, GpuFftEngine, GpuPlan, GpuResult,
198};
199
200// Re-export low-level DFT functions for advanced users
201pub use dft::solvers::{
202    ct::{
203        fft_radix2, fft_radix2_inplace, ifft_radix2, ifft_radix2_inplace, ifft_radix2_normalized,
204    },
205    direct::{dft_direct, idft_direct, idft_direct_normalized},
206    nop::dft_nop,
207};
208
209// Re-export DCT/DST/DHT convenience functions
210pub use rdft::solvers::{dct1, dct2, dct3, dct4, dht, dst1, dst2, dst3, dst4};
211
212// Re-export memory allocation utilities
213pub use api::{
214    alloc_complex, alloc_complex_aligned, alloc_real, alloc_real_aligned, is_aligned,
215    AlignedBuffer, DEFAULT_ALIGNMENT,
216};
217
218// Re-export NUFFT (Non-uniform FFT)
219#[cfg(feature = "std")]
220pub use nufft::{
221    nufft2d_type1, nufft2d_type2, nufft3d_type1, nufft_type1, nufft_type2, nufft_type3, Nufft,
222    NufftError, NufftOptions, NufftResult, NufftType,
223};
224
225// Re-export FrFT (Fractional Fourier Transform)
226#[cfg(feature = "std")]
227pub use frft::{frft, frft_checked, ifrft, ifrft_checked, Frft, FrftError, FrftResult};
228
229// Re-export Convolution functions
230pub use conv::{
231    convolve, convolve_circular, convolve_complex, convolve_complex_mode, convolve_mode,
232    convolve_with_mode, correlate, correlate_complex, correlate_complex_mode, correlate_mode,
233    polynomial_multiply, polynomial_multiply_complex, polynomial_power, ConvMode,
234};
235
236// Re-export Automatic Differentiation
237pub use autodiff::{
238    fft_dual, fft_jacobian, grad_fft, grad_ifft, jvp_fft, vjp_fft, DiffFftPlan, Dual, DualComplex,
239};
240
241// Re-export signal processing when signal feature is enabled
242#[cfg(feature = "signal")]
243pub use signal::{
244    coherence, complex_cepstrum, cross_spectral_density, envelope, hilbert,
245    instantaneous_frequency, instantaneous_phase, minimum_phase, periodogram, real_cepstrum,
246    resample, resample_to, welch, SpectralWindow, WelchConfig,
247};