use std::f64::consts::{ PI };
use num_complex::Complex64;
pub fn convolve<T>(a_i: &[T], b_i: &[T]) -> Vec<T>
where T: std::ops::Mul<Output = T> + std::ops::AddAssign + Default + Copy {
let (a, b): (&[T], &[T]) = match a_i.len() < b_i.len() {
true => (b_i, a_i),
false => (a_i, b_i)
};
let mut sum: T;
let l_a: usize = a.len();
let l_b: usize = b.len();
let mut res: Vec<T> = Vec::with_capacity(l_a + 2 * l_b - 2);
for n in 0..(l_b - 1) {
sum = T::default();
for m in 0..=n {
sum += a[n-m] * b[m];
}
res.push(sum);
}
for n in (l_b - 1)..=(l_a - 1) {
sum = T::default();
for m in 0..l_b {
sum += a[n-m] * b[m];
}
res.push(sum);
}
for n in l_a..(l_a + l_b - 1) {
sum = T::default();
for m in (n - l_a + 1)..l_b {
sum += a[n-m] * b[m];
}
res.push(sum);
}
res
}
pub fn convolve_full<T>(a_i: &[T], b_i: &[T]) -> Vec<T>
where T: std::ops::Mul<Output = T> + std::ops::AddAssign + Default + Copy {
let (a, b): (&[T], &[T]) = match a_i.len() < b_i.len() {
true => (b_i, a_i),
false => (a_i, b_i)
};
let mut sum: T;
let l_a: usize = a.len();
let l_b: usize = b.len();
let mut res: Vec<T> = Vec::with_capacity(l_a - l_b + 1);
for n in (l_b - 1)..=(l_a - 1) {
sum = T::default();
for m in 0..l_b {
sum += a[n-m] * b[m];
}
res.push(sum);
}
res
}
pub fn fft<T>(data: &[T]) -> Vec<Complex64>
where T: Into<Complex64> + Copy {
let length: isize = data.len() as isize;
let ipi_n: Complex64 = Complex64::i() * PI / length as f64;
let mut res: Vec<Complex64> = Vec::with_capacity(data.len());
let mut an: Complex64;
let mut bkn: Complex64;
let mut bk_star: Complex64;
let mut sum_k: Complex64;
for k in 0..length {
sum_k = Complex64::default();
bk_star = (k.pow(2) as f64 * ipi_n).exp().conj();
for (n, val) in data.iter().enumerate() {
an = (- (n.pow(2) as f64) * ipi_n).exp() * (*val).into();
bkn = ((k - n as isize).pow(2) as f64 * ipi_n).exp();
sum_k += an * bkn;
}
res.push(bk_star * sum_k);
}
res
}
pub fn ifft<T>(data: &[T]) -> Vec<Complex64>
where T: Into<Complex64> + Copy {
let length: isize = data.len() as isize;
let norm: f64 = length as f64;
let ipi_n: Complex64 = -Complex64::i() * PI / length as f64;
let mut res: Vec<Complex64> = Vec::with_capacity(data.len());
let mut an: Complex64;
let mut bkn: Complex64;
let mut bk_star: Complex64;
let mut sum_k: Complex64;
for k in 0..length {
sum_k = Complex64::default();
bk_star = (k.pow(2) as f64 * ipi_n).exp().conj();
for (n, val) in data.iter().enumerate() {
an = (- (n.pow(2) as f64) * ipi_n).exp() * (*val).into();
bkn = ((k - n as isize).pow(2) as f64 * ipi_n).exp();
sum_k += an * bkn;
}
res.push(bk_star * sum_k / norm);
}
res
}