conspire/math/tensor/list/
mod.rs

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