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