Skip to main content

geo_nd/
qarray.rs

1use std::ops::Deref;
2
3use num_traits::{ConstOne, ConstZero};
4
5use super::{Float, Quaternion, SqMatrix, SqMatrix3, SqMatrix4, Vector};
6use super::{quat, vector};
7
8//a QArray
9//tp QArray
10/// The [QArray] is a wrapper around a `D` sized array of [Float]s.
11///
12/// It provides implementations of the traits required for a [Vector]
13/// trait, hence it can be used for a [Vector] of any size `D`.
14#[derive(Clone, Copy, Debug, PartialEq)]
15#[repr(transparent)]
16pub struct QArray<F>
17where
18    F: Float,
19{
20    /// Data is stored i,j,k,r - so that the vector can be used [F;3] without alignment issues
21    data: [F; 4],
22}
23
24//a Macros to implement the traits
25//mi qarray_basic_traits!
26macro_rules! qarray_basic_traits {
27    { $f:ty, $ty:ty } => {
28
29        //ip Default for Qarray
30        impl std::default::Default for $ty {
31            fn default() -> Self {
32                [<$f>::ZERO,
33                 <$f>::ZERO,
34                 <$f>::ZERO,
35                 <$f>::ONE,
36                 ].into()
37            }
38        }
39
40        //ip Display for Qarray
41        impl std::fmt::Display for $ty {
42            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
43                vector::fmt(f, &self.data)
44            }
45        }
46    }
47}
48
49//mi qarray_mul_div_traits
50macro_rules! qarray_mul_div_traits {
51    { $f:ty, $ty:ty } => {
52        // Mul of  Self for Self
53        impl std::ops::Mul for $ty {
54            type Output = $ty;
55            fn mul(self, other: $ty) -> $ty {
56                quat::multiply(self.deref(), other.deref()).into()
57            }
58        }
59
60        // Mul of &Self for Self
61        impl <'a> std::ops::Mul<&'a $ty> for $ty {
62            type Output = $ty;
63            fn mul(self, other: &'a $ty) -> $ty {
64                (&self) * other
65            }
66        }
67
68        // Mul of &Self for &Self
69        impl <'a> std::ops::Mul<&'a $ty> for &'a $ty {
70            type Output = $ty;
71            fn mul(self, other: &'a $ty) -> $ty {
72                *self * other
73            }
74        }
75
76        // Mul of &Self for &Self
77        impl<'a> std::ops::Mul<$ty> for &'a $ty {
78            type Output = $ty;
79            fn mul(self, other: $ty) -> $ty {
80                *self * other
81            }
82        }
83
84        impl <'a> std::ops::MulAssign<&'a $ty> for $ty {
85            fn mul_assign(&mut self, other: &'a $ty)  {
86                *self = self.deref() * other;
87            }
88        }
89
90        impl std::ops::MulAssign for $ty {
91            fn mul_assign(&mut self, other: Self) {
92                *self = self.deref() * other;
93            }
94        }
95
96        // Mul of &V for &Self
97        impl<'a, V:Vector<$f, 3>> std::ops::Mul<&'a V> for &'a $ty
98         {
99            type Output = V;
100            fn mul(self, other: &'a V) -> V {
101                quat::apply3(&self.data, other.as_ref()).into()
102            }
103        }
104
105        // Mul of &V for Self
106        impl<'a, V:Vector<$f, 3>> std::ops::Mul<&'a V> for $ty
107         {
108            type Output = V;
109            fn mul(self, other: &'a V) -> V {
110                quat::apply3(&self.data, other.as_ref()).into()
111            }
112        }
113
114
115        // Div of  Self for Self
116        impl std::ops::Div for $ty {
117            type Output = $ty;
118            fn div(self, other: $ty) -> $ty {
119                quat::divide(self.deref(), other.deref()).into()
120            }
121        }
122
123        // Div of &[F; 4] for Self
124        impl <'a> std::ops::Div<&'a [$f; 4]> for $ty {
125            type Output = $ty;
126            fn div(self, other: &'a [$f; 4]) -> $ty {
127                quat::divide(self.deref(), other).into()
128            }
129        }
130
131        // Div of  &Self  for Self
132        impl <'a> std::ops::Div<&'a $ty> for $ty {
133            type Output = $ty;
134            fn div(self, other: &'a $ty) -> $ty {
135                (&self) / other
136            }
137        }
138
139        // Div of &Self for &Self
140        impl <'a> std::ops::Div<&'a $ty> for &'a $ty {
141            type Output = $ty;
142            fn div(self, other: &'a $ty) -> $ty {
143                *self / other
144            }
145        }
146
147        // Div of Self for &Self (Covers &Self + Self)
148        impl<'a> std::ops::Div<$ty> for &'a $ty {
149            type Output = $ty;
150            fn div(self, other: $ty) -> $ty {
151                *self / other.deref()
152            }
153        }
154
155        impl <'a> std::ops::DivAssign<&'a $ty> for $ty {
156            fn div_assign(&mut self, other: &'a $ty)  {
157                *self = self.deref() / other;
158            }
159        }
160
161        // DivAssign of &[F; 4] for Self
162        impl <'a> std::ops::DivAssign<&'a [$f; 4]> for $ty {
163            fn div_assign(&mut self, other: &'a [$f; 4]) {
164                *self = *self / other;
165            }
166        }
167
168        impl std::ops::DivAssign<Self> for $ty {
169            fn div_assign(&mut self, other: Self) {
170                *self = *self / other.deref();
171            }
172        }
173
174
175
176    }
177}
178
179//mi qarray_quaternion_trait
180macro_rules! qarray_quaternion_trait {
181    { $f:ty,  $ty:ty } => {
182
183        impl Quaternion<$f> for $ty
184        {
185            #[inline]
186            fn as_rijk(&self) -> ($f, $f, $f, $f) {
187                quat::as_rijk(self.deref())
188            }
189
190            #[inline]
191            fn of_rijk(r: $f, i: $f, j: $f, k: $f) -> Self {
192                quat::of_rijk(r, i, j, k).into()
193            }
194
195            //fp of_rotation3
196            /// Find the quaternion of a Matrix3 assuming it is purely a rotation
197            #[inline]
198            fn of_rotation3<M>(rotation: &M) -> Self
199            where
200                M: SqMatrix3<$f>
201            {
202                quat::of_rotation(rotation.as_ref()).into()
203            }
204
205            #[inline]
206            fn set_rotation3<M> (&self, matrix3:&mut M)
207            where
208                M: SqMatrix<$f, 3, 9>
209            {
210                quat::to_rotation3(&self.data, matrix3.as_mut())
211            }
212
213            #[inline]
214            fn set_rotation4<M> (&self, matrix:&mut M)
215            where
216                M: SqMatrix4<$f>
217            {
218                quat::to_rotation4(&self.data, matrix.as_mut())
219            }
220        }
221    }
222}
223
224//mi qarray_traits
225macro_rules! qarray_traits {
226    { $f:ty, $ty:ty } => {
227
228        qarray_basic_traits!{$f, $ty}
229        crate::ref_traits!{$f, 4, $ty}
230        crate::convert_traits!{$f, 4, $ty}
231        crate::serialize_traits!{$f, 4, $ty}
232        crate::unary_traits!{$f, 4, $ty}
233        crate::elementwise_traits!{$f, 4, $ty, Add, add, +, AddAssign, add_assign, +=}
234        crate::elementwise_traits!{$f, 4, $ty, Sub, sub, -, SubAssign, sub_assign, -=}
235        crate::scale_by_f_traits!{$f, $ty, Mul, mul, *, MulAssign, mul_assign, *=}
236        crate::scale_by_f_traits!{$f, $ty, Div, div, /, DivAssign, div_assign, /=}
237        qarray_mul_div_traits!{$f, $ty}
238
239        qarray_quaternion_trait!{$f, $ty}
240    }
241}
242
243//mi Invoke qarray_traits!
244qarray_traits! { f32, QArray<f32>}
245qarray_traits! { f64, QArray<f64>}