geo_nd/
qarray.rs

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