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 manhattan_distance(self) -> T::Unsigned
36 where
37 T: Integer
38 {
39 T::Unsigned::ZERO $(+ self.$f.unsigned_abs())+
40 }
41
42 #[inline]
44 #[must_use]
45 pub fn manhattan_distance_to(self, rhs: Self) -> T::Unsigned
46 where
47 T: Integer
48 {
49 T::Unsigned::ZERO $(+ self.$f.abs_diff(rhs.$f))+
50 }
51
52 #[inline]
54 #[must_use]
55 pub fn manhattan_distance_to_aabb(self, min: Self, max: Self) -> T::Unsigned
56 where
57 T: Integer
58 {
59 T::Unsigned::ZERO $(
60 + min.$f.saturating_sub_0(self.$f)
61 + self.$f.saturating_sub_0(max.$f)
62 )+
63 }
64
65 #[inline]
69 #[must_use]
70 pub fn wrapping_add_signed(self, rhs: $s<T::Signed>) -> Self
71 where
72 T: UnsignedInteger,
73 {
74 Self{
75 $($f: self.$f.wrapping_add_signed(rhs.$f),)+
76 }
77 }
78 }
79
80 impl<T: Number> Add for $s<T> {
81 type Output = Self;
82
83 #[inline]
84 fn add(self, rhs: Self) -> Self {
85 Self{
86 $($f: self.$f + rhs.$f,)+
87 }
88 }
89 }
90
91 impl<T: Number> AddAssign for $s<T> {
92 #[inline]
93 fn add_assign(&mut self, rhs: Self) {
94 $(self.$f += rhs.$f;)+
95 }
96 }
97
98 impl<T: Number> Mul<T> for $s<T> {
99 type Output = Self;
100
101 #[inline]
102 fn mul(self, rhs: T) -> Self {
103 Self{
104 $($f: self.$f * rhs,)+
105 }
106 }
107 }
108
109 impl<T: Number> MulAssign<T> for $s<T> {
110 #[inline]
111 fn mul_assign(&mut self, rhs: T) {
112 $(self.$f *= rhs;)+
113 }
114 }
115
116 impl<T: Number> Sub for $s<T> {
117 type Output = Self;
118
119 #[inline]
120 fn sub(self, rhs: Self) -> Self {
121 Self{
122 $($f: self.$f - rhs.$f,)+
123 }
124 }
125 }
126
127 impl<T: Number> SubAssign for $s<T> {
128 #[inline]
129 fn sub_assign(&mut self, rhs: Self) {
130 $(self.$f -= rhs.$f;)+
131 }
132 }
133
134 impl<T: Number> From<[T; $n]> for $s<T> {
135 #[inline]
136 fn from(arr: [T; $n]) -> Self {
137 Self{$(
138 $f: arr[$i],
139 )+}
140 }
141 }
142
143 impl<T: Number> From<$tuple> for $s<T> {
144 #[inline]
145 fn from(arr: $tuple) -> Self {
146 Self{$(
147 $f: arr.$i,
148 )+}
149 }
150 }
151
152 impl<T: Number> From<$s<T>> for [T; $n] {
153 #[inline]
154 fn from(value: $s<T>) -> Self {
155 [$(value.$f),+]
156 }
157 }
158
159 impl<T: Number> From<$s<T>> for $tuple {
160 #[inline]
161 fn from(value: $s<T>) -> Self {
162 ($(value.$f),+)
163 }
164 }
165 };
166}
167
168vec_impl! {2, (T, T) =>
169 #[doc(alias("Vector", "Vector2", "Point", "Point2", "Point2D"))]
171 pub struct Vec2{0 => x, 1 => y}
172}
173
174impl<T: Signed> Vec2<T> {
175 pub const UP: Self = Self {
176 x: T::ZERO,
177 y: T::ONE,
178 };
179 pub const RIGHT: Self = Self {
180 x: T::ONE,
181 y: T::ZERO,
182 };
183 pub const DOWN: Self = Self {
184 x: T::ZERO,
185 y: T::MINUS_ONE,
186 };
187 pub const LEFT: Self = Self {
188 x: T::MINUS_ONE,
189 y: T::ZERO,
190 };
191 pub const DIRECTIONS: [Self; 4] = [Self::UP, Self::RIGHT, Self::DOWN, Self::LEFT];
192
193 #[inline]
195 #[must_use]
196 pub fn turn_right(self) -> Self {
197 Self {
198 x: self.y,
199 y: -self.x,
200 }
201 }
202
203 #[inline]
205 #[must_use]
206 pub fn turn_left(self) -> Self {
207 Self {
208 x: -self.y,
209 y: self.x,
210 }
211 }
212}
213
214vec_impl! {3, (T, T, T) =>
215 #[doc(alias("Vector3", "Point3", "Point3D"))]
217 pub struct Vec3{0 => x, 1 => y, 2 => z}
218}
219
220vec_impl! {4, (T, T, T, T) =>
221 #[doc(alias("Vector4", "Point4", "Point4D"))]
223 pub struct Vec4{0 => x, 1 => y, 2 => z, 3 => w}
224}
225
226#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
228#[repr(u8)]
229pub enum Direction {
230 #[default]
231 Up = 0,
232 Right,
233 Down,
234 Left,
235}
236
237impl Direction {
238 #[inline]
240 #[must_use]
241 pub fn turn(self, turn: Turn) -> Self {
242 Self::from((self as u8).wrapping_add_signed(turn as i8))
243 }
244
245 #[inline]
247 #[must_use]
248 pub fn turn_left(self) -> Self {
249 self.turn(Turn::Left)
250 }
251
252 #[inline]
254 #[must_use]
255 pub fn turn_right(self) -> Self {
256 self.turn(Turn::Right)
257 }
258}
259
260impl From<u8> for Direction {
261 #[inline]
262 fn from(value: u8) -> Self {
263 match value % 4 {
264 0 => Direction::Up,
265 1 => Direction::Right,
266 2 => Direction::Down,
267 3 => Direction::Left,
268 _ => unreachable!(),
269 }
270 }
271}
272
273impl Not for Direction {
274 type Output = Self;
275
276 #[inline]
277 fn not(self) -> Self::Output {
278 Self::from((self as u8).wrapping_add(2))
279 }
280}
281
282impl<T: Signed> From<Direction> for Vec2<T> {
283 #[inline]
284 fn from(value: Direction) -> Self {
285 Vec2::DIRECTIONS[value as usize]
286 }
287}
288
289impl<T: Signed> Add<Direction> for Vec2<T> {
290 type Output = Self;
291
292 #[inline]
293 fn add(self, rhs: Direction) -> Self::Output {
294 self + Vec2::from(rhs)
295 }
296}
297
298impl<T: Signed> Sub<Direction> for Vec2<T> {
299 type Output = Self;
300
301 #[inline]
302 fn sub(self, rhs: Direction) -> Self::Output {
303 self - Vec2::from(rhs)
304 }
305}
306
307#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
309#[repr(i8)]
310pub enum Turn {
311 #[doc(alias("Anticlockwise"))]
312 Left = -1,
313 #[doc(alias("Straight"))]
314 #[default]
315 None = 0,
316 #[doc(alias("Clockwise"))]
317 Right = 1,
318}