use num::{Float, Zero};
use std::iter::Sum;
use std::ops::Mul;
pub fn veclistsum<T: Float>(veclist: &[&[T]]) -> Vec<T> {
let maxlen: usize = veclist.iter().map(|lst| lst.len()).max().unwrap_or(0_usize);
veclist.iter().fold(vec![Zero::zero()], |acc, ref x| {
(0..maxlen)
.map(|idx| {
*acc.get(idx).unwrap_or(&Zero::zero()) + *x.get(idx).unwrap_or(&Zero::zero())
})
.collect()
})
}
pub fn vecvecmin<T: Float>(vec1: &[T], vec2: &[T]) -> Vec<T> {
assert_eq!(vec1.len(), vec2.len());
vec1.iter()
.zip(vec2.iter())
.map(|(a, b)| a.min(*b))
.collect()
}
pub fn vecvecsum<T: Float>(vec1: &[T], vec2: &[T]) -> Vec<T> {
assert_eq!(vec1.len(), vec2.len());
vec1.iter().zip(vec2.iter()).map(|(a, b)| *a + *b).collect()
}
pub fn vecvecdif<T: Float>(vec1: &[T], vec2: &[T]) -> Vec<T> {
assert_eq!(vec1.len(), vec2.len());
vec1.iter().zip(vec2.iter()).map(|(a, b)| *a - *b).collect()
}
pub fn vecvecmul<T: Float>(vec1: &[T], vec2: &[T]) -> Vec<T> {
assert_eq!(vec1.len(), vec2.len());
vec1.iter().zip(vec2.iter()).map(|(a, b)| *a * *b).collect()
}
pub fn veckmul<T, I>(iter: I, k: T) -> Vec<T>
where
T: Float,
I: IntoIterator,
I::Item: Mul<T, Output = T>,
{
iter.into_iter().map(|el| el * k).collect()
}
pub fn vecsum<'a, T>(vec: &'a [T]) -> T
where
T: Float + Sum<&'a T> + 'a,
{
vec.iter().sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn vecops_veclistsum() {
assert_eq!(
vec![6.0, 6.0, 6.0],
veclistsum(&[&[1.0, 1.0, 1.0], &[2.0, 2.0, 2.0], &[3.0, 3.0, 3.0]])
);
assert_eq!(
vec![6.0, 6.0, 6.0],
veclistsum(&[
&vec![1.0, 1.0, 1.0],
&vec![2.0, 2.0, 2.0],
&vec![3.0, 3.0, 3.0],
])
);
}
#[test]
fn vecops_vecvecmin() {
assert_eq!(
vec![2.0, 1.0, 2.0],
vecvecmin(&[2.0, 2.0, 2.0], &[4.0, 1.0, 2.0])
);
}
#[test]
fn vecops_vecvecsum() {
assert_eq!(
vec![4.0, 4.0, 4.0],
vecvecsum(&[2.0, 1.0, 3.0], &[2.0, 3.0, 1.0])
);
}
#[test]
fn vecops_vecvecdif() {
assert_eq!(
vec![1.0, 1.0, 1.0],
vecvecdif(&[2.0, 3.0, 4.0], &[1.0, 2.0, 3.0])
);
}
#[test]
fn vecops_vecvecmul() {
assert_eq!(
vec![1.0, 6.0, 4.0],
vecvecmul(&[1.0, 3.0, 2.0], &[1.0, 2.0, 2.0])
);
}
#[test]
fn vecops_veckmul() {
assert_eq!(vec![2.0, 4.0, 6.0], veckmul(&[1.0, 2.0, 3.0], 2.0));
assert_eq!(vec![2.0, 4.0, 6.0], veckmul(vec![1.0, 2.0, 3.0], 2.0));
}
#[test]
fn vecops_vecsum() {
assert!(f32::abs(9.0 - vecsum(&[2.0, 3.0, 4.0])) < f32::EPSILON);
}
}