1use core::ops::{Add, Sub, Mul};
4use crate::Float;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct Vec2<T: Float> {
9 pub x: T,
11 pub y: T,
13}
14
15impl<T: Float> Vec2<T> {
16 pub fn new(x: T, y: T) -> Self { Self { x, y } }
18
19 pub fn dot(self, other: Vec2<T>) -> T {
21 self.x * other.x + self.y * other.y
22 }
23
24 pub fn magnitude(self) -> T {
26 self.dot(self).sqrt()
27 }
28
29 pub fn cross(self, other: Vec2<T>) -> T {
31 self.x * other.y - self.y * other.x
32 }
33}
34impl<T: Float> Add for Vec2<T> {
36 type Output = Vec2<T>;
37 fn add(self, rhs: Vec2<T>) -> Vec2<T> {
38 Vec2::new(self.x + rhs.x, self.y + rhs.y)
39 }
40}
41impl<T: Float> Sub for Vec2<T> {
43 type Output = Vec2<T>;
44 fn sub(self, rhs: Vec2<T>) -> Vec2<T> {
45 Vec2::new(self.x - rhs.x, self.y - rhs.y)
46 }
47}
48impl<T: Float> Mul<T> for Vec2<T> {
50 type Output = Vec2<T>;
51 fn mul(self, rhs: T) -> Vec2<T> {
52 Vec2::new(self.x * rhs, self.y * rhs)
53 }
54}
55#[derive(Debug, Clone, Copy, PartialEq)]
57pub struct Vec3<T: Float> {
58 pub x: T,
60 pub y: T,
62 pub z: T,
64}
65
66impl<T: Float> Vec3<T> {
67 pub fn new(x: T, y: T, z: T) -> Self { Self { x, y, z } }
69
70 pub fn dot(self, other: Vec3<T>) -> T {
72 self.x * other.x + self.y * other.y + self.z * other.z
73 }
74
75 pub fn cross(self, other: Vec3<T>) -> Vec3<T> {
77 Vec3::new(
78 self.y * other.z - self.z * other.y,
79 self.z * other.x - self.x * other.z,
80 self.x * other.y - self.y * other.x,
81 )
82 }
83
84 pub fn magnitude(self) -> T {
86 self.dot(self).sqrt()
87 }
88}
89impl<T: Float> Add for Vec3<T> {
90 type Output = Vec3<T>;
91 fn add(self, rhs: Vec3<T>) -> Vec3<T> {
92 Vec3::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
93 }
94}
95impl<T: Float> Sub for Vec3<T> {
96 type Output = Vec3<T>;
97 fn sub(self, rhs: Vec3<T>) -> Vec3<T> {
98 Vec3::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
99 }
100}
101impl<T: Float> Mul<T> for Vec3<T> {
102 type Output = Vec3<T>;
103 fn mul(self, rhs: T) -> Vec3<T> {
104 Vec3::new(self.x * rhs, self.y * rhs, self.z * rhs)
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use crate::{Vec2, Vec3};
111
112 #[test]
113 fn vec2_dot_and_cross() {
114 let u = Vec2::new(1.0, 0.0);
115 let v = Vec2::new(0.0, 1.0);
116 assert_eq!(u.dot(v), 0.0);
117 assert_eq!(u.cross(v), 1.0);
119 }
120
121 #[test]
122 fn vec3_dot_and_cross() {
123 let i = Vec3::new(1.0, 0.0, 0.0);
124 let j = Vec3::new(0.0, 1.0, 0.0);
125 let k = Vec3::new(0.0, 0.0, 1.0);
126 assert_eq!(i.dot(j), 0.0);
127 assert_eq!(i.cross(j), k);
128 }
129
130 #[test]
131 fn vec_scaling_and_magnitude() {
132 let v = Vec3::new(2.0, -3.0, 6.0);
133 let scaled = v * 2.0;
134 assert_eq!(scaled, Vec3::new(4.0, -6.0, 12.0));
135 let len = (4.0_f64*4.0 + 6.0*6.0 + 12.0*12.0).sqrt();
136 assert!((scaled.magnitude() - len).abs() < 1e-12);
137 }
138}