1use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
2
3#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6#[cfg_attr(feature = "bytemuck", derive(bytemuck::AnyBitPattern))]
7#[repr(C)]
8pub struct Point<T> {
9 pub x: T,
11 pub y: T,
13}
14
15#[cfg(feature = "bytemuck")]
33unsafe impl<T> bytemuck::NoUninit for Point<T> where T: bytemuck::NoUninit {}
34
35impl<T> Point<T> {
36 #[inline(always)]
38 pub const fn new(x: T, y: T) -> Self {
39 Self { x, y }
40 }
41
42 pub const fn broadcast(xy: T) -> Self
44 where
45 T: Copy,
46 {
47 Self { x: xy, y: xy }
48 }
49
50 #[inline(always)]
52 pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> Point<U> {
53 Point {
54 x: f(self.x),
55 y: f(self.y),
56 }
57 }
58}
59
60impl<T> Add for Point<T>
61where
62 T: Add<Output = T>,
63{
64 type Output = Self;
65
66 #[inline(always)]
67 fn add(self, rhs: Self) -> Self::Output {
68 Self {
69 x: self.x + rhs.x,
70 y: self.y + rhs.y,
71 }
72 }
73}
74
75impl<T> AddAssign for Point<T>
76where
77 T: AddAssign,
78{
79 #[inline(always)]
80 fn add_assign(&mut self, rhs: Self) {
81 self.x += rhs.x;
82 self.y += rhs.y;
83 }
84}
85
86impl<T> Sub for Point<T>
87where
88 T: Sub<Output = T>,
89{
90 type Output = Self;
91
92 #[inline(always)]
93 fn sub(self, rhs: Self) -> Self::Output {
94 Self {
95 x: self.x - rhs.x,
96 y: self.y - rhs.y,
97 }
98 }
99}
100
101impl<T> SubAssign for Point<T>
102where
103 T: SubAssign,
104{
105 #[inline(always)]
106 fn sub_assign(&mut self, rhs: Self) {
107 self.x -= rhs.x;
108 self.y -= rhs.y;
109 }
110}
111
112impl<T> Mul for Point<T>
113where
114 T: Mul<Output = T>,
115{
116 type Output = Self;
117
118 #[inline(always)]
119 fn mul(self, rhs: Self) -> Self::Output {
120 Self {
121 x: self.x * rhs.x,
122 y: self.y * rhs.y,
123 }
124 }
125}
126
127impl<T> Mul<T> for Point<T>
128where
129 T: Mul<Output = T> + Copy,
130{
131 type Output = Self;
132
133 #[inline(always)]
134 fn mul(self, rhs: T) -> Self::Output {
135 Self {
136 x: self.x * rhs,
137 y: self.y * rhs,
138 }
139 }
140}
141
142impl<T> MulAssign for Point<T>
143where
144 T: MulAssign,
145{
146 #[inline(always)]
147 fn mul_assign(&mut self, rhs: Self) {
148 self.x *= rhs.x;
149 self.y *= rhs.y;
150 }
151}
152
153impl<T> MulAssign<T> for Point<T>
154where
155 T: MulAssign + Copy,
156{
157 #[inline(always)]
158 fn mul_assign(&mut self, rhs: T) {
159 self.x *= rhs;
160 self.y *= rhs;
161 }
162}
163
164impl<T> Div for Point<T>
165where
166 T: Div<Output = T>,
167{
168 type Output = Self;
169
170 #[inline(always)]
171 fn div(self, rhs: Self) -> Self::Output {
172 Self {
173 x: self.x / rhs.x,
174 y: self.y / rhs.y,
175 }
176 }
177}
178
179impl<T> Div<T> for Point<T>
180where
181 T: Div<Output = T> + Copy,
182{
183 type Output = Self;
184
185 #[inline(always)]
186 fn div(self, rhs: T) -> Self::Output {
187 Self {
188 x: self.x / rhs,
189 y: self.y / rhs,
190 }
191 }
192}
193
194impl<T> DivAssign for Point<T>
195where
196 T: DivAssign,
197{
198 #[inline(always)]
199 fn div_assign(&mut self, rhs: Self) {
200 self.x /= rhs.x;
201 self.y /= rhs.y;
202 }
203}
204
205impl<T> DivAssign<T> for Point<T>
206where
207 T: DivAssign + Copy,
208{
209 #[inline(always)]
210 fn div_assign(&mut self, rhs: T) {
211 self.x /= rhs;
212 self.y /= rhs;
213 }
214}
215
216impl<T> Neg for Point<T>
217where
218 T: Neg<Output = T>,
219{
220 type Output = Self;
221
222 #[inline(always)]
223 fn neg(self) -> Self::Output {
224 Self {
225 x: -self.x,
226 y: -self.y,
227 }
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::Point;
234 use crate::F26Dot6;
235
236 #[test]
237 fn map() {
238 assert_eq!(
239 Point::new(42.5, 20.1).map(F26Dot6::from_f64),
240 Point::new(F26Dot6::from_f64(42.5), F26Dot6::from_f64(20.1))
241 );
242 }
243
244 #[test]
245 fn add() {
246 assert_eq!(Point::new(1, 2) + Point::new(3, 4), Point::new(4, 6));
247 let mut point = Point::new(1, 2);
248 point += Point::new(3, 4);
249 assert_eq!(point, Point::new(4, 6));
250 }
251
252 #[test]
253 fn sub() {
254 assert_eq!(Point::new(1, 2) - Point::new(3, 4), Point::new(-2, -2));
255 let mut point = Point::new(1, 2);
256 point -= Point::new(3, 4);
257 assert_eq!(point, Point::new(-2, -2));
258 }
259
260 #[test]
261 fn mul() {
262 assert_eq!(Point::new(1, 2) * Point::new(3, 4), Point::new(3, 8));
263 let mut point = Point::new(1, 2);
264 point *= Point::new(3, 4);
265 assert_eq!(point, Point::new(3, 8));
266 assert_eq!(Point::new(1, 2) * 8, Point::new(8, 16));
267 }
268
269 #[test]
270 fn div() {
271 assert_eq!(Point::new(10, 16) / Point::new(2, 3), Point::new(5, 5));
272 let mut point = Point::new(10, 16);
273 point /= Point::new(2, 3);
274 assert_eq!(point, Point::new(5, 5));
275 assert_eq!(Point::new(10, 16) / 2, Point::new(5, 8));
276 }
277
278 #[test]
279 fn neg() {
280 assert_eq!(-Point::new(1, -2), Point::new(-1, 2));
281 }
282}