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> MinMax for fixed::$fixed <U> where U : Unsigned + $fixed_sqrt_bound {
182 fn min (self, other : Self) -> Self {
183 Ord::min (self, other)
184 }
185 fn max (self, other : Self) -> Self {
186 Ord::max (self, other)
187 }
188 fn clamp (self, min : Self, max : Self) -> Self {
189 Ord::clamp (self, min, max)
190 }
191 }
192 impl <U> Sqrt for fixed::$fixed <U> where U : $fixed_sqrt_bound {
193 fn sqrt (self) -> Self {
194 fixed_sqrt::FastSqrt::fast_sqrt (self)
195 }
196 }
197 impl <U> Exp for fixed::$fixed <U> where
198 U : 'static + Unsigned + IsLessOrEqual<$cordic_bound_3, Output = True> +
199 IsLessOrEqual<$cordic_bound_2, Output = True> +
200 IsLessOrEqual<$cordic_bound_1, Output = True>
201 {
202 fn exp (self) -> Self {
203 cordic::exp (self)
204 }
205 }
206 impl <U> Powi for fixed::$fixed <U> where
207 U : Unsigned + IsLessOrEqual<$cordic_bound_2, Output = True> + $fixed_sqrt_bound
208 {
209 fn powi (self, _n : i32) -> Self {
210 unimplemented!("TODO: fixed integer powers")
211 }
212 }
213 impl <U> Powf for fixed::$fixed <U> where
214 U : Unsigned + IsLessOrEqual<$cordic_bound_2, Output = True> + $fixed_sqrt_bound
215 {
216 fn powf (self, _n : Self) -> Self {
217 unimplemented!("TODO: fixed fractional powers")
218 }
219 }
220
221 impl <U> Trig for fixed::$fixed <U> where
222 U : 'static + Unsigned + IsLessOrEqual<$cordic_bound_3, Output = True> +
223 IsLessOrEqual<$cordic_bound_2, Output = True> +
224 IsLessOrEqual<$cordic_bound_1, Output = True>
225 {
226 fn sin (self) -> Self {
227 cordic::sin (self)
228 }
229 fn sin_cos (self) -> (Self, Self) {
230 cordic::sin_cos (self)
231 }
232 fn cos (self) -> Self {
233 cordic::cos (self)
234 }
235 fn tan (self) -> Self {
236 cordic::tan (self)
237 }
238 fn asin (self) -> Self {
239 cordic::asin (self)
240 }
241 fn acos (self) -> Self {
242 cordic::acos (self)
243 }
244 fn atan (self) -> Self {
245 cordic::atan (self)
246 }
247 fn atan2 (self, other : Self) -> Self {
248 cordic::atan2 (self, other)
249 }
250 }
251}
252
253impl_real_fixed!(FixedI8, U5, U6, U8, fixed_sqrt::traits::LtU8);
254impl_real_fixed!(FixedI16, U13, U14, U16, fixed_sqrt::traits::LtU16);
255impl_real_fixed!(FixedI32, U29, U30, U32, fixed_sqrt::traits::LtU32);
256impl_real_fixed!(FixedI64, U61, U62, U64, fixed_sqrt::traits::LtU64);