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 #[cfg(target_arch = "x86")]
10 use core::arch::x86::*;
11 #[cfg(target_arch = "x86_64")]
12 use core::arch::x86_64::*;
13 
14 #[repr(C)]
15 union UnionCast {
16     a: [f32; 4],
17     v: Mat2,
18 }
19 
20 /// Creates a 2x2 matrix from two column vectors.
21 #[inline(always)]
22 #[must_use]
mat2(x_axis: Vec2, y_axis: Vec2) -> Mat223 pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
24     Mat2::from_cols(x_axis, y_axis)
25 }
26 
27 /// A 2x2 column major matrix.
28 ///
29 /// SIMD vector types are used for storage on supported platforms.
30 ///
31 /// This type is 16 byte aligned.
32 #[derive(Clone, Copy)]
33 #[repr(transparent)]
34 pub struct Mat2(pub(crate) __m128);
35 
36 impl Mat2 {
37     /// A 2x2 matrix with all elements set to `0.0`.
38     pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
39 
40     /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
41     pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
42 
43     /// All NAN:s.
44     pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
45 
46     #[allow(clippy::too_many_arguments)]
47     #[inline(always)]
48     #[must_use]
new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self49     const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
50         unsafe {
51             UnionCast {
52                 a: [m00, m01, m10, m11],
53             }
54             .v
55         }
56     }
57 
58     /// Creates a 2x2 matrix from two column vectors.
59     #[inline(always)]
60     #[must_use]
from_cols(x_axis: Vec2, y_axis: Vec2) -> Self61     pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
62         unsafe {
63             UnionCast {
64                 a: [x_axis.x, x_axis.y, y_axis.x, y_axis.y],
65             }
66             .v
67         }
68     }
69 
70     /// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order.
71     /// If your data is stored in row major you will need to `transpose` the returned
72     /// matrix.
73     #[inline]
74     #[must_use]
from_cols_array(m: &[f32; 4]) -> Self75     pub const fn from_cols_array(m: &[f32; 4]) -> Self {
76         Self::new(m[0], m[1], m[2], m[3])
77     }
78 
79     /// Creates a `[f32; 4]` array storing data in column major order.
80     /// If you require data in row major order `transpose` the matrix first.
81     #[inline]
82     #[must_use]
to_cols_array(&self) -> [f32; 4]83     pub const fn to_cols_array(&self) -> [f32; 4] {
84         unsafe { *(self as *const Self as *const [f32; 4]) }
85     }
86 
87     /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order.
88     /// If your data is in row major order you will need to `transpose` the returned
89     /// matrix.
90     #[inline]
91     #[must_use]
from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self92     pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
93         Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
94     }
95 
96     /// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
97     /// If you require data in row major order `transpose` the matrix first.
98     #[inline]
99     #[must_use]
to_cols_array_2d(&self) -> [[f32; 2]; 2]100     pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
101         unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
102     }
103 
104     /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
105     #[doc(alias = "scale")]
106     #[inline]
107     #[must_use]
from_diagonal(diagonal: Vec2) -> Self108     pub const fn from_diagonal(diagonal: Vec2) -> Self {
109         Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
110     }
111 
112     /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
113     /// `angle` (in radians).
114     #[inline]
115     #[must_use]
from_scale_angle(scale: Vec2, angle: f32) -> Self116     pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
117         let (sin, cos) = math::sin_cos(angle);
118         Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
119     }
120 
121     /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
122     #[inline]
123     #[must_use]
from_angle(angle: f32) -> Self124     pub fn from_angle(angle: f32) -> Self {
125         let (sin, cos) = math::sin_cos(angle);
126         Self::new(cos, sin, -sin, cos)
127     }
128 
129     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
130     #[inline]
131     #[must_use]
from_mat3(m: Mat3) -> Self132     pub fn from_mat3(m: Mat3) -> Self {
133         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
134     }
135 
136     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
137     #[inline]
138     #[must_use]
from_mat3a(m: Mat3A) -> Self139     pub fn from_mat3a(m: Mat3A) -> Self {
140         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
141     }
142 
143     /// Creates a 2x2 matrix from the first 4 values in `slice`.
144     ///
145     /// # Panics
146     ///
147     /// Panics if `slice` is less than 4 elements long.
148     #[inline]
149     #[must_use]
from_cols_slice(slice: &[f32]) -> Self150     pub const fn from_cols_slice(slice: &[f32]) -> Self {
151         Self::new(slice[0], slice[1], slice[2], slice[3])
152     }
153 
154     /// Writes the columns of `self` to the first 4 elements in `slice`.
155     ///
156     /// # Panics
157     ///
158     /// Panics if `slice` is less than 4 elements long.
159     #[inline]
write_cols_to_slice(self, slice: &mut [f32])160     pub fn write_cols_to_slice(self, slice: &mut [f32]) {
161         slice[0] = self.x_axis.x;
162         slice[1] = self.x_axis.y;
163         slice[2] = self.y_axis.x;
164         slice[3] = self.y_axis.y;
165     }
166 
167     /// Returns the matrix column for the given `index`.
168     ///
169     /// # Panics
170     ///
171     /// Panics if `index` is greater than 1.
172     #[inline]
173     #[must_use]
col(&self, index: usize) -> Vec2174     pub fn col(&self, index: usize) -> Vec2 {
175         match index {
176             0 => self.x_axis,
177             1 => self.y_axis,
178             _ => panic!("index out of bounds"),
179         }
180     }
181 
182     /// Returns a mutable reference to the matrix column for the given `index`.
183     ///
184     /// # Panics
185     ///
186     /// Panics if `index` is greater than 1.
187     #[inline]
col_mut(&mut self, index: usize) -> &mut Vec2188     pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
189         match index {
190             0 => &mut self.x_axis,
191             1 => &mut self.y_axis,
192             _ => panic!("index out of bounds"),
193         }
194     }
195 
196     /// Returns the matrix row for the given `index`.
197     ///
198     /// # Panics
199     ///
200     /// Panics if `index` is greater than 1.
201     #[inline]
202     #[must_use]
row(&self, index: usize) -> Vec2203     pub fn row(&self, index: usize) -> Vec2 {
204         match index {
205             0 => Vec2::new(self.x_axis.x, self.y_axis.x),
206             1 => Vec2::new(self.x_axis.y, self.y_axis.y),
207             _ => panic!("index out of bounds"),
208         }
209     }
210 
211     /// Returns `true` if, and only if, all elements are finite.
212     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
213     #[inline]
214     #[must_use]
is_finite(&self) -> bool215     pub fn is_finite(&self) -> bool {
216         self.x_axis.is_finite() && self.y_axis.is_finite()
217     }
218 
219     /// Returns `true` if any elements are `NaN`.
220     #[inline]
221     #[must_use]
is_nan(&self) -> bool222     pub fn is_nan(&self) -> bool {
223         self.x_axis.is_nan() || self.y_axis.is_nan()
224     }
225 
226     /// Returns the transpose of `self`.
227     #[inline]
228     #[must_use]
transpose(&self) -> Self229     pub fn transpose(&self) -> Self {
230         Self(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_00) })
231     }
232 
233     /// Returns the determinant of `self`.
234     #[inline]
235     #[must_use]
determinant(&self) -> f32236     pub fn determinant(&self) -> f32 {
237         unsafe {
238             let abcd = self.0;
239             let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
240             let prod = _mm_mul_ps(abcd, dcba);
241             let det = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
242             _mm_cvtss_f32(det)
243         }
244     }
245 
246     /// Returns the inverse of `self`.
247     ///
248     /// If the matrix is not invertible the returned matrix will be invalid.
249     ///
250     /// # Panics
251     ///
252     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
253     #[inline]
254     #[must_use]
inverse(&self) -> Self255     pub fn inverse(&self) -> Self {
256         unsafe {
257             const SIGN: __m128 = crate::sse2::m128_from_f32x4([1.0, -1.0, -1.0, 1.0]);
258             let abcd = self.0;
259             let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
260             let prod = _mm_mul_ps(abcd, dcba);
261             let sub = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
262             let det = _mm_shuffle_ps(sub, sub, 0b00_00_00_00);
263             let tmp = _mm_div_ps(SIGN, det);
264             glam_assert!(Mat2(tmp).is_finite());
265             let dbca = _mm_shuffle_ps(abcd, abcd, 0b00_10_01_11);
266             Self(_mm_mul_ps(dbca, tmp))
267         }
268     }
269 
270     /// Transforms a 2D vector.
271     #[inline]
272     #[must_use]
mul_vec2(&self, rhs: Vec2) -> Vec2273     pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
274         unsafe {
275             use crate::Align16;
276             use core::mem::MaybeUninit;
277             let abcd = self.0;
278             let xxyy = _mm_set_ps(rhs.y, rhs.y, rhs.x, rhs.x);
279             let axbxcydy = _mm_mul_ps(abcd, xxyy);
280             let cydyaxbx = _mm_shuffle_ps(axbxcydy, axbxcydy, 0b01_00_11_10);
281             let result = _mm_add_ps(axbxcydy, cydyaxbx);
282             let mut out: MaybeUninit<Align16<Vec2>> = MaybeUninit::uninit();
283             _mm_store_ps(out.as_mut_ptr().cast(), result);
284             out.assume_init().0
285         }
286     }
287 
288     /// Multiplies two 2x2 matrices.
289     #[inline]
290     #[must_use]
mul_mat2(&self, rhs: &Self) -> Self291     pub fn mul_mat2(&self, rhs: &Self) -> Self {
292         unsafe {
293             let abcd = self.0;
294             let rhs = rhs.0;
295             let xxyy0 = _mm_shuffle_ps(rhs, rhs, 0b01_01_00_00);
296             let xxyy1 = _mm_shuffle_ps(rhs, rhs, 0b11_11_10_10);
297             let axbxcydy0 = _mm_mul_ps(abcd, xxyy0);
298             let axbxcydy1 = _mm_mul_ps(abcd, xxyy1);
299             let cydyaxbx0 = _mm_shuffle_ps(axbxcydy0, axbxcydy0, 0b01_00_11_10);
300             let cydyaxbx1 = _mm_shuffle_ps(axbxcydy1, axbxcydy1, 0b01_00_11_10);
301             let result0 = _mm_add_ps(axbxcydy0, cydyaxbx0);
302             let result1 = _mm_add_ps(axbxcydy1, cydyaxbx1);
303             Self(_mm_shuffle_ps(result0, result1, 0b01_00_01_00))
304         }
305     }
306 
307     /// Adds two 2x2 matrices.
308     #[inline]
309     #[must_use]
add_mat2(&self, rhs: &Self) -> Self310     pub fn add_mat2(&self, rhs: &Self) -> Self {
311         Self(unsafe { _mm_add_ps(self.0, rhs.0) })
312     }
313 
314     /// Subtracts two 2x2 matrices.
315     #[inline]
316     #[must_use]
sub_mat2(&self, rhs: &Self) -> Self317     pub fn sub_mat2(&self, rhs: &Self) -> Self {
318         Self(unsafe { _mm_sub_ps(self.0, rhs.0) })
319     }
320 
321     /// Multiplies a 2x2 matrix by a scalar.
322     #[inline]
323     #[must_use]
mul_scalar(&self, rhs: f32) -> Self324     pub fn mul_scalar(&self, rhs: f32) -> Self {
325         Self(unsafe { _mm_mul_ps(self.0, _mm_set_ps1(rhs)) })
326     }
327 
328     /// Returns true if the absolute difference of all elements between `self` and `rhs`
329     /// is less than or equal to `max_abs_diff`.
330     ///
331     /// This can be used to compare if two matrices contain similar elements. It works best
332     /// when comparing with a known value. The `max_abs_diff` that should be used used
333     /// depends on the values being compared against.
334     ///
335     /// For more see
336     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
337     #[inline]
338     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool339     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
340         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
341             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
342     }
343 
344     #[inline]
as_dmat2(&self) -> DMat2345     pub fn as_dmat2(&self) -> DMat2 {
346         DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
347     }
348 }
349 
350 impl Default for Mat2 {
351     #[inline]
default() -> Self352     fn default() -> Self {
353         Self::IDENTITY
354     }
355 }
356 
357 impl Add<Mat2> for Mat2 {
358     type Output = Self;
359     #[inline]
add(self, rhs: Self) -> Self::Output360     fn add(self, rhs: Self) -> Self::Output {
361         self.add_mat2(&rhs)
362     }
363 }
364 
365 impl AddAssign<Mat2> for Mat2 {
366     #[inline]
add_assign(&mut self, rhs: Self)367     fn add_assign(&mut self, rhs: Self) {
368         *self = self.add_mat2(&rhs);
369     }
370 }
371 
372 impl Sub<Mat2> for Mat2 {
373     type Output = Self;
374     #[inline]
sub(self, rhs: Self) -> Self::Output375     fn sub(self, rhs: Self) -> Self::Output {
376         self.sub_mat2(&rhs)
377     }
378 }
379 
380 impl SubAssign<Mat2> for Mat2 {
381     #[inline]
sub_assign(&mut self, rhs: Self)382     fn sub_assign(&mut self, rhs: Self) {
383         *self = self.sub_mat2(&rhs);
384     }
385 }
386 
387 impl Neg for Mat2 {
388     type Output = Self;
389     #[inline]
neg(self) -> Self::Output390     fn neg(self) -> Self::Output {
391         Self(unsafe { _mm_xor_ps(self.0, _mm_set1_ps(-0.0)) })
392     }
393 }
394 
395 impl Mul<Mat2> for Mat2 {
396     type Output = Self;
397     #[inline]
mul(self, rhs: Self) -> Self::Output398     fn mul(self, rhs: Self) -> Self::Output {
399         self.mul_mat2(&rhs)
400     }
401 }
402 
403 impl MulAssign<Mat2> for Mat2 {
404     #[inline]
mul_assign(&mut self, rhs: Self)405     fn mul_assign(&mut self, rhs: Self) {
406         *self = self.mul_mat2(&rhs);
407     }
408 }
409 
410 impl Mul<Vec2> for Mat2 {
411     type Output = Vec2;
412     #[inline]
mul(self, rhs: Vec2) -> Self::Output413     fn mul(self, rhs: Vec2) -> Self::Output {
414         self.mul_vec2(rhs)
415     }
416 }
417 
418 impl Mul<Mat2> for f32 {
419     type Output = Mat2;
420     #[inline]
mul(self, rhs: Mat2) -> Self::Output421     fn mul(self, rhs: Mat2) -> Self::Output {
422         rhs.mul_scalar(self)
423     }
424 }
425 
426 impl Mul<f32> for Mat2 {
427     type Output = Self;
428     #[inline]
mul(self, rhs: f32) -> Self::Output429     fn mul(self, rhs: f32) -> Self::Output {
430         self.mul_scalar(rhs)
431     }
432 }
433 
434 impl MulAssign<f32> for Mat2 {
435     #[inline]
mul_assign(&mut self, rhs: f32)436     fn mul_assign(&mut self, rhs: f32) {
437         *self = self.mul_scalar(rhs);
438     }
439 }
440 
441 impl Sum<Self> for Mat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,442     fn sum<I>(iter: I) -> Self
443     where
444         I: Iterator<Item = Self>,
445     {
446         iter.fold(Self::ZERO, Self::add)
447     }
448 }
449 
450 impl<'a> Sum<&'a Self> for Mat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,451     fn sum<I>(iter: I) -> Self
452     where
453         I: Iterator<Item = &'a Self>,
454     {
455         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
456     }
457 }
458 
459 impl Product for Mat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,460     fn product<I>(iter: I) -> Self
461     where
462         I: Iterator<Item = Self>,
463     {
464         iter.fold(Self::IDENTITY, Self::mul)
465     }
466 }
467 
468 impl<'a> Product<&'a Self> for Mat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,469     fn product<I>(iter: I) -> Self
470     where
471         I: Iterator<Item = &'a Self>,
472     {
473         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
474     }
475 }
476 
477 impl PartialEq for Mat2 {
478     #[inline]
eq(&self, rhs: &Self) -> bool479     fn eq(&self, rhs: &Self) -> bool {
480         self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
481     }
482 }
483 
484 #[cfg(not(target_arch = "spirv"))]
485 impl AsRef<[f32; 4]> for Mat2 {
486     #[inline]
as_ref(&self) -> &[f32; 4]487     fn as_ref(&self) -> &[f32; 4] {
488         unsafe { &*(self as *const Self as *const [f32; 4]) }
489     }
490 }
491 
492 #[cfg(not(target_arch = "spirv"))]
493 impl AsMut<[f32; 4]> for Mat2 {
494     #[inline]
as_mut(&mut self) -> &mut [f32; 4]495     fn as_mut(&mut self) -> &mut [f32; 4] {
496         unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
497     }
498 }
499 
500 impl core::ops::Deref for Mat2 {
501     type Target = crate::deref::Cols2<Vec2>;
502     #[inline]
deref(&self) -> &Self::Target503     fn deref(&self) -> &Self::Target {
504         unsafe { &*(self as *const Self as *const Self::Target) }
505     }
506 }
507 
508 impl core::ops::DerefMut for Mat2 {
509     #[inline]
deref_mut(&mut self) -> &mut Self::Target510     fn deref_mut(&mut self) -> &mut Self::Target {
511         unsafe { &mut *(self as *mut Self as *mut Self::Target) }
512     }
513 }
514 
515 #[cfg(not(target_arch = "spirv"))]
516 impl fmt::Debug for Mat2 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result517     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
518         fmt.debug_struct(stringify!(Mat2))
519             .field("x_axis", &self.x_axis)
520             .field("y_axis", &self.y_axis)
521             .finish()
522     }
523 }
524 
525 #[cfg(not(target_arch = "spirv"))]
526 impl fmt::Display for Mat2 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result527     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
528         write!(f, "[{}, {}]", self.x_axis, self.y_axis)
529     }
530 }
531