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 ($(#[$m:meta])* $v:vis struct $s:ident{$($f:ident),+}) => {
9 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
10 $(#[$m])* $v struct $s<T: Number> {
11 $(pub $f: T,)+
12 }
13
14 impl<T: Number> $s<T> {
15 pub const ORIGIN: Self = Self{$($f: T::ZERO),+};
16
17 #[inline]
18 #[must_use]
19 pub const fn new($($f: T),+) -> Self {
20 Self{$($f),+}
21 }
22
23 #[inline]
25 #[must_use]
26 pub fn manhattan_distance(self) -> T::Unsigned
27 where
28 T: Integer
29 {
30 T::Unsigned::ZERO $(+ self.$f.unsigned_abs())+
31 }
32
33 #[inline]
35 #[must_use]
36 pub fn manhattan_distance_from(self, rhs: Self) -> T::Unsigned
37 where
38 T: Integer
39 {
40 T::Unsigned::ZERO $(+ self.$f.abs_diff(rhs.$f))+
41 }
42
43 #[inline]
47 #[must_use]
48 pub fn wrapping_add_signed(self, rhs: $s<T::Signed>) -> Self
49 where
50 T: UnsignedInteger,
51 {
52 Self{
53 $($f: self.$f.wrapping_add_signed(rhs.$f),)+
54 }
55 }
56 }
57
58 impl<T: Number> Add for $s<T> {
59 type Output = Self;
60
61 #[inline]
62 fn add(self, rhs: Self) -> Self {
63 Self{
64 $($f: self.$f + rhs.$f,)+
65 }
66 }
67 }
68
69 impl<T: Number> AddAssign for $s<T> {
70 #[inline]
71 fn add_assign(&mut self, rhs: Self) {
72 $(self.$f += rhs.$f;)+
73 }
74 }
75
76 impl<T: Number> Mul<T> for $s<T> {
77 type Output = Self;
78
79 #[inline]
80 fn mul(self, rhs: T) -> Self {
81 Self{
82 $($f: self.$f * rhs,)+
83 }
84 }
85 }
86
87 impl<T: Number> MulAssign<T> for $s<T> {
88 #[inline]
89 fn mul_assign(&mut self, rhs: T) {
90 $(self.$f *= rhs;)+
91 }
92 }
93
94 impl<T: Number> Sub for $s<T> {
95 type Output = Self;
96
97 #[inline]
98 fn sub(self, rhs: Self) -> Self {
99 Self{
100 $($f: self.$f - rhs.$f,)+
101 }
102 }
103 }
104
105 impl<T: Number> SubAssign for $s<T> {
106 #[inline]
107 fn sub_assign(&mut self, rhs: Self) {
108 $(self.$f -= rhs.$f;)+
109 }
110 }
111 };
112}
113
114point_impl! {
115 pub struct Point2D{x, y}
117}
118
119impl<T: Signed> Point2D<T> {
120 pub const UP: Self = Self {
121 x: T::ZERO,
122 y: T::ONE,
123 };
124 pub const RIGHT: Self = Self {
125 x: T::ONE,
126 y: T::ZERO,
127 };
128 pub const DOWN: Self = Self {
129 x: T::ZERO,
130 y: T::MINUS_ONE,
131 };
132 pub const LEFT: Self = Self {
133 x: T::MINUS_ONE,
134 y: T::ZERO,
135 };
136
137 #[inline]
139 #[must_use]
140 pub fn turn_right(self) -> Self {
141 Self {
142 x: self.y,
143 y: -self.x,
144 }
145 }
146
147 #[inline]
149 #[must_use]
150 pub fn turn_left(self) -> Self {
151 Self {
152 x: -self.y,
153 y: self.x,
154 }
155 }
156}
157
158point_impl! {
159 pub struct Point3D{x, y, z}
161}