pub fn addVecs<'a>(v1: &'a [f32], v2: &'a [f32]) -> Vec<f32> {
    v1.iter().zip(v2).map(|(a, b)| a + b).collect()
}

pub fn subVecs(v1: &[f32], v2: &[f32]) -> Vec<f32> {
    v1.iter().zip(v2).map(|(a, b)| a - b).collect()
}

pub fn normalizeVec(v1: &[f32]) -> Vec<f32> {
    let l2Norm = normVec(v1);
    mulScalVec(&l2Norm.powi(-1), v1)
}

pub fn normVec(v1: &[f32]) -> f32 {
    dotVecVec(v1, v1).powf(0.5)
}

pub fn dotVecVec(v1: &[f32], v2: &[f32]) -> f32 {
    v1.iter().zip(v2).map(|(a, b)| a * b).sum()
}

pub fn mulScalVec<'a>(s: &'a f32, v1: &'a [f32]) -> Vec<f32> {
    v1.iter().map(|a| a * s).collect()
}

pub fn checkEqualLenVec(v1: &[f32], v2: &[f32]) -> bool {
    v1.len() == v2.len()
}
