1#![macro_use]
33use core::fmt;
34use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
35use core::ops::{Deref, DerefMut, Index, IndexMut};
36
37use crate::slices_methods::*;
38use crate::traits::LinearAlgebra;
39use crate::utils::nearly_zero;
40use crate::vector2::*;
41use num::{Float, Num, One, Signed, Zero};
42
43#[derive(Copy, Clone, Debug, PartialEq)]
45pub struct M22<T>([[T; 2]; 2]);
46
47impl<T> M22<T> {
48 #[inline(always)]
49 pub const fn new(data_input: [[T; 2]; 2]) -> Self {
50 Self(data_input)
51 }
52
53 #[inline(always)]
54 pub const fn new_from(a: T, b: T, c: T, d: T) -> Self {
55 Self::new([[a, b], [c, d]])
56 }
57
58 #[inline(always)]
59 pub const fn rows(&self) -> usize {
60 self.0.len()
61 }
62
63 #[inline(always)]
64 pub const fn cols(&self) -> usize {
65 self.rows()
66 }
67}
68
69impl<T: Float + core::iter::Sum> LinearAlgebra<T> for M22<T> {
70 fn rows(&self) -> usize {
71 self.0.len()
72 }
73
74 fn cols(&self) -> usize {
75 self.rows()
76 }
77
78 #[inline(always)]
79 fn det(&self) -> T {
80 (self[(0, 0)] * self[(1, 1)]) - (self[(1, 0)] * self[(0, 1)])
81 }
82
83 #[inline(always)]
84 fn transpose(&self) -> M22<T> {
85 M22::new([[self[(0, 0)], self[(1, 0)]], [self[(0, 1)], self[(1, 1)]]])
86 }
87
88 #[inline(always)]
89 fn trace(&self) -> T {
90 self[(0, 0)] + self[(1, 1)]
91 }
92
93 #[inline(always)]
94 fn norm2(&self) -> T {
95 T::sqrt(self[(0, 0)] * self[(0, 0)] + self[(0, 1)] * self[(0, 1)] +
96 self[(1, 0)] * self[(1, 0)] + self[(1, 1)] * self[(1, 1)])
97 }
98
99 #[inline(always)]
100 fn inverse(&self) -> Option<Self> {
101 let det = self.det();
102 if !nearly_zero(det) {
103 let det_recip = det.recip();
104 Some(M22::new([[self[(1, 1)] * det_recip, -self[(0, 1)] * det_recip],
105 [-self[(1, 0)] * det_recip, self[(0, 0)] * det_recip]]))
106 } else {
107 None
108 }
109 }
110
111 fn qr(&self) -> Option<(Self, Self)> {
114 if !nearly_zero(self.det()) {
115 let cols = self.get_cols();
116 let mut q: [V2<T>; 2] = *M22::zeros().get_cols();
117 for i in 0..q.len() {
118 let mut q_tilde = cols[i];
119 for elem in q.iter().take(i) {
120 q_tilde -= *elem * project_x_over_y(&*cols[i], &**elem);
121 }
122 normalize(&mut *q_tilde);
123 q[i] = q_tilde;
124 }
125 let basis = V2::new_from(q[0], q[1]);
126 let q = M22::new_from_vecs(basis);
127 let r = q.transpose() * (*self);
128 Some((q, r))
129 } else {
130 None
131 }
132 }
133}
134
135impl<T: Num + Copy> M22<T> {
136 pub fn identity() -> M22<T> {
138 <M22<T> as One>::one()
139 }
140
141 pub fn zeros() -> M22<T> {
143 <M22<T> as Zero>::zero()
144 }
145
146 pub fn as_vec(&self) -> [T; 4] {
148 let mut result = [T::zero(); 4];
149 for (index, element) in self.iter().flatten().enumerate() {
150 result[index] = *element;
151 }
152 result
153 }
154
155 pub fn new_from_vecs(cols: V2<V2<T>>) -> Self {
157 let mut result = Self::zeros();
158
159 for i in 0..result.cols() {
160 result[(i, 0)] = cols[0][i];
161 result[(i, 1)] = cols[1][i];
162 }
163 result
164 }
165
166 pub fn get_diagonal(&self) -> V2<T> {
168 let mut result = V2::zeros();
169 let mut index: usize = 0;
170 for i in 0..self.rows() {
171 for j in 0..self.cols() {
172 if i == j {
173 result[index] = self[(i, j)];
174 index += 1;
175 }
176 }
177 }
178 result
179 }
180}
181
182impl<T: Num + Copy> Mul<V2<T>> for M22<T> {
184 type Output = V2<T>;
185
186 #[inline(always)]
187 fn mul(self, rhs: V2<T>) -> V2<T> {
188 V2::new_from(self[(0, 0)] * rhs[0] + self[(0, 1)] * rhs[1],
189 self[(1, 0)] * rhs[0] + self[(1, 1)] * rhs[1])
190 }
191}
192
193impl<T: Num + Copy> Add for M22<T> {
195 type Output = Self;
196
197 #[inline(always)]
198 fn add(self, rhs: Self) -> Self {
199 Self::new([[self[(0, 0)] + rhs[(0, 0)], self[(0, 1)] + rhs[(0, 1)]],
200 [self[(1, 0)] + rhs[(1, 0)], self[(1, 1)] + rhs[(1, 1)]]])
201 }
202}
203
204impl<T: Num + Copy> AddAssign for M22<T> {
206 #[inline(always)]
207 fn add_assign(&mut self, other: Self) {
208 *self = *self + other
209 }
210}
211
212impl<T: Num + Copy> Sub for M22<T> {
214 type Output = Self;
215
216 #[inline(always)]
217 fn sub(self, rhs: Self) -> Self {
218 Self::new([[self[(0, 0)] - rhs[(0, 0)], self[(0, 1)] - rhs[(0, 1)]],
219 [self[(1, 0)] - rhs[(1, 0)], self[(1, 1)] - rhs[(1, 1)]]])
220 }
221}
222
223impl<T: Num + Copy> SubAssign for M22<T> {
225 #[inline]
226 fn sub_assign(&mut self, other: Self) {
227 *self = *self - other
228 }
229}
230
231impl<T: Num + Copy> M22<T> {
232 pub fn get_rows(self) -> V2<V2<T>> {
234 let mut r0 = V2::zeros();
235 let mut r1 = V2::zeros();
236
237 for j in 0..self.rows() {
238 r0[j] = self[(0, j)];
239 r1[j] = self[(1, j)]
240 }
241
242 V2::new([r0, r1])
243 }
244
245 pub fn get_cols(self) -> V2<V2<T>> {
247 let mut c0 = V2::zeros();
248 let mut c1 = V2::zeros();
249
250 for i in 0..self.cols() {
251 c0[i] = self[(i, 0)];
252 c1[i] = self[(i, 1)]
253 }
254
255 V2::new([c0, c1])
256 }
257
258 pub fn for_each(&self, f: impl Fn(T) -> T) -> Self {
260 let mut result = Self::zeros();
261 for i in 0..self.rows() {
262 for j in 0..self.cols() {
263 result[(i, j)] = f(self[(i, j)]);
264 }
265 }
266 result
267 }
268}
269
270impl<T: Float + core::iter::Sum> M22<T> {
272 pub fn real_eigenvals(&self) -> Option<V2<T>> {
274 let tau = self.trace();
275 let delta = self.det();
276 let tau_2 = tau * tau;
277 let four = T::from(4)?;
278 let discr = tau_2 - four * delta;
279 if discr < T::zero() {
280 None
281 } else {
282 let two = T::from(2)?;
283 let lambda2 = (tau - T::sqrt(discr)) / two;
284 let lambda1 = (tau + T::sqrt(discr)) / two;
285 Some(V2::new([lambda1, lambda2]))
286 }
287 }
288}
289
290impl Mul<M22<f32>> for f32 {
293 type Output = M22<f32>;
294
295 #[inline]
296 fn mul(self, rhs: M22<f32>) -> M22<f32> {
297 M22::new([[rhs[(0, 0)] * self, rhs[(0, 1)] * self],
298 [rhs[(1, 0)] * self, rhs[(1, 1)] * self]])
299 }
300}
301
302impl<T: Num + Copy> Mul<T> for M22<T> {
304 type Output = M22<T>;
305
306 #[inline(always)]
307 fn mul(self, rhs: T) -> M22<T> {
308 Self::new([[self[(0, 0)] * rhs, self[(0, 1)] * rhs],
309 [self[(1, 0)] * rhs, self[(1, 1)] * rhs]])
310 }
311}
312
313impl<T: Num + Copy> Div<T> for M22<T> {
315 type Output = Self;
316
317 fn div(self, rhs: T) -> Self::Output {
318 Self::new([[self[(0, 0)] / rhs, self[(0, 1)] / rhs],
319 [self[(1, 0)] / rhs, self[(1, 1)] / rhs]])
320 }
321}
322
323impl<T: Num + Copy> Mul for M22<T> {
325 type Output = Self;
326
327 #[inline(always)]
328 fn mul(self, rhs: Self) -> Self {
329 let a1 = self[(0, 0)];
330 let b1 = self[(0, 1)];
331 let c1 = self[(1, 0)];
332 let d1 = self[(1, 1)];
333
334 let a2 = rhs[(0, 0)];
335 let b2 = rhs[(0, 1)];
336 let c2 = rhs[(1, 0)];
337 let d2 = rhs[(1, 1)];
338
339 Self::new([[a1 * a2 + b1 * c2, a1 * b2 + b1 * d2],
340 [c1 * a2 + d1 * c2, c1 * b2 + d1 * d2]])
341 }
342}
343
344impl<T: Num + Copy + Signed> Neg for M22<T> {
346 type Output = Self;
347
348 #[inline(always)]
349 fn neg(self) -> Self {
350 Self::new([[-self[(0, 0)], -self[(0, 1)]],
351 [-self[(1, 0)], -self[(1, 1)]]])
352 }
353}
354
355impl<T: Num + Copy> Zero for M22<T> {
356 #[inline(always)]
357 fn zero() -> M22<T> {
358 M22::new([[T::zero(); 2]; 2])
359 }
360
361 fn is_zero(&self) -> bool {
362 *self == M22::zero()
363 }
364}
365
366impl<T: Num + Copy> One for M22<T> {
367 fn one() -> M22<T> {
369 let one = T::one();
370 let zero = T::zero();
371 M22::new([[one, zero], [zero, one]])
372 }
373}
374
375impl<T> Deref for M22<T> {
376 type Target = [[T; 2]; 2];
377 #[inline]
378 fn deref(&self) -> &Self::Target {
379 &self.0
380 }
381}
382
383impl<T> DerefMut for M22<T> {
384 #[inline]
385 fn deref_mut(&mut self) -> &mut Self::Target {
386 &mut self.0
387 }
388}
389
390impl<T> From<[[T; 2]; 2]> for M22<T> {
391 fn from(data: [[T; 2]; 2]) -> M22<T> {
392 M22(data)
393 }
394}
395
396impl<T> Index<(usize, usize)> for M22<T> {
397 type Output = T;
398 #[inline(always)]
399 fn index(&self, index: (usize, usize)) -> &T {
400 &self.0[index.0][index.1]
401 }
402}
403
404impl<T> IndexMut<(usize, usize)> for M22<T> {
405 #[inline(always)]
406 fn index_mut(&mut self, index: (usize, usize)) -> &mut T {
407 &mut self.0[index.0][index.1]
408 }
409}
410
411#[macro_export]
415macro_rules! m22_new {
416 ($($first_row:expr),* ; $($second_row:expr),*) => {
417 M22::new([[$($first_row),*], [$($second_row),*]])
418 }
419}
420
421impl<T: Num + fmt::Display> fmt::Display for M22<T> {
425 fn fmt(&self, dest: &mut fmt::Formatter) -> fmt::Result {
426 println!();
427 writeln!(dest, "|{0:^3.2} {1:^3.2}|", self[(0, 0)], self[(0, 1)])?;
428 writeln!(dest, "|{0:^3.2} {1:^3.2}|", self[(1, 0)], self[(1, 1)])
429 }
430}
431
432pub const M22_ZEROS: M22<f32> = M22::new([[0.0, 0.0], [0.0, 0.0]]);
437pub const M22_IDENT: M22<f32> = M22::new([[1.0, 0.0], [0.0, 1.0]]);
438#[cfg(test)]
443mod test_matrix2x2 {
444 use crate::matrix2x2::M22;
445 use crate::traits::LinearAlgebra;
446 use crate::utils::{compare_vecs, nearly_equal};
447 use crate::vector2::V2;
448
449 const EPS: f32 = 1e-7;
450
451 #[test]
452 fn create_m22_floats() {
453 let matrix = M22::new([[0.0, 1.0], [2.0, 3.0]]);
454 assert_eq!(matrix[(0, 0)], 0.0);
455 assert_eq!(matrix[(0, 1)], 1.0);
456 assert_eq!(matrix[(1, 0)], 2.0);
457 assert_eq!(matrix[(1, 1)], 3.0);
458 }
459
460 #[test]
461 fn create_m22_test() {
462 let m = m22_new!(0.0, 1.0;
463 2.0, 3.0);
464
465 assert_eq!(m[(0, 0)], 0.0);
466 assert_eq!(m[(0, 1)], 1.0);
467 assert_eq!(m[(1, 0)], 2.0);
468 assert_eq!(m[(1, 1)], 3.0);
469 }
470
471 #[test]
472 fn create_m22_ints() {
473 let m = M22::new([[0, 1], [2, 3]]);
474 assert_eq!(m[(0, 0)], 0);
475 assert_eq!(m[(0, 1)], 1);
476 assert_eq!(m[(1, 0)], 2);
477 assert_eq!(m[(1, 1)], 3);
478 }
479
480 #[test]
481 fn create_identity_floats() {
482 let expected = M22::new([[1.0, 0.0], [0.0, 1.0]]);
483 let result: M22<f64> = M22::identity();
484 assert_eq!(result.as_vec(), expected.as_vec());
485 }
486
487 #[test]
488 fn create_identity_ints() {
489 let expected = M22::new([[1, 0], [0, 1]]);
490 let result: M22<i32> = M22::identity();
491 assert_eq!(result.as_vec(), expected.as_vec());
492 }
493
494 #[test]
495 fn add_m22_floats() {
496 let m1 = M22::new([[1.0, 2.0], [3.0, 4.0]]);
497 let m2 = M22::new([[5.0, 6.0], [7.0, 8.0]]);
498 let expected = M22::new([[6.0, 8.0], [10.0, 12.0]]);
499 let result = m1 + m2;
500 assert_eq!(result.as_vec(), expected.as_vec());
501 }
502
503 #[test]
504 fn sub_test() {
505 let m1 = m22_new!(1.0, 2.0;
506 3.0, 4.0);
507 let m2 = m22_new!(5.0, 6.0;
508 7.0, 8.0);
509 let expected = m22_new!( -4.0, -4.0;
510 -4.0, -4.0);
511 let result = m1 - m2;
512 assert_eq!(result.as_vec(), expected.as_vec());
513 }
514
515 #[test]
516 fn add_m22_ints() {
517 let m1 = M22::new([[1, 2], [3, 4]]);
518 let m2 = M22::new([[5, 6], [7, 8]]);
519 let expected = M22::new([[6, 8], [10, 12]]);
520 let result = m1 + m2;
521 assert_eq!(result.as_vec(), expected.as_vec());
522 }
523
524 #[test]
525 fn test_determinant() {
526 let m1 = M22::new([[1.0, 2.0], [1.0, 2.0]]);
527 let result = m1.det();
528 let expected = 0.0;
529 assert_eq!(result, expected);
530 }
531
532 #[test]
533 fn product_with_vector2_rhs_test() {
534 let m1 = M22::new([[1.0, 2.0], [3.0, 4.0]]);
535 let v = V2::new([1.0, 2.0]);
536
537 let result = m1 * v;
538 let expected = V2::new([5.0, 11.0]);
539 assert_eq!(
540 &result[..],
541 &expected[..],
542 "\nExpected\n{:?}\nfound\n{:?}",
543 &result[..],
544 &expected[..]
545 );
546 }
547
548 #[test]
549 fn product_with_matrix2x2_rhs_test() {
550 let v = V2::new([1.0, 2.0]);
551 let m1 = M22::new([[1.0, 2.0], [3.0, 4.0]]);
552 let result = v * m1;
553 let expected = V2::new([7.0, 10.0]);
554 assert_eq!(
555 &result[..],
556 &expected[..],
557 "\nExpected\n{:?}\nfound\n{:?}",
558 &result[..],
559 &expected[..]
560 );
561 }
562
563 #[test]
564 fn inverse_test() {
565 use super::test_matrix2x2::EPS;
568 let m1 = M22::new([[1.0, 2.0], [3.0, 4.0]]);
569 let expected = M22::new([[-2.0, 1.0], [1.5, -0.5]]);
570 if let Some(result) = m1.inverse() {
571 assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
572 }
573 }
574
575 #[test]
576 fn inverse_fail() {
577 let m1 = M22::new([[1.0, 2.0], [1.0, 2.0]]);
578 let result = m1.inverse();
579 assert!(result.is_none())
580 }
581
582 #[test]
583 fn get_columns_test() {
584 let m1 = m22_new!(1.0, 2.0;
585 3.0, 4.0);
586 let result = m1.get_cols();
587
588 let expected1 = V2::new([1.0, 3.0]);
589 let expected2 = V2::new([2.0, 4.0]);
590 let expected = V2::new([expected1, expected2]);
591 assert_eq!(
592 &result[..],
593 &expected[..],
594 "\nExpected\n{:?}\nfound\n{:?}",
595 &result[..],
596 &expected[..]
597 );
598 }
599
600 #[test]
601 fn get_rows_test() {
602 let m1 = m22_new!(1.0, 2.0;
603 3.0, 4.0);
604 let result = m1.get_rows();
605
606 let expected1 = V2::new([1.0, 2.0]);
607 let expected2 = V2::new([3.0, 4.0]);
608 let expected = V2::new([expected1, expected2]);
609 assert_eq!(
610 &result[..],
611 &expected[..],
612 "\nExpected\n{:?}\nfound\n{:?}",
613 &result[..],
614 &expected[..]
615 );
616 }
617
618 #[test]
619 fn new_from_vecs_test() {
620 let expected = m22_new!(1.0, 2.0;
621 3.0, 4.0);
622
623 let cols = expected.get_cols();
624
625 let result = M22::new_from_vecs(cols);
626
627 assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
628 }
629
630 #[test]
631 fn qr_test() {
632 let expected = m22_new!(10.0, 2.0;
633 3.0, -4.0);
634 if let Some((q, r)) = expected.qr() {
635 let result = q * r;
636 assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
637 assert!(nearly_equal(q.det().abs(), 1.0, EPS));
638 }
639 }
640
641 #[test]
642 fn get_diagonal() {
643 let m = m22_new!(10.0, 2.0;
644 3.0, -4.0);
645 let result = m.get_diagonal();
646 let expected = V2::new([10.0, -4.0]);
647 assert_eq!(
648 &result[..],
649 &expected[..],
650 "\nExpected\n{:?}\nfound\n{:?}",
651 &result[..],
652 &expected[..]
653 );
654 }
655
656 #[test]
657 fn for_each_test() {
658 let m = m22_new!(10.0, 2.0;
659 3.0, -4.0);
660 let result = m.for_each(|element| element + 37.0);
661 let expected = m22_new!(47.0, 39.0;
662 40.0, 33.0);
663
664 assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
665 }
666}