use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};
pub type Coord = f32;
#[derive(Clone, Copy, Debug, PartialEq, Default)]
pub struct RuVec2 {
pub x: Coord,
pub y: Coord,
}
impl RuVec2 {
pub const ZERO: RuVec2 = RuVec2 { x: 0.0, y: 0.0 };
#[inline]
pub const fn new(x: Coord, y: Coord) -> Self {
Self { x, y }
}
#[inline]
pub const fn splat(v: Coord) -> Self {
Self { x: v, y: v }
}
}
impl Add for RuVec2 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self { Self { x: self.x + rhs.x, y: self.y + rhs.y } }
}
impl AddAssign for RuVec2 {
#[inline]
fn add_assign(&mut self, rhs: Self) { self.x += rhs.x; self.y += rhs.y; }
}
impl Sub for RuVec2 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self { Self { x: self.x - rhs.x, y: self.y - rhs.y } }
}
impl SubAssign for RuVec2 {
#[inline]
fn sub_assign(&mut self, rhs: Self) { self.x -= rhs.x; self.y -= rhs.y; }
}
impl Neg for RuVec2 {
type Output = Self;
#[inline]
fn neg(self) -> Self { Self { x: -self.x, y: -self.y } }
}
impl Mul<Coord> for RuVec2 {
type Output = Self;
#[inline]
fn mul(self, k: Coord) -> Self { Self { x: self.x * k, y: self.y * k } }
}
impl MulAssign<Coord> for RuVec2 {
#[inline]
fn mul_assign(&mut self, k: Coord) { self.x *= k; self.y *= k; }
}
impl Div<Coord> for RuVec2 {
type Output = Self;
#[inline]
fn div(self, k: Coord) -> Self { Self { x: self.x / k, y: self.y / k } }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn arithmetic_round_trip() {
let a = RuVec2::new(1.5, -2.25);
let b = RuVec2::new(0.5, 0.25);
let sum = a + b;
assert_eq!(sum, RuVec2::new(2.0, -2.0));
assert_eq!(sum - b, a);
assert_eq!(-a, RuVec2::new(-1.5, 2.25));
}
#[test]
fn zero_is_identity() {
let v = RuVec2::new(3.0, -1.0);
assert_eq!(v + RuVec2::ZERO, v);
}
#[test]
fn scalar_mul_div() {
let v = RuVec2::new(2.0, -4.0);
assert_eq!(v * 0.5, RuVec2::new(1.0, -2.0));
assert_eq!(v / 2.0, RuVec2::new(1.0, -2.0));
}
}