conspire/math/tensor/rank_2/list/
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::{Tensor, TensorArray, TensorRank0, TensorRank2};
14
15/// A list of *d*-dimensional tensors of rank 2.
16///
17/// `D` is the dimension, `I`, `J` are the configurations `W` is the list length.
18#[derive(Clone, Debug)]
19pub struct TensorRank2List<const D: usize, const I: usize, const J: usize, const W: usize>(
20    [TensorRank2<D, I, J>; W],
21);
22
23pub const fn tensor_rank_2_list<const D: usize, const I: usize, const J: usize, const W: usize>(
24    array: [TensorRank2<D, I, J>; W],
25) -> TensorRank2List<D, I, J, W> {
26    TensorRank2List(array)
27}
28
29impl<const D: usize, const I: usize, const J: usize, const W: usize> Display
30    for TensorRank2List<D, I, J, W>
31{
32    fn fmt(&self, _f: &mut Formatter) -> Result {
33        Ok(())
34    }
35}
36
37#[cfg(test)]
38impl<const D: usize, const I: usize, const J: usize, const W: usize> ErrorTensor
39    for TensorRank2List<D, I, J, W>
40{
41    fn error(
42        &self,
43        comparator: &Self,
44        tol_abs: &TensorRank0,
45        tol_rel: &TensorRank0,
46    ) -> Option<usize> {
47        let error_count = self
48            .iter()
49            .zip(comparator.iter())
50            .map(|(self_a, comparator_a)| {
51                self_a
52                    .iter()
53                    .zip(comparator_a.iter())
54                    .map(|(self_a_i, comparator_a_i)| {
55                        self_a_i
56                            .iter()
57                            .zip(comparator_a_i.iter())
58                            .filter(|&(&self_a_ij, &comparator_a_ij)| {
59                                &(self_a_ij - comparator_a_ij).abs() >= tol_abs
60                                    && &(self_a_ij / comparator_a_ij - 1.0).abs() >= tol_rel
61                            })
62                            .count()
63                    })
64                    .sum::<usize>()
65            })
66            .sum();
67        if error_count > 0 {
68            Some(error_count)
69        } else {
70            None
71        }
72    }
73    fn error_fd(&self, comparator: &Self, epsilon: &TensorRank0) -> Option<(bool, usize)> {
74        let error_count = self
75            .iter()
76            .zip(comparator.iter())
77            .map(|(self_a, comparator_a)| {
78                self_a
79                    .iter()
80                    .zip(comparator_a.iter())
81                    .map(|(self_a_i, comparator_a_i)| {
82                        self_a_i
83                            .iter()
84                            .zip(comparator_a_i.iter())
85                            .filter(|&(&self_a_ij, &comparator_a_ij)| {
86                                &(self_a_ij / comparator_a_ij - 1.0).abs() >= epsilon
87                                    && (&self_a_ij.abs() >= epsilon
88                                        || &comparator_a_ij.abs() >= epsilon)
89                            })
90                            .count()
91                    })
92                    .sum::<usize>()
93            })
94            .sum();
95        if error_count > 0 {
96            Some((true, error_count))
97        } else {
98            None
99        }
100    }
101}
102
103impl<const D: usize, const I: usize, const J: usize, const W: usize> Tensor
104    for TensorRank2List<D, I, J, W>
105{
106    type Item = TensorRank2<D, I, J>;
107    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
108        self.0.iter()
109    }
110    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
111        self.0.iter_mut()
112    }
113}
114
115impl<const D: usize, const I: usize, const J: usize, const W: usize> TensorArray
116    for TensorRank2List<D, I, J, W>
117{
118    type Array = [[[TensorRank0; D]; D]; W];
119    type Item = TensorRank2<D, I, J>;
120    fn as_array(&self) -> Self::Array {
121        let mut array = [[[0.0; D]; D]; W];
122        array
123            .iter_mut()
124            .zip(self.iter())
125            .for_each(|(entry_rank_2, tensor_rank_2)| *entry_rank_2 = tensor_rank_2.as_array());
126        array
127    }
128    fn identity() -> Self {
129        Self(from_fn(|_| Self::Item::identity()))
130    }
131    fn new(array: Self::Array) -> Self {
132        array.into_iter().map(TensorRank2::new).collect()
133    }
134    fn zero() -> Self {
135        Self(from_fn(|_| TensorRank2::zero()))
136    }
137}
138
139impl<const D: usize, const I: usize, const J: usize, const W: usize>
140    FromIterator<TensorRank2<D, I, J>> for TensorRank2List<D, I, J, W>
141{
142    fn from_iter<Ii: IntoIterator<Item = TensorRank2<D, I, J>>>(into_iterator: Ii) -> Self {
143        let mut tensor_rank_2_list = Self::zero();
144        tensor_rank_2_list
145            .iter_mut()
146            .zip(into_iterator)
147            .for_each(|(tensor_rank_2_list_entry, entry)| *tensor_rank_2_list_entry = entry);
148        tensor_rank_2_list
149    }
150}
151
152impl<const D: usize, const I: usize, const J: usize, const W: usize> Index<usize>
153    for TensorRank2List<D, I, J, W>
154{
155    type Output = TensorRank2<D, I, J>;
156    fn index(&self, index: usize) -> &Self::Output {
157        &self.0[index]
158    }
159}
160
161impl<const D: usize, const I: usize, const J: usize, const W: usize> IndexMut<usize>
162    for TensorRank2List<D, I, J, W>
163{
164    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
165        &mut self.0[index]
166    }
167}
168
169impl<const D: usize, const I: usize, const J: usize, const W: usize> Add
170    for TensorRank2List<D, I, J, W>
171{
172    type Output = Self;
173    fn add(mut self, tensor_rank_2_list: Self) -> Self::Output {
174        self += tensor_rank_2_list;
175        self
176    }
177}
178
179impl<const D: usize, const I: usize, const J: usize, const W: usize> Add<&Self>
180    for TensorRank2List<D, I, J, W>
181{
182    type Output = Self;
183    fn add(mut self, tensor_rank_2_list: &Self) -> Self::Output {
184        self += tensor_rank_2_list;
185        self
186    }
187}
188
189impl<const D: usize, const I: usize, const J: usize, const W: usize> AddAssign
190    for TensorRank2List<D, I, J, W>
191{
192    fn add_assign(&mut self, tensor_rank_2_list: Self) {
193        self.iter_mut()
194            .zip(tensor_rank_2_list.iter())
195            .for_each(|(self_entry, tensor_rank_2)| *self_entry += tensor_rank_2);
196    }
197}
198
199impl<const D: usize, const I: usize, const J: usize, const W: usize> AddAssign<&Self>
200    for TensorRank2List<D, I, J, W>
201{
202    fn add_assign(&mut self, tensor_rank_2_list: &Self) {
203        self.iter_mut()
204            .zip(tensor_rank_2_list.iter())
205            .for_each(|(self_entry, tensor_rank_2)| *self_entry += tensor_rank_2);
206    }
207}
208
209impl<const D: usize, const I: usize, const J: usize, const W: usize> Div<TensorRank0>
210    for TensorRank2List<D, I, J, W>
211{
212    type Output = Self;
213    fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
214        self /= &tensor_rank_0;
215        self
216    }
217}
218
219impl<const D: usize, const I: usize, const J: usize, const W: usize> Div<&TensorRank0>
220    for TensorRank2List<D, I, J, W>
221{
222    type Output = Self;
223    fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
224        self /= tensor_rank_0;
225        self
226    }
227}
228
229impl<const D: usize, const I: usize, const J: usize, const W: usize> DivAssign<TensorRank0>
230    for TensorRank2List<D, I, J, W>
231{
232    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
233        self.iter_mut().for_each(|entry| *entry /= &tensor_rank_0);
234    }
235}
236
237impl<const D: usize, const I: usize, const J: usize, const W: usize> DivAssign<&TensorRank0>
238    for TensorRank2List<D, I, J, W>
239{
240    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
241        self.iter_mut().for_each(|entry| *entry /= tensor_rank_0);
242    }
243}
244
245impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<TensorRank0>
246    for TensorRank2List<D, I, J, W>
247{
248    type Output = Self;
249    fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
250        self *= &tensor_rank_0;
251        self
252    }
253}
254
255impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<&TensorRank0>
256    for TensorRank2List<D, I, J, W>
257{
258    type Output = Self;
259    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
260        self *= tensor_rank_0;
261        self
262    }
263}
264
265impl<const D: usize, const I: usize, const J: usize, const W: usize> MulAssign<TensorRank0>
266    for TensorRank2List<D, I, J, W>
267{
268    fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
269        self.iter_mut().for_each(|entry| *entry *= &tensor_rank_0);
270    }
271}
272
273impl<const D: usize, const I: usize, const J: usize, const W: usize> MulAssign<&TensorRank0>
274    for TensorRank2List<D, I, J, W>
275{
276    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
277        self.iter_mut().for_each(|entry| *entry *= tensor_rank_0);
278    }
279}
280
281impl<const D: usize, const I: usize, const J: usize, const W: usize> Sub
282    for TensorRank2List<D, I, J, W>
283{
284    type Output = Self;
285    fn sub(mut self, tensor_rank_2_list: Self) -> Self::Output {
286        self -= tensor_rank_2_list;
287        self
288    }
289}
290
291impl<const D: usize, const I: usize, const J: usize, const W: usize> Sub<&Self>
292    for TensorRank2List<D, I, J, W>
293{
294    type Output = Self;
295    fn sub(mut self, tensor_rank_2_list: &Self) -> Self::Output {
296        self -= tensor_rank_2_list;
297        self
298    }
299}
300
301impl<const D: usize, const I: usize, const J: usize, const W: usize> SubAssign
302    for TensorRank2List<D, I, J, W>
303{
304    fn sub_assign(&mut self, tensor_rank_2_list: Self) {
305        self.iter_mut()
306            .zip(tensor_rank_2_list.iter())
307            .for_each(|(self_entry, tensor_rank_2)| *self_entry -= tensor_rank_2);
308    }
309}
310
311impl<const D: usize, const I: usize, const J: usize, const W: usize> SubAssign<&Self>
312    for TensorRank2List<D, I, J, W>
313{
314    fn sub_assign(&mut self, tensor_rank_2_list: &Self) {
315        self.iter_mut()
316            .zip(tensor_rank_2_list.iter())
317            .for_each(|(self_entry, tensor_rank_2)| *self_entry -= tensor_rank_2);
318    }
319}