conspire/math/tensor/rank_2/inverse/
mod.rs1#[cfg(test)]
2mod test;
3use crate::math::{Factor, Reference};
4use crate::units::{Dimensionless, UnitInv};
5
6use super::{Quantity, Rank2, Tensor, TensorArray, TensorRank0, TensorRank2, relabel};
7use crate::ABS_TOL;
8
9type LuFactors<const D: usize, I, J, U> = (
11 TensorRank2<D, I, Factor, U>,
12 TensorRank2<D, Factor, J, U>,
13 Vec<usize>,
14);
15
16type Inverse<U> = <U as UnitInv>::Output;
18
19impl<const D: usize, I, J, U> TensorRank2<D, I, J, U> {
20 pub fn determinant(&self) -> TensorRank0 {
22 self.canonical().determinant_core()
23 }
24 pub fn inverse(&self) -> TensorRank2<D, J, I, Inverse<U>>
26 where
27 U: UnitInv,
28 {
29 relabel(self.canonical().inverse_core())
30 }
31 pub fn inverse_and_determinant(&self) -> (TensorRank2<D, J, I, Inverse<U>>, TensorRank0)
33 where
34 U: UnitInv,
35 {
36 let (inverse, determinant) = self.canonical().inverse_and_determinant_core();
37 (relabel(inverse), determinant)
38 }
39 pub fn inverse_transpose(&self) -> TensorRank2<D, I, J, Inverse<U>>
41 where
42 U: UnitInv,
43 {
44 relabel(self.canonical().inverse_transpose_core())
45 }
46 pub fn inverse_transpose_and_determinant(
48 &self,
49 ) -> (TensorRank2<D, I, J, Inverse<U>>, TensorRank0)
50 where
51 U: UnitInv,
52 {
53 let (inverse_transpose, determinant) =
54 self.canonical().inverse_transpose_and_determinant_core();
55 (relabel(inverse_transpose), determinant)
56 }
57 pub fn lu_decomposition(&self) -> LuFactors<D, I, J, U> {
59 let (tensor_l, tensor_u, p) = self.canonical().lu_decomposition_core();
60 (relabel(tensor_l), relabel(tensor_u), p)
61 }
62 pub fn lu_decomposition_inverse(&self) -> LuFactors<D, I, J, U> {
64 let (tensor_l, tensor_u, p) = self.canonical().lu_decomposition_inverse_core();
65 (relabel(tensor_l), relabel(tensor_u), p)
66 }
67}
68
69impl<const D: usize> TensorRank2<D, Reference, Reference, Dimensionless> {
70 fn determinant_core(&self) -> TensorRank0 {
71 if D == 2 {
72 (self[0][0] * self[1][1] - self[0][1] * self[1][0]).value()
73 } else if D == 3 {
74 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
75 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
76 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
77 (self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20).value()
78 } else if D == 4 {
79 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
80 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
81 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
82 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
83 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
84 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
85 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
86 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
87 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
88 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
89 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
90 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
91 (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0).value()
92 } else {
93 let (_, u, p) = self.lu_decomposition_core();
94 let num_swaps = p.iter().enumerate().filter(|(i, p_i)| p_i != &i).count();
95 u.into_iter()
96 .enumerate()
97 .map(|(i, u_i)| u_i[i].value())
98 .product::<TensorRank0>()
99 * if num_swaps % 2 == 0 { 1.0 } else { -1.0 }
100 }
101 }
102 fn inverse_core(&self) -> Self {
103 if D == 2 {
104 let mut adjugate = Self::zero();
105 adjugate[0][0] = self[1][1];
106 adjugate[0][1] = -self[0][1];
107 adjugate[1][0] = -self[1][0];
108 adjugate[1][1] = self[0][0];
109 adjugate / self.determinant_core()
110 } else if D == 3 {
111 let mut adjugate = Self::zero();
112 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
113 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
114 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
115 adjugate[0][0] = c_00;
116 adjugate[0][1] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
117 adjugate[0][2] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
118 adjugate[1][0] = c_10;
119 adjugate[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
120 adjugate[1][2] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
121 adjugate[2][0] = c_20;
122 adjugate[2][1] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
123 adjugate[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
124 adjugate / (self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20)
125 } else if D == 4 {
126 let mut adjugate = Self::zero();
127 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
128 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
129 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
130 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
131 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
132 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
133 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
134 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
135 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
136 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
137 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
138 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
139 adjugate[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
140 adjugate[0][1] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
141 adjugate[0][2] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
142 adjugate[0][3] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
143 adjugate[1][0] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
144 adjugate[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
145 adjugate[1][2] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
146 adjugate[1][3] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
147 adjugate[2][0] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
148 adjugate[2][1] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
149 adjugate[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
150 adjugate[2][3] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
151 adjugate[3][0] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
152 adjugate[3][1] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
153 adjugate[3][2] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
154 adjugate[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
155 adjugate / (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0)
156 } else {
157 let (l_inverse, u_inverse, p) = self.lu_decomposition_inverse_core();
158 let mut q = [0; D];
159 p.into_iter().enumerate().for_each(|(i, p_i)| q[p_i] = i);
160 u_inverse
161 .into_iter()
162 .map(|u_inverse_i| {
163 q.iter()
164 .map(|&q_j| {
165 u_inverse_i
166 .iter()
167 .zip(l_inverse.iter())
168 .map(|(u_inverse_ik, l_inverse_k)| u_inverse_ik * l_inverse_k[q_j])
169 .sum::<Quantity>()
170 })
171 .collect()
172 })
173 .collect()
174 }
175 }
176 fn inverse_and_determinant_core(&self) -> (Self, TensorRank0) {
177 if D == 2 {
178 let mut adjugate = Self::zero();
179 adjugate[0][0] = self[1][1];
180 adjugate[0][1] = -self[0][1];
181 adjugate[1][0] = -self[1][0];
182 adjugate[1][1] = self[0][0];
183 let determinant = self.determinant_core();
184 (adjugate / determinant, determinant)
185 } else if D == 3 {
186 let mut adjugate = Self::zero();
187 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
188 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
189 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
190 let determinant = (self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20).value();
191 adjugate[0][0] = c_00;
192 adjugate[0][1] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
193 adjugate[0][2] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
194 adjugate[1][0] = c_10;
195 adjugate[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
196 adjugate[1][2] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
197 adjugate[2][0] = c_20;
198 adjugate[2][1] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
199 adjugate[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
200 (adjugate / determinant, determinant)
201 } else if D == 4 {
202 let mut adjugate = Self::zero();
203 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
204 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
205 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
206 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
207 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
208 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
209 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
210 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
211 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
212 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
213 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
214 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
215 let determinant = (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0).value();
216 adjugate[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
217 adjugate[0][1] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
218 adjugate[0][2] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
219 adjugate[0][3] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
220 adjugate[1][0] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
221 adjugate[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
222 adjugate[1][2] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
223 adjugate[1][3] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
224 adjugate[2][0] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
225 adjugate[2][1] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
226 adjugate[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
227 adjugate[2][3] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
228 adjugate[3][0] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
229 adjugate[3][1] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
230 adjugate[3][2] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
231 adjugate[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
232 (adjugate / determinant, determinant)
233 } else {
234 (self.inverse_core(), self.determinant_core())
235 }
236 }
237 fn inverse_transpose_core(&self) -> Self {
238 if D == 2 {
239 let mut adjugate_transpose = Self::zero();
240 adjugate_transpose[0][0] = self[1][1];
241 adjugate_transpose[0][1] = -self[1][0];
242 adjugate_transpose[1][0] = -self[0][1];
243 adjugate_transpose[1][1] = self[0][0];
244 adjugate_transpose / self.determinant_core()
245 } else if D == 3 {
246 let mut adjugate_transpose = Self::zero();
247 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
248 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
249 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
250 adjugate_transpose[0][0] = c_00;
251 adjugate_transpose[1][0] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
252 adjugate_transpose[2][0] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
253 adjugate_transpose[0][1] = c_10;
254 adjugate_transpose[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
255 adjugate_transpose[2][1] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
256 adjugate_transpose[0][2] = c_20;
257 adjugate_transpose[1][2] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
258 adjugate_transpose[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
259 adjugate_transpose / (self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20)
260 } else if D == 4 {
261 let mut adjugate_transpose = Self::zero();
262 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
263 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
264 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
265 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
266 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
267 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
268 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
269 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
270 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
271 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
272 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
273 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
274 adjugate_transpose[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
275 adjugate_transpose[1][0] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
276 adjugate_transpose[2][0] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
277 adjugate_transpose[3][0] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
278 adjugate_transpose[0][1] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
279 adjugate_transpose[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
280 adjugate_transpose[2][1] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
281 adjugate_transpose[3][1] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
282 adjugate_transpose[0][2] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
283 adjugate_transpose[1][2] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
284 adjugate_transpose[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
285 adjugate_transpose[3][2] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
286 adjugate_transpose[0][3] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
287 adjugate_transpose[1][3] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
288 adjugate_transpose[2][3] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
289 adjugate_transpose[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
290 adjugate_transpose / (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0)
291 } else {
292 self.inverse_core().transpose()
293 }
294 }
295 fn inverse_transpose_and_determinant_core(&self) -> (Self, TensorRank0) {
296 if D == 2 {
297 let mut adjugate_transpose = Self::zero();
298 adjugate_transpose[0][0] = self[1][1];
299 adjugate_transpose[0][1] = -self[1][0];
300 adjugate_transpose[1][0] = -self[0][1];
301 adjugate_transpose[1][1] = self[0][0];
302 let determinant = self.determinant_core();
303 (adjugate_transpose / determinant, determinant)
304 } else if D == 3 {
305 let mut adjugate_transpose = Self::zero();
306 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
307 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
308 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
309 let determinant = (self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20).value();
310 adjugate_transpose[0][0] = c_00;
311 adjugate_transpose[1][0] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
312 adjugate_transpose[2][0] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
313 adjugate_transpose[0][1] = c_10;
314 adjugate_transpose[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
315 adjugate_transpose[2][1] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
316 adjugate_transpose[0][2] = c_20;
317 adjugate_transpose[1][2] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
318 adjugate_transpose[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
319 (adjugate_transpose / determinant, determinant)
320 } else if D == 4 {
321 let mut adjugate_transpose = Self::zero();
322 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
323 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
324 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
325 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
326 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
327 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
328 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
329 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
330 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
331 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
332 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
333 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
334 let determinant = (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0).value();
335 adjugate_transpose[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
336 adjugate_transpose[1][0] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
337 adjugate_transpose[2][0] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
338 adjugate_transpose[3][0] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
339 adjugate_transpose[0][1] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
340 adjugate_transpose[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
341 adjugate_transpose[2][1] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
342 adjugate_transpose[3][1] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
343 adjugate_transpose[0][2] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
344 adjugate_transpose[1][2] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
345 adjugate_transpose[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
346 adjugate_transpose[3][2] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
347 adjugate_transpose[0][3] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
348 adjugate_transpose[1][3] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
349 adjugate_transpose[2][3] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
350 adjugate_transpose[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
351 (adjugate_transpose / determinant, determinant)
352 } else {
353 (self.inverse_transpose_core(), self.determinant_core())
354 }
355 }
356 fn lu_decomposition_core(&self) -> (Self, Self, Vec<usize>) {
357 let n = D;
358 let mut p: Vec<usize> = (0..n).collect();
359 let mut factor;
360 let mut lu = self.clone();
361 let mut max_row;
362 let mut max_val;
363 let mut pivot;
364 for i in 0..n {
365 max_row = i;
366 max_val = lu[max_row][i].abs();
367 for k in i + 1..n {
368 if lu[k][i].abs() > max_val {
369 max_row = k;
370 max_val = lu[max_row][i].abs();
371 }
372 }
373 if max_row != i {
374 lu.0.swap(i, max_row);
375 p.swap(i, max_row);
376 }
377 pivot = lu[i][i];
378 if pivot.abs() < ABS_TOL {
379 panic!("LU decomposition failed (zero pivot).")
380 }
381 for j in i + 1..n {
382 if lu[j][i] != 0.0 {
383 lu[j][i] = lu[j][i] / pivot;
384 factor = lu[j][i];
385 for k in i + 1..n {
386 let update = factor * lu[i][k];
387 lu[j][k] -= update;
388 }
389 }
390 }
391 }
392 let mut l = TensorRank2::identity();
393 for i in 0..D {
394 for j in 0..i {
395 l[i][j] = lu[i][j]
396 }
397 }
398 let mut u = TensorRank2::zero();
399 for i in 0..D {
400 for j in i..D {
401 u[i][j] = lu[i][j]
402 }
403 }
404 (l, u, p)
405 }
406 fn lu_decomposition_inverse_core(&self) -> (Self, Self, Vec<usize>) {
407 let (mut tensor_l, mut tensor_u, p) = self.lu_decomposition_core();
408 let mut sum: Quantity;
409 for i in 0..D {
410 tensor_l[i][i] = 1.0 / tensor_l[i][i];
411 for j in 0..i {
412 sum = Quantity::new(0.0);
413 for k in j..i {
414 sum += tensor_l[i][k] * tensor_l[k][j];
415 }
416 tensor_l[i][j] = -sum * tensor_l[i][i];
417 }
418 }
419 for i in 0..D {
420 tensor_u[i][i] = 1.0 / tensor_u[i][i];
421 for j in 0..i {
422 sum = Quantity::new(0.0);
423 for k in j..i {
424 sum += tensor_u[j][k] * tensor_u[k][i];
425 }
426 tensor_u[j][i] = -sum * tensor_u[i][i];
427 }
428 }
429 (tensor_l, tensor_u, p)
430 }
431}