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