1#![allow(dead_code)]
2
3use std::{
4 fmt::Display,
5 ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
6};
7
8use crate::algebra::{vec2d, Mat2f, Mat3d, Mat4d, Vec2d};
9
10#[derive(Clone, Copy, PartialEq, Debug)]
11pub struct Mat2d {
12 x_axis: Vec2d,
13 y_axis: Vec2d,
14}
15
16pub fn mat2d(m00: f64, m01: f64, m10: f64, m11: f64) -> Mat2d {
17 Mat2d::from_array([m00, m01, m10, m11])
18}
19
20impl Display for Mat2d {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 write!(
23 f,
24 "Mat2d({}, {} | {}, {})",
25 self.x_axis.x(),
26 self.x_axis.y(),
27 self.y_axis.x(),
28 self.y_axis.y()
29 )
30 }
31}
32
33impl Default for Mat2d {
34 fn default() -> Self {
35 Self {
36 x_axis: Vec2d::default(),
37 y_axis: Vec2d::default(),
38 }
39 }
40}
41
42impl Add<Mat2d> for Mat2d {
43 type Output = Mat2d;
44
45 fn add(self, rhs: Mat2d) -> Self::Output {
46 Mat2d::new(self.x_axis + rhs.x_axis, self.y_axis + rhs.y_axis)
47 }
48}
49
50impl Add<f64> for Mat2d {
51 type Output = Mat2d;
52
53 fn add(self, rhs: f64) -> Self::Output {
54 Mat2d::new(self.x_axis + rhs, self.y_axis + rhs)
55 }
56}
57
58impl Add<Mat2d> for f64 {
59 type Output = Mat2d;
60
61 fn add(self, rhs: Mat2d) -> Self::Output {
62 Mat2d::new(self + rhs.x_axis, self + rhs.y_axis)
63 }
64}
65
66impl AddAssign<Mat2d> for Mat2d {
67 fn add_assign(&mut self, rhs: Mat2d) {
68 *self = *self + rhs;
69 }
70}
71
72impl AddAssign<f64> for Mat2d {
73 fn add_assign(&mut self, rhs: f64) {
74 *self = *self + rhs;
75 }
76}
77
78impl Sub<Mat2d> for Mat2d {
79 type Output = Mat2d;
80
81 fn sub(self, rhs: Mat2d) -> Self::Output {
82 Mat2d::new(self.x_axis - rhs.x_axis, self.y_axis - rhs.y_axis)
83 }
84}
85
86impl Sub<f64> for Mat2d {
87 type Output = Mat2d;
88
89 fn sub(self, rhs: f64) -> Self::Output {
90 Mat2d::new(self.x_axis - rhs, self.y_axis - rhs)
91 }
92}
93
94impl Sub<Mat2d> for f64 {
95 type Output = Mat2d;
96
97 fn sub(self, rhs: Mat2d) -> Self::Output {
98 Mat2d::new(self - rhs.x_axis, self - rhs.y_axis)
99 }
100}
101
102impl SubAssign<Mat2d> for Mat2d {
103 fn sub_assign(&mut self, rhs: Mat2d) {
104 *self = *self - rhs;
105 }
106}
107
108impl SubAssign<f64> for Mat2d {
109 fn sub_assign(&mut self, rhs: f64) {
110 *self = *self - rhs;
111 }
112}
113
114impl Mul<Mat2d> for Mat2d {
115 type Output = Mat2d;
116
117 fn mul(self, rhs: Mat2d) -> Self::Output {
118 let m00 = self.x_axis.dot(vec2d(rhs[0][0], rhs[1][0]));
119 let m01 = self.x_axis.dot(vec2d(rhs[0][1], rhs[1][1]));
120 let m10 = self.y_axis.dot(vec2d(rhs[0][0], rhs[1][0]));
121 let m11 = self.y_axis.dot(vec2d(rhs[0][1], rhs[1][1]));
122 Mat2d::new(vec2d(m00, m01), vec2d(m10, m11))
123 }
124}
125
126impl Mul<Vec2d> for Mat2d {
127 type Output = Vec2d;
128
129 fn mul(self, rhs: Vec2d) -> Self::Output {
130 let v0 = self.x_axis.dot(rhs);
131 let v1 = self.y_axis.dot(rhs);
132 vec2d(v0, v1)
133 }
134}
135
136impl Mul<f64> for Mat2d {
137 type Output = Mat2d;
138
139 fn mul(self, rhs: f64) -> Self::Output {
140 Mat2d::new(self.x_axis * rhs, self.y_axis * rhs)
141 }
142}
143
144impl Mul<Mat2d> for f64 {
145 type Output = Mat2d;
146
147 fn mul(self, rhs: Mat2d) -> Self::Output {
148 Mat2d::new(self * rhs.x_axis, self * rhs.y_axis)
149 }
150}
151
152impl MulAssign<Mat2d> for Mat2d {
153 fn mul_assign(&mut self, rhs: Mat2d) {
154 *self = *self * rhs;
155 }
156}
157
158impl MulAssign<f64> for Mat2d {
159 fn mul_assign(&mut self, rhs: f64) {
160 *self = *self * rhs;
161 }
162}
163
164impl Div<f64> for Mat2d {
165 type Output = Mat2d;
166
167 fn div(self, rhs: f64) -> Self::Output {
168 Mat2d::new(self.x_axis / rhs, self.y_axis / rhs)
169 }
170}
171
172impl DivAssign<f64> for Mat2d {
173 fn div_assign(&mut self, rhs: f64) {
174 *self = *self / rhs;
175 }
176}
177
178impl Index<usize> for Mat2d {
179 type Output = Vec2d;
180
181 fn index(&self, index: usize) -> &Self::Output {
182 match index {
183 0 => &self.x_axis,
184 1 => &self.y_axis,
185 _ => panic!("`rmath::algebra::Mat2d::index`: index out of bounds."),
186 }
187 }
188}
189
190impl IndexMut<usize> for Mat2d {
191 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
192 match index {
193 0 => &mut self.x_axis,
194 1 => &mut self.y_axis,
195 _ => panic!("`rmath::algebra::Mat2d::index_mut`: index out of bounds."),
196 }
197 }
198}
199
200impl Mat2d {
201 pub fn new(x_axis: Vec2d, y_axis: Vec2d) -> Self {
202 Self { x_axis, y_axis }
203 }
204
205 pub fn zero() -> Self {
206 Self::new(vec2d(0.0, 0.0), vec2d(0.0, 0.0))
207 }
208
209 pub fn identity() -> Self {
210 Self::new(vec2d(1.0, 0.0), vec2d(0.0, 1.0))
211 }
212}
213
214impl Mat2d {
215 pub fn col(&self, index: usize) -> Vec2d {
216 match index {
217 0 => vec2d(self[0][0], self[1][0]),
218 1 => vec2d(self[0][1], self[1][1]),
219 _ => panic!("`rmath::algebra::Mat2d::col`: index out of bounds."),
220 }
221 }
222
223 pub fn row(&self, index: usize) -> Vec2d {
224 match index {
225 0 => self.x_axis,
226 1 => self.y_axis,
227 _ => panic!("`rmath::algebra::Mat2d::row`: index out of bounds."),
228 }
229 }
230
231 pub fn is_nan(&self) -> bool {
232 self.x_axis.is_nan() || self.y_axis.is_nan()
233 }
234
235 pub fn is_infinite(&self) -> bool {
236 self.x_axis.is_infinite() || self.y_axis.is_infinite()
237 }
238
239 pub fn is_finite(&self) -> bool {
240 self.x_axis.is_finite() && self.y_axis.is_finite()
241 }
242
243 pub fn transpose(&self) -> Self {
244 let (m00, m01) = self.x_axis.to_tuple();
245 let (m10, m11) = self.y_axis.to_tuple();
246 Self::new(vec2d(m00, m10), vec2d(m01, m11))
247 }
248
249 pub fn determinant(&self) -> f64 {
250 let (m00, m01) = self.x_axis.to_tuple();
251 let (m10, m11) = self.y_axis.to_tuple();
252 m00 * m11 - m01 * m10
253 }
254
255 pub fn inverse(&self) -> Self {
256 let det = self.determinant();
257 ruby_assert!(!(det.abs() < f64::EPSILON));
258
259 let inv_det = det.recip();
260 let a00 = self[1][1];
261 let a01 = -self[1][0];
262 let a10 = -self[0][1];
263 let a11 = self[0][0];
264
265 Self::new(vec2d(a00, a10), vec2d(a01, a11)).mul(inv_det)
266 }
267
268 pub fn try_inverse(&self) -> Option<Self> {
269 let det = self.determinant();
270 if det.abs() < f64::EPSILON {
271 return None;
272 }
273
274 let inv_det = det.recip();
275 let a00 = self[1][1];
276 let a01 = -self[1][0];
277 let a10 = -self[0][1];
278 let a11 = self[0][0];
279
280 Some(Self::new(vec2d(a00, a10), vec2d(a01, a11)).mul(inv_det))
281 }
282}
283
284impl From<Mat3d> for Mat2d {
285 fn from(m: Mat3d) -> Self {
286 mat2d(m[0][0], m[0][1], m[1][0], m[1][1])
287 }
288}
289
290impl From<Mat4d> for Mat2d {
291 fn from(m: Mat4d) -> Self {
292 mat2d(m[0][0], m[0][1], m[1][0], m[1][1])
293 }
294}
295
296impl Mat2d {
297 pub fn from_array(m: [f64; 4]) -> Self {
298 Self::new(vec2d(m[0], m[1]), vec2d(m[2], m[3]))
299 }
300
301 pub fn from_array_2d(m: [[f64; 2]; 2]) -> Self {
302 Self::new(vec2d(m[0][0], m[0][1]), vec2d(m[1][0], m[1][1]))
303 }
304
305 pub fn from_diagonal(diagonal: Vec2d) -> Self {
306 Self::new(vec2d(diagonal.x(), 0.0), vec2d(0.0, diagonal.y()))
307 }
308}
309
310impl Mat2d {
311 pub fn to_array(self) -> [f64; 4] {
312 [self[0][0], self[0][1], self[1][0], self[1][1]]
313 }
314
315 pub fn to_array_2d(self) -> [[f64; 2]; 2] {
316 [[self[0][0], self[0][1]], [self[1][0], self[1][1]]]
317 }
318
319 pub fn to_mat3d(self) -> Mat3d {
320 Mat3d::from(self)
321 }
322
323 pub fn to_mat4d(self) -> Mat4d {
324 Mat4d::from(self)
325 }
326
327 pub fn to_mat2f(self) -> Mat2f {
328 Mat2f::new(self.x_axis.to_vec2f(), self.y_axis.to_vec2f())
329 }
330}