math_utils/
fixed.rs

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