| 1 /*! |
1 /*! |
| 2 Linear equation solvers for small problems stored in Rust arrays. |
2 Linear equation solvers for small problems stored in Rust arrays. |
| 3 */ |
3 */ |
| 4 |
4 |
| 5 use crate::types::Float; |
5 use crate::types::Float; |
| |
6 #[cfg(feature = "nightly")] |
| 6 use std::mem::MaybeUninit; |
7 use std::mem::MaybeUninit; |
| 7 |
8 |
| 8 /// Gaussian elimination for $AX=B$, where $A$ and $B$ are both stored in `ab`, |
9 /// Gaussian elimination for $AX=B$, where $A$ and $B$ are both stored in `ab`, |
| 9 /// $A \in \mathbb{R}^{M \times M}$ and $X, B \in \mathbb{R}^{M \times K}$. |
10 /// $A \in \mathbb{R}^{M \times M}$ and $X, B \in \mathbb{R}^{M \times K}$. |
| 10 pub fn linsolve0<F : Float, const M : usize, const N : usize, const K : usize>( |
11 pub fn linsolve0<F : Float, const M : usize, const N : usize, const K : usize>( |
| 43 } |
44 } |
| 44 } |
45 } |
| 45 |
46 |
| 46 // Solve UAX=UB for X where UA with U presenting the transformations above an |
47 // Solve UAX=UB for X where UA with U presenting the transformations above an |
| 47 // upper triangular matrix. |
48 // upper triangular matrix. |
| |
49 // |
| |
50 // If the "nightly" feature is enabled, we will use an uninitialised array for a |
| |
51 // little bit of efficiency. |
| 48 // This use of MaybeUninit assumes F : Copy. Otherwise undefined behaviour may occur. |
52 // This use of MaybeUninit assumes F : Copy. Otherwise undefined behaviour may occur. |
| 49 let mut x : [[MaybeUninit<F>; K]; M] = core::array::from_fn(|_| MaybeUninit::uninit_array::<K>() ); |
53 #[cfg(feature = "nightly")] |
| 50 //unsafe { std::mem::MaybeUninit::uninit().assume_init() }; |
54 { |
| 51 for i in (0..M).rev() { |
55 let mut x : [[MaybeUninit<F>; K]; M] = core::array::from_fn(|_| MaybeUninit::uninit_array::<K>() ); |
| 52 for 𝓁 in 0..K { |
56 //unsafe { std::mem::MaybeUninit::uninit().assume_init() }; |
| 53 let mut tmp = ab[i][M+𝓁]; |
57 for i in (0..M).rev() { |
| 54 for j in (i+1)..M { |
58 for 𝓁 in 0..K { |
| 55 tmp -= ab[i][j] * unsafe { *(x[j][𝓁].assume_init_ref()) }; |
59 let mut tmp = ab[i][M+𝓁]; |
| |
60 for j in (i+1)..M { |
| |
61 tmp -= ab[i][j] * unsafe { *(x[j][𝓁].assume_init_ref()) }; |
| |
62 } |
| |
63 tmp /= ab[i][i]; |
| |
64 x[i][𝓁].write(tmp); |
| 56 } |
65 } |
| 57 tmp /= ab[i][i]; |
66 } |
| 58 x[i][𝓁].write(tmp); |
67 unsafe { |
| |
68 //core::intrinsics::assert_inhabited::<[[F; K]; M]>(); |
| |
69 (&x as *const _ as *const [[F; K]; M]).read() |
| 59 } |
70 } |
| 60 } |
71 } |
| 61 //unsafe { MaybeUninit::array_assume_init(x) }; |
72 #[cfg(not(feature = "nightly"))] |
| 62 let xinit = unsafe { |
73 { |
| 63 //core::intrinsics::assert_inhabited::<[[F; K]; M]>(); |
74 let mut x : [[F; K]; M] = [[F::ZERO; K]; M]; |
| 64 (&x as *const _ as *const [[F; K]; M]).read() |
75 for i in (0..M).rev() { |
| 65 }; |
76 for 𝓁 in 0..K { |
| 66 |
77 let mut tmp = ab[i][M+𝓁]; |
| 67 //std::mem::forget(x); |
78 for j in (i+1)..M { |
| 68 xinit |
79 tmp -= ab[i][j] * x[j][𝓁]; |
| |
80 } |
| |
81 tmp /= ab[i][i]; |
| |
82 x[i][𝓁] = tmp; |
| |
83 } |
| |
84 } |
| |
85 x |
| |
86 } |
| 69 } |
87 } |
| 70 |
88 |
| 71 /// Gaussian elimination for $Ax=b$, where $A$ and $b$ are both stored in `ab`, |
89 /// Gaussian elimination for $Ax=b$, where $A$ and $b$ are both stored in `ab`, |
| 72 /// $A \in \mathbb{R}^{M \times M}$ and $x, b \in \mathbb{R}^M$. |
90 /// $A \in \mathbb{R}^{M \times M}$ and $x, b \in \mathbb{R}^M$. |
| 73 #[inline] |
91 #[inline] |