conspire/math/tensor/rank_2/
mod.rs

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/// A *d*-dimensional tensor of rank 2.
32///
33/// `D` is the dimension, `I`, `J` are the configurations.
34#[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    /// Returns the rank-2 tensor reshaped as a rank-1 tensor.
249    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    /// Returns the determinant of the rank-2 tensor.
261    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    /// Returns a rank-2 tensor constructed from a dyad of the given vectors.
294    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    /// Returns the inverse of the rank-2 tensor.
306    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    /// Returns the inverse and determinant of the rank-2 tensor.
366    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    /// Returns the inverse transpose of the rank-2 tensor.
428    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    /// Returns the inverse transpose and determinant of the rank-2 tensor.
487    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    /// Returns the LU decomposition of the rank-2 tensor.
549    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    /// Returns the inverse of the LU decomposition of the rank-2 tensor.
577    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        //
603        // above is copied from lu_decomposition
604        //
605        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            // .map(|i| self.iter().map(|self_j| self_j[i]).collect())
698            .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}