1use glium::uniforms::AsUniformValue;
2use crate::prelude::Vec2;
3use super::{Mat3, Mat4};
4
5#[derive(Clone, Copy, PartialEq, Debug)]
6pub struct Mat2 {
8 matrix: [[f32; 2]; 2]
9}
10impl Mat2{
11 pub const IDENTITY: Self = Mat2::from_values(
12 1.0, 0.0,
13 0.0, 1.0,
14 );
15 pub const fn from_column_major_array(array: [[f32; 2]; 2]) -> Self { Self { matrix: array } }
16 pub const fn into_column_major_array(self) -> [[f32; 2]; 2] { self.matrix }
17 pub const fn from_row_major_array(array: [[f32; 2]; 2]) -> Self { Self { matrix: array }.transpose() }
18 pub const fn into_row_major_array(self) -> [[f32; 2]; 2] { self.transpose().matrix }
19 pub const fn from_scale(scale: Vec2) -> Self{
20 Mat2::from_values(
21 scale.x, 0.0,
22 0.0, scale.y
23 )
24 }
25 pub fn from_transform(scale: Vec2, rot: f32) -> Self{
26 Self::from_values(
27 rot.cos()*scale.x, -rot.sin()*scale.y,
28 rot.sin()*scale.x, rot.cos()*scale.y
29 )
30 }
31 pub fn from_rot(rot: f32) -> Self{
32 Self::from_values(
33 rot.cos(), -rot.sin(),
34 rot.sin(), rot.cos()
35 )
36 }
37 pub const fn from_values(
47 a: f32, b: f32,
48 c: f32, d: f32
49 ) -> Self{
50 Self{
51 matrix: [
53 [a, c],
54 [b, d]
55 ]
56 }
57 }
58 pub fn scale(&self, scalar: f32) -> Mat2 {
59 let Mat2 { matrix: [
60 [a, c],
61 [b, d]
62 ]} = self;
63 Self::from_values(
64 a * scalar, b * scalar,
65 c * scalar, d * scalar
66 )
67 }
68 pub const fn transpose(self) -> Self {
69 let Mat2 { matrix: [
70 [a, c],
71 [b, d]
72 ] } = self;
73 Mat2::from_values(
74 a, c,
75 b, d
76 )
77 }
78 pub fn determinant(&self) -> f32 {
79 let Mat2 { matrix: [
80 [a, c],
81 [b, d]
82 ]} = self;
83 a*d - b*c
84 }
85 pub fn inverse(&self) -> Mat2 {
86 let Mat2 { matrix: [
87 [a, c],
88 [b, d]
89 ]} = self;
90
91 let scalar = 1.0/self.determinant();
92 Self::from_values(
93 *d, -b,
94 -c, *a
95 ).scale(scalar)
96 }
97 pub const fn column(&self, pos: usize) -> [f32; 2] {
98 self.matrix[pos]
99 }
100 pub const fn row(&self, pos: usize) -> [f32; 2] {
101 let matrix = self.matrix;
102 [matrix[0][pos], matrix[1][pos]]
103 }
104}
105impl Default for Mat2 {
106 fn default() -> Self {
107 Self { matrix: [
108 [1.0, 0.0],
109 [0.0, 1.0],
110 ] }
111 }
112}
113impl std::ops::Mul<Vec2> for Mat2 {
114 fn mul(self, rhs: Vec2) -> Self::Output { rhs.transform(self) }
115 type Output = Vec2;
116}
117impl std::ops::Mul<f32> for Mat2 {
118 fn mul(self, rhs: f32) -> Self::Output { self.scale(rhs) }
119 type Output = Self;
120}
121impl std::ops::MulAssign<f32> for Mat2 {
122 fn mul_assign(&mut self, rhs: f32) { *self = *self * rhs }
123}
124impl std::ops::Mul<Mat2> for f32 {
125 fn mul(self, rhs: Mat2) -> Self::Output { rhs * self }
126 type Output = Mat2;
127}
128impl std::ops::Div<f32> for Mat2 {
129 fn div(self, rhs: f32) -> Self::Output { self.scale(1.0/rhs) }
130 type Output = Self;
131}
132impl std::ops::DivAssign<f32> for Mat2 {
133 fn div_assign(&mut self, rhs: f32) { *self = *self / rhs }
134}
135impl std::ops::Div<Mat2> for f32 {
136 fn div(self, rhs: Mat2) -> Self::Output {
137 let Mat2 { matrix: [
138 [a, c],
139 [b, d]
140 ] } = rhs;
141 Mat2::from_values(
142 self/a, self/b,
143 self/c, self/d
144 )
145 }
146 type Output = Mat2;
147}
148impl std::ops::Rem<f32> for Mat2 {
149 fn rem(self, rhs: f32) -> Self::Output {
150 let Mat2 { matrix: [
151 [a, c],
152 [b, d]
153 ] } = self;
154 Mat2::from_values(
155 a%rhs, b%rhs,
156 c%rhs, d%rhs
157 )
158 }
159 type Output = Self;
160}
161impl std::ops::RemAssign<f32> for Mat2 {
162 fn rem_assign(&mut self, rhs: f32) { *self = *self % rhs }
163}
164impl std::ops::Rem<Mat2> for f32 {
165 fn rem(self, rhs: Mat2) -> Self::Output {
166 let Mat2 { matrix: [
167 [a, c],
168 [b, d]
169 ] } = rhs;
170 Mat2::from_values(
171 self%a, self%b,
172 self%c, self%d
173 )
174 }
175 type Output = Mat2;
176}
177#[allow(clippy::needless_range_loop)]
178impl std::ops::Mul for Mat2 {
179 fn mul(self, rhs: Self) -> Self::Output {
180 let mut matrix = [[0.0; 2]; 2];
181 for x in 0..2 {
182 for y in 0..2 {
183 matrix[x][y] = Vec2::dot(self.row(y).into(), rhs.column(x).into());
184 }
185 }
186 Self {
187 matrix
188 }
189 }
190 type Output = Self;
191}
192impl std::ops::MulAssign for Mat2 {
193 fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs }
194}
195#[allow(clippy::suspicious_arithmetic_impl)]
196impl std::ops::Div for Mat2 {
197 fn div(self, rhs: Self) -> Self::Output { self * rhs.inverse() }
198 type Output = Self;
199}
200impl std::ops::DivAssign for Mat2 {
201 fn div_assign(&mut self, rhs: Self) { *self = *self / rhs }
202}
203impl AsUniformValue for Mat2 {
204 fn as_uniform_value(&self) -> glium::uniforms::UniformValue<'_> {
205 glium::uniforms::UniformValue::Mat2(self.matrix)
206 }
207}
208impl From<Mat3> for Mat2 {
209 fn from(value: Mat3) -> Self {
210 Self::from_values(
211 value[0][0], value[0][1],
212 value[1][0], value[1][1]
213 )
214 }
215}
216impl From<Mat4> for Mat2 {
217 fn from(value: Mat4) -> Self {
218 Self::from_values(
219 value[0][0], value[0][1],
220 value[1][0], value[1][1]
221 )
222 }
223}
224impl std::ops::Index<usize> for Mat2 {
225 fn index(&self, index: usize) -> &Self::Output {
226 &self.matrix[index]
227 }
228
229 type Output = [f32; 2];
230}
231impl std::ops::IndexMut<usize> for Mat2 {
232 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
233 &mut self.matrix[index]
234 }
235}
236#[test]
237fn test_inverse() {
238 let mut a = Mat2::from_values(
239 4.0, 0.0,
240 1.0, 3.0
241 );
242 a = a.inverse() * a;
243 assert!(a == Mat2::IDENTITY)
244}
245#[test]
246fn addition() {
247 let a = Mat2::IDENTITY;
248 assert_eq!(a + a, Mat2::from_values(
249 2.0, 0.0,
250 0.0, 2.0
251 ))
252}
253
254impl std::ops::Add for Mat2{
255 fn add(self, rhs: Self) -> Self::Output {
256 let a = self.matrix;
257 let b = rhs.matrix;
258 Self{
259 matrix:[
260 [a[0][0] + b[0][0], a[0][1] + b[0][1]],
261 [a[1][0] + b[1][0], a[1][1] + b[1][1]]
262 ]
263 }
264 }
265 type Output = Self;
266}
267impl std::ops::AddAssign for Mat2{
268 fn add_assign(&mut self, rhs: Self) {
269 let a = self.matrix;
270 let b = rhs.matrix;
271 *self = Self{
272 matrix:[
273 [a[0][0] + b[0][0], a[0][1] + b[0][1]],
274 [a[1][0] + b[1][0], a[1][1] + b[1][1]]
275 ]
276 };
277 }
278}
279impl std::ops::Sub for Mat2{
280 fn sub(self, rhs: Self) -> Self::Output {
281 let a = self.matrix;
282 let b = rhs.matrix;
283 Self{
284 matrix:[
285 [a[0][0] - b[0][0], a[0][1] - b[0][1]],
286 [a[1][0] - b[1][0], a[1][1] - b[1][1]]
287 ]
288 }
289 }
290 type Output = Self;
291}
292impl std::ops::SubAssign for Mat2{
293 fn sub_assign(&mut self, rhs: Self) {
294 *self = *self - rhs
295 }
296}