1use super::Vector2;
4#[cfg(any(test, feature = "std"))]
5#[cfg(test)]
6use core::hash;
7use core::ops::{Add, Neg, Sub};
8use num_traits::Num;
9
10#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Default)]
21pub struct Point<T> {
22 pub xcoord: T,
24 pub ycoord: T,
26}
27
28impl<T> Point<T> {
29 #[inline]
51 pub const fn new(xcoord: T, ycoord: T) -> Self {
52 Point { xcoord, ycoord }
53 }
54}
55
56macro_rules! forward_xf_xf_binop {
57 (impl $imp:ident, $method:ident) => {
58 impl<'a, 'b, T: Clone + Num> $imp<&'b Vector2<T>> for &'a Point<T> {
59 type Output = Point<T>;
60
61 #[inline]
62 fn $method(self, other: &Vector2<T>) -> Self::Output {
63 self.clone().$method(other.clone())
64 }
65 }
66 };
67}
68
69macro_rules! forward_xf_val_binop {
70 (impl $imp:ident, $method:ident) => {
71 impl<'a, T: Clone + Num> $imp<Vector2<T>> for &'a Point<T> {
72 type Output = Point<T>;
73
74 #[inline]
75 fn $method(self, other: Vector2<T>) -> Self::Output {
76 self.clone().$method(other)
77 }
78 }
79 };
80}
81
82macro_rules! forward_val_xf_binop {
83 (impl $imp:ident, $method:ident) => {
84 impl<'a, T: Clone + Num> $imp<&'a Vector2<T>> for Point<T> {
85 type Output = Point<T>;
86
87 #[inline]
88 fn $method(self, other: &Vector2<T>) -> Self::Output {
89 self.$method(other.clone())
90 }
91 }
92 };
93}
94
95macro_rules! forward_all_binop {
96 (impl $imp:ident, $method:ident) => {
97 forward_xf_xf_binop!(impl $imp, $method);
98 forward_xf_val_binop!(impl $imp, $method);
99 forward_val_xf_binop!(impl $imp, $method);
100 };
101}
102
103forward_all_binop!(impl Add, add);
105
106impl<T: Clone + Num> Add<Vector2<T>> for Point<T> {
108 type Output = Self;
109
110 #[inline]
126 fn add(self, other: Vector2<T>) -> Self::Output {
127 Self::Output::new(self.xcoord + other.x_, self.ycoord + other.y_)
128 }
129}
130
131forward_all_binop!(impl Sub, sub);
132
133impl<T: Clone + Num> Sub<Vector2<T>> for Point<T> {
135 type Output = Self;
136
137 #[inline]
153 fn sub(self, other: Vector2<T>) -> Self::Output {
154 Self::Output::new(self.xcoord - other.x_, self.ycoord - other.y_)
155 }
156}
157
158macro_rules! forward_xf_xf_binop2 {
159 (impl $imp:ident, $method:ident) => {
160 impl<'a, 'b, T: Clone + Num> $imp<&'b Point<T>> for &'a Point<T> {
161 type Output = Vector2<T>;
162
163 #[inline]
164 fn $method(self, other: &Point<T>) -> Self::Output {
165 self.clone().$method(other.clone())
166 }
167 }
168 };
169}
170
171macro_rules! forward_xf_val_binop2 {
172 (impl $imp:ident, $method:ident) => {
173 impl<'a, T: Clone + Num> $imp<Point<T>> for &'a Point<T> {
174 type Output = Vector2<T>;
175
176 #[inline]
177 fn $method(self, other: Point<T>) -> Self::Output {
178 self.clone().$method(other)
179 }
180 }
181 };
182}
183
184macro_rules! forward_val_xf_binop2 {
185 (impl $imp:ident, $method:ident) => {
186 impl<'a, T: Clone + Num> $imp<&'a Point<T>> for Point<T> {
187 type Output = Vector2<T>;
188
189 #[inline]
190 fn $method(self, other: &Point<T>) -> Self::Output {
191 self.$method(other.clone())
192 }
193 }
194 };
195}
196
197macro_rules! forward_all_binop2 {
198 (impl $imp:ident, $method:ident) => {
199 forward_xf_xf_binop2!(impl $imp, $method);
200 forward_xf_val_binop2!(impl $imp, $method);
201 forward_val_xf_binop2!(impl $imp, $method);
202 };
203}
204
205forward_all_binop2!(impl Sub, sub);
207
208impl<T: Clone + Num> Sub for Point<T> {
209 type Output = Vector2<T>;
210
211 #[inline]
230 fn sub(self, other: Self) -> Self::Output {
231 Self::Output::new(self.xcoord - other.xcoord, self.ycoord - other.ycoord)
232 }
233}
234
235mod opassign {
238 use core::ops::{AddAssign, SubAssign};
239
240 use num_traits::NumAssign;
241
242 use crate::Point;
243 use crate::Vector2;
244
245 impl<T: Clone + NumAssign> AddAssign<Vector2<T>> for Point<T> {
246 fn add_assign(&mut self, other: Vector2<T>) {
247 self.xcoord += other.x_;
248 self.ycoord += other.y_;
249 }
250 }
251
252 impl<T: Clone + NumAssign> SubAssign<Vector2<T>> for Point<T> {
253 fn sub_assign(&mut self, other: Vector2<T>) {
254 self.xcoord -= other.x_;
255 self.ycoord -= other.y_;
256 }
257 }
258
259 macro_rules! forward_op_assign {
260 (impl $imp:ident, $method:ident) => {
261 impl<'a, T: Clone + NumAssign> $imp<&'a Vector2<T>> for Point<T> {
262 #[inline]
263 fn $method(&mut self, other: &Vector2<T>) {
264 self.$method(other.clone())
265 }
266 }
267 };
268 }
269
270 forward_op_assign!(impl AddAssign, add_assign);
271 forward_op_assign!(impl SubAssign, sub_assign);
272}
273
274impl<T: Clone + Num + Neg<Output = T>> Neg for Point<T> {
275 type Output = Self;
276
277 #[inline]
287 fn neg(self) -> Self::Output {
288 Self::Output::new(-self.xcoord, -self.ycoord)
289 }
290}
291
292impl<'a, T: Clone + Num + Neg<Output = T>> Neg for &'a Point<T> {
293 type Output = Point<T>;
294
295 #[inline]
296 fn neg(self) -> Self::Output {
297 -self.clone()
298 }
299}
300
301#[cfg(test)]
302fn hash<T: hash::Hash>(x: &T) -> u64 {
303 use std::collections::hash_map::RandomState;
304 use std::hash::{BuildHasher, Hasher};
305 let mut hasher = <RandomState as BuildHasher>::Hasher::new();
306 x.hash(&mut hasher);
307 hasher.finish()
308}
309
310#[cfg(test)]
311mod test {
312 #![allow(non_upper_case_globals)]
313
314 use super::{hash, Point, Vector2};
315 use core::i32;
316
317 pub const _0_0p: Point<i32> = Point {
318 xcoord: 0,
319 ycoord: 0,
320 };
321 pub const _1_0p: Point<i32> = Point {
322 xcoord: 1,
323 ycoord: 0,
324 };
325 pub const _1_1p: Point<i32> = Point {
326 xcoord: 1,
327 ycoord: 1,
328 };
329 pub const _0_1p: Point<i32> = Point {
330 xcoord: 0,
331 ycoord: 1,
332 };
333 pub const _neg1_1p: Point<i32> = Point {
334 xcoord: -1,
335 ycoord: 1,
336 };
337 pub const _4_2p: Point<i32> = Point {
339 xcoord: 4,
340 ycoord: 2,
341 };
342
343 #[test]
344 fn test_consts() {
345 fn test(c: Point<i32>, r: i32, i: i32) {
347 assert_eq!(c, Point::new(r, i));
348 }
349 test(_0_0p, 0, 0);
350 test(_1_0p, 1, 0);
351 test(_1_1p, 1, 1);
352 test(_neg1_1p, -1, 1);
353 }
354
355 #[test]
356 fn test_hash() {
357 let a = Point::new(0i32, 0i32);
358 let b = Point::new(1i32, 0i32);
359 let c = Point::new(0i32, 1i32);
360 assert!(hash(&a) != hash(&b));
361 assert!(hash(&b) != hash(&c));
362 assert!(hash(&c) != hash(&a));
363 }
364
365 #[test]
366 fn test_add() {
367 let a = Point::new(0i32, 0i32);
368 let b = Point::new(1i32, 0i32);
369 let v = Vector2::new(5i32, 6i32);
370 assert_eq!(a, a + v - v);
371 assert_eq!(b, b - v + v);
372 }
373}