Last active
January 18, 2023 12:42
-
-
Save alexmerou/23167623356e58d5fd636f5332905ed2 to your computer and use it in GitHub Desktop.
An implementation of a mathematical 2D vector type with tests.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::ops::{Add, Div, Mul, Neg, Sub}; | |
#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)] | |
pub struct Vector2 { | |
pub x: f32, | |
pub y: f32, | |
} | |
impl Vector2 { | |
pub const UNIT_X: Self = Self { x: 1.0, y: 0.0 }; | |
pub const UNIT_Y: Self = Self { x: 0.0, y: 1.0 }; | |
#[must_use] | |
pub const fn new(x: f32, y: f32) -> Self { | |
Self { x, y } | |
} | |
#[must_use] | |
pub const fn splat(value: f32) -> Self { | |
Self { x: value, y: value } | |
} | |
#[must_use] | |
pub fn length(self) -> f32 { | |
self.x.hypot(self.y) | |
} | |
#[must_use] | |
pub fn normalized(self) -> Self { | |
let length = self.length(); | |
Self { | |
x: self.x / length, | |
y: self.y / length, | |
} | |
} | |
#[must_use] | |
pub fn dot(self, other: &Self) -> f32 { | |
self.x.mul_add(other.x, self.y * other.y) | |
} | |
} | |
impl From<[f32; 2]> for Vector2 { | |
fn from(array: [f32; 2]) -> Self { | |
Self { | |
x: array[0], | |
y: array[1], | |
} | |
} | |
} | |
impl From<(f32, f32)> for Vector2 { | |
fn from(tuple: (f32, f32)) -> Self { | |
Self { | |
x: tuple.0, | |
y: tuple.1, | |
} | |
} | |
} | |
impl Add for Vector2 { | |
type Output = Self; | |
fn add(self, other: Self) -> Self { | |
Self { | |
x: self.x + other.x, | |
y: self.y + other.y, | |
} | |
} | |
} | |
impl Sub for Vector2 { | |
type Output = Self; | |
fn sub(self, other: Self) -> Self { | |
Self { | |
x: self.x - other.x, | |
y: self.y - other.y, | |
} | |
} | |
} | |
impl Mul<f32> for Vector2 { | |
type Output = Self; | |
fn mul(self, scalar: f32) -> Self { | |
Self { | |
x: self.x * scalar, | |
y: self.y * scalar, | |
} | |
} | |
} | |
impl Mul<Vector2> for f32 { | |
type Output = Vector2; | |
fn mul(self, vector: Vector2) -> Vector2 { | |
Vector2 { | |
x: self * vector.x, | |
y: self * vector.y, | |
} | |
} | |
} | |
impl Div<f32> for Vector2 { | |
type Output = Self; | |
fn div(self, scalar: f32) -> Self { | |
Self { | |
x: self.x / scalar, | |
y: self.y / scalar, | |
} | |
} | |
} | |
impl Neg for Vector2 { | |
type Output = Self; | |
fn neg(self) -> Self { | |
Self { | |
x: -self.x, | |
y: -self.y, | |
} | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
#[test] | |
fn vector_add() { | |
let v1 = Vector2::new(1.0, 2.0); | |
let v2 = Vector2::new(2.0, 3.0); | |
let v3 = v1 + v2; | |
let v4 = Vector2::new(3.0, 5.0); | |
assert_eq!(v3, v4); | |
} | |
#[test] | |
fn vector_sub() { | |
let v1 = Vector2::new(1.0, 2.0); | |
let v2 = Vector2::new(2.0, 3.0); | |
let v3 = v1 - v2; | |
let v4 = Vector2::new(-1.0, -1.0); | |
assert_eq!(v3, v4); | |
} | |
#[test] | |
fn scalar_mul() { | |
let v1 = Vector2::new(1.0, 2.0); | |
let v2 = v1 * 2.0; | |
let v3 = 2.0 * v1; | |
let v4 = Vector2::new(2.0, 4.0); | |
assert_eq!(v2, v4); | |
assert_eq!(v3, v4); | |
} | |
#[test] | |
fn scalar_div() { | |
let v1 = Vector2::new(1.0, 2.0); | |
let v2 = v1 / 2.0; | |
let v3 = Vector2::new(0.5, 1.0); | |
assert_eq!(v2, v3); | |
} | |
#[test] | |
fn negation() { | |
let v1 = Vector2::new(1.0, 2.0); | |
let v2 = -v1; | |
let v3 = Vector2::new(-1.0, -2.0); | |
assert_eq!(v2, v3); | |
} | |
#[test] | |
fn length() { | |
let v1 = Vector2::new(3.0, 4.0); | |
let len = v1.length(); | |
let expected_len = 5.0; | |
assert_eq!(len, expected_len); | |
} | |
#[test] | |
fn normalize() { | |
let v1 = Vector2::new(3.0, 4.0); | |
let v2 = v1.normalized(); | |
let expected_x = 3.0 / 5.0; | |
let expected_y = 4.0 / 5.0; | |
assert_eq!(v2.x, expected_x); | |
assert_eq!(v2.y, expected_y); | |
assert_eq!(v2.length(), 1.0); | |
} | |
#[test] | |
fn dot_product() { | |
let v1 = Vector2::new(1.0, 2.0); | |
let v2 = Vector2::new(2.0, 3.0); | |
let dot = v1.dot(&v2); | |
let expected_dot = 8.0; | |
assert_eq!(dot, expected_dot); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment