use num::{Num, Float, Signed};
use crate::utils::nearly_equal;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct MaxMin<T> {
pub max: (T, usize),
pub min: (T, usize),
}
pub fn find_max_min<T: core::cmp::PartialOrd + Copy>(slice: &[T]) -> MaxMin<T> {
let mut max = &slice[0];
let mut min = &slice[0];
let mut max_pos: usize = 0;
let mut min_pos: usize = 0;
for (index, element) in slice.iter().enumerate().skip(1) {
if element < min { min = element; min_pos = index; }
if element > max { max = element; max_pos = index; }
}
MaxMin{max: (*max, max_pos), min: (*min, min_pos)}
}
pub fn norm_inf<T: Num + Copy + core::cmp::PartialOrd>(slice: &[T]) -> T {
let max_min = find_max_min(slice);
max_min.max.0
}
pub fn norm_l<T: Num + Copy + Signed + core::iter::Sum>(slice: &[T]) -> T {
slice.iter().map(|element| element.abs()).sum()
}
pub fn norm2<T: Float>(slice: &[T]) -> T {
slice.iter().fold(T::zero(), |n, &i| (i * i) + n).sqrt()
}
pub fn dot<T: Num + Copy + core::iter::Sum>(slice1: &[T], slice2: &[T]) -> T {
slice1.iter().zip(slice2).map(|(&a, &b)| a * b).sum()
}
pub fn normalize<T: Float>(slice: &mut [T]) {
let n = norm2(slice);
slice.iter_mut().for_each(|element| {
*element = *element / n;
})
}
pub fn project_x_over_y<T: Float + core::iter::Sum>(x: &[T], y: &[T]) -> T {
dot(x, y) / dot(y, y)
}
pub fn check_elements<T: Float>(v: &[T], tol: T) -> bool {
let mut result = false;
for num in v.iter() {
result |= nearly_equal(*num, T::zero(), tol);
}
result
}
#[cfg(test)]
mod test_slides_methods {
use crate::vector3::V3;
use crate::slices_methods::*;
#[test]
fn find_max_min_test() {
let v = V3::new([1, 10, 37]);
let result = find_max_min(&*v);
let expected = MaxMin{max: (37, 2), min: (1, 0)};
assert_eq!(result, expected);
}
#[test]
fn dot_tests() {
let v1 = V3::new([1, 1, 1]);
let v2 = V3::new([1, 1, 3]);
let result = dot(&*v1, &*v2);
let expected = 5;
assert_eq!(result, expected);
}
#[test]
fn normalize_test() {
let mut v1 = V3::new([1.0, 1.0, 1.0]);
normalize(&mut *v1);
let expected = V3::new([0.5773502691896258, 0.5773502691896258, 0.5773502691896258]);
assert_eq!(
&v1[..],
&expected[..],
"\nExpected\n{:?}\nfound\n{:?}",
&v1[..],
&expected[..]
);
}
}