1use crate::number::{Integer, Number, Signed, UnsignedInteger};
4use std::fmt::Debug;
5use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Sub, SubAssign};
6
7macro_rules! vec_impl {
8 ($n:literal, $tuple:tt =>
9 $(#[$m:meta])* $v:vis struct $s:ident{$($i:tt => $f:ident),+}
10 ) => {
11 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
12 $(#[$m])* $v struct $s<T: Number> {
13 $(pub $f: T,)+
14 }
15
16 impl<T: Number> $s<T> {
17 pub const ORIGIN: Self = Self{$($f: T::ZERO),+};
18
19 #[inline]
20 #[must_use]
21 pub const fn new($($f: T),+) -> Self {
22 Self{$($f),+}
23 }
24
25 #[inline]
27 #[must_use]
28 pub const fn splat(v: T) -> Self {
29 Self{$($f: v),+}
30 }
31
32 #[inline]
34 #[must_use]
35 pub fn map<O: Number>(self, mut f: impl FnMut(T) -> O) -> $s<O> {
36 $s{$($f: f(self.$f)),+}
37 }
38
39 #[inline]
41 #[must_use]
42 pub fn cast<O: Number + From<T>>(self) -> $s<O> {
43 self.map(O::from)
44 }
45
46 #[inline]
48 #[must_use]
49 pub fn manhattan_distance(self) -> T::Unsigned
50 where
51 T: Integer
52 {
53 T::Unsigned::ZERO $(+ self.$f.unsigned_abs())+
54 }
55
56 #[inline]
58 #[must_use]
59 pub fn manhattan_distance_to(self, rhs: Self) -> T::Unsigned
60 where
61 T: Integer
62 {
63 T::Unsigned::ZERO $(+ self.$f.abs_diff(rhs.$f))+
64 }
65
66 #[inline]
68 #[must_use]
69 pub fn manhattan_distance_to_aabb(self, min: Self, max: Self) -> T::Unsigned
70 where
71 T: Integer
72 {
73 T::Unsigned::ZERO $(
74 + min.$f.saturating_sub_0(self.$f)
75 + self.$f.saturating_sub_0(max.$f)
76 )+
77 }
78
79 #[inline]
81 #[must_use]
82 pub fn squared_euclidean_distance_to(self, rhs: Self) -> T {
83 T::ZERO $(+ self.$f.squared_diff(rhs.$f))+
84 }
85
86 #[inline]
90 #[must_use]
91 pub fn wrapping_add_signed(self, rhs: $s<T::Signed>) -> Self
92 where
93 T: UnsignedInteger,
94 {
95 Self{
96 $($f: self.$f.wrapping_add_signed(rhs.$f),)+
97 }
98 }
99
100 #[inline]
102 #[must_use]
103 pub fn component_min(self, rhs: Self) -> Self
104 where
105 T: Ord,
106 {
107 Self{
108 $($f: self.$f.min(rhs.$f),)+
109 }
110 }
111
112
113 #[inline]
115 #[must_use]
116 pub fn component_max(self, rhs: Self) -> Self
117 where
118 T: Ord,
119 {
120 Self{
121 $($f: self.$f.max(rhs.$f),)+
122 }
123 }
124 }
125
126 impl<T: Number> Add for $s<T> {
127 type Output = Self;
128
129 #[inline]
130 fn add(self, rhs: Self) -> Self {
131 Self{
132 $($f: self.$f + rhs.$f,)+
133 }
134 }
135 }
136
137 impl<T: Number> AddAssign for $s<T> {
138 #[inline]
139 fn add_assign(&mut self, rhs: Self) {
140 $(self.$f += rhs.$f;)+
141 }
142 }
143
144 impl<T: Number> Div<T> for $s<T> {
145 type Output = Self;
146
147 #[inline]
148 fn div(self, rhs: T) -> Self {
149 Self{
150 $($f: self.$f / rhs,)+
151 }
152 }
153 }
154
155 impl<T: Number> DivAssign<T> for $s<T> {
156 #[inline]
157 fn div_assign(&mut self, rhs: T) {
158 $(self.$f /= rhs;)+
159 }
160 }
161
162 impl<T: Number> Mul<T> for $s<T> {
163 type Output = Self;
164
165 #[inline]
166 fn mul(self, rhs: T) -> Self {
167 Self{
168 $($f: self.$f * rhs,)+
169 }
170 }
171 }
172
173 impl<T: Number> MulAssign<T> for $s<T> {
174 #[inline]
175 fn mul_assign(&mut self, rhs: T) {
176 $(self.$f *= rhs;)+
177 }
178 }
179
180 impl<T: Number> Sub for $s<T> {
181 type Output = Self;
182
183 #[inline]
184 fn sub(self, rhs: Self) -> Self {
185 Self{
186 $($f: self.$f - rhs.$f,)+
187 }
188 }
189 }
190
191 impl<T: Number> SubAssign for $s<T> {
192 #[inline]
193 fn sub_assign(&mut self, rhs: Self) {
194 $(self.$f -= rhs.$f;)+
195 }
196 }
197
198 impl<T: Signed> Neg for $s<T> {
199 type Output = Self;
200
201 #[inline]
202 fn neg(self) -> Self {
203 Self{
204 $($f: -self.$f,)+
205 }
206 }
207 }
208
209 impl<T: Number> From<[T; $n]> for $s<T> {
210 #[inline]
211 fn from(arr: [T; $n]) -> Self {
212 Self{$(
213 $f: arr[$i],
214 )+}
215 }
216 }
217
218 impl<T: Number> From<$tuple> for $s<T> {
219 #[inline]
220 fn from(arr: $tuple) -> Self {
221 Self{$(
222 $f: arr.$i,
223 )+}
224 }
225 }
226
227 impl<T: Number> From<$s<T>> for [T; $n] {
228 #[inline]
229 fn from(value: $s<T>) -> Self {
230 [$(value.$f),+]
231 }
232 }
233
234 impl<T: Number> From<$s<T>> for $tuple {
235 #[inline]
236 fn from(value: $s<T>) -> Self {
237 ($(value.$f),+)
238 }
239 }
240
241 vec_impl!(@widen $s{$($f),+},
242 u8 => [u16, u32, u64, u128, i16, i32, i64, i128, f32, f64],
243 u16 => [u32, u64, u128, i32, i64, i128, f32, f64],
244 u32 => [u64, u128, i64, i128, f64],
245 u64 => [u128, i128],
246 i8 => [i16, i32, i64, i128, f32, f64],
247 i16 => [i32, i64, i128, f32, f64],
248 i32 => [i64, i128, f64],
249 i64 => [i128],
250 );
251 };
252 (@widen $s:ident{$($f:ident),+}, $($from:ident => [$($to:ident),+],)+) => {$($(
253 impl From<$s<$from>> for $s<$to> {
254 #[inline(always)]
255 fn from(value: $s<$from>) -> Self {
256 value.cast()
257 }
258 }
259 )+)+};
260}
261
262vec_impl! {2, (T, T) =>
263 #[doc(alias("Vector", "Vector2", "Point", "Point2", "Point2D"))]
265 pub struct Vec2{0 => x, 1 => y}
266}
267
268impl<T: Signed> Vec2<T> {
269 pub const UP: Self = Self {
270 x: T::ZERO,
271 y: T::ONE,
272 };
273 pub const RIGHT: Self = Self {
274 x: T::ONE,
275 y: T::ZERO,
276 };
277 pub const DOWN: Self = Self {
278 x: T::ZERO,
279 y: T::MINUS_ONE,
280 };
281 pub const LEFT: Self = Self {
282 x: T::MINUS_ONE,
283 y: T::ZERO,
284 };
285 pub const DIRECTIONS: [Self; 4] = [Self::UP, Self::RIGHT, Self::DOWN, Self::LEFT];
286
287 #[inline]
289 #[must_use]
290 pub fn turn_right(self) -> Self {
291 Self {
292 x: self.y,
293 y: -self.x,
294 }
295 }
296
297 #[inline]
299 #[must_use]
300 pub fn turn_left(self) -> Self {
301 Self {
302 x: -self.y,
303 y: self.x,
304 }
305 }
306}
307
308vec_impl! {3, (T, T, T) =>
309 #[doc(alias("Vector3", "Point3", "Point3D"))]
311 pub struct Vec3{0 => x, 1 => y, 2 => z}
312}
313
314vec_impl! {4, (T, T, T, T) =>
315 #[doc(alias("Vector4", "Point4", "Point4D"))]
317 pub struct Vec4{0 => x, 1 => y, 2 => z, 3 => w}
318}
319
320#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
322#[repr(u8)]
323pub enum Direction {
324 #[default]
325 Up = 0,
326 Right,
327 Down,
328 Left,
329}
330
331impl Direction {
332 #[inline]
334 #[must_use]
335 pub fn turn(self, turn: Turn) -> Self {
336 Self::from((self as u8).wrapping_add_signed(turn as i8))
337 }
338
339 #[inline]
341 #[must_use]
342 pub fn turn_left(self) -> Self {
343 self.turn(Turn::Left)
344 }
345
346 #[inline]
348 #[must_use]
349 pub fn turn_right(self) -> Self {
350 self.turn(Turn::Right)
351 }
352}
353
354impl From<u8> for Direction {
355 #[inline]
356 fn from(value: u8) -> Self {
357 match value % 4 {
358 0 => Direction::Up,
359 1 => Direction::Right,
360 2 => Direction::Down,
361 3 => Direction::Left,
362 _ => unreachable!(),
363 }
364 }
365}
366
367impl Not for Direction {
368 type Output = Self;
369
370 #[inline]
371 fn not(self) -> Self::Output {
372 Self::from((self as u8).wrapping_add(2))
373 }
374}
375
376impl<T: Signed> From<Direction> for Vec2<T> {
377 #[inline]
378 fn from(value: Direction) -> Self {
379 Vec2::DIRECTIONS[value as usize]
380 }
381}
382
383impl<T: Signed> Add<Direction> for Vec2<T> {
384 type Output = Self;
385
386 #[inline]
387 fn add(self, rhs: Direction) -> Self::Output {
388 self + Vec2::from(rhs)
389 }
390}
391
392impl<T: Signed> Sub<Direction> for Vec2<T> {
393 type Output = Self;
394
395 #[inline]
396 fn sub(self, rhs: Direction) -> Self::Output {
397 self - Vec2::from(rhs)
398 }
399}
400
401#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
403#[repr(i8)]
404pub enum Turn {
405 #[doc(alias("Anticlockwise"))]
406 Left = -1,
407 #[doc(alias("Straight"))]
408 #[default]
409 None = 0,
410 #[doc(alias("Clockwise"))]
411 Right = 1,
412}