mod vec2d;
mod vec2i;
use std::ops::{Add, Div, Mul, Sub};
pub use self::vec2d::*;
pub use self::vec2i::*;
#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
pub struct Vec2<T> {
pub x: T,
pub y: T,
}
#[macro_export]
macro_rules! vec2 {
() => {
$crate::vec::Vec2::default()
};
($val:expr) => {
$crate::vec::Vec2 { x: $val, y: $val }
};
($x:expr, $y:expr) => {
$crate::vec::Vec2 { x: $x, y: $y }
};
}
pub trait VectorOperations<T> {
fn length(&self) -> f64;
fn normalize(&self) -> Vec2<f64>;
fn dot(&self, rhs: &Self) -> T;
}
impl<T> Add for Vec2<T>
where
T: Add<Output = T>,
{
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl<T> Sub for Vec2<T>
where
T: Sub<Output = T>,
{
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
impl<T> Mul<T> for Vec2<T>
where
T: Mul<Output = T> + Clone + Copy,
{
type Output = Self;
fn mul(self, rhs: T) -> Self::Output {
Self {
x: self.x * rhs,
y: self.y * rhs,
}
}
}
impl<T> Div<T> for Vec2<T>
where
T: Div<Output = T> + Clone + Copy,
{
type Output = Self;
fn div(self, rhs: T) -> Self::Output {
Self {
x: self.x / rhs,
y: self.y / rhs,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vec_add() {
assert_eq!(
Vec2 { x: 1, y: 0 } + Vec2 { x: 2, y: 1 },
Vec2 { x: 3, y: 1 }
);
}
#[test]
fn test_vec_sub() {
assert_eq!(
Vec2 { x: 1, y: 0 } - Vec2 { x: 2, y: 1 },
Vec2 { x: -1, y: -1 }
);
}
#[test]
fn test_vec_scale() {
assert_eq!(Vec2 { x: 2, y: 5 } * 3, Vec2 { x: 6, y: 15 });
}
#[test]
fn test_vec_div() {
assert_eq!(Vec2 { x: 2.0, y: 5.0 } / 2.0, Vec2 { x: 1.0, y: 2.5 });
}
#[test]
fn test_vec2_macro_empty() {
assert_eq!(vec2![], Vec2 { x: 0, y: 0 });
}
#[test]
fn test_vec2_macro_splat() {
assert_eq!(vec2![42], Vec2 { x: 42, y: 42 });
}
#[test]
fn test_vec2_macro_double_args() {
assert_eq!(vec2![3, 4], Vec2 { x: 3, y: 4 });
}
}