scirs2_fft/sparse_fft/config.rs
1//! Configuration types and utilities for Sparse FFT algorithms
2//!
3//! This module contains the configuration structures, enums, and utility functions
4//! used to configure and control sparse FFT computations.
5
6use scirs2_core::numeric::Complex64;
7use std::fmt::Debug;
8
9/// Helper function to extract complex values from various types (for doctests)
10#[allow(dead_code)]
11pub fn try_as_complex<T: 'static + Copy>(val: T) -> Option<Complex64> {
12 use std::any::Any;
13
14 // Try to use runtime type checking with Any for complex types
15 if let Some(complex) = (&val as &dyn Any).downcast_ref::<Complex64>() {
16 return Some(*complex);
17 }
18
19 // Try to handle f32 complex numbers
20 if let Some(complex32) = (&val as &dyn Any).downcast_ref::<scirs2_core::numeric::Complex<f32>>()
21 {
22 return Some(Complex64::new(complex32.re as f64, complex32.im as f64));
23 }
24
25 None
26}
27
28/// Sparsity estimation method
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum SparsityEstimationMethod {
31 /// Manual estimation (user provides the sparsity)
32 Manual,
33 /// Automatic estimation based on thresholding
34 Threshold,
35 /// Adaptive estimation based on signal properties
36 Adaptive,
37 /// Frequency domain pruning for high accuracy estimation
38 FrequencyPruning,
39 /// Spectral flatness measure for noise vs signal discrimination
40 SpectralFlatness,
41}
42
43/// Sparse FFT algorithm variant
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub enum SparseFFTAlgorithm {
46 /// Sublinear Sparse FFT
47 Sublinear,
48 /// Compressed Sensing-based Sparse FFT
49 CompressedSensing,
50 /// Iterative Method for Sparse FFT
51 Iterative,
52 /// Deterministic Sparse FFT
53 Deterministic,
54 /// Frequency-domain pruning approach
55 FrequencyPruning,
56 /// Advanced pruning using spectral flatness measure
57 SpectralFlatness,
58}
59
60/// Window function to apply before FFT
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub enum WindowFunction {
63 /// No windowing (rectangular window)
64 None,
65 /// Hann window (reduces spectral leakage)
66 Hann,
67 /// Hamming window (good for speech)
68 Hamming,
69 /// Blackman window (excellent sidelobe suppression)
70 Blackman,
71 /// Flat top window (best amplitude accuracy)
72 FlatTop,
73 /// Kaiser window with adjustable parameter
74 Kaiser,
75}
76
77/// Sparse FFT configuration
78#[derive(Debug, Clone)]
79pub struct SparseFFTConfig {
80 /// The sparsity estimation method
81 pub estimation_method: SparsityEstimationMethod,
82 /// Expected sparsity (k) - number of significant frequency components
83 pub sparsity: usize,
84 /// Algorithm variant to use
85 pub algorithm: SparseFFTAlgorithm,
86 /// Threshold for frequency coefficient significance (when using threshold method)
87 pub threshold: f64,
88 /// Number of iterations for iterative methods
89 pub iterations: usize,
90 /// Random seed for probabilistic algorithms
91 pub seed: Option<u64>,
92 /// Maximum signal size to process (to prevent test timeouts)
93 pub max_signal_size: usize,
94 /// Adaptivity parameter (controls how aggressive adaptivity is)
95 pub adaptivity_factor: f64,
96 /// Pruning parameter (controls sensitivity of frequency pruning)
97 pub pruning_sensitivity: f64,
98 /// Spectral flatness threshold (0-1, lower values = more selective)
99 pub flatness_threshold: f64,
100 /// Analysis window size for spectral flatness calculations
101 pub window_size: usize,
102 /// Window function to apply before FFT
103 pub window_function: WindowFunction,
104 /// Kaiser window beta parameter (when using Kaiser window)
105 pub kaiser_beta: f64,
106}
107
108impl Default for SparseFFTConfig {
109 fn default() -> Self {
110 Self {
111 estimation_method: SparsityEstimationMethod::Threshold,
112 sparsity: 10,
113 algorithm: SparseFFTAlgorithm::Sublinear,
114 threshold: 0.01,
115 iterations: 3,
116 seed: None,
117 max_signal_size: 1024, // Default max size to avoid test timeouts
118 adaptivity_factor: 0.25,
119 pruning_sensitivity: 0.05,
120 flatness_threshold: 0.3,
121 window_size: 16,
122 window_function: WindowFunction::None,
123 kaiser_beta: 14.0, // Default beta for Kaiser window
124 }
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn test_default_config() {
134 let config = SparseFFTConfig::default();
135 assert_eq!(config.sparsity, 10);
136 assert_eq!(config.threshold, 0.01);
137 assert_eq!(config.max_signal_size, 1024);
138 }
139
140 #[test]
141 fn test_try_as_complex() {
142 let val = Complex64::new(1.0, 2.0);
143 assert_eq!(try_as_complex(val), Some(val));
144
145 let val32 = scirs2_core::numeric::Complex::new(1.0f32, 2.0f32);
146 assert_eq!(try_as_complex(val32), Some(Complex64::new(1.0, 2.0)));
147 }
148}