conspire/math/tensor/rank_1/list/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::math::{
5 CrossProduct, Tensor, TensorRank0, TensorRank1, TensorRank2, tensor::list::TensorList,
6};
7use std::ops::Mul;
8
9use crate::math::assert::FiniteDifference;
10
11pub type TensorRank1List<const D: usize, const I: usize, const N: usize> =
13 TensorList<TensorRank1<D, I>, N>;
14
15impl<const D: usize, const I: usize, const N: usize> TensorRank1List<D, I, N> {
16 pub fn bounding_box(&self) -> TensorRank1List<D, I, 2> {
17 self.iter()
18 .skip(1)
19 .fold(
20 [self[0].clone(), self[0].clone()],
21 |[mut min, mut max], entry| {
22 entry
23 .iter()
24 .zip(min.iter_mut().zip(max.iter_mut()))
25 .for_each(|(&entry_i, (min_i, max_i))| {
26 *min_i = min_i.min(entry_i);
27 *max_i = max_i.max(entry_i);
28 });
29 [min, max]
30 },
31 )
32 .into()
33 }
34}
35
36impl<const I: usize> TensorRank1List<3, I, 3> {
37 pub fn scalar_triple_product(&self) -> TensorRank0 {
38 &self[0] * self[1].cross(&self[2])
39 }
40}
41
42impl<const D: usize, const I: usize, const N: usize> From<[[TensorRank0; D]; N]>
43 for TensorRank1List<D, I, N>
44{
45 fn from(array: [[TensorRank0; D]; N]) -> Self {
46 array.into_iter().map(|entry| entry.into()).collect()
47 }
48}
49
50impl<const D: usize, const N: usize> From<TensorRank1List<D, 9, N>> for TensorRank1List<D, 0, N> {
51 fn from(tensor_rank_1_list: TensorRank1List<D, 9, N>) -> Self {
52 tensor_rank_1_list
53 .into_iter()
54 .map(|entry| entry.into())
55 .collect()
56 }
57}
58
59impl<const D: usize, const N: usize> From<TensorRank1List<D, 0, N>> for TensorRank1List<D, 1, N> {
60 fn from(tensor_rank_1_list: TensorRank1List<D, 0, N>) -> Self {
61 tensor_rank_1_list
62 .into_iter()
63 .map(|entry| entry.into())
64 .collect()
65 }
66}
67
68impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<TensorRank1List<D, J, W>>
69 for TensorRank1List<D, I, W>
70{
71 type Output = TensorRank2<D, I, J>;
72 fn mul(self, tensor_rank_1_list: TensorRank1List<D, J, W>) -> Self::Output {
73 self.into_iter()
74 .zip(tensor_rank_1_list)
75 .map(|(self_entry, entry)| Self::Output::from((self_entry, entry)))
76 .sum()
77 }
78}
79
80impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<&TensorRank1List<D, J, W>>
81 for TensorRank1List<D, I, W>
82{
83 type Output = TensorRank2<D, I, J>;
84 fn mul(self, tensor_rank_1_list: &TensorRank1List<D, J, W>) -> Self::Output {
85 self.into_iter()
86 .zip(tensor_rank_1_list.iter())
87 .map(|(self_entry, entry)| Self::Output::from((self_entry, entry)))
88 .sum()
89 }
90}
91
92impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<TensorRank1List<D, J, W>>
93 for &TensorRank1List<D, I, W>
94{
95 type Output = TensorRank2<D, I, J>;
96 fn mul(self, tensor_rank_1_list: TensorRank1List<D, J, W>) -> Self::Output {
97 self.iter()
98 .zip(tensor_rank_1_list)
99 .map(|(self_entry, entry)| Self::Output::from((self_entry, entry)))
100 .sum()
101 }
102}
103
104impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<&TensorRank1List<D, J, W>>
105 for &TensorRank1List<D, I, W>
106{
107 type Output = TensorRank2<D, I, J>;
108 fn mul(self, tensor_rank_1_list: &TensorRank1List<D, J, W>) -> Self::Output {
109 self.iter()
110 .zip(tensor_rank_1_list.iter())
111 .map(|(self_entry, entry)| Self::Output::from((self_entry, entry)))
112 .sum()
113 }
114}
115
116impl<const D: usize, const I: usize, const W: usize> FiniteDifference for TensorRank1List<D, I, W> {
117 fn error_fd(&self, comparator: &Self, epsilon: TensorRank0) -> Option<(bool, usize)> {
118 let error_count = self
119 .iter()
120 .zip(comparator.iter())
121 .map(|(entry, comparator_entry)| {
122 entry
123 .iter()
124 .zip(comparator_entry.iter())
125 .filter(|&(&entry_i, &comparator_entry_i)| {
126 (entry_i / comparator_entry_i - 1.0).abs() >= epsilon
127 && (entry_i.abs() >= epsilon || comparator_entry_i.abs() >= epsilon)
128 })
129 .count()
130 })
131 .sum();
132 if error_count > 0 {
133 let auxiliary = self
134 .iter()
135 .zip(comparator.iter())
136 .map(|(entry, comparator_entry)| {
137 entry
138 .iter()
139 .zip(comparator_entry.iter())
140 .filter(|&(&entry_i, &comparator_entry_i)| {
141 (entry_i / comparator_entry_i - 1.0).abs() >= epsilon
142 && (entry_i - comparator_entry_i).abs() >= epsilon
143 && (entry_i.abs() >= epsilon || comparator_entry_i.abs() >= epsilon)
144 })
145 .count()
146 })
147 .sum::<usize>()
148 > 0;
149 Some((auxiliary, error_count))
150 } else {
151 None
152 }
153 }
154}