• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{f64::math, swizzles::*, DMat3, DVec2, Mat2};
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]
dmat2(x_axis: DVec2, y_axis: DVec2) -> DMat211 pub const fn dmat2(x_axis: DVec2, y_axis: DVec2) -> DMat2 {
12     DMat2::from_cols(x_axis, y_axis)
13 }
14 
15 /// A 2x2 column major matrix.
16 #[derive(Clone, Copy)]
17 #[cfg_attr(feature = "cuda", repr(align(16)))]
18 #[repr(C)]
19 pub struct DMat2 {
20     pub x_axis: DVec2,
21     pub y_axis: DVec2,
22 }
23 
24 impl DMat2 {
25     /// A 2x2 matrix with all elements set to `0.0`.
26     pub const ZERO: Self = Self::from_cols(DVec2::ZERO, DVec2::ZERO);
27 
28     /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
29     pub const IDENTITY: Self = Self::from_cols(DVec2::X, DVec2::Y);
30 
31     /// All NAN:s.
32     pub const NAN: Self = Self::from_cols(DVec2::NAN, DVec2::NAN);
33 
34     #[allow(clippy::too_many_arguments)]
35     #[inline(always)]
36     #[must_use]
new(m00: f64, m01: f64, m10: f64, m11: f64) -> Self37     const fn new(m00: f64, m01: f64, m10: f64, m11: f64) -> Self {
38         Self {
39             x_axis: DVec2::new(m00, m01),
40             y_axis: DVec2::new(m10, m11),
41         }
42     }
43 
44     /// Creates a 2x2 matrix from two column vectors.
45     #[inline(always)]
46     #[must_use]
from_cols(x_axis: DVec2, y_axis: DVec2) -> Self47     pub const fn from_cols(x_axis: DVec2, y_axis: DVec2) -> Self {
48         Self { x_axis, y_axis }
49     }
50 
51     /// Creates a 2x2 matrix from a `[f64; 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: &[f64; 4]) -> Self56     pub const fn from_cols_array(m: &[f64; 4]) -> Self {
57         Self::new(m[0], m[1], m[2], m[3])
58     }
59 
60     /// Creates a `[f64; 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) -> [f64; 4]64     pub const fn to_cols_array(&self) -> [f64; 4] {
65         [self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
66     }
67 
68     /// Creates a 2x2 matrix from a `[[f64; 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: &[[f64; 2]; 2]) -> Self73     pub const fn from_cols_array_2d(m: &[[f64; 2]; 2]) -> Self {
74         Self::from_cols(DVec2::from_array(m[0]), DVec2::from_array(m[1]))
75     }
76 
77     /// Creates a `[[f64; 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) -> [[f64; 2]; 2]81     pub const fn to_cols_array_2d(&self) -> [[f64; 2]; 2] {
82         [self.x_axis.to_array(), self.y_axis.to_array()]
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: DVec2) -> Self89     pub const fn from_diagonal(diagonal: DVec2) -> 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: DVec2, angle: f64) -> Self97     pub fn from_scale_angle(scale: DVec2, angle: f64) -> 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: f64) -> Self105     pub fn from_angle(angle: f64) -> 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: DMat3) -> Self113     pub fn from_mat3(m: DMat3) -> Self {
114         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
115     }
116 
117     /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
118     /// and `j`th row.
119     ///
120     /// # Panics
121     ///
122     /// Panics if `i` or `j` is greater than 2.
123     #[inline]
124     #[must_use]
from_mat3_minor(m: DMat3, i: usize, j: usize) -> Self125     pub fn from_mat3_minor(m: DMat3, i: usize, j: usize) -> Self {
126         match (i, j) {
127             (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
128             (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
129             (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
130             (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
131             (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
132             (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
133             (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
134             (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
135             (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
136             _ => panic!("index out of bounds"),
137         }
138     }
139 
140     /// Creates a 2x2 matrix from the first 4 values in `slice`.
141     ///
142     /// # Panics
143     ///
144     /// Panics if `slice` is less than 4 elements long.
145     #[inline]
146     #[must_use]
from_cols_slice(slice: &[f64]) -> Self147     pub const fn from_cols_slice(slice: &[f64]) -> Self {
148         Self::new(slice[0], slice[1], slice[2], slice[3])
149     }
150 
151     /// Writes the columns of `self` to the first 4 elements in `slice`.
152     ///
153     /// # Panics
154     ///
155     /// Panics if `slice` is less than 4 elements long.
156     #[inline]
write_cols_to_slice(self, slice: &mut [f64])157     pub fn write_cols_to_slice(self, slice: &mut [f64]) {
158         slice[0] = self.x_axis.x;
159         slice[1] = self.x_axis.y;
160         slice[2] = self.y_axis.x;
161         slice[3] = self.y_axis.y;
162     }
163 
164     /// Returns the matrix column for the given `index`.
165     ///
166     /// # Panics
167     ///
168     /// Panics if `index` is greater than 1.
169     #[inline]
170     #[must_use]
col(&self, index: usize) -> DVec2171     pub fn col(&self, index: usize) -> DVec2 {
172         match index {
173             0 => self.x_axis,
174             1 => self.y_axis,
175             _ => panic!("index out of bounds"),
176         }
177     }
178 
179     /// Returns a mutable reference to the matrix column for the given `index`.
180     ///
181     /// # Panics
182     ///
183     /// Panics if `index` is greater than 1.
184     #[inline]
col_mut(&mut self, index: usize) -> &mut DVec2185     pub fn col_mut(&mut self, index: usize) -> &mut DVec2 {
186         match index {
187             0 => &mut self.x_axis,
188             1 => &mut self.y_axis,
189             _ => panic!("index out of bounds"),
190         }
191     }
192 
193     /// Returns the matrix row for the given `index`.
194     ///
195     /// # Panics
196     ///
197     /// Panics if `index` is greater than 1.
198     #[inline]
199     #[must_use]
row(&self, index: usize) -> DVec2200     pub fn row(&self, index: usize) -> DVec2 {
201         match index {
202             0 => DVec2::new(self.x_axis.x, self.y_axis.x),
203             1 => DVec2::new(self.x_axis.y, self.y_axis.y),
204             _ => panic!("index out of bounds"),
205         }
206     }
207 
208     /// Returns `true` if, and only if, all elements are finite.
209     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
210     #[inline]
211     #[must_use]
is_finite(&self) -> bool212     pub fn is_finite(&self) -> bool {
213         self.x_axis.is_finite() && self.y_axis.is_finite()
214     }
215 
216     /// Returns `true` if any elements are `NaN`.
217     #[inline]
218     #[must_use]
is_nan(&self) -> bool219     pub fn is_nan(&self) -> bool {
220         self.x_axis.is_nan() || self.y_axis.is_nan()
221     }
222 
223     /// Returns the transpose of `self`.
224     #[inline]
225     #[must_use]
transpose(&self) -> Self226     pub fn transpose(&self) -> Self {
227         Self {
228             x_axis: DVec2::new(self.x_axis.x, self.y_axis.x),
229             y_axis: DVec2::new(self.x_axis.y, self.y_axis.y),
230         }
231     }
232 
233     /// Returns the determinant of `self`.
234     #[inline]
235     #[must_use]
determinant(&self) -> f64236     pub fn determinant(&self) -> f64 {
237         self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
238     }
239 
240     /// Returns the inverse of `self`.
241     ///
242     /// If the matrix is not invertible the returned matrix will be invalid.
243     ///
244     /// # Panics
245     ///
246     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
247     #[inline]
248     #[must_use]
inverse(&self) -> Self249     pub fn inverse(&self) -> Self {
250         let inv_det = {
251             let det = self.determinant();
252             glam_assert!(det != 0.0);
253             det.recip()
254         };
255         Self::new(
256             self.y_axis.y * inv_det,
257             self.x_axis.y * -inv_det,
258             self.y_axis.x * -inv_det,
259             self.x_axis.x * inv_det,
260         )
261     }
262 
263     /// Transforms a 2D vector.
264     #[inline]
265     #[must_use]
mul_vec2(&self, rhs: DVec2) -> DVec2266     pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
267         #[allow(clippy::suspicious_operation_groupings)]
268         DVec2::new(
269             (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
270             (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
271         )
272     }
273 
274     /// Multiplies two 2x2 matrices.
275     #[inline]
276     #[must_use]
mul_mat2(&self, rhs: &Self) -> Self277     pub fn mul_mat2(&self, rhs: &Self) -> Self {
278         Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
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::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
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::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
293     }
294 
295     /// Multiplies a 2x2 matrix by a scalar.
296     #[inline]
297     #[must_use]
mul_scalar(&self, rhs: f64) -> Self298     pub fn mul_scalar(&self, rhs: f64) -> Self {
299         Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
300     }
301 
302     /// Divides a 2x2 matrix by a scalar.
303     #[inline]
304     #[must_use]
div_scalar(&self, rhs: f64) -> Self305     pub fn div_scalar(&self, rhs: f64) -> Self {
306         let rhs = DVec2::splat(rhs);
307         Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
308     }
309 
310     /// Returns true if the absolute difference of all elements between `self` and `rhs`
311     /// is less than or equal to `max_abs_diff`.
312     ///
313     /// This can be used to compare if two matrices contain similar elements. It works best
314     /// when comparing with a known value. The `max_abs_diff` that should be used used
315     /// depends on the values being compared against.
316     ///
317     /// For more see
318     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
319     #[inline]
320     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool321     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
322         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
323             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
324     }
325 
326     /// Takes the absolute value of each element in `self`
327     #[inline]
328     #[must_use]
abs(&self) -> Self329     pub fn abs(&self) -> Self {
330         Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
331     }
332 
333     #[inline]
as_mat2(&self) -> Mat2334     pub fn as_mat2(&self) -> Mat2 {
335         Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
336     }
337 }
338 
339 impl Default for DMat2 {
340     #[inline]
default() -> Self341     fn default() -> Self {
342         Self::IDENTITY
343     }
344 }
345 
346 impl Add<DMat2> for DMat2 {
347     type Output = Self;
348     #[inline]
add(self, rhs: Self) -> Self::Output349     fn add(self, rhs: Self) -> Self::Output {
350         self.add_mat2(&rhs)
351     }
352 }
353 
354 impl AddAssign<DMat2> for DMat2 {
355     #[inline]
add_assign(&mut self, rhs: Self)356     fn add_assign(&mut self, rhs: Self) {
357         *self = self.add_mat2(&rhs);
358     }
359 }
360 
361 impl Sub<DMat2> for DMat2 {
362     type Output = Self;
363     #[inline]
sub(self, rhs: Self) -> Self::Output364     fn sub(self, rhs: Self) -> Self::Output {
365         self.sub_mat2(&rhs)
366     }
367 }
368 
369 impl SubAssign<DMat2> for DMat2 {
370     #[inline]
sub_assign(&mut self, rhs: Self)371     fn sub_assign(&mut self, rhs: Self) {
372         *self = self.sub_mat2(&rhs);
373     }
374 }
375 
376 impl Neg for DMat2 {
377     type Output = Self;
378     #[inline]
neg(self) -> Self::Output379     fn neg(self) -> Self::Output {
380         Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
381     }
382 }
383 
384 impl Mul<DMat2> for DMat2 {
385     type Output = Self;
386     #[inline]
mul(self, rhs: Self) -> Self::Output387     fn mul(self, rhs: Self) -> Self::Output {
388         self.mul_mat2(&rhs)
389     }
390 }
391 
392 impl MulAssign<DMat2> for DMat2 {
393     #[inline]
mul_assign(&mut self, rhs: Self)394     fn mul_assign(&mut self, rhs: Self) {
395         *self = self.mul_mat2(&rhs);
396     }
397 }
398 
399 impl Mul<DVec2> for DMat2 {
400     type Output = DVec2;
401     #[inline]
mul(self, rhs: DVec2) -> Self::Output402     fn mul(self, rhs: DVec2) -> Self::Output {
403         self.mul_vec2(rhs)
404     }
405 }
406 
407 impl Mul<DMat2> for f64 {
408     type Output = DMat2;
409     #[inline]
mul(self, rhs: DMat2) -> Self::Output410     fn mul(self, rhs: DMat2) -> Self::Output {
411         rhs.mul_scalar(self)
412     }
413 }
414 
415 impl Mul<f64> for DMat2 {
416     type Output = Self;
417     #[inline]
mul(self, rhs: f64) -> Self::Output418     fn mul(self, rhs: f64) -> Self::Output {
419         self.mul_scalar(rhs)
420     }
421 }
422 
423 impl MulAssign<f64> for DMat2 {
424     #[inline]
mul_assign(&mut self, rhs: f64)425     fn mul_assign(&mut self, rhs: f64) {
426         *self = self.mul_scalar(rhs);
427     }
428 }
429 
430 impl Div<DMat2> for f64 {
431     type Output = DMat2;
432     #[inline]
div(self, rhs: DMat2) -> Self::Output433     fn div(self, rhs: DMat2) -> Self::Output {
434         rhs.div_scalar(self)
435     }
436 }
437 
438 impl Div<f64> for DMat2 {
439     type Output = Self;
440     #[inline]
div(self, rhs: f64) -> Self::Output441     fn div(self, rhs: f64) -> Self::Output {
442         self.div_scalar(rhs)
443     }
444 }
445 
446 impl DivAssign<f64> for DMat2 {
447     #[inline]
div_assign(&mut self, rhs: f64)448     fn div_assign(&mut self, rhs: f64) {
449         *self = self.div_scalar(rhs);
450     }
451 }
452 
453 impl Sum<Self> for DMat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,454     fn sum<I>(iter: I) -> Self
455     where
456         I: Iterator<Item = Self>,
457     {
458         iter.fold(Self::ZERO, Self::add)
459     }
460 }
461 
462 impl<'a> Sum<&'a Self> for DMat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,463     fn sum<I>(iter: I) -> Self
464     where
465         I: Iterator<Item = &'a Self>,
466     {
467         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
468     }
469 }
470 
471 impl Product for DMat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,472     fn product<I>(iter: I) -> Self
473     where
474         I: Iterator<Item = Self>,
475     {
476         iter.fold(Self::IDENTITY, Self::mul)
477     }
478 }
479 
480 impl<'a> Product<&'a Self> for DMat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,481     fn product<I>(iter: I) -> Self
482     where
483         I: Iterator<Item = &'a Self>,
484     {
485         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
486     }
487 }
488 
489 impl PartialEq for DMat2 {
490     #[inline]
eq(&self, rhs: &Self) -> bool491     fn eq(&self, rhs: &Self) -> bool {
492         self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
493     }
494 }
495 
496 #[cfg(not(target_arch = "spirv"))]
497 impl AsRef<[f64; 4]> for DMat2 {
498     #[inline]
as_ref(&self) -> &[f64; 4]499     fn as_ref(&self) -> &[f64; 4] {
500         unsafe { &*(self as *const Self as *const [f64; 4]) }
501     }
502 }
503 
504 #[cfg(not(target_arch = "spirv"))]
505 impl AsMut<[f64; 4]> for DMat2 {
506     #[inline]
as_mut(&mut self) -> &mut [f64; 4]507     fn as_mut(&mut self) -> &mut [f64; 4] {
508         unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
509     }
510 }
511 
512 impl fmt::Debug for DMat2 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result513     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
514         fmt.debug_struct(stringify!(DMat2))
515             .field("x_axis", &self.x_axis)
516             .field("y_axis", &self.y_axis)
517             .finish()
518     }
519 }
520 
521 impl fmt::Display for DMat2 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result522     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
523         if let Some(p) = f.precision() {
524             write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
525         } else {
526             write!(f, "[{}, {}]", self.x_axis, self.y_axis)
527         }
528     }
529 }
530