1#![feature(associated_type_defaults)]
4
5use fixed::traits::{FixedSigned, FromFixed, ToFixed};
6pub use fixed_sqrt::FixedSqrt;
7
8#[allow(unused_macros)]
9macro_rules! show {
10 ($e:expr) => { println!("{}: {:?}", stringify!($e), $e); }
11}
12
13pub mod wrapped;
14
15pub trait Space2d : Sized {
16 type Scalar : FixedSqrt;
17 type Point : Point2d <Self::Scalar, Self> =
18 euclid::Point2D <Self::Scalar, Self>;
19 type Vector : Vector2d <Self::Scalar, Self> =
20 euclid::Vector2D <Self::Scalar, Self>;
21}
22
23pub trait Point2d <S : FixedSqrt, U> : Sized + Clone + Copy + Default {
24 fn new (x : S, y : S) -> Self;
26 fn map <F, T> (self, f : F) -> euclid::Point2D <T, U> where
27 F : FnMut (S) -> T;
28 fn origin() -> Self {
30 Self::default()
31 }
32 fn from_num <N : ToFixed> (num : euclid::Point2D <N, U>) -> Self {
33 Self::new (num.x.to_fixed(), num.y.to_fixed())
34 }
35 fn wrapping_from_num <N : ToFixed> (num : euclid::Point2D <N, U>) -> Self {
36 Self::new (num.x.wrapping_to_fixed(), num.y.wrapping_to_fixed())
37 }
38 fn from_bits (bits : euclid::Point2D <S::Bits, U>) -> Self {
39 Self::new (S::from_bits (bits.x), S::from_bits (bits.y))
40 }
41 fn to_num <N : FromFixed> (self) -> euclid::Point2D <N, U> {
42 self.map (S::to_num)
43 }
44 fn to_bits (self) -> euclid::Point2D <S::Bits, U> {
45 self.map (S::to_bits)
46 }
47}
48
49pub trait Vector2d <S : FixedSqrt, U> : Sized + Clone + Copy + Default {
50 fn new (x : S, y : S) -> Self;
52 fn map <F, T> (self, f : F) -> euclid::Vector2D <T, U> where
53 F : FnMut (S) -> T;
54 fn magnitude2 (self) -> Option <S>;
55 fn norm (self) -> Norm <S> where S : FixedSigned;
56 fn zero() -> Self {
58 Self::default()
59 }
60 fn from_num <N : ToFixed> (num : euclid::Vector2D <N, U>) -> Self {
61 Self::new (num.x.to_fixed(), num.y.to_fixed())
62 }
63 fn wrapping_from_num <N : ToFixed> (num : euclid::Vector2D <N, U>) -> Self {
64 Self::new (num.x.wrapping_to_fixed(), num.y.wrapping_to_fixed())
65 }
66 fn from_bits (bits : euclid::Vector2D <S::Bits, U>) -> Self {
67 Self::new (S::from_bits (bits.x), S::from_bits (bits.y))
68 }
69 fn to_num <N : FromFixed> (self) -> euclid::Vector2D <N, U> {
70 self.map (N::from_fixed)
71 }
72 fn to_bits (self) -> euclid::Vector2D <S::Bits, U> {
73 self.map (S::to_bits)
74 }
75 fn scale (self, s : S) -> Self {
76 let new = self.map (|x| x * s);
77 Self::new (new.x, new.y)
78 }
79 fn magnitude (self) -> Option <S> {
80 self.magnitude2().map (FixedSqrt::sqrt)
81 }
82 fn normalized (mut self) -> Self {
83 let magnitude = loop {
84 match self.magnitude() {
85 Some (s) => break s,
86 None => {
87 let new = self.map (|s| s >> 1);
88 self = Self::new (new.x, new.y);
89 }
90 }
91 };
92 let one = S::from_num (1usize);
94 self.scale (one / magnitude)
95 }
96}
97
98impl <S, U> Point2d <S, U> for euclid::Point2D <S, U> where S : FixedSqrt {
99 fn new (x : S, y : S) -> Self {
100 euclid::Point2D::new (x, y)
101 }
102 fn map <F, T> (self, mut f : F) -> euclid::Point2D <T, U> where
103 F : FnMut (S) -> T
104 {
105 euclid::Point2D::new (f (self.x), f (self.y))
106 }
107}
108
109impl <S, U> Vector2d <S, U> for euclid::Vector2D <S, U> where S : FixedSqrt {
110 fn new (x : S, y : S) -> Self {
111 euclid::Vector2D::new (x, y)
112 }
113 fn map <F, T> (self, mut f : F) -> euclid::Vector2D <T, U> where
114 F : FnMut (S) -> T
115 {
116 euclid::Vector2D::new (f (self.x), f (self.y))
117 }
118 fn magnitude2 (self) -> Option <S> {
119 let x2 = self.x.checked_mul (self.x)?;
120 let y2 = self.y.checked_mul (self.y)?;
121 x2.checked_add (y2)
122 }
123 fn norm (self) -> Norm <S> where S : FixedSigned {
124 if let Some (magnitude) = self.magnitude() {
125 return Norm::Euclidean (magnitude)
126 }
127 if let Some (sum) = self.x.checked_abs()
128 .and_then (|x| self.y.checked_abs().and_then (|y| x.checked_add (y)))
129 {
130 return Norm::Taxicab (sum)
131 }
132 Norm::Maximum (self.x.saturating_abs().max (self.y.saturating_abs()))
133 }
134}
135
136pub enum Norm <S> {
137 Euclidean (S),
139 Taxicab (S),
141 Maximum (S)
143}
144
145#[cfg(test)]
146mod tests {
147 use fixed;
148 use euclid;
149 use super::*;
150
151 #[test]
152 #[should_panic]
153 fn test_overflow() {
154 struct World;
155 impl Space2d for World {
156 type Scalar = fixed::types::I4F4;
157 type Point = euclid::Point2D <Self::Scalar, Self>;
158 type Vector = euclid::Vector2D <Self::Scalar, Self>;
159 }
160 type Scalar = <World as Space2d>::Scalar;
161 type Point = <World as Space2d>::Point;
162 let p = Point::new (Scalar::MIN, Scalar::MIN);
165 let q = Point::new (Scalar::MAX, Scalar::MAX);
166 show!(p);
167 show!(q);
168 show!(q - p);
169 show!(p - q);
170 }
171
172 #[test]
173 fn test_norm_positive() {
174 struct World;
175 impl Space2d for World {
176 type Scalar = fixed::types::I4F4;
177 type Point = euclid::Point2D <Self::Scalar, Self>;
178 type Vector = euclid::Vector2D <Self::Scalar, Self>;
179 }
180 type Scalar = <World as Space2d>::Scalar;
181 type Vector = <World as Space2d>::Vector;
183 let mut x = Scalar::MIN;
184 loop {
185 let mut y = Scalar::MIN;
186 loop {
187 let norm = match Vector::new (x, y).norm() {
188 Norm::Euclidean (n) => n,
189 Norm::Taxicab (n) => n,
190 Norm::Maximum (n) => n
191 };
192 show!(norm);
193 assert!(norm >= Scalar::from_bits (0));
194 if y == Scalar::MAX {
195 break
196 }
197 y += Scalar::from_bits (1);
198 }
199 if x == Scalar::MAX {
200 break
201 }
202 x += Scalar::from_bits (1);
203 }
204 }
205
206}