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
220#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
222#[repr(u8)]
223pub enum Direction {
224 #[default]
225 Up = 0,
226 Right,
227 Down,
228 Left,
229}
230
231impl Direction {
232 #[inline]
234 #[must_use]
235 pub fn turn(self, turn: Turn) -> Self {
236 Self::from((self as u8).wrapping_add_signed(turn as i8))
237 }
238
239 #[inline]
241 #[must_use]
242 pub fn turn_left(self) -> Self {
243 self.turn(Turn::Left)
244 }
245
246 #[inline]
248 #[must_use]
249 pub fn turn_right(self) -> Self {
250 self.turn(Turn::Right)
251 }
252}
253
254impl From<u8> for Direction {
255 #[inline]
256 fn from(value: u8) -> Self {
257 match value % 4 {
258 0 => Direction::Up,
259 1 => Direction::Right,
260 2 => Direction::Down,
261 3 => Direction::Left,
262 _ => unreachable!(),
263 }
264 }
265}
266
267impl Not for Direction {
268 type Output = Self;
269
270 #[inline]
271 fn not(self) -> Self::Output {
272 Self::from((self as u8).wrapping_add(2))
273 }
274}
275
276impl<T: Signed> From<Direction> for Vec2<T> {
277 #[inline]
278 fn from(value: Direction) -> Self {
279 Vec2::DIRECTIONS[value as usize]
280 }
281}
282
283impl<T: Signed> Add<Direction> for Vec2<T> {
284 type Output = Self;
285
286 #[inline]
287 fn add(self, rhs: Direction) -> Self::Output {
288 self + Vec2::from(rhs)
289 }
290}
291
292impl<T: Signed> Sub<Direction> for Vec2<T> {
293 type Output = Self;
294
295 #[inline]
296 fn sub(self, rhs: Direction) -> Self::Output {
297 self - Vec2::from(rhs)
298 }
299}
300
301#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
303#[repr(i8)]
304pub enum Turn {
305 #[doc(alias("Anticlockwise"))]
306 Left = -1,
307 #[doc(alias("Straight"))]
308 #[default]
309 None = 0,
310 #[doc(alias("Clockwise"))]
311 Right = 1,
312}