1use crate::number::{Integer, Number, Signed, UnsignedInteger};
4use std::fmt::Debug;
5use std::ops::{Add, AddAssign, Mul, MulAssign, 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> Mul<T> for $s<T> {
145 type Output = Self;
146
147 #[inline]
148 fn mul(self, rhs: T) -> Self {
149 Self{
150 $($f: self.$f * rhs,)+
151 }
152 }
153 }
154
155 impl<T: Number> MulAssign<T> for $s<T> {
156 #[inline]
157 fn mul_assign(&mut self, rhs: T) {
158 $(self.$f *= rhs;)+
159 }
160 }
161
162 impl<T: Number> Sub for $s<T> {
163 type Output = Self;
164
165 #[inline]
166 fn sub(self, rhs: Self) -> Self {
167 Self{
168 $($f: self.$f - rhs.$f,)+
169 }
170 }
171 }
172
173 impl<T: Number> SubAssign for $s<T> {
174 #[inline]
175 fn sub_assign(&mut self, rhs: Self) {
176 $(self.$f -= rhs.$f;)+
177 }
178 }
179
180 impl<T: Number> From<[T; $n]> for $s<T> {
181 #[inline]
182 fn from(arr: [T; $n]) -> Self {
183 Self{$(
184 $f: arr[$i],
185 )+}
186 }
187 }
188
189 impl<T: Number> From<$tuple> for $s<T> {
190 #[inline]
191 fn from(arr: $tuple) -> Self {
192 Self{$(
193 $f: arr.$i,
194 )+}
195 }
196 }
197
198 impl<T: Number> From<$s<T>> for [T; $n] {
199 #[inline]
200 fn from(value: $s<T>) -> Self {
201 [$(value.$f),+]
202 }
203 }
204
205 impl<T: Number> From<$s<T>> for $tuple {
206 #[inline]
207 fn from(value: $s<T>) -> Self {
208 ($(value.$f),+)
209 }
210 }
211
212 vec_impl!(@widen $s{$($f),+},
213 u8 => [u16, u32, u64, u128, i16, i32, i64, i128, f32, f64],
214 u16 => [u32, u64, u128, i32, i64, i128, f32, f64],
215 u32 => [u64, u128, i64, i128, f64],
216 u64 => [u128, i128],
217 i8 => [i16, i32, i64, i128, f32, f64],
218 i16 => [i32, i64, i128, f32, f64],
219 i32 => [i64, i128, f64],
220 i64 => [i128],
221 );
222 };
223 (@widen $s:ident{$($f:ident),+}, $($from:ident => [$($to:ident),+],)+) => {$($(
224 impl From<$s<$from>> for $s<$to> {
225 #[inline(always)]
226 fn from(value: $s<$from>) -> Self {
227 value.cast()
228 }
229 }
230 )+)+};
231}
232
233vec_impl! {2, (T, T) =>
234 #[doc(alias("Vector", "Vector2", "Point", "Point2", "Point2D"))]
236 pub struct Vec2{0 => x, 1 => y}
237}
238
239impl<T: Signed> Vec2<T> {
240 pub const UP: Self = Self {
241 x: T::ZERO,
242 y: T::ONE,
243 };
244 pub const RIGHT: Self = Self {
245 x: T::ONE,
246 y: T::ZERO,
247 };
248 pub const DOWN: Self = Self {
249 x: T::ZERO,
250 y: T::MINUS_ONE,
251 };
252 pub const LEFT: Self = Self {
253 x: T::MINUS_ONE,
254 y: T::ZERO,
255 };
256 pub const DIRECTIONS: [Self; 4] = [Self::UP, Self::RIGHT, Self::DOWN, Self::LEFT];
257
258 #[inline]
260 #[must_use]
261 pub fn turn_right(self) -> Self {
262 Self {
263 x: self.y,
264 y: -self.x,
265 }
266 }
267
268 #[inline]
270 #[must_use]
271 pub fn turn_left(self) -> Self {
272 Self {
273 x: -self.y,
274 y: self.x,
275 }
276 }
277}
278
279vec_impl! {3, (T, T, T) =>
280 #[doc(alias("Vector3", "Point3", "Point3D"))]
282 pub struct Vec3{0 => x, 1 => y, 2 => z}
283}
284
285vec_impl! {4, (T, T, T, T) =>
286 #[doc(alias("Vector4", "Point4", "Point4D"))]
288 pub struct Vec4{0 => x, 1 => y, 2 => z, 3 => w}
289}
290
291#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
293#[repr(u8)]
294pub enum Direction {
295 #[default]
296 Up = 0,
297 Right,
298 Down,
299 Left,
300}
301
302impl Direction {
303 #[inline]
305 #[must_use]
306 pub fn turn(self, turn: Turn) -> Self {
307 Self::from((self as u8).wrapping_add_signed(turn as i8))
308 }
309
310 #[inline]
312 #[must_use]
313 pub fn turn_left(self) -> Self {
314 self.turn(Turn::Left)
315 }
316
317 #[inline]
319 #[must_use]
320 pub fn turn_right(self) -> Self {
321 self.turn(Turn::Right)
322 }
323}
324
325impl From<u8> for Direction {
326 #[inline]
327 fn from(value: u8) -> Self {
328 match value % 4 {
329 0 => Direction::Up,
330 1 => Direction::Right,
331 2 => Direction::Down,
332 3 => Direction::Left,
333 _ => unreachable!(),
334 }
335 }
336}
337
338impl Not for Direction {
339 type Output = Self;
340
341 #[inline]
342 fn not(self) -> Self::Output {
343 Self::from((self as u8).wrapping_add(2))
344 }
345}
346
347impl<T: Signed> From<Direction> for Vec2<T> {
348 #[inline]
349 fn from(value: Direction) -> Self {
350 Vec2::DIRECTIONS[value as usize]
351 }
352}
353
354impl<T: Signed> Add<Direction> for Vec2<T> {
355 type Output = Self;
356
357 #[inline]
358 fn add(self, rhs: Direction) -> Self::Output {
359 self + Vec2::from(rhs)
360 }
361}
362
363impl<T: Signed> Sub<Direction> for Vec2<T> {
364 type Output = Self;
365
366 #[inline]
367 fn sub(self, rhs: Direction) -> Self::Output {
368 self - Vec2::from(rhs)
369 }
370}
371
372#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
374#[repr(i8)]
375pub enum Turn {
376 #[doc(alias("Anticlockwise"))]
377 Left = -1,
378 #[doc(alias("Straight"))]
379 #[default]
380 None = 0,
381 #[doc(alias("Clockwise"))]
382 Right = 1,
383}