conspire/math/tensor/rank_1/
mod.rs

1#[cfg(test)]
2mod test;
3
4pub mod list;
5pub mod list_2d;
6pub mod vec;
7pub mod vec_2d;
8
9use std::{
10    fmt::{Display, Formatter, Result},
11    mem::transmute,
12    ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
13};
14
15use super::{
16    super::write_tensor_rank_0, Tensor, TensorArray, rank_0::TensorRank0, rank_2::TensorRank2,
17    test::ErrorTensor,
18};
19
20/// A *d*-dimensional tensor of rank 1.
21///
22/// `D` is the dimension, `I` is the configuration.
23#[derive(Clone, Debug, PartialEq)]
24pub struct TensorRank1<const D: usize, const I: usize>([TensorRank0; D]);
25
26pub const fn tensor_rank_1<const D: usize, const I: usize>(
27    array: [TensorRank0; D],
28) -> TensorRank1<D, I> {
29    TensorRank1(array)
30}
31
32impl<const D: usize, const I: usize> Display for TensorRank1<D, I> {
33    fn fmt(&self, f: &mut Formatter) -> Result {
34        write!(f, "[")?;
35        self.iter()
36            .try_for_each(|entry| write_tensor_rank_0(f, entry))?;
37        write!(f, "\x1B[2D]")
38    }
39}
40
41impl<const D: usize, const I: usize> TensorRank1<D, I> {
42    /// Returns the cross product with another rank-1 tensor.
43    pub fn cross(&self, tensor_rank_1: &Self) -> Self {
44        if D == 3 {
45            let mut output = zero();
46            output[0] = self[1] * tensor_rank_1[2] - self[2] * tensor_rank_1[1];
47            output[1] = self[2] * tensor_rank_1[0] - self[0] * tensor_rank_1[2];
48            output[2] = self[0] * tensor_rank_1[1] - self[1] * tensor_rank_1[0];
49            output
50        } else {
51            panic!()
52        }
53    }
54}
55
56impl<const D: usize, const I: usize> ErrorTensor for TensorRank1<D, I> {
57    fn error(
58        &self,
59        comparator: &Self,
60        tol_abs: &TensorRank0,
61        tol_rel: &TensorRank0,
62    ) -> Option<usize> {
63        let error_count = self
64            .iter()
65            .zip(comparator.iter())
66            .filter(|&(&self_i, &comparator_i)| {
67                &(self_i - comparator_i).abs() >= tol_abs
68                    && &(self_i / comparator_i - 1.0).abs() >= tol_rel
69            })
70            .count();
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            .filter(|&(&self_i, &comparator_i)| {
82                &(self_i / comparator_i - 1.0).abs() >= epsilon
83                    && (&self_i.abs() >= epsilon || &comparator_i.abs() >= epsilon)
84            })
85            .count();
86        if error_count > 0 {
87            Some((true, error_count))
88        } else {
89            None
90        }
91    }
92}
93
94impl<const D: usize, const I: usize> Tensor for TensorRank1<D, I> {
95    type Item = TensorRank0;
96    fn full_contraction(&self, tensor_rank_1: &Self) -> TensorRank0 {
97        self * tensor_rank_1
98    }
99    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
100        self.0.iter()
101    }
102    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
103        self.0.iter_mut()
104    }
105    fn norm_inf(&self) -> TensorRank0 {
106        self.iter().fold(0.0, |acc, entry| entry.abs().max(acc))
107    }
108}
109
110impl<const D: usize, const I: usize> IntoIterator for TensorRank1<D, I> {
111    type Item = TensorRank0;
112    type IntoIter = std::array::IntoIter<Self::Item, D>;
113    fn into_iter(self) -> Self::IntoIter {
114        self.0.into_iter()
115    }
116}
117
118impl<const D: usize, const I: usize> TensorArray for TensorRank1<D, I> {
119    type Array = [TensorRank0; D];
120    type Item = TensorRank0;
121    fn as_array(&self) -> Self::Array {
122        self.0
123    }
124    fn identity() -> Self {
125        panic!()
126    }
127    fn new(array: Self::Array) -> Self {
128        array.into_iter().collect()
129    }
130    fn zero() -> Self {
131        zero()
132    }
133}
134
135/// Returns the rank-1 zero tensor as a constant.
136pub const fn zero<const D: usize, const I: usize>() -> TensorRank1<D, I> {
137    TensorRank1([0.0; D])
138}
139
140impl<const D: usize, const I: usize> From<[TensorRank0; D]> for TensorRank1<D, I> {
141    fn from(array: [TensorRank0; D]) -> Self {
142        Self(array)
143    }
144}
145
146impl<const D: usize, const I: usize> From<Vec<TensorRank0>> for TensorRank1<D, I> {
147    fn from(vec: Vec<TensorRank0>) -> Self {
148        Self(vec.try_into().unwrap())
149    }
150}
151
152impl<const D: usize, const I: usize> From<TensorRank1<D, I>> for [TensorRank0; D] {
153    fn from(tensor_rank_1: TensorRank1<D, I>) -> Self {
154        tensor_rank_1.0
155    }
156}
157
158impl<const D: usize, const I: usize> From<TensorRank1<D, I>> for Vec<TensorRank0> {
159    fn from(tensor_rank_1: TensorRank1<D, I>) -> Self {
160        tensor_rank_1.0.to_vec()
161    }
162}
163
164impl From<TensorRank1<3, 0>> for TensorRank1<3, 1> {
165    fn from(tensor_rank_1: TensorRank1<3, 0>) -> Self {
166        unsafe { transmute::<TensorRank1<3, 0>, TensorRank1<3, 1>>(tensor_rank_1) }
167    }
168}
169
170impl<const D: usize, const I: usize> FromIterator<TensorRank0> for TensorRank1<D, I> {
171    fn from_iter<Ii: IntoIterator<Item = TensorRank0>>(into_iterator: Ii) -> Self {
172        let mut tensor_rank_1 = zero();
173        tensor_rank_1
174            .iter_mut()
175            .zip(into_iterator)
176            .for_each(|(tensor_rank_1_i, value_i)| *tensor_rank_1_i = value_i);
177        tensor_rank_1
178    }
179}
180
181impl<const D: usize, const I: usize> Index<usize> for TensorRank1<D, I> {
182    type Output = TensorRank0;
183    fn index(&self, index: usize) -> &Self::Output {
184        &self.0[index]
185    }
186}
187
188impl<const D: usize, const I: usize> IndexMut<usize> for TensorRank1<D, I> {
189    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
190        &mut self.0[index]
191    }
192}
193
194impl<const D: usize, const I: usize> std::iter::Sum for TensorRank1<D, I> {
195    fn sum<Ii>(iter: Ii) -> Self
196    where
197        Ii: Iterator<Item = Self>,
198    {
199        let mut output = zero();
200        iter.for_each(|item| output += item);
201        output
202    }
203}
204
205impl<const D: usize, const I: usize> Div<TensorRank0> for TensorRank1<D, I> {
206    type Output = Self;
207    fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
208        self /= tensor_rank_0;
209        self
210    }
211}
212
213impl<const D: usize, const I: usize> Div<TensorRank0> for &TensorRank1<D, I> {
214    type Output = TensorRank1<D, I>;
215    fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
216        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
217    }
218}
219
220impl<const D: usize, const I: usize> Div<&TensorRank0> for TensorRank1<D, I> {
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> Div<&TensorRank0> for &TensorRank1<D, I> {
229    type Output = TensorRank1<D, I>;
230    fn div(self, tensor_rank_0: &TensorRank0) -> Self::Output {
231        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
232    }
233}
234
235impl<const D: usize, const I: usize> DivAssign<TensorRank0> for TensorRank1<D, I> {
236    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
237        self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
238    }
239}
240
241impl<const D: usize, const I: usize> DivAssign<&TensorRank0> for TensorRank1<D, I> {
242    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
243        self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
244    }
245}
246
247impl<const D: usize, const I: usize> Mul<TensorRank0> for TensorRank1<D, I> {
248    type Output = Self;
249    fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
250        self *= tensor_rank_0;
251        self
252    }
253}
254
255impl<const D: usize, const I: usize> Mul<TensorRank0> for &TensorRank1<D, I> {
256    type Output = TensorRank1<D, I>;
257    fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
258        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
259    }
260}
261
262impl<const D: usize, const I: usize> Mul<&TensorRank0> for TensorRank1<D, I> {
263    type Output = Self;
264    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
265        self *= tensor_rank_0;
266        self
267    }
268}
269
270impl<const D: usize, const I: usize> Mul<&TensorRank0> for &TensorRank1<D, I> {
271    type Output = TensorRank1<D, I>;
272    fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
273        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
274    }
275}
276
277impl<const D: usize, const I: usize> MulAssign<TensorRank0> for TensorRank1<D, I> {
278    fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
279        self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
280    }
281}
282
283impl<const D: usize, const I: usize> MulAssign<&TensorRank0> for TensorRank1<D, I> {
284    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
285        self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
286    }
287}
288
289impl<const D: usize, const I: usize> Add for TensorRank1<D, I> {
290    type Output = Self;
291    fn add(mut self, tensor_rank_1: Self) -> Self::Output {
292        self += tensor_rank_1;
293        self
294    }
295}
296
297impl<const D: usize, const I: usize> Add<&Self> for TensorRank1<D, I> {
298    type Output = Self;
299    fn add(mut self, tensor_rank_1: &Self) -> Self::Output {
300        self += tensor_rank_1;
301        self
302    }
303}
304
305impl<const D: usize, const I: usize> Add<TensorRank1<D, I>> for &TensorRank1<D, I> {
306    type Output = TensorRank1<D, I>;
307    fn add(self, mut tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
308        tensor_rank_1 += self;
309        tensor_rank_1
310    }
311}
312
313impl<const D: usize, const I: usize> AddAssign for TensorRank1<D, I> {
314    fn add_assign(&mut self, tensor_rank_1: Self) {
315        self.iter_mut()
316            .zip(tensor_rank_1.iter())
317            .for_each(|(self_i, tensor_rank_1_i)| *self_i += tensor_rank_1_i);
318    }
319}
320
321impl<const D: usize, const I: usize> AddAssign<&Self> for TensorRank1<D, I> {
322    fn add_assign(&mut self, tensor_rank_1: &Self) {
323        self.iter_mut()
324            .zip(tensor_rank_1.iter())
325            .for_each(|(self_i, tensor_rank_1_i)| *self_i += tensor_rank_1_i);
326    }
327}
328
329impl<const D: usize, const I: usize> Sub for TensorRank1<D, I> {
330    type Output = Self;
331    fn sub(mut self, tensor_rank_1: Self) -> Self::Output {
332        self -= tensor_rank_1;
333        self
334    }
335}
336
337impl<const D: usize, const I: usize> Sub<&Self> for TensorRank1<D, I> {
338    type Output = Self;
339    fn sub(mut self, tensor_rank_1: &Self) -> Self::Output {
340        self -= tensor_rank_1;
341        self
342    }
343}
344
345impl<const D: usize, const I: usize> Sub<TensorRank1<D, I>> for &TensorRank1<D, I> {
346    type Output = TensorRank1<D, I>;
347    fn sub(self, mut tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
348        tensor_rank_1
349            .iter_mut()
350            .zip(self.iter())
351            .for_each(|(tensor_rank_1_i, self_i)| *tensor_rank_1_i = self_i - *tensor_rank_1_i);
352        tensor_rank_1
353    }
354}
355
356impl<const D: usize, const I: usize> Sub<Self> for &TensorRank1<D, I> {
357    type Output = TensorRank1<D, I>;
358    fn sub(self, tensor_rank_1: Self) -> Self::Output {
359        tensor_rank_1
360            .iter()
361            .zip(self.iter())
362            .map(|(tensor_rank_1_i, self_i)| self_i - *tensor_rank_1_i)
363            .collect()
364    }
365}
366
367impl<const D: usize, const I: usize> SubAssign for TensorRank1<D, I> {
368    fn sub_assign(&mut self, tensor_rank_1: Self) {
369        self.iter_mut()
370            .zip(tensor_rank_1.iter())
371            .for_each(|(self_i, tensor_rank_1_i)| *self_i -= tensor_rank_1_i);
372    }
373}
374
375impl<const D: usize, const I: usize> SubAssign<&Self> for TensorRank1<D, I> {
376    fn sub_assign(&mut self, tensor_rank_1: &Self) {
377        self.iter_mut()
378            .zip(tensor_rank_1.iter())
379            .for_each(|(self_i, tensor_rank_1_i)| *self_i -= tensor_rank_1_i);
380    }
381}
382
383impl<const D: usize, const I: usize> Mul for TensorRank1<D, I> {
384    type Output = TensorRank0;
385    fn mul(self, tensor_rank_1: Self) -> Self::Output {
386        self.iter()
387            .zip(tensor_rank_1.iter())
388            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
389            .sum()
390    }
391}
392
393impl<const D: usize, const I: usize> Mul<&Self> for TensorRank1<D, I> {
394    type Output = TensorRank0;
395    fn mul(self, tensor_rank_1: &Self) -> Self::Output {
396        self.iter()
397            .zip(tensor_rank_1.iter())
398            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
399            .sum()
400    }
401}
402
403impl<const D: usize, const I: usize> Mul<TensorRank1<D, I>> for &TensorRank1<D, I> {
404    type Output = TensorRank0;
405    fn mul(self, tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
406        self.iter()
407            .zip(tensor_rank_1.iter())
408            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
409            .sum()
410    }
411}
412
413impl<const D: usize, const I: usize> Mul for &TensorRank1<D, I> {
414    type Output = TensorRank0;
415    fn mul(self, tensor_rank_1: Self) -> Self::Output {
416        self.iter()
417            .zip(tensor_rank_1.iter())
418            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
419            .sum()
420    }
421}
422
423#[allow(clippy::suspicious_arithmetic_impl)]
424impl<const D: usize, const I: usize, const J: usize> Div<TensorRank2<D, I, J>>
425    for TensorRank1<D, I>
426{
427    type Output = TensorRank1<D, J>;
428    fn div(self, tensor_rank_2: TensorRank2<D, I, J>) -> Self::Output {
429        tensor_rank_2.inverse() * self
430    }
431}