conspire/math/tensor/rank_1/list/
mod.rs

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