use no_denormals::*;
pub struct Convolution {
history: Vec<f32>,
kernel: Box<[f32]>,
}
impl Convolution {
pub fn new(kernel: &[f32]) -> Self {
Self {
history: vec![0.0; kernel.len()],
kernel: kernel.to_vec().into_boxed_slice(),
}
}
pub fn kernel_len(&self) -> usize {
self.kernel.len()
}
#[inline]
fn push(&mut self, value: f32) {
let len = self.history.len();
if len == 0 {
return;
}
self.history.copy_within(1..len, 0);
self.history[len - 1] = value;
}
#[inline]
pub fn process(&mut self, input: f32) -> f32 {
self.push(input);
crate::simd::dot(&self.history, &self.kernel)
}
pub fn run(&mut self, input: &[f32], output: &mut [f32]) {
unsafe {
no_denormals(|| {
for index in 0..input.len().min(output.len()) {
self.push(input[index]);
output[index] = crate::simd::dot(&self.history, &self.kernel);
}
});
}
}
}