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#[derive(Clone, Copy, Debug, PartialEq)]
15#[repr(transparent)]
16pub struct QArray<F>
17where
18 F: Float,
19{
20 data: [F; 4],
22}
23
24macro_rules! qarray_basic_traits {
27 { $f:ty, $ty:ty } => {
28
29 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 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
49macro_rules! qarray_mul_div_traits {
51 { $f:ty, $ty:ty } => {
52 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 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 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 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 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 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 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 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 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 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 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 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
179macro_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 #[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
224macro_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
243qarray_traits! { f32, QArray<f32>}
245qarray_traits! { f64, QArray<f64>}