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

1#[cfg(test)]
2mod test;
3
4#[cfg(test)]
5use super::super::test::ErrorTensor;
6
7use std::{
8    array::from_fn,
9    fmt::{Display, Formatter, Result},
10    ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
11};
12
13use super::{
14    super::{Tensor, TensorArray},
15    TensorRank0, TensorRank2,
16    list::TensorRank2List,
17};
18
19/// A 2D list of *d*-dimensional tensors of rank 2.
20///
21/// `D` is the dimension, `I`, `J` are the configurations, `W` and `X` are the list lengths.
22#[derive(Clone, Debug)]
23pub struct TensorRank2List2D<
24    const D: usize,
25    const I: usize,
26    const J: usize,
27    const W: usize,
28    const X: usize,
29>([TensorRank2List<D, I, J, W>; X]);
30
31impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> Display
32    for TensorRank2List2D<D, I, J, W, X>
33{
34    fn fmt(&self, _f: &mut Formatter) -> Result {
35        Ok(())
36    }
37}
38
39#[cfg(test)]
40impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> ErrorTensor
41    for TensorRank2List2D<D, I, J, W, X>
42{
43    fn error(
44        &self,
45        comparator: &Self,
46        tol_abs: &TensorRank0,
47        tol_rel: &TensorRank0,
48    ) -> Option<usize> {
49        let error_count = self
50            .iter()
51            .zip(comparator.iter())
52            .map(|(self_a, comparator_a)| {
53                self_a
54                    .iter()
55                    .zip(comparator_a.iter())
56                    .map(|(self_ab, comparator_ab)| {
57                        self_ab
58                            .iter()
59                            .zip(comparator_ab.iter())
60                            .map(|(self_ab_i, comparator_ab_i)| {
61                                self_ab_i
62                                    .iter()
63                                    .zip(comparator_ab_i.iter())
64                                    .filter(|&(&self_ab_ij, &comparator_ab_ij)| {
65                                        &(self_ab_ij - comparator_ab_ij).abs() >= tol_abs
66                                            && &(self_ab_ij / comparator_ab_ij - 1.0).abs()
67                                                >= tol_rel
68                                    })
69                                    .count()
70                            })
71                            .sum::<usize>()
72                    })
73                    .sum::<usize>()
74            })
75            .sum();
76        if error_count > 0 {
77            Some(error_count)
78        } else {
79            None
80        }
81    }
82    fn error_fd(&self, comparator: &Self, epsilon: &TensorRank0) -> Option<(bool, usize)> {
83        let error_count = self
84            .iter()
85            .zip(comparator.iter())
86            .map(|(self_a, comparator_a)| {
87                self_a
88                    .iter()
89                    .zip(comparator_a.iter())
90                    .map(|(self_ab, comparator_ab)| {
91                        self_ab
92                            .iter()
93                            .zip(comparator_ab.iter())
94                            .map(|(self_ab_i, comparator_ab_i)| {
95                                self_ab_i
96                                    .iter()
97                                    .zip(comparator_ab_i.iter())
98                                    .filter(|&(&self_ab_ij, &comparator_ab_ij)| {
99                                        &(self_ab_ij / comparator_ab_ij - 1.0).abs() >= epsilon
100                                            && (&self_ab_ij.abs() >= epsilon
101                                                || &comparator_ab_ij.abs() >= epsilon)
102                                    })
103                                    .count()
104                            })
105                            .sum::<usize>()
106                    })
107                    .sum::<usize>()
108            })
109            .sum();
110        if error_count > 0 {
111            let auxillary = self
112                .iter()
113                .zip(comparator.iter())
114                .map(|(self_a, comparator_a)| {
115                    self_a
116                        .iter()
117                        .zip(comparator_a.iter())
118                        .map(|(self_ab, comparator_ab)| {
119                            self_ab
120                                .iter()
121                                .zip(comparator_ab.iter())
122                                .map(|(self_ab_i, comparator_ab_i)| {
123                                    self_ab_i
124                                        .iter()
125                                        .zip(comparator_ab_i.iter())
126                                        .filter(|&(&self_ab_ij, &comparator_ab_ij)| {
127                                            &(self_ab_ij / comparator_ab_ij - 1.0).abs() >= epsilon
128                                                && &(self_ab_ij - comparator_ab_ij).abs() >= epsilon
129                                                && (&self_ab_ij.abs() >= epsilon
130                                                    || &comparator_ab_ij.abs() >= epsilon)
131                                        })
132                                        .count()
133                                })
134                                .sum::<usize>()
135                        })
136                        .sum::<usize>()
137                })
138                .sum::<usize>()
139                > 0;
140            Some((auxillary, error_count))
141        } else {
142            None
143        }
144    }
145}
146
147impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> Tensor
148    for TensorRank2List2D<D, I, J, W, X>
149{
150    type Item = TensorRank2List<D, I, J, W>;
151    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
152        self.0.iter()
153    }
154    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
155        self.0.iter_mut()
156    }
157}
158
159impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> TensorArray
160    for TensorRank2List2D<D, I, J, W, X>
161{
162    type Array = [[[[TensorRank0; D]; D]; W]; X];
163    type Item = TensorRank2List<D, I, J, W>;
164    fn as_array(&self) -> Self::Array {
165        let mut array = [[[[0.0; D]; D]; W]; X];
166        array
167            .iter_mut()
168            .zip(self.iter())
169            .for_each(|(entry_rank_2_list, tensor_rank_2_list)| {
170                *entry_rank_2_list = tensor_rank_2_list.as_array()
171            });
172        array
173    }
174    fn identity() -> Self {
175        Self(from_fn(|_| Self::Item::identity()))
176    }
177    fn new(array: Self::Array) -> Self {
178        array.into_iter().map(Self::Item::new).collect()
179    }
180    fn zero() -> Self {
181        Self(from_fn(|_| Self::Item::zero()))
182    }
183}
184
185impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
186    FromIterator<TensorRank2List<D, I, J, W>> for TensorRank2List2D<D, I, J, W, X>
187{
188    fn from_iter<Ii: IntoIterator<Item = TensorRank2List<D, I, J, W>>>(into_iterator: Ii) -> Self {
189        let mut tensor_rank_2_list_2d = Self::zero();
190        tensor_rank_2_list_2d
191            .iter_mut()
192            .zip(into_iterator)
193            .for_each(|(tensor_rank_2_list, entry)| *tensor_rank_2_list = entry);
194        tensor_rank_2_list_2d
195    }
196}
197
198impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> Index<usize>
199    for TensorRank2List2D<D, I, J, W, X>
200{
201    type Output = TensorRank2List<D, I, J, W>;
202    fn index(&self, index: usize) -> &Self::Output {
203        &self.0[index]
204    }
205}
206
207impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> IndexMut<usize>
208    for TensorRank2List2D<D, I, J, W, X>
209{
210    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
211        &mut self.0[index]
212    }
213}
214
215impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> std::iter::Sum
216    for TensorRank2List2D<D, I, J, W, X>
217{
218    fn sum<Ii>(iter: Ii) -> Self
219    where
220        Ii: Iterator<Item = Self>,
221    {
222        let mut output = TensorRank2List2D::zero();
223        iter.for_each(|item| output += item);
224        output
225    }
226}
227
228impl<const D: usize, const I: usize, const J: usize, const K: usize, const W: usize, const X: usize>
229    Mul<TensorRank2<D, J, K>> for TensorRank2List2D<D, I, J, W, X>
230{
231    type Output = TensorRank2List2D<D, I, K, W, X>;
232    fn mul(self, tensor_rank_2: TensorRank2<D, J, K>) -> Self::Output {
233        self.iter()
234            .map(|self_entry| {
235                self_entry
236                    .iter()
237                    .map(|self_tensor_rank_2| self_tensor_rank_2 * &tensor_rank_2)
238                    .collect()
239            })
240            .collect()
241    }
242}
243
244impl<const D: usize, const I: usize, const J: usize, const K: usize, const W: usize, const X: usize>
245    Mul<&TensorRank2<D, J, K>> for TensorRank2List2D<D, I, J, W, X>
246{
247    type Output = TensorRank2List2D<D, I, K, W, X>;
248    fn mul(self, tensor_rank_2: &TensorRank2<D, J, K>) -> Self::Output {
249        self.iter()
250            .map(|self_entry| {
251                self_entry
252                    .iter()
253                    .map(|self_tensor_rank_2| self_tensor_rank_2 * tensor_rank_2)
254                    .collect()
255            })
256            .collect()
257    }
258}
259
260impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> Add
261    for TensorRank2List2D<D, I, J, W, X>
262{
263    type Output = Self;
264    fn add(mut self, tensor_rank_2_list_2d: Self) -> Self::Output {
265        self += tensor_rank_2_list_2d;
266        self
267    }
268}
269
270impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> Add<&Self>
271    for TensorRank2List2D<D, I, J, W, X>
272{
273    type Output = Self;
274    fn add(mut self, tensor_rank_2_list_2d: &Self) -> Self::Output {
275        self += tensor_rank_2_list_2d;
276        self
277    }
278}
279
280impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> AddAssign
281    for TensorRank2List2D<D, I, J, W, X>
282{
283    fn add_assign(&mut self, tensor_rank_2_list_2d: Self) {
284        self.iter_mut()
285            .zip(tensor_rank_2_list_2d.iter())
286            .for_each(|(self_entry, tensor_rank_2_list)| *self_entry += tensor_rank_2_list);
287    }
288}
289
290impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
291    AddAssign<&Self> for TensorRank2List2D<D, I, J, W, X>
292{
293    fn add_assign(&mut self, tensor_rank_2_list_2d: &Self) {
294        self.iter_mut()
295            .zip(tensor_rank_2_list_2d.iter())
296            .for_each(|(self_entry, tensor_rank_2_list)| *self_entry += tensor_rank_2_list);
297    }
298}
299
300impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
301    Div<TensorRank0> for TensorRank2List2D<D, I, J, W, X>
302{
303    type Output = Self;
304    fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
305        self /= &tensor_rank_0;
306        self
307    }
308}
309
310impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
311    Div<&TensorRank0> for TensorRank2List2D<D, I, J, W, X>
312{
313    type Output = Self;
314    fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
315        self /= tensor_rank_0;
316        self
317    }
318}
319
320impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
321    DivAssign<TensorRank0> for TensorRank2List2D<D, I, J, W, X>
322{
323    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
324        self.iter_mut().for_each(|entry| *entry /= &tensor_rank_0);
325    }
326}
327
328impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
329    DivAssign<&TensorRank0> for TensorRank2List2D<D, I, J, W, X>
330{
331    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
332        self.iter_mut().for_each(|entry| *entry /= tensor_rank_0);
333    }
334}
335
336impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
337    Mul<TensorRank0> for TensorRank2List2D<D, I, J, W, X>
338{
339    type Output = Self;
340    fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
341        self *= &tensor_rank_0;
342        self
343    }
344}
345
346impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
347    Mul<&TensorRank0> for TensorRank2List2D<D, I, J, W, X>
348{
349    type Output = Self;
350    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
351        self *= tensor_rank_0;
352        self
353    }
354}
355
356impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
357    MulAssign<TensorRank0> for TensorRank2List2D<D, I, J, W, X>
358{
359    fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
360        self.iter_mut().for_each(|entry| *entry *= &tensor_rank_0);
361    }
362}
363
364impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
365    MulAssign<&TensorRank0> for TensorRank2List2D<D, I, J, W, X>
366{
367    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
368        self.iter_mut().for_each(|entry| *entry *= tensor_rank_0);
369    }
370}
371
372impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> Sub
373    for TensorRank2List2D<D, I, J, W, X>
374{
375    type Output = Self;
376    fn sub(mut self, tensor_rank_2_list_2d: Self) -> Self::Output {
377        self -= tensor_rank_2_list_2d;
378        self
379    }
380}
381
382impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> Sub<&Self>
383    for TensorRank2List2D<D, I, J, W, X>
384{
385    type Output = Self;
386    fn sub(mut self, tensor_rank_2_list_2d: &Self) -> Self::Output {
387        self -= tensor_rank_2_list_2d;
388        self
389    }
390}
391
392impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize> SubAssign
393    for TensorRank2List2D<D, I, J, W, X>
394{
395    fn sub_assign(&mut self, tensor_rank_2_list_2d: Self) {
396        self.iter_mut()
397            .zip(tensor_rank_2_list_2d.iter())
398            .for_each(|(self_entry, tensor_rank_2_list)| *self_entry -= tensor_rank_2_list);
399    }
400}
401
402impl<const D: usize, const I: usize, const J: usize, const W: usize, const X: usize>
403    SubAssign<&Self> for TensorRank2List2D<D, I, J, W, X>
404{
405    fn sub_assign(&mut self, tensor_rank_2_list_2d: &Self) {
406        self.iter_mut()
407            .zip(tensor_rank_2_list_2d.iter())
408            .for_each(|(self_entry, tensor_rank_2_list)| *self_entry -= tensor_rank_2_list);
409    }
410}