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