static_math/
matrix5x5.rs

1//-------------------------------------------------------------------------
2// @file matrix5x5.rs
3//
4// @date 06/02/20 20:39:15
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//-------------------------------------------------------------------------
31use num::{Float, One, Zero, Num, Signed};
32use core::fmt;
33use core::ops::{Add, Mul, Div, Sub, AddAssign, SubAssign, Neg};
34use core::ops::{Deref, DerefMut, Index, IndexMut};
35
36use crate::slices_methods::*;
37use crate::traits::LinearAlgebra;
38use crate::matrix4x4::M44;
39use crate::vector5::V5;
40use crate::utils::nearly_zero;
41
42//-------------------------------------------------------------------------
43//                        code
44//-------------------------------------------------------------------------
45/// A static Matrix of 5x5 shape
46#[derive(Copy, Clone, Debug, PartialEq)]
47pub struct M55<T>([[T; 5]; 5]);
48
49impl<T> M55<T> {
50    pub fn new(data_input: [[T; 5]; 5]) -> Self {
51        Self(data_input)
52    }
53    pub fn rows(&self) -> usize {
54        self.0.len()
55    }
56    pub fn cols(&self) -> usize {
57        self.rows()
58    }
59}
60
61impl<T: Float + core::iter::Sum> LinearAlgebra<T> for M55<T> {
62    fn rows(&self) -> usize {
63        self.0.len()
64    }
65
66    fn cols(&self) -> usize {
67        self.rows()
68    }
69
70    fn transpose(&self) -> Self {
71        let a_00 = self[(0, 0)];
72        let a_01 = self[(0, 1)];
73        let a_02 = self[(0, 2)];
74        let a_03 = self[(0, 3)];
75        let a_04 = self[(0, 4)];
76        let a_10 = self[(1, 0)];
77        let a_11 = self[(1, 1)];
78        let a_12 = self[(1, 2)];
79        let a_13 = self[(1, 3)];
80        let a_14 = self[(1, 4)];
81        let a_20 = self[(2, 0)];
82        let a_21 = self[(2, 1)];
83        let a_22 = self[(2, 2)];
84        let a_23 = self[(2, 3)];
85        let a_24 = self[(2, 4)];
86        let a_30 = self[(3, 0)];
87        let a_31 = self[(3, 1)];
88        let a_32 = self[(3, 2)];
89        let a_33 = self[(3, 3)];
90        let a_34 = self[(3, 4)];
91        let a_40 = self[(4, 0)];
92        let a_41 = self[(4, 1)];
93        let a_42 = self[(4, 2)];
94        let a_43 = self[(4, 3)];
95        let a_44 = self[(4, 4)];
96
97        M55::new([
98            [a_00, a_10, a_20, a_30, a_40],
99            [a_01, a_11, a_21, a_31, a_41],
100            [a_02, a_12, a_22, a_32, a_42],
101            [a_03, a_13, a_23, a_33, a_43],
102            [a_04, a_14, a_24, a_34, a_44],
103        ])
104    }
105
106    fn trace(&self) -> T {
107        self[(0, 0)] + self[(1, 1)] + self[(2, 2)] + self[(3, 3)] + self[(4, 4)]
108    }
109
110    fn norm2(&self) -> T {
111        T::sqrt(
112            self.iter()
113                .flatten()
114                .cloned()
115                .map(|element| element * element)
116                .sum(),
117        )
118    }
119
120    fn det(&self) -> T {
121        let a_00 = self[(0, 0)];
122        let a_01 = self[(0, 1)];
123        let a_02 = self[(0, 2)];
124        let a_03 = self[(0, 3)];
125        let a_04 = self[(0, 4)];
126        let a_10 = self[(1, 0)];
127        let a_11 = self[(1, 1)];
128        let a_12 = self[(1, 2)];
129        let a_13 = self[(1, 3)];
130        let a_14 = self[(1, 4)];
131        let a_20 = self[(2, 0)];
132        let a_21 = self[(2, 1)];
133        let a_22 = self[(2, 2)];
134        let a_23 = self[(2, 3)];
135        let a_24 = self[(2, 4)];
136        let a_30 = self[(3, 0)];
137        let a_31 = self[(3, 1)];
138        let a_32 = self[(3, 2)];
139        let a_33 = self[(3, 3)];
140        let a_34 = self[(3, 4)];
141        let a_40 = self[(4, 0)];
142        let a_41 = self[(4, 1)];
143        let a_42 = self[(4, 2)];
144        let a_43 = self[(4, 3)];
145        let a_44 = self[(4, 4)];
146
147        a_00 * a_11 * a_22 * a_33 * a_44
148            - a_00 * a_11 * a_22 * a_34 * a_43
149            - a_00 * a_11 * a_23 * a_32 * a_44
150            + a_00 * a_11 * a_23 * a_34 * a_42
151            + a_00 * a_11 * a_24 * a_32 * a_43
152            - a_00 * a_11 * a_24 * a_33 * a_42
153            - a_00 * a_12 * a_21 * a_33 * a_44
154            + a_00 * a_12 * a_21 * a_34 * a_43
155            + a_00 * a_12 * a_23 * a_31 * a_44
156            - a_00 * a_12 * a_23 * a_34 * a_41
157            - a_00 * a_12 * a_24 * a_31 * a_43
158            + a_00 * a_12 * a_24 * a_33 * a_41
159            + a_00 * a_13 * a_21 * a_32 * a_44
160            - a_00 * a_13 * a_21 * a_34 * a_42
161            - a_00 * a_13 * a_22 * a_31 * a_44
162            + a_00 * a_13 * a_22 * a_34 * a_41
163            + a_00 * a_13 * a_24 * a_31 * a_42
164            - a_00 * a_13 * a_24 * a_32 * a_41
165            - a_00 * a_14 * a_21 * a_32 * a_43
166            + a_00 * a_14 * a_21 * a_33 * a_42
167            + a_00 * a_14 * a_22 * a_31 * a_43
168            - a_00 * a_14 * a_22 * a_33 * a_41
169            - a_00 * a_14 * a_23 * a_31 * a_42
170            + a_00 * a_14 * a_23 * a_32 * a_41
171            - a_01 * a_10 * a_22 * a_33 * a_44
172            + a_01 * a_10 * a_22 * a_34 * a_43
173            + a_01 * a_10 * a_23 * a_32 * a_44
174            - a_01 * a_10 * a_23 * a_34 * a_42
175            - a_01 * a_10 * a_24 * a_32 * a_43
176            + a_01 * a_10 * a_24 * a_33 * a_42
177            + a_01 * a_12 * a_20 * a_33 * a_44
178            - a_01 * a_12 * a_20 * a_34 * a_43
179            - a_01 * a_12 * a_23 * a_30 * a_44
180            + a_01 * a_12 * a_23 * a_34 * a_40
181            + a_01 * a_12 * a_24 * a_30 * a_43
182            - a_01 * a_12 * a_24 * a_33 * a_40
183            - a_01 * a_13 * a_20 * a_32 * a_44
184            + a_01 * a_13 * a_20 * a_34 * a_42
185            + a_01 * a_13 * a_22 * a_30 * a_44
186            - a_01 * a_13 * a_22 * a_34 * a_40
187            - a_01 * a_13 * a_24 * a_30 * a_42
188            + a_01 * a_13 * a_24 * a_32 * a_40
189            + a_01 * a_14 * a_20 * a_32 * a_43
190            - a_01 * a_14 * a_20 * a_33 * a_42
191            - a_01 * a_14 * a_22 * a_30 * a_43
192            + a_01 * a_14 * a_22 * a_33 * a_40
193            + a_01 * a_14 * a_23 * a_30 * a_42
194            - a_01 * a_14 * a_23 * a_32 * a_40
195            + a_02 * a_10 * a_21 * a_33 * a_44
196            - a_02 * a_10 * a_21 * a_34 * a_43
197            - a_02 * a_10 * a_23 * a_31 * a_44
198            + a_02 * a_10 * a_23 * a_34 * a_41
199            + a_02 * a_10 * a_24 * a_31 * a_43
200            - a_02 * a_10 * a_24 * a_33 * a_41
201            - a_02 * a_11 * a_20 * a_33 * a_44
202            + a_02 * a_11 * a_20 * a_34 * a_43
203            + a_02 * a_11 * a_23 * a_30 * a_44
204            - a_02 * a_11 * a_23 * a_34 * a_40
205            - a_02 * a_11 * a_24 * a_30 * a_43
206            + a_02 * a_11 * a_24 * a_33 * a_40
207            + a_02 * a_13 * a_20 * a_31 * a_44
208            - a_02 * a_13 * a_20 * a_34 * a_41
209            - a_02 * a_13 * a_21 * a_30 * a_44
210            + a_02 * a_13 * a_21 * a_34 * a_40
211            + a_02 * a_13 * a_24 * a_30 * a_41
212            - a_02 * a_13 * a_24 * a_31 * a_40
213            - a_02 * a_14 * a_20 * a_31 * a_43
214            + a_02 * a_14 * a_20 * a_33 * a_41
215            + a_02 * a_14 * a_21 * a_30 * a_43
216            - a_02 * a_14 * a_21 * a_33 * a_40
217            - a_02 * a_14 * a_23 * a_30 * a_41
218            + a_02 * a_14 * a_23 * a_31 * a_40
219            - a_03 * a_10 * a_21 * a_32 * a_44
220            + a_03 * a_10 * a_21 * a_34 * a_42
221            + a_03 * a_10 * a_22 * a_31 * a_44
222            - a_03 * a_10 * a_22 * a_34 * a_41
223            - a_03 * a_10 * a_24 * a_31 * a_42
224            + a_03 * a_10 * a_24 * a_32 * a_41
225            + a_03 * a_11 * a_20 * a_32 * a_44
226            - a_03 * a_11 * a_20 * a_34 * a_42
227            - a_03 * a_11 * a_22 * a_30 * a_44
228            + a_03 * a_11 * a_22 * a_34 * a_40
229            + a_03 * a_11 * a_24 * a_30 * a_42
230            - a_03 * a_11 * a_24 * a_32 * a_40
231            - a_03 * a_12 * a_20 * a_31 * a_44
232            + a_03 * a_12 * a_20 * a_34 * a_41
233            + a_03 * a_12 * a_21 * a_30 * a_44
234            - a_03 * a_12 * a_21 * a_34 * a_40
235            - a_03 * a_12 * a_24 * a_30 * a_41
236            + a_03 * a_12 * a_24 * a_31 * a_40
237            + a_03 * a_14 * a_20 * a_31 * a_42
238            - a_03 * a_14 * a_20 * a_32 * a_41
239            - a_03 * a_14 * a_21 * a_30 * a_42
240            + a_03 * a_14 * a_21 * a_32 * a_40
241            + a_03 * a_14 * a_22 * a_30 * a_41
242            - a_03 * a_14 * a_22 * a_31 * a_40
243            + a_04 * a_10 * a_21 * a_32 * a_43
244            - a_04 * a_10 * a_21 * a_33 * a_42
245            - a_04 * a_10 * a_22 * a_31 * a_43
246            + a_04 * a_10 * a_22 * a_33 * a_41
247            + a_04 * a_10 * a_23 * a_31 * a_42
248            - a_04 * a_10 * a_23 * a_32 * a_41
249            - a_04 * a_11 * a_20 * a_32 * a_43
250            + a_04 * a_11 * a_20 * a_33 * a_42
251            + a_04 * a_11 * a_22 * a_30 * a_43
252            - a_04 * a_11 * a_22 * a_33 * a_40
253            - a_04 * a_11 * a_23 * a_30 * a_42
254            + a_04 * a_11 * a_23 * a_32 * a_40
255            + a_04 * a_12 * a_20 * a_31 * a_43
256            - a_04 * a_12 * a_20 * a_33 * a_41
257            - a_04 * a_12 * a_21 * a_30 * a_43
258            + a_04 * a_12 * a_21 * a_33 * a_40
259            + a_04 * a_12 * a_23 * a_30 * a_41
260            - a_04 * a_12 * a_23 * a_31 * a_40
261            - a_04 * a_13 * a_20 * a_31 * a_42
262            + a_04 * a_13 * a_20 * a_32 * a_41
263            + a_04 * a_13 * a_21 * a_30 * a_42
264            - a_04 * a_13 * a_21 * a_32 * a_40
265            - a_04 * a_13 * a_22 * a_30 * a_41
266            + a_04 * a_13 * a_22 * a_31 * a_40
267    }
268    ///
269    /// Calculate the inverse of the Matrix6x6 via tha Adjoint Matrix:
270    /// A^(-1) = 1/det Adj
271    /// where Adj = Cofactor.Transpose()
272    /// Cofactor = (-1)^(i+j) M(i, j).det()
273    ///
274    #[inline(always)]
275    fn inverse(&self) -> Option<Self> {
276        let one = T::one();
277        let det = self.det();
278        if !nearly_zero(det) {
279            let mut cofactors: M55<T> = M55::zeros();
280            for i in 0..self.rows() {
281                for j in 0..self.cols() {
282                    let sign = if (i + j) % 2 == 0 {one} else {-one};
283                    // transpose in place
284                    cofactors[(j, i)] = sign * self.get_submatrix((i, j)).det();
285                }
286            }
287            Some(cofactors / det)
288        } else {
289            None
290        }
291    }
292
293    /// Calculate de QR factorization of the M55 via gram-schmidt
294    /// orthogonalization process
295    fn qr(&self) -> Option<(Self, Self)> {
296        if !nearly_zero(self.det()) {
297            let cols = self.get_cols();
298            let mut q: [V5<T>; 5] = *M55::zeros().get_cols();
299            for i in 0..q.len() {
300                let mut q_tilde = cols[i];
301                for elem in q.iter().take(i) {
302                    q_tilde -= *elem * project_x_over_y(&*cols[i], &**elem);
303                }
304                normalize(&mut *q_tilde);
305                q[i] = q_tilde;
306            }
307            let basis = V5::new_from(q[0], q[1], q[2], q[3], q[4]);
308            let q     = M55::new_from_vecs(basis);
309            let r     = q.transpose() * (*self);
310            Some((q, r))
311        } else {
312            None
313        }
314    }
315}
316
317
318impl<T: Num + Copy> Add for M55<T> {
319    type Output = Self;
320
321    fn add(self, rhs: Self) -> Self {
322        let a_00 = self[(0, 0)];
323        let a_01 = self[(0, 1)];
324        let a_02 = self[(0, 2)];
325        let a_03 = self[(0, 3)];
326        let a_04 = self[(0, 4)];
327        let a_10 = self[(1, 0)];
328        let a_11 = self[(1, 1)];
329        let a_12 = self[(1, 2)];
330        let a_13 = self[(1, 3)];
331        let a_14 = self[(1, 4)];
332        let a_20 = self[(2, 0)];
333        let a_21 = self[(2, 1)];
334        let a_22 = self[(2, 2)];
335        let a_23 = self[(2, 3)];
336        let a_24 = self[(2, 4)];
337        let a_30 = self[(3, 0)];
338        let a_31 = self[(3, 1)];
339        let a_32 = self[(3, 2)];
340        let a_33 = self[(3, 3)];
341        let a_34 = self[(3, 4)];
342        let a_40 = self[(4, 0)];
343        let a_41 = self[(4, 1)];
344        let a_42 = self[(4, 2)];
345        let a_43 = self[(4, 3)];
346        let a_44 = self[(4, 4)];
347
348        let b_00 = rhs[(0, 0)];
349        let b_01 = rhs[(0, 1)];
350        let b_02 = rhs[(0, 2)];
351        let b_03 = rhs[(0, 3)];
352        let b_04 = rhs[(0, 4)];
353        let b_10 = rhs[(1, 0)];
354        let b_11 = rhs[(1, 1)];
355        let b_12 = rhs[(1, 2)];
356        let b_13 = rhs[(1, 3)];
357        let b_14 = rhs[(1, 4)];
358        let b_20 = rhs[(2, 0)];
359        let b_21 = rhs[(2, 1)];
360        let b_22 = rhs[(2, 2)];
361        let b_23 = rhs[(2, 3)];
362        let b_24 = rhs[(2, 4)];
363        let b_30 = rhs[(3, 0)];
364        let b_31 = rhs[(3, 1)];
365        let b_32 = rhs[(3, 2)];
366        let b_33 = rhs[(3, 3)];
367        let b_34 = rhs[(3, 4)];
368        let b_40 = rhs[(4, 0)];
369        let b_41 = rhs[(4, 1)];
370        let b_42 = rhs[(4, 2)];
371        let b_43 = rhs[(4, 3)];
372        let b_44 = rhs[(4, 4)];
373
374        M55::new([
375            [
376                a_00 + b_00,
377                a_01 + b_01,
378                a_02 + b_02,
379                a_03 + b_03,
380                a_04 + b_04,
381            ],
382            [
383                a_10 + b_10,
384                a_11 + b_11,
385                a_12 + b_12,
386                a_13 + b_13,
387                a_14 + b_14,
388            ],
389            [
390                a_20 + b_20,
391                a_21 + b_21,
392                a_22 + b_22,
393                a_23 + b_23,
394                a_24 + b_24,
395            ],
396            [
397                a_30 + b_30,
398                a_31 + b_31,
399                a_32 + b_32,
400                a_33 + b_33,
401                a_34 + b_34,
402            ],
403            [
404                a_40 + b_40,
405                a_41 + b_41,
406                a_42 + b_42,
407                a_43 + b_43,
408                a_44 + b_44,
409            ],
410        ])
411    }
412}
413
414
415// M55 += M55
416impl<T: Num + Copy> AddAssign for M55<T> {
417    fn add_assign(&mut self, other: Self) {
418        *self = *self + other
419    }
420}
421
422// M55 - M55
423impl<T: Num + Copy> Sub for M55<T> {
424    type Output = Self;
425
426    fn sub(self, rhs: Self) -> Self {
427        let a_00 = self[(0, 0)];
428        let a_01 = self[(0, 1)];
429        let a_02 = self[(0, 2)];
430        let a_03 = self[(0, 3)];
431        let a_04 = self[(0, 4)];
432        let a_10 = self[(1, 0)];
433        let a_11 = self[(1, 1)];
434        let a_12 = self[(1, 2)];
435        let a_13 = self[(1, 3)];
436        let a_14 = self[(1, 4)];
437        let a_20 = self[(2, 0)];
438        let a_21 = self[(2, 1)];
439        let a_22 = self[(2, 2)];
440        let a_23 = self[(2, 3)];
441        let a_24 = self[(2, 4)];
442        let a_30 = self[(3, 0)];
443        let a_31 = self[(3, 1)];
444        let a_32 = self[(3, 2)];
445        let a_33 = self[(3, 3)];
446        let a_34 = self[(3, 4)];
447        let a_40 = self[(4, 0)];
448        let a_41 = self[(4, 1)];
449        let a_42 = self[(4, 2)];
450        let a_43 = self[(4, 3)];
451        let a_44 = self[(4, 4)];
452
453        let b_00 = rhs[(0, 0)];
454        let b_01 = rhs[(0, 1)];
455        let b_02 = rhs[(0, 2)];
456        let b_03 = rhs[(0, 3)];
457        let b_04 = rhs[(0, 4)];
458        let b_10 = rhs[(1, 0)];
459        let b_11 = rhs[(1, 1)];
460        let b_12 = rhs[(1, 2)];
461        let b_13 = rhs[(1, 3)];
462        let b_14 = rhs[(1, 4)];
463        let b_20 = rhs[(2, 0)];
464        let b_21 = rhs[(2, 1)];
465        let b_22 = rhs[(2, 2)];
466        let b_23 = rhs[(2, 3)];
467        let b_24 = rhs[(2, 4)];
468        let b_30 = rhs[(3, 0)];
469        let b_31 = rhs[(3, 1)];
470        let b_32 = rhs[(3, 2)];
471        let b_33 = rhs[(3, 3)];
472        let b_34 = rhs[(3, 4)];
473        let b_40 = rhs[(4, 0)];
474        let b_41 = rhs[(4, 1)];
475        let b_42 = rhs[(4, 2)];
476        let b_43 = rhs[(4, 3)];
477        let b_44 = rhs[(4, 4)];
478
479        M55::new([
480            [
481                a_00 - b_00,
482                a_01 - b_01,
483                a_02 - b_02,
484                a_03 - b_03,
485                a_04 - b_04,
486            ],
487            [
488                a_10 - b_10,
489                a_11 - b_11,
490                a_12 - b_12,
491                a_13 - b_13,
492                a_14 - b_14,
493            ],
494            [
495                a_20 - b_20,
496                a_21 - b_21,
497                a_22 - b_22,
498                a_23 - b_23,
499                a_24 - b_24,
500            ],
501            [
502                a_30 - b_30,
503                a_31 - b_31,
504                a_32 - b_32,
505                a_33 - b_33,
506                a_34 - b_34,
507            ],
508            [
509                a_40 - b_40,
510                a_41 - b_41,
511                a_42 - b_42,
512                a_43 - b_43,
513                a_44 - b_44,
514            ],
515        ])
516    }
517}
518
519// M55 -= M55
520impl<T: Num + Copy> SubAssign for M55<T> {
521    fn sub_assign(&mut self, other: Self) {
522        *self = *self - other
523    }
524}
525
526// M55 * constant
527impl<T: Num + Copy> Mul<T> for M55<T> {
528    type Output = M55<T>;
529
530    fn mul(self, rhs: T) -> M55<T> {
531        let a_00 = self[(0, 0)] * rhs;
532        let a_01 = self[(0, 1)] * rhs;
533        let a_02 = self[(0, 2)] * rhs;
534        let a_03 = self[(0, 3)] * rhs;
535        let a_04 = self[(0, 4)] * rhs;
536        let a_10 = self[(1, 0)] * rhs;
537        let a_11 = self[(1, 1)] * rhs;
538        let a_12 = self[(1, 2)] * rhs;
539        let a_13 = self[(1, 3)] * rhs;
540        let a_14 = self[(1, 4)] * rhs;
541        let a_20 = self[(2, 0)] * rhs;
542        let a_21 = self[(2, 1)] * rhs;
543        let a_22 = self[(2, 2)] * rhs;
544        let a_23 = self[(2, 3)] * rhs;
545        let a_24 = self[(2, 4)] * rhs;
546        let a_30 = self[(3, 0)] * rhs;
547        let a_31 = self[(3, 1)] * rhs;
548        let a_32 = self[(3, 2)] * rhs;
549        let a_33 = self[(3, 3)] * rhs;
550        let a_34 = self[(3, 4)] * rhs;
551        let a_40 = self[(4, 0)] * rhs;
552        let a_41 = self[(4, 1)] * rhs;
553        let a_42 = self[(4, 2)] * rhs;
554        let a_43 = self[(4, 3)] * rhs;
555        let a_44 = self[(4, 4)] * rhs;
556
557        M55::new([
558            [a_00, a_01, a_02, a_03, a_04],
559            [a_10, a_11, a_12, a_13, a_14],
560            [a_20, a_21, a_22, a_23, a_24],
561            [a_30, a_31, a_32, a_33, a_34],
562            [a_40, a_41, a_42, a_43, a_44],
563        ])
564    }
565}
566
567// M55 / constant
568impl<T: Num + Copy> Div<T> for M55<T> {
569    type Output = Self;
570
571    fn div(self, rhs: T) -> Self::Output {
572        let a_00 = self[(0, 0)] / rhs;
573        let a_01 = self[(0, 1)] / rhs;
574        let a_02 = self[(0, 2)] / rhs;
575        let a_03 = self[(0, 3)] / rhs;
576        let a_04 = self[(0, 4)] / rhs;
577        let a_10 = self[(1, 0)] / rhs;
578        let a_11 = self[(1, 1)] / rhs;
579        let a_12 = self[(1, 2)] / rhs;
580        let a_13 = self[(1, 3)] / rhs;
581        let a_14 = self[(1, 4)] / rhs;
582        let a_20 = self[(2, 0)] / rhs;
583        let a_21 = self[(2, 1)] / rhs;
584        let a_22 = self[(2, 2)] / rhs;
585        let a_23 = self[(2, 3)] / rhs;
586        let a_24 = self[(2, 4)] / rhs;
587        let a_30 = self[(3, 0)] / rhs;
588        let a_31 = self[(3, 1)] / rhs;
589        let a_32 = self[(3, 2)] / rhs;
590        let a_33 = self[(3, 3)] / rhs;
591        let a_34 = self[(3, 4)] / rhs;
592        let a_40 = self[(4, 0)] / rhs;
593        let a_41 = self[(4, 1)] / rhs;
594        let a_42 = self[(4, 2)] / rhs;
595        let a_43 = self[(4, 3)] / rhs;
596        let a_44 = self[(4, 4)] / rhs;
597
598        M55::new([
599            [a_00, a_01, a_02, a_03, a_04],
600            [a_10, a_11, a_12, a_13, a_14],
601            [a_20, a_21, a_22, a_23, a_24],
602            [a_30, a_31, a_32, a_33, a_34],
603            [a_40, a_41, a_42, a_43, a_44],
604        ])
605    }
606}
607
608// M55 * V5
609impl<T: Num + Copy> Mul<V5<T>> for M55<T> {
610    type Output = V5<T>;
611
612    fn mul(self, rhs: V5<T>) -> V5<T> {
613
614        let a_00 = self[(0, 0)];
615        let a_01 = self[(0, 1)];
616        let a_02 = self[(0, 2)];
617        let a_03 = self[(0, 3)];
618        let a_04 = self[(0, 4)];
619        let a_10 = self[(1, 0)];
620        let a_11 = self[(1, 1)];
621        let a_12 = self[(1, 2)];
622        let a_13 = self[(1, 3)];
623        let a_14 = self[(1, 4)];
624        let a_20 = self[(2, 0)];
625        let a_21 = self[(2, 1)];
626        let a_22 = self[(2, 2)];
627        let a_23 = self[(2, 3)];
628        let a_24 = self[(2, 4)];
629        let a_30 = self[(3, 0)];
630        let a_31 = self[(3, 1)];
631        let a_32 = self[(3, 2)];
632        let a_33 = self[(3, 3)];
633        let a_34 = self[(3, 4)];
634        let a_40 = self[(4, 0)];
635        let a_41 = self[(4, 1)];
636        let a_42 = self[(4, 2)];
637        let a_43 = self[(4, 3)];
638        let a_44 = self[(4, 4)];
639
640        let v0 = a_00 * rhs[0] + a_01 * rhs[1] + a_02 * rhs[2] + a_03 * rhs[3] + a_04 * rhs[4];
641        let v1 = a_10 * rhs[0] + a_11 * rhs[1] + a_12 * rhs[2] + a_13 * rhs[3] + a_14 * rhs[4];
642        let v2 = a_20 * rhs[0] + a_21 * rhs[1] + a_22 * rhs[2] + a_23 * rhs[3] + a_24 * rhs[4];
643        let v3 = a_30 * rhs[0] + a_31 * rhs[1] + a_32 * rhs[2] + a_33 * rhs[3] + a_34 * rhs[4];
644        let v4 = a_40 * rhs[0] + a_41 * rhs[1] + a_42 * rhs[2] + a_43 * rhs[3] + a_44 * rhs[4];
645
646        V5::new([v0, v1, v2, v3, v4])
647    }
648
649}
650
651// M55 * M55
652impl<T: Num + Copy> Mul for M55<T> {
653    type Output = Self;
654
655    fn mul(self, rhs: Self) -> Self {
656        let a_00 = self[(0, 0)];
657        let a_01 = self[(0, 1)];
658        let a_02 = self[(0, 2)];
659        let a_03 = self[(0, 3)];
660        let a_04 = self[(0, 4)];
661        let a_10 = self[(1, 0)];
662        let a_11 = self[(1, 1)];
663        let a_12 = self[(1, 2)];
664        let a_13 = self[(1, 3)];
665        let a_14 = self[(1, 4)];
666        let a_20 = self[(2, 0)];
667        let a_21 = self[(2, 1)];
668        let a_22 = self[(2, 2)];
669        let a_23 = self[(2, 3)];
670        let a_24 = self[(2, 4)];
671        let a_30 = self[(3, 0)];
672        let a_31 = self[(3, 1)];
673        let a_32 = self[(3, 2)];
674        let a_33 = self[(3, 3)];
675        let a_34 = self[(3, 4)];
676        let a_40 = self[(4, 0)];
677        let a_41 = self[(4, 1)];
678        let a_42 = self[(4, 2)];
679        let a_43 = self[(4, 3)];
680        let a_44 = self[(4, 4)];
681
682        let b_00 = rhs[(0, 0)];
683        let b_01 = rhs[(0, 1)];
684        let b_02 = rhs[(0, 2)];
685        let b_03 = rhs[(0, 3)];
686        let b_04 = rhs[(0, 4)];
687        let b_10 = rhs[(1, 0)];
688        let b_11 = rhs[(1, 1)];
689        let b_12 = rhs[(1, 2)];
690        let b_13 = rhs[(1, 3)];
691        let b_14 = rhs[(1, 4)];
692        let b_20 = rhs[(2, 0)];
693        let b_21 = rhs[(2, 1)];
694        let b_22 = rhs[(2, 2)];
695        let b_23 = rhs[(2, 3)];
696        let b_24 = rhs[(2, 4)];
697        let b_30 = rhs[(3, 0)];
698        let b_31 = rhs[(3, 1)];
699        let b_32 = rhs[(3, 2)];
700        let b_33 = rhs[(3, 3)];
701        let b_34 = rhs[(3, 4)];
702        let b_40 = rhs[(4, 0)];
703        let b_41 = rhs[(4, 1)];
704        let b_42 = rhs[(4, 2)];
705        let b_43 = rhs[(4, 3)];
706        let b_44 = rhs[(4, 4)];
707
708        M55::new([
709            [
710                a_00 * b_00 + a_01 * b_10 + a_02 * b_20 + a_03 * b_30 + a_04 * b_40,
711                a_00 * b_01 + a_01 * b_11 + a_02 * b_21 + a_03 * b_31 + a_04 * b_41,
712                a_00 * b_02 + a_01 * b_12 + a_02 * b_22 + a_03 * b_32 + a_04 * b_42,
713                a_00 * b_03 + a_01 * b_13 + a_02 * b_23 + a_03 * b_33 + a_04 * b_43,
714                a_00 * b_04 + a_01 * b_14 + a_02 * b_24 + a_03 * b_34 + a_04 * b_44,
715            ],
716            [
717                a_10 * b_00 + a_11 * b_10 + a_12 * b_20 + a_13 * b_30 + a_14 * b_40,
718                a_10 * b_01 + a_11 * b_11 + a_12 * b_21 + a_13 * b_31 + a_14 * b_41,
719                a_10 * b_02 + a_11 * b_12 + a_12 * b_22 + a_13 * b_32 + a_14 * b_42,
720                a_10 * b_03 + a_11 * b_13 + a_12 * b_23 + a_13 * b_33 + a_14 * b_43,
721                a_10 * b_04 + a_11 * b_14 + a_12 * b_24 + a_13 * b_34 + a_14 * b_44,
722            ],
723            [
724                a_20 * b_00 + a_21 * b_10 + a_22 * b_20 + a_23 * b_30 + a_24 * b_40,
725                a_20 * b_01 + a_21 * b_11 + a_22 * b_21 + a_23 * b_31 + a_24 * b_41,
726                a_20 * b_02 + a_21 * b_12 + a_22 * b_22 + a_23 * b_32 + a_24 * b_42,
727                a_20 * b_03 + a_21 * b_13 + a_22 * b_23 + a_23 * b_33 + a_24 * b_43,
728                a_20 * b_04 + a_21 * b_14 + a_22 * b_24 + a_23 * b_34 + a_24 * b_44,
729            ],
730            [
731                a_30 * b_00 + a_31 * b_10 + a_32 * b_20 + a_33 * b_30 + a_34 * b_40,
732                a_30 * b_01 + a_31 * b_11 + a_32 * b_21 + a_33 * b_31 + a_34 * b_41,
733                a_30 * b_02 + a_31 * b_12 + a_32 * b_22 + a_33 * b_32 + a_34 * b_42,
734                a_30 * b_03 + a_31 * b_13 + a_32 * b_23 + a_33 * b_33 + a_34 * b_43,
735                a_30 * b_04 + a_31 * b_14 + a_32 * b_24 + a_33 * b_34 + a_34 * b_44,
736            ],
737            [
738                a_40 * b_00 + a_41 * b_10 + a_42 * b_20 + a_43 * b_30 + a_44 * b_40,
739                a_40 * b_01 + a_41 * b_11 + a_42 * b_21 + a_43 * b_31 + a_44 * b_41,
740                a_40 * b_02 + a_41 * b_12 + a_42 * b_22 + a_43 * b_32 + a_44 * b_42,
741                a_40 * b_03 + a_41 * b_13 + a_42 * b_23 + a_43 * b_33 + a_44 * b_43,
742                a_40 * b_04 + a_41 * b_14 + a_42 * b_24 + a_43 * b_34 + a_44 * b_44,
743            ],
744        ])
745    }
746}
747
748// -M55
749impl<T: Num + Copy + Signed> Neg for M55<T> {
750    type Output = Self;
751
752    fn neg(self) -> Self {
753        let a_00 = -self[(0, 0)];
754        let a_01 = -self[(0, 1)];
755        let a_02 = -self[(0, 2)];
756        let a_03 = -self[(0, 3)];
757        let a_04 = -self[(0, 4)];
758        let a_10 = -self[(1, 0)];
759        let a_11 = -self[(1, 1)];
760        let a_12 = -self[(1, 2)];
761        let a_13 = -self[(1, 3)];
762        let a_14 = -self[(1, 4)];
763        let a_20 = -self[(2, 0)];
764        let a_21 = -self[(2, 1)];
765        let a_22 = -self[(2, 2)];
766        let a_23 = -self[(2, 3)];
767        let a_24 = -self[(2, 4)];
768        let a_30 = -self[(3, 0)];
769        let a_31 = -self[(3, 1)];
770        let a_32 = -self[(3, 2)];
771        let a_33 = -self[(3, 3)];
772        let a_34 = -self[(3, 4)];
773        let a_40 = -self[(4, 0)];
774        let a_41 = -self[(4, 1)];
775        let a_42 = -self[(4, 2)];
776        let a_43 = -self[(4, 3)];
777        let a_44 = -self[(4, 4)];
778
779        M55::new([
780            [a_00, a_01, a_02, a_03, a_04],
781            [a_10, a_11, a_12, a_13, a_14],
782            [a_20, a_21, a_22, a_23, a_24],
783            [a_30, a_31, a_32, a_33, a_34],
784            [a_40, a_41, a_42, a_43, a_44],
785        ])
786    }
787}
788impl<T: Num + Copy> Zero for M55<T> {
789    fn zero() -> M55<T> {
790        M55::new([[T::zero(); 5]; 5])
791    }
792
793    fn is_zero(&self) -> bool {
794        *self == M55::zero()
795    }
796}
797
798impl<T: Num + Copy> One for M55<T> {
799    /// Create an identity matrix
800    fn one() -> M55<T> {
801        let one = T::one();
802        let zero = T::zero();
803        M55::new([
804            [one, zero, zero, zero, zero],
805            [zero, one, zero, zero, zero],
806            [zero, zero, one, zero, zero],
807            [zero, zero, zero, one, zero],
808            [zero, zero, zero, zero, one],
809        ])
810    }
811}
812
813impl<T: Num + Copy> M55<T> {
814    /// contruct identity matrix
815    pub fn identity() -> M55<T> {
816        <M55<T> as One>::one()
817    }
818
819    /// construct the matrix with all zeros
820    pub fn zeros() -> M55<T> {
821        <M55<T> as Zero>::zero()
822    }
823
824    /// transform the matrix to a flatten vector
825    pub fn as_vec(&self) -> [T; 25] {
826        let mut result = [T::zero(); 25];
827        for (index, element) in self.iter().flatten().enumerate() {
828            result[index] = *element;
829        }
830        result
831    }
832
833    pub fn new_from_vecs(cols: V5<V5<T>>) -> Self {
834        let mut result = Self::zeros();
835
836        for i in 0..result.cols() {
837            result[(i, 0)] = cols[0][i];
838            result[(i, 1)] = cols[1][i];
839            result[(i, 2)] = cols[2][i];
840            result[(i, 3)] = cols[3][i];
841            result[(i, 4)] = cols[4][i];
842        }
843        result
844    }
845
846    /// get the diagonal of the matrix
847    pub fn get_diagonal(&self) -> V5<T> {
848        let mut result = V5::zeros();
849        let mut index: usize = 0;
850        for i in 0..self.rows() {
851            for j in 0..self.cols() {
852                if i == j {
853                    result[index] = self[(i, j)];
854                    index += 1;
855                }
856            }
857        }
858        result
859    }
860
861    /// get the a submatrix from discard row `i` and column `j`
862    fn get_submatrix(&self, selected: (usize, usize)) -> M44<T> {
863        let mut values: [T; 16] = [T::zero(); 16];
864        let mut result: M44<T> = M44::zeros();
865        let mut index: usize = 0;
866        for i in 0..self.rows() {
867            for j in 0..self.cols() {
868                if !(i == selected.0 || j == selected.1) {
869                    values[index] = self[(i, j)];
870                    index += 1;
871                }
872            }
873        }
874        index = 0;
875        for r in 0..result.rows() {
876            for c in 0..result.cols() {
877                result[(r, c)] = values[index];
878                index += 1;
879            }
880        }
881        result
882    }
883
884    pub fn get_rows(self) -> V5<V5<T>> {
885        let mut r0 = V5::zeros();
886        let mut r1 = V5::zeros();
887        let mut r2 = V5::zeros();
888        let mut r3 = V5::zeros();
889        let mut r4 = V5::zeros();
890
891        for j in 0..self.rows() {
892            r0[j] = self[(0, j)];
893            r1[j] = self[(1, j)];
894            r2[j] = self[(2, j)];
895            r3[j] = self[(3, j)];
896            r4[j] = self[(4, j)];
897        }
898        V5::new([r0, r1, r2, r3, r4])
899    }
900
901    pub fn get_cols(self) -> V5<V5<T>> {
902        let mut c0 = V5::zeros();
903        let mut c1 = V5::zeros();
904        let mut c2 = V5::zeros();
905        let mut c3 = V5::zeros();
906        let mut c4 = V5::zeros();
907
908        for i in 0..self.cols() {
909            c0[i] = self[(i, 0)];
910            c1[i] = self[(i, 1)];
911            c2[i] = self[(i, 2)];
912            c3[i] = self[(i, 3)];
913            c4[i] = self[(i, 4)];
914        }
915        V5::new([c0, c1, c2, c3, c4])
916    }
917
918    pub fn get_upper_triagular(&self) -> [T; 10] {
919        let zero = T::zero();
920        let mut result: [T; 10] = [zero; 10];
921        let mut index = 0;
922        for i in 0..self.rows() {
923            for j in 0..self.cols() {
924                if i < j {
925                    result[index] = self[(i, j)];
926                    index += 1;
927                }
928            }
929        }
930        result
931    }
932
933    pub fn get_lower_triangular(&self) -> [T; 10] {
934        let zero = T::zero();
935        let mut result: [T; 10] = [zero; 10];
936        let mut index = 0;
937        for i in 0..self.rows() {
938            for j in 0..self.cols() {
939                if i > j {
940                    result[index] = self[(i, j)];
941                    index += 1;
942                }
943            }
944        }
945        result
946    }
947
948    /// Applies `f` of each element in the M44
949    pub fn for_each(&self, f: impl Fn(T) -> T) -> Self {
950        let mut result = Self::zeros();
951        for i in 0..self.rows() {
952            for j in 0..self.cols() {
953                result[(i, j)] = f(self[(i, j)]);
954            }
955        }
956        result
957    }
958
959}
960
961impl<T> Deref for M55<T> {
962    type Target = [[T; 5]; 5];
963    #[inline]
964    fn deref(&self) -> &Self::Target {
965        &self.0
966    }
967}
968
969impl<T> DerefMut for M55<T> {
970    #[inline]
971    fn deref_mut(&mut self) -> &mut Self::Target {
972        &mut self.0
973    }
974}
975
976impl<T> From<[[T; 5]; 5]> for M55<T> {
977    fn from(data: [[T; 5]; 5]) -> M55<T> {
978        M55(data)
979    }
980}
981
982impl<T> Index<(usize, usize)> for M55<T> {
983    type Output = T;
984    #[inline(always)]
985    fn index(&self, index: (usize, usize)) -> &T {
986        &self.0[index.0][index.1]
987    }
988}
989
990impl<T> IndexMut<(usize, usize)> for M55<T> {
991    #[inline(always)]
992    fn index_mut(&mut self, index: (usize, usize)) -> &mut T {
993        &mut self.0[index.0][index.1]
994    }
995}
996
997//-------------------------------------------------------------------------
998//                        Display for M55
999//-------------------------------------------------------------------------
1000impl<T: Num + fmt::Display> fmt::Display for M55<T> {
1001    fn fmt(&self, dest: &mut fmt::Formatter) -> fmt::Result {
1002        println!();
1003        writeln!(
1004            dest,
1005            "|{0:<7.2} {1:^7.2} {2:^7.2} {3:^7.2} {4:>7.2}|",
1006            self[(0, 0)],
1007            self[(0, 1)],
1008            self[(0, 2)],
1009            self[(0, 3)],
1010            self[(0, 4)]
1011        )?;
1012        writeln!(
1013            dest,
1014            "|{0:<7.2} {1:^7.2} {2:^7.2} {3:^7.2} {4:>7.2}|",
1015            self[(1, 0)],
1016            self[(1, 1)],
1017            self[(1, 2)],
1018            self[(1, 3)],
1019            self[(1, 4)]
1020        )?;
1021        writeln!(
1022            dest,
1023            "|{0:<7.2} {1:^7.2} {2:^7.2} {3:^7.2} {4:>7.2}|",
1024            self[(2, 0)],
1025            self[(2, 1)],
1026            self[(2, 2)],
1027            self[(2, 3)],
1028            self[(2, 4)]
1029        )?;
1030        writeln!(
1031            dest,
1032            "|{0:<7.2} {1:^7.2} {2:^7.2} {3:^7.2} {4:>7.2}|",
1033            self[(3, 0)],
1034            self[(3, 1)],
1035            self[(3, 2)],
1036            self[(3, 3)],
1037            self[(3, 4)]
1038        )?;
1039        writeln!(
1040            dest,
1041            "|{0:<7.2} {1:^7.2} {2:^7.2} {3:^7.2} {4:>7.2}|",
1042            self[(4, 0)],
1043            self[(4, 1)],
1044            self[(4, 2)],
1045            self[(4, 3)],
1046            self[(4, 4)]
1047        )
1048    }
1049}
1050
1051//-------------------------------------------------------------------------
1052//                        macros
1053//-------------------------------------------------------------------------
1054#[macro_export]
1055macro_rules! m55_new {
1056    ($($first_row:expr),*;
1057     $($second_row:expr),*;
1058     $($third_row:expr),*;
1059     $($fourth_row:expr),*;
1060     $($fifth_row:expr),*
1061     ) => {
1062        M55::new([[$($first_row),*],
1063                 [$($second_row),*],
1064                 [$($third_row),*],
1065                 [$($fourth_row),*],
1066                 [$($fifth_row),*]])
1067    }
1068}
1069
1070//-------------------------------------------------------------------------
1071//                        tests
1072//-------------------------------------------------------------------------
1073
1074#[cfg(test)]
1075mod test_matrix5x5 {
1076
1077    use crate::matrix5x5::M55;
1078    use crate::traits::LinearAlgebra;
1079    use crate::utils::nearly_equal;
1080    use crate::utils::compare_vecs;
1081    use crate::vector5::V5;
1082
1083    const EPS: f32 = 1e-6;
1084
1085    #[test]
1086    fn matrix5x5_det_test() {
1087
1088        use super::test_matrix5x5::EPS;
1089
1090        let m = M55::new([
1091            [10.0, 1.0, 7.0, 1.0, 5.0],
1092            [2.0, 4.0, 8.0, 3.0, 2.0],
1093            [5.0, 1.0, 2.0, 9.0, 10.0],
1094            [6.0, 9.0, 9.0, 7.0, 3.0],
1095            [1.0, 8.0, 8.0, 10.0, 5.0],
1096        ]);
1097        let result = m.det();
1098        let expected = 49.99999999999798;
1099        assert!(nearly_equal(result, expected, EPS));
1100    }
1101
1102    #[test]
1103    fn matrix5x5_sum_test() {
1104
1105        use super::test_matrix5x5::EPS;
1106
1107        let m = M55::new([
1108            [10.0, 1.0, 7.0, 1.0, 5.0],
1109            [2.0, 4.0, 8.0, 3.0, 2.0],
1110            [5.0, 1.0, 2.0, 9.0, 10.0],
1111            [6.0, 9.0, 9.0, 7.0, 3.0],
1112            [1.0, 8.0, 8.0, 10.0, 5.0],
1113        ]);
1114
1115        let expected = M55::new([
1116            [20.0, 2.0, 14.0, 2.0, 10.0],
1117            [4.0, 8.0, 16.0, 6.0, 4.0],
1118            [10.0, 2.0, 4.0, 18.0, 20.0],
1119            [12.0, 18.0, 18.0, 14.0, 6.0],
1120            [2.0, 16.0, 16.0, 20.0, 10.0],
1121        ]);
1122        let result = m + m;
1123
1124        assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
1125    }
1126
1127    #[test]
1128    fn sub_test() {
1129        use super::test_matrix5x5::EPS;
1130
1131        let m1 = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1132                           2.0, 4.0, 8.0,  3.0,  2.0;
1133                           5.0, 1.0, 2.0,  9.0, 10.0;
1134                           6.0, 9.0, 9.0,  7.0,  3.0;
1135                           1.0, 8.0, 8.0, 10.0,  5.0);
1136
1137        let m2 = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1138                           2.0, 4.0, 8.0,  3.0,  2.0;
1139                           5.0, 1.0, 2.0,  9.0, 10.0;
1140                           6.0, 9.0, 9.0,  7.0,  3.0;
1141                           1.0, 8.0, 8.0, 10.0,  5.0);
1142
1143        let result = m1 - m2;
1144        let expected = m55_new!( 0.0, 0.0, 0.0,  0.0,  0.0;
1145                                 0.0, 0.0, 0.0,  0.0,  0.0;
1146                                 0.0, 0.0, 0.0,  0.0,  0.0;
1147                                 0.0, 0.0, 0.0,  0.0,  0.0;
1148                                 0.0, 0.0, 0.0,  0.0,  0.0);
1149
1150        assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
1151    }
1152
1153    #[test]
1154    fn matrix5x5_product_test() {
1155
1156        use super::test_matrix5x5::EPS;
1157
1158        let m = M55::new([
1159            [10.0, 1.0, 7.0, 1.0, 5.0],
1160            [2.0, 4.0, 8.0, 3.0, 2.0],
1161            [5.0, 1.0, 2.0, 9.0, 10.0],
1162            [6.0, 9.0, 9.0, 7.0, 3.0],
1163            [1.0, 8.0, 8.0, 10.0, 5.0],
1164        ]);
1165        let result = m * m;
1166        let expected = M55::new([
1167            [148.0, 70.0, 141.0, 133.0, 150.0],
1168            [88.0, 69.0, 105.0, 127.0, 117.0],
1169            [126.0, 172.0, 208.0, 189.0, 124.0],
1170            [168.0, 138.0, 219.0, 193.0, 174.0],
1171            [131.0, 171.0, 217.0, 217.0, 156.0],
1172        ]);
1173
1174        assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
1175    }
1176    #[test]
1177    fn matrix5x5_norm2_test() {
1178
1179        use super::test_matrix5x5::EPS;
1180
1181        let m = M55::new([
1182            [10.0, 1.0, 7.0, 1.0, 5.0],
1183            [2.0, 4.0, 8.0, 3.0, 2.0],
1184            [5.0, 1.0, 2.0, 9.0, 10.0],
1185            [6.0, 9.0, 9.0, 7.0, 3.0],
1186            [1.0, 8.0, 8.0, 10.0, 5.0],
1187        ]);
1188
1189        let result = m.norm2();
1190        let expected = 31.52776554086889;
1191        assert!(nearly_equal(result, expected, EPS));
1192    }
1193
1194    #[test]
1195    fn matrix5x5_const_product_test() {
1196
1197        use super::test_matrix5x5::EPS;
1198
1199        let m = M55::new([
1200            [10.0, 1.0, 7.0, 1.0, 5.0],
1201            [2.0, 4.0, 8.0, 3.0, 2.0],
1202            [5.0, 1.0, 2.0, 9.0, 10.0],
1203            [6.0, 9.0, 9.0, 7.0, 3.0],
1204            [1.0, 8.0, 8.0, 10.0, 5.0],
1205        ]);
1206
1207        let result = m * 0.5;
1208        let expected = M55::new([
1209            [5.0, 0.5, 3.5, 0.5, 2.5],
1210            [1.0, 2.0, 4.0, 1.5, 1.0],
1211            [2.5, 0.5, 1.0, 4.5, 5.0],
1212            [3.0, 4.5, 4.5, 3.5, 1.5],
1213            [0.5, 4.0, 4.0, 5.0, 2.5],
1214        ]);
1215        assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
1216    }
1217    #[test]
1218    fn matrix5x5_inv_test() {
1219
1220        use super::test_matrix5x5::EPS;
1221
1222        let m = M55::new([
1223            [10.0, 1.0, 7.0, 1.0, 5.0],
1224            [2.0, 4.0, 8.0, 3.0, 2.0],
1225            [5.0, 1.0, 2.0, 9.0, 10.0],
1226            [6.0, 9.0, 9.0, 7.0, 3.0],
1227            [1.0, 8.0, 8.0, 10.0, 5.0],
1228        ]);
1229        let expected = M55::new([
1230            [-11.98, 15.64, 9.32, 10.34, -19.12],
1231            [33.62, -44.16, -26.08, -28.46, 53.28],
1232            [-9.36, 12.48, 7.24, 7.88, -14.84],
1233            [-37.2, 48.6, 28.8, 31.6, -58.8],
1234            [37.98, -49.64, -29.32, -32.34, 60.12],
1235        ]);
1236
1237        if let Some(result) = m.inverse() {
1238            assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
1239        }
1240    }
1241
1242    #[test]
1243    fn inverse_fail() {
1244        let m = M55::new([
1245            [10.0, 1.0, 7.0, 1.0, 5.0],
1246            [10.0, 1.0, 7.0, 1.0, 5.0],
1247            [5.0, 1.0, 2.0, 9.0, 10.0],
1248            [6.0, 9.0, 9.0, 7.0, 3.0],
1249            [1.0, 8.0, 8.0, 10.0, 5.0],
1250        ]);
1251        let result = m.inverse();
1252        let expected = None;
1253        assert_eq!(result, expected);
1254    }
1255
1256    #[test]
1257    fn get_cols_test() {
1258        let m1 = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1259                           2.0, 4.0, 8.0,  3.0,  2.0;
1260                           5.0, 1.0, 2.0,  9.0, 10.0;
1261                           6.0, 9.0, 9.0,  7.0,  3.0;
1262                           1.0, 8.0, 8.0, 10.0,  5.0);
1263
1264        let result = m1.get_cols();
1265
1266        let expected0 = V5::new([10.0, 2.0, 5.0, 6.0, 1.0]);
1267        let expected1 = V5::new([1.0, 4.0, 1.0, 9.0, 8.0]);
1268        let expected2 = V5::new([7.0, 8.0, 2.0, 9.0, 8.0]);
1269        let expected3 = V5::new([1.0, 3.0, 9.0, 7.0, 10.0]);
1270        let expected4 = V5::new([5.0, 2.0, 10.0, 3.0, 5.0]);
1271
1272        let expected = V5::new([expected0, expected1, expected2, expected3, expected4]);
1273        assert_eq!(
1274            &result[..],
1275            &expected[..],
1276            "\nExpected\n{:?}\nfound\n{:?}",
1277            &result[..],
1278            &expected[..]
1279        );
1280    }
1281
1282    #[test]
1283    fn mul_vector_rhs() {
1284        let m = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1285                          2.0, 4.0, 8.0,  3.0,  2.0;
1286                          5.0, 1.0, 2.0,  9.0, 10.0;
1287                          6.0, 9.0, 9.0,  7.0,  3.0;
1288                          1.0, 8.0, 8.0, 10.0,  5.0);
1289
1290        let v = V5::new([0.0, 1.0, 2.0, 3.0, 4.0]);
1291        let result = m * v;
1292        let expected = V5::new([38.0, 37.0, 72.0, 60.0, 74.0]);
1293
1294        assert_eq!(
1295            &result[..],
1296            &expected[..],
1297            "\nExpected\n{:?}\nfound\n{:?}",
1298            &result[..],
1299            &expected[..]
1300        );
1301    }
1302
1303    #[test]
1304    fn get_rows_test() {
1305        let m1 = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1306                           2.0, 4.0, 8.0,  3.0,  2.0;
1307                           5.0, 1.0, 2.0,  9.0, 10.0;
1308                           6.0, 9.0, 9.0,  7.0,  3.0;
1309                           1.0, 8.0, 8.0, 10.0,  5.0);
1310
1311        let result = m1.transpose().get_rows();
1312
1313        let expected0 = V5::new([10.0, 2.0, 5.0, 6.0, 1.0]);
1314        let expected1 = V5::new([1.0, 4.0, 1.0, 9.0, 8.0]);
1315        let expected2 = V5::new([7.0, 8.0, 2.0, 9.0, 8.0]);
1316        let expected3 = V5::new([1.0, 3.0, 9.0, 7.0, 10.0]);
1317        let expected4 = V5::new([5.0, 2.0, 10.0, 3.0, 5.0]);
1318
1319        let expected = V5::new([expected0, expected1, expected2, expected3, expected4]);
1320        assert_eq!(
1321            &result[..],
1322            &expected[..],
1323            "\nExpected\n{:?}\nfound\n{:?}",
1324            &result[..],
1325            &expected[..]
1326        );
1327    }
1328
1329    #[test]
1330    fn new_from_vecs_test() {
1331        let expected = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1332                                 2.0, 4.0, 8.0,  3.0,  2.0;
1333                                 5.0, 1.0, 2.0,  9.0, 10.0;
1334                                 6.0, 9.0, 9.0,  7.0,  3.0;
1335                                 1.0, 8.0, 8.0, 10.0,  5.0);
1336
1337        let cols = expected.get_cols();
1338
1339        let result = M55::new_from_vecs(cols);
1340
1341        assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
1342    }
1343
1344    #[test]
1345    fn qr_test() {
1346        let expected = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1347                                 2.0, 1.0, 8.0,  3.0,  2.0;
1348                                 5.0, 1.0, 1.0,  9.0, 10.0;
1349                                 6.0, 9.0, 9.0,  1.0,  3.0;
1350                                 1.0, 8.0, 8.0, 10.0,  5.0);
1351        if let Some((q, r)) = expected.qr() {
1352            let result = q * r;
1353            assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
1354            assert!(nearly_equal(q.det().abs(), 1.0, EPS));
1355        }
1356    }
1357
1358    #[test]
1359    fn get_diagonal() {
1360        let m = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1361                          2.0, 1.0, 8.0,  3.0,  2.0;
1362                          5.0, 1.0, 1.0,  9.0, 10.0;
1363                          6.0, 9.0, 9.0,  1.0,  3.0;
1364                          1.0, 8.0, 8.0, 10.0,  5.0);
1365        let result = m.get_diagonal();
1366        let expected = V5::new([10.0, 1.0, 1.0, 1.0, 5.0]);
1367        assert_eq!(
1368            &result[..],
1369            &expected[..],
1370            "\nExpected\n{:?}\nfound\n{:?}",
1371            &result[..],
1372            &expected[..]
1373        );
1374    }
1375
1376    #[test]
1377    fn get_upper_triangular_test() {
1378        let m = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1379                          2.0, 1.0, 8.0,  3.0,  2.0;
1380                          5.0, 1.0, 1.0,  9.0, 10.0;
1381                          6.0, 9.0, 9.0,  1.0,  3.0;
1382                          1.0, 8.0, 8.0, 10.0,  5.0);
1383        let result = m.get_upper_triagular();
1384        let expected = [1.0, 7.0, 1.0, 5.0, 8.0, 3.0, 2.0, 9.0, 10.0, 3.0];
1385        assert_eq!(
1386            &result[..],
1387            &expected[..],
1388            "\nExpected\n{:?}\nfound\n{:?}",
1389            &result[..],
1390            &expected[..]
1391        );
1392    }
1393
1394    #[test]
1395    fn get_lower_triangular_test() {
1396        let m = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1397                          2.0, 1.0, 8.0,  3.0,  2.0;
1398                          5.0, 1.0, 1.0,  9.0, 10.0;
1399                          6.0, 9.0, 9.0,  1.0,  3.0;
1400                          1.0, 8.0, 8.0, 10.0,  5.0);
1401        let result = m.get_lower_triangular();
1402        let expected = [2.0, 5.0, 1.0, 6.0, 9.0, 9.0, 1.0, 8.0, 8.0, 10.0];
1403        assert_eq!(
1404            &result[..],
1405            &expected[..],
1406            "\nExpected\n{:?}\nfound\n{:?}",
1407            &result[..],
1408            &expected[..]
1409        );
1410    }
1411
1412    #[test]
1413    fn for_each_test() {
1414        let m = m55_new!(10.0, 1.0, 7.0,  1.0,  5.0;
1415                          2.0, 1.0, 8.0,  3.0,  2.0;
1416                          5.0, 1.0, 1.0,  9.0, 10.0;
1417                          6.0, 9.0, 9.0,  1.0,  3.0;
1418                          1.0, 8.0, 8.0, 10.0,  5.0);
1419
1420        let result = m.for_each(|element| element + 1.0);
1421
1422        let expected = m55_new!(11.0, 2.0, 8.0,  2.0,  6.0;
1423                                 3.0, 2.0, 9.0,  4.0,  3.0;
1424                                 6.0, 2.0, 2.0,  10.0, 11.0;
1425                                 7.0, 10.0, 10.0,  2.0,  4.0;
1426                                 2.0, 9.0, 9.0, 11.0,  6.0);
1427
1428        assert!(compare_vecs(&result.as_vec(), &expected.as_vec(), EPS));
1429    }
1430
1431}