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