• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 use core::fmt;
5 use core::iter::{Product, Sum};
6 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7 
8 /// Creates a 2x2 matrix from two column vectors.
9 #[inline(always)]
10 #[must_use]
mat2(x_axis: Vec2, y_axis: Vec2) -> Mat211 pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
12     Mat2::from_cols(x_axis, y_axis)
13 }
14 
15 /// A 2x2 column major matrix.
16 #[derive(Clone, Copy)]
17 #[cfg_attr(
18     not(any(feature = "scalar-math", target_arch = "spirv")),
19     repr(align(16))
20 )]
21 #[cfg_attr(feature = "cuda", repr(align(8)))]
22 #[repr(C)]
23 pub struct Mat2 {
24     pub x_axis: Vec2,
25     pub y_axis: Vec2,
26 }
27 
28 impl Mat2 {
29     /// A 2x2 matrix with all elements set to `0.0`.
30     pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
31 
32     /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
33     pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
34 
35     /// All NAN:s.
36     pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
37 
38     #[allow(clippy::too_many_arguments)]
39     #[inline(always)]
40     #[must_use]
new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self41     const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
42         Self {
43             x_axis: Vec2::new(m00, m01),
44             y_axis: Vec2::new(m10, m11),
45         }
46     }
47 
48     /// Creates a 2x2 matrix from two column vectors.
49     #[inline(always)]
50     #[must_use]
from_cols(x_axis: Vec2, y_axis: Vec2) -> Self51     pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
52         Self { x_axis, y_axis }
53     }
54 
55     /// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order.
56     /// If your data is stored in row major you will need to `transpose` the returned
57     /// matrix.
58     #[inline]
59     #[must_use]
from_cols_array(m: &[f32; 4]) -> Self60     pub const fn from_cols_array(m: &[f32; 4]) -> Self {
61         Self::new(m[0], m[1], m[2], m[3])
62     }
63 
64     /// Creates a `[f32; 4]` array storing data in column major order.
65     /// If you require data in row major order `transpose` the matrix first.
66     #[inline]
67     #[must_use]
to_cols_array(&self) -> [f32; 4]68     pub const fn to_cols_array(&self) -> [f32; 4] {
69         [self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
70     }
71 
72     /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order.
73     /// If your data is in row major order you will need to `transpose` the returned
74     /// matrix.
75     #[inline]
76     #[must_use]
from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self77     pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
78         Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
79     }
80 
81     /// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
82     /// If you require data in row major order `transpose` the matrix first.
83     #[inline]
84     #[must_use]
to_cols_array_2d(&self) -> [[f32; 2]; 2]85     pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
86         [self.x_axis.to_array(), self.y_axis.to_array()]
87     }
88 
89     /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
90     #[doc(alias = "scale")]
91     #[inline]
92     #[must_use]
from_diagonal(diagonal: Vec2) -> Self93     pub const fn from_diagonal(diagonal: Vec2) -> Self {
94         Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
95     }
96 
97     /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
98     /// `angle` (in radians).
99     #[inline]
100     #[must_use]
from_scale_angle(scale: Vec2, angle: f32) -> Self101     pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
102         let (sin, cos) = math::sin_cos(angle);
103         Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
104     }
105 
106     /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
107     #[inline]
108     #[must_use]
from_angle(angle: f32) -> Self109     pub fn from_angle(angle: f32) -> Self {
110         let (sin, cos) = math::sin_cos(angle);
111         Self::new(cos, sin, -sin, cos)
112     }
113 
114     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
115     #[inline]
116     #[must_use]
from_mat3(m: Mat3) -> Self117     pub fn from_mat3(m: Mat3) -> Self {
118         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
119     }
120 
121     /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
122     /// and `j`th row.
123     ///
124     /// # Panics
125     ///
126     /// Panics if `i` or `j` is greater than 2.
127     #[inline]
128     #[must_use]
from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self129     pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
130         match (i, j) {
131             (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
132             (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
133             (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
134             (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
135             (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
136             (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
137             (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
138             (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
139             (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
140             _ => panic!("index out of bounds"),
141         }
142     }
143 
144     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
145     #[inline]
146     #[must_use]
from_mat3a(m: Mat3A) -> Self147     pub fn from_mat3a(m: Mat3A) -> Self {
148         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
149     }
150 
151     /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
152     /// and `j`th row.
153     ///
154     /// # Panics
155     ///
156     /// Panics if `i` or `j` is greater than 2.
157     #[inline]
158     #[must_use]
from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self159     pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
160         match (i, j) {
161             (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
162             (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
163             (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
164             (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
165             (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
166             (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
167             (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
168             (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
169             (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
170             _ => panic!("index out of bounds"),
171         }
172     }
173 
174     /// Creates a 2x2 matrix from the first 4 values in `slice`.
175     ///
176     /// # Panics
177     ///
178     /// Panics if `slice` is less than 4 elements long.
179     #[inline]
180     #[must_use]
from_cols_slice(slice: &[f32]) -> Self181     pub const fn from_cols_slice(slice: &[f32]) -> Self {
182         Self::new(slice[0], slice[1], slice[2], slice[3])
183     }
184 
185     /// Writes the columns of `self` to the first 4 elements in `slice`.
186     ///
187     /// # Panics
188     ///
189     /// Panics if `slice` is less than 4 elements long.
190     #[inline]
write_cols_to_slice(self, slice: &mut [f32])191     pub fn write_cols_to_slice(self, slice: &mut [f32]) {
192         slice[0] = self.x_axis.x;
193         slice[1] = self.x_axis.y;
194         slice[2] = self.y_axis.x;
195         slice[3] = self.y_axis.y;
196     }
197 
198     /// Returns the matrix column for the given `index`.
199     ///
200     /// # Panics
201     ///
202     /// Panics if `index` is greater than 1.
203     #[inline]
204     #[must_use]
col(&self, index: usize) -> Vec2205     pub fn col(&self, index: usize) -> Vec2 {
206         match index {
207             0 => self.x_axis,
208             1 => self.y_axis,
209             _ => panic!("index out of bounds"),
210         }
211     }
212 
213     /// Returns a mutable reference to the matrix column for the given `index`.
214     ///
215     /// # Panics
216     ///
217     /// Panics if `index` is greater than 1.
218     #[inline]
col_mut(&mut self, index: usize) -> &mut Vec2219     pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
220         match index {
221             0 => &mut self.x_axis,
222             1 => &mut self.y_axis,
223             _ => panic!("index out of bounds"),
224         }
225     }
226 
227     /// Returns the matrix row for the given `index`.
228     ///
229     /// # Panics
230     ///
231     /// Panics if `index` is greater than 1.
232     #[inline]
233     #[must_use]
row(&self, index: usize) -> Vec2234     pub fn row(&self, index: usize) -> Vec2 {
235         match index {
236             0 => Vec2::new(self.x_axis.x, self.y_axis.x),
237             1 => Vec2::new(self.x_axis.y, self.y_axis.y),
238             _ => panic!("index out of bounds"),
239         }
240     }
241 
242     /// Returns `true` if, and only if, all elements are finite.
243     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
244     #[inline]
245     #[must_use]
is_finite(&self) -> bool246     pub fn is_finite(&self) -> bool {
247         self.x_axis.is_finite() && self.y_axis.is_finite()
248     }
249 
250     /// Returns `true` if any elements are `NaN`.
251     #[inline]
252     #[must_use]
is_nan(&self) -> bool253     pub fn is_nan(&self) -> bool {
254         self.x_axis.is_nan() || self.y_axis.is_nan()
255     }
256 
257     /// Returns the transpose of `self`.
258     #[inline]
259     #[must_use]
transpose(&self) -> Self260     pub fn transpose(&self) -> Self {
261         Self {
262             x_axis: Vec2::new(self.x_axis.x, self.y_axis.x),
263             y_axis: Vec2::new(self.x_axis.y, self.y_axis.y),
264         }
265     }
266 
267     /// Returns the determinant of `self`.
268     #[inline]
269     #[must_use]
determinant(&self) -> f32270     pub fn determinant(&self) -> f32 {
271         self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
272     }
273 
274     /// Returns the inverse of `self`.
275     ///
276     /// If the matrix is not invertible the returned matrix will be invalid.
277     ///
278     /// # Panics
279     ///
280     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
281     #[inline]
282     #[must_use]
inverse(&self) -> Self283     pub fn inverse(&self) -> Self {
284         let inv_det = {
285             let det = self.determinant();
286             glam_assert!(det != 0.0);
287             det.recip()
288         };
289         Self::new(
290             self.y_axis.y * inv_det,
291             self.x_axis.y * -inv_det,
292             self.y_axis.x * -inv_det,
293             self.x_axis.x * inv_det,
294         )
295     }
296 
297     /// Transforms a 2D vector.
298     #[inline]
299     #[must_use]
mul_vec2(&self, rhs: Vec2) -> Vec2300     pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
301         #[allow(clippy::suspicious_operation_groupings)]
302         Vec2::new(
303             (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
304             (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
305         )
306     }
307 
308     /// Multiplies two 2x2 matrices.
309     #[inline]
310     #[must_use]
mul_mat2(&self, rhs: &Self) -> Self311     pub fn mul_mat2(&self, rhs: &Self) -> Self {
312         Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
313     }
314 
315     /// Adds two 2x2 matrices.
316     #[inline]
317     #[must_use]
add_mat2(&self, rhs: &Self) -> Self318     pub fn add_mat2(&self, rhs: &Self) -> Self {
319         Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
320     }
321 
322     /// Subtracts two 2x2 matrices.
323     #[inline]
324     #[must_use]
sub_mat2(&self, rhs: &Self) -> Self325     pub fn sub_mat2(&self, rhs: &Self) -> Self {
326         Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
327     }
328 
329     /// Multiplies a 2x2 matrix by a scalar.
330     #[inline]
331     #[must_use]
mul_scalar(&self, rhs: f32) -> Self332     pub fn mul_scalar(&self, rhs: f32) -> Self {
333         Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
334     }
335 
336     /// Divides a 2x2 matrix by a scalar.
337     #[inline]
338     #[must_use]
div_scalar(&self, rhs: f32) -> Self339     pub fn div_scalar(&self, rhs: f32) -> Self {
340         let rhs = Vec2::splat(rhs);
341         Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
342     }
343 
344     /// Returns true if the absolute difference of all elements between `self` and `rhs`
345     /// is less than or equal to `max_abs_diff`.
346     ///
347     /// This can be used to compare if two matrices contain similar elements. It works best
348     /// when comparing with a known value. The `max_abs_diff` that should be used used
349     /// depends on the values being compared against.
350     ///
351     /// For more see
352     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
353     #[inline]
354     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool355     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
356         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
357             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
358     }
359 
360     /// Takes the absolute value of each element in `self`
361     #[inline]
362     #[must_use]
abs(&self) -> Self363     pub fn abs(&self) -> Self {
364         Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
365     }
366 
367     #[inline]
as_dmat2(&self) -> DMat2368     pub fn as_dmat2(&self) -> DMat2 {
369         DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
370     }
371 }
372 
373 impl Default for Mat2 {
374     #[inline]
default() -> Self375     fn default() -> Self {
376         Self::IDENTITY
377     }
378 }
379 
380 impl Add<Mat2> for Mat2 {
381     type Output = Self;
382     #[inline]
add(self, rhs: Self) -> Self::Output383     fn add(self, rhs: Self) -> Self::Output {
384         self.add_mat2(&rhs)
385     }
386 }
387 
388 impl AddAssign<Mat2> for Mat2 {
389     #[inline]
add_assign(&mut self, rhs: Self)390     fn add_assign(&mut self, rhs: Self) {
391         *self = self.add_mat2(&rhs);
392     }
393 }
394 
395 impl Sub<Mat2> for Mat2 {
396     type Output = Self;
397     #[inline]
sub(self, rhs: Self) -> Self::Output398     fn sub(self, rhs: Self) -> Self::Output {
399         self.sub_mat2(&rhs)
400     }
401 }
402 
403 impl SubAssign<Mat2> for Mat2 {
404     #[inline]
sub_assign(&mut self, rhs: Self)405     fn sub_assign(&mut self, rhs: Self) {
406         *self = self.sub_mat2(&rhs);
407     }
408 }
409 
410 impl Neg for Mat2 {
411     type Output = Self;
412     #[inline]
neg(self) -> Self::Output413     fn neg(self) -> Self::Output {
414         Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
415     }
416 }
417 
418 impl Mul<Mat2> for Mat2 {
419     type Output = Self;
420     #[inline]
mul(self, rhs: Self) -> Self::Output421     fn mul(self, rhs: Self) -> Self::Output {
422         self.mul_mat2(&rhs)
423     }
424 }
425 
426 impl MulAssign<Mat2> for Mat2 {
427     #[inline]
mul_assign(&mut self, rhs: Self)428     fn mul_assign(&mut self, rhs: Self) {
429         *self = self.mul_mat2(&rhs);
430     }
431 }
432 
433 impl Mul<Vec2> for Mat2 {
434     type Output = Vec2;
435     #[inline]
mul(self, rhs: Vec2) -> Self::Output436     fn mul(self, rhs: Vec2) -> Self::Output {
437         self.mul_vec2(rhs)
438     }
439 }
440 
441 impl Mul<Mat2> for f32 {
442     type Output = Mat2;
443     #[inline]
mul(self, rhs: Mat2) -> Self::Output444     fn mul(self, rhs: Mat2) -> Self::Output {
445         rhs.mul_scalar(self)
446     }
447 }
448 
449 impl Mul<f32> for Mat2 {
450     type Output = Self;
451     #[inline]
mul(self, rhs: f32) -> Self::Output452     fn mul(self, rhs: f32) -> Self::Output {
453         self.mul_scalar(rhs)
454     }
455 }
456 
457 impl MulAssign<f32> for Mat2 {
458     #[inline]
mul_assign(&mut self, rhs: f32)459     fn mul_assign(&mut self, rhs: f32) {
460         *self = self.mul_scalar(rhs);
461     }
462 }
463 
464 impl Div<Mat2> for f32 {
465     type Output = Mat2;
466     #[inline]
div(self, rhs: Mat2) -> Self::Output467     fn div(self, rhs: Mat2) -> Self::Output {
468         rhs.div_scalar(self)
469     }
470 }
471 
472 impl Div<f32> for Mat2 {
473     type Output = Self;
474     #[inline]
div(self, rhs: f32) -> Self::Output475     fn div(self, rhs: f32) -> Self::Output {
476         self.div_scalar(rhs)
477     }
478 }
479 
480 impl DivAssign<f32> for Mat2 {
481     #[inline]
div_assign(&mut self, rhs: f32)482     fn div_assign(&mut self, rhs: f32) {
483         *self = self.div_scalar(rhs);
484     }
485 }
486 
487 impl Sum<Self> for Mat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,488     fn sum<I>(iter: I) -> Self
489     where
490         I: Iterator<Item = Self>,
491     {
492         iter.fold(Self::ZERO, Self::add)
493     }
494 }
495 
496 impl<'a> Sum<&'a Self> for Mat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,497     fn sum<I>(iter: I) -> Self
498     where
499         I: Iterator<Item = &'a Self>,
500     {
501         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
502     }
503 }
504 
505 impl Product for Mat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,506     fn product<I>(iter: I) -> Self
507     where
508         I: Iterator<Item = Self>,
509     {
510         iter.fold(Self::IDENTITY, Self::mul)
511     }
512 }
513 
514 impl<'a> Product<&'a Self> for Mat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,515     fn product<I>(iter: I) -> Self
516     where
517         I: Iterator<Item = &'a Self>,
518     {
519         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
520     }
521 }
522 
523 impl PartialEq for Mat2 {
524     #[inline]
eq(&self, rhs: &Self) -> bool525     fn eq(&self, rhs: &Self) -> bool {
526         self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
527     }
528 }
529 
530 #[cfg(not(target_arch = "spirv"))]
531 impl AsRef<[f32; 4]> for Mat2 {
532     #[inline]
as_ref(&self) -> &[f32; 4]533     fn as_ref(&self) -> &[f32; 4] {
534         unsafe { &*(self as *const Self as *const [f32; 4]) }
535     }
536 }
537 
538 #[cfg(not(target_arch = "spirv"))]
539 impl AsMut<[f32; 4]> for Mat2 {
540     #[inline]
as_mut(&mut self) -> &mut [f32; 4]541     fn as_mut(&mut self) -> &mut [f32; 4] {
542         unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
543     }
544 }
545 
546 impl fmt::Debug for Mat2 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result547     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
548         fmt.debug_struct(stringify!(Mat2))
549             .field("x_axis", &self.x_axis)
550             .field("y_axis", &self.y_axis)
551             .finish()
552     }
553 }
554 
555 impl fmt::Display for Mat2 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result556     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
557         if let Some(p) = f.precision() {
558             write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
559         } else {
560             write!(f, "[{}, {}]", self.x_axis, self.y_axis)
561         }
562     }
563 }
564