1use core::ops::{Add, Div, Mul, Neg, Sub};
2
3#[derive(Clone, Copy, Debug, Default, PartialEq)]
9pub struct Vec2 {
10 pub dx: f64,
11 pub dy: f64,
12}
13
14impl Vec2 {
15 pub const ZERO: Self = Self { dx: 0.0, dy: 0.0 };
16
17 #[inline]
18 pub const fn new(dx: f64, dy: f64) -> Self {
19 Self { dx, dy }
20 }
21
22 #[inline]
24 pub const fn splat(v: f64) -> Self {
25 Self { dx: v, dy: v }
26 }
27
28 #[inline]
29 pub fn length(self) -> f64 {
30 self.length_squared().sqrt()
31 }
32
33 #[inline]
34 pub fn length_squared(self) -> f64 {
35 self.dx * self.dx + self.dy * self.dy
36 }
37
38 #[inline]
39 pub fn dot(self, other: Self) -> f64 {
40 self.dx * other.dx + self.dy * other.dy
41 }
42
43 #[inline]
46 pub fn normalized(self) -> Self {
47 let len = self.length();
48 if len == 0.0 { Self::ZERO } else { self / len }
49 }
50}
51
52impl Add for Vec2 {
53 type Output = Vec2;
54 #[inline]
55 fn add(self, rhs: Vec2) -> Vec2 {
56 Vec2::new(self.dx + rhs.dx, self.dy + rhs.dy)
57 }
58}
59
60impl Sub for Vec2 {
61 type Output = Vec2;
62 #[inline]
63 fn sub(self, rhs: Vec2) -> Vec2 {
64 Vec2::new(self.dx - rhs.dx, self.dy - rhs.dy)
65 }
66}
67
68impl Neg for Vec2 {
69 type Output = Vec2;
70 #[inline]
71 fn neg(self) -> Vec2 {
72 Vec2::new(-self.dx, -self.dy)
73 }
74}
75
76impl Mul<f64> for Vec2 {
77 type Output = Vec2;
78 #[inline]
79 fn mul(self, rhs: f64) -> Vec2 {
80 Vec2::new(self.dx * rhs, self.dy * rhs)
81 }
82}
83
84impl Div<f64> for Vec2 {
85 type Output = Vec2;
86 #[inline]
87 fn div(self, rhs: f64) -> Vec2 {
88 Vec2::new(self.dx / rhs, self.dy / rhs)
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn length_and_normalize() {
98 let v = Vec2::new(3.0, 4.0);
99 assert_eq!(v.length(), 5.0);
100 let n = v.normalized();
101 assert!((n.length() - 1.0).abs() < 1e-12);
102 assert_eq!(Vec2::ZERO.normalized(), Vec2::ZERO);
103 }
104
105 #[test]
106 fn arithmetic() {
107 assert_eq!(
108 Vec2::new(1.0, 2.0) + Vec2::new(3.0, 4.0),
109 Vec2::new(4.0, 6.0)
110 );
111 assert_eq!(Vec2::splat(2.0) * 3.0, Vec2::new(6.0, 6.0));
112 assert_eq!(-Vec2::new(1.0, -2.0), Vec2::new(-1.0, 2.0));
113 }
114}