1use crate::{Angle, Float, Mat3, Num, Signed, Vec2, impl_mat, vec2};
2
3pub type Mat2F = Mat2<f32>;
4
5#[repr(C)]
7#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
8pub struct Mat2<T> {
9 pub x_axis: Vec2<T>,
10 pub y_axis: Vec2<T>,
11}
12
13#[inline]
15pub const fn mat2<T>(x_axis: Vec2<T>, y_axis: Vec2<T>) -> Mat2<T> {
16 Mat2 { x_axis, y_axis }
17}
18
19impl_mat!(
20 NAME = Mat2
21 SHORT = mat2
22 VEC_TY = Vec2
23 MUL_FN = mul_mat2
24 FIELDS = (x_axis, y_axis)
25 CONSTS = (X_AXIS, Y_AXIS)
26);
27
28impl<T: Copy> Mat2<T> {
29 #[inline]
31 pub fn from_mat3(m: &Mat3<T>) -> Self {
32 mat2(m.x_axis.xy(), m.y_axis.xy())
33 }
34
35 #[inline]
37 pub const fn transpose(&self) -> Self {
38 mat2(
39 vec2(self.x_axis.x, self.y_axis.x),
40 vec2(self.x_axis.y, self.y_axis.y),
41 )
42 }
43}
44
45impl<T: Num> Mat2<T> {
46 #[inline]
48 pub fn determinant(&self) -> T {
49 self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
50 }
51
52 #[inline]
54 pub fn transform_vec2(&self, rhs: Vec2<T>) -> Vec2<T> {
55 vec2(
56 self.x_axis.x * rhs.x + self.y_axis.x * rhs.y,
57 self.x_axis.y * rhs.x + self.y_axis.y * rhs.y,
58 )
59 }
60
61 #[inline]
63 pub fn mul_mat2(&self, rhs: &Self) -> Self {
64 mat2(
65 self.transform_vec2(rhs.x_axis),
66 self.transform_vec2(rhs.y_axis),
67 )
68 }
69
70 #[inline]
72 pub fn scale(scale: impl Into<Vec2<T>>) -> Self {
73 let scale = scale.into();
74 mat2(vec2(scale.x, T::ZERO), vec2(T::ZERO, scale.y))
75 }
76}
77
78impl<T: Signed> Mat2<T> {
79 #[inline]
81 pub fn rotation(angle: impl Angle<T>) -> Self {
82 let (sin, cos) = angle.sin_cos();
83 mat2(vec2(cos, sin), vec2(-sin, cos))
84 }
85
86 #[inline]
88 pub fn scale_rotation(scale: impl Into<Vec2<T>>, angle: impl Angle<T>) -> Self {
89 let (sin, cos) = angle.sin_cos();
90 let scale = scale.into();
91 mat2(
92 vec2(cos * scale.x, sin * scale.x),
93 vec2(-sin * scale.y, cos * scale.y),
94 )
95 }
96}
97
98impl<T: Float> Mat2<T> {
99 #[inline]
101 pub fn inverse(&self) -> Option<Self> {
102 let inv_det = {
103 let det = self.determinant();
104 if det == T::ZERO {
105 return None;
106 }
107 T::ONE / det
108 };
109 Some(mat2(
110 vec2(self.y_axis.y * inv_det, self.x_axis.y * -inv_det),
111 vec2(self.y_axis.x * -inv_det, self.x_axis.x * inv_det),
112 ))
113 }
114}