math_utils/
fixed.rs

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);