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