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