static_math/
matrix3x3.rs

1//-------------------------------------------------------------------------
2// @file matrix3x3.rs
3//
4// @date 06/02/20 18:41:39
5// @author Martin Noblia
6// @email mnoblia@disroot.org
7//
8// @brief
9//
10// @detail
11//
12// Licence MIT:
13// Copyright <2020> <Martin Noblia>
14//
15// Permission is hereby granted, free of charge, to any person obtaining a copy
16// of this software and associated documentation files (the "Software"), to deal
17// in the Software without restriction, including without limitation the rights
18// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19// copies of the Software, and to permit persons to whom the Software is
20// furnished to do so, subject to the following conditions:
21//
22// The above copyright notice and this permission notice shall be included in
23// all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED
24// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
25// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
26// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30//-------------------------------------------------------------------------
31#![macro_use]
32use core::fmt;
33use core::ops::{Add, Mul, Div, Sub, SubAssign, AddAssign, Neg};
34use core::ops::{Deref, DerefMut, Index, IndexMut};
35
36use crate::traits::LinearAlgebra;
37use crate::utils::nearly_zero;
38use num::{Float, One, Zero, Num, Signed};
39
40use crate::slices_methods::*;
41use crate::vector3::*;
42//-------------------------------------------------------------------------
43//                        code
44//-------------------------------------------------------------------------
45
46/// A static matrix of 3x3 shape
47#[derive(Copy, Clone, Debug, PartialEq)]
48pub struct M33<T>([[T; 3]; 3]);
49
50impl<T> M33<T> {
51    pub const fn new(data_input: [[T; 3]; 3]) -> M33<T> {
52        M33(data_input)
53    }
54
55    pub const fn rows(&self) -> usize {
56        self.0.len()
57    }
58
59    pub const fn cols(&self) -> usize {
60        self.rows()
61    }
62}
63
64impl<T: Float + core::iter::Sum> LinearAlgebra<T> for M33<T> {
65    fn rows(&self) -> usize {
66        self.0.len()
67    }
68
69    fn cols(&self) -> usize {
70        self.rows()
71    }
72
73    #[inline(always)]
74    fn transpose(&self) -> M33<T> {
75        M33::new([
76            [self[(0, 0)], self[(1, 0)], self[(2, 0)]],
77            [self[(0, 1)], self[(1, 1)], self[(2, 1)]],
78            [self[(0, 2)], self[(1, 2)], self[(2, 2)]],
79        ])
80    }
81
82    #[inline(always)]
83    fn trace(&self) -> T {
84        self[(0, 0)] + self[(1, 1)] + self[(2, 2)]
85    }
86
87    fn norm2(&self) -> T {
88        T::sqrt(
89            self[(0, 0)] * self[(0, 0)]
90                + self[(1, 0)] * self[(1, 0)]
91                + self[(2, 0)] * self[(2, 0)]
92                + self[(0, 1)] * self[(0, 1)]
93                + self[(1, 1)] * self[(1, 1)]
94                + self[(2, 1)] * self[(2, 1)]
95                + self[(0, 2)] * self[(0, 2)]
96                + self[(1, 2)] * self[(1, 2)]
97                + self[(2, 2)] * self[(2, 2)],
98        )
99    }
100
101    /// Calculate the determinant of the matrix
102    #[inline(always)]
103    fn det(&self) -> T {
104          self[(0, 0)] * (self[(1, 1)] * self[(2, 2)] - self[(2, 1)] * self[(1, 2)])
105        - self[(0, 1)] * (self[(1, 0)] * self[(2, 2)] - self[(1, 2)] * self[(2, 0)])
106        + self[(0, 2)] * (self[(1, 0)] * self[(2, 1)] - self[(1, 1)] * self[(2, 0)])
107    }
108
109    /// Calculate the inverse
110    #[inline(always)]
111    fn inverse(&self) -> Option<Self> {
112        let det = self.det();
113        if !nearly_zero(det) {
114            let invdet = det.recip();
115            let mut res = M33::zero();
116            res[(0, 0)] = (self[(1, 1)] * self[(2, 2)] - self[(2, 1)] * self[(1, 2)]) * invdet;
117            res[(0, 1)] = (self[(0, 2)] * self[(2, 1)] - self[(0, 1)] * self[(2, 2)]) * invdet;
118            res[(0, 2)] = (self[(0, 1)] * self[(1, 2)] - self[(0, 2)] * self[(1, 1)]) * invdet;
119            res[(1, 0)] = (self[(1, 2)] * self[(2, 0)] - self[(1, 0)] * self[(2, 2)]) * invdet;
120            res[(1, 1)] = (self[(0, 0)] * self[(2, 2)] - self[(0, 2)] * self[(2, 0)]) * invdet;
121            res[(1, 2)] = (self[(1, 0)] * self[(0, 2)] - self[(0, 0)] * self[(1, 2)]) * invdet;
122            res[(2, 0)] = (self[(1, 0)] * self[(2, 1)] - self[(2, 0)] * self[(1, 1)]) * invdet;
123            res[(2, 1)] = (self[(2, 0)] * self[(0, 1)] - self[(0, 0)] * self[(2, 1)]) * invdet;
124            res[(2, 2)] = (self[(0, 0)] * self[(1, 1)] - self[(1, 0)] * self[(0, 1)]) * invdet;
125            Some(res)
126        } else {
127            None
128        }
129    }
130
131    /// Calculate de QR factorization of the M33 via gram-schmidt
132    /// orthogonalization process
133    fn qr(&self) -> Option<(Self, Self)> {
134        if !nearly_zero(self.det()) {
135            let cols = self.get_cols();
136            let mut q: [V3<T>; 3] = *M33::zeros().get_cols();
137            for i in 0..q.len() {
138                let mut q_tilde = cols[i];
139                for elem in q.iter().take(i) {
140                    q_tilde -= *elem * project_x_over_y(&*cols[i], &**elem);
141                }
142                normalize(&mut *q_tilde);
143                q[i] = q_tilde;
144            }
145            let basis = V3::new_from(q[0], q[1], q[2]);
146            let q     = M33::new_from_vecs(basis);
147            let r     = q.transpose() * (*self);
148            Some((q, r))
149        } else {
150            None
151        }
152    }
153}
154
155impl<T: Num + Copy> M33<T> {
156    /// contruct identity matrix
157    pub fn identity() -> M33<T> {
158        <M33<T> as One>::one()
159    }
160
161    /// construct the matrix with all zeros
162    pub fn zeros() -> M33<T> {
163        <M33<T> as Zero>::zero()
164    }
165
166    /// transform the matrix to a flatten vector
167    pub fn as_vec(&self) -> [T; 9] {
168        let mut result = [T::zero(); 9];
169        for (index, element) in self.iter().flatten().enumerate() {
170            result[index] = *element;
171        }
172        result
173    }
174
175    /// construct the matrix from columns-vectors
176    pub fn new_from_vecs(cols: V3<V3<T>>) -> Self {
177        let mut result = Self::zeros();
178
179        for i in 0..result.cols() {
180            result[(i, 0)] = cols[0][i];
181            result[(i, 1)] = cols[1][i];
182            result[(i, 2)] = cols[2][i];
183        }
184        result
185    }
186
187    /// get the diagonal of the matrix
188    pub fn get_diagonal(&self) -> V3<T> {
189        let mut result = V3::zeros();
190        let mut index: usize = 0;
191        for i in 0..self.rows() {
192            for j in 0..self.cols() {
193                if i == j {
194                    result[index] = self[(i, j)];
195                    index += 1;
196                }
197            }
198        }
199        result
200    }
201
202    pub fn get_upper_triagular(&self) -> [T; 3] {
203        let zero = T::zero();
204        let mut result: [T; 3] = [zero, zero, zero];
205        let mut index = 0;
206        for i in 0..self.rows() {
207            for j in 0..self.cols() {
208                if i < j {
209                    result[index] = self[(i, j)];
210                    index += 1;
211                }
212            }
213        }
214        result
215    }
216
217    pub fn get_lower_triangular(&self) -> [T; 3] {
218        let zero = T::zero();
219        let mut result: [T; 3] = [zero, zero, zero];
220        let mut index = 0;
221        for i in 0..self.rows() {
222            for j in 0..self.cols() {
223                if i > j {
224                    result[index] = self[(i, j)];
225                    index += 1;
226                }
227            }
228        }
229        result
230    }
231
232
233    /// Applies `f` of each element in the M33
234    pub fn for_each(&self, f: impl Fn(T) -> T) -> Self {
235        let mut result = Self::zeros();
236        for i in 0..self.rows() {
237            for j in 0..self.cols() {
238                result[(i, j)] = f(self[(i, j)]);
239            }
240        }
241        result
242    }
243
244}
245
246impl<T: Num + Copy> M33<T> {
247
248    /// get the rows of the matrix as a vectors
249    pub fn get_rows(self) -> V3<V3<T>> {
250        let mut r0 = V3::zeros();
251        let mut r1 = V3::zeros();
252        let mut r2 = V3::zeros();
253
254        for j in 0..self.rows() {
255            r0[j] = self[(0, j)];
256            r1[j] = self[(1, j)];
257            r2[j] = self[(2, j)];
258        }
259        V3::new([r0, r1, r2])
260    }
261
262    /// get the columns of the matrix as a vectors
263    pub fn get_cols(self) -> V3<V3<T>> {
264        let mut c0 = V3::zeros();
265        let mut c1 = V3::zeros();
266        let mut c2 = V3::zeros();
267
268        for i in 0..self.rows() {
269            c0[i] = self[(i, 0)];
270            c1[i] = self[(i, 1)];
271            c2[i] = self[(i, 2)];
272        }
273        V3::new([c0, c1, c2])
274    }
275}
276
277impl<T: Num + Copy> Add for M33<T> {
278    type Output = Self;
279
280    #[inline(always)]
281    fn add(self, rhs: Self) -> Self {
282        M33::new([
283            [
284                self[(0, 0)] + rhs[(0, 0)],
285                self[(0, 1)] + rhs[(0, 1)],
286                self[(0, 2)] + rhs[(0, 2)],
287            ],
288            [
289                self[(1, 0)] + rhs[(1, 0)],
290                self[(1, 1)] + rhs[(1, 1)],
291                self[(1, 2)] + rhs[(1, 2)],
292            ],
293            [
294                self[(2, 0)] + rhs[(2, 0)],
295                self[(2, 1)] + rhs[(2, 1)],
296                self[(2, 2)] + rhs[(2, 2)],
297            ],
298        ])
299    }
300}
301
302// M33 += M33
303impl<T: Num + Copy> AddAssign for M33<T> {
304    fn add_assign(&mut self, other: Self) {
305        *self = *self + other
306    }
307}
308
309// M33 - M33
310impl<T: Num + Copy> Sub for M33<T> {
311    type Output = Self;
312
313    fn sub(self, rhs: Self) -> Self {
314        M33::new([
315            [
316                self[(0, 0)] - rhs[(0, 0)],
317                self[(0, 1)] - rhs[(0, 1)],
318                self[(0, 2)] - rhs[(0, 2)],
319            ],
320            [
321                self[(1, 0)] - rhs[(1, 0)],
322                self[(1, 1)] - rhs[(1, 1)],
323                self[(1, 2)] - rhs[(1, 2)],
324            ],
325            [
326                self[(2, 0)] - rhs[(2, 0)],
327                self[(2, 1)] - rhs[(2, 1)],
328                self[(2, 2)] - rhs[(2, 2)],
329            ],
330        ])
331    }
332}
333
334// M33 -= M33
335impl<T: Num + Copy> SubAssign for M33<T> {
336    fn sub_assign(&mut self, other: Self) {
337        *self = *self - other
338    }
339}
340
341// M3 * V3
342impl<T: Num + Copy> Mul<V3<T>> for M33<T> {
343    type Output = V3<T>;
344
345    #[inline(always)]
346    fn mul(self, rhs: V3<T>) -> V3<T> {
347
348        let a_00 = self[(0, 0)];
349        let a_01 = self[(0, 1)];
350        let a_02 = self[(0, 2)];
351        let a_10 = self[(1, 0)];
352        let a_11 = self[(1, 1)];
353        let a_12 = self[(1, 2)];
354        let a_20 = self[(2, 0)];
355        let a_21 = self[(2, 1)];
356        let a_22 = self[(2, 2)];
357
358        let v0 = rhs[0];
359        let v1 = rhs[1];
360        let v2 = rhs[2];
361        V3::new([a_00 * v0 + a_01 * v1 + a_02 * v2,
362                 a_10 * v0 + a_11 * v1 + a_12 * v2,
363                 a_20 * v0 + a_21 * v1 + a_22 * v2])
364    }
365}
366
367// M3 * constant
368impl<T: Num + Copy> Mul<T> for M33<T> {
369    type Output = M33<T>;
370
371    fn mul(self, rhs: T) -> Self::Output {
372        let a_00 = self[(0, 0)] * rhs;
373        let a_01 = self[(0, 1)] * rhs;
374        let a_02 = self[(0, 2)] * rhs;
375        let a_10 = self[(1, 0)] * rhs;
376        let a_11 = self[(1, 1)] * rhs;
377        let a_12 = self[(1, 2)] * rhs;
378        let a_20 = self[(2, 0)] * rhs;
379        let a_21 = self[(2, 1)] * rhs;
380        let a_22 = self[(2, 2)] * rhs;
381
382        M33::new([[a_00, a_01, a_02], [a_10, a_11, a_12], [a_20, a_21, a_22]])
383    }
384}
385
386// M33 / constant
387impl<T: Num + Copy> Div<T> for M33<T> {
388    type Output = Self;
389
390    fn div(self, rhs: T) -> Self::Output {
391        let a_00 = self[(0, 0)] / rhs;
392        let a_01 = self[(0, 1)] / rhs;
393        let a_02 = self[(0, 2)] / rhs;
394        let a_10 = self[(1, 0)] / rhs;
395        let a_11 = self[(1, 1)] / rhs;
396        let a_12 = self[(1, 2)] / rhs;
397        let a_20 = self[(2, 0)] / rhs;
398        let a_21 = self[(2, 1)] / rhs;
399        let a_22 = self[(2, 2)] / rhs;
400
401        M33::new([[a_00, a_01, a_02], [a_10, a_11, a_12], [a_20, a_21, a_22]])
402    }
403}
404
405// f32 * M33<f32>
406impl Mul<M33<f32>> for f32 {
407    type Output = M33<f32>;
408
409    fn mul(self, rhs: M33<f32>) -> Self::Output {
410        let a_00 = self * rhs[(0, 0)];
411        let a_01 = self * rhs[(0, 1)];
412        let a_02 = self * rhs[(0, 2)];
413        let a_10 = self * rhs[(1, 0)];
414        let a_11 = self * rhs[(1, 1)];
415        let a_12 = self * rhs[(1, 2)];
416        let a_20 = self * rhs[(2, 0)];
417        let a_21 = self * rhs[(2, 1)];
418        let a_22 = self * rhs[(2, 2)];
419
420        M33::new([[a_00, a_01, a_02], [a_10, a_11, a_12], [a_20, a_21, a_22]])
421    }
422}
423
424// f64 * M33<f64>
425impl Mul<M33<f64>> for f64 {
426    type Output = M33<f64>;
427
428    fn mul(self, rhs: M33<f64>) -> Self::Output {
429        let a_00 = self * rhs[(0, 0)];
430        let a_01 = self * rhs[(0, 1)];
431        let a_02 = self * rhs[(0, 2)];
432        let a_10 = self * rhs[(1, 0)];
433        let a_11 = self * rhs[(1, 1)];
434        let a_12 = self * rhs[(1, 2)];
435        let a_20 = self * rhs[(2, 0)];
436        let a_21 = self * rhs[(2, 1)];
437        let a_22 = self * rhs[(2, 2)];
438
439        M33::new([[a_00, a_01, a_02], [a_10, a_11, a_12], [a_20, a_21, a_22]])
440    }
441}
442
443
444// M3 * M3
445impl<T: Num + Copy> Mul for M33<T> {
446    type Output = Self;
447
448    #[inline]
449    fn mul(self, rhs: Self) -> Self {
450        let m00 =
451            self[(0, 0)] * rhs[(0, 0)] + self[(0, 1)] * rhs[(1, 0)] + self[(0, 2)] * rhs[(2, 0)];
452        let m01 =
453            self[(0, 0)] * rhs[(0, 1)] + self[(0, 1)] * rhs[(1, 1)] + self[(0, 2)] * rhs[(2, 1)];
454        let m02 =
455            self[(0, 0)] * rhs[(0, 2)] + self[(0, 1)] * rhs[(1, 2)] + self[(0, 2)] * rhs[(2, 2)];
456
457        let m10 =
458            self[(1, 0)] * rhs[(0, 0)] + self[(1, 1)] * rhs[(1, 0)] + self[(1, 2)] * rhs[(2, 0)];
459        let m11 =
460            self[(1, 0)] * rhs[(0, 1)] + self[(1, 1)] * rhs[(1, 1)] + self[(1, 2)] * rhs[(2, 1)];
461        let m12 =
462            self[(1, 0)] * rhs[(0, 2)] + self[(1, 1)] * rhs[(1, 2)] + self[(1, 2)] * rhs[(2, 2)];
463
464        let m20 =
465            self[(2, 0)] * rhs[(0, 0)] + self[(2, 1)] * rhs[(1, 0)] + self[(2, 2)] * rhs[(2, 0)];
466        let m21 =
467            self[(2, 0)] * rhs[(0, 1)] + self[(2, 1)] * rhs[(1, 1)] + self[(2, 2)] * rhs[(2, 1)];
468        let m22 =
469            self[(2, 0)] * rhs[(0, 2)] + self[(2, 1)] * rhs[(1, 2)] + self[(2, 2)] * rhs[(2, 2)];
470
471        M33::new([[m00, m01, m02], [m10, m11, m12], [m20, m21, m22]])
472    }
473}
474
475// -M33
476impl<T: Num + Copy + Signed> Neg for M33<T> {
477    type Output = Self;
478
479    fn neg(self) -> Self {
480        let a_00 = -self[(0, 0)];
481        let a_01 = -self[(0, 1)];
482        let a_02 = -self[(0, 2)];
483        let a_10 = -self[(1, 0)];
484        let a_11 = -self[(1, 1)];
485        let a_12 = -self[(1, 2)];
486        let a_20 = -self[(2, 0)];
487        let a_21 = -self[(2, 1)];
488        let a_22 = -self[(2, 2)];
489
490        M33::new([[a_00, a_01, a_02], [a_10, a_11, a_12], [a_20, a_21, a_22]])
491    }
492}
493
494impl<T: Num + Copy> Zero for M33<T> {
495    fn zero() -> M33<T> {
496        M33::new([[T::zero(); 3]; 3])
497    }
498
499    fn is_zero(&self) -> bool {
500        *self == M33::zero()
501    }
502}
503
504impl<T: Num + Copy> One for M33<T> {
505    /// Create an identity matrix
506    fn one() -> M33<T> {
507        let one = T::one();
508        let zero = T::zero();
509        M33::new([[one, zero, zero], [zero, one, zero], [zero, zero, one]])
510    }
511}
512//
513impl<T> Deref for M33<T> {
514    type Target = [[T; 3]; 3];
515    #[inline]
516    fn deref(&self) -> &Self::Target {
517        &self.0
518    }
519}
520
521impl<T> DerefMut for M33<T> {
522    #[inline]
523    fn deref_mut(&mut self) -> &mut Self::Target {
524        &mut self.0
525    }
526}
527
528impl<T> From<[[T; 3]; 3]> for M33<T> {
529    fn from(data: [[T; 3]; 3]) -> M33<T> {
530        M33(data)
531    }
532}
533
534impl<T> Index<(usize, usize)> for M33<T> {
535    type Output = T;
536    #[inline(always)]
537    fn index(&self, index: (usize, usize)) -> &T {
538        &self.0[index.0][index.1]
539    }
540}
541
542impl<T> IndexMut<(usize, usize)> for M33<T> {
543    #[inline(always)]
544    fn index_mut(&mut self, index: (usize, usize)) -> &mut T {
545        &mut self.0[index.0][index.1]
546    }
547}
548
549//-------------------------------------------------------------------------
550//                        Display for M33
551//-------------------------------------------------------------------------
552impl<T: Num + fmt::Display> fmt::Display for M33<T> {
553    fn fmt(&self, dest: &mut fmt::Formatter) -> fmt::Result {
554        println!();
555        writeln!(
556            dest,
557            "|{0:<7.2} {1:^7.2} {2:>7.2}|",
558            self[(0, 0)],
559            self[(0, 1)],
560            self[(0, 2)]
561        )?;
562        writeln!(
563            dest,
564            "|{0:<7.2} {1:^7.2} {2:>7.2}|",
565            self[(1, 0)],
566            self[(1, 1)],
567            self[(1, 2)]
568        )?;
569        writeln!(
570            dest,
571            "|{0:<7.2} {1:^7.2} {2:>7.2}|",
572            self[(2, 0)],
573            self[(2, 1)],
574            self[(2, 2)]
575        )
576    }
577}
578
579//-------------------------------------------------------------------------
580//                        macros
581//-------------------------------------------------------------------------
582#[macro_export]
583macro_rules! m33_new {
584    ($($first_row:expr),*;
585     $($second_row:expr),*;
586     $($third_row:expr),*
587     ) => {
588        M33::new([[$($first_row),*], [$($second_row),*], [$($third_row),*]])
589    }
590}
591
592//-------------------------------------------------------------------------
593//                        tests
594//-------------------------------------------------------------------------
595
596#[cfg(test)]
597mod test_matrix3x3 {
598    use crate::traits::LinearAlgebra;
599    use crate::matrix3x3::M33;
600    use crate::utils::nearly_equal;
601    use crate::utils::compare_vecs;
602    use crate::vector3::*;
603
604    const EPS: f32 = 1e-8;
605
606    #[test]
607    fn create_matrix() {
608        let matrix = M33::new([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]);
609        assert_eq!(matrix[(0, 0)], 0.0);
610        assert_eq!(matrix[(0, 1)], 1.0);
611        assert_eq!(matrix[(0, 2)], 2.0);
612        assert_eq!(matrix[(1, 0)], 3.0);
613        assert_eq!(matrix[(1, 1)], 4.0);
614        assert_eq!(matrix[(1, 2)], 5.0);
615        assert_eq!(matrix[(2, 0)], 6.0);
616        assert_eq!(matrix[(2, 1)], 7.0);
617        assert_eq!(matrix[(2, 2)], 8.0);
618    }
619
620    #[test]
621    fn trace_test() {
622        let matrix = M33::new([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]);
623        assert_eq!(matrix.trace(), 12.0);
624    }
625
626    #[test]
627    fn add_matrix() {
628        use super::test_matrix3x3::EPS;
629        let m1 = M33::new([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]);
630
631        let m2 = M33::new([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]);
632
633        let expected = M33::new([[0.0, 2.0, 4.0], [6.0, 8.0, 10.0], [12.0, 14.0, 16.0]]);
634        let result = m1 + m2;
635        assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
636    }
637
638    #[test]
639    fn sub_test() {
640        use super::test_matrix3x3::EPS;
641        let m1 = m33_new!(0.0, 1.0, 2.0;
642                          3.0, 4.0, 5.0;
643                          6.0, 7.0, 8.0);
644
645        let m2 = m33_new!(0.0, 1.0, 2.0;
646                          3.0, 4.0, 5.0;
647                          6.0, 7.0, 8.0);
648
649        let expected = m33_new!(0.0, 0.0, 0.0;
650                          0.0, 0.0, 0.0;
651                          0.0, 0.0, 0.0);
652
653        let result = m1 - m2;
654        assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
655    }
656
657    #[test]
658    fn test_identity_creation() {
659        use super::test_matrix3x3::EPS;
660        let identity: M33<f32> = M33::identity();
661
662        let expected = M33::new([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]);
663        assert!(compare_vecs(&identity.as_vec(), &expected.as_vec(), EPS));
664    }
665
666    #[test]
667    fn test_zeros_creation() {
668        use super::test_matrix3x3::EPS;
669        let zero: M33<f32> = M33::zeros();
670
671        let expected = M33::new([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]);
672        assert!(compare_vecs(&zero.as_vec(), &expected.as_vec(), EPS));
673    }
674
675    #[test]
676    fn test_trace() {
677        let m: M33<f32> = M33::identity();
678        assert_eq!(m.trace(), 3.0);
679    }
680
681    #[test]
682    fn test_norm2() {
683        use super::test_matrix3x3::EPS;
684        let m = M33::new([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]);
685        assert!(nearly_equal(m.norm2(), 14.2828568570857, EPS));
686    }
687
688    #[test]
689    fn determinant_test() {
690        let m = M33::new([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 9.0]]);
691        let expected = -3.0;
692        let result = m.det();
693
694        assert!(nearly_equal(result, expected, EPS));
695    }
696
697    #[test]
698    fn inverse_test() {
699        use super::test_matrix3x3::EPS;
700        let m = M33::new([[1.0, 0.0, 3.0], [2.0, 1.0, 6.0], [1.0, 0.0, 9.0]]);
701        // NOTE(elsuizo:2019-09-25): hay que buscar una que tenga una inversa mas facil jasjdfjas
702        let expected = M33::new([
703            [1.5, 0.0, -0.5],
704            [-2.0, 1.0, 0.0],
705            [-0.16666666666666666, 0.0, 0.16666666666666666],
706        ]);
707
708        if let Some(result) = m.inverse() {
709            assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
710        }
711    }
712
713    #[test]
714    fn inverse_fail() {
715        let m = M33::new([[1.0, 0.0, 3.0], [1.0, 0.0, 3.0], [10.0, 0.0, 3.0]]);
716        let result = m.inverse();
717        let expected = None;
718        assert_eq!(result, expected);
719    }
720
721    #[test]
722    fn test_mul_m33_v3() {
723        let m = M33::new([[1.0,  1.0,  1.0],
724                          [3.0,  2.0,  1.0],
725                          [7.0,  3.0,  3.0],]);
726        let v = V3::new([2.0, 7.0, 6.0]);
727        let result = m * v;
728        let expected = V3::new([15.0, 26.0, 53.0]);
729        assert_eq!(
730            &result[..],
731            &expected[..],
732            "\nExpected\n{:?}\nfound\n{:?}",
733            &result[..],
734            &expected[..]
735        );
736    }
737
738    #[test]
739    fn get_columns_test() {
740        let m = m33_new!(0.0, 1.0, 2.0;
741                         3.0, 4.0, 5.0;
742                         6.0, 7.0, 8.0);
743
744        let result = m.get_cols();
745
746        let expected0 = V3::new([0.0, 3.0, 6.0]);
747        let expected1 = V3::new([1.0, 4.0, 7.0]);
748        let expected2 = V3::new([2.0, 5.0, 8.0]);
749
750        let expected = V3::new([expected0, expected1, expected2]);
751        assert_eq!(
752            &result[..],
753            &expected[..],
754            "\nExpected\n{:?}\nfound\n{:?}",
755            &result[..],
756            &expected[..]
757        );
758    }
759
760    #[test]
761    fn get_rows_test() {
762        let m = m33_new!(0.0, 1.0, 2.0;
763                         3.0, 4.0, 5.0;
764                         6.0, 7.0, 8.0);
765
766        let result = m.get_rows();
767
768        let expected0 = V3::new([0.0, 1.0, 2.0]);
769        let expected1 = V3::new([3.0, 4.0, 5.0]);
770        let expected2 = V3::new([6.0, 7.0, 8.0]);
771
772        let expected = V3::new([expected0, expected1, expected2]);
773
774        assert_eq!(
775            &result[..],
776            &expected[..],
777            "\nExpected\n{:?}\nfound\n{:?}",
778            &result[..],
779            &expected[..]
780        );
781    }
782
783    #[test]
784    fn new_from_vecs_test() {
785        let expected = m33_new!(0.0, 1.0, 2.0;
786                                3.0, 4.0, 5.0;
787                                6.0, 7.0, 8.0);
788
789        let cols = expected.get_cols();
790
791        let result = M33::new_from_vecs(cols);
792
793        assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
794    }
795
796    #[test]
797    fn qr_test() {
798        let expected = m33_new!(0.0, 1.0, 2.0;
799                                3.0, 4.0, 5.0;
800                                6.0, 7.0, 8.0);
801        if let Some((q, r)) = expected.qr() {
802            let result = q * r;
803            assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
804            assert!(nearly_equal(q.det().abs(), 1.0, EPS));
805        }
806    }
807
808    #[test]
809    fn get_diagonal() {
810        let m = m33_new!(0.0, 1.0, 2.0;
811                         3.0, 4.0, 5.0;
812                         6.0, 7.0, 8.0);
813        let result = m.get_diagonal();
814        let expected = V3::new([0.0, 4.0, 8.0]);
815        assert_eq!(
816            &result[..],
817            &expected[..],
818            "\nExpected\n{:?}\nfound\n{:?}",
819            &result[..],
820            &expected[..]
821        );
822    }
823
824    #[test]
825    fn get_upper_triangular_test() {
826        let m = m33_new!(0.0, 1.0, 2.0;
827                         3.0, 4.0, 5.0;
828                         6.0, 7.0, 8.0);
829        let result = m.get_upper_triagular();
830        let expected = [1.0, 2.0, 5.0];
831        assert_eq!(
832            &result[..],
833            &expected[..],
834            "\nExpected\n{:?}\nfound\n{:?}",
835            &result[..],
836            &expected[..]
837        );
838    }
839
840    #[test]
841    fn get_lower_triangular_test() {
842        let m = m33_new!(0.0, 1.0, 2.0;
843                         3.0, 4.0, 5.0;
844                         6.0, 7.0, 8.0);
845        let result = m.get_lower_triangular();
846        let expected = [3.0, 6.0, 7.0];
847        assert_eq!(
848            &result[..],
849            &expected[..],
850            "\nExpected\n{:?}\nfound\n{:?}",
851            &result[..],
852            &expected[..]
853        );
854    }
855
856    #[test]
857    fn for_each_test() {
858        let m = m33_new!(0.0, 1.0, 2.0;
859                         3.0, 4.0, 5.0;
860                         6.0, 7.0, 8.0);
861        let result = m.for_each(|element| element + 1.0);
862        let expected = m33_new!(1.0, 2.0, 3.0;
863                                4.0, 5.0, 6.0;
864                                7.0, 8.0, 9.0);
865        assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
866    }
867
868}