1use fixed::traits::{Fixed, ToFixed};
2use fixed::types::extra::*;
3
4use crate::num_traits as num;
5use crate::traits::*;
6use crate::types::*;
7use crate::types::coordinate::*;
8
9macro_rules! impl_dimension {
10 (
11 $point:ident, $vector:ident, $matrix:ident,
12 $position:ident, $displacement:ident, $transform:ident,
13 $fixed_point:ident, $fixed_vector:ident, $fixed_matrix:ident,
14 $dimension:expr, $mat_dims:expr, [$($component:ident),+]
15 ) => {
16 #[doc = "Convert to fixed precision"]
17 #[doc = $dimension]
18 #[doc = "vector"]
19 pub trait $fixed_vector <S> {
20 fn from_num <N : ToFixed> (num : $vector <N>) -> Self;
21 fn wrapping_from_num <N : ToFixed> (num : $vector <N>) -> Self;
22 }
23 impl <S> $fixed_vector <S> for $vector <S> where S : Fixed {
24 fn from_num <N : ToFixed> (num : $vector <N>) -> Self {
25 $vector::new ($(num.$component.to_fixed()),+)
26 }
27 fn wrapping_from_num <N : ToFixed> (num : $vector <N>) -> Self {
28 $vector::new ($(num.$component.wrapping_to_fixed()),+)
29 }
30 }
31 impl <S, U> $fixed_vector <S> for $displacement <S, U> where S : Fixed {
32 fn from_num <N : ToFixed> (num : $vector <N>) -> Self {
33 $vector::from_num (num).into()
34 }
35 fn wrapping_from_num <N : ToFixed> (num : $vector <N>) -> Self {
36 $vector::wrapping_from_num (num).into()
37 }
38 }
39
40 #[doc = "Convert to fixed precision"]
41 #[doc = $dimension]
42 #[doc = "point"]
43 pub trait $fixed_point <S> {
44 fn from_num <N : ToFixed> (num : $point <N>) -> Self;
45 fn wrapping_from_num <N : ToFixed> (num : $point <N>) -> Self;
46 }
47 impl <S> $fixed_point <S> for $point <S> where S : Fixed {
48 fn from_num <N : ToFixed> (num : $point <N>) -> Self {
49 $vector::from_num (num.0).into()
50 }
51 fn wrapping_from_num <N : ToFixed> (num : $point <N>) -> Self {
52 $vector::wrapping_from_num (num.0).into()
53 }
54 }
55 impl <S, U> $fixed_point <S> for $position <S, U> where S : Fixed {
56 fn from_num <N : ToFixed> (num : $point <N>) -> Self {
57 $point::from_num (num).into()
58 }
59 fn wrapping_from_num <N : ToFixed> (num : $point <N>) -> Self {
60 $point::wrapping_from_num (num).into()
61 }
62 }
63
64 #[doc = "Convert to fixed precision"]
65 #[doc = $mat_dims]
66 #[doc = "matrix"]
67 pub trait $fixed_matrix <S> {
68 fn from_num <N : ToFixed> (num : $matrix <N>) -> Self;
69 fn wrapping_from_num <N : ToFixed> (num : $matrix <N>) -> Self;
70 }
71 impl <S> $fixed_matrix <S> for $matrix <S> where S : Fixed {
72 fn from_num <N : ToFixed> (num : $matrix <N>) -> Self {
73 $matrix {
74 cols: [
75 $($vector::from_num (num.cols.$component)),+
76 ].into()
77 }
78 }
79 fn wrapping_from_num <N : ToFixed> (num : $matrix <N>) -> Self {
80 $matrix {
81 cols: [
82 $($vector::wrapping_from_num (num.cols.$component)),+
83 ].into()
84 }
85 }
86 }
87 impl <S, U, V> $fixed_matrix <S> for $transform <S, U, V> where
88 S : Fixed + num::Zero + num::One
89 {
90 fn from_num <N : ToFixed> (num : $matrix <N>) -> Self {
91 $matrix::from_num (num).into()
92 }
93 fn wrapping_from_num <N : ToFixed> (num : $matrix <N>) -> Self {
94 $matrix::wrapping_from_num (num).into()
95 }
96 }
97 }
98}
99
100impl_dimension!(
101 Point2, Vector2, Matrix2,
102 Position2, Displacement2, Transform2,
103 FixedPoint2, FixedVector2, FixedMatrix2, "2D",
104 "2x2", [x, y]);
105impl_dimension!(
106 Point3, Vector3, Matrix3,
107 Position3, Displacement3, Transform3,
108 FixedPoint3, FixedVector3, FixedMatrix3, "3D",
109 "3x3", [x, y, z]);
110impl_dimension!(
111 Point4, Vector4, Matrix4,
112 Position4, Displacement4, Transform4,
113 FixedPoint4, FixedVector4, FixedMatrix4, "4D",
114 "4x4", [x, y, z, w]);
115
116macro impl_real_fixed ($fixed:ident,
117 $cordic_bound_1:ident, $cordic_bound_2:ident, $cordic_bound_3:ident,
118 $fixed_sqrt_bound:path
119) {
120 impl <U> VectorSpace <Self> for fixed::$fixed <U> where
121 U : Unsigned +
122 IsLessOrEqual<$cordic_bound_2, Output = True> +
123 IsLessOrEqual<$cordic_bound_1, Output = True> +
124 $fixed_sqrt_bound
125 {
126 fn map <F> (self, mut f : F) -> Self where F : FnMut (Self) -> Self {
127 f (self)
128 }
129 }
130 impl <U> Module <Self> for fixed::$fixed <U> where
131 U : Unsigned +
132 IsLessOrEqual<$cordic_bound_2, Output = True> +
133 IsLessOrEqual<$cordic_bound_1, Output = True> +
134 $fixed_sqrt_bound
135 {
136 type LinearEndo = Self;
137 }
138 impl <U> LinearMap <Self, Self, Self> for fixed::$fixed <U> where
139 U : Unsigned +
140 IsLessOrEqual<$cordic_bound_2, Output = True> +
141 IsLessOrEqual<$cordic_bound_1, Output = True> +
142 $fixed_sqrt_bound
143 {
144 fn determinant (self) -> Self {
145 self
146 }
147 fn transpose (self) -> Self {
148 self
149 }
150 }
151 impl <U> Real for fixed::$fixed <U> where
152 U : Unsigned +
153 IsLessOrEqual<$cordic_bound_2, Output = True> +
154 IsLessOrEqual<$cordic_bound_1, Output = True> +
155 $fixed_sqrt_bound
156 {
157 fn pi() -> Self {
158 Self::from_num (fixed::consts::PI)
159 }
160 fn frac_pi_3() -> Self {
161 Self::from_num (fixed::consts::FRAC_PI_3)
162 }
163 fn sqrt_3() -> Self {
164 Self::from_num (fixed::consts::SQRT_3)
165 }
166 fn frac_1_sqrt_3() -> Self {
167 Self::from_num (fixed::consts::FRAC_1_SQRT_3)
168 }
169 fn floor (self) -> Self {
170 self.floor()
171 }
172 fn ceil (self) -> Self {
173 self.ceil()
174 }
175 fn trunc (self) -> Self {
176 self.int()
177 }
178 fn fract (self) -> Self {
179 self.frac()
180 }
181 }
182 impl <U> Field for fixed::$fixed <U> where
183 U : Unsigned + IsLessOrEqual<$cordic_bound_2, Output = True> +
184 $fixed_sqrt_bound
185 { }
186 impl <U> Ring for fixed::$fixed <U> where
187 U : Unsigned + IsLessOrEqual<$cordic_bound_2, Output = True> +
188 $fixed_sqrt_bound
189 { }
190 impl <U> MultiplicativeGroup for fixed::$fixed <U> where
191 U : Unsigned + IsLessOrEqual<$cordic_bound_2, Output = True> +
192 $fixed_sqrt_bound
193 { }
194 impl <U> MultiplicativeMonoid for fixed::$fixed <U> where
195 U : Unsigned + IsLessOrEqual<$cordic_bound_2, Output = True> +
196 $fixed_sqrt_bound
197 { }
198 impl <U> AdditiveGroup for fixed::$fixed <U> where
199 U : Unsigned + $fixed_sqrt_bound
200 { }
201 impl <U> AdditiveMonoid for fixed::$fixed <U> where
202 U : Unsigned + $fixed_sqrt_bound
203 { }
204 impl <U> SignedExt for fixed::$fixed <U> where
205 U : Unsigned + $fixed_sqrt_bound +
206 IsLessOrEqual<$cordic_bound_2, Output = True>
207 { }
208 impl <U> MinMax for fixed::$fixed <U> where
209 U : Unsigned + $fixed_sqrt_bound
210 {
211 fn min (self, other : Self) -> Self {
212 Ord::min (self, other)
213 }
214 fn max (self, other : Self) -> Self {
215 Ord::max (self, other)
216 }
217 fn clamp (self, min : Self, max : Self) -> Self {
218 Ord::clamp (self, min, max)
219 }
220 }
221 impl <U> Sqrt for fixed::$fixed <U> where U : $fixed_sqrt_bound {
222 fn sqrt (self) -> Self {
223 fixed_sqrt::FastSqrt::fast_sqrt (self)
224 }
225 }
226 impl <U> Exp for fixed::$fixed <U> where
227 U : 'static + Unsigned + IsLessOrEqual<$cordic_bound_3, Output = True> +
228 IsLessOrEqual<$cordic_bound_2, Output = True> +
229 IsLessOrEqual<$cordic_bound_1, Output = True>
230 {
231 fn exp (self) -> Self {
232 cordic::exp (self)
233 }
234 }
235 impl <U> Powi for fixed::$fixed <U> where
236 U : Unsigned + IsLessOrEqual<$cordic_bound_2, Output = True> +
237 $fixed_sqrt_bound
238 {
239 fn powi (self, _n : i32) -> Self {
240 unimplemented!("TODO: fixed integer powers")
241 }
242 }
243 impl <U> Powf for fixed::$fixed <U> where
244 U : Unsigned + IsLessOrEqual<$cordic_bound_2, Output = True> +
245 $fixed_sqrt_bound
246 {
247 fn powf (self, _n : Self) -> Self {
248 unimplemented!("TODO: fixed fractional powers")
249 }
250 }
251
252 impl <U> Trig for fixed::$fixed <U> where
253 U : 'static + Unsigned + IsLessOrEqual<$cordic_bound_3, Output = True> +
254 IsLessOrEqual<$cordic_bound_2, Output = True> +
255 IsLessOrEqual<$cordic_bound_1, Output = True>
256 {
257 fn sin (self) -> Self {
258 cordic::sin (self)
259 }
260 fn sin_cos (self) -> (Self, Self) {
261 cordic::sin_cos (self)
262 }
263 fn cos (self) -> Self {
264 cordic::cos (self)
265 }
266 fn tan (self) -> Self {
267 cordic::tan (self)
268 }
269 fn asin (self) -> Self {
270 cordic::asin (self)
271 }
272 fn acos (self) -> Self {
273 cordic::acos (self)
274 }
275 fn atan (self) -> Self {
276 cordic::atan (self)
277 }
278 fn atan2 (self, other : Self) -> Self {
279 cordic::atan2 (self, other)
280 }
281 }
282}
283
284impl_real_fixed!(FixedI8, U5, U6, U8, fixed_sqrt::traits::LtU8);
285impl_real_fixed!(FixedI16, U13, U14, U16, fixed_sqrt::traits::LtU16);
286impl_real_fixed!(FixedI32, U29, U30, U32, fixed_sqrt::traits::LtU32);
287impl_real_fixed!(FixedI64, U61, U62, U64, fixed_sqrt::traits::LtU64);