Function bodies 301 total
test_rrc_filter_frequency_response function · rust · L393-L454 (62 LOC)src/generate/psk_carrier.rs
fn test_rrc_filter_frequency_response() {
use std::env;
use crate::fft::{fft, fftshift, fftfreqs};
use crate::vector_ops;
let sample_rate_hz = 1e6_f64;
let symbol_rate_hz = 800e3_f64;
let filter_taps = 51;
let rolloff_factor = 0.05_f64;
// Build the RRC filter
let rrc = RRCFilter::new(
filter_taps,
sample_rate_hz,
symbol_rate_hz,
rolloff_factor,
);
let filter = rrc.build_filter::<f64>();
println!("\n=== RRC Filter Analysis ===");
println!("Filter taps: {}", filter.len());
println!("Sample rate: {} Hz", sample_rate_hz);
println!("Symbol rate: {} Hz", symbol_rate_hz);
println!("Samples per symbol (SPS): {}", sample_rate_hz / symbol_rate_hz);
println!("Rolloff: {}", rolloff_factor);
// Print all taps to see the shape
println!("\nAll filter taps:");
for i in 0..filter.len() {
new_from_seed function · rust · L14-L20 (7 LOC)src/generate/random_bit_generator.rs
pub fn new_from_seed(seed: u64) -> Self {
Self {
rng: StdRng::seed_from_u64(seed),
buffer: 0,
bits_remaining: 0,
}
}new_from_entropy function · rust · L21-L28 (8 LOC)src/generate/random_bit_generator.rs
pub fn new_from_entropy() -> Self {
Self {
rng: StdRng::from_entropy(),
buffer: 0,
bits_remaining: 0,
}
}next_bits function · rust · L31-L53 (23 LOC)src/generate/random_bit_generator.rs
pub fn next_bits(&mut self, num_bits: u8) -> u64 {
assert!(num_bits > 0 && num_bits <= 64, "num_bits must be 1-64");
// Refill buffer if we don't have enough bits
if self.bits_remaining < num_bits {
self.buffer = self.rng.next_u64();
self.bits_remaining = 64;
}
// Extract the requested bits from the low end
let mask = if num_bits == 64 {
u64::MAX
} else {
(1u64 << num_bits) - 1
};
let result = self.buffer & mask;
// Shift buffer and update remaining count
self.buffer >>= num_bits;
self.bits_remaining -= num_bits;
return result;
}get_mod_type_from_enum function · rust · L40-L52 (13 LOC)src/mod_type.rs
pub fn get_mod_type_from_enum<T: Float>(mod_enum: ModType) -> Modulation<T> {
match mod_enum {
ModType::_BPSK => Modulation::BPSK(_BPSK::new(bpsk_map())),
ModType::_QPSK => Modulation::QPSK(_QPSK::new(qpsk_gray_map())),
ModType::_8PSK => Modulation::PSK8(_8PSK::new(psk8_gray_map())),
ModType::_16APSK => Modulation::APSK16(_16APSK::new(apsk16_gray_map())),
ModType::_16QAM => Modulation::QAM16(_16QAM::new(qam16_gray_map())),
ModType::_32QAM => Modulation::QAM32(_32QAM::new(qam32_gray_map())),
ModType::_64QAM => Modulation::QAM64(_64QAM::new(qam64_gray_map())),
ModType::_CW => unreachable!("CW is handled separately by Carrier, not through modulation system"),
}
}new function · rust · L65-L73 (9 LOC)src/mod_type.rs
pub fn new(bit_symbol_map: HashMap<u8, Complex<T>>) -> Self {
_BPSK {
mod_properties: ModProperties {
bits_per_symbol: 1,
num_symbols: 2,
bit_symbol_map
}
}
}demodulate function · rust · L80-L90 (11 LOC)src/mod_type.rs
fn demodulate(&self, symbol: &Complex<T>) -> Option<u8> {
self.mod_properties.bit_symbol_map
.iter()
.min_by(|(_, s1), (_, s2)| {
let d1 = (*s1 - *symbol).norm_sqr();
let d2 = (*s2 - *symbol).norm_sqr();
d1.partial_cmp(&d2).unwrap()
})
.map(|(bits, _)| *bits)
}All rows scored by the Repobility analyzer (https://repobility.com)
new function · rust · L98-L106 (9 LOC)src/mod_type.rs
pub fn new(bit_symbol_map: HashMap<u8, Complex<T>>) -> Self {
_QPSK {
mod_properties: ModProperties {
bits_per_symbol: 2,
num_symbols: 4,
bit_symbol_map,
}
}
}demodulate function · rust · L113-L123 (11 LOC)src/mod_type.rs
fn demodulate(&self, symbol: &Complex<T>) -> Option<u8> {
self.mod_properties.bit_symbol_map
.iter()
.min_by(|(_, s1), (_, s2)| {
let d1 = (*s1 - *symbol).norm_sqr();
let d2 = (*s2 - *symbol).norm_sqr();
d1.partial_cmp(&d2).unwrap()
})
.map(|(bits, _)| *bits)
}new function · rust · L131-L139 (9 LOC)src/mod_type.rs
pub fn new(bit_symbol_map: HashMap<u8, Complex<T>>) -> Self {
_8PSK {
mod_properties: ModProperties {
bits_per_symbol: 3,
num_symbols: 8,
bit_symbol_map,
}
}
}demodulate function · rust · L146-L156 (11 LOC)src/mod_type.rs
fn demodulate(&self, symbol: &Complex<T>) -> Option<u8> {
self.mod_properties.bit_symbol_map
.iter()
.min_by(|(_, s1), (_, s2)| {
let d1 = (*s1 - *symbol).norm_sqr();
let d2 = (*s2 - *symbol).norm_sqr();
d1.partial_cmp(&d2).unwrap()
})
.map(|(bits, _)| *bits)
}new function · rust · L164-L172 (9 LOC)src/mod_type.rs
pub fn new(bit_symbol_map: HashMap<u8, Complex<T>>) -> Self {
_16APSK {
mod_properties: ModProperties {
bits_per_symbol: 4,
num_symbols: 16,
bit_symbol_map,
}
}
}demodulate function · rust · L179-L189 (11 LOC)src/mod_type.rs
fn demodulate(&self, symbol: &Complex<T>) -> Option<u8> {
self.mod_properties.bit_symbol_map
.iter()
.min_by(|(_, s1), (_, s2)| {
let d1 = (*s1 - *symbol).norm_sqr();
let d2 = (*s2 - *symbol).norm_sqr();
d1.partial_cmp(&d2).unwrap()
})
.map(|(bits, _)| *bits)
}new function · rust · L197-L205 (9 LOC)src/mod_type.rs
pub fn new(bit_symbol_map: HashMap<u8, Complex<T>>) -> Self {
_16QAM {
mod_properties: ModProperties {
bits_per_symbol: 4,
num_symbols: 16,
bit_symbol_map,
}
}
}demodulate function · rust · L212-L222 (11 LOC)src/mod_type.rs
fn demodulate(&self, symbol: &Complex<T>) -> Option<u8> {
self.mod_properties.bit_symbol_map
.iter()
.min_by(|(_, s1), (_, s2)| {
let d1 = (*s1 - *symbol).norm_sqr();
let d2 = (*s2 - *symbol).norm_sqr();
d1.partial_cmp(&d2).unwrap()
})
.map(|(bits, _)| *bits)
}Repobility analyzer · published findings · https://repobility.com
new function · rust · L230-L238 (9 LOC)src/mod_type.rs
pub fn new(bit_symbol_map: HashMap<u8, Complex<T>>) -> Self {
_32QAM {
mod_properties: ModProperties {
bits_per_symbol: 5,
num_symbols: 32,
bit_symbol_map,
}
}
}demodulate function · rust · L245-L255 (11 LOC)src/mod_type.rs
fn demodulate(&self, symbol: &Complex<T>) -> Option<u8> {
self.mod_properties.bit_symbol_map
.iter()
.min_by(|(_, s1), (_, s2)| {
let d1 = (*s1 - *symbol).norm_sqr();
let d2 = (*s2 - *symbol).norm_sqr();
d1.partial_cmp(&d2).unwrap()
})
.map(|(bits, _)| *bits)
}new function · rust · L263-L271 (9 LOC)src/mod_type.rs
pub fn new(bit_symbol_map: HashMap<u8, Complex<T>>) -> Self {
_64QAM {
mod_properties: ModProperties {
bits_per_symbol: 6,
num_symbols: 64,
bit_symbol_map,
}
}
}demodulate function · rust · L278-L288 (11 LOC)src/mod_type.rs
fn demodulate(&self, symbol: &Complex<T>) -> Option<u8> {
self.mod_properties.bit_symbol_map
.iter()
.min_by(|(_, s1), (_, s2)| {
let d1 = (*s1 - *symbol).norm_sqr();
let d2 = (*s2 - *symbol).norm_sqr();
d1.partial_cmp(&d2).unwrap()
})
.map(|(bits, _)| *bits)
}test_bpsk_modulate function · rust · L296-L306 (11 LOC)src/mod_type.rs
fn test_bpsk_modulate() {
let bpsk = _BPSK::<f64>::new(crate::symbol_maps::bpsk_map());
let symbol = bpsk.modulate(0b0).unwrap();
assert!(symbol.re > 0.0);
assert_eq!(symbol.im, 0.0);
let symbol = bpsk.modulate(0b1).unwrap();
assert!(symbol.re < 0.0);
assert_eq!(symbol.im, 0.0);
}test_bpsk_demodulate function · rust · L309-L319 (11 LOC)src/mod_type.rs
fn test_bpsk_demodulate() {
let bpsk = _BPSK::<f64>::new(crate::symbol_maps::bpsk_map());
let symbol = bpsk.modulate(0b0).unwrap();
let bits = bpsk.demodulate(&symbol).unwrap();
assert_eq!(bits, 0b0);
let symbol = bpsk.modulate(0b1).unwrap();
let bits = bpsk.demodulate(&symbol).unwrap();
assert_eq!(bits, 0b1);
}test_qpsk_modulate function · rust · L322-L330 (9 LOC)src/mod_type.rs
fn test_qpsk_modulate() {
let qpsk = _QPSK::<f64>::new(crate::symbol_maps::qpsk_gray_map());
let symbol = qpsk.modulate(0b00).unwrap();
assert!(symbol.re > 0.0 && symbol.im > 0.0);
let symbol = qpsk.modulate(0b11).unwrap();
assert!(symbol.re < 0.0 && symbol.im < 0.0);
}test_qpsk_demodulate function · rust · L333-L339 (7 LOC)src/mod_type.rs
fn test_qpsk_demodulate() {
let qpsk = _QPSK::<f64>::new(crate::symbol_maps::qpsk_gray_map());
let symbol = qpsk.modulate(0b01).unwrap();
let bits = qpsk.demodulate(&symbol).unwrap();
assert_eq!(bits, 0b01);
}All rows above produced by Repobility · https://repobility.com
test_psk8_modulate function · rust · L342-L347 (6 LOC)src/mod_type.rs
fn test_psk8_modulate() {
let psk8 = _8PSK::<f64>::new(crate::symbol_maps::psk8_gray_map());
let symbol = psk8.modulate(0b000).unwrap();
assert!(symbol.norm() > 0.99 && symbol.norm() < 1.01);
}test_qam16_modulate_demodulate function · rust · L350-L358 (9 LOC)src/mod_type.rs
fn test_qam16_modulate_demodulate() {
let qam16 = _16QAM::<f64>::new(crate::symbol_maps::qam16_gray_map());
for bits in 0..16u8 {
let symbol = qam16.modulate(bits).unwrap();
let decoded = qam16.demodulate(&symbol).unwrap();
assert_eq!(bits, decoded);
}
}test_get_mod_type_from_enum function · rust · L361-L371 (11 LOC)src/mod_type.rs
fn test_get_mod_type_from_enum() {
let modulation = get_mod_type_from_enum::<f64>(ModType::_QPSK);
match modulation {
Modulation::QPSK(qpsk) => {
let symbol = qpsk.modulate(0b00).unwrap();
assert!(symbol.norm() > 0.0);
},
_ => panic!("Expected QPSK variant"),
}
}plot_spectrum function · rust · L15-L32 (18 LOC)src/plot.rs
pub fn plot_spectrum<T: Float>(freqs: &Vec<T>, spectrum: &Vec<T>, title: &str) {
// Convert to f64 for plotting
let freqs_f64: Vec<f64> = freqs.iter().map(|f| f.to_f64().unwrap()).collect();
let spectrum_f64: Vec<f64> = spectrum.iter().map(|s| s.to_f64().unwrap()).collect();
let mut plot = Plot::new();
let trace = Scatter::new(freqs_f64, spectrum_f64);
plot.add_trace(trace);
let layout = Layout::new()
.title(title)
.x_axis(Axis::new().title("Frequency (Hz)"))
.y_axis(Axis::new().title("Magnitude (dB)"))
.auto_size(true);
plot.set_layout(layout);
plot.show();
}plot_constellation function · rust · L56-L103 (48 LOC)src/plot.rs
pub fn plot_constellation<T: Float + std::fmt::Display>(symbols: &[Complex<T>], title: &str) {
// Extract I and Q values
let mut i_vals = Vec::new();
let mut q_vals = Vec::new();
for symbol in symbols {
// Convert to f64 for plotting
i_vals.push(symbol.re.to_f64().unwrap());
q_vals.push(symbol.im.to_f64().unwrap());
}
// Create scatter plot for constellation points
let trace = Scatter::new(i_vals.clone(), q_vals.clone())
.mode(Mode::Markers)
.name("Constellation");
let mut plot = Plot::new();
plot.add_trace(trace);
// Add axis reference lines at 0
let x_axis_line = Scatter::new(vec![-1.5, 1.5], vec![0.0, 0.0])
.mode(Mode::Lines)
.name("I-axis")
.show_legend(false);
let y_axis_line = Scatter::new(vec![0.0, 0.0], vec![-1.5, 1.5])
.mode(Mode::Lines)
.name("Q-axis")
.show_legend(false);
plot.add_trace(x_axis_line);
plot.add_trace(y_axis_line);parse_modulation function · rust · L22-L41 (20 LOC)src/python_bindings.rs
fn parse_modulation(mod_str: &str) -> PyResult<ModType> {
match mod_str.to_uppercase().as_str() {
"BPSK" => Ok(ModType::_BPSK),
"QPSK" => Ok(ModType::_QPSK),
"8PSK" => Ok(ModType::_8PSK),
"16APSK" => Ok(ModType::_16APSK),
"16QAM" => Ok(ModType::_16QAM),
"32QAM" => Ok(ModType::_32QAM),
"64QAM" => Ok(ModType::_64QAM),
"CW" => Ok(ModType::_CW),
_ => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
format!(
"Unknown modulation type: '{}'. Supported types (case-insensitive):\n \
BPSK (Binary PSK), QPSK (Quadrature PSK), 8PSK, 16APSK, \n \
16QAM, 32QAM, 64QAM, CW (Continuous Wave)",
mod_str
),
)),
}
}parse_impairment function · rust · L56-L165 (110 LOC)src/python_bindings.rs
fn parse_impairment(config: &Bound<PyAny>) -> PyResult<Impairment> {
// Try as string first
if let Ok(s) = config.extract::<String>() {
return match s.to_lowercase().as_str() {
"digitizer_droop_ad9361" => Ok(Impairment::DigitizerDroopAD9361),
"digitizer_droop_traditional" => Ok(Impairment::DigitizerDroopTraditional),
"cosine_taper_digitizer" => Ok(Impairment::CosineTaperDigitizer),
_ => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
format!(
"Unknown impairment: '{}'. Supported strings: digitizer_droop_ad9361, digitizer_droop_traditional, cosine_taper_digitizer. Or use a dict with 'type' key.",
s
),
)),
};
}
// Try as dictionary
if let Ok(dict) = config.downcast::<PyDict>() {
let impairment_type: String = dict
.get_item("type")?
.ok_or_else(|| PyErr::new::<pyo3::exceptions::PyValueEnew function · rust · L201-L245 (45 LOC)src/python_bindings.rs
fn new(
modulation: &str,
bandwidth: f64,
center_freq: f64,
snr_db: f64,
rolloff: f64,
sample_rate_hz: f64,
seed: Option<u64>,
) -> PyResult<Self> {
let mod_type = parse_modulation(modulation)?;
// Validate parameters (same validation as Rust API)
if bandwidth <= 0.0 || bandwidth > 1.0 {
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
"bandwidth must be in range (0.0, 1.0]",
));
}
if center_freq < -0.5 || center_freq > 0.5 {
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
"center_freq must be in range [-0.5, 0.5]",
));
}
if rolloff < 0.0 || rolloff > 1.0 {
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
"rolloff must be in range [0.0, 1.0]",
));
}
if sample_rate_hz <= 0.0 {
return Err(PMethodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
generate function · rust · L254-L265 (12 LOC)src/python_bindings.rs
fn generate(&self, py: Python, num_samples: usize) -> Py<PyArray1<Complex<f64>>> {
let samples = self.inner.generate::<f64>(num_samples);
// Convert ComplexVec to Vec<Complex<f64>>
let vec: Vec<Complex<f64>> = (0..samples.len())
.map(|i| samples[i])
.collect();
// Transfer ownership to Python
let array = vec.into_pyarray_bound(py);
array.into()
}generate_clean function · rust · L276-L287 (12 LOC)src/python_bindings.rs
fn generate_clean(&self, py: Python, num_samples: usize) -> Py<PyArray1<Complex<f64>>> {
let samples = self.inner.generate_clean::<f64>(num_samples);
// Convert ComplexVec to Vec<Complex<f64>>
let vec: Vec<Complex<f64>> = (0..samples.len())
.map(|i| samples[i])
.collect();
// Transfer ownership to Python
let array = vec.into_pyarray_bound(py);
array.into()
}new function · rust · L310-L325 (16 LOC)src/python_bindings.rs
fn new(carriers: Vec<PyRef<PythonCarrier>>) -> PyResult<Self> {
let rust_carriers: Vec<Carrier> = carriers
.into_iter()
.map(|c| c.inner.clone())
.collect();
if rust_carriers.is_empty() {
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
"Channel must have at least one carrier",
));
}
Ok(PythonChannel {
inner: Channel::new(rust_carriers),
})
}set_noise_floor_linear function · rust · L339-L347 (9 LOC)src/python_bindings.rs
fn set_noise_floor_linear(&mut self, noise_floor_linear: f64) -> PyResult<()> {
if noise_floor_linear <= 0.0 {
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
"noise_floor_linear must be positive",
));
}
self.inner.set_noise_floor_linear(noise_floor_linear);
Ok(())
}generate function · rust · L364-L375 (12 LOC)src/python_bindings.rs
fn generate(&self, py: Python, num_samples: usize) -> PyResult<Py<PyArray1<Complex<f64>>>> {
let samples = self.inner.generate::<f64>(num_samples);
// Convert ComplexVec to Vec<Complex<f64>>
let vec: Vec<Complex<f64>> = (0..samples.len())
.map(|i| samples[i])
.collect();
// Transfer ownership to Python
let array = vec.into_pyarray_bound(py);
Ok(array.into())
}generate_clean function · rust · L386-L397 (12 LOC)src/python_bindings.rs
fn generate_clean(&self, py: Python, num_samples: usize) -> Py<PyArray1<Complex<f64>>> {
let samples = self.inner.generate_clean::<f64>(num_samples);
// Convert ComplexVec to Vec<Complex<f64>>
let vec: Vec<Complex<f64>> = (0..samples.len())
.map(|i| samples[i])
.collect();
// Transfer ownership to Python
let array = vec.into_pyarray_bound(py);
array.into()
}parse_window_type function · rust · L433-L446 (14 LOC)src/python_bindings.rs
fn parse_window_type(window_str: &str) -> PyResult<WindowType> {
match window_str.to_lowercase().as_str() {
"hann" => Ok(WindowType::Hann),
"hamming" => Ok(WindowType::Hamming),
"blackman" => Ok(WindowType::Blackman),
"rectangular" | "rect" => Ok(WindowType::Rectangular),
_ => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
format!(
"Unknown window type: '{}'. Supported types: hann, hamming, blackman, rectangular",
window_str
),
)),
}
}welch function · rust · L473-L515 (43 LOC)src/python_bindings.rs
fn welch(
py: Python,
signal: PyReadonlyArray1<Complex<f64>>,
sample_rate: f64,
nperseg: usize,
noverlap: Option<usize>,
nfft: Option<usize>,
window: &str,
) -> PyResult<(Py<PyArray1<f64>>, Py<PyArray1<f64>>)> {
// Validate parameters
if nperseg == 0 {
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
"nperseg must be greater than 0",
));
}
if sample_rate <= 0.0 {
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
"sample_rate must be positive",
));
}
let window_type = parse_window_type(window)?;
// Extract signal from numpy array
let signal_vec: Vec<Complex<f64>> = signal.as_array().to_vec();
// Call the Rust implementation
let (freqs, psd) = welch_impl(
&signal_vec,
sample_rate,
nperseg,
noverlap,
nfft,
window_type,
None, // Use default averaging method (Mean)
);
// Convert reAll rows scored by the Repobility analyzer (https://repobility.com)
_signal_kit function · rust · L519-L526 (8 LOC)src/python_bindings.rs
fn _signal_kit(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PythonCarrier>()?;
m.add_class::<PythonChannel>()?;
m.add_function(wrap_pyfunction!(welch, m)?)?;
m.add("__version__", "0.1.0")?;
Ok(())
}welch function · rust · L38-L86 (49 LOC)src/spectrum/welch.rs
pub fn welch<T>(
signal: &[Complex<T>],
sample_rate: T,
nperseg: usize,
noverlap: Option<usize>,
nfft: Option<usize>,
window: WindowType,
averaging: Option<AveragingMethod>,
) -> (Vec<T>, Vec<T>)
where
T: Float + std::fmt::Debug + std::ops::RemAssign + std::ops::DivAssign + Send + Sync + num_traits::FromPrimitive + num_traits::Signed + 'static,
{
// Compute defaults
let (overlap, fft_len) = compute_defaults(nperseg, noverlap, nfft);
let avg_method = averaging.unwrap_or(AveragingMethod::Mean);
// Generate window
let window_vec = generate_window(window, nperseg);
// Extract overlapping segments
let segments = extract_segments(signal, nperseg, overlap);
if segments.is_empty() {
// Return empty result if no segments
return (vec![], vec![]);
}
// Compute PSD for each segment
let psds: Vec<Vec<T>> = segments
.iter()
.map(|seg| compute_segment_psd(seg, &window_vec, fft_len))
compute_defaults function · rust · L89-L97 (9 LOC)src/spectrum/welch.rs
fn compute_defaults(
nperseg: usize,
noverlap: Option<usize>,
nfft: Option<usize>,
) -> (usize, usize) {
let overlap = noverlap.unwrap_or(nperseg / 2);
let fft_len = nfft.unwrap_or(nperseg);
(overlap, fft_len)
}extract_segments function · rust · L100-L116 (17 LOC)src/spectrum/welch.rs
fn extract_segments<T: Float>(
signal: &[Complex<T>],
nperseg: usize,
noverlap: usize,
) -> Vec<Vec<Complex<T>>> {
let step = nperseg - noverlap;
let mut segments = Vec::new();
let mut start = 0;
while start + nperseg <= signal.len() {
let segment = signal[start..start + nperseg].to_vec();
segments.push(segment);
start += step;
}
segments
}compute_segment_psd function · rust · L119-L138 (20 LOC)src/spectrum/welch.rs
fn compute_segment_psd<T>(
segment: &[Complex<T>],
window: &[T],
nfft: usize,
) -> Vec<T>
where
T: Float + std::fmt::Debug + std::ops::RemAssign + std::ops::DivAssign + Send + Sync + num_traits::FromPrimitive + num_traits::Signed + 'static,
{
// Apply window
let windowed = apply_window(segment, window);
// Pad or truncate to nfft length
let mut fft_input = prepare_fft_input(windowed, nfft);
// Compute FFT
fft(&mut fft_input);
// Compute power: |FFT|^2
fft_input.iter().map(|c| c.norm_sqr()).collect()
}apply_window function · rust · L141-L147 (7 LOC)src/spectrum/welch.rs
fn apply_window<T: Float>(segment: &[Complex<T>], window: &[T]) -> Vec<Complex<T>> {
segment
.iter()
.zip(window.iter())
.map(|(s, &w)| Complex::new(s.re * w, s.im * w))
.collect()
}prepare_fft_input function · rust · L150-L162 (13 LOC)src/spectrum/welch.rs
fn prepare_fft_input<T: Float>(windowed: Vec<Complex<T>>, nfft: usize) -> Vec<Complex<T>> {
let mut fft_input = windowed;
if nfft > fft_input.len() {
// Zero-pad
fft_input.resize(nfft, Complex::new(T::zero(), T::zero()));
} else if nfft < fft_input.len() {
// Truncate
fft_input.truncate(nfft);
}
fft_input
}average_spectra function · rust · L165-L172 (8 LOC)src/spectrum/welch.rs
fn average_spectra<T: Float>(spectra: Vec<Vec<T>>, method: AveragingMethod) -> Vec<T> {
match method {
AveragingMethod::Mean => compute_mean(&spectra),
AveragingMethod::Median => compute_median(&spectra),
AveragingMethod::Max => compute_max(&spectra),
AveragingMethod::Min => compute_min(&spectra),
}
}Repobility analyzer · published findings · https://repobility.com
compute_mean function · rust · L175-L189 (15 LOC)src/spectrum/welch.rs
fn compute_mean<T: Float>(spectra: &[Vec<T>]) -> Vec<T> {
if spectra.is_empty() {
return vec![];
}
let n_bins = spectra[0].len();
let n_spectra = T::from(spectra.len()).unwrap();
(0..n_bins)
.map(|i| {
let sum = spectra.iter().fold(T::zero(), |acc, spec| acc + spec[i]);
sum / n_spectra
})
.collect()
}compute_median function · rust · L192-L205 (14 LOC)src/spectrum/welch.rs
fn compute_median<T: Float>(spectra: &[Vec<T>]) -> Vec<T> {
if spectra.is_empty() {
return vec![];
}
let n_bins = spectra[0].len();
(0..n_bins)
.map(|i| {
let mut values: Vec<T> = spectra.iter().map(|spec| spec[i]).collect();
median_of_slice(&mut values)
})
.collect()
}compute_max function · rust · L208-L225 (18 LOC)src/spectrum/welch.rs
fn compute_max<T: Float>(spectra: &[Vec<T>]) -> Vec<T> {
if spectra.is_empty() {
return vec![];
}
let n_bins = spectra[0].len();
(0..n_bins)
.map(|i| {
spectra
.iter()
.map(|spec| spec[i])
.fold(T::neg_infinity(), |acc, val| {
if val > acc { val } else { acc }
})
})
.collect()
}