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::simd::*;
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) f32x4);
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::from_array([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::from_array([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(f32x4::from_array(*m))
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(simd_swizzle!(self.0, [0, 2, 1, 3]))
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 = simd_swizzle!(abcd, [3, 2, 1, 0]);
220 let prod = abcd * dcba;
221 let det = prod - simd_swizzle!(prod, [1, 1, 1, 1]);
222 det[0]
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: f32x4 = f32x4::from_array([1.0, -1.0, -1.0, 1.0]);
236 let abcd = self.0;
237 let dcba = simd_swizzle!(abcd, [3, 2, 1, 0]);
238 let prod = abcd * dcba;
239 let sub = prod - simd_swizzle!(prod, [1, 1, 1, 1]);
240 let det = simd_swizzle!(sub, [0, 0, 0, 0]);
241 let tmp = SIGN / det;
242 glam_assert!(Mat2(tmp).is_finite());
243 let dbca = simd_swizzle!(abcd, [3, 1, 2, 0]);
244 Self(dbca.mul(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 let abcd = self.0;
252 let xxyy = f32x4::from_array([rhs.x, rhs.x, rhs.y, rhs.y]);
253 let axbxcydy = abcd.mul(xxyy);
254 let cydyaxbx = simd_swizzle!(axbxcydy, [2, 3, 0, 1]);
255 let result = axbxcydy.add(cydyaxbx);
256 unsafe { *(&result as *const f32x4 as *const Vec2) }
257 }
258
259 /// Multiplies two 2x2 matrices.
260 #[inline]
261 #[must_use]
mul_mat2(&self, rhs: &Self) -> Self262 pub fn mul_mat2(&self, rhs: &Self) -> Self {
263 let abcd = self.0;
264 let xxyy0 = simd_swizzle!(rhs.0, [0, 0, 1, 1]);
265 let xxyy1 = simd_swizzle!(rhs.0, [2, 2, 3, 3]);
266 let axbxcydy0 = abcd * xxyy0;
267 let axbxcydy1 = abcd * xxyy1;
268 let cydyaxbx0 = simd_swizzle!(axbxcydy0, [2, 3, 0, 1]);
269 let cydyaxbx1 = simd_swizzle!(axbxcydy1, [2, 3, 0, 1]);
270 let result0 = axbxcydy0 + cydyaxbx0;
271 let result1 = axbxcydy1 + cydyaxbx1;
272 Self(simd_swizzle!(result0, result1, [0, 1, 4, 5]))
273 }
274
275 /// Adds two 2x2 matrices.
276 #[inline]
277 #[must_use]
add_mat2(&self, rhs: &Self) -> Self278 pub fn add_mat2(&self, rhs: &Self) -> Self {
279 Self(self.0 + rhs.0)
280 }
281
282 /// Subtracts two 2x2 matrices.
283 #[inline]
284 #[must_use]
sub_mat2(&self, rhs: &Self) -> Self285 pub fn sub_mat2(&self, rhs: &Self) -> Self {
286 Self(self.0 - rhs.0)
287 }
288
289 /// Multiplies a 2x2 matrix by a scalar.
290 #[inline]
291 #[must_use]
mul_scalar(&self, rhs: f32) -> Self292 pub fn mul_scalar(&self, rhs: f32) -> Self {
293 Self(self.0 * f32x4::splat(rhs))
294 }
295
296 /// Returns true if the absolute difference of all elements between `self` and `rhs`
297 /// is less than or equal to `max_abs_diff`.
298 ///
299 /// This can be used to compare if two matrices contain similar elements. It works best
300 /// when comparing with a known value. The `max_abs_diff` that should be used used
301 /// depends on the values being compared against.
302 ///
303 /// For more see
304 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
305 #[inline]
306 #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool307 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
308 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
309 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
310 }
311
312 #[inline]
as_dmat2(&self) -> DMat2313 pub fn as_dmat2(&self) -> DMat2 {
314 DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
315 }
316 }
317
318 impl Default for Mat2 {
319 #[inline]
default() -> Self320 fn default() -> Self {
321 Self::IDENTITY
322 }
323 }
324
325 impl Add<Mat2> for Mat2 {
326 type Output = Self;
327 #[inline]
add(self, rhs: Self) -> Self::Output328 fn add(self, rhs: Self) -> Self::Output {
329 self.add_mat2(&rhs)
330 }
331 }
332
333 impl AddAssign<Mat2> for Mat2 {
334 #[inline]
add_assign(&mut self, rhs: Self)335 fn add_assign(&mut self, rhs: Self) {
336 *self = self.add_mat2(&rhs);
337 }
338 }
339
340 impl Sub<Mat2> for Mat2 {
341 type Output = Self;
342 #[inline]
sub(self, rhs: Self) -> Self::Output343 fn sub(self, rhs: Self) -> Self::Output {
344 self.sub_mat2(&rhs)
345 }
346 }
347
348 impl SubAssign<Mat2> for Mat2 {
349 #[inline]
sub_assign(&mut self, rhs: Self)350 fn sub_assign(&mut self, rhs: Self) {
351 *self = self.sub_mat2(&rhs);
352 }
353 }
354
355 impl Neg for Mat2 {
356 type Output = Self;
357 #[inline]
neg(self) -> Self::Output358 fn neg(self) -> Self::Output {
359 Self(-self.0)
360 }
361 }
362
363 impl Mul<Mat2> for Mat2 {
364 type Output = Self;
365 #[inline]
mul(self, rhs: Self) -> Self::Output366 fn mul(self, rhs: Self) -> Self::Output {
367 self.mul_mat2(&rhs)
368 }
369 }
370
371 impl MulAssign<Mat2> for Mat2 {
372 #[inline]
mul_assign(&mut self, rhs: Self)373 fn mul_assign(&mut self, rhs: Self) {
374 *self = self.mul_mat2(&rhs);
375 }
376 }
377
378 impl Mul<Vec2> for Mat2 {
379 type Output = Vec2;
380 #[inline]
mul(self, rhs: Vec2) -> Self::Output381 fn mul(self, rhs: Vec2) -> Self::Output {
382 self.mul_vec2(rhs)
383 }
384 }
385
386 impl Mul<Mat2> for f32 {
387 type Output = Mat2;
388 #[inline]
mul(self, rhs: Mat2) -> Self::Output389 fn mul(self, rhs: Mat2) -> Self::Output {
390 rhs.mul_scalar(self)
391 }
392 }
393
394 impl Mul<f32> for Mat2 {
395 type Output = Self;
396 #[inline]
mul(self, rhs: f32) -> Self::Output397 fn mul(self, rhs: f32) -> Self::Output {
398 self.mul_scalar(rhs)
399 }
400 }
401
402 impl MulAssign<f32> for Mat2 {
403 #[inline]
mul_assign(&mut self, rhs: f32)404 fn mul_assign(&mut self, rhs: f32) {
405 *self = self.mul_scalar(rhs);
406 }
407 }
408
409 impl Sum<Self> for Mat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,410 fn sum<I>(iter: I) -> Self
411 where
412 I: Iterator<Item = Self>,
413 {
414 iter.fold(Self::ZERO, Self::add)
415 }
416 }
417
418 impl<'a> Sum<&'a Self> for Mat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,419 fn sum<I>(iter: I) -> Self
420 where
421 I: Iterator<Item = &'a Self>,
422 {
423 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
424 }
425 }
426
427 impl Product for Mat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,428 fn product<I>(iter: I) -> Self
429 where
430 I: Iterator<Item = Self>,
431 {
432 iter.fold(Self::IDENTITY, Self::mul)
433 }
434 }
435
436 impl<'a> Product<&'a Self> for Mat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,437 fn product<I>(iter: I) -> Self
438 where
439 I: Iterator<Item = &'a Self>,
440 {
441 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
442 }
443 }
444
445 impl PartialEq for Mat2 {
446 #[inline]
eq(&self, rhs: &Self) -> bool447 fn eq(&self, rhs: &Self) -> bool {
448 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
449 }
450 }
451
452 #[cfg(not(target_arch = "spirv"))]
453 impl AsRef<[f32; 4]> for Mat2 {
454 #[inline]
as_ref(&self) -> &[f32; 4]455 fn as_ref(&self) -> &[f32; 4] {
456 unsafe { &*(self as *const Self as *const [f32; 4]) }
457 }
458 }
459
460 #[cfg(not(target_arch = "spirv"))]
461 impl AsMut<[f32; 4]> for Mat2 {
462 #[inline]
as_mut(&mut self) -> &mut [f32; 4]463 fn as_mut(&mut self) -> &mut [f32; 4] {
464 unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
465 }
466 }
467
468 impl core::ops::Deref for Mat2 {
469 type Target = crate::deref::Cols2<Vec2>;
470 #[inline]
deref(&self) -> &Self::Target471 fn deref(&self) -> &Self::Target {
472 unsafe { &*(self as *const Self as *const Self::Target) }
473 }
474 }
475
476 impl core::ops::DerefMut for Mat2 {
477 #[inline]
deref_mut(&mut self) -> &mut Self::Target478 fn deref_mut(&mut self) -> &mut Self::Target {
479 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
480 }
481 }
482
483 #[cfg(not(target_arch = "spirv"))]
484 impl fmt::Debug for Mat2 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result485 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
486 fmt.debug_struct(stringify!(Mat2))
487 .field("x_axis", &self.x_axis)
488 .field("y_axis", &self.y_axis)
489 .finish()
490 }
491 }
492
493 #[cfg(not(target_arch = "spirv"))]
494 impl fmt::Display for Mat2 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result495 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
496 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
497 }
498 }
499