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, Jacobian, Solution, Tensor, TensorArray, Vector,
17    rank_0::TensorRank0, rank_2::TensorRank2, 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> Solution for TensorRank1<D, I> {
95    fn decrement_from_chained(&mut self, _other: &mut Vector, _vector: Vector) {
96        unimplemented!()
97    }
98}
99
100impl<const D: usize, const I: usize> Jacobian for TensorRank1<D, I> {
101    fn fill_into(self, _vector: &mut Vector) {
102        unimplemented!()
103    }
104    fn fill_into_chained(self, _other: Vector, _vector: &mut Vector) {
105        unimplemented!()
106    }
107}
108
109impl<const D: usize, const I: usize> Sub<Vector> for TensorRank1<D, I> {
110    type Output = Self;
111    fn sub(self, _vector: Vector) -> Self::Output {
112        unimplemented!()
113    }
114}
115
116impl<const D: usize, const I: usize> Sub<&Vector> for TensorRank1<D, I> {
117    type Output = Self;
118    fn sub(self, _vector: &Vector) -> Self::Output {
119        unimplemented!()
120    }
121}
122
123impl<const D: usize, const I: usize> Tensor for TensorRank1<D, I> {
124    type Item = TensorRank0;
125    fn full_contraction(&self, tensor_rank_1: &Self) -> TensorRank0 {
126        self * tensor_rank_1
127    }
128    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
129        self.0.iter()
130    }
131    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
132        self.0.iter_mut()
133    }
134    fn norm_inf(&self) -> TensorRank0 {
135        self.iter().fold(0.0, |acc, entry| entry.abs().max(acc))
136    }
137}
138
139impl<const D: usize, const I: usize> IntoIterator for TensorRank1<D, I> {
140    type Item = TensorRank0;
141    type IntoIter = std::array::IntoIter<Self::Item, D>;
142    fn into_iter(self) -> Self::IntoIter {
143        self.0.into_iter()
144    }
145}
146
147impl<const D: usize, const I: usize> TensorArray for TensorRank1<D, I> {
148    type Array = [TensorRank0; D];
149    type Item = TensorRank0;
150    fn as_array(&self) -> Self::Array {
151        self.0
152    }
153    fn identity() -> Self {
154        ones()
155    }
156    fn new(array: Self::Array) -> Self {
157        array.into_iter().collect()
158    }
159    fn zero() -> Self {
160        zero()
161    }
162}
163
164/// Returns the rank-1 tensor of ones as a constant.
165pub const fn ones<const D: usize, const I: usize>() -> TensorRank1<D, I> {
166    TensorRank1([1.0; D])
167}
168
169/// Returns the rank-1 zero tensor as a constant.
170pub const fn zero<const D: usize, const I: usize>() -> TensorRank1<D, I> {
171    TensorRank1([0.0; D])
172}
173
174impl<const D: usize, const I: usize> From<[TensorRank0; D]> for TensorRank1<D, I> {
175    fn from(array: [TensorRank0; D]) -> Self {
176        Self(array)
177    }
178}
179
180impl<const D: usize, const I: usize> From<Vec<TensorRank0>> for TensorRank1<D, I> {
181    fn from(vec: Vec<TensorRank0>) -> Self {
182        Self(vec.try_into().unwrap())
183    }
184}
185
186impl<const D: usize, const I: usize> From<TensorRank1<D, I>> for [TensorRank0; D] {
187    fn from(tensor_rank_1: TensorRank1<D, I>) -> Self {
188        tensor_rank_1.0
189    }
190}
191
192impl<const D: usize, const I: usize> From<TensorRank1<D, I>> for Vec<TensorRank0> {
193    fn from(tensor_rank_1: TensorRank1<D, I>) -> Self {
194        tensor_rank_1.0.to_vec()
195    }
196}
197
198impl From<TensorRank1<3, 0>> for TensorRank1<3, 1> {
199    fn from(tensor_rank_1: TensorRank1<3, 0>) -> Self {
200        unsafe { transmute::<TensorRank1<3, 0>, TensorRank1<3, 1>>(tensor_rank_1) }
201    }
202}
203
204impl<const D: usize, const I: usize> FromIterator<TensorRank0> for TensorRank1<D, I> {
205    fn from_iter<Ii: IntoIterator<Item = TensorRank0>>(into_iterator: Ii) -> Self {
206        let mut tensor_rank_1 = zero();
207        tensor_rank_1
208            .iter_mut()
209            .zip(into_iterator)
210            .for_each(|(tensor_rank_1_i, value_i)| *tensor_rank_1_i = value_i);
211        tensor_rank_1
212    }
213}
214
215impl<const D: usize, const I: usize> Index<usize> for TensorRank1<D, I> {
216    type Output = TensorRank0;
217    fn index(&self, index: usize) -> &Self::Output {
218        &self.0[index]
219    }
220}
221
222impl<const D: usize, const I: usize> IndexMut<usize> for TensorRank1<D, I> {
223    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
224        &mut self.0[index]
225    }
226}
227
228impl<const D: usize, const I: usize> std::iter::Sum for TensorRank1<D, I> {
229    fn sum<Ii>(iter: Ii) -> Self
230    where
231        Ii: Iterator<Item = Self>,
232    {
233        let mut output = zero();
234        iter.for_each(|item| output += item);
235        output
236    }
237}
238
239impl<const D: usize, const I: usize> Div<TensorRank0> for TensorRank1<D, I> {
240    type Output = Self;
241    fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
242        self /= tensor_rank_0;
243        self
244    }
245}
246
247impl<const D: usize, const I: usize> Div<TensorRank0> for &TensorRank1<D, I> {
248    type Output = TensorRank1<D, I>;
249    fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
250        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
251    }
252}
253
254impl<const D: usize, const I: usize> Div<&TensorRank0> for TensorRank1<D, I> {
255    type Output = Self;
256    fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
257        self /= tensor_rank_0;
258        self
259    }
260}
261
262impl<const D: usize, const I: usize> Div<&TensorRank0> for &TensorRank1<D, I> {
263    type Output = TensorRank1<D, I>;
264    fn div(self, tensor_rank_0: &TensorRank0) -> Self::Output {
265        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
266    }
267}
268
269impl<const D: usize, const I: usize> DivAssign<TensorRank0> for TensorRank1<D, I> {
270    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
271        self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
272    }
273}
274
275impl<const D: usize, const I: usize> DivAssign<&TensorRank0> for TensorRank1<D, I> {
276    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
277        self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
278    }
279}
280
281impl<const D: usize, const I: usize> Mul<TensorRank0> for TensorRank1<D, I> {
282    type Output = Self;
283    fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
284        self *= tensor_rank_0;
285        self
286    }
287}
288
289impl<const D: usize, const I: usize> Mul<TensorRank0> for &TensorRank1<D, I> {
290    type Output = TensorRank1<D, I>;
291    fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
292        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
293    }
294}
295
296impl<const D: usize, const I: usize> Mul<&TensorRank0> for TensorRank1<D, I> {
297    type Output = Self;
298    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
299        self *= tensor_rank_0;
300        self
301    }
302}
303
304impl<const D: usize, const I: usize> Mul<&TensorRank0> for &TensorRank1<D, I> {
305    type Output = TensorRank1<D, I>;
306    fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
307        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
308    }
309}
310
311impl<const D: usize, const I: usize> MulAssign<TensorRank0> for TensorRank1<D, I> {
312    fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
313        self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
314    }
315}
316
317impl<const D: usize, const I: usize> MulAssign<&TensorRank0> for TensorRank1<D, I> {
318    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
319        self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
320    }
321}
322
323impl<const D: usize, const I: usize> Add for TensorRank1<D, I> {
324    type Output = Self;
325    fn add(mut self, tensor_rank_1: Self) -> Self::Output {
326        self += tensor_rank_1;
327        self
328    }
329}
330
331impl<const D: usize, const I: usize> Add<&Self> for TensorRank1<D, I> {
332    type Output = Self;
333    fn add(mut self, tensor_rank_1: &Self) -> Self::Output {
334        self += tensor_rank_1;
335        self
336    }
337}
338
339impl<const D: usize, const I: usize> Add<TensorRank1<D, I>> for &TensorRank1<D, I> {
340    type Output = TensorRank1<D, I>;
341    fn add(self, mut tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
342        tensor_rank_1 += self;
343        tensor_rank_1
344    }
345}
346
347impl<const D: usize, const I: usize> AddAssign for TensorRank1<D, I> {
348    fn add_assign(&mut self, tensor_rank_1: Self) {
349        self.iter_mut()
350            .zip(tensor_rank_1.iter())
351            .for_each(|(self_i, tensor_rank_1_i)| *self_i += tensor_rank_1_i);
352    }
353}
354
355impl<const D: usize, const I: usize> AddAssign<&Self> for TensorRank1<D, I> {
356    fn add_assign(&mut self, tensor_rank_1: &Self) {
357        self.iter_mut()
358            .zip(tensor_rank_1.iter())
359            .for_each(|(self_i, tensor_rank_1_i)| *self_i += tensor_rank_1_i);
360    }
361}
362
363impl<const D: usize, const I: usize> Sub for TensorRank1<D, I> {
364    type Output = Self;
365    fn sub(mut self, tensor_rank_1: Self) -> Self::Output {
366        self -= tensor_rank_1;
367        self
368    }
369}
370
371impl<const D: usize, const I: usize> Sub<&Self> for TensorRank1<D, I> {
372    type Output = Self;
373    fn sub(mut self, tensor_rank_1: &Self) -> Self::Output {
374        self -= tensor_rank_1;
375        self
376    }
377}
378
379impl<const D: usize, const I: usize> Sub<TensorRank1<D, I>> for &TensorRank1<D, I> {
380    type Output = TensorRank1<D, I>;
381    fn sub(self, mut tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
382        tensor_rank_1
383            .iter_mut()
384            .zip(self.iter())
385            .for_each(|(tensor_rank_1_i, self_i)| *tensor_rank_1_i = self_i - *tensor_rank_1_i);
386        tensor_rank_1
387    }
388}
389
390impl<const D: usize, const I: usize> Sub<Self> for &TensorRank1<D, I> {
391    type Output = TensorRank1<D, I>;
392    fn sub(self, tensor_rank_1: Self) -> Self::Output {
393        tensor_rank_1
394            .iter()
395            .zip(self.iter())
396            .map(|(tensor_rank_1_i, self_i)| self_i - *tensor_rank_1_i)
397            .collect()
398    }
399}
400
401impl<const D: usize, const I: usize> SubAssign for TensorRank1<D, I> {
402    fn sub_assign(&mut self, tensor_rank_1: Self) {
403        self.iter_mut()
404            .zip(tensor_rank_1.iter())
405            .for_each(|(self_i, tensor_rank_1_i)| *self_i -= tensor_rank_1_i);
406    }
407}
408
409impl<const D: usize, const I: usize> SubAssign<&Self> for TensorRank1<D, I> {
410    fn sub_assign(&mut self, tensor_rank_1: &Self) {
411        self.iter_mut()
412            .zip(tensor_rank_1.iter())
413            .for_each(|(self_i, tensor_rank_1_i)| *self_i -= tensor_rank_1_i);
414    }
415}
416
417impl<const D: usize, const I: usize> Mul for TensorRank1<D, I> {
418    type Output = TensorRank0;
419    fn mul(self, tensor_rank_1: Self) -> Self::Output {
420        self.iter()
421            .zip(tensor_rank_1.iter())
422            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
423            .sum()
424    }
425}
426
427impl<const D: usize, const I: usize> Mul<&Self> for TensorRank1<D, I> {
428    type Output = TensorRank0;
429    fn mul(self, tensor_rank_1: &Self) -> Self::Output {
430        self.iter()
431            .zip(tensor_rank_1.iter())
432            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
433            .sum()
434    }
435}
436
437impl<const D: usize, const I: usize> Mul<TensorRank1<D, I>> for &TensorRank1<D, I> {
438    type Output = TensorRank0;
439    fn mul(self, tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
440        self.iter()
441            .zip(tensor_rank_1.iter())
442            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
443            .sum()
444    }
445}
446
447impl<const D: usize, const I: usize> Mul for &TensorRank1<D, I> {
448    type Output = TensorRank0;
449    fn mul(self, tensor_rank_1: Self) -> Self::Output {
450        self.iter()
451            .zip(tensor_rank_1.iter())
452            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
453            .sum()
454    }
455}
456
457#[allow(clippy::suspicious_arithmetic_impl)]
458impl<const D: usize, const I: usize, const J: usize> Div<TensorRank2<D, I, J>>
459    for &TensorRank1<D, I>
460{
461    type Output = TensorRank1<D, J>;
462    fn div(self, tensor_rank_2: TensorRank2<D, I, J>) -> Self::Output {
463        tensor_rank_2.inverse() * self
464    }
465}