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