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#[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 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}