Function cwt_fft
pub fn cwt_fft<T>(
signal: &Signal<T>,
wavelet: &dyn ContinuousWavelet,
scales: &[f64],
sampling_freq: f64,
) -> Result<CWTResult<T>>where
T: Float + FromPrimitive + Send + Sync + SignalType + AddAssign + SubAssign + MulAssign + DivAssign + RemAssign,Expand description
High-performance CWT using FFT-based convolution with parallel processing
This implementation uses:
- Parallel scale processing via Rayon for multi-core utilization
- FFT-based convolution reducing complexity from O(N²) to O(N log N) per scale
- Thread-local FFT planner caching for efficient plan reuse
- SIMD-accelerated frequency-domain multiplication (AVX2 when available)
§Complexity
O(M × N log N / P) where N is signal length, M is number of scales, P is thread count.
§Example
use ferro_wave::transform::{cwt_fft, Morlet};
use ferro_wave::Signal;
let signal = Signal::new(vec![1.0, 2.0, 3.0, 2.0, 1.0, 0.0, -1.0, 0.0]);
let wavelet = Morlet::with_default_omega();
let scales: Vec<f64> = (1..=16).map(|i| i as f64).collect();
let result = cwt_fft(&signal, &wavelet, &scales, 100.0).unwrap();§Valid scale range
For meaningful coefficients keep scale ∈ [~ω₀/π, N/16] — roughly [2, N/16]
for the default Morlet (ω₀ = 6). This path uses the wavelet’s exact analytic
Fourier transform, so it stays accurate at small scales where the direct
cwt (which time-samples the wavelet) under-resolves oscillations near the
Nyquist limit (ω₀/scale ≳ π) — prefer cwt_fft there. At large scales
(scale ≳ N/8) the wavelet support approaches the signal length and this path’s
circular-convolution boundary handling dominates (the direct path truncates
instead); coefficients there are off-band and tiny — boundary artefacts.
Within the valid band cwt_fft and cwt agree to ~1e-9 (mid-band to machine
precision); the divergence outside it is the methods’ accuracy envelope, not a
normalisation difference. See tests/cwt_fft_accumulation.rs.