cwt_fft

Function cwt_fft 

pub fn cwt_fft<T>(
    signal: &Signal<T>,
    wavelet: &dyn ContinuousWavelet,
    scales: &[f64],
    sampling_freq: f64,
) -> Result<CWTResult<T>>
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.