glam/f64/
dmat2.rs

1// Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3use crate::{f64::math, swizzles::*, DMat3, DVec2, Mat2};
4use core::fmt;
5use core::iter::{Product, Sum};
6use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8#[cfg(feature = "zerocopy")]
9use zerocopy_derive::*;
10
11/// Creates a 2x2 matrix from two column vectors.
12#[inline(always)]
13#[must_use]
14pub const fn dmat2(x_axis: DVec2, y_axis: DVec2) -> DMat2 {
15    DMat2::from_cols(x_axis, y_axis)
16}
17
18/// A 2x2 column major matrix.
19#[derive(Clone, Copy)]
20#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
21#[cfg_attr(
22    feature = "zerocopy",
23    derive(FromBytes, Immutable, IntoBytes, KnownLayout)
24)]
25#[cfg_attr(feature = "cuda", repr(align(16)))]
26#[repr(C)]
27pub struct DMat2 {
28    pub x_axis: DVec2,
29    pub y_axis: DVec2,
30}
31
32impl DMat2 {
33    /// A 2x2 matrix with all elements set to `0.0`.
34    pub const ZERO: Self = Self::from_cols(DVec2::ZERO, DVec2::ZERO);
35
36    /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
37    pub const IDENTITY: Self = Self::from_cols(DVec2::X, DVec2::Y);
38
39    /// All NAN:s.
40    pub const NAN: Self = Self::from_cols(DVec2::NAN, DVec2::NAN);
41
42    #[allow(clippy::too_many_arguments)]
43    #[inline(always)]
44    #[must_use]
45    const fn new(m00: f64, m01: f64, m10: f64, m11: f64) -> Self {
46        Self {
47            x_axis: DVec2::new(m00, m01),
48            y_axis: DVec2::new(m10, m11),
49        }
50    }
51
52    /// Creates a 2x2 matrix from two column vectors.
53    #[inline(always)]
54    #[must_use]
55    pub const fn from_cols(x_axis: DVec2, y_axis: DVec2) -> Self {
56        Self { x_axis, y_axis }
57    }
58
59    /// Creates a 2x2 matrix from a `[f64; 4]` array stored in column major order.
60    /// If your data is stored in row major you will need to `transpose` the returned
61    /// matrix.
62    #[inline]
63    #[must_use]
64    pub const fn from_cols_array(m: &[f64; 4]) -> Self {
65        Self::new(m[0], m[1], m[2], m[3])
66    }
67
68    /// Creates a `[f64; 4]` array storing data in column major order.
69    /// If you require data in row major order `transpose` the matrix first.
70    #[inline]
71    #[must_use]
72    pub const fn to_cols_array(&self) -> [f64; 4] {
73        [self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
74    }
75
76    /// Creates a 2x2 matrix from a `[[f64; 2]; 2]` 2D array stored in column major order.
77    /// If your data is in row major order you will need to `transpose` the returned
78    /// matrix.
79    #[inline]
80    #[must_use]
81    pub const fn from_cols_array_2d(m: &[[f64; 2]; 2]) -> Self {
82        Self::from_cols(DVec2::from_array(m[0]), DVec2::from_array(m[1]))
83    }
84
85    /// Creates a `[[f64; 2]; 2]` 2D array storing data in column major order.
86    /// If you require data in row major order `transpose` the matrix first.
87    #[inline]
88    #[must_use]
89    pub const fn to_cols_array_2d(&self) -> [[f64; 2]; 2] {
90        [self.x_axis.to_array(), self.y_axis.to_array()]
91    }
92
93    /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
94    #[doc(alias = "scale")]
95    #[inline]
96    #[must_use]
97    pub const fn from_diagonal(diagonal: DVec2) -> Self {
98        Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
99    }
100
101    /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
102    /// `angle` (in radians).
103    #[inline]
104    #[must_use]
105    pub fn from_scale_angle(scale: DVec2, angle: f64) -> Self {
106        let (sin, cos) = math::sin_cos(angle);
107        Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
108    }
109
110    /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
111    #[inline]
112    #[must_use]
113    pub fn from_angle(angle: f64) -> Self {
114        let (sin, cos) = math::sin_cos(angle);
115        Self::new(cos, sin, -sin, cos)
116    }
117
118    /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
119    #[inline]
120    #[must_use]
121    pub fn from_mat3(m: DMat3) -> Self {
122        Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
123    }
124
125    /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
126    /// and `j`th row.
127    ///
128    /// # Panics
129    ///
130    /// Panics if `i` or `j` is greater than 2.
131    #[inline]
132    #[must_use]
133    pub fn from_mat3_minor(m: DMat3, i: usize, j: usize) -> Self {
134        match (i, j) {
135            (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
136            (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
137            (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
138            (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
139            (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
140            (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
141            (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
142            (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
143            (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
144            _ => panic!("index out of bounds"),
145        }
146    }
147
148    /// Creates a 2x2 matrix from the first 4 values in `slice`.
149    ///
150    /// # Panics
151    ///
152    /// Panics if `slice` is less than 4 elements long.
153    #[inline]
154    #[must_use]
155    pub const fn from_cols_slice(slice: &[f64]) -> Self {
156        Self::new(slice[0], slice[1], slice[2], slice[3])
157    }
158
159    /// Writes the columns of `self` to the first 4 elements in `slice`.
160    ///
161    /// # Panics
162    ///
163    /// Panics if `slice` is less than 4 elements long.
164    #[inline]
165    pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
166        slice[0] = self.x_axis.x;
167        slice[1] = self.x_axis.y;
168        slice[2] = self.y_axis.x;
169        slice[3] = self.y_axis.y;
170    }
171
172    /// Returns the matrix column for the given `index`.
173    ///
174    /// # Panics
175    ///
176    /// Panics if `index` is greater than 1.
177    #[inline]
178    #[must_use]
179    pub fn col(&self, index: usize) -> DVec2 {
180        match index {
181            0 => self.x_axis,
182            1 => self.y_axis,
183            _ => panic!("index out of bounds"),
184        }
185    }
186
187    /// Returns a mutable reference to the matrix column for the given `index`.
188    ///
189    /// # Panics
190    ///
191    /// Panics if `index` is greater than 1.
192    #[inline]
193    pub fn col_mut(&mut self, index: usize) -> &mut DVec2 {
194        match index {
195            0 => &mut self.x_axis,
196            1 => &mut self.y_axis,
197            _ => panic!("index out of bounds"),
198        }
199    }
200
201    /// Returns the matrix row for the given `index`.
202    ///
203    /// # Panics
204    ///
205    /// Panics if `index` is greater than 1.
206    #[inline]
207    #[must_use]
208    pub fn row(&self, index: usize) -> DVec2 {
209        match index {
210            0 => DVec2::new(self.x_axis.x, self.y_axis.x),
211            1 => DVec2::new(self.x_axis.y, self.y_axis.y),
212            _ => panic!("index out of bounds"),
213        }
214    }
215
216    /// Returns `true` if, and only if, all elements are finite.
217    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
218    #[inline]
219    #[must_use]
220    pub fn is_finite(&self) -> bool {
221        self.x_axis.is_finite() && self.y_axis.is_finite()
222    }
223
224    /// Returns `true` if any elements are `NaN`.
225    #[inline]
226    #[must_use]
227    pub fn is_nan(&self) -> bool {
228        self.x_axis.is_nan() || self.y_axis.is_nan()
229    }
230
231    /// Returns the transpose of `self`.
232    #[inline]
233    #[must_use]
234    pub fn transpose(&self) -> Self {
235        Self {
236            x_axis: DVec2::new(self.x_axis.x, self.y_axis.x),
237            y_axis: DVec2::new(self.x_axis.y, self.y_axis.y),
238        }
239    }
240
241    /// Returns the diagonal of `self`.
242    #[inline]
243    #[must_use]
244    pub fn diagonal(&self) -> DVec2 {
245        DVec2::new(self.x_axis.x, self.y_axis.y)
246    }
247
248    /// Returns the determinant of `self`.
249    #[inline]
250    #[must_use]
251    pub fn determinant(&self) -> f64 {
252        self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
253    }
254
255    /// If `CHECKED` is true then if the determinant is zero this function will return a tuple
256    /// containing a zero matrix and false. If the determinant is non zero a tuple containing the
257    /// inverted matrix and true is returned.
258    ///
259    /// If `CHECKED` is false then the determinant is not checked and if it is zero the resulting
260    /// inverted matrix will be invalid. Will panic if the determinant of `self` is zero when
261    /// `glam_assert` is enabled.
262    ///
263    /// A tuple containing the inverted matrix and a bool is used instead of an option here as
264    /// regular Rust enums put the discriminant first which can result in a lot of padding if the
265    /// matrix is aligned.
266    #[inline(always)]
267    #[must_use]
268    fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
269        let det = self.determinant();
270        if CHECKED {
271            if det == 0.0 {
272                return (Self::ZERO, false);
273            }
274        } else {
275            glam_assert!(det != 0.0);
276        }
277        let inv_det = det.recip();
278        (
279            Self::new(
280                self.y_axis.y * inv_det,
281                self.x_axis.y * -inv_det,
282                self.y_axis.x * -inv_det,
283                self.x_axis.x * inv_det,
284            ),
285            true,
286        )
287    }
288
289    /// Returns the inverse of `self`.
290    ///
291    /// If the matrix is not invertible the returned matrix will be invalid.
292    ///
293    /// # Panics
294    ///
295    /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
296    #[inline]
297    #[must_use]
298    pub fn inverse(&self) -> Self {
299        self.inverse_checked::<false>().0
300    }
301
302    /// Returns the inverse of `self` or `None` if the matrix is not invertible.
303    #[inline]
304    #[must_use]
305    pub fn try_inverse(&self) -> Option<Self> {
306        let (m, is_valid) = self.inverse_checked::<true>();
307        if is_valid {
308            Some(m)
309        } else {
310            None
311        }
312    }
313
314    /// Returns the inverse of `self` or `DMat2::ZERO` if the matrix is not invertible.
315    #[inline]
316    #[must_use]
317    pub fn inverse_or_zero(&self) -> Self {
318        self.inverse_checked::<true>().0
319    }
320
321    /// Transforms a 2D vector.
322    #[inline]
323    #[must_use]
324    pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
325        #[allow(clippy::suspicious_operation_groupings)]
326        DVec2::new(
327            (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
328            (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
329        )
330    }
331
332    /// Transforms a 2D vector by the transpose of `self`.
333    #[inline]
334    #[must_use]
335    pub fn mul_transpose_vec2(&self, rhs: DVec2) -> DVec2 {
336        DVec2::new(self.x_axis.dot(rhs), self.y_axis.dot(rhs))
337    }
338
339    /// Multiplies two 2x2 matrices.
340    #[inline]
341    #[must_use]
342    pub fn mul_mat2(&self, rhs: &Self) -> Self {
343        self.mul(rhs)
344    }
345
346    /// Adds two 2x2 matrices.
347    #[inline]
348    #[must_use]
349    pub fn add_mat2(&self, rhs: &Self) -> Self {
350        self.add(rhs)
351    }
352
353    /// Subtracts two 2x2 matrices.
354    #[inline]
355    #[must_use]
356    pub fn sub_mat2(&self, rhs: &Self) -> Self {
357        self.sub(rhs)
358    }
359
360    /// Multiplies a 2x2 matrix by a scalar.
361    #[inline]
362    #[must_use]
363    pub fn mul_scalar(&self, rhs: f64) -> Self {
364        Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
365    }
366
367    /// Multiply `self` by a scaling vector `scale`.
368    /// This is faster than creating a whole diagonal scaling matrix and then multiplying that.
369    /// This operation is commutative.
370    #[inline]
371    #[must_use]
372    pub fn mul_diagonal_scale(&self, scale: DVec2) -> Self {
373        Self::from_cols(self.x_axis * scale.x, self.y_axis * scale.y)
374    }
375
376    /// Divides a 2x2 matrix by a scalar.
377    #[inline]
378    #[must_use]
379    pub fn div_scalar(&self, rhs: f64) -> Self {
380        let rhs = DVec2::splat(rhs);
381        Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
382    }
383
384    /// Returns true if the absolute difference of all elements between `self` and `rhs`
385    /// is less than or equal to `max_abs_diff`.
386    ///
387    /// This can be used to compare if two matrices contain similar elements. It works best
388    /// when comparing with a known value. The `max_abs_diff` that should be used used
389    /// depends on the values being compared against.
390    ///
391    /// For more see
392    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
393    #[inline]
394    #[must_use]
395    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
396        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
397            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
398    }
399
400    /// Takes the absolute value of each element in `self`
401    #[inline]
402    #[must_use]
403    pub fn abs(&self) -> Self {
404        Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
405    }
406
407    #[inline]
408    pub fn as_mat2(&self) -> Mat2 {
409        Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
410    }
411}
412
413impl Default for DMat2 {
414    #[inline]
415    fn default() -> Self {
416        Self::IDENTITY
417    }
418}
419
420impl Add for DMat2 {
421    type Output = Self;
422    #[inline]
423    fn add(self, rhs: Self) -> Self {
424        Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
425    }
426}
427
428impl Add<&Self> for DMat2 {
429    type Output = Self;
430    #[inline]
431    fn add(self, rhs: &Self) -> Self {
432        self.add(*rhs)
433    }
434}
435
436impl Add<&DMat2> for &DMat2 {
437    type Output = DMat2;
438    #[inline]
439    fn add(self, rhs: &DMat2) -> DMat2 {
440        (*self).add(*rhs)
441    }
442}
443
444impl Add<DMat2> for &DMat2 {
445    type Output = DMat2;
446    #[inline]
447    fn add(self, rhs: DMat2) -> DMat2 {
448        (*self).add(rhs)
449    }
450}
451
452impl AddAssign for DMat2 {
453    #[inline]
454    fn add_assign(&mut self, rhs: Self) {
455        *self = self.add(rhs);
456    }
457}
458
459impl AddAssign<&Self> for DMat2 {
460    #[inline]
461    fn add_assign(&mut self, rhs: &Self) {
462        self.add_assign(*rhs);
463    }
464}
465
466impl Sub for DMat2 {
467    type Output = Self;
468    #[inline]
469    fn sub(self, rhs: Self) -> Self {
470        Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
471    }
472}
473
474impl Sub<&Self> for DMat2 {
475    type Output = Self;
476    #[inline]
477    fn sub(self, rhs: &Self) -> Self {
478        self.sub(*rhs)
479    }
480}
481
482impl Sub<&DMat2> for &DMat2 {
483    type Output = DMat2;
484    #[inline]
485    fn sub(self, rhs: &DMat2) -> DMat2 {
486        (*self).sub(*rhs)
487    }
488}
489
490impl Sub<DMat2> for &DMat2 {
491    type Output = DMat2;
492    #[inline]
493    fn sub(self, rhs: DMat2) -> DMat2 {
494        (*self).sub(rhs)
495    }
496}
497
498impl SubAssign for DMat2 {
499    #[inline]
500    fn sub_assign(&mut self, rhs: Self) {
501        *self = self.sub(rhs);
502    }
503}
504
505impl SubAssign<&Self> for DMat2 {
506    #[inline]
507    fn sub_assign(&mut self, rhs: &Self) {
508        self.sub_assign(*rhs);
509    }
510}
511
512impl Neg for DMat2 {
513    type Output = Self;
514    #[inline]
515    fn neg(self) -> Self::Output {
516        Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
517    }
518}
519
520impl Neg for &DMat2 {
521    type Output = DMat2;
522    #[inline]
523    fn neg(self) -> DMat2 {
524        (*self).neg()
525    }
526}
527
528impl Mul for DMat2 {
529    type Output = Self;
530    #[inline]
531    fn mul(self, rhs: Self) -> Self {
532        Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
533    }
534}
535
536impl Mul<&Self> for DMat2 {
537    type Output = Self;
538    #[inline]
539    fn mul(self, rhs: &Self) -> Self {
540        self.mul(*rhs)
541    }
542}
543
544impl Mul<&DMat2> for &DMat2 {
545    type Output = DMat2;
546    #[inline]
547    fn mul(self, rhs: &DMat2) -> DMat2 {
548        (*self).mul(*rhs)
549    }
550}
551
552impl Mul<DMat2> for &DMat2 {
553    type Output = DMat2;
554    #[inline]
555    fn mul(self, rhs: DMat2) -> DMat2 {
556        (*self).mul(rhs)
557    }
558}
559
560impl MulAssign for DMat2 {
561    #[inline]
562    fn mul_assign(&mut self, rhs: Self) {
563        *self = self.mul(rhs);
564    }
565}
566
567impl MulAssign<&Self> for DMat2 {
568    #[inline]
569    fn mul_assign(&mut self, rhs: &Self) {
570        self.mul_assign(*rhs);
571    }
572}
573
574impl Mul<DVec2> for DMat2 {
575    type Output = DVec2;
576    #[inline]
577    fn mul(self, rhs: DVec2) -> Self::Output {
578        self.mul_vec2(rhs)
579    }
580}
581
582impl Mul<&DVec2> for DMat2 {
583    type Output = DVec2;
584    #[inline]
585    fn mul(self, rhs: &DVec2) -> DVec2 {
586        self.mul(*rhs)
587    }
588}
589
590impl Mul<&DVec2> for &DMat2 {
591    type Output = DVec2;
592    #[inline]
593    fn mul(self, rhs: &DVec2) -> DVec2 {
594        (*self).mul(*rhs)
595    }
596}
597
598impl Mul<DVec2> for &DMat2 {
599    type Output = DVec2;
600    #[inline]
601    fn mul(self, rhs: DVec2) -> DVec2 {
602        (*self).mul(rhs)
603    }
604}
605
606impl Mul<DMat2> for f64 {
607    type Output = DMat2;
608    #[inline]
609    fn mul(self, rhs: DMat2) -> Self::Output {
610        rhs.mul_scalar(self)
611    }
612}
613
614impl Mul<&DMat2> for f64 {
615    type Output = DMat2;
616    #[inline]
617    fn mul(self, rhs: &DMat2) -> DMat2 {
618        self.mul(*rhs)
619    }
620}
621
622impl Mul<&DMat2> for &f64 {
623    type Output = DMat2;
624    #[inline]
625    fn mul(self, rhs: &DMat2) -> DMat2 {
626        (*self).mul(*rhs)
627    }
628}
629
630impl Mul<DMat2> for &f64 {
631    type Output = DMat2;
632    #[inline]
633    fn mul(self, rhs: DMat2) -> DMat2 {
634        (*self).mul(rhs)
635    }
636}
637
638impl Mul<f64> for DMat2 {
639    type Output = Self;
640    #[inline]
641    fn mul(self, rhs: f64) -> Self {
642        self.mul_scalar(rhs)
643    }
644}
645
646impl Mul<&f64> for DMat2 {
647    type Output = Self;
648    #[inline]
649    fn mul(self, rhs: &f64) -> Self {
650        self.mul(*rhs)
651    }
652}
653
654impl Mul<&f64> for &DMat2 {
655    type Output = DMat2;
656    #[inline]
657    fn mul(self, rhs: &f64) -> DMat2 {
658        (*self).mul(*rhs)
659    }
660}
661
662impl Mul<f64> for &DMat2 {
663    type Output = DMat2;
664    #[inline]
665    fn mul(self, rhs: f64) -> DMat2 {
666        (*self).mul(rhs)
667    }
668}
669
670impl MulAssign<f64> for DMat2 {
671    #[inline]
672    fn mul_assign(&mut self, rhs: f64) {
673        *self = self.mul(rhs);
674    }
675}
676
677impl MulAssign<&f64> for DMat2 {
678    #[inline]
679    fn mul_assign(&mut self, rhs: &f64) {
680        self.mul_assign(*rhs);
681    }
682}
683
684impl Div<DMat2> for f64 {
685    type Output = DMat2;
686    #[inline]
687    fn div(self, rhs: DMat2) -> Self::Output {
688        rhs.div_scalar(self)
689    }
690}
691
692impl Div<&DMat2> for f64 {
693    type Output = DMat2;
694    #[inline]
695    fn div(self, rhs: &DMat2) -> DMat2 {
696        self.div(*rhs)
697    }
698}
699
700impl Div<&DMat2> for &f64 {
701    type Output = DMat2;
702    #[inline]
703    fn div(self, rhs: &DMat2) -> DMat2 {
704        (*self).div(*rhs)
705    }
706}
707
708impl Div<DMat2> for &f64 {
709    type Output = DMat2;
710    #[inline]
711    fn div(self, rhs: DMat2) -> DMat2 {
712        (*self).div(rhs)
713    }
714}
715
716impl Div<f64> for DMat2 {
717    type Output = Self;
718    #[inline]
719    fn div(self, rhs: f64) -> Self {
720        self.div_scalar(rhs)
721    }
722}
723
724impl Div<&f64> for DMat2 {
725    type Output = Self;
726    #[inline]
727    fn div(self, rhs: &f64) -> Self {
728        self.div(*rhs)
729    }
730}
731
732impl Div<&f64> for &DMat2 {
733    type Output = DMat2;
734    #[inline]
735    fn div(self, rhs: &f64) -> DMat2 {
736        (*self).div(*rhs)
737    }
738}
739
740impl Div<f64> for &DMat2 {
741    type Output = DMat2;
742    #[inline]
743    fn div(self, rhs: f64) -> DMat2 {
744        (*self).div(rhs)
745    }
746}
747
748impl DivAssign<f64> for DMat2 {
749    #[inline]
750    fn div_assign(&mut self, rhs: f64) {
751        *self = self.div(rhs);
752    }
753}
754
755impl DivAssign<&f64> for DMat2 {
756    #[inline]
757    fn div_assign(&mut self, rhs: &f64) {
758        self.div_assign(*rhs);
759    }
760}
761
762impl Sum<Self> for DMat2 {
763    fn sum<I>(iter: I) -> Self
764    where
765        I: Iterator<Item = Self>,
766    {
767        iter.fold(Self::ZERO, Self::add)
768    }
769}
770
771impl<'a> Sum<&'a Self> for DMat2 {
772    fn sum<I>(iter: I) -> Self
773    where
774        I: Iterator<Item = &'a Self>,
775    {
776        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
777    }
778}
779
780impl Product for DMat2 {
781    fn product<I>(iter: I) -> Self
782    where
783        I: Iterator<Item = Self>,
784    {
785        iter.fold(Self::IDENTITY, Self::mul)
786    }
787}
788
789impl<'a> Product<&'a Self> for DMat2 {
790    fn product<I>(iter: I) -> Self
791    where
792        I: Iterator<Item = &'a Self>,
793    {
794        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
795    }
796}
797
798impl PartialEq for DMat2 {
799    #[inline]
800    fn eq(&self, rhs: &Self) -> bool {
801        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
802    }
803}
804
805impl AsRef<[f64; 4]> for DMat2 {
806    #[inline]
807    fn as_ref(&self) -> &[f64; 4] {
808        unsafe { &*(self as *const Self as *const [f64; 4]) }
809    }
810}
811
812impl AsMut<[f64; 4]> for DMat2 {
813    #[inline]
814    fn as_mut(&mut self) -> &mut [f64; 4] {
815        unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
816    }
817}
818
819impl fmt::Debug for DMat2 {
820    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
821        fmt.debug_struct(stringify!(DMat2))
822            .field("x_axis", &self.x_axis)
823            .field("y_axis", &self.y_axis)
824            .finish()
825    }
826}
827
828impl fmt::Display for DMat2 {
829    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
830        if let Some(p) = f.precision() {
831            write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
832        } else {
833            write!(f, "[{}, {}]", self.x_axis, self.y_axis)
834        }
835    }
836}