gloss_utils/
ndarray_inverse.rs

1#![allow(non_snake_case)]
2#![allow(clippy::too_many_lines)]
3use ndarray::{prelude::*, ScalarOperand, Zip};
4use num_traits::{Float, One, Zero};
5use std::{
6    fmt::Debug,
7    iter::Sum,
8    ops::{AddAssign, Mul, Neg, Sub},
9};
10
11pub trait Inverse<T: Float> {
12    fn det(&self) -> T;
13
14    fn inv(&self) -> Option<Self>
15    where
16        Self: Sized;
17
18    fn inv_diag(&self) -> Option<Self>
19    where
20        Self: Sized;
21
22    fn lu_inv(&self) -> Option<Self>
23    where
24        Self: Sized;
25
26    fn inv_lt(&self) -> Option<Self>
27    where
28        Self: Sized;
29
30    fn inv_ut(&self) -> Option<Self>
31    where
32        Self: Sized;
33
34    #[allow(clippy::return_self_not_must_use)]
35    fn cholesky(&self) -> Self
36    where
37        Self: Sized;
38
39    fn lu(&self) -> Option<(Self, Self, Self)>
40    where
41        Self: Sized;
42}
43
44impl<T> Inverse<T> for Array2<T>
45where
46    T: Float + Debug + ScalarOperand + Sum<T> + AddAssign,
47{
48    fn det(&self) -> T {
49        let s = self.raw_dim();
50        assert!(s[0] == s[1]);
51        // Flatten to Vec!
52        let vm: Vec<T> = self.iter().copied().collect();
53        determinant(&vm, s[0])
54    }
55
56    fn inv(&self) -> Option<Self> {
57        fn submat<T: Float>(res: &mut [T], m: &Array2<T>, sr: usize, sc: usize) {
58            let s = m.raw_dim();
59            let mut i: usize = 0;
60            (0..s[0]).for_each(|r| {
61                (0..s[1]).for_each(|c| {
62                    if r != sr && c != sc {
63                        res[i] = m[(r, c)];
64                        i += 1;
65                    }
66                });
67            });
68        }
69
70        let s = self.raw_dim();
71        assert!(s[0] == s[1]);
72        let l = s[0];
73        // check if determinant for shortcut cases only
74        // Note: Cases must match with following main match
75        let det = match l {
76            2..=4 => {
77                let d = self.det();
78
79                if d.is_zero() {
80                    return None;
81                }
82                d
83            }
84            _ => T::zero(),
85        };
86        match l {
87            1 => Some(array![[self[(0, 0)].recip()]]),
88            2 => Some(array![
89                [self[(1, 1)] / det, -self[(0, 1)] / det],
90                [-self[(1, 0)] / det, self[(0, 0)] / det],
91            ]),
92            3 => {
93                let m00 = self[(0, 0)];
94                let m01 = self[(0, 1)];
95                let m02 = self[(0, 2)];
96                let m10 = self[(1, 0)];
97                let m11 = self[(1, 1)];
98                let m12 = self[(1, 2)];
99                let m20 = self[(2, 0)];
100                let m21 = self[(2, 1)];
101                let m22 = self[(2, 2)];
102
103                let x00 = m11 * m22 - m21 * m12;
104                let x01 = m02 * m21 - m01 * m22;
105                let x02 = m01 * m12 - m02 * m11;
106                let x10 = m12 * m20 - m10 * m22;
107                let x11 = m00 * m22 - m02 * m20;
108                let x12 = m10 * m02 - m00 * m12;
109                let x20 = m10 * m21 - m20 * m11;
110                let x21 = m20 * m01 - m00 * m21;
111                let x22 = m00 * m11 - m10 * m01;
112
113                Some(array![
114                    [x00 / det, x01 / det, x02 / det],
115                    [x10 / det, x11 / det, x12 / det],
116                    [x20 / det, x21 / det, x22 / det]
117                ])
118            }
119            4 => {
120                let m00 = self[(0, 0)];
121                let m01 = self[(0, 1)];
122                let m02 = self[(0, 2)];
123                let m03 = self[(0, 3)];
124                let m10 = self[(1, 0)];
125                let m11 = self[(1, 1)];
126                let m12 = self[(1, 2)];
127                let m13 = self[(1, 3)];
128                let m20 = self[(2, 0)];
129                let m21 = self[(2, 1)];
130                let m22 = self[(2, 2)];
131                let m23 = self[(2, 3)];
132                let m30 = self[(3, 0)];
133                let m31 = self[(3, 1)];
134                let m32 = self[(3, 2)];
135                let m33 = self[(3, 3)];
136
137                let x00 = m11 * m22 * m33 - m11 * m32 * m23 - m12 * m21 * m33 + m12 * m31 * m23 + m13 * m21 * m32 - m13 * m31 * m22;
138
139                let x10 = -m10 * m22 * m33 + m10 * m32 * m23 + m12 * m20 * m33 - m12 * m30 * m23 - m13 * m20 * m32 + m13 * m30 * m22;
140
141                let x20 = m10 * m21 * m33 - m10 * m31 * m23 - m11 * m20 * m33 + m11 * m30 * m23 + m13 * m20 * m31 - m13 * m30 * m21;
142
143                let x30 = -m10 * m21 * m32 + m10 * m31 * m22 + m11 * m20 * m32 - m11 * m30 * m22 - m12 * m20 * m31 + m12 * m30 * m21;
144
145                let x01 = -m01 * m22 * m33 + m01 * m32 * m23 + m02 * m21 * m33 - m02 * m31 * m23 - m03 * m21 * m32 + m03 * m31 * m22;
146
147                let x11 = m00 * m22 * m33 - m00 * m32 * m23 - m02 * m20 * m33 + m02 * m30 * m23 + m03 * m20 * m32 - m03 * m30 * m22;
148
149                let x21 = -m00 * m21 * m33 + m00 * m31 * m23 + m01 * m20 * m33 - m01 * m30 * m23 - m03 * m20 * m31 + m03 * m30 * m21;
150
151                let x31 = m00 * m21 * m32 - m00 * m31 * m22 - m01 * m20 * m32 + m01 * m30 * m22 + m02 * m20 * m31 - m02 * m30 * m21;
152
153                let x02 = m01 * m12 * m33 - m01 * m32 * m13 - m02 * m11 * m33 + m02 * m31 * m13 + m03 * m11 * m32 - m03 * m31 * m12;
154
155                let x12 = -m00 * m12 * m33 + m00 * m32 * m13 + m02 * m10 * m33 - m02 * m30 * m13 - m03 * m10 * m32 + m03 * m30 * m12;
156
157                let x22 = m00 * m11 * m33 - m00 * m31 * m13 - m01 * m10 * m33 + m01 * m30 * m13 + m03 * m10 * m31 - m03 * m30 * m11;
158
159                let x03 = -m01 * m12 * m23 + m01 * m22 * m13 + m02 * m11 * m23 - m02 * m21 * m13 - m03 * m11 * m22 + m03 * m21 * m12;
160
161                let x32 = -m00 * m11 * m32 + m00 * m31 * m12 + m01 * m10 * m32 - m01 * m30 * m12 - m02 * m10 * m31 + m02 * m30 * m11;
162
163                let x13 = m00 * m12 * m23 - m00 * m22 * m13 - m02 * m10 * m23 + m02 * m20 * m13 + m03 * m10 * m22 - m03 * m20 * m12;
164
165                let x23 = -m00 * m11 * m23 + m00 * m21 * m13 + m01 * m10 * m23 - m01 * m20 * m13 - m03 * m10 * m21 + m03 * m20 * m11;
166
167                let x33 = m00 * m11 * m22 - m00 * m21 * m12 - m01 * m10 * m22 + m01 * m20 * m12 + m02 * m10 * m21 - m02 * m20 * m11;
168
169                Some(array![
170                    [x00 / det, x01 / det, x02 / det, x03 / det],
171                    [x10 / det, x11 / det, x12 / det, x13 / det],
172                    [x20 / det, x21 / det, x22 / det, x23 / det],
173                    [x30 / det, x31 / det, x32 / det, x33 / det]
174                ])
175            }
176            _ => {
177                if let Some(res) = self.lu_inv() {
178                    Some(res)
179                } else {
180                    let det = self.det();
181                    // Fully expanding any more is too clunky!
182                    if det.is_zero() {
183                        None
184                    } else {
185                        let mut cofactors: Array2<T> = Array2::zeros((l, l));
186                        let mut res: Vec<T> = vec![T::zero(); (l - 1) * (l - 1)];
187                        for r in 0..l {
188                            for c in 0..l {
189                                // Find submatrix
190                                submat(&mut res, self, r, c);
191                                let d = determinant(&res, l - 1);
192                                cofactors[(c, r)] = if ((r + c) % 2) == 0 { d } else { -d };
193                            }
194                        }
195                        Some(cofactors / det)
196                    }
197                }
198            }
199        }
200    }
201
202    fn inv_diag(&self) -> Option<Self> {
203        let s = self.raw_dim();
204        assert!(s[0] == s[1]);
205
206        let mut res: Array2<T> = Array2::zeros(s);
207
208        for i in 0..s[0] {
209            res[(i, i)] = self[(i, i)].recip();
210        }
211
212        Some(res)
213    }
214
215    fn cholesky(&self) -> Self {
216        let s = self.raw_dim();
217        assert!(s[0] == s[1]);
218        let l = s[0];
219        let mut res: Array2<T> = Array2::zeros(s);
220        for i in 0..l {
221            for j in 0..=i {
222                let mut s = T::zero();
223                for k in 0..j {
224                    if !res[(i, k)].is_zero() && !res[(j, k)].is_zero() {
225                        s += res[(i, k)] * res[(j, k)];
226                    }
227                }
228
229                res[(i, j)] = if i == j {
230                    (self[(i, i)] - s).sqrt()
231                } else {
232                    res[(j, j)].recip() * (self[(i, j)] - s)
233                };
234            }
235        }
236
237        res
238    }
239
240    fn lu(&self) -> Option<(Self, Self, Self)> {
241        fn pivot<T: Float>(A: &Array2<T>) -> Array2<T> {
242            let n = A.raw_dim()[0];
243            let mut P: Array2<T> = Array::eye(n);
244
245            for (idx, col) in A.axis_iter(Axis(1)).enumerate() {
246                // find index of maximum value in column i
247                let mut mp = idx;
248                for i in idx..n {
249                    if col[mp].abs() < col[i].abs() {
250                        mp = i;
251                    }
252                }
253                // swap rows when different
254                if mp != idx {
255                    let (l, r) = P.multi_slice_mut((s![idx, ..], s![mp, ..]));
256
257                    Zip::from(l).and(r).for_each(std::mem::swap);
258                }
259            }
260
261            P
262        }
263
264        let d = self.raw_dim();
265        let n = d[0];
266        assert_eq!(n, d[1], "LU decomposition must take a square matrix.");
267
268        let P = pivot(self);
269        let pA = P.dot(self);
270
271        let mut L: Array2<T> = Array::eye(n);
272        let mut U: Array2<T> = Array::zeros((n, n));
273
274        for c in 0..n {
275            for r in 0..n {
276                let s = U.slice(s![0..r, c]).dot(&L.slice(s![r, 0..r]));
277
278                if s.is_nan() || s.is_infinite() {
279                    return None;
280                }
281
282                let pAs = pA[[r, c]] - s;
283
284                if r < c + 1 {
285                    // U
286                    U[[r, c]] = pAs;
287                } else {
288                    // L
289                    L[[r, c]] = (pAs) / U[[c, c]];
290                }
291            }
292        }
293
294        Some((L, U, P))
295    }
296
297    fn lu_inv(&self) -> Option<Self> {
298        let d = self.raw_dim();
299        let n = d[0];
300
301        assert!(d[0] == d[1]);
302
303        if let Some((l, u, p)) = self.lu() {
304            let lt = linv(&l, n);
305            let ut = uinv(&u, n);
306
307            Some(ut.dot(&lt).dot(&p))
308        } else {
309            None
310        }
311    }
312
313    fn inv_lt(&self) -> Option<Self> {
314        let n = check_diag(self);
315
316        if n == 0 {
317            None
318        } else {
319            Some(linv(self, n))
320        }
321    }
322
323    fn inv_ut(&self) -> Option<Self> {
324        let n = check_diag(self);
325
326        if n == 0 {
327            None
328        } else {
329            Some(uinv(self, n))
330        }
331    }
332}
333
334fn determinant<T>(vm: &[T], l: usize) -> T
335where
336    T: Copy + Debug + Zero + One + Mul + PartialEq + Sub<Output = T> + Neg<Output = T> + Sum<T>,
337{
338    // Must be square matrix l x l!
339    // Fully expanding the first few determinants makes a big
340    // difference, especially as the generic algorithm is recursive
341    match l {
342        1 => vm[0],
343        2 => vm[0] * vm[3] - vm[2] * vm[1],
344        3 => {
345            let m00 = vm[0];
346            let m01 = vm[1];
347            let m02 = vm[2];
348            let m10 = vm[3];
349            let m11 = vm[4];
350            let m12 = vm[5];
351            let m20 = vm[6];
352            let m21 = vm[7];
353            let m22 = vm[8];
354
355            m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + m02 * (m10 * m21 - m11 * m20)
356        }
357        4 => {
358            let m00 = vm[0];
359            let m01 = vm[1];
360            let m02 = vm[2];
361            let m03 = vm[3];
362            let m10 = vm[4];
363            let m11 = vm[5];
364            let m12 = vm[6];
365            let m13 = vm[7];
366            let m20 = vm[8];
367            let m21 = vm[9];
368            let m22 = vm[10];
369            let m23 = vm[11];
370            let m30 = vm[12];
371            let m31 = vm[13];
372            let m32 = vm[14];
373            let m33 = vm[15];
374
375            // Note: Compiler optimisation will remove redundant multiplies
376            m00 * m21 * m32 * m13 - m00 * m21 * m33 * m12 - m00 * m22 * m31 * m13 + m00 * m22 * m33 * m11 + m00 * m23 * m31 * m12
377                - m00 * m23 * m32 * m11
378                - m21 * m30 * m02 * m13
379                + m21 * m30 * m03 * m12
380                - m21 * m32 * m03 * m10
381                + m21 * m33 * m02 * m10
382                + m22 * m30 * m01 * m13
383                - m22 * m30 * m03 * m11
384                + m22 * m31 * m03 * m10
385                - m22 * m33 * m01 * m10
386                - m23 * m30 * m01 * m12
387                + m23 * m30 * m02 * m11
388                - m23 * m31 * m02 * m10
389                + m23 * m32 * m01 * m10
390                + m31 * m02 * m13 * m20
391                - m31 * m03 * m12 * m20
392                - m32 * m01 * m13 * m20
393                + m32 * m03 * m11 * m20
394                + m33 * m01 * m12 * m20
395                - m33 * m02 * m11 * m20
396        }
397        5 => {
398            let m00 = vm[0];
399            let m01 = vm[1];
400            let m02 = vm[2];
401            let m03 = vm[3];
402            let m04 = vm[4];
403            let m10 = vm[5];
404            let m11 = vm[6];
405            let m12 = vm[7];
406            let m13 = vm[8];
407            let m14 = vm[9];
408            let m20 = vm[10];
409            let m21 = vm[11];
410            let m22 = vm[12];
411            let m23 = vm[13];
412            let m24 = vm[14];
413            let m30 = vm[15];
414            let m31 = vm[16];
415            let m32 = vm[17];
416            let m33 = vm[18];
417            let m34 = vm[19];
418            let m40 = vm[20];
419            let m41 = vm[21];
420            let m42 = vm[22];
421            let m43 = vm[23];
422            let m44 = vm[24];
423
424            // Note: Compiler optimisation will remove redundant multiplies
425            m00 * m11 * m22 * m33 * m44 - m00 * m11 * m22 * m34 * m43 - m00 * m11 * m23 * m32 * m44
426                + m00 * m11 * m23 * m34 * m42
427                + m00 * m11 * m24 * m32 * m43
428                - m00 * m11 * m24 * m33 * m42
429                - m00 * m12 * m21 * m33 * m44
430                + m00 * m12 * m21 * m34 * m43
431                + m00 * m12 * m23 * m31 * m44
432                - m00 * m12 * m23 * m34 * m41
433                - m00 * m12 * m24 * m31 * m43
434                + m00 * m12 * m24 * m33 * m41
435                + m00 * m13 * m21 * m32 * m44
436                - m00 * m13 * m21 * m34 * m42
437                - m00 * m13 * m22 * m31 * m44
438                + m00 * m13 * m22 * m34 * m41
439                + m00 * m13 * m24 * m31 * m42
440                - m00 * m13 * m24 * m32 * m41
441                - m00 * m14 * m21 * m32 * m43
442                + m00 * m14 * m21 * m33 * m42
443                + m00 * m14 * m22 * m31 * m43
444                - m00 * m14 * m22 * m33 * m41
445                - m00 * m14 * m23 * m31 * m42
446                + m00 * m14 * m23 * m32 * m41
447                - m01 * m10 * m22 * m33 * m44
448                + m01 * m10 * m22 * m34 * m43
449                + m01 * m10 * m23 * m32 * m44
450                - m01 * m10 * m23 * m34 * m42
451                - m01 * m10 * m24 * m32 * m43
452                + m01 * m10 * m24 * m33 * m42
453                + m01 * m12 * m20 * m33 * m44
454                - m01 * m12 * m20 * m34 * m43
455                - m01 * m12 * m23 * m30 * m44
456                + m01 * m12 * m23 * m34 * m40
457                + m01 * m12 * m24 * m30 * m43
458                - m01 * m12 * m24 * m33 * m40
459                - m01 * m13 * m20 * m32 * m44
460                + m01 * m13 * m20 * m34 * m42
461                + m01 * m13 * m22 * m30 * m44
462                - m01 * m13 * m22 * m34 * m40
463                - m01 * m13 * m24 * m30 * m42
464                + m01 * m13 * m24 * m32 * m40
465                + m01 * m14 * m20 * m32 * m43
466                - m01 * m14 * m20 * m33 * m42
467                - m01 * m14 * m22 * m30 * m43
468                + m01 * m14 * m22 * m33 * m40
469                + m01 * m14 * m23 * m30 * m42
470                - m01 * m14 * m23 * m32 * m40
471                + m02 * m10 * m21 * m33 * m44
472                - m02 * m10 * m21 * m34 * m43
473                - m02 * m10 * m23 * m31 * m44
474                + m02 * m10 * m23 * m34 * m41
475                + m02 * m10 * m24 * m31 * m43
476                - m02 * m10 * m24 * m33 * m41
477                - m02 * m11 * m20 * m33 * m44
478                + m02 * m11 * m20 * m34 * m43
479                + m02 * m11 * m23 * m30 * m44
480                - m02 * m11 * m23 * m34 * m40
481                - m02 * m11 * m24 * m30 * m43
482                + m02 * m11 * m24 * m33 * m40
483                + m02 * m13 * m20 * m31 * m44
484                - m02 * m13 * m20 * m34 * m41
485                - m02 * m13 * m21 * m30 * m44
486                + m02 * m13 * m21 * m34 * m40
487                + m02 * m13 * m24 * m30 * m41
488                - m02 * m13 * m24 * m31 * m40
489                - m02 * m14 * m20 * m31 * m43
490                + m02 * m14 * m20 * m33 * m41
491                + m02 * m14 * m21 * m30 * m43
492                - m02 * m14 * m21 * m33 * m40
493                - m02 * m14 * m23 * m30 * m41
494                + m02 * m14 * m23 * m31 * m40
495                - m03 * m10 * m21 * m32 * m44
496                + m03 * m10 * m21 * m34 * m42
497                + m03 * m10 * m22 * m31 * m44
498                - m03 * m10 * m22 * m34 * m41
499                - m03 * m10 * m24 * m31 * m42
500                + m03 * m10 * m24 * m32 * m41
501                + m03 * m11 * m20 * m32 * m44
502                - m03 * m11 * m20 * m34 * m42
503                - m03 * m11 * m22 * m30 * m44
504                + m03 * m11 * m22 * m34 * m40
505                + m03 * m11 * m24 * m30 * m42
506                - m03 * m11 * m24 * m32 * m40
507                - m03 * m12 * m20 * m31 * m44
508                + m03 * m12 * m20 * m34 * m41
509                + m03 * m12 * m21 * m30 * m44
510                - m03 * m12 * m21 * m34 * m40
511                - m03 * m12 * m24 * m30 * m41
512                + m03 * m12 * m24 * m31 * m40
513                + m03 * m14 * m20 * m31 * m42
514                - m03 * m14 * m20 * m32 * m41
515                - m03 * m14 * m21 * m30 * m42
516                + m03 * m14 * m21 * m32 * m40
517                + m03 * m14 * m22 * m30 * m41
518                - m03 * m14 * m22 * m31 * m40
519                + m04 * m10 * m21 * m32 * m43
520                - m04 * m10 * m21 * m33 * m42
521                - m04 * m10 * m22 * m31 * m43
522                + m04 * m10 * m22 * m33 * m41
523                + m04 * m10 * m23 * m31 * m42
524                - m04 * m10 * m23 * m32 * m41
525                - m04 * m11 * m20 * m32 * m43
526                + m04 * m11 * m20 * m33 * m42
527                + m04 * m11 * m22 * m30 * m43
528                - m04 * m11 * m22 * m33 * m40
529                - m04 * m11 * m23 * m30 * m42
530                + m04 * m11 * m23 * m32 * m40
531                + m04 * m12 * m20 * m31 * m43
532                - m04 * m12 * m20 * m33 * m41
533                - m04 * m12 * m21 * m30 * m43
534                + m04 * m12 * m21 * m33 * m40
535                + m04 * m12 * m23 * m30 * m41
536                - m04 * m12 * m23 * m31 * m40
537                - m04 * m13 * m20 * m31 * m42
538                + m04 * m13 * m20 * m32 * m41
539                + m04 * m13 * m21 * m30 * m42
540                - m04 * m13 * m21 * m32 * m40
541                - m04 * m13 * m22 * m30 * m41
542                + m04 * m13 * m22 * m31 * m40
543        }
544        6 => {
545            // Okay, getting very unweldy but worth it
546            let m00 = vm[0];
547            let m01 = vm[1];
548            let m02 = vm[2];
549            let m03 = vm[3];
550            let m04 = vm[4];
551            let m05 = vm[5];
552            let m10 = vm[6];
553            let m11 = vm[7];
554            let m12 = vm[8];
555            let m13 = vm[9];
556            let m14 = vm[10];
557            let m15 = vm[11];
558            let m20 = vm[12];
559            let m21 = vm[13];
560            let m22 = vm[14];
561            let m23 = vm[15];
562            let m24 = vm[16];
563            let m25 = vm[17];
564            let m30 = vm[18];
565            let m31 = vm[19];
566            let m32 = vm[20];
567            let m33 = vm[21];
568            let m34 = vm[22];
569            let m35 = vm[23];
570            let m40 = vm[24];
571            let m41 = vm[25];
572            let m42 = vm[26];
573            let m43 = vm[27];
574            let m44 = vm[28];
575            let m45 = vm[29];
576            let m50 = vm[30];
577            let m51 = vm[31];
578            let m52 = vm[32];
579            let m53 = vm[33];
580            let m54 = vm[34];
581            let m55 = vm[35];
582
583            // Note: Compiler optimisation will remove redundant multiplies
584            m00 * m11 * m22 * m33 * m44 * m55 - m00 * m11 * m22 * m33 * m45 * m54 - m00 * m11 * m22 * m34 * m43 * m55
585                + m00 * m11 * m22 * m34 * m45 * m53
586                + m00 * m11 * m22 * m35 * m43 * m54
587                - m00 * m11 * m22 * m35 * m44 * m53
588                - m00 * m11 * m23 * m32 * m44 * m55
589                + m00 * m11 * m23 * m32 * m45 * m54
590                + m00 * m11 * m23 * m34 * m42 * m55
591                - m00 * m11 * m23 * m34 * m45 * m52
592                - m00 * m11 * m23 * m35 * m42 * m54
593                + m00 * m11 * m23 * m35 * m44 * m52
594                + m00 * m11 * m24 * m32 * m43 * m55
595                - m00 * m11 * m24 * m32 * m45 * m53
596                - m00 * m11 * m24 * m33 * m42 * m55
597                + m00 * m11 * m24 * m33 * m45 * m52
598                + m00 * m11 * m24 * m35 * m42 * m53
599                - m00 * m11 * m24 * m35 * m43 * m52
600                - m00 * m11 * m25 * m32 * m43 * m54
601                + m00 * m11 * m25 * m32 * m44 * m53
602                + m00 * m11 * m25 * m33 * m42 * m54
603                - m00 * m11 * m25 * m33 * m44 * m52
604                - m00 * m11 * m25 * m34 * m42 * m53
605                + m00 * m11 * m25 * m34 * m43 * m52
606                - m00 * m12 * m21 * m33 * m44 * m55
607                + m00 * m12 * m21 * m33 * m45 * m54
608                + m00 * m12 * m21 * m34 * m43 * m55
609                - m00 * m12 * m21 * m34 * m45 * m53
610                - m00 * m12 * m21 * m35 * m43 * m54
611                + m00 * m12 * m21 * m35 * m44 * m53
612                + m00 * m12 * m23 * m31 * m44 * m55
613                - m00 * m12 * m23 * m31 * m45 * m54
614                - m00 * m12 * m23 * m34 * m41 * m55
615                + m00 * m12 * m23 * m34 * m45 * m51
616                + m00 * m12 * m23 * m35 * m41 * m54
617                - m00 * m12 * m23 * m35 * m44 * m51
618                - m00 * m12 * m24 * m31 * m43 * m55
619                + m00 * m12 * m24 * m31 * m45 * m53
620                + m00 * m12 * m24 * m33 * m41 * m55
621                - m00 * m12 * m24 * m33 * m45 * m51
622                - m00 * m12 * m24 * m35 * m41 * m53
623                + m00 * m12 * m24 * m35 * m43 * m51
624                + m00 * m12 * m25 * m31 * m43 * m54
625                - m00 * m12 * m25 * m31 * m44 * m53
626                - m00 * m12 * m25 * m33 * m41 * m54
627                + m00 * m12 * m25 * m33 * m44 * m51
628                + m00 * m12 * m25 * m34 * m41 * m53
629                - m00 * m12 * m25 * m34 * m43 * m51
630                + m00 * m13 * m21 * m32 * m44 * m55
631                - m00 * m13 * m21 * m32 * m45 * m54
632                - m00 * m13 * m21 * m34 * m42 * m55
633                + m00 * m13 * m21 * m34 * m45 * m52
634                + m00 * m13 * m21 * m35 * m42 * m54
635                - m00 * m13 * m21 * m35 * m44 * m52
636                - m00 * m13 * m22 * m31 * m44 * m55
637                + m00 * m13 * m22 * m31 * m45 * m54
638                + m00 * m13 * m22 * m34 * m41 * m55
639                - m00 * m13 * m22 * m34 * m45 * m51
640                - m00 * m13 * m22 * m35 * m41 * m54
641                + m00 * m13 * m22 * m35 * m44 * m51
642                + m00 * m13 * m24 * m31 * m42 * m55
643                - m00 * m13 * m24 * m31 * m45 * m52
644                - m00 * m13 * m24 * m32 * m41 * m55
645                + m00 * m13 * m24 * m32 * m45 * m51
646                + m00 * m13 * m24 * m35 * m41 * m52
647                - m00 * m13 * m24 * m35 * m42 * m51
648                - m00 * m13 * m25 * m31 * m42 * m54
649                + m00 * m13 * m25 * m31 * m44 * m52
650                + m00 * m13 * m25 * m32 * m41 * m54
651                - m00 * m13 * m25 * m32 * m44 * m51
652                - m00 * m13 * m25 * m34 * m41 * m52
653                + m00 * m13 * m25 * m34 * m42 * m51
654                - m00 * m14 * m21 * m32 * m43 * m55
655                + m00 * m14 * m21 * m32 * m45 * m53
656                + m00 * m14 * m21 * m33 * m42 * m55
657                - m00 * m14 * m21 * m33 * m45 * m52
658                - m00 * m14 * m21 * m35 * m42 * m53
659                + m00 * m14 * m21 * m35 * m43 * m52
660                + m00 * m14 * m22 * m31 * m43 * m55
661                - m00 * m14 * m22 * m31 * m45 * m53
662                - m00 * m14 * m22 * m33 * m41 * m55
663                + m00 * m14 * m22 * m33 * m45 * m51
664                + m00 * m14 * m22 * m35 * m41 * m53
665                - m00 * m14 * m22 * m35 * m43 * m51
666                - m00 * m14 * m23 * m31 * m42 * m55
667                + m00 * m14 * m23 * m31 * m45 * m52
668                + m00 * m14 * m23 * m32 * m41 * m55
669                - m00 * m14 * m23 * m32 * m45 * m51
670                - m00 * m14 * m23 * m35 * m41 * m52
671                + m00 * m14 * m23 * m35 * m42 * m51
672                + m00 * m14 * m25 * m31 * m42 * m53
673                - m00 * m14 * m25 * m31 * m43 * m52
674                - m00 * m14 * m25 * m32 * m41 * m53
675                + m00 * m14 * m25 * m32 * m43 * m51
676                + m00 * m14 * m25 * m33 * m41 * m52
677                - m00 * m14 * m25 * m33 * m42 * m51
678                + m00 * m15 * m21 * m32 * m43 * m54
679                - m00 * m15 * m21 * m32 * m44 * m53
680                - m00 * m15 * m21 * m33 * m42 * m54
681                + m00 * m15 * m21 * m33 * m44 * m52
682                + m00 * m15 * m21 * m34 * m42 * m53
683                - m00 * m15 * m21 * m34 * m43 * m52
684                - m00 * m15 * m22 * m31 * m43 * m54
685                + m00 * m15 * m22 * m31 * m44 * m53
686                + m00 * m15 * m22 * m33 * m41 * m54
687                - m00 * m15 * m22 * m33 * m44 * m51
688                - m00 * m15 * m22 * m34 * m41 * m53
689                + m00 * m15 * m22 * m34 * m43 * m51
690                + m00 * m15 * m23 * m31 * m42 * m54
691                - m00 * m15 * m23 * m31 * m44 * m52
692                - m00 * m15 * m23 * m32 * m41 * m54
693                + m00 * m15 * m23 * m32 * m44 * m51
694                + m00 * m15 * m23 * m34 * m41 * m52
695                - m00 * m15 * m23 * m34 * m42 * m51
696                - m00 * m15 * m24 * m31 * m42 * m53
697                + m00 * m15 * m24 * m31 * m43 * m52
698                + m00 * m15 * m24 * m32 * m41 * m53
699                - m00 * m15 * m24 * m32 * m43 * m51
700                - m00 * m15 * m24 * m33 * m41 * m52
701                + m00 * m15 * m24 * m33 * m42 * m51
702                - m01 * m10 * m22 * m33 * m44 * m55
703                + m01 * m10 * m22 * m33 * m45 * m54
704                + m01 * m10 * m22 * m34 * m43 * m55
705                - m01 * m10 * m22 * m34 * m45 * m53
706                - m01 * m10 * m22 * m35 * m43 * m54
707                + m01 * m10 * m22 * m35 * m44 * m53
708                + m01 * m10 * m23 * m32 * m44 * m55
709                - m01 * m10 * m23 * m32 * m45 * m54
710                - m01 * m10 * m23 * m34 * m42 * m55
711                + m01 * m10 * m23 * m34 * m45 * m52
712                + m01 * m10 * m23 * m35 * m42 * m54
713                - m01 * m10 * m23 * m35 * m44 * m52
714                - m01 * m10 * m24 * m32 * m43 * m55
715                + m01 * m10 * m24 * m32 * m45 * m53
716                + m01 * m10 * m24 * m33 * m42 * m55
717                - m01 * m10 * m24 * m33 * m45 * m52
718                - m01 * m10 * m24 * m35 * m42 * m53
719                + m01 * m10 * m24 * m35 * m43 * m52
720                + m01 * m10 * m25 * m32 * m43 * m54
721                - m01 * m10 * m25 * m32 * m44 * m53
722                - m01 * m10 * m25 * m33 * m42 * m54
723                + m01 * m10 * m25 * m33 * m44 * m52
724                + m01 * m10 * m25 * m34 * m42 * m53
725                - m01 * m10 * m25 * m34 * m43 * m52
726                + m01 * m12 * m20 * m33 * m44 * m55
727                - m01 * m12 * m20 * m33 * m45 * m54
728                - m01 * m12 * m20 * m34 * m43 * m55
729                + m01 * m12 * m20 * m34 * m45 * m53
730                + m01 * m12 * m20 * m35 * m43 * m54
731                - m01 * m12 * m20 * m35 * m44 * m53
732                - m01 * m12 * m23 * m30 * m44 * m55
733                + m01 * m12 * m23 * m30 * m45 * m54
734                + m01 * m12 * m23 * m34 * m40 * m55
735                - m01 * m12 * m23 * m34 * m45 * m50
736                - m01 * m12 * m23 * m35 * m40 * m54
737                + m01 * m12 * m23 * m35 * m44 * m50
738                + m01 * m12 * m24 * m30 * m43 * m55
739                - m01 * m12 * m24 * m30 * m45 * m53
740                - m01 * m12 * m24 * m33 * m40 * m55
741                + m01 * m12 * m24 * m33 * m45 * m50
742                + m01 * m12 * m24 * m35 * m40 * m53
743                - m01 * m12 * m24 * m35 * m43 * m50
744                - m01 * m12 * m25 * m30 * m43 * m54
745                + m01 * m12 * m25 * m30 * m44 * m53
746                + m01 * m12 * m25 * m33 * m40 * m54
747                - m01 * m12 * m25 * m33 * m44 * m50
748                - m01 * m12 * m25 * m34 * m40 * m53
749                + m01 * m12 * m25 * m34 * m43 * m50
750                - m01 * m13 * m20 * m32 * m44 * m55
751                + m01 * m13 * m20 * m32 * m45 * m54
752                + m01 * m13 * m20 * m34 * m42 * m55
753                - m01 * m13 * m20 * m34 * m45 * m52
754                - m01 * m13 * m20 * m35 * m42 * m54
755                + m01 * m13 * m20 * m35 * m44 * m52
756                + m01 * m13 * m22 * m30 * m44 * m55
757                - m01 * m13 * m22 * m30 * m45 * m54
758                - m01 * m13 * m22 * m34 * m40 * m55
759                + m01 * m13 * m22 * m34 * m45 * m50
760                + m01 * m13 * m22 * m35 * m40 * m54
761                - m01 * m13 * m22 * m35 * m44 * m50
762                - m01 * m13 * m24 * m30 * m42 * m55
763                + m01 * m13 * m24 * m30 * m45 * m52
764                + m01 * m13 * m24 * m32 * m40 * m55
765                - m01 * m13 * m24 * m32 * m45 * m50
766                - m01 * m13 * m24 * m35 * m40 * m52
767                + m01 * m13 * m24 * m35 * m42 * m50
768                + m01 * m13 * m25 * m30 * m42 * m54
769                - m01 * m13 * m25 * m30 * m44 * m52
770                - m01 * m13 * m25 * m32 * m40 * m54
771                + m01 * m13 * m25 * m32 * m44 * m50
772                + m01 * m13 * m25 * m34 * m40 * m52
773                - m01 * m13 * m25 * m34 * m42 * m50
774                + m01 * m14 * m20 * m32 * m43 * m55
775                - m01 * m14 * m20 * m32 * m45 * m53
776                - m01 * m14 * m20 * m33 * m42 * m55
777                + m01 * m14 * m20 * m33 * m45 * m52
778                + m01 * m14 * m20 * m35 * m42 * m53
779                - m01 * m14 * m20 * m35 * m43 * m52
780                - m01 * m14 * m22 * m30 * m43 * m55
781                + m01 * m14 * m22 * m30 * m45 * m53
782                + m01 * m14 * m22 * m33 * m40 * m55
783                - m01 * m14 * m22 * m33 * m45 * m50
784                - m01 * m14 * m22 * m35 * m40 * m53
785                + m01 * m14 * m22 * m35 * m43 * m50
786                + m01 * m14 * m23 * m30 * m42 * m55
787                - m01 * m14 * m23 * m30 * m45 * m52
788                - m01 * m14 * m23 * m32 * m40 * m55
789                + m01 * m14 * m23 * m32 * m45 * m50
790                + m01 * m14 * m23 * m35 * m40 * m52
791                - m01 * m14 * m23 * m35 * m42 * m50
792                - m01 * m14 * m25 * m30 * m42 * m53
793                + m01 * m14 * m25 * m30 * m43 * m52
794                + m01 * m14 * m25 * m32 * m40 * m53
795                - m01 * m14 * m25 * m32 * m43 * m50
796                - m01 * m14 * m25 * m33 * m40 * m52
797                + m01 * m14 * m25 * m33 * m42 * m50
798                - m01 * m15 * m20 * m32 * m43 * m54
799                + m01 * m15 * m20 * m32 * m44 * m53
800                + m01 * m15 * m20 * m33 * m42 * m54
801                - m01 * m15 * m20 * m33 * m44 * m52
802                - m01 * m15 * m20 * m34 * m42 * m53
803                + m01 * m15 * m20 * m34 * m43 * m52
804                + m01 * m15 * m22 * m30 * m43 * m54
805                - m01 * m15 * m22 * m30 * m44 * m53
806                - m01 * m15 * m22 * m33 * m40 * m54
807                + m01 * m15 * m22 * m33 * m44 * m50
808                + m01 * m15 * m22 * m34 * m40 * m53
809                - m01 * m15 * m22 * m34 * m43 * m50
810                - m01 * m15 * m23 * m30 * m42 * m54
811                + m01 * m15 * m23 * m30 * m44 * m52
812                + m01 * m15 * m23 * m32 * m40 * m54
813                - m01 * m15 * m23 * m32 * m44 * m50
814                - m01 * m15 * m23 * m34 * m40 * m52
815                + m01 * m15 * m23 * m34 * m42 * m50
816                + m01 * m15 * m24 * m30 * m42 * m53
817                - m01 * m15 * m24 * m30 * m43 * m52
818                - m01 * m15 * m24 * m32 * m40 * m53
819                + m01 * m15 * m24 * m32 * m43 * m50
820                + m01 * m15 * m24 * m33 * m40 * m52
821                - m01 * m15 * m24 * m33 * m42 * m50
822                + m02 * m10 * m21 * m33 * m44 * m55
823                - m02 * m10 * m21 * m33 * m45 * m54
824                - m02 * m10 * m21 * m34 * m43 * m55
825                + m02 * m10 * m21 * m34 * m45 * m53
826                + m02 * m10 * m21 * m35 * m43 * m54
827                - m02 * m10 * m21 * m35 * m44 * m53
828                - m02 * m10 * m23 * m31 * m44 * m55
829                + m02 * m10 * m23 * m31 * m45 * m54
830                + m02 * m10 * m23 * m34 * m41 * m55
831                - m02 * m10 * m23 * m34 * m45 * m51
832                - m02 * m10 * m23 * m35 * m41 * m54
833                + m02 * m10 * m23 * m35 * m44 * m51
834                + m02 * m10 * m24 * m31 * m43 * m55
835                - m02 * m10 * m24 * m31 * m45 * m53
836                - m02 * m10 * m24 * m33 * m41 * m55
837                + m02 * m10 * m24 * m33 * m45 * m51
838                + m02 * m10 * m24 * m35 * m41 * m53
839                - m02 * m10 * m24 * m35 * m43 * m51
840                - m02 * m10 * m25 * m31 * m43 * m54
841                + m02 * m10 * m25 * m31 * m44 * m53
842                + m02 * m10 * m25 * m33 * m41 * m54
843                - m02 * m10 * m25 * m33 * m44 * m51
844                - m02 * m10 * m25 * m34 * m41 * m53
845                + m02 * m10 * m25 * m34 * m43 * m51
846                - m02 * m11 * m20 * m33 * m44 * m55
847                + m02 * m11 * m20 * m33 * m45 * m54
848                + m02 * m11 * m20 * m34 * m43 * m55
849                - m02 * m11 * m20 * m34 * m45 * m53
850                - m02 * m11 * m20 * m35 * m43 * m54
851                + m02 * m11 * m20 * m35 * m44 * m53
852                + m02 * m11 * m23 * m30 * m44 * m55
853                - m02 * m11 * m23 * m30 * m45 * m54
854                - m02 * m11 * m23 * m34 * m40 * m55
855                + m02 * m11 * m23 * m34 * m45 * m50
856                + m02 * m11 * m23 * m35 * m40 * m54
857                - m02 * m11 * m23 * m35 * m44 * m50
858                - m02 * m11 * m24 * m30 * m43 * m55
859                + m02 * m11 * m24 * m30 * m45 * m53
860                + m02 * m11 * m24 * m33 * m40 * m55
861                - m02 * m11 * m24 * m33 * m45 * m50
862                - m02 * m11 * m24 * m35 * m40 * m53
863                + m02 * m11 * m24 * m35 * m43 * m50
864                + m02 * m11 * m25 * m30 * m43 * m54
865                - m02 * m11 * m25 * m30 * m44 * m53
866                - m02 * m11 * m25 * m33 * m40 * m54
867                + m02 * m11 * m25 * m33 * m44 * m50
868                + m02 * m11 * m25 * m34 * m40 * m53
869                - m02 * m11 * m25 * m34 * m43 * m50
870                + m02 * m13 * m20 * m31 * m44 * m55
871                - m02 * m13 * m20 * m31 * m45 * m54
872                - m02 * m13 * m20 * m34 * m41 * m55
873                + m02 * m13 * m20 * m34 * m45 * m51
874                + m02 * m13 * m20 * m35 * m41 * m54
875                - m02 * m13 * m20 * m35 * m44 * m51
876                - m02 * m13 * m21 * m30 * m44 * m55
877                + m02 * m13 * m21 * m30 * m45 * m54
878                + m02 * m13 * m21 * m34 * m40 * m55
879                - m02 * m13 * m21 * m34 * m45 * m50
880                - m02 * m13 * m21 * m35 * m40 * m54
881                + m02 * m13 * m21 * m35 * m44 * m50
882                + m02 * m13 * m24 * m30 * m41 * m55
883                - m02 * m13 * m24 * m30 * m45 * m51
884                - m02 * m13 * m24 * m31 * m40 * m55
885                + m02 * m13 * m24 * m31 * m45 * m50
886                + m02 * m13 * m24 * m35 * m40 * m51
887                - m02 * m13 * m24 * m35 * m41 * m50
888                - m02 * m13 * m25 * m30 * m41 * m54
889                + m02 * m13 * m25 * m30 * m44 * m51
890                + m02 * m13 * m25 * m31 * m40 * m54
891                - m02 * m13 * m25 * m31 * m44 * m50
892                - m02 * m13 * m25 * m34 * m40 * m51
893                + m02 * m13 * m25 * m34 * m41 * m50
894                - m02 * m14 * m20 * m31 * m43 * m55
895                + m02 * m14 * m20 * m31 * m45 * m53
896                + m02 * m14 * m20 * m33 * m41 * m55
897                - m02 * m14 * m20 * m33 * m45 * m51
898                - m02 * m14 * m20 * m35 * m41 * m53
899                + m02 * m14 * m20 * m35 * m43 * m51
900                + m02 * m14 * m21 * m30 * m43 * m55
901                - m02 * m14 * m21 * m30 * m45 * m53
902                - m02 * m14 * m21 * m33 * m40 * m55
903                + m02 * m14 * m21 * m33 * m45 * m50
904                + m02 * m14 * m21 * m35 * m40 * m53
905                - m02 * m14 * m21 * m35 * m43 * m50
906                - m02 * m14 * m23 * m30 * m41 * m55
907                + m02 * m14 * m23 * m30 * m45 * m51
908                + m02 * m14 * m23 * m31 * m40 * m55
909                - m02 * m14 * m23 * m31 * m45 * m50
910                - m02 * m14 * m23 * m35 * m40 * m51
911                + m02 * m14 * m23 * m35 * m41 * m50
912                + m02 * m14 * m25 * m30 * m41 * m53
913                - m02 * m14 * m25 * m30 * m43 * m51
914                - m02 * m14 * m25 * m31 * m40 * m53
915                + m02 * m14 * m25 * m31 * m43 * m50
916                + m02 * m14 * m25 * m33 * m40 * m51
917                - m02 * m14 * m25 * m33 * m41 * m50
918                + m02 * m15 * m20 * m31 * m43 * m54
919                - m02 * m15 * m20 * m31 * m44 * m53
920                - m02 * m15 * m20 * m33 * m41 * m54
921                + m02 * m15 * m20 * m33 * m44 * m51
922                + m02 * m15 * m20 * m34 * m41 * m53
923                - m02 * m15 * m20 * m34 * m43 * m51
924                - m02 * m15 * m21 * m30 * m43 * m54
925                + m02 * m15 * m21 * m30 * m44 * m53
926                + m02 * m15 * m21 * m33 * m40 * m54
927                - m02 * m15 * m21 * m33 * m44 * m50
928                - m02 * m15 * m21 * m34 * m40 * m53
929                + m02 * m15 * m21 * m34 * m43 * m50
930                + m02 * m15 * m23 * m30 * m41 * m54
931                - m02 * m15 * m23 * m30 * m44 * m51
932                - m02 * m15 * m23 * m31 * m40 * m54
933                + m02 * m15 * m23 * m31 * m44 * m50
934                + m02 * m15 * m23 * m34 * m40 * m51
935                - m02 * m15 * m23 * m34 * m41 * m50
936                - m02 * m15 * m24 * m30 * m41 * m53
937                + m02 * m15 * m24 * m30 * m43 * m51
938                + m02 * m15 * m24 * m31 * m40 * m53
939                - m02 * m15 * m24 * m31 * m43 * m50
940                - m02 * m15 * m24 * m33 * m40 * m51
941                + m02 * m15 * m24 * m33 * m41 * m50
942                - m03 * m10 * m21 * m32 * m44 * m55
943                + m03 * m10 * m21 * m32 * m45 * m54
944                + m03 * m10 * m21 * m34 * m42 * m55
945                - m03 * m10 * m21 * m34 * m45 * m52
946                - m03 * m10 * m21 * m35 * m42 * m54
947                + m03 * m10 * m21 * m35 * m44 * m52
948                + m03 * m10 * m22 * m31 * m44 * m55
949                - m03 * m10 * m22 * m31 * m45 * m54
950                - m03 * m10 * m22 * m34 * m41 * m55
951                + m03 * m10 * m22 * m34 * m45 * m51
952                + m03 * m10 * m22 * m35 * m41 * m54
953                - m03 * m10 * m22 * m35 * m44 * m51
954                - m03 * m10 * m24 * m31 * m42 * m55
955                + m03 * m10 * m24 * m31 * m45 * m52
956                + m03 * m10 * m24 * m32 * m41 * m55
957                - m03 * m10 * m24 * m32 * m45 * m51
958                - m03 * m10 * m24 * m35 * m41 * m52
959                + m03 * m10 * m24 * m35 * m42 * m51
960                + m03 * m10 * m25 * m31 * m42 * m54
961                - m03 * m10 * m25 * m31 * m44 * m52
962                - m03 * m10 * m25 * m32 * m41 * m54
963                + m03 * m10 * m25 * m32 * m44 * m51
964                + m03 * m10 * m25 * m34 * m41 * m52
965                - m03 * m10 * m25 * m34 * m42 * m51
966                + m03 * m11 * m20 * m32 * m44 * m55
967                - m03 * m11 * m20 * m32 * m45 * m54
968                - m03 * m11 * m20 * m34 * m42 * m55
969                + m03 * m11 * m20 * m34 * m45 * m52
970                + m03 * m11 * m20 * m35 * m42 * m54
971                - m03 * m11 * m20 * m35 * m44 * m52
972                - m03 * m11 * m22 * m30 * m44 * m55
973                + m03 * m11 * m22 * m30 * m45 * m54
974                + m03 * m11 * m22 * m34 * m40 * m55
975                - m03 * m11 * m22 * m34 * m45 * m50
976                - m03 * m11 * m22 * m35 * m40 * m54
977                + m03 * m11 * m22 * m35 * m44 * m50
978                + m03 * m11 * m24 * m30 * m42 * m55
979                - m03 * m11 * m24 * m30 * m45 * m52
980                - m03 * m11 * m24 * m32 * m40 * m55
981                + m03 * m11 * m24 * m32 * m45 * m50
982                + m03 * m11 * m24 * m35 * m40 * m52
983                - m03 * m11 * m24 * m35 * m42 * m50
984                - m03 * m11 * m25 * m30 * m42 * m54
985                + m03 * m11 * m25 * m30 * m44 * m52
986                + m03 * m11 * m25 * m32 * m40 * m54
987                - m03 * m11 * m25 * m32 * m44 * m50
988                - m03 * m11 * m25 * m34 * m40 * m52
989                + m03 * m11 * m25 * m34 * m42 * m50
990                - m03 * m12 * m20 * m31 * m44 * m55
991                + m03 * m12 * m20 * m31 * m45 * m54
992                + m03 * m12 * m20 * m34 * m41 * m55
993                - m03 * m12 * m20 * m34 * m45 * m51
994                - m03 * m12 * m20 * m35 * m41 * m54
995                + m03 * m12 * m20 * m35 * m44 * m51
996                + m03 * m12 * m21 * m30 * m44 * m55
997                - m03 * m12 * m21 * m30 * m45 * m54
998                - m03 * m12 * m21 * m34 * m40 * m55
999                + m03 * m12 * m21 * m34 * m45 * m50
1000                + m03 * m12 * m21 * m35 * m40 * m54
1001                - m03 * m12 * m21 * m35 * m44 * m50
1002                - m03 * m12 * m24 * m30 * m41 * m55
1003                + m03 * m12 * m24 * m30 * m45 * m51
1004                + m03 * m12 * m24 * m31 * m40 * m55
1005                - m03 * m12 * m24 * m31 * m45 * m50
1006                - m03 * m12 * m24 * m35 * m40 * m51
1007                + m03 * m12 * m24 * m35 * m41 * m50
1008                + m03 * m12 * m25 * m30 * m41 * m54
1009                - m03 * m12 * m25 * m30 * m44 * m51
1010                - m03 * m12 * m25 * m31 * m40 * m54
1011                + m03 * m12 * m25 * m31 * m44 * m50
1012                + m03 * m12 * m25 * m34 * m40 * m51
1013                - m03 * m12 * m25 * m34 * m41 * m50
1014                + m03 * m14 * m20 * m31 * m42 * m55
1015                - m03 * m14 * m20 * m31 * m45 * m52
1016                - m03 * m14 * m20 * m32 * m41 * m55
1017                + m03 * m14 * m20 * m32 * m45 * m51
1018                + m03 * m14 * m20 * m35 * m41 * m52
1019                - m03 * m14 * m20 * m35 * m42 * m51
1020                - m03 * m14 * m21 * m30 * m42 * m55
1021                + m03 * m14 * m21 * m30 * m45 * m52
1022                + m03 * m14 * m21 * m32 * m40 * m55
1023                - m03 * m14 * m21 * m32 * m45 * m50
1024                - m03 * m14 * m21 * m35 * m40 * m52
1025                + m03 * m14 * m21 * m35 * m42 * m50
1026                + m03 * m14 * m22 * m30 * m41 * m55
1027                - m03 * m14 * m22 * m30 * m45 * m51
1028                - m03 * m14 * m22 * m31 * m40 * m55
1029                + m03 * m14 * m22 * m31 * m45 * m50
1030                + m03 * m14 * m22 * m35 * m40 * m51
1031                - m03 * m14 * m22 * m35 * m41 * m50
1032                - m03 * m14 * m25 * m30 * m41 * m52
1033                + m03 * m14 * m25 * m30 * m42 * m51
1034                + m03 * m14 * m25 * m31 * m40 * m52
1035                - m03 * m14 * m25 * m31 * m42 * m50
1036                - m03 * m14 * m25 * m32 * m40 * m51
1037                + m03 * m14 * m25 * m32 * m41 * m50
1038                - m03 * m15 * m20 * m31 * m42 * m54
1039                + m03 * m15 * m20 * m31 * m44 * m52
1040                + m03 * m15 * m20 * m32 * m41 * m54
1041                - m03 * m15 * m20 * m32 * m44 * m51
1042                - m03 * m15 * m20 * m34 * m41 * m52
1043                + m03 * m15 * m20 * m34 * m42 * m51
1044                + m03 * m15 * m21 * m30 * m42 * m54
1045                - m03 * m15 * m21 * m30 * m44 * m52
1046                - m03 * m15 * m21 * m32 * m40 * m54
1047                + m03 * m15 * m21 * m32 * m44 * m50
1048                + m03 * m15 * m21 * m34 * m40 * m52
1049                - m03 * m15 * m21 * m34 * m42 * m50
1050                - m03 * m15 * m22 * m30 * m41 * m54
1051                + m03 * m15 * m22 * m30 * m44 * m51
1052                + m03 * m15 * m22 * m31 * m40 * m54
1053                - m03 * m15 * m22 * m31 * m44 * m50
1054                - m03 * m15 * m22 * m34 * m40 * m51
1055                + m03 * m15 * m22 * m34 * m41 * m50
1056                + m03 * m15 * m24 * m30 * m41 * m52
1057                - m03 * m15 * m24 * m30 * m42 * m51
1058                - m03 * m15 * m24 * m31 * m40 * m52
1059                + m03 * m15 * m24 * m31 * m42 * m50
1060                + m03 * m15 * m24 * m32 * m40 * m51
1061                - m03 * m15 * m24 * m32 * m41 * m50
1062                + m04 * m10 * m21 * m32 * m43 * m55
1063                - m04 * m10 * m21 * m32 * m45 * m53
1064                - m04 * m10 * m21 * m33 * m42 * m55
1065                + m04 * m10 * m21 * m33 * m45 * m52
1066                + m04 * m10 * m21 * m35 * m42 * m53
1067                - m04 * m10 * m21 * m35 * m43 * m52
1068                - m04 * m10 * m22 * m31 * m43 * m55
1069                + m04 * m10 * m22 * m31 * m45 * m53
1070                + m04 * m10 * m22 * m33 * m41 * m55
1071                - m04 * m10 * m22 * m33 * m45 * m51
1072                - m04 * m10 * m22 * m35 * m41 * m53
1073                + m04 * m10 * m22 * m35 * m43 * m51
1074                + m04 * m10 * m23 * m31 * m42 * m55
1075                - m04 * m10 * m23 * m31 * m45 * m52
1076                - m04 * m10 * m23 * m32 * m41 * m55
1077                + m04 * m10 * m23 * m32 * m45 * m51
1078                + m04 * m10 * m23 * m35 * m41 * m52
1079                - m04 * m10 * m23 * m35 * m42 * m51
1080                - m04 * m10 * m25 * m31 * m42 * m53
1081                + m04 * m10 * m25 * m31 * m43 * m52
1082                + m04 * m10 * m25 * m32 * m41 * m53
1083                - m04 * m10 * m25 * m32 * m43 * m51
1084                - m04 * m10 * m25 * m33 * m41 * m52
1085                + m04 * m10 * m25 * m33 * m42 * m51
1086                - m04 * m11 * m20 * m32 * m43 * m55
1087                + m04 * m11 * m20 * m32 * m45 * m53
1088                + m04 * m11 * m20 * m33 * m42 * m55
1089                - m04 * m11 * m20 * m33 * m45 * m52
1090                - m04 * m11 * m20 * m35 * m42 * m53
1091                + m04 * m11 * m20 * m35 * m43 * m52
1092                + m04 * m11 * m22 * m30 * m43 * m55
1093                - m04 * m11 * m22 * m30 * m45 * m53
1094                - m04 * m11 * m22 * m33 * m40 * m55
1095                + m04 * m11 * m22 * m33 * m45 * m50
1096                + m04 * m11 * m22 * m35 * m40 * m53
1097                - m04 * m11 * m22 * m35 * m43 * m50
1098                - m04 * m11 * m23 * m30 * m42 * m55
1099                + m04 * m11 * m23 * m30 * m45 * m52
1100                + m04 * m11 * m23 * m32 * m40 * m55
1101                - m04 * m11 * m23 * m32 * m45 * m50
1102                - m04 * m11 * m23 * m35 * m40 * m52
1103                + m04 * m11 * m23 * m35 * m42 * m50
1104                + m04 * m11 * m25 * m30 * m42 * m53
1105                - m04 * m11 * m25 * m30 * m43 * m52
1106                - m04 * m11 * m25 * m32 * m40 * m53
1107                + m04 * m11 * m25 * m32 * m43 * m50
1108                + m04 * m11 * m25 * m33 * m40 * m52
1109                - m04 * m11 * m25 * m33 * m42 * m50
1110                + m04 * m12 * m20 * m31 * m43 * m55
1111                - m04 * m12 * m20 * m31 * m45 * m53
1112                - m04 * m12 * m20 * m33 * m41 * m55
1113                + m04 * m12 * m20 * m33 * m45 * m51
1114                + m04 * m12 * m20 * m35 * m41 * m53
1115                - m04 * m12 * m20 * m35 * m43 * m51
1116                - m04 * m12 * m21 * m30 * m43 * m55
1117                + m04 * m12 * m21 * m30 * m45 * m53
1118                + m04 * m12 * m21 * m33 * m40 * m55
1119                - m04 * m12 * m21 * m33 * m45 * m50
1120                - m04 * m12 * m21 * m35 * m40 * m53
1121                + m04 * m12 * m21 * m35 * m43 * m50
1122                + m04 * m12 * m23 * m30 * m41 * m55
1123                - m04 * m12 * m23 * m30 * m45 * m51
1124                - m04 * m12 * m23 * m31 * m40 * m55
1125                + m04 * m12 * m23 * m31 * m45 * m50
1126                + m04 * m12 * m23 * m35 * m40 * m51
1127                - m04 * m12 * m23 * m35 * m41 * m50
1128                - m04 * m12 * m25 * m30 * m41 * m53
1129                + m04 * m12 * m25 * m30 * m43 * m51
1130                + m04 * m12 * m25 * m31 * m40 * m53
1131                - m04 * m12 * m25 * m31 * m43 * m50
1132                - m04 * m12 * m25 * m33 * m40 * m51
1133                + m04 * m12 * m25 * m33 * m41 * m50
1134                - m04 * m13 * m20 * m31 * m42 * m55
1135                + m04 * m13 * m20 * m31 * m45 * m52
1136                + m04 * m13 * m20 * m32 * m41 * m55
1137                - m04 * m13 * m20 * m32 * m45 * m51
1138                - m04 * m13 * m20 * m35 * m41 * m52
1139                + m04 * m13 * m20 * m35 * m42 * m51
1140                + m04 * m13 * m21 * m30 * m42 * m55
1141                - m04 * m13 * m21 * m30 * m45 * m52
1142                - m04 * m13 * m21 * m32 * m40 * m55
1143                + m04 * m13 * m21 * m32 * m45 * m50
1144                + m04 * m13 * m21 * m35 * m40 * m52
1145                - m04 * m13 * m21 * m35 * m42 * m50
1146                - m04 * m13 * m22 * m30 * m41 * m55
1147                + m04 * m13 * m22 * m30 * m45 * m51
1148                + m04 * m13 * m22 * m31 * m40 * m55
1149                - m04 * m13 * m22 * m31 * m45 * m50
1150                - m04 * m13 * m22 * m35 * m40 * m51
1151                + m04 * m13 * m22 * m35 * m41 * m50
1152                + m04 * m13 * m25 * m30 * m41 * m52
1153                - m04 * m13 * m25 * m30 * m42 * m51
1154                - m04 * m13 * m25 * m31 * m40 * m52
1155                + m04 * m13 * m25 * m31 * m42 * m50
1156                + m04 * m13 * m25 * m32 * m40 * m51
1157                - m04 * m13 * m25 * m32 * m41 * m50
1158                + m04 * m15 * m20 * m31 * m42 * m53
1159                - m04 * m15 * m20 * m31 * m43 * m52
1160                - m04 * m15 * m20 * m32 * m41 * m53
1161                + m04 * m15 * m20 * m32 * m43 * m51
1162                + m04 * m15 * m20 * m33 * m41 * m52
1163                - m04 * m15 * m20 * m33 * m42 * m51
1164                - m04 * m15 * m21 * m30 * m42 * m53
1165                + m04 * m15 * m21 * m30 * m43 * m52
1166                + m04 * m15 * m21 * m32 * m40 * m53
1167                - m04 * m15 * m21 * m32 * m43 * m50
1168                - m04 * m15 * m21 * m33 * m40 * m52
1169                + m04 * m15 * m21 * m33 * m42 * m50
1170                + m04 * m15 * m22 * m30 * m41 * m53
1171                - m04 * m15 * m22 * m30 * m43 * m51
1172                - m04 * m15 * m22 * m31 * m40 * m53
1173                + m04 * m15 * m22 * m31 * m43 * m50
1174                + m04 * m15 * m22 * m33 * m40 * m51
1175                - m04 * m15 * m22 * m33 * m41 * m50
1176                - m04 * m15 * m23 * m30 * m41 * m52
1177                + m04 * m15 * m23 * m30 * m42 * m51
1178                + m04 * m15 * m23 * m31 * m40 * m52
1179                - m04 * m15 * m23 * m31 * m42 * m50
1180                - m04 * m15 * m23 * m32 * m40 * m51
1181                + m04 * m15 * m23 * m32 * m41 * m50
1182                - m05 * m10 * m21 * m32 * m43 * m54
1183                + m05 * m10 * m21 * m32 * m44 * m53
1184                + m05 * m10 * m21 * m33 * m42 * m54
1185                - m05 * m10 * m21 * m33 * m44 * m52
1186                - m05 * m10 * m21 * m34 * m42 * m53
1187                + m05 * m10 * m21 * m34 * m43 * m52
1188                + m05 * m10 * m22 * m31 * m43 * m54
1189                - m05 * m10 * m22 * m31 * m44 * m53
1190                - m05 * m10 * m22 * m33 * m41 * m54
1191                + m05 * m10 * m22 * m33 * m44 * m51
1192                + m05 * m10 * m22 * m34 * m41 * m53
1193                - m05 * m10 * m22 * m34 * m43 * m51
1194                - m05 * m10 * m23 * m31 * m42 * m54
1195                + m05 * m10 * m23 * m31 * m44 * m52
1196                + m05 * m10 * m23 * m32 * m41 * m54
1197                - m05 * m10 * m23 * m32 * m44 * m51
1198                - m05 * m10 * m23 * m34 * m41 * m52
1199                + m05 * m10 * m23 * m34 * m42 * m51
1200                + m05 * m10 * m24 * m31 * m42 * m53
1201                - m05 * m10 * m24 * m31 * m43 * m52
1202                - m05 * m10 * m24 * m32 * m41 * m53
1203                + m05 * m10 * m24 * m32 * m43 * m51
1204                + m05 * m10 * m24 * m33 * m41 * m52
1205                - m05 * m10 * m24 * m33 * m42 * m51
1206                + m05 * m11 * m20 * m32 * m43 * m54
1207                - m05 * m11 * m20 * m32 * m44 * m53
1208                - m05 * m11 * m20 * m33 * m42 * m54
1209                + m05 * m11 * m20 * m33 * m44 * m52
1210                + m05 * m11 * m20 * m34 * m42 * m53
1211                - m05 * m11 * m20 * m34 * m43 * m52
1212                - m05 * m11 * m22 * m30 * m43 * m54
1213                + m05 * m11 * m22 * m30 * m44 * m53
1214                + m05 * m11 * m22 * m33 * m40 * m54
1215                - m05 * m11 * m22 * m33 * m44 * m50
1216                - m05 * m11 * m22 * m34 * m40 * m53
1217                + m05 * m11 * m22 * m34 * m43 * m50
1218                + m05 * m11 * m23 * m30 * m42 * m54
1219                - m05 * m11 * m23 * m30 * m44 * m52
1220                - m05 * m11 * m23 * m32 * m40 * m54
1221                + m05 * m11 * m23 * m32 * m44 * m50
1222                + m05 * m11 * m23 * m34 * m40 * m52
1223                - m05 * m11 * m23 * m34 * m42 * m50
1224                - m05 * m11 * m24 * m30 * m42 * m53
1225                + m05 * m11 * m24 * m30 * m43 * m52
1226                + m05 * m11 * m24 * m32 * m40 * m53
1227                - m05 * m11 * m24 * m32 * m43 * m50
1228                - m05 * m11 * m24 * m33 * m40 * m52
1229                + m05 * m11 * m24 * m33 * m42 * m50
1230                - m05 * m12 * m20 * m31 * m43 * m54
1231                + m05 * m12 * m20 * m31 * m44 * m53
1232                + m05 * m12 * m20 * m33 * m41 * m54
1233                - m05 * m12 * m20 * m33 * m44 * m51
1234                - m05 * m12 * m20 * m34 * m41 * m53
1235                + m05 * m12 * m20 * m34 * m43 * m51
1236                + m05 * m12 * m21 * m30 * m43 * m54
1237                - m05 * m12 * m21 * m30 * m44 * m53
1238                - m05 * m12 * m21 * m33 * m40 * m54
1239                + m05 * m12 * m21 * m33 * m44 * m50
1240                + m05 * m12 * m21 * m34 * m40 * m53
1241                - m05 * m12 * m21 * m34 * m43 * m50
1242                - m05 * m12 * m23 * m30 * m41 * m54
1243                + m05 * m12 * m23 * m30 * m44 * m51
1244                + m05 * m12 * m23 * m31 * m40 * m54
1245                - m05 * m12 * m23 * m31 * m44 * m50
1246                - m05 * m12 * m23 * m34 * m40 * m51
1247                + m05 * m12 * m23 * m34 * m41 * m50
1248                + m05 * m12 * m24 * m30 * m41 * m53
1249                - m05 * m12 * m24 * m30 * m43 * m51
1250                - m05 * m12 * m24 * m31 * m40 * m53
1251                + m05 * m12 * m24 * m31 * m43 * m50
1252                + m05 * m12 * m24 * m33 * m40 * m51
1253                - m05 * m12 * m24 * m33 * m41 * m50
1254                + m05 * m13 * m20 * m31 * m42 * m54
1255                - m05 * m13 * m20 * m31 * m44 * m52
1256                - m05 * m13 * m20 * m32 * m41 * m54
1257                + m05 * m13 * m20 * m32 * m44 * m51
1258                + m05 * m13 * m20 * m34 * m41 * m52
1259                - m05 * m13 * m20 * m34 * m42 * m51
1260                - m05 * m13 * m21 * m30 * m42 * m54
1261                + m05 * m13 * m21 * m30 * m44 * m52
1262                + m05 * m13 * m21 * m32 * m40 * m54
1263                - m05 * m13 * m21 * m32 * m44 * m50
1264                - m05 * m13 * m21 * m34 * m40 * m52
1265                + m05 * m13 * m21 * m34 * m42 * m50
1266                + m05 * m13 * m22 * m30 * m41 * m54
1267                - m05 * m13 * m22 * m30 * m44 * m51
1268                - m05 * m13 * m22 * m31 * m40 * m54
1269                + m05 * m13 * m22 * m31 * m44 * m50
1270                + m05 * m13 * m22 * m34 * m40 * m51
1271                - m05 * m13 * m22 * m34 * m41 * m50
1272                - m05 * m13 * m24 * m30 * m41 * m52
1273                + m05 * m13 * m24 * m30 * m42 * m51
1274                + m05 * m13 * m24 * m31 * m40 * m52
1275                - m05 * m13 * m24 * m31 * m42 * m50
1276                - m05 * m13 * m24 * m32 * m40 * m51
1277                + m05 * m13 * m24 * m32 * m41 * m50
1278                - m05 * m14 * m20 * m31 * m42 * m53
1279                + m05 * m14 * m20 * m31 * m43 * m52
1280                + m05 * m14 * m20 * m32 * m41 * m53
1281                - m05 * m14 * m20 * m32 * m43 * m51
1282                - m05 * m14 * m20 * m33 * m41 * m52
1283                + m05 * m14 * m20 * m33 * m42 * m51
1284                + m05 * m14 * m21 * m30 * m42 * m53
1285                - m05 * m14 * m21 * m30 * m43 * m52
1286                - m05 * m14 * m21 * m32 * m40 * m53
1287                + m05 * m14 * m21 * m32 * m43 * m50
1288                + m05 * m14 * m21 * m33 * m40 * m52
1289                - m05 * m14 * m21 * m33 * m42 * m50
1290                - m05 * m14 * m22 * m30 * m41 * m53
1291                + m05 * m14 * m22 * m30 * m43 * m51
1292                + m05 * m14 * m22 * m31 * m40 * m53
1293                - m05 * m14 * m22 * m31 * m43 * m50
1294                - m05 * m14 * m22 * m33 * m40 * m51
1295                + m05 * m14 * m22 * m33 * m41 * m50
1296                + m05 * m14 * m23 * m30 * m41 * m52
1297                - m05 * m14 * m23 * m30 * m42 * m51
1298                - m05 * m14 * m23 * m31 * m40 * m52
1299                + m05 * m14 * m23 * m31 * m42 * m50
1300                + m05 * m14 * m23 * m32 * m40 * m51
1301                - m05 * m14 * m23 * m32 * m41 * m50
1302        }
1303        _ =>
1304        // Now do it the traditional way
1305        {
1306            // Reuseable result to reduce memory allocations
1307            let l1 = l - 1;
1308            let mut res: Vec<T> = vm.to_vec(); // same shape/size as vm
1309                                               // This is n^3
1310            (0..l)
1311                .map(|i| {
1312                    // Makes a modest difference
1313                    if vm[i].is_zero() {
1314                        T::zero()
1315                    } else {
1316                        for r in 0..l1 {
1317                            let d = r * l1;
1318                            let s = (r + 1) * l;
1319                            for c in 0..l1 {
1320                                res[d + c] = vm[s + c + usize::from(c >= i)];
1321                            }
1322                        }
1323                        let v = vm[i] * determinant(&res, l1);
1324                        if (i % 2) == 0 {
1325                            v
1326                        } else {
1327                            -v
1328                        }
1329                    }
1330                })
1331                .sum::<T>()
1332        }
1333    }
1334}
1335
1336fn check_diag<T: Float>(m: &Array2<T>) -> usize {
1337    let d = m.raw_dim();
1338    assert!(d[0] == d[1]);
1339
1340    for i in 0..d[0] {
1341        if m[(i, i)].is_zero() {
1342            return 0;
1343        }
1344    }
1345
1346    d[0]
1347}
1348
1349fn linv<T: Float>(l: &Array2<T>, n: usize) -> Array2<T> {
1350    let mut m: Array2<T> = Array2::zeros((n, n));
1351
1352    for i in 0..n {
1353        m[(i, i)] = l[(i, i)].recip();
1354
1355        for j in 0..i {
1356            for k in j..i {
1357                m[(i, j)] = m[(i, j)] + l[(i, k)] * m[(k, j)];
1358            }
1359
1360            m[(i, j)] = -m[(i, j)] * m[(i, i)];
1361        }
1362    }
1363
1364    m
1365}
1366
1367fn uinv<T: Float>(u: &Array2<T>, n: usize) -> Array2<T> {
1368    linv(&u.t().to_owned(), n).t().to_owned()
1369}
1370
1371// #[cfg(test)]
1372// mod test_inverse {
1373//     use crate::Inverse;
1374//     use ndarray::prelude::*;
1375//     use num_traits::Float;
1376//     use std::fmt::Debug;
1377
1378//     const EPS: f64 = 1e-8;
1379
1380//     fn to_vec<T: Float>(m: &Array2<T>) -> Vec<T> {
1381//         m.iter().map(|&e| e).collect()
1382//     }
1383
1384//     /// utility function to compare vectors of Floats
1385//     fn compare_vecs<T: Float + Debug>(v1: &Array2<T>, v2: &Array2<T>,
1386// epsilon: T) -> bool {         to_vec(v1)
1387//             .into_iter()
1388//             .zip(to_vec(v2))
1389//             .map(|(a, b)| Float::abs(a.abs() - b.abs()) < epsilon)
1390//             .all(|b| b)
1391//     }
1392
1393//     #[test]
1394//     fn test_1x1() {
1395//         let a: Array2<f64> = array![[2.0]];
1396//         let inv = a.inv().expect("Sods Law");
1397//         let back = inv.inv();
1398//         assert!(compare_vecs(&a, &back.unwrap(), EPS));
1399//         let expected = array![[0.5]];
1400//         assert!(compare_vecs(&inv, &expected, EPS));
1401//     }
1402
1403//     #[test]
1404//     fn test_2x2() {
1405//         let a: Array2<f64> = array![[1.0, 2.0], [3.0, 4.0]];
1406//         let inv = a.inv().expect("Sods Law");
1407//         let back = inv.inv();
1408//         assert!(compare_vecs(&a, &back.unwrap(), EPS));
1409//         let expected = array![[-2.0, 1.0], [1.5, -0.5]];
1410//         assert!(compare_vecs(&inv, &expected, EPS));
1411//     }
1412
1413//     #[test]
1414//     fn test_3x3() {
1415//         let a: Array2<f64> = array![[1.0, 0.0, 3.0], [2.0, 1.0, 6.0], [1.0,
1416// 0.0, 9.0]];         let inv = a.inv().expect("Sods Law");
1417//         let back = inv.inv();
1418//         assert!(compare_vecs(&a, &back.unwrap(), EPS));
1419//         let expected = array![[1.5, 0.0, -0.5], [-2.0, 1.0, -0.0],
1420// [-0.16666667, 0.0, 0.16666667]];         assert!(compare_vecs(&inv,
1421// &expected, EPS));     }
1422
1423//     #[test]
1424//     fn test_4x4() {
1425//         let a: Array2<f64> = array![
1426//             [-68.0, 68.0, -16.0, 4.0],
1427//             [-36.0, 35.0, -9.0, 3.0],
1428//             [48.0, -47.0, 11.0, -3.0],
1429//             [64.0, -64.0, 16.0, -4.0]
1430//         ];
1431//         let inv = a.inv().expect("Sods Law");
1432//         let back = inv.inv();
1433//         eprintln!("{:?}", to_vec(&inv));
1434//         // This fails with LU Inverse only
1435//         assert!(compare_vecs(&a, &back.unwrap(), EPS));
1436//         let expected = array![[1.25, 0.5, 1.5, 0.5], [1.5, 0.5, 1.5, 0.75],
1437// [1.5, 0.5, 0.5, 1.5], [2.0, 2.0, 2.0, 1.75]];         assert!(compare_vecs(&
1438// inv, &expected, EPS));     }
1439
1440//     #[test]
1441//     fn test_5x5() {
1442//         let a: Array2<f64> = array![
1443//             [10.0, 1.0, 7.0, 1.0, 5.0],
1444//             [2.0, 4.0, 8.0, 3.0, 2.0],
1445//             [5.0, 1.0, 2.0, 9.0, 10.0],
1446//             [6.0, 9.0, 9.0, 7.0, 3.0],
1447//             [1.0, 8.0, 8.0, 10.0, 5.0],
1448//         ];
1449//         let inv = a.inv().expect("Sods Law");
1450//         let back = inv.inv().unwrap();
1451//         // some concern here, precision might not be ideal (try 1e-5)
1452//         // Note: Precision is better for LU Inverse and full EPS can be used
1453//         assert!(compare_vecs(&a, &back, EPS));
1454//         let expected: Array2<f64> = array![
1455//             [-11.98, 15.64, 9.32, 10.34, -19.12],
1456//             [33.62, -44.16, -26.08, -28.46, 53.28],
1457//             [-9.36, 12.48, 7.24, 7.88, -14.84],
1458//             [-37.2, 48.6, 28.8, 31.6, -58.8],
1459//             [37.98, -49.64, -29.32, -32.34, 60.12]
1460//         ];
1461//         assert!(compare_vecs(&inv, &expected, EPS));
1462//     }
1463
1464//     #[test]
1465//     fn test_5x5b() {
1466//         let a: Array2<f64> = array![
1467//             [8.12658, 1.02214, 2.67754, 7.00746, 0.16869],
1468//             [3.31581, 0.63792, 4.28436, 5.61229, 1.19785],
1469//             [8.13028, 6.48437, 6.91838, 2.68860, 6.60971],
1470//             [2.85578, 4.40362, 1.13265, 8.32311, 4.41366],
1471//             [7.93379, 4.09682, 4.86444, 6.67282, 3.57098]
1472//         ];
1473//         let inv = a.inv().expect("Sods Law");
1474//         let back = inv.inv().unwrap();
1475//         // Precision is good here!
1476//         assert!(compare_vecs(&a, &back, EPS));
1477//         let expected: Array2<f64> = array![
1478//             [0.50074759, -0.02510542, 0.33877844, 0.09275141, -0.7569348],
1479//             [-1.58848174, -0.64356647, -1.32943575, -0.57849057, 3.46664012],
1480//             [-0.49917931, 0.12378294, -0.30452856, -0.25789124, 0.86447499],
1481//             [-0.0513424, 0.06348965, -0.1164256, 0.0585164, 0.12430141],
1482//             [1.48578933, 0.50685455, 1.40491123, 0.69956389, -3.42524083]
1483//         ];
1484//         assert!(compare_vecs(&inv, &expected, EPS));
1485//     }
1486
1487//     #[test]
1488//     fn test_6x6() {
1489//         let a: Array2<f64> = array![
1490//             [1.0, 1.0, 3.0, 4.0, 9.0, 3.0],
1491//             [10.0, 10.0, 1.0, 2.0, 2.0, 5.0],
1492//             [2.0, 9.0, 6.0, 10.0, 10.0, 9.0],
1493//             [10.0, 9.0, 9.0, 7.0, 3.0, 6.0],
1494//             [7.0, 6.0, 6.0, 2.0, 9.0, 5.0],
1495//             [3.0, 8.0, 1.0, 4.0, 1.0, 5.0]
1496//         ];
1497//         let inv = a.inv().expect("Sods Law");
1498//         eprintln!("{:?}", to_vec(&inv));
1499//         let back = inv.inv();
1500//         // This fails with LU Inverse only
1501//         assert!(compare_vecs(&a, &back.unwrap(), EPS));
1502//         let expected = array![
1503//             [-0.53881418, 0.57793399, 0.6653423, -0.08374083, -0.16962103,
1504// -1.18215159],             [2.16075795, -1.52750611, -2.44070905, 0.44132029,
1505// 0.32457213, 3.77017115],             [0.21454768, -0.41503667, -0.39425428,
1506// 0.14792176, 0.19743276, 0.62102689],             [0.70018337, -0.24052567,
1507// -0.525978, 0.20354523, -0.21179707, 0.73471883],             [0.85055012,
1508// -0.47157702, -0.82793399, 0.1106357, 0.1146088, 1.20415648],
1509// [-3.90709046, 2.46699267, 4.17114914, -0.87041565, -0.31051345, -6.07579462]
1510//         ];
1511//         assert!(compare_vecs(&inv, &expected, EPS));
1512//     }
1513
1514//     #[test]
1515//     fn test_7x7() {
1516//         let a: Array2<f64> = array![
1517//             [4.3552, 6.25851, 4.12662, 1.93708, 0.21272, 3.25683, 6.53326],
1518//             [4.24746, 1.84137, 6.71904, 0.59754, 3.5806, 3.63597, 5.347],
1519//             [2.30479, 1.70591, 3.05354, 1.82188, 5.27839, 7.9166, 2.04607],
1520//             [2.40158, 6.38524, 7.90296, 4.69683, 6.63801, 7.32958, 1.45936],
1521//             [0.42456, 6.47456, 1.55398, 8.28979, 4.20987, 0.90401, 4.94587],
1522//             [5.78903, 1.92032, 6.20261, 5.78543, 1.94331, 8.25178, 7.47273],
1523//             [1.44797, 7.41157, 7.69495, 8.90113, 3.05983, 0.41582, 6.42932]
1524//         ];
1525//         let inv = a.inv().expect("Sods Law");
1526//         let back = inv.inv();
1527//         assert!(compare_vecs(&a, &back.unwrap(), EPS));
1528//         let expected = array![
1529//             [-0.0819729, 0.30947774, -0.90286793, 0.49545542, 0.47316173,
1530// 0.30651669, -0.71946285],             [0.15235561, -0.07559205, -0.0070691,
1531// 0.06757486, 0.01026404, -0.08019532, -0.01972633],             [-0.03064041,
1532// -0.00625996, 0.07810921, -0.01780696, -0.19716224, -0.03302802, 0.20558502],
1533//             [-0.11358415, -0.02543206, -0.24035635, 0.1260263, 0.1346972,
1534// 0.16555344, -0.111583],             [-0.1016236, 0.21480081, -0.0698384,
1535// 0.05521421, 0.20158013, -0.05049775, -0.16205801],             [0.0760218,
1536// -0.20124886, 0.34308958, -0.12448475, -0.18988991, -0.02734616, 0.18705112],
1537//             [0.08020185, -0.02906765, 0.46181332, -0.36087425, -0.15255756,
1538// -0.14045526, 0.31376606]         ];
1539//         assert!(compare_vecs(&inv, &expected, EPS));
1540//     }
1541
1542//     #[cfg(not(debug_assertions))]
1543//     use std::time::{Duration, Instant};
1544
1545//     #[test]
1546//     #[cfg(not(debug_assertions))]
1547//     // This is very fast when compiled with full optimisations
1548//     // About 50x slower in debug mode! Thanks Optimizer.
1549//     fn bench_6x6() {
1550//         let a: Array2<f64> = array![
1551//             [1.0, 1.0, 3.0, 4.0, 9.0, 3.0],
1552//             [10.0, 10.0, 1.0, 2.0, 2.0, 5.0],
1553//             [2.0, 9.0, 6.0, 10.0, 10.0, 9.0],
1554//             [10.0, 9.0, 9.0, 7.0, 3.0, 6.0],
1555//             [7.0, 6.0, 6.0, 2.0, 9.0, 5.0],
1556//             [3.0, 8.0, 1.0, 4.0, 1.0, 5.0]
1557//         ];
1558
1559//         let start = Instant::now();
1560//         let mut _q = a.inv();
1561//         for _ in 0..100000 {
1562//             _q = a.inv();
1563//         }
1564//         // Takes about a second on average modern desktop / laptop
1565//         assert!(start.elapsed() < Duration::new(2, 0));
1566//     }
1567
1568//     #[test]
1569//     fn test_diag() {
1570//         let a: Array2<f64> = array![
1571//             [1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
1572//             [0.0, 10.0, 0.0, 0.0, 0.0, 0.0],
1573//             [0.0, 0.0, 6.0, 0.0, 0.0, 0.0],
1574//             [0.0, 0.0, 0.0, 7.0, 0.0, 0.0],
1575//             [0.0, 0.0, 0.0, 0.0, 9.0, 0.0],
1576//             [0.0, 0.0, 0.0, 0.0, 0.0, 5.0]
1577//         ];
1578//         let inv = a.inv_diag().expect("Sods Law");
1579//         let back = inv.inv_diag();
1580//         assert!(compare_vecs(&a, &back.unwrap(), EPS));
1581//         let expected = a.inv().expect("Sods Law");
1582//         assert!(compare_vecs(&inv, &expected, EPS));
1583//     }
1584
1585//     #[test]
1586//     fn test_cholesky() {
1587//         let a = array![[25.0, 15.0, -5.0], [15.0, 18.0, 0.0], [-5.0, 0.0,
1588// 11.0]];
1589
1590//         let res = a.cholesky();
1591
1592//         let expected = array![[5.0, 0.0, 0.0], [3.0, 3.0, 0.0], [-1.0, 1.0,
1593// 3.]];
1594
1595//         assert!(compare_vecs(&res, &expected, EPS));
1596
1597//         let a = array![
1598//             [18.0, 22.0, 54.0, 42.0],
1599//             [22.0, 70.0, 86.0, 62.0],
1600//             [54.0, 86.0, 174.0, 134.0],
1601//             [42.0, 62.0, 134.0, 106.0]
1602//         ];
1603
1604//         let res = a.cholesky();
1605
1606//         let expected = array![
1607//             [4.242640687119285, 0.0, 0.0, 0.0],
1608//             [5.185449728701349, 6.565905201197403, 0.0, 0.0],
1609//             [12.727922061357857, 3.0460384954008553, 1.6497422479090704,
1610// 0.0],             [9.899494936611667, 1.624553864213788, 1.8497110052313648,
1611// 1.3926212476456026]         ];
1612
1613//         assert!(compare_vecs(&res, &expected, EPS));
1614
1615//         let a = array![[2.0, 0.1], [0.1, 3.0]];
1616
1617//         let res = a.cholesky().t().to_owned();
1618
1619//         let expected = array![[1.41421356, 0.07071068], [0.0, 1.73060683]];
1620
1621//         assert!(compare_vecs(&res, &expected, EPS));
1622
1623//         let expected_sq = array![[2.005, 0.12237238], [0.12237238, 2.995]];
1624
1625//         assert!(compare_vecs(&res.dot(&res.t()), &expected_sq, EPS));
1626//     }
1627
1628//     #[test]
1629//     fn test_triangular() {
1630//         let a = array![
1631//             [4.242640687119285, 0.0, 0.0, 0.0],
1632//             [5.185449728701349, 6.565905201197403, 0.0, 0.0],
1633//             [12.727922061357857, 3.0460384954008553, 1.6497422479090704,
1634// 0.0],             [9.899494936611667, 1.624553864213788, 1.8497110052313648,
1635// 1.3926212476456026]         ];
1636
1637//         assert!(compare_vecs(&a.inv().unwrap(), &a.inv_lt().unwrap(), EPS));
1638//         assert!(compare_vecs(&a.t().to_owned().inv().unwrap(),
1639// &a.t().to_owned().inv_ut().unwrap(), EPS));     }
1640// }