Skip to main content

conspire/math/tensor/rank_2/list_2d/
mod.rs

1#[cfg(test)]
2mod test;
3
4use crate::math::{Tensor, TensorRank0, TensorRank2, TensorRank2List, tensor::list::TensorList};
5use std::ops::Mul;
6
7use crate::math::assert::FiniteDifference;
8
9/// A list of lists of rank-2 tensors.
10pub type TensorRank2List2D<
11    const D: usize,
12    const I: usize,
13    const J: usize,
14    const M: usize,
15    const N: usize,
16> = TensorList<TensorRank2List<D, I, J, M>, N>;
17
18impl<const D: usize, const I: usize, const J: usize, const M: usize, const N: usize>
19    From<[[[[TensorRank0; D]; D]; M]; N]> for TensorRank2List2D<D, I, J, M, N>
20{
21    fn from(array: [[[[TensorRank0; D]; D]; M]; N]) -> Self {
22        array.into_iter().map(|entry| entry.into()).collect()
23    }
24}
25
26impl<const D: usize, const I: usize, const J: usize, const K: usize, const W: usize, const X: usize>
27    Mul<TensorRank2<D, J, K>> for TensorRank2List2D<D, I, J, W, X>
28{
29    type Output = TensorRank2List2D<D, I, K, W, X>;
30    fn mul(self, tensor_rank_2: TensorRank2<D, J, K>) -> Self::Output {
31        self.iter()
32            .map(|self_entry| {
33                self_entry
34                    .iter()
35                    .map(|self_tensor_rank_2| self_tensor_rank_2 * &tensor_rank_2)
36                    .collect()
37            })
38            .collect()
39    }
40}
41
42impl<const D: usize, const I: usize, const J: usize, const K: usize, const W: usize, const X: usize>
43    Mul<&TensorRank2<D, J, K>> for TensorRank2List2D<D, I, J, W, X>
44{
45    type Output = TensorRank2List2D<D, I, K, W, X>;
46    fn mul(self, tensor_rank_2: &TensorRank2<D, J, K>) -> Self::Output {
47        self.iter()
48            .map(|self_entry| {
49                self_entry
50                    .iter()
51                    .map(|self_tensor_rank_2| self_tensor_rank_2 * tensor_rank_2)
52                    .collect()
53            })
54            .collect()
55    }
56}
57
58impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
59    FiniteDifference for TensorRank2List2D<D, I, J, W, X>
60{
61    fn error_fd(&self, comparator: &Self, epsilon: TensorRank0) -> Option<(bool, usize)> {
62        let error_count = self
63            .iter()
64            .zip(comparator.iter())
65            .map(|(self_a, comparator_a)| {
66                self_a
67                    .iter()
68                    .zip(comparator_a.iter())
69                    .map(|(self_ab, comparator_ab)| {
70                        self_ab
71                            .iter()
72                            .zip(comparator_ab.iter())
73                            .map(|(self_ab_i, comparator_ab_i)| {
74                                self_ab_i
75                                    .iter()
76                                    .zip(comparator_ab_i.iter())
77                                    .filter(|&(&self_ab_ij, &comparator_ab_ij)| {
78                                        ((self_ab_ij / comparator_ab_ij - 1.0).abs() >= epsilon
79                                            && (self_ab_ij.abs() >= epsilon
80                                                || comparator_ab_ij.abs() >= epsilon))
81                                            || self_ab_ij.is_nan()
82                                            || comparator_ab_ij.is_nan()
83                                    })
84                                    .count()
85                            })
86                            .sum::<usize>()
87                    })
88                    .sum::<usize>()
89            })
90            .sum();
91        if error_count > 0 {
92            let auxiliary = self
93                .iter()
94                .zip(comparator.iter())
95                .map(|(self_a, comparator_a)| {
96                    self_a
97                        .iter()
98                        .zip(comparator_a.iter())
99                        .map(|(self_ab, comparator_ab)| {
100                            self_ab
101                                .iter()
102                                .zip(comparator_ab.iter())
103                                .map(|(self_ab_i, comparator_ab_i)| {
104                                    self_ab_i
105                                        .iter()
106                                        .zip(comparator_ab_i.iter())
107                                        .filter(|&(&self_ab_ij, &comparator_ab_ij)| {
108                                            ((self_ab_ij / comparator_ab_ij - 1.0).abs() >= epsilon
109                                                && (self_ab_ij - comparator_ab_ij).abs() >= epsilon
110                                                && (self_ab_ij.abs() >= epsilon
111                                                    || comparator_ab_ij.abs() >= epsilon))
112                                                || self_ab_ij.is_nan()
113                                                || comparator_ab_ij.is_nan()
114                                        })
115                                        .count()
116                                })
117                                .sum::<usize>()
118                        })
119                        .sum::<usize>()
120                })
121                .sum::<usize>()
122                > 0;
123            Some((auxiliary, error_count))
124        } else {
125            None
126        }
127    }
128}