#![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> {
pub const fn new(x: T, y: T) -> Vector2<T> {
Self {
x,
y
}
}
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> {
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> {
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)
}
}