Skip to main content

conspire/math/tensor/rank_2/
mod.rs

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