1#[cfg(test)]
2mod test;
3
4pub mod list;
5pub mod list_2d;
6pub mod vec;
7pub mod vec_2d;
8
9use std::{
10 array::from_fn,
11 fmt,
12 mem::transmute,
13 ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
14};
15
16use super::{
17 super::write_tensor_rank_0,
18 Hessian, Jacobian, Rank2, Solution, SquareMatrix, Tensor, TensorArray, Vector,
19 rank_0::TensorRank0,
20 rank_1::{
21 TensorRank1, list::TensorRank1List, tensor_rank_1, vec::TensorRank1Vec,
22 zero as tensor_rank_1_zero,
23 },
24 rank_4::TensorRank4,
25 test::ErrorTensor,
26};
27use crate::ABS_TOL;
28use list_2d::TensorRank2List2D;
29use vec_2d::TensorRank2Vec2D;
30
31#[derive(Clone, Debug, PartialEq)]
35pub struct TensorRank2<const D: usize, const I: usize, const J: usize>([TensorRank1<D, J>; D]);
36
37pub const fn tensor_rank_2<const D: usize, const I: usize, const J: usize>(
38 array: [TensorRank1<D, J>; D],
39) -> TensorRank2<D, I, J> {
40 TensorRank2(array)
41}
42
43pub const fn get_levi_civita_parts<const I: usize, const J: usize>() -> [TensorRank2<3, I, J>; 3] {
44 [
45 TensorRank2([
46 tensor_rank_1_zero(),
47 tensor_rank_1([0.0, 0.0, 1.0]),
48 tensor_rank_1([0.0, -1.0, 0.0]),
49 ]),
50 TensorRank2([
51 tensor_rank_1([0.0, 0.0, -1.0]),
52 tensor_rank_1_zero(),
53 tensor_rank_1([1.0, 0.0, 0.0]),
54 ]),
55 TensorRank2([
56 tensor_rank_1([0.0, 1.0, 0.0]),
57 tensor_rank_1([-1.0, 0.0, 0.0]),
58 tensor_rank_1_zero(),
59 ]),
60 ]
61}
62
63pub const fn get_identity_1010_parts_1<const I: usize, const J: usize>() -> [TensorRank2<3, I, J>; 3]
64{
65 [
66 TensorRank2([
67 tensor_rank_1([1.0, 0.0, 0.0]),
68 tensor_rank_1_zero(),
69 tensor_rank_1_zero(),
70 ]),
71 TensorRank2([
72 tensor_rank_1([0.0, 1.0, 0.0]),
73 tensor_rank_1_zero(),
74 tensor_rank_1_zero(),
75 ]),
76 TensorRank2([
77 tensor_rank_1([0.0, 0.0, 1.0]),
78 tensor_rank_1_zero(),
79 tensor_rank_1_zero(),
80 ]),
81 ]
82}
83
84pub const fn get_identity_1010_parts_2<const I: usize, const J: usize>() -> [TensorRank2<3, I, J>; 3]
85{
86 [
87 TensorRank2([
88 tensor_rank_1_zero(),
89 tensor_rank_1([1.0, 0.0, 0.0]),
90 tensor_rank_1_zero(),
91 ]),
92 TensorRank2([
93 tensor_rank_1_zero(),
94 tensor_rank_1([0.0, 1.0, 0.0]),
95 tensor_rank_1_zero(),
96 ]),
97 TensorRank2([
98 tensor_rank_1_zero(),
99 tensor_rank_1([0.0, 0.0, 1.0]),
100 tensor_rank_1_zero(),
101 ]),
102 ]
103}
104
105pub const fn get_identity_1010_parts_3<const I: usize, const J: usize>() -> [TensorRank2<3, I, J>; 3]
106{
107 [
108 TensorRank2([
109 tensor_rank_1_zero(),
110 tensor_rank_1_zero(),
111 tensor_rank_1([1.0, 0.0, 0.0]),
112 ]),
113 TensorRank2([
114 tensor_rank_1_zero(),
115 tensor_rank_1_zero(),
116 tensor_rank_1([0.0, 1.0, 0.0]),
117 ]),
118 TensorRank2([
119 tensor_rank_1_zero(),
120 tensor_rank_1_zero(),
121 tensor_rank_1([0.0, 0.0, 1.0]),
122 ]),
123 ]
124}
125
126pub const IDENTITY: TensorRank2<3, 1, 1> = TensorRank2([
127 tensor_rank_1([1.0, 0.0, 0.0]),
128 tensor_rank_1([0.0, 1.0, 0.0]),
129 tensor_rank_1([0.0, 0.0, 1.0]),
130]);
131
132pub const IDENTITY_00: TensorRank2<3, 0, 0> = TensorRank2([
133 tensor_rank_1([1.0, 0.0, 0.0]),
134 tensor_rank_1([0.0, 1.0, 0.0]),
135 tensor_rank_1([0.0, 0.0, 1.0]),
136]);
137
138pub const IDENTITY_10: TensorRank2<3, 1, 0> = TensorRank2([
139 tensor_rank_1([1.0, 0.0, 0.0]),
140 tensor_rank_1([0.0, 1.0, 0.0]),
141 tensor_rank_1([0.0, 0.0, 1.0]),
142]);
143
144pub const ZERO: TensorRank2<3, 1, 1> = TensorRank2([
145 tensor_rank_1_zero(),
146 tensor_rank_1_zero(),
147 tensor_rank_1_zero(),
148]);
149
150pub const ZERO_10: TensorRank2<3, 1, 0> = TensorRank2([
151 tensor_rank_1_zero(),
152 tensor_rank_1_zero(),
153 tensor_rank_1_zero(),
154]);
155
156impl<const D: usize, const I: usize, const J: usize> From<Vec<Vec<TensorRank0>>>
157 for TensorRank2<D, I, J>
158{
159 fn from(vec: Vec<Vec<TensorRank0>>) -> Self {
160 assert_eq!(vec.len(), D);
161 vec.iter().for_each(|entry| assert_eq!(entry.len(), D));
162 vec.into_iter()
163 .map(|entry| entry.into_iter().collect())
164 .collect()
165 }
166}
167
168impl<const D: usize, const I: usize, const J: usize> From<TensorRank2<D, I, J>>
169 for Vec<Vec<TensorRank0>>
170{
171 fn from(tensor: TensorRank2<D, I, J>) -> Self {
172 tensor
173 .iter()
174 .map(|entry| entry.iter().copied().collect())
175 .collect()
176 }
177}
178
179impl<const D: usize, const I: usize, const J: usize> fmt::Display for TensorRank2<D, I, J> {
180 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181 write!(f, "\x1B[s")?;
182 write!(f, "[[")?;
183 self.iter().enumerate().try_for_each(|(i, row)| {
184 row.iter()
185 .try_for_each(|entry| write_tensor_rank_0(f, entry))?;
186 if i + 1 < D {
187 writeln!(f, "\x1B[2D],")?;
188 write!(f, "\x1B[u")?;
189 write!(f, "\x1B[{}B [", i + 1)?;
190 }
191 Ok(())
192 })?;
193 write!(f, "\x1B[2D]]")
194 }
195}
196
197impl<const D: usize, const I: usize, const J: usize> ErrorTensor for TensorRank2<D, I, J> {
198 fn error(
199 &self,
200 comparator: &Self,
201 tol_abs: &TensorRank0,
202 tol_rel: &TensorRank0,
203 ) -> Option<usize> {
204 let error_count = self
205 .iter()
206 .zip(comparator.iter())
207 .map(|(self_i, comparator_i)| {
208 self_i
209 .iter()
210 .zip(comparator_i.iter())
211 .filter(|&(&self_ij, &comparator_ij)| {
212 &(self_ij - comparator_ij).abs() >= tol_abs
213 && &(self_ij / comparator_ij - 1.0).abs() >= tol_rel
214 })
215 .count()
216 })
217 .sum();
218 if error_count > 0 {
219 Some(error_count)
220 } else {
221 None
222 }
223 }
224 fn error_fd(&self, comparator: &Self, epsilon: &TensorRank0) -> Option<(bool, usize)> {
225 let error_count = self
226 .iter()
227 .zip(comparator.iter())
228 .map(|(self_i, comparator_i)| {
229 self_i
230 .iter()
231 .zip(comparator_i.iter())
232 .filter(|&(&self_ij, &comparator_ij)| {
233 &(self_ij / comparator_ij - 1.0).abs() >= epsilon
234 && (&self_ij.abs() >= epsilon || &comparator_ij.abs() >= epsilon)
235 })
236 .count()
237 })
238 .sum();
239 if error_count > 0 {
240 Some((true, error_count))
241 } else {
242 None
243 }
244 }
245}
246
247impl<const D: usize, const I: usize, const J: usize> TensorRank2<D, I, J> {
248 pub fn as_tensor_rank_1(&self) -> TensorRank1<9, 88> {
250 assert_eq!(D, 3);
251 let mut tensor_rank_1 = TensorRank1::<9, 88>::zero();
252 self.iter().enumerate().for_each(|(i, self_i)| {
253 self_i
254 .iter()
255 .enumerate()
256 .for_each(|(j, self_ij)| tensor_rank_1[3 * i + j] = *self_ij)
257 });
258 tensor_rank_1
259 }
260 pub fn determinant(&self) -> TensorRank0 {
262 if D == 2 {
263 self[0][0] * self[1][1] - self[0][1] * self[1][0]
264 } else if D == 3 {
265 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
266 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
267 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
268 self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20
269 } else if D == 4 {
270 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
271 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
272 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
273 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
274 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
275 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
276 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
277 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
278 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
279 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
280 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
281 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
282 s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0
283 } else {
284 let (tensor_l, tensor_u) = self.lu_decomposition();
285 tensor_l
286 .iter()
287 .enumerate()
288 .zip(tensor_u.iter())
289 .map(|((i, tensor_l_i), tensor_u_i)| tensor_l_i[i] * tensor_u_i[i])
290 .product()
291 }
292 }
293 pub fn dyad(vector_a: &TensorRank1<D, I>, vector_b: &TensorRank1<D, J>) -> Self {
295 vector_a
296 .iter()
297 .map(|vector_a_i| {
298 vector_b
299 .iter()
300 .map(|vector_b_j| vector_a_i * vector_b_j)
301 .collect()
302 })
303 .collect()
304 }
305 pub fn inverse(&self) -> TensorRank2<D, J, I> {
307 if D == 2 {
308 let mut adjugate = TensorRank2::<D, J, I>::zero();
309 adjugate[0][0] = self[1][1];
310 adjugate[0][1] = -self[0][1];
311 adjugate[1][0] = -self[1][0];
312 adjugate[1][1] = self[0][0];
313 adjugate / self.determinant()
314 } else if D == 3 {
315 let mut adjugate = TensorRank2::<D, J, I>::zero();
316 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
317 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
318 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
319 adjugate[0][0] = c_00;
320 adjugate[0][1] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
321 adjugate[0][2] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
322 adjugate[1][0] = c_10;
323 adjugate[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
324 adjugate[1][2] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
325 adjugate[2][0] = c_20;
326 adjugate[2][1] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
327 adjugate[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
328 adjugate / (self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20)
329 } else if D == 4 {
330 let mut adjugate = TensorRank2::<D, J, I>::zero();
331 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
332 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
333 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
334 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
335 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
336 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
337 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
338 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
339 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
340 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
341 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
342 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
343 adjugate[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
344 adjugate[0][1] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
345 adjugate[0][2] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
346 adjugate[0][3] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
347 adjugate[1][0] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
348 adjugate[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
349 adjugate[1][2] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
350 adjugate[1][3] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
351 adjugate[2][0] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
352 adjugate[2][1] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
353 adjugate[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
354 adjugate[2][3] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
355 adjugate[3][0] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
356 adjugate[3][1] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
357 adjugate[3][2] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
358 adjugate[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
359 adjugate / (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0)
360 } else {
361 let (tensor_l_inverse, tensor_u_inverse) = self.lu_decomposition_inverse();
362 tensor_u_inverse * tensor_l_inverse
363 }
364 }
365 pub fn inverse_and_determinant(&self) -> (TensorRank2<D, J, I>, TensorRank0) {
367 if D == 2 {
368 let mut adjugate = TensorRank2::<D, J, I>::zero();
369 adjugate[0][0] = self[1][1];
370 adjugate[0][1] = -self[0][1];
371 adjugate[1][0] = -self[1][0];
372 adjugate[1][1] = self[0][0];
373 let determinant = self.determinant();
374 (adjugate / determinant, determinant)
375 } else if D == 3 {
376 let mut adjugate = TensorRank2::<D, J, I>::zero();
377 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
378 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
379 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
380 let determinant = self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20;
381 adjugate[0][0] = c_00;
382 adjugate[0][1] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
383 adjugate[0][2] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
384 adjugate[1][0] = c_10;
385 adjugate[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
386 adjugate[1][2] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
387 adjugate[2][0] = c_20;
388 adjugate[2][1] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
389 adjugate[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
390 (adjugate / determinant, determinant)
391 } else if D == 4 {
392 let mut adjugate = TensorRank2::<D, J, I>::zero();
393 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
394 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
395 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
396 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
397 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
398 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
399 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
400 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
401 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
402 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
403 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
404 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
405 let determinant = s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0;
406 adjugate[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
407 adjugate[0][1] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
408 adjugate[0][2] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
409 adjugate[0][3] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
410 adjugate[1][0] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
411 adjugate[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
412 adjugate[1][2] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
413 adjugate[1][3] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
414 adjugate[2][0] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
415 adjugate[2][1] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
416 adjugate[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
417 adjugate[2][3] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
418 adjugate[3][0] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
419 adjugate[3][1] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
420 adjugate[3][2] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
421 adjugate[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
422 (adjugate / determinant, determinant)
423 } else {
424 panic!()
425 }
426 }
427 pub fn inverse_transpose(&self) -> Self {
429 if D == 2 {
430 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
431 adjugate_transpose[0][0] = self[1][1];
432 adjugate_transpose[0][1] = -self[1][0];
433 adjugate_transpose[1][0] = -self[0][1];
434 adjugate_transpose[1][1] = self[0][0];
435 adjugate_transpose / self.determinant()
436 } else if D == 3 {
437 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
438 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
439 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
440 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
441 adjugate_transpose[0][0] = c_00;
442 adjugate_transpose[1][0] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
443 adjugate_transpose[2][0] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
444 adjugate_transpose[0][1] = c_10;
445 adjugate_transpose[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
446 adjugate_transpose[2][1] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
447 adjugate_transpose[0][2] = c_20;
448 adjugate_transpose[1][2] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
449 adjugate_transpose[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
450 adjugate_transpose / (self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20)
451 } else if D == 4 {
452 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
453 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
454 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
455 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
456 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
457 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
458 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
459 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
460 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
461 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
462 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
463 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
464 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
465 adjugate_transpose[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
466 adjugate_transpose[1][0] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
467 adjugate_transpose[2][0] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
468 adjugate_transpose[3][0] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
469 adjugate_transpose[0][1] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
470 adjugate_transpose[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
471 adjugate_transpose[2][1] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
472 adjugate_transpose[3][1] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
473 adjugate_transpose[0][2] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
474 adjugate_transpose[1][2] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
475 adjugate_transpose[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
476 adjugate_transpose[3][2] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
477 adjugate_transpose[0][3] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
478 adjugate_transpose[1][3] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
479 adjugate_transpose[2][3] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
480 adjugate_transpose[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
481 adjugate_transpose / (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0)
482 } else {
483 self.inverse().transpose()
484 }
485 }
486 pub fn inverse_transpose_and_determinant(&self) -> (Self, TensorRank0) {
488 if D == 2 {
489 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
490 adjugate_transpose[0][0] = self[1][1];
491 adjugate_transpose[0][1] = -self[1][0];
492 adjugate_transpose[1][0] = -self[0][1];
493 adjugate_transpose[1][1] = self[0][0];
494 let determinant = self.determinant();
495 (adjugate_transpose / determinant, determinant)
496 } else if D == 3 {
497 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
498 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
499 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
500 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
501 let determinant = self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20;
502 adjugate_transpose[0][0] = c_00;
503 adjugate_transpose[1][0] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
504 adjugate_transpose[2][0] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
505 adjugate_transpose[0][1] = c_10;
506 adjugate_transpose[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
507 adjugate_transpose[2][1] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
508 adjugate_transpose[0][2] = c_20;
509 adjugate_transpose[1][2] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
510 adjugate_transpose[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
511 (adjugate_transpose / determinant, determinant)
512 } else if D == 4 {
513 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
514 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
515 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
516 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
517 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
518 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
519 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
520 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
521 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
522 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
523 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
524 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
525 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
526 let determinant = s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0;
527 adjugate_transpose[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
528 adjugate_transpose[1][0] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
529 adjugate_transpose[2][0] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
530 adjugate_transpose[3][0] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
531 adjugate_transpose[0][1] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
532 adjugate_transpose[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
533 adjugate_transpose[2][1] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
534 adjugate_transpose[3][1] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
535 adjugate_transpose[0][2] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
536 adjugate_transpose[1][2] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
537 adjugate_transpose[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
538 adjugate_transpose[3][2] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
539 adjugate_transpose[0][3] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
540 adjugate_transpose[1][3] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
541 adjugate_transpose[2][3] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
542 adjugate_transpose[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
543 (adjugate_transpose / determinant, determinant)
544 } else {
545 panic!()
546 }
547 }
548 pub fn lu_decomposition(&self) -> (TensorRank2<D, I, 88>, TensorRank2<D, 88, J>) {
550 let mut tensor_l = TensorRank2::zero();
551 let mut tensor_u = TensorRank2::zero();
552 for i in 0..D {
553 for k in i..D {
554 tensor_u[i][k] = self[i][k];
555 for j in 0..i {
556 tensor_u[i][k] -= tensor_l[i][j] * tensor_u[j][k];
557 }
558 }
559 if tensor_u[i][i].abs() <= ABS_TOL {
560 panic!("LU decomposition failed (zero pivot).")
561 }
562 for k in i..D {
563 if i == k {
564 tensor_l[i][k] = 1.0
565 } else {
566 tensor_l[k][i] = self[k][i];
567 for j in 0..i {
568 tensor_l[k][i] -= tensor_l[k][j] * tensor_u[j][i];
569 }
570 tensor_l[k][i] /= tensor_u[i][i]
571 }
572 }
573 }
574 (tensor_l, tensor_u)
575 }
576 pub fn lu_decomposition_inverse(&self) -> (TensorRank2<D, 88, I>, TensorRank2<D, J, 88>) {
578 let mut tensor_l = TensorRank2::zero();
579 let mut tensor_u = TensorRank2::zero();
580 for i in 0..D {
581 for k in i..D {
582 tensor_u[i][k] = self[i][k];
583 for j in 0..i {
584 tensor_u[i][k] -= tensor_l[i][j] * tensor_u[j][k];
585 }
586 }
587 if tensor_u[i][i].abs() <= ABS_TOL {
588 panic!("LU decomposition failed (zero pivot).")
589 }
590 for k in i..D {
591 if i == k {
592 tensor_l[i][k] = 1.0
593 } else {
594 tensor_l[k][i] = self[k][i];
595 for j in 0..i {
596 tensor_l[k][i] -= tensor_l[k][j] * tensor_u[j][i];
597 }
598 tensor_l[k][i] /= tensor_u[i][i]
599 }
600 }
601 }
602 let mut sum;
606 for i in 0..D {
607 tensor_l[i][i] = 1.0 / tensor_l[i][i];
608 for j in 0..i {
609 sum = 0.0;
610 for k in j..i {
611 sum += tensor_l[i][k] * tensor_l[k][j];
612 }
613 tensor_l[i][j] = -sum * tensor_l[i][i];
614 }
615 }
616 for i in 0..D {
617 tensor_u[i][i] = 1.0 / tensor_u[i][i];
618 for j in 0..i {
619 sum = 0.0;
620 for k in j..i {
621 sum += tensor_u[j][k] * tensor_u[k][i];
622 }
623 tensor_u[j][i] = -sum * tensor_u[i][i];
624 }
625 }
626 (tensor_l, tensor_u)
627 }
628}
629
630impl<const D: usize, const I: usize, const J: usize> Hessian for TensorRank2<D, I, J> {
631 fn fill_into(self, square_matrix: &mut SquareMatrix) {
632 self.into_iter().enumerate().for_each(|(i, self_i)| {
633 self_i
634 .into_iter()
635 .enumerate()
636 .for_each(|(j, self_ij)| square_matrix[i][j] = self_ij)
637 })
638 }
639}
640
641impl<const D: usize, const I: usize, const J: usize> Rank2 for TensorRank2<D, I, J> {
642 type Transpose = TensorRank2<D, J, I>;
643 fn deviatoric(&self) -> Self {
644 Self::identity() * (self.trace() / -(D as TensorRank0)) + self
645 }
646 fn deviatoric_and_trace(&self) -> (Self, TensorRank0) {
647 let trace = self.trace();
648 (
649 Self::identity() * (trace / -(D as TensorRank0)) + self,
650 trace,
651 )
652 }
653 fn is_diagonal(&self) -> bool {
654 self.iter()
655 .enumerate()
656 .map(|(i, self_i)| {
657 self_i
658 .iter()
659 .enumerate()
660 .map(|(j, self_ij)| (self_ij.abs() < ABS_TOL) as u8 * (i != j) as u8)
661 .sum::<u8>()
662 })
663 .sum::<u8>()
664 == (D.pow(2) - D) as u8
665 }
666 fn is_identity(&self) -> bool {
667 self.iter()
668 .enumerate()
669 .map(|(i, self_i)| {
670 self_i
671 .iter()
672 .enumerate()
673 .map(|(j, self_ij)| (self_ij == &((i == j) as u8 as TensorRank0)) as u8)
674 .sum::<u8>()
675 })
676 .sum::<u8>()
677 == D.pow(2) as u8
678 }
679 fn squared_trace(&self) -> TensorRank0 {
680 self.iter()
681 .enumerate()
682 .map(|(i, self_i)| {
683 self_i
684 .iter()
685 .zip(self.iter())
686 .map(|(self_ij, self_j)| self_ij * self_j[i])
687 .sum::<TensorRank0>()
688 })
689 .sum()
690 }
691 fn trace(&self) -> TensorRank0 {
692 self.iter().enumerate().map(|(i, self_i)| self_i[i]).sum()
693 }
694 fn transpose(&self) -> Self::Transpose {
695 (0..D)
696 .map(|i| (0..D).map(|j| self[j][i]).collect())
697 .collect()
699 }
700}
701
702impl<const D: usize, const I: usize, const J: usize> Tensor for TensorRank2<D, I, J> {
703 type Item = TensorRank1<D, J>;
704 fn iter(&self) -> impl Iterator<Item = &Self::Item> {
705 self.0.iter()
706 }
707 fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
708 self.0.iter_mut()
709 }
710 fn norm_inf(&self) -> TensorRank0 {
711 self.iter()
712 .map(|tensor_rank_1| {
713 tensor_rank_1
714 .iter()
715 .fold(0.0, |acc, entry| entry.abs().max(acc))
716 })
717 .reduce(TensorRank0::max)
718 .unwrap()
719 }
720 fn num_entries(&self) -> usize {
721 D * D
722 }
723}
724
725impl<const D: usize, const I: usize, const J: usize> IntoIterator for TensorRank2<D, I, J> {
726 type Item = TensorRank1<D, J>;
727 type IntoIter = std::array::IntoIter<Self::Item, D>;
728 fn into_iter(self) -> Self::IntoIter {
729 self.0.into_iter()
730 }
731}
732
733impl<const D: usize, const I: usize, const J: usize> TensorArray for TensorRank2<D, I, J> {
734 type Array = [[TensorRank0; D]; D];
735 type Item = TensorRank1<D, J>;
736 fn as_array(&self) -> Self::Array {
737 let mut array = [[0.0; D]; D];
738 array
739 .iter_mut()
740 .zip(self.iter())
741 .for_each(|(entry, tensor_rank_1)| *entry = tensor_rank_1.as_array());
742 array
743 }
744 fn identity() -> Self {
745 (0..D)
746 .map(|i| (0..D).map(|j| ((i == j) as u8) as TensorRank0).collect())
747 .collect()
748 }
749 fn new(array: Self::Array) -> Self {
750 array.into_iter().map(Self::Item::new).collect()
751 }
752 fn zero() -> Self {
753 Self(from_fn(|_| Self::Item::zero()))
754 }
755}
756
757impl<const D: usize, const I: usize, const J: usize> Solution for TensorRank2<D, I, J> {
758 fn decrement_from_chained(&mut self, other: &mut Vector, vector: Vector) {
759 self.iter_mut()
760 .flat_map(|x| x.iter_mut())
761 .chain(other.iter_mut())
762 .zip(vector)
763 .for_each(|(entry_i, vector_i)| *entry_i -= vector_i)
764 }
765}
766
767impl<const D: usize, const I: usize, const J: usize> Jacobian for TensorRank2<D, I, J> {
768 fn fill_into(self, vector: &mut Vector) {
769 self.into_iter()
770 .flatten()
771 .zip(vector.iter_mut())
772 .for_each(|(self_i, vector_i)| *vector_i = self_i)
773 }
774 fn fill_into_chained(self, other: Vector, vector: &mut Vector) {
775 self.into_iter()
776 .flatten()
777 .chain(other)
778 .zip(vector.iter_mut())
779 .for_each(|(self_i, vector_i)| *vector_i = self_i)
780 }
781}
782
783impl<const D: usize, const I: usize, const J: usize> Sub<Vector> for TensorRank2<D, I, J> {
784 type Output = Self;
785 fn sub(mut self, vector: Vector) -> Self::Output {
786 self.iter_mut().enumerate().for_each(|(i, self_i)| {
787 self_i
788 .iter_mut()
789 .enumerate()
790 .for_each(|(j, self_ij)| *self_ij -= vector[D * i + j])
791 });
792 self
793 }
794}
795
796impl<const D: usize, const I: usize, const J: usize> Sub<&Vector> for TensorRank2<D, I, J> {
797 type Output = Self;
798 fn sub(mut self, vector: &Vector) -> Self::Output {
799 self.iter_mut().enumerate().for_each(|(i, self_i)| {
800 self_i
801 .iter_mut()
802 .enumerate()
803 .for_each(|(j, self_ij)| *self_ij -= vector[D * i + j])
804 });
805 self
806 }
807}
808
809impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
810 From<TensorRank4<D, I, J, K, L>> for TensorRank2<9, 88, 99>
811{
812 fn from(tensor_rank_4: TensorRank4<D, I, J, K, L>) -> Self {
813 assert_eq!(D, 3);
814 tensor_rank_4
815 .into_iter()
816 .flatten()
817 .map(|entry_ij| entry_ij.into_iter().flatten().collect())
818 .collect()
819 }
820}
821
822impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
823 From<&TensorRank4<D, I, J, K, L>> for TensorRank2<9, 88, 99>
824{
825 fn from(tensor_rank_4: &TensorRank4<D, I, J, K, L>) -> Self {
826 assert_eq!(D, 3);
827 tensor_rank_4
828 .clone()
829 .into_iter()
830 .flatten()
831 .map(|entry_ij| entry_ij.into_iter().flatten().collect())
832 .collect()
833 }
834}
835
836impl From<TensorRank2<3, 0, 0>> for TensorRank2<3, 1, 0> {
837 fn from(tensor_rank_2: TensorRank2<3, 0, 0>) -> Self {
838 unsafe { transmute::<TensorRank2<3, 0, 0>, TensorRank2<3, 1, 0>>(tensor_rank_2) }
839 }
840}
841
842impl From<TensorRank2<3, 0, 0>> for TensorRank2<3, 1, 1> {
843 fn from(tensor_rank_2: TensorRank2<3, 0, 0>) -> Self {
844 unsafe { transmute::<TensorRank2<3, 0, 0>, TensorRank2<3, 1, 1>>(tensor_rank_2) }
845 }
846}
847
848impl From<TensorRank2<3, 0, 1>> for TensorRank2<3, 0, 0> {
849 fn from(tensor_rank_2: TensorRank2<3, 0, 1>) -> Self {
850 unsafe { transmute::<TensorRank2<3, 0, 1>, TensorRank2<3, 0, 0>>(tensor_rank_2) }
851 }
852}
853
854impl From<TensorRank2<3, 1, 0>> for TensorRank2<3, 0, 0> {
855 fn from(tensor_rank_2: TensorRank2<3, 1, 0>) -> Self {
856 unsafe { transmute::<TensorRank2<3, 1, 0>, TensorRank2<3, 0, 0>>(tensor_rank_2) }
857 }
858}
859
860impl From<TensorRank2<3, 1, 1>> for TensorRank2<3, 1, 0> {
861 fn from(tensor_rank_2: TensorRank2<3, 1, 1>) -> Self {
862 unsafe { transmute::<TensorRank2<3, 1, 1>, TensorRank2<3, 1, 0>>(tensor_rank_2) }
863 }
864}
865
866impl From<TensorRank2<3, 1, 2>> for TensorRank2<3, 1, 0> {
867 fn from(tensor_rank_2: TensorRank2<3, 1, 2>) -> Self {
868 unsafe { transmute::<TensorRank2<3, 1, 2>, TensorRank2<3, 1, 0>>(tensor_rank_2) }
869 }
870}
871
872impl<const D: usize, const I: usize, const J: usize> FromIterator<TensorRank1<D, J>>
873 for TensorRank2<D, I, J>
874{
875 fn from_iter<Ii: IntoIterator<Item = TensorRank1<D, J>>>(into_iterator: Ii) -> Self {
876 let mut tensor_rank_2 = Self::zero();
877 tensor_rank_2
878 .iter_mut()
879 .zip(into_iterator)
880 .for_each(|(tensor_rank_2_i, value_i)| *tensor_rank_2_i = value_i);
881 tensor_rank_2
882 }
883}
884
885impl<const D: usize, const I: usize, const J: usize> Index<usize> for TensorRank2<D, I, J> {
886 type Output = TensorRank1<D, J>;
887 fn index(&self, index: usize) -> &Self::Output {
888 &self.0[index]
889 }
890}
891
892impl<const D: usize, const I: usize, const J: usize> IndexMut<usize> for TensorRank2<D, I, J> {
893 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
894 &mut self.0[index]
895 }
896}
897
898impl<const D: usize, const I: usize, const J: usize> std::iter::Sum for TensorRank2<D, I, J> {
899 fn sum<Ii>(iter: Ii) -> Self
900 where
901 Ii: Iterator<Item = Self>,
902 {
903 let mut output = Self::zero();
904 iter.for_each(|item| output += item);
905 output
906 }
907}
908
909impl<const D: usize, const I: usize, const J: usize> Div<TensorRank0> for TensorRank2<D, I, J> {
910 type Output = Self;
911 fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
912 self /= &tensor_rank_0;
913 self
914 }
915}
916
917impl<const D: usize, const I: usize, const J: usize> Div<TensorRank0> for &TensorRank2<D, I, J> {
918 type Output = TensorRank2<D, I, J>;
919 fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
920 self.iter().map(|self_i| self_i / tensor_rank_0).collect()
921 }
922}
923
924impl<const D: usize, const I: usize, const J: usize> Div<&TensorRank0> for TensorRank2<D, I, J> {
925 type Output = Self;
926 fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
927 self /= tensor_rank_0;
928 self
929 }
930}
931
932impl<const D: usize, const I: usize, const J: usize> Div<&TensorRank0> for &TensorRank2<D, I, J> {
933 type Output = TensorRank2<D, I, J>;
934 fn div(self, tensor_rank_0: &TensorRank0) -> Self::Output {
935 self.iter().map(|self_i| self_i / tensor_rank_0).collect()
936 }
937}
938
939impl<const D: usize, const I: usize, const J: usize> DivAssign<TensorRank0>
940 for TensorRank2<D, I, J>
941{
942 fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
943 self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
944 }
945}
946
947impl<const D: usize, const I: usize, const J: usize> DivAssign<&TensorRank0>
948 for TensorRank2<D, I, J>
949{
950 fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
951 self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
952 }
953}
954
955impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank0> for TensorRank2<D, I, J> {
956 type Output = Self;
957 fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
958 self *= &tensor_rank_0;
959 self
960 }
961}
962
963impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank0> for &TensorRank2<D, I, J> {
964 type Output = TensorRank2<D, I, J>;
965 fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
966 self.iter().map(|self_i| self_i * tensor_rank_0).collect()
967 }
968}
969
970impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank0> for TensorRank2<D, I, J> {
971 type Output = Self;
972 fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
973 self *= tensor_rank_0;
974 self
975 }
976}
977
978impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank0> for &TensorRank2<D, I, J> {
979 type Output = TensorRank2<D, I, J>;
980 fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
981 self.iter().map(|self_i| self_i * tensor_rank_0).collect()
982 }
983}
984
985impl<const D: usize, const I: usize, const J: usize> MulAssign<TensorRank0>
986 for TensorRank2<D, I, J>
987{
988 fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
989 self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
990 }
991}
992
993impl<const D: usize, const I: usize, const J: usize> MulAssign<&TensorRank0>
994 for TensorRank2<D, I, J>
995{
996 fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
997 self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
998 }
999}
1000
1001impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank1<D, J>>
1002 for TensorRank2<D, I, J>
1003{
1004 type Output = TensorRank1<D, I>;
1005 fn mul(self, tensor_rank_1: TensorRank1<D, J>) -> Self::Output {
1006 self.iter().map(|self_i| self_i * &tensor_rank_1).collect()
1007 }
1008}
1009
1010impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank1<D, J>>
1011 for TensorRank2<D, I, J>
1012{
1013 type Output = TensorRank1<D, I>;
1014 fn mul(self, tensor_rank_1: &TensorRank1<D, J>) -> Self::Output {
1015 self.iter().map(|self_i| self_i * tensor_rank_1).collect()
1016 }
1017}
1018
1019impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank1<D, J>>
1020 for &TensorRank2<D, I, J>
1021{
1022 type Output = TensorRank1<D, I>;
1023 fn mul(self, tensor_rank_1: TensorRank1<D, J>) -> Self::Output {
1024 self.iter().map(|self_i| self_i * &tensor_rank_1).collect()
1025 }
1026}
1027
1028impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank1<D, J>>
1029 for &TensorRank2<D, I, J>
1030{
1031 type Output = TensorRank1<D, I>;
1032 fn mul(self, tensor_rank_1: &TensorRank1<D, J>) -> Self::Output {
1033 self.iter().map(|self_i| self_i * tensor_rank_1).collect()
1034 }
1035}
1036
1037impl<const D: usize, const I: usize, const J: usize> Add for TensorRank2<D, I, J> {
1038 type Output = Self;
1039 fn add(mut self, tensor_rank_2: Self) -> Self::Output {
1040 self += tensor_rank_2;
1041 self
1042 }
1043}
1044
1045impl<const D: usize, const I: usize, const J: usize> Add<&Self> for TensorRank2<D, I, J> {
1046 type Output = Self;
1047 fn add(mut self, tensor_rank_2: &Self) -> Self::Output {
1048 self += tensor_rank_2;
1049 self
1050 }
1051}
1052
1053impl<const D: usize, const I: usize, const J: usize> Add<TensorRank2<D, I, J>>
1054 for &TensorRank2<D, I, J>
1055{
1056 type Output = TensorRank2<D, I, J>;
1057 fn add(self, mut tensor_rank_2: TensorRank2<D, I, J>) -> Self::Output {
1058 tensor_rank_2 += self;
1059 tensor_rank_2
1060 }
1061}
1062
1063impl<const D: usize, const I: usize, const J: usize> AddAssign for TensorRank2<D, I, J> {
1064 fn add_assign(&mut self, tensor_rank_2: Self) {
1065 self.iter_mut()
1066 .zip(tensor_rank_2.iter())
1067 .for_each(|(self_i, tensor_rank_2_i)| *self_i += tensor_rank_2_i);
1068 }
1069}
1070
1071impl<const D: usize, const I: usize, const J: usize> AddAssign<&Self> for TensorRank2<D, I, J> {
1072 fn add_assign(&mut self, tensor_rank_2: &Self) {
1073 self.iter_mut()
1074 .zip(tensor_rank_2.iter())
1075 .for_each(|(self_i, tensor_rank_2_i)| *self_i += tensor_rank_2_i);
1076 }
1077}
1078
1079impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank2<D, J, K>>
1080 for TensorRank2<D, I, J>
1081{
1082 type Output = TensorRank2<D, I, K>;
1083 fn mul(self, tensor_rank_2: TensorRank2<D, J, K>) -> Self::Output {
1084 self.iter()
1085 .map(|self_i| {
1086 self_i
1087 .iter()
1088 .zip(tensor_rank_2.iter())
1089 .map(|(self_ij, tensor_rank_2_j)| tensor_rank_2_j * self_ij)
1090 .sum()
1091 })
1092 .collect()
1093 }
1094}
1095
1096impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<&TensorRank2<D, J, K>>
1097 for TensorRank2<D, I, J>
1098{
1099 type Output = TensorRank2<D, I, K>;
1100 fn mul(self, tensor_rank_2: &TensorRank2<D, J, K>) -> Self::Output {
1101 self.iter()
1102 .map(|self_i| {
1103 self_i
1104 .iter()
1105 .zip(tensor_rank_2.iter())
1106 .map(|(self_ij, tensor_rank_2_j)| tensor_rank_2_j * self_ij)
1107 .sum()
1108 })
1109 .collect()
1110 }
1111}
1112
1113impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank2<D, J, K>>
1114 for &TensorRank2<D, I, J>
1115{
1116 type Output = TensorRank2<D, I, K>;
1117 fn mul(self, tensor_rank_2: TensorRank2<D, J, K>) -> Self::Output {
1118 self.iter()
1119 .map(|self_i| {
1120 self_i
1121 .iter()
1122 .zip(tensor_rank_2.iter())
1123 .map(|(self_ij, tensor_rank_2_j)| tensor_rank_2_j * self_ij)
1124 .sum()
1125 })
1126 .collect()
1127 }
1128}
1129
1130impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<&TensorRank2<D, J, K>>
1131 for &TensorRank2<D, I, J>
1132{
1133 type Output = TensorRank2<D, I, K>;
1134 fn mul(self, tensor_rank_2: &TensorRank2<D, J, K>) -> Self::Output {
1135 self.iter()
1136 .map(|self_i| {
1137 self_i
1138 .iter()
1139 .zip(tensor_rank_2.iter())
1140 .map(|(self_ij, tensor_rank_2_j)| tensor_rank_2_j * self_ij)
1141 .sum()
1142 })
1143 .collect()
1144 }
1145}
1146
1147impl<const D: usize, const I: usize, const J: usize> Sub for TensorRank2<D, I, J> {
1148 type Output = Self;
1149 fn sub(mut self, tensor_rank_2: Self) -> Self::Output {
1150 self -= tensor_rank_2;
1151 self
1152 }
1153}
1154
1155impl<const D: usize, const I: usize, const J: usize> Sub<&Self> for TensorRank2<D, I, J> {
1156 type Output = Self;
1157 fn sub(mut self, tensor_rank_2: &Self) -> Self::Output {
1158 self -= tensor_rank_2;
1159 self
1160 }
1161}
1162
1163impl<const D: usize, const I: usize, const J: usize> Sub for &TensorRank2<D, I, J> {
1164 type Output = TensorRank2<D, I, J>;
1165 fn sub(self, tensor_rank_2: Self) -> Self::Output {
1166 let mut output = self.clone();
1167 output -= tensor_rank_2;
1168 output
1169 }
1170}
1171
1172impl<const D: usize, const I: usize, const J: usize> SubAssign for TensorRank2<D, I, J> {
1173 fn sub_assign(&mut self, tensor_rank_2: Self) {
1174 self.iter_mut()
1175 .zip(tensor_rank_2.iter())
1176 .for_each(|(self_i, tensor_rank_2_i)| *self_i -= tensor_rank_2_i);
1177 }
1178}
1179
1180impl<const D: usize, const I: usize, const J: usize> SubAssign<&Self> for TensorRank2<D, I, J> {
1181 fn sub_assign(&mut self, tensor_rank_2: &Self) {
1182 self.iter_mut()
1183 .zip(tensor_rank_2.iter())
1184 .for_each(|(self_i, tensor_rank_2_i)| *self_i -= tensor_rank_2_i);
1185 }
1186}
1187
1188impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<TensorRank1List<D, J, W>>
1189 for TensorRank2<D, I, J>
1190{
1191 type Output = TensorRank1List<D, I, W>;
1192 fn mul(self, tensor_rank_1_list: TensorRank1List<D, J, W>) -> Self::Output {
1193 tensor_rank_1_list
1194 .iter()
1195 .map(|tensor_rank_1| &self * tensor_rank_1)
1196 .collect()
1197 }
1198}
1199
1200impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<&TensorRank1List<D, J, W>>
1201 for TensorRank2<D, I, J>
1202{
1203 type Output = TensorRank1List<D, I, W>;
1204 fn mul(self, tensor_rank_1_list: &TensorRank1List<D, J, W>) -> Self::Output {
1205 tensor_rank_1_list
1206 .iter()
1207 .map(|tensor_rank_1| &self * tensor_rank_1)
1208 .collect()
1209 }
1210}
1211
1212impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<TensorRank1List<D, J, W>>
1213 for &TensorRank2<D, I, J>
1214{
1215 type Output = TensorRank1List<D, I, W>;
1216 fn mul(self, tensor_rank_1_list: TensorRank1List<D, J, W>) -> Self::Output {
1217 tensor_rank_1_list
1218 .iter()
1219 .map(|tensor_rank_1| self * tensor_rank_1)
1220 .collect()
1221 }
1222}
1223
1224impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<&TensorRank1List<D, J, W>>
1225 for &TensorRank2<D, I, J>
1226{
1227 type Output = TensorRank1List<D, I, W>;
1228 fn mul(self, tensor_rank_1_list: &TensorRank1List<D, J, W>) -> Self::Output {
1229 tensor_rank_1_list
1230 .iter()
1231 .map(|tensor_rank_1| self * tensor_rank_1)
1232 .collect()
1233 }
1234}
1235
1236impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank1Vec<D, J>>
1237 for TensorRank2<D, I, J>
1238{
1239 type Output = TensorRank1Vec<D, I>;
1240 fn mul(self, tensor_rank_1_vec: TensorRank1Vec<D, J>) -> Self::Output {
1241 tensor_rank_1_vec
1242 .iter()
1243 .map(|tensor_rank_1| &self * tensor_rank_1)
1244 .collect()
1245 }
1246}
1247
1248impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank1Vec<D, J>>
1249 for TensorRank2<D, I, J>
1250{
1251 type Output = TensorRank1Vec<D, I>;
1252 fn mul(self, tensor_rank_1_vec: &TensorRank1Vec<D, J>) -> Self::Output {
1253 tensor_rank_1_vec
1254 .iter()
1255 .map(|tensor_rank_1| &self * tensor_rank_1)
1256 .collect()
1257 }
1258}
1259
1260impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank1Vec<D, J>>
1261 for &TensorRank2<D, I, J>
1262{
1263 type Output = TensorRank1Vec<D, I>;
1264 fn mul(self, tensor_rank_1_vec: TensorRank1Vec<D, J>) -> Self::Output {
1265 tensor_rank_1_vec
1266 .iter()
1267 .map(|tensor_rank_1| self * tensor_rank_1)
1268 .collect()
1269 }
1270}
1271
1272impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank1Vec<D, J>>
1273 for &TensorRank2<D, I, J>
1274{
1275 type Output = TensorRank1Vec<D, I>;
1276 fn mul(self, tensor_rank_1_vec: &TensorRank1Vec<D, J>) -> Self::Output {
1277 tensor_rank_1_vec
1278 .iter()
1279 .map(|tensor_rank_1| self * tensor_rank_1)
1280 .collect()
1281 }
1282}
1283
1284impl<const D: usize, const I: usize, const J: usize, const K: usize, const W: usize, const X: usize>
1285 Mul<TensorRank2List2D<D, J, K, W, X>> for TensorRank2<D, I, J>
1286{
1287 type Output = TensorRank2List2D<D, I, K, W, X>;
1288 fn mul(self, tensor_rank_2_list_2d: TensorRank2List2D<D, J, K, W, X>) -> Self::Output {
1289 tensor_rank_2_list_2d
1290 .iter()
1291 .map(|tensor_rank_2_list_2d_entry| {
1292 tensor_rank_2_list_2d_entry
1293 .iter()
1294 .map(|tensor_rank_2| &self * tensor_rank_2)
1295 .collect()
1296 })
1297 .collect()
1298 }
1299}
1300
1301impl<const D: usize, const I: usize, const J: usize, const K: usize, const W: usize, const X: usize>
1302 Mul<TensorRank2List2D<D, J, K, W, X>> for &TensorRank2<D, I, J>
1303{
1304 type Output = TensorRank2List2D<D, I, K, W, X>;
1305 fn mul(self, tensor_rank_2_list_2d: TensorRank2List2D<D, J, K, W, X>) -> Self::Output {
1306 tensor_rank_2_list_2d
1307 .iter()
1308 .map(|tensor_rank_2_list_2d_entry| {
1309 tensor_rank_2_list_2d_entry
1310 .iter()
1311 .map(|tensor_rank_2| self * tensor_rank_2)
1312 .collect()
1313 })
1314 .collect()
1315 }
1316}
1317
1318impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank2Vec2D<D, J, K>>
1319 for TensorRank2<D, I, J>
1320{
1321 type Output = TensorRank2Vec2D<D, I, K>;
1322 fn mul(self, tensor_rank_2_list_2d: TensorRank2Vec2D<D, J, K>) -> Self::Output {
1323 tensor_rank_2_list_2d
1324 .iter()
1325 .map(|tensor_rank_2_list_2d_entry| {
1326 tensor_rank_2_list_2d_entry
1327 .iter()
1328 .map(|tensor_rank_2| &self * tensor_rank_2)
1329 .collect()
1330 })
1331 .collect()
1332 }
1333}
1334
1335impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank2Vec2D<D, J, K>>
1336 for &TensorRank2<D, I, J>
1337{
1338 type Output = TensorRank2Vec2D<D, I, K>;
1339 fn mul(self, tensor_rank_2_list_2d: TensorRank2Vec2D<D, J, K>) -> Self::Output {
1340 tensor_rank_2_list_2d
1341 .iter()
1342 .map(|tensor_rank_2_list_2d_entry| {
1343 tensor_rank_2_list_2d_entry
1344 .iter()
1345 .map(|tensor_rank_2| self * tensor_rank_2)
1346 .collect()
1347 })
1348 .collect()
1349 }
1350}
1351
1352#[allow(clippy::suspicious_arithmetic_impl)]
1353impl<const I: usize, const J: usize, const K: usize, const L: usize> Div<TensorRank4<3, I, J, K, L>>
1354 for &TensorRank2<3, I, J>
1355{
1356 type Output = TensorRank2<3, K, L>;
1357 fn div(self, tensor_rank_4: TensorRank4<3, I, J, K, L>) -> Self::Output {
1358 let tensor_rank_2: TensorRank2<9, 88, 99> = tensor_rank_4.into();
1359 let output_tensor_rank_1 = tensor_rank_2.inverse() * self.as_tensor_rank_1();
1360 let mut output = TensorRank2::zero();
1361 output.iter_mut().enumerate().for_each(|(i, output_i)| {
1362 output_i
1363 .iter_mut()
1364 .enumerate()
1365 .for_each(|(j, output_ij)| *output_ij = output_tensor_rank_1[3 * i + j])
1366 });
1367 output
1368 }
1369}