1use 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#[derive(Clone, Copy, Debug, PartialEq)]
17#[repr(transparent)]
18pub struct QArray<F>
19where
20 F: Float,
21{
22 data: [F; 4],
24}
25
26macro_rules! qarray_basic_traits {
29 { $f:ty, $ty:ty } => {
30
31 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 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
51macro_rules! qarray_mul_div_traits {
53 { $f:ty, $ty:ty } => {
54 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 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 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 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 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 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 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 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 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 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 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 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
181macro_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 #[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
226macro_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
245qarray_traits! { f32, QArray<f32>}
247qarray_traits! { f64, QArray<f64>}