1use crate::number::{Integer, Number, Signed, UnsignedInteger};
4use std::fmt::Debug;
5use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
6
7macro_rules! point_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
148point_impl! {2, (T, T) =>
149 pub struct Point2D{0 => x, 1 => y}
151}
152
153impl<T: Signed> Point2D<T> {
154 pub const UP: Self = Self {
155 x: T::ZERO,
156 y: T::ONE,
157 };
158 pub const RIGHT: Self = Self {
159 x: T::ONE,
160 y: T::ZERO,
161 };
162 pub const DOWN: Self = Self {
163 x: T::ZERO,
164 y: T::MINUS_ONE,
165 };
166 pub const LEFT: Self = Self {
167 x: T::MINUS_ONE,
168 y: T::ZERO,
169 };
170
171 #[inline]
173 #[must_use]
174 pub fn turn_right(self) -> Self {
175 Self {
176 x: self.y,
177 y: -self.x,
178 }
179 }
180
181 #[inline]
183 #[must_use]
184 pub fn turn_left(self) -> Self {
185 Self {
186 x: -self.y,
187 y: self.x,
188 }
189 }
190}
191
192point_impl! {3, (T, T, T) =>
193 pub struct Point3D{0 => x, 1 => y, 2 => z}
195}