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