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