2020-03-21 19:16:46 +08:00
|
|
|
|
use simba::scalar::ComplexField;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2019-03-23 21:29:07 +08:00
|
|
|
|
use crate::base::allocator::Allocator;
|
|
|
|
|
use crate::base::dimension::Dim;
|
|
|
|
|
use crate::base::storage::{Storage, StorageMut};
|
2021-04-11 17:00:38 +08:00
|
|
|
|
use crate::base::{DefaultAllocator, OMatrix, SquareMatrix};
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2019-03-23 21:29:07 +08:00
|
|
|
|
use crate::linalg::lu;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: ComplexField, D: Dim, S: Storage<T, D, D>> SquareMatrix<T, D, S> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/// Attempts to invert this matrix.
|
|
|
|
|
#[inline]
|
2019-06-06 05:04:04 +08:00
|
|
|
|
#[must_use = "Did you mean to use try_inverse_mut()?"]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn try_inverse(self) -> Option<OMatrix<T, D, D>>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut me = self.into_owned();
|
|
|
|
|
if me.try_inverse_mut() {
|
|
|
|
|
Some(me)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: ComplexField, D: Dim, S: StorageMut<T, D, D>> SquareMatrix<T, D, S> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/// Attempts to invert this matrix in-place. Returns `false` and leaves `self` untouched if
|
|
|
|
|
/// inversion fails.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn try_inverse_mut(&mut self) -> bool
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
assert!(self.is_square(), "Unable to invert a non-square matrix.");
|
|
|
|
|
|
|
|
|
|
let dim = self.shape().0;
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
match dim {
|
|
|
|
|
0 => true,
|
|
|
|
|
1 => {
|
2021-08-04 23:34:25 +08:00
|
|
|
|
let determinant = self.get_unchecked((0, 0)).clone();
|
2019-03-18 16:08:42 +08:00
|
|
|
|
if determinant.is_zero() {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
false
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2021-04-11 17:00:38 +08:00
|
|
|
|
*self.get_unchecked_mut((0, 0)) = T::one() / determinant;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
true
|
|
|
|
|
}
|
2018-02-02 19:26:35 +08:00
|
|
|
|
}
|
2017-08-03 01:37:44 +08:00
|
|
|
|
2 => {
|
2021-08-04 23:34:25 +08:00
|
|
|
|
let m11 = self.get_unchecked((0, 0)).clone();
|
|
|
|
|
let m12 = self.get_unchecked((0, 1)).clone();
|
|
|
|
|
let m21 = self.get_unchecked((1, 0)).clone();
|
|
|
|
|
let m22 = self.get_unchecked((1, 1)).clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2021-08-04 23:34:25 +08:00
|
|
|
|
let determinant = m11.clone() * m22.clone() - m21.clone() * m12.clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2019-03-18 16:08:42 +08:00
|
|
|
|
if determinant.is_zero() {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
false
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2021-08-04 23:34:25 +08:00
|
|
|
|
*self.get_unchecked_mut((0, 0)) = m22 / determinant.clone();
|
|
|
|
|
*self.get_unchecked_mut((0, 1)) = -m12 / determinant.clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2021-08-04 23:34:25 +08:00
|
|
|
|
*self.get_unchecked_mut((1, 0)) = -m21 / determinant.clone();
|
2018-12-03 04:00:08 +08:00
|
|
|
|
*self.get_unchecked_mut((1, 1)) = m11 / determinant;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
true
|
|
|
|
|
}
|
2018-02-02 19:26:35 +08:00
|
|
|
|
}
|
2017-08-03 01:37:44 +08:00
|
|
|
|
3 => {
|
2021-08-04 23:34:25 +08:00
|
|
|
|
let m11 = self.get_unchecked((0, 0)).clone();
|
|
|
|
|
let m12 = self.get_unchecked((0, 1)).clone();
|
|
|
|
|
let m13 = self.get_unchecked((0, 2)).clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2021-08-04 23:34:25 +08:00
|
|
|
|
let m21 = self.get_unchecked((1, 0)).clone();
|
|
|
|
|
let m22 = self.get_unchecked((1, 1)).clone();
|
|
|
|
|
let m23 = self.get_unchecked((1, 2)).clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2021-08-04 23:34:25 +08:00
|
|
|
|
let m31 = self.get_unchecked((2, 0)).clone();
|
|
|
|
|
let m32 = self.get_unchecked((2, 1)).clone();
|
|
|
|
|
let m33 = self.get_unchecked((2, 2)).clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2021-08-04 23:34:25 +08:00
|
|
|
|
let minor_m12_m23 = m22.clone() * m33.clone() - m32.clone() * m23.clone();
|
|
|
|
|
let minor_m11_m23 = m21.clone() * m33.clone() - m31.clone() * m23.clone();
|
|
|
|
|
let minor_m11_m22 = m21.clone() * m32.clone() - m31.clone() * m22.clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2021-08-04 23:34:25 +08:00
|
|
|
|
let determinant = m11.clone() * minor_m12_m23.clone()
|
|
|
|
|
- m12.clone() * minor_m11_m23.clone()
|
|
|
|
|
+ m13.clone() * minor_m11_m22.clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2019-03-18 16:08:42 +08:00
|
|
|
|
if determinant.is_zero() {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
false
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2021-08-04 23:34:25 +08:00
|
|
|
|
*self.get_unchecked_mut((0, 0)) = minor_m12_m23 / determinant.clone();
|
|
|
|
|
*self.get_unchecked_mut((0, 1)) = (m13.clone() * m32.clone()
|
|
|
|
|
- m33.clone() * m12.clone())
|
|
|
|
|
/ determinant.clone();
|
|
|
|
|
*self.get_unchecked_mut((0, 2)) = (m12.clone() * m23.clone()
|
|
|
|
|
- m22.clone() * m13.clone())
|
|
|
|
|
/ determinant.clone();
|
|
|
|
|
|
|
|
|
|
*self.get_unchecked_mut((1, 0)) = -minor_m11_m23 / determinant.clone();
|
|
|
|
|
*self.get_unchecked_mut((1, 1)) =
|
|
|
|
|
(m11.clone() * m33 - m31.clone() * m13.clone()) / determinant.clone();
|
|
|
|
|
*self.get_unchecked_mut((1, 2)) =
|
|
|
|
|
(m13 * m21.clone() - m23 * m11.clone()) / determinant.clone();
|
|
|
|
|
|
|
|
|
|
*self.get_unchecked_mut((2, 0)) = minor_m11_m22 / determinant.clone();
|
|
|
|
|
*self.get_unchecked_mut((2, 1)) =
|
|
|
|
|
(m12.clone() * m31 - m32 * m11.clone()) / determinant.clone();
|
2018-12-03 04:00:08 +08:00
|
|
|
|
*self.get_unchecked_mut((2, 2)) = (m11 * m22 - m21 * m12) / determinant;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
true
|
|
|
|
|
}
|
2018-02-02 19:26:35 +08:00
|
|
|
|
}
|
|
|
|
|
4 => {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let oself = self.clone_owned();
|
|
|
|
|
do_inverse4(&oself, self)
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
let oself = self.clone_owned();
|
|
|
|
|
lu::try_invert_to(oself, self)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-24 12:48:42 +08:00
|
|
|
|
// NOTE: this is an extremely efficient, loop-unrolled matrix inverse from MESA (MIT licensed).
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn do_inverse4<T: ComplexField, D: Dim, S: StorageMut<T, D, D>>(
|
|
|
|
|
m: &OMatrix<T, D, D>,
|
|
|
|
|
out: &mut SquareMatrix<T, D, S>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
) -> bool
|
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2021-06-17 15:46:49 +08:00
|
|
|
|
let m = m.as_slice();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2021-08-04 23:34:25 +08:00
|
|
|
|
out[(0, 0)] = m[5].clone() * m[10].clone() * m[15].clone()
|
|
|
|
|
- m[5].clone() * m[11].clone() * m[14].clone()
|
|
|
|
|
- m[9].clone() * m[6].clone() * m[15].clone()
|
|
|
|
|
+ m[9].clone() * m[7].clone() * m[14].clone()
|
|
|
|
|
+ m[13].clone() * m[6].clone() * m[11].clone()
|
|
|
|
|
- m[13].clone() * m[7].clone() * m[10].clone();
|
|
|
|
|
|
|
|
|
|
out[(1, 0)] = -m[1].clone() * m[10].clone() * m[15].clone()
|
|
|
|
|
+ m[1].clone() * m[11].clone() * m[14].clone()
|
|
|
|
|
+ m[9].clone() * m[2].clone() * m[15].clone()
|
|
|
|
|
- m[9].clone() * m[3].clone() * m[14].clone()
|
|
|
|
|
- m[13].clone() * m[2].clone() * m[11].clone()
|
|
|
|
|
+ m[13].clone() * m[3].clone() * m[10].clone();
|
|
|
|
|
|
|
|
|
|
out[(2, 0)] = m[1].clone() * m[6].clone() * m[15].clone()
|
|
|
|
|
- m[1].clone() * m[7].clone() * m[14].clone()
|
|
|
|
|
- m[5].clone() * m[2].clone() * m[15].clone()
|
|
|
|
|
+ m[5].clone() * m[3].clone() * m[14].clone()
|
|
|
|
|
+ m[13].clone() * m[2].clone() * m[7].clone()
|
|
|
|
|
- m[13].clone() * m[3].clone() * m[6].clone();
|
|
|
|
|
|
|
|
|
|
out[(3, 0)] = -m[1].clone() * m[6].clone() * m[11].clone()
|
|
|
|
|
+ m[1].clone() * m[7].clone() * m[10].clone()
|
|
|
|
|
+ m[5].clone() * m[2].clone() * m[11].clone()
|
|
|
|
|
- m[5].clone() * m[3].clone() * m[10].clone()
|
|
|
|
|
- m[9].clone() * m[2].clone() * m[7].clone()
|
|
|
|
|
+ m[9].clone() * m[3].clone() * m[6].clone();
|
|
|
|
|
|
|
|
|
|
out[(0, 1)] = -m[4].clone() * m[10].clone() * m[15].clone()
|
|
|
|
|
+ m[4].clone() * m[11].clone() * m[14].clone()
|
|
|
|
|
+ m[8].clone() * m[6].clone() * m[15].clone()
|
|
|
|
|
- m[8].clone() * m[7].clone() * m[14].clone()
|
|
|
|
|
- m[12].clone() * m[6].clone() * m[11].clone()
|
|
|
|
|
+ m[12].clone() * m[7].clone() * m[10].clone();
|
|
|
|
|
|
|
|
|
|
out[(1, 1)] = m[0].clone() * m[10].clone() * m[15].clone()
|
|
|
|
|
- m[0].clone() * m[11].clone() * m[14].clone()
|
|
|
|
|
- m[8].clone() * m[2].clone() * m[15].clone()
|
|
|
|
|
+ m[8].clone() * m[3].clone() * m[14].clone()
|
|
|
|
|
+ m[12].clone() * m[2].clone() * m[11].clone()
|
|
|
|
|
- m[12].clone() * m[3].clone() * m[10].clone();
|
|
|
|
|
|
|
|
|
|
out[(2, 1)] = -m[0].clone() * m[6].clone() * m[15].clone()
|
|
|
|
|
+ m[0].clone() * m[7].clone() * m[14].clone()
|
|
|
|
|
+ m[4].clone() * m[2].clone() * m[15].clone()
|
|
|
|
|
- m[4].clone() * m[3].clone() * m[14].clone()
|
|
|
|
|
- m[12].clone() * m[2].clone() * m[7].clone()
|
|
|
|
|
+ m[12].clone() * m[3].clone() * m[6].clone();
|
|
|
|
|
|
|
|
|
|
out[(3, 1)] = m[0].clone() * m[6].clone() * m[11].clone()
|
|
|
|
|
- m[0].clone() * m[7].clone() * m[10].clone()
|
|
|
|
|
- m[4].clone() * m[2].clone() * m[11].clone()
|
|
|
|
|
+ m[4].clone() * m[3].clone() * m[10].clone()
|
|
|
|
|
+ m[8].clone() * m[2].clone() * m[7].clone()
|
|
|
|
|
- m[8].clone() * m[3].clone() * m[6].clone();
|
|
|
|
|
|
|
|
|
|
out[(0, 2)] = m[4].clone() * m[9].clone() * m[15].clone()
|
|
|
|
|
- m[4].clone() * m[11].clone() * m[13].clone()
|
|
|
|
|
- m[8].clone() * m[5].clone() * m[15].clone()
|
|
|
|
|
+ m[8].clone() * m[7].clone() * m[13].clone()
|
|
|
|
|
+ m[12].clone() * m[5].clone() * m[11].clone()
|
|
|
|
|
- m[12].clone() * m[7].clone() * m[9].clone();
|
|
|
|
|
|
|
|
|
|
out[(1, 2)] = -m[0].clone() * m[9].clone() * m[15].clone()
|
|
|
|
|
+ m[0].clone() * m[11].clone() * m[13].clone()
|
|
|
|
|
+ m[8].clone() * m[1].clone() * m[15].clone()
|
|
|
|
|
- m[8].clone() * m[3].clone() * m[13].clone()
|
|
|
|
|
- m[12].clone() * m[1].clone() * m[11].clone()
|
|
|
|
|
+ m[12].clone() * m[3].clone() * m[9].clone();
|
|
|
|
|
|
|
|
|
|
out[(2, 2)] = m[0].clone() * m[5].clone() * m[15].clone()
|
|
|
|
|
- m[0].clone() * m[7].clone() * m[13].clone()
|
|
|
|
|
- m[4].clone() * m[1].clone() * m[15].clone()
|
|
|
|
|
+ m[4].clone() * m[3].clone() * m[13].clone()
|
|
|
|
|
+ m[12].clone() * m[1].clone() * m[7].clone()
|
|
|
|
|
- m[12].clone() * m[3].clone() * m[5].clone();
|
|
|
|
|
|
|
|
|
|
out[(0, 3)] = -m[4].clone() * m[9].clone() * m[14].clone()
|
|
|
|
|
+ m[4].clone() * m[10].clone() * m[13].clone()
|
|
|
|
|
+ m[8].clone() * m[5].clone() * m[14].clone()
|
|
|
|
|
- m[8].clone() * m[6].clone() * m[13].clone()
|
|
|
|
|
- m[12].clone() * m[5].clone() * m[10].clone()
|
|
|
|
|
+ m[12].clone() * m[6].clone() * m[9].clone();
|
|
|
|
|
|
|
|
|
|
out[(3, 2)] = -m[0].clone() * m[5].clone() * m[11].clone()
|
|
|
|
|
+ m[0].clone() * m[7].clone() * m[9].clone()
|
|
|
|
|
+ m[4].clone() * m[1].clone() * m[11].clone()
|
|
|
|
|
- m[4].clone() * m[3].clone() * m[9].clone()
|
|
|
|
|
- m[8].clone() * m[1].clone() * m[7].clone()
|
|
|
|
|
+ m[8].clone() * m[3].clone() * m[5].clone();
|
|
|
|
|
|
|
|
|
|
out[(1, 3)] = m[0].clone() * m[9].clone() * m[14].clone()
|
|
|
|
|
- m[0].clone() * m[10].clone() * m[13].clone()
|
|
|
|
|
- m[8].clone() * m[1].clone() * m[14].clone()
|
|
|
|
|
+ m[8].clone() * m[2].clone() * m[13].clone()
|
|
|
|
|
+ m[12].clone() * m[1].clone() * m[10].clone()
|
|
|
|
|
- m[12].clone() * m[2].clone() * m[9].clone();
|
|
|
|
|
|
|
|
|
|
out[(2, 3)] = -m[0].clone() * m[5].clone() * m[14].clone()
|
|
|
|
|
+ m[0].clone() * m[6].clone() * m[13].clone()
|
|
|
|
|
+ m[4].clone() * m[1].clone() * m[14].clone()
|
|
|
|
|
- m[4].clone() * m[2].clone() * m[13].clone()
|
|
|
|
|
- m[12].clone() * m[1].clone() * m[6].clone()
|
|
|
|
|
+ m[12].clone() * m[2].clone() * m[5].clone();
|
|
|
|
|
|
|
|
|
|
out[(3, 3)] = m[0].clone() * m[5].clone() * m[10].clone()
|
|
|
|
|
- m[0].clone() * m[6].clone() * m[9].clone()
|
|
|
|
|
- m[4].clone() * m[1].clone() * m[10].clone()
|
|
|
|
|
+ m[4].clone() * m[2].clone() * m[9].clone()
|
|
|
|
|
+ m[8].clone() * m[1].clone() * m[6].clone()
|
|
|
|
|
- m[8].clone() * m[2].clone() * m[5].clone();
|
|
|
|
|
|
|
|
|
|
let det = m[0].clone() * out[(0, 0)].clone()
|
|
|
|
|
+ m[1].clone() * out[(0, 1)].clone()
|
|
|
|
|
+ m[2].clone() * out[(0, 2)].clone()
|
|
|
|
|
+ m[3].clone() * out[(0, 3)].clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
if !det.is_zero() {
|
2021-04-11 17:00:38 +08:00
|
|
|
|
let inv_det = T::one() / det;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2018-02-02 19:26:35 +08:00
|
|
|
|
for j in 0..4 {
|
|
|
|
|
for i in 0..4 {
|
2021-08-04 23:34:25 +08:00
|
|
|
|
out[(i, j)] *= inv_det.clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
true
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
}
|