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

1#[cfg(test)]
2use super::super::test::ErrorTensor;
3
4use crate::math::{
5    Jacobian, Solution, Tensor, TensorArray, TensorRank0, TensorRank1, TensorRank2,
6    TensorRank2Vec2D, TensorVec, Vector, write_tensor_rank_0,
7};
8use std::{
9    fmt::{Display, Formatter, Result},
10    mem::transmute,
11    ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
12};
13
14/// A vector of *d*-dimensional tensors of rank 1.
15///
16/// `D` is the dimension, `I` is the configuration.
17#[derive(Clone, Debug)]
18pub struct TensorRank1Vec<const D: usize, const I: usize>(Vec<TensorRank1<D, I>>);
19
20impl<const D: usize, const I: usize> Display for TensorRank1Vec<D, I> {
21    fn fmt(&self, f: &mut Formatter) -> Result {
22        write!(f, "\x1B[s")?;
23        write!(f, "[[")?;
24        self.iter().enumerate().try_for_each(|(i, tensor_rank_1)| {
25            tensor_rank_1
26                .iter()
27                .try_for_each(|entry| write_tensor_rank_0(f, entry))?;
28            if i + 1 < self.len() {
29                writeln!(f, "\x1B[2D],")?;
30                write!(f, "\x1B[u")?;
31                write!(f, "\x1B[{}B [", i + 1)?;
32            }
33            Ok(())
34        })?;
35        write!(f, "\x1B[2D]]")
36    }
37}
38
39#[cfg(test)]
40impl<const D: usize, const I: usize> ErrorTensor for TensorRank1Vec<D, I> {
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(|(entry, comparator_entry)| {
51                entry
52                    .iter()
53                    .zip(comparator_entry.iter())
54                    .filter(|&(&entry_i, &comparator_entry_i)| {
55                        &(entry_i - comparator_entry_i).abs() >= tol_abs
56                            && &(entry_i / comparator_entry_i - 1.0).abs() >= tol_rel
57                    })
58                    .count()
59            })
60            .sum();
61        if error_count > 0 {
62            Some(error_count)
63        } else {
64            None
65        }
66    }
67    fn error_fd(&self, comparator: &Self, epsilon: &TensorRank0) -> Option<(bool, usize)> {
68        let error_count = self
69            .iter()
70            .zip(comparator.iter())
71            .map(|(entry, comparator_entry)| {
72                entry
73                    .iter()
74                    .zip(comparator_entry.iter())
75                    .filter(|&(&entry_i, &comparator_entry_i)| {
76                        &(entry_i / comparator_entry_i - 1.0).abs() >= epsilon
77                            && (&entry_i.abs() >= epsilon || &comparator_entry_i.abs() >= epsilon)
78                    })
79                    .count()
80            })
81            .sum();
82        if error_count > 0 {
83            let auxillary = self
84                .iter()
85                .zip(comparator.iter())
86                .map(|(entry, comparator_entry)| {
87                    entry
88                        .iter()
89                        .zip(comparator_entry.iter())
90                        .filter(|&(&entry_i, &comparator_entry_i)| {
91                            &(entry_i / comparator_entry_i - 1.0).abs() >= epsilon
92                                && &(entry_i - comparator_entry_i).abs() >= epsilon
93                                && (&entry_i.abs() >= epsilon
94                                    || &comparator_entry_i.abs() >= epsilon)
95                        })
96                        .count()
97                })
98                .sum::<usize>()
99                > 0;
100            Some((auxillary, error_count))
101        } else {
102            None
103        }
104    }
105}
106
107impl<const D: usize, const I: usize> From<Vec<[TensorRank0; D]>> for TensorRank1Vec<D, I> {
108    fn from(vec: Vec<[TensorRank0; D]>) -> Self {
109        vec.into_iter()
110            .map(|tensor_rank_1| tensor_rank_1.into())
111            .collect()
112    }
113}
114
115impl<const D: usize, const I: usize> From<Vec<Vec<TensorRank0>>> for TensorRank1Vec<D, I> {
116    fn from(vec: Vec<Vec<TensorRank0>>) -> Self {
117        vec.into_iter()
118            .map(|tensor_rank_1| tensor_rank_1.into())
119            .collect()
120    }
121}
122
123impl<const D: usize, const I: usize> From<TensorRank1Vec<D, I>> for Vec<[TensorRank0; D]> {
124    fn from(tensor_rank_1_vec: TensorRank1Vec<D, I>) -> Self {
125        tensor_rank_1_vec
126            .iter()
127            .map(|tensor_rank_1| tensor_rank_1.clone().into())
128            .collect()
129    }
130}
131
132impl<const D: usize, const I: usize> From<TensorRank1Vec<D, I>> for Vec<Vec<TensorRank0>> {
133    fn from(tensor_rank_1_vec: TensorRank1Vec<D, I>) -> Self {
134        tensor_rank_1_vec
135            .iter()
136            .map(|tensor_rank_1| tensor_rank_1.clone().into())
137            .collect()
138    }
139}
140
141impl From<TensorRank1Vec<3, 0>> for TensorRank1Vec<3, 1> {
142    fn from(tensor_rank_1_vec: TensorRank1Vec<3, 0>) -> Self {
143        unsafe { transmute::<TensorRank1Vec<3, 0>, TensorRank1Vec<3, 1>>(tensor_rank_1_vec) }
144    }
145}
146
147impl From<TensorRank1Vec<3, 1>> for TensorRank1Vec<3, 0> {
148    fn from(tensor_rank_1_vec: TensorRank1Vec<3, 1>) -> Self {
149        unsafe { transmute::<TensorRank1Vec<3, 1>, TensorRank1Vec<3, 0>>(tensor_rank_1_vec) }
150    }
151}
152
153impl<const D: usize, const I: usize> From<Vector> for TensorRank1Vec<D, I> {
154    fn from(vector: Vector) -> Self {
155        let n = vector.len();
156        if n % D != 0 {
157            panic!("Vector length mismatch.")
158        } else {
159            (0..n / D)
160                .map(|a| (0..D).map(|i| vector[D * a + i]).collect())
161                .collect()
162        }
163    }
164}
165
166impl<const D: usize, const I: usize> From<&Vector> for TensorRank1Vec<D, I> {
167    fn from(vector: &Vector) -> Self {
168        let n = vector.len();
169        if n % D != 0 {
170            panic!("Vector length mismatch.")
171        } else {
172            (0..n / D)
173                .map(|a| (0..D).map(|i| vector[D * a + i]).collect())
174                .collect()
175        }
176    }
177}
178
179impl<const D: usize, const I: usize> FromIterator<TensorRank1<D, I>> for TensorRank1Vec<D, I> {
180    fn from_iter<Ii: IntoIterator<Item = TensorRank1<D, I>>>(into_iterator: Ii) -> Self {
181        Self(Vec::from_iter(into_iterator))
182    }
183}
184
185impl<const D: usize, const I: usize> Index<usize> for TensorRank1Vec<D, I> {
186    type Output = TensorRank1<D, I>;
187    fn index(&self, index: usize) -> &Self::Output {
188        &self.0[index]
189    }
190}
191
192impl<const D: usize, const I: usize> IndexMut<usize> for TensorRank1Vec<D, I> {
193    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
194        &mut self.0[index]
195    }
196}
197
198impl<const D: usize, const I: usize> TensorRank1Vec<D, I> {
199    /// Returns the sum of the full dot product of each tensor in each vector.
200    pub fn dot(&self, tensors: &Self) -> TensorRank0 {
201        self.iter()
202            .zip(tensors.iter())
203            .map(|(entry, tensor)| entry * tensor)
204            .sum()
205    }
206}
207
208impl<const D: usize, const I: usize> TensorVec for TensorRank1Vec<D, I> {
209    type Item = TensorRank1<D, I>;
210    type Slice<'a> = &'a [[TensorRank0; D]];
211    fn append(&mut self, other: &mut Self) {
212        self.0.append(&mut other.0)
213    }
214    fn is_empty(&self) -> bool {
215        self.0.is_empty()
216    }
217    fn len(&self) -> usize {
218        self.0.len()
219    }
220    fn new(slice: Self::Slice<'_>) -> Self {
221        slice
222            .iter()
223            .map(|slice_entry| Self::Item::new(*slice_entry))
224            .collect()
225    }
226    fn push(&mut self, item: Self::Item) {
227        self.0.push(item)
228    }
229    fn zero(len: usize) -> Self {
230        (0..len).map(|_| super::zero()).collect()
231    }
232}
233
234impl<const D: usize, const I: usize> Tensor for TensorRank1Vec<D, I> {
235    type Item = TensorRank1<D, I>;
236    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
237        self.0.iter()
238    }
239    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
240        self.0.iter_mut()
241    }
242    fn norm_inf(&self) -> TensorRank0 {
243        self.iter()
244            .map(|tensor_rank_1| {
245                tensor_rank_1
246                    .iter()
247                    .fold(0.0, |acc, entry| entry.abs().max(acc))
248            })
249            .reduce(TensorRank0::max)
250            .unwrap()
251    }
252    fn num_entries(&self) -> usize {
253        D * self.len()
254    }
255}
256
257impl<const D: usize, const I: usize> IntoIterator for TensorRank1Vec<D, I> {
258    type Item = TensorRank1<D, I>;
259    type IntoIter = std::vec::IntoIter<Self::Item>;
260    fn into_iter(self) -> Self::IntoIter {
261        self.0.into_iter()
262    }
263}
264
265impl<const D: usize, const I: usize> Solution for TensorRank1Vec<D, I> {
266    fn decrement_from_chained(&mut self, other: &mut Vector, vector: Vector) {
267        self.iter_mut()
268            .flat_map(|x| x.iter_mut())
269            .chain(other.iter_mut())
270            .zip(vector)
271            .for_each(|(entry_i, vector_i)| *entry_i -= vector_i)
272    }
273}
274
275impl<const D: usize, const I: usize> Jacobian for TensorRank1Vec<D, I> {
276    fn fill_into(self, vector: &mut Vector) {
277        self.into_iter()
278            .flatten()
279            .zip(vector.iter_mut())
280            .for_each(|(self_i, vector_i)| *vector_i = self_i)
281    }
282    fn fill_into_chained(self, other: Vector, vector: &mut Vector) {
283        self.into_iter()
284            .flatten()
285            .chain(other)
286            .zip(vector.iter_mut())
287            .for_each(|(self_i, vector_i)| *vector_i = self_i)
288    }
289}
290
291impl<const D: usize, const I: usize, const J: usize> Div<TensorRank2Vec2D<D, I, J>>
292    for TensorRank1Vec<D, I>
293{
294    type Output = Self;
295    fn div(self, _tensor_rank_2_vec_2d: TensorRank2Vec2D<D, I, J>) -> Self::Output {
296        todo!()
297    }
298}
299
300impl<const D: usize, const I: usize> Sub<Vector> for TensorRank1Vec<D, I> {
301    type Output = Self;
302    fn sub(mut self, vector: Vector) -> Self::Output {
303        self.iter_mut().enumerate().for_each(|(a, self_a)| {
304            self_a
305                .iter_mut()
306                .enumerate()
307                .for_each(|(i, self_a_i)| *self_a_i -= vector[D * a + i])
308        });
309        self
310    }
311}
312
313impl<const D: usize, const I: usize> Div<TensorRank0> for TensorRank1Vec<D, I> {
314    type Output = Self;
315    fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
316        self /= &tensor_rank_0;
317        self
318    }
319}
320
321impl<const D: usize, const I: usize> Div<&TensorRank0> for TensorRank1Vec<D, I> {
322    type Output = Self;
323    fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
324        self /= tensor_rank_0;
325        self
326    }
327}
328
329impl<const D: usize, const I: usize> DivAssign<TensorRank0> for TensorRank1Vec<D, I> {
330    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
331        self.iter_mut().for_each(|entry| *entry /= &tensor_rank_0);
332    }
333}
334
335impl<const D: usize, const I: usize> DivAssign<&TensorRank0> for TensorRank1Vec<D, I> {
336    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
337        self.iter_mut().for_each(|entry| *entry /= tensor_rank_0);
338    }
339}
340
341impl<const D: usize, const I: usize> Mul<TensorRank0> for TensorRank1Vec<D, I> {
342    type Output = Self;
343    fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
344        self *= &tensor_rank_0;
345        self
346    }
347}
348
349impl<const D: usize, const I: usize> Mul<&TensorRank0> for TensorRank1Vec<D, I> {
350    type Output = Self;
351    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
352        self *= tensor_rank_0;
353        self
354    }
355}
356
357impl<const D: usize, const I: usize> Mul<TensorRank0> for &TensorRank1Vec<D, I> {
358    type Output = TensorRank1Vec<D, I>;
359    fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
360        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
361    }
362}
363
364impl<const D: usize, const I: usize> Mul<&TensorRank0> for &TensorRank1Vec<D, I> {
365    type Output = TensorRank1Vec<D, I>;
366    fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
367        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
368    }
369}
370
371impl<const D: usize, const I: usize> MulAssign<TensorRank0> for TensorRank1Vec<D, I> {
372    fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
373        self.iter_mut().for_each(|entry| *entry *= &tensor_rank_0);
374    }
375}
376
377impl<const D: usize, const I: usize> MulAssign<&TensorRank0> for TensorRank1Vec<D, I> {
378    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
379        self.iter_mut().for_each(|entry| *entry *= tensor_rank_0);
380    }
381}
382
383impl<const D: usize, const I: usize> Add for TensorRank1Vec<D, I> {
384    type Output = Self;
385    fn add(mut self, tensor_rank_1_vec: Self) -> Self::Output {
386        self += tensor_rank_1_vec;
387        self
388    }
389}
390
391impl<const D: usize, const I: usize> Add<&Self> for TensorRank1Vec<D, I> {
392    type Output = Self;
393    fn add(mut self, tensor_rank_1_vec: &Self) -> Self::Output {
394        self += tensor_rank_1_vec;
395        self
396    }
397}
398
399impl<const D: usize, const I: usize> AddAssign for TensorRank1Vec<D, I> {
400    fn add_assign(&mut self, tensor_rank_1_vec: Self) {
401        self.iter_mut()
402            .zip(tensor_rank_1_vec.iter())
403            .for_each(|(self_entry, tensor_rank_1)| *self_entry += tensor_rank_1);
404    }
405}
406
407impl<const D: usize, const I: usize> AddAssign<&Self> for TensorRank1Vec<D, I> {
408    fn add_assign(&mut self, tensor_rank_1_vec: &Self) {
409        self.iter_mut()
410            .zip(tensor_rank_1_vec.iter())
411            .for_each(|(self_entry, tensor_rank_1)| *self_entry += tensor_rank_1);
412    }
413}
414
415impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank1Vec<D, J>>
416    for TensorRank1Vec<D, I>
417{
418    type Output = TensorRank2<D, I, J>;
419    fn mul(self, tensor_rank_1_vec: TensorRank1Vec<D, J>) -> Self::Output {
420        self.iter()
421            .zip(tensor_rank_1_vec.iter())
422            .map(|(self_entry, tensor_rank_1_vec_entry)| {
423                TensorRank2::dyad(self_entry, tensor_rank_1_vec_entry)
424            })
425            .sum()
426    }
427}
428
429impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank1Vec<D, J>>
430    for TensorRank1Vec<D, I>
431{
432    type Output = TensorRank2<D, I, J>;
433    fn mul(self, tensor_rank_1_vec: &TensorRank1Vec<D, J>) -> Self::Output {
434        self.iter()
435            .zip(tensor_rank_1_vec.iter())
436            .map(|(self_entry, tensor_rank_1_vec_entry)| {
437                TensorRank2::dyad(self_entry, tensor_rank_1_vec_entry)
438            })
439            .sum()
440    }
441}
442
443impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank1Vec<D, J>>
444    for &TensorRank1Vec<D, I>
445{
446    type Output = TensorRank2<D, I, J>;
447    fn mul(self, tensor_rank_1_vec: TensorRank1Vec<D, J>) -> Self::Output {
448        self.iter()
449            .zip(tensor_rank_1_vec.iter())
450            .map(|(self_entry, tensor_rank_1_vec_entry)| {
451                TensorRank2::dyad(self_entry, tensor_rank_1_vec_entry)
452            })
453            .sum()
454    }
455}
456
457impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank1Vec<D, J>>
458    for &TensorRank1Vec<D, I>
459{
460    type Output = TensorRank2<D, I, J>;
461    fn mul(self, tensor_rank_1_vec: &TensorRank1Vec<D, J>) -> Self::Output {
462        self.iter()
463            .zip(tensor_rank_1_vec.iter())
464            .map(|(self_entry, tensor_rank_1_vec_entry)| {
465                TensorRank2::dyad(self_entry, tensor_rank_1_vec_entry)
466            })
467            .sum()
468    }
469}
470
471impl<const D: usize, const I: usize> Sub for TensorRank1Vec<D, I> {
472    type Output = Self;
473    fn sub(mut self, tensor_rank_1_vec: Self) -> Self::Output {
474        self -= tensor_rank_1_vec;
475        self
476    }
477}
478
479impl<const D: usize, const I: usize> Sub<&Self> for TensorRank1Vec<D, I> {
480    type Output = Self;
481    fn sub(mut self, tensor_rank_1_vec: &Self) -> Self::Output {
482        self -= tensor_rank_1_vec;
483        self
484    }
485}
486
487impl<const D: usize, const I: usize> Sub for &TensorRank1Vec<D, I> {
488    type Output = TensorRank1Vec<D, I>;
489    fn sub(self, tensor_rank_1_vec: Self) -> Self::Output {
490        tensor_rank_1_vec
491            .iter()
492            .zip(self.iter())
493            .map(|(tensor_rank_1_vec_a, self_a)| {
494                tensor_rank_1_vec_a
495                    .iter()
496                    .zip(self_a.iter())
497                    .map(|(tensor_rank_1_vec_a_i, self_a_i)| self_a_i - *tensor_rank_1_vec_a_i)
498                    .collect()
499            })
500            .collect()
501    }
502}
503
504impl<const D: usize, const I: usize> SubAssign for TensorRank1Vec<D, I> {
505    fn sub_assign(&mut self, tensor_rank_1_vec: Self) {
506        self.iter_mut()
507            .zip(tensor_rank_1_vec.iter())
508            .for_each(|(self_entry, tensor_rank_1)| *self_entry -= tensor_rank_1);
509    }
510}
511
512impl<const D: usize, const I: usize> SubAssign<&Self> for TensorRank1Vec<D, I> {
513    fn sub_assign(&mut self, tensor_rank_1_vec: &Self) {
514        self.iter_mut()
515            .zip(tensor_rank_1_vec.iter())
516            .for_each(|(self_entry, tensor_rank_1)| *self_entry -= tensor_rank_1);
517    }
518}