pub(crate) mod pads;
pub(crate) mod wires;
fn nn_greedy_deconvolution(
signal: &[f64],
response: &[f64],
offset: usize,
look_ahead: usize,
) -> (f64, Vec<f64>) {
let response_window = &response[offset..][..look_ahead];
assert!(response_window.iter().all(|&x| x < 0.0));
let mut residual = signal.to_vec();
let mut input = vec![0.0; signal.len()];
let mut i = 0;
while i + offset + look_ahead <= residual.len() {
let residual_window = &residual[i + offset..][..look_ahead];
let last_positive = residual_window
.iter()
.enumerate()
.rev()
.find(|(_, x)| **x >= 0.0)
.map(|(i, _)| i);
if let Some(last_positive) = last_positive {
i += last_positive + 1;
} else {
let val = residual_window
.iter()
.zip(response_window)
.map(|(s, r)| s / r)
.reduce(f64::min)
.unwrap();
input[i] = val;
residual[i..]
.iter_mut()
.zip(response)
.for_each(|(s, r)| *s -= val * r);
i += 1;
}
}
let residual = residual.iter().map(|x| x.powi(2)).sum();
(residual, input)
}
fn ls_deconvolution<I>(signal: &[f64], response: &[f64], offsets: I, look_aheads: I) -> Vec<f64>
where
I: Iterator<Item = usize> + Clone,
{
let mut best_residual = f64::INFINITY;
let mut best_input = Vec::new();
for offset in offsets {
for look_ahead in look_aheads.clone() {
let (residual, input) = nn_greedy_deconvolution(signal, response, offset, look_ahead);
if residual < best_residual {
best_residual = residual;
best_input = input;
}
}
}
best_input
}