1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
4 #[cfg(not(target_arch = "spirv"))]
5 use core::fmt;
6 use core::iter::{Product, Sum};
7 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8 
9 use core::arch::wasm32::*;
10 
11 /// Creates a 2x2 matrix from two column vectors.
12 #[inline(always)]
13 #[must_use]
mat2(x_axis: Vec2, y_axis: Vec2) -> Mat214 pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
15     Mat2::from_cols(x_axis, y_axis)
16 }
17 
18 /// A 2x2 column major matrix.
19 ///
20 /// SIMD vector types are used for storage on supported platforms.
21 ///
22 /// This type is 16 byte aligned.
23 #[derive(Clone, Copy)]
24 #[repr(transparent)]
25 pub struct Mat2(pub(crate) v128);
26 
27 impl Mat2 {
28     /// A 2x2 matrix with all elements set to `0.0`.
29     pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
30 
31     /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
32     pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
33 
34     /// All NAN:s.
35     pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
36 
37     #[allow(clippy::too_many_arguments)]
38     #[inline(always)]
39     #[must_use]
new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self40     const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
41         Self(f32x4(m00, m01, m10, m11))
42     }
43 
44     /// Creates a 2x2 matrix from two column vectors.
45     #[inline(always)]
46     #[must_use]
from_cols(x_axis: Vec2, y_axis: Vec2) -> Self47     pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
48         Self(f32x4(x_axis.x, x_axis.y, y_axis.x, y_axis.y))
49     }
50 
51     /// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order.
52     /// If your data is stored in row major you will need to `transpose` the returned
53     /// matrix.
54     #[inline]
55     #[must_use]
from_cols_array(m: &[f32; 4]) -> Self56     pub const fn from_cols_array(m: &[f32; 4]) -> Self {
57         Self::new(m[0], m[1], m[2], m[3])
58     }
59 
60     /// Creates a `[f32; 4]` array storing data in column major order.
61     /// If you require data in row major order `transpose` the matrix first.
62     #[inline]
63     #[must_use]
to_cols_array(&self) -> [f32; 4]64     pub const fn to_cols_array(&self) -> [f32; 4] {
65         unsafe { *(self as *const Self as *const [f32; 4]) }
66     }
67 
68     /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order.
69     /// If your data is in row major order you will need to `transpose` the returned
70     /// matrix.
71     #[inline]
72     #[must_use]
from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self73     pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
74         Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
75     }
76 
77     /// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
78     /// If you require data in row major order `transpose` the matrix first.
79     #[inline]
80     #[must_use]
to_cols_array_2d(&self) -> [[f32; 2]; 2]81     pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
82         unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
83     }
84 
85     /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
86     #[doc(alias = "scale")]
87     #[inline]
88     #[must_use]
from_diagonal(diagonal: Vec2) -> Self89     pub const fn from_diagonal(diagonal: Vec2) -> Self {
90         Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
91     }
92 
93     /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
94     /// `angle` (in radians).
95     #[inline]
96     #[must_use]
from_scale_angle(scale: Vec2, angle: f32) -> Self97     pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
98         let (sin, cos) = math::sin_cos(angle);
99         Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
100     }
101 
102     /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
103     #[inline]
104     #[must_use]
from_angle(angle: f32) -> Self105     pub fn from_angle(angle: f32) -> Self {
106         let (sin, cos) = math::sin_cos(angle);
107         Self::new(cos, sin, -sin, cos)
108     }
109 
110     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
111     #[inline]
112     #[must_use]
from_mat3(m: Mat3) -> Self113     pub fn from_mat3(m: Mat3) -> Self {
114         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
115     }
116 
117     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
118     #[inline]
119     #[must_use]
from_mat3a(m: Mat3A) -> Self120     pub fn from_mat3a(m: Mat3A) -> Self {
121         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
122     }
123 
124     /// Creates a 2x2 matrix from the first 4 values in `slice`.
125     ///
126     /// # Panics
127     ///
128     /// Panics if `slice` is less than 4 elements long.
129     #[inline]
130     #[must_use]
from_cols_slice(slice: &[f32]) -> Self131     pub const fn from_cols_slice(slice: &[f32]) -> Self {
132         Self::new(slice[0], slice[1], slice[2], slice[3])
133     }
134 
135     /// Writes the columns of `self` to the first 4 elements in `slice`.
136     ///
137     /// # Panics
138     ///
139     /// Panics if `slice` is less than 4 elements long.
140     #[inline]
write_cols_to_slice(self, slice: &mut [f32])141     pub fn write_cols_to_slice(self, slice: &mut [f32]) {
142         slice[0] = self.x_axis.x;
143         slice[1] = self.x_axis.y;
144         slice[2] = self.y_axis.x;
145         slice[3] = self.y_axis.y;
146     }
147 
148     /// Returns the matrix column for the given `index`.
149     ///
150     /// # Panics
151     ///
152     /// Panics if `index` is greater than 1.
153     #[inline]
154     #[must_use]
col(&self, index: usize) -> Vec2155     pub fn col(&self, index: usize) -> Vec2 {
156         match index {
157             0 => self.x_axis,
158             1 => self.y_axis,
159             _ => panic!("index out of bounds"),
160         }
161     }
162 
163     /// Returns a mutable reference to the matrix column for the given `index`.
164     ///
165     /// # Panics
166     ///
167     /// Panics if `index` is greater than 1.
168     #[inline]
col_mut(&mut self, index: usize) -> &mut Vec2169     pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
170         match index {
171             0 => &mut self.x_axis,
172             1 => &mut self.y_axis,
173             _ => panic!("index out of bounds"),
174         }
175     }
176 
177     /// Returns the matrix row for the given `index`.
178     ///
179     /// # Panics
180     ///
181     /// Panics if `index` is greater than 1.
182     #[inline]
183     #[must_use]
row(&self, index: usize) -> Vec2184     pub fn row(&self, index: usize) -> Vec2 {
185         match index {
186             0 => Vec2::new(self.x_axis.x, self.y_axis.x),
187             1 => Vec2::new(self.x_axis.y, self.y_axis.y),
188             _ => panic!("index out of bounds"),
189         }
190     }
191 
192     /// Returns `true` if, and only if, all elements are finite.
193     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
194     #[inline]
195     #[must_use]
is_finite(&self) -> bool196     pub fn is_finite(&self) -> bool {
197         self.x_axis.is_finite() && self.y_axis.is_finite()
198     }
199 
200     /// Returns `true` if any elements are `NaN`.
201     #[inline]
202     #[must_use]
is_nan(&self) -> bool203     pub fn is_nan(&self) -> bool {
204         self.x_axis.is_nan() || self.y_axis.is_nan()
205     }
206 
207     /// Returns the transpose of `self`.
208     #[inline]
209     #[must_use]
transpose(&self) -> Self210     pub fn transpose(&self) -> Self {
211         Self(i32x4_shuffle::<0, 2, 5, 7>(self.0, self.0))
212     }
213 
214     /// Returns the determinant of `self`.
215     #[inline]
216     #[must_use]
determinant(&self) -> f32217     pub fn determinant(&self) -> f32 {
218         let abcd = self.0;
219         let dcba = i32x4_shuffle::<3, 2, 5, 4>(abcd, abcd);
220         let prod = f32x4_mul(abcd, dcba);
221         let det = f32x4_sub(prod, i32x4_shuffle::<1, 1, 5, 5>(prod, prod));
222         f32x4_extract_lane::<0>(det)
223     }
224 
225     /// Returns the inverse of `self`.
226     ///
227     /// If the matrix is not invertible the returned matrix will be invalid.
228     ///
229     /// # Panics
230     ///
231     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
232     #[inline]
233     #[must_use]
inverse(&self) -> Self234     pub fn inverse(&self) -> Self {
235         const SIGN: v128 = crate::wasm32::v128_from_f32x4([1.0, -1.0, -1.0, 1.0]);
236         let abcd = self.0;
237         let dcba = i32x4_shuffle::<3, 2, 5, 4>(abcd, abcd);
238         let prod = f32x4_mul(abcd, dcba);
239         let sub = f32x4_sub(prod, i32x4_shuffle::<1, 1, 5, 5>(prod, prod));
240         let det = i32x4_shuffle::<0, 0, 4, 4>(sub, sub);
241         let tmp = f32x4_div(SIGN, det);
242         glam_assert!(Mat2(tmp).is_finite());
243         let dbca = i32x4_shuffle::<3, 1, 6, 4>(abcd, abcd);
244         Self(f32x4_mul(dbca, tmp))
245     }
246 
247     /// Transforms a 2D vector.
248     #[inline]
249     #[must_use]
mul_vec2(&self, rhs: Vec2) -> Vec2250     pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
251         use core::mem::MaybeUninit;
252         let abcd = self.0;
253         let xxyy = f32x4(rhs.x, rhs.x, rhs.y, rhs.y);
254         let axbxcydy = f32x4_mul(abcd, xxyy);
255         let cydyaxbx = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy, axbxcydy);
256         let result = f32x4_add(axbxcydy, cydyaxbx);
257         let mut out: MaybeUninit<v128> = MaybeUninit::uninit();
258         unsafe {
259             v128_store(out.as_mut_ptr(), result);
260             *(&out.assume_init() as *const v128 as *const Vec2)
261         }
262     }
263 
264     /// Multiplies two 2x2 matrices.
265     #[inline]
266     #[must_use]
mul_mat2(&self, rhs: &Self) -> Self267     pub fn mul_mat2(&self, rhs: &Self) -> Self {
268         let abcd = self.0;
269         let rhs = rhs.0;
270         let xxyy0 = i32x4_shuffle::<0, 0, 5, 5>(rhs, rhs);
271         let xxyy1 = i32x4_shuffle::<2, 2, 7, 7>(rhs, rhs);
272         let axbxcydy0 = f32x4_mul(abcd, xxyy0);
273         let axbxcydy1 = f32x4_mul(abcd, xxyy1);
274         let cydyaxbx0 = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy0, axbxcydy0);
275         let cydyaxbx1 = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy1, axbxcydy1);
276         let result0 = f32x4_add(axbxcydy0, cydyaxbx0);
277         let result1 = f32x4_add(axbxcydy1, cydyaxbx1);
278         Self(i32x4_shuffle::<0, 1, 4, 5>(result0, result1))
279     }
280 
281     /// Adds two 2x2 matrices.
282     #[inline]
283     #[must_use]
add_mat2(&self, rhs: &Self) -> Self284     pub fn add_mat2(&self, rhs: &Self) -> Self {
285         Self(f32x4_add(self.0, rhs.0))
286     }
287 
288     /// Subtracts two 2x2 matrices.
289     #[inline]
290     #[must_use]
sub_mat2(&self, rhs: &Self) -> Self291     pub fn sub_mat2(&self, rhs: &Self) -> Self {
292         Self(f32x4_sub(self.0, rhs.0))
293     }
294 
295     /// Multiplies a 2x2 matrix by a scalar.
296     #[inline]
297     #[must_use]
mul_scalar(&self, rhs: f32) -> Self298     pub fn mul_scalar(&self, rhs: f32) -> Self {
299         Self(f32x4_mul(self.0, f32x4_splat(rhs)))
300     }
301 
302     /// Returns true if the absolute difference of all elements between `self` and `rhs`
303     /// is less than or equal to `max_abs_diff`.
304     ///
305     /// This can be used to compare if two matrices contain similar elements. It works best
306     /// when comparing with a known value. The `max_abs_diff` that should be used used
307     /// depends on the values being compared against.
308     ///
309     /// For more see
310     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
311     #[inline]
312     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool313     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
314         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
315             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
316     }
317 
318     #[inline]
as_dmat2(&self) -> DMat2319     pub fn as_dmat2(&self) -> DMat2 {
320         DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
321     }
322 }
323 
324 impl Default for Mat2 {
325     #[inline]
default() -> Self326     fn default() -> Self {
327         Self::IDENTITY
328     }
329 }
330 
331 impl Add<Mat2> for Mat2 {
332     type Output = Self;
333     #[inline]
add(self, rhs: Self) -> Self::Output334     fn add(self, rhs: Self) -> Self::Output {
335         self.add_mat2(&rhs)
336     }
337 }
338 
339 impl AddAssign<Mat2> for Mat2 {
340     #[inline]
add_assign(&mut self, rhs: Self)341     fn add_assign(&mut self, rhs: Self) {
342         *self = self.add_mat2(&rhs);
343     }
344 }
345 
346 impl Sub<Mat2> for Mat2 {
347     type Output = Self;
348     #[inline]
sub(self, rhs: Self) -> Self::Output349     fn sub(self, rhs: Self) -> Self::Output {
350         self.sub_mat2(&rhs)
351     }
352 }
353 
354 impl SubAssign<Mat2> for Mat2 {
355     #[inline]
sub_assign(&mut self, rhs: Self)356     fn sub_assign(&mut self, rhs: Self) {
357         *self = self.sub_mat2(&rhs);
358     }
359 }
360 
361 impl Neg for Mat2 {
362     type Output = Self;
363     #[inline]
neg(self) -> Self::Output364     fn neg(self) -> Self::Output {
365         Self(f32x4_neg(self.0))
366     }
367 }
368 
369 impl Mul<Mat2> for Mat2 {
370     type Output = Self;
371     #[inline]
mul(self, rhs: Self) -> Self::Output372     fn mul(self, rhs: Self) -> Self::Output {
373         self.mul_mat2(&rhs)
374     }
375 }
376 
377 impl MulAssign<Mat2> for Mat2 {
378     #[inline]
mul_assign(&mut self, rhs: Self)379     fn mul_assign(&mut self, rhs: Self) {
380         *self = self.mul_mat2(&rhs);
381     }
382 }
383 
384 impl Mul<Vec2> for Mat2 {
385     type Output = Vec2;
386     #[inline]
mul(self, rhs: Vec2) -> Self::Output387     fn mul(self, rhs: Vec2) -> Self::Output {
388         self.mul_vec2(rhs)
389     }
390 }
391 
392 impl Mul<Mat2> for f32 {
393     type Output = Mat2;
394     #[inline]
mul(self, rhs: Mat2) -> Self::Output395     fn mul(self, rhs: Mat2) -> Self::Output {
396         rhs.mul_scalar(self)
397     }
398 }
399 
400 impl Mul<f32> for Mat2 {
401     type Output = Self;
402     #[inline]
mul(self, rhs: f32) -> Self::Output403     fn mul(self, rhs: f32) -> Self::Output {
404         self.mul_scalar(rhs)
405     }
406 }
407 
408 impl MulAssign<f32> for Mat2 {
409     #[inline]
mul_assign(&mut self, rhs: f32)410     fn mul_assign(&mut self, rhs: f32) {
411         *self = self.mul_scalar(rhs);
412     }
413 }
414 
415 impl Sum<Self> for Mat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,416     fn sum<I>(iter: I) -> Self
417     where
418         I: Iterator<Item = Self>,
419     {
420         iter.fold(Self::ZERO, Self::add)
421     }
422 }
423 
424 impl<'a> Sum<&'a Self> for Mat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,425     fn sum<I>(iter: I) -> Self
426     where
427         I: Iterator<Item = &'a Self>,
428     {
429         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
430     }
431 }
432 
433 impl Product for Mat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,434     fn product<I>(iter: I) -> Self
435     where
436         I: Iterator<Item = Self>,
437     {
438         iter.fold(Self::IDENTITY, Self::mul)
439     }
440 }
441 
442 impl<'a> Product<&'a Self> for Mat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,443     fn product<I>(iter: I) -> Self
444     where
445         I: Iterator<Item = &'a Self>,
446     {
447         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
448     }
449 }
450 
451 impl PartialEq for Mat2 {
452     #[inline]
eq(&self, rhs: &Self) -> bool453     fn eq(&self, rhs: &Self) -> bool {
454         self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
455     }
456 }
457 
458 #[cfg(not(target_arch = "spirv"))]
459 impl AsRef<[f32; 4]> for Mat2 {
460     #[inline]
as_ref(&self) -> &[f32; 4]461     fn as_ref(&self) -> &[f32; 4] {
462         unsafe { &*(self as *const Self as *const [f32; 4]) }
463     }
464 }
465 
466 #[cfg(not(target_arch = "spirv"))]
467 impl AsMut<[f32; 4]> for Mat2 {
468     #[inline]
as_mut(&mut self) -> &mut [f32; 4]469     fn as_mut(&mut self) -> &mut [f32; 4] {
470         unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
471     }
472 }
473 
474 impl core::ops::Deref for Mat2 {
475     type Target = crate::deref::Cols2<Vec2>;
476     #[inline]
deref(&self) -> &Self::Target477     fn deref(&self) -> &Self::Target {
478         unsafe { &*(self as *const Self as *const Self::Target) }
479     }
480 }
481 
482 impl core::ops::DerefMut for Mat2 {
483     #[inline]
deref_mut(&mut self) -> &mut Self::Target484     fn deref_mut(&mut self) -> &mut Self::Target {
485         unsafe { &mut *(self as *mut Self as *mut Self::Target) }
486     }
487 }
488 
489 #[cfg(not(target_arch = "spirv"))]
490 impl fmt::Debug for Mat2 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result491     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
492         fmt.debug_struct(stringify!(Mat2))
493             .field("x_axis", &self.x_axis)
494             .field("y_axis", &self.y_axis)
495             .finish()
496     }
497 }
498 
499 #[cfg(not(target_arch = "spirv"))]
500 impl fmt::Display for Mat2 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result501     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502         write!(f, "[{}, {}]", self.x_axis, self.y_axis)
503     }
504 }
505