simple_vector2 2.1.5

A simple libary for generic vector manipulation that just works.
Documentation
#![cfg_attr(not(test), no_std)]

use core::fmt::{Display, Formatter};
use core::ops::{Add, Div, Mul, Sub};
use libm::{sqrt, sqrtf};

pub mod vector_2_to_decimal;
pub mod mul;


#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Vector2<T> {
    pub x: T,
    pub y: T
}

impl<T> Vector2<T> {
    /// Make a new vector
    pub const fn new(x: T, y: T) -> Vector2<T> {
        Self {
            x,
            y
        }
    }

    /// Cast a vector from type T to type R
    pub fn cast_to<R: From<T>>(self) -> Vector2<R> {
        Vector2::<R> {
            x: R::from(self.x),
            y: R::from(self.y),
        }
    }

    pub fn map<R, M: FnMut(T) -> R>(self, mut f: M) -> Vector2<R> {
        Vector2::<R> {
            x: f(self.x),
            y: f(self.y),
        }
    }
}

impl<T: Add<Output=T>+Mul<Output=T>+Copy> Vector2<T> {

    /// Returns the value of (x * x) + (y * y). Integer types don't implement sqrt so we
    /// can't implement magnitude.
    pub fn square_magnitude(&self) -> T {
        (self.x * self.x) + (self.y * self.y)
    }
}

fn abs_sub<T: Sub<Output=T>+PartialOrd>(a:T, b:T) -> T {
    if a > b {
        a - b
    } else {
        b - a
    }
}

impl<T: Mul<Output=T>+Add<Output=T>+Sub<Output=T>+Copy+PartialOrd> Vector2<T> {
    /// Returns the value of (x_2 - x_1)^2 + (y_2 - y_1)^2. Integer types don't implement
    /// sqrt so we can't implement distance.
    pub fn square_distance(&self, from: &Vector2<T>) -> T {
        let x_dist = abs_sub(from.x, self.x);
        let y_dist = abs_sub(from.y, self.y);

        (x_dist * x_dist) + (y_dist * y_dist)
    }
}

impl Vector2<f32> {
    pub fn magnitude(&self) -> f32 {
        sqrtf(self.square_magnitude())
    }
    pub fn distance(&self, other: &Vector2<f32>) -> f32 {
        sqrtf(self.square_distance(other))
    }
}

impl Vector2<f64> {
    pub fn magnitude(&self) -> f64 {
        sqrt(self.square_magnitude())
    }
    pub fn distance(&self, other: &Vector2<f64>) -> f64 {
        sqrt(self.square_distance(other))
    }
}

impl<T> From<(T, T)> for Vector2<T> {
    fn from(value: (T, T)) -> Self {
        Vector2::new(value.0, value.1)
    }
}


impl<T: Display> Display for Vector2<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

impl<T:Default> Default for Vector2<T> {
    fn default() -> Self {
        Self {
            x: T::default(),
            y: T::default(),
        }
    }
}

impl<T> Add for Vector2<T> where T: Add<Output = T>{
    type Output = Vector2<T>;

    fn add(self, rhs: Self) -> Self::Output {
        Self {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
        }
    }
}

impl<T> Sub for Vector2<T> where T: Sub<Output = T>{
    type Output = Vector2<T>;

    fn sub(self, rhs: Self) -> Self::Output {
        Self {
            x: self.x - rhs.x,
            y: self.y - rhs.y,
        }
    }
}

impl<T> Mul<T> for Vector2<T> where T: Mul<Output = T> + Copy {
    type Output = Vector2<T>;

    fn mul(self, scalar: T) -> Self::Output {
        Self {
            x: self.x * scalar.clone(),
            y: self.y * scalar,
        }
    }
}

impl<T> Div<T> for Vector2<T> where T: Div<Output = T> + Copy {
    type Output = Vector2<T>;

    fn div(self, scalar: T) -> Self::Output {
        Self {
            x: self.x / scalar.clone(),
            y: self.y / scalar,
        }
    }
}


#[cfg(test)]
mod tests {
    use crate::vector_2_to_decimal::{Vector2ToDouble, Vector2ToFloat};
    use super::*;

    #[test]
    fn convert_i32_f32() {
        let v1 = Vector2::new(3, 4);
        let v2 = v1.to_float();
        assert_eq!(v2, Vector2::new(3.0, 4.0))
    }

    #[test]
    fn convert_i32_f64() {
        let v1 = Vector2::new(3, 4);
        let v2 = v1.to_double();
        assert_eq!(v2, Vector2::new(3.0, 4.0))
    }

    #[test]
    fn cast_i32_i64() {
        let v1 = Vector2::new(3, 4);
        let v2: Vector2<i64> = v1.cast_to();
        assert_eq!(v2, Vector2::new(3, 4))
    }

    #[test]
    fn add() {
        let v1 = Vector2::new(1, 2);
        let v2 = Vector2::new(2, 2);
        assert_eq!(v1 + v2, Vector2::new(3, 4))
    }

    #[test]
    fn sub() {
        let v1 = Vector2::new(1, 2);
        let v2 = Vector2::new(2, 2);
        assert_eq!(v2 - v1, Vector2::new(1, 0))
    }

    #[test]
    fn mul() {
        let v1 = Vector2::new(1, 1);
        let v2 = 2 * v1;
        assert_eq!(v2, Vector2::new(2, 2))
    }

    #[test]
    fn div() {
        let v1 = Vector2::new(2, 2);
        let v2 = v1 / 2;

        assert_eq!(v2, Vector2::new(1, 1))
    }

    #[test]
    fn map() {
        let v1 = Vector2::new(1, 2);
        assert_eq!(Vector2::new(2, 4), v1.map(|x| x * 2))
    }

    #[test]
    fn underflow() {
        let a = Vector2::new(0_u8, 0_u8);
        let b = Vector2::new(1_u8, 1_u8);

        assert_eq!(a.square_distance(&b), 2);
        assert_eq!(b.square_distance(&a), 2)

    }
}