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    iter::Sum,
12    mem::transmute,
13    ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
14};
15
16use super::{
17    super::write_tensor_rank_0, Jacobian, Solution, Tensor, TensorArray, Vector,
18    rank_0::TensorRank0, rank_2::TensorRank2,
19};
20
21#[cfg(test)]
22use super::test::ErrorTensor;
23
24/// A *d*-dimensional tensor of rank 1.
25///
26/// `D` is the dimension, `I` is the configuration.
27#[repr(transparent)]
28#[derive(Clone, Debug, PartialEq)]
29pub struct TensorRank1<const D: usize, const I: usize>([TensorRank0; D]);
30
31impl<const D: usize, const I: usize> Default for TensorRank1<D, I> {
32    fn default() -> Self {
33        Self::zero()
34    }
35}
36
37pub const fn tensor_rank_1<const D: usize, const I: usize>(
38    array: [TensorRank0; D],
39) -> TensorRank1<D, I> {
40    TensorRank1(array)
41}
42
43impl<const D: usize, const I: usize> Display for TensorRank1<D, I> {
44    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
45        write!(f, "\x1B[s")?;
46        write!(f, "[")?;
47        self.iter()
48            .try_for_each(|entry| write_tensor_rank_0(f, entry))?;
49        write!(f, "\x1B[2D]")
50    }
51}
52
53impl<const D: usize, const I: usize> TensorRank1<D, I> {
54    /// Returns a raw pointer to the slice’s buffer.
55    pub const fn as_ptr(&self) -> *const TensorRank0 {
56        self.0.as_ptr()
57    }
58    /// Returns the cross product with another rank-1 tensor.
59    pub fn cross(&self, tensor_rank_1: &Self) -> Self {
60        if D == 3 {
61            let mut output = zero();
62            output[0] = self[1] * tensor_rank_1[2] - self[2] * tensor_rank_1[1];
63            output[1] = self[2] * tensor_rank_1[0] - self[0] * tensor_rank_1[2];
64            output[2] = self[0] * tensor_rank_1[1] - self[1] * tensor_rank_1[0];
65            output
66        } else {
67            panic!()
68        }
69    }
70}
71
72#[cfg(test)]
73impl<const D: usize, const I: usize> ErrorTensor for TensorRank1<D, I> {
74    fn error_fd(&self, comparator: &Self, epsilon: &TensorRank0) -> Option<(bool, usize)> {
75        let error_count = self
76            .iter()
77            .zip(comparator.iter())
78            .filter(|&(&self_i, &comparator_i)| {
79                &(self_i / comparator_i - 1.0).abs() >= epsilon
80                    && (&self_i.abs() >= epsilon || &comparator_i.abs() >= epsilon)
81            })
82            .count();
83        if error_count > 0 {
84            Some((true, error_count))
85        } else {
86            None
87        }
88    }
89}
90
91impl<const D: usize, const I: usize> Solution for TensorRank1<D, I> {
92    fn decrement_from(&mut self, _other: &Vector) {
93        unimplemented!()
94    }
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 len(&self) -> usize {
135        D
136    }
137    fn size(&self) -> usize {
138        D
139    }
140}
141
142impl<const D: usize, const I: usize> IntoIterator for TensorRank1<D, I> {
143    type Item = TensorRank0;
144    type IntoIter = std::array::IntoIter<Self::Item, D>;
145    fn into_iter(self) -> Self::IntoIter {
146        self.0.into_iter()
147    }
148}
149
150impl<const D: usize, const I: usize> TensorArray for TensorRank1<D, I> {
151    type Array = [TensorRank0; D];
152    type Item = TensorRank0;
153    fn as_array(&self) -> Self::Array {
154        self.0
155    }
156    fn identity() -> Self {
157        ones()
158    }
159    fn new(array: Self::Array) -> Self {
160        array.into_iter().collect()
161    }
162    fn zero() -> Self {
163        zero()
164    }
165}
166
167/// Returns the rank-1 tensor of ones as a constant.
168pub const fn ones<const D: usize, const I: usize>() -> TensorRank1<D, I> {
169    TensorRank1([1.0; D])
170}
171
172/// Returns the rank-1 zero tensor as a constant.
173pub const fn zero<const D: usize, const I: usize>() -> TensorRank1<D, I> {
174    TensorRank1([0.0; D])
175}
176
177impl From<TensorRank1<3, 0>> for TensorRank1<3, 1> {
178    fn from(tensor_rank_1: TensorRank1<3, 0>) -> Self {
179        unsafe { transmute::<TensorRank1<3, 0>, TensorRank1<3, 1>>(tensor_rank_1) }
180    }
181}
182
183impl<const D: usize, const I: usize> From<[TensorRank0; D]> for TensorRank1<D, I> {
184    fn from(array: [TensorRank0; D]) -> Self {
185        Self(array)
186    }
187}
188
189impl<const D: usize, const I: usize> From<TensorRank1<D, I>> for [TensorRank0; D] {
190    fn from(tensor_rank_1: TensorRank1<D, I>) -> Self {
191        tensor_rank_1.0
192    }
193}
194
195impl<const D: usize, const I: usize> From<Vec<TensorRank0>> for TensorRank1<D, I> {
196    fn from(vec: Vec<TensorRank0>) -> Self {
197        Self(vec.try_into().unwrap())
198    }
199}
200
201impl<const D: usize, const I: usize> From<TensorRank1<D, I>> for Vec<TensorRank0> {
202    fn from(tensor_rank_1: TensorRank1<D, I>) -> Self {
203        tensor_rank_1.0.to_vec()
204    }
205}
206
207impl<const D: usize, const I: usize> From<Vector> for TensorRank1<D, I> {
208    fn from(_vector: Vector) -> Self {
209        unimplemented!()
210    }
211}
212
213impl<const D: usize, const I: usize> FromIterator<TensorRank0> for TensorRank1<D, I> {
214    fn from_iter<Ii: IntoIterator<Item = TensorRank0>>(into_iterator: Ii) -> Self {
215        let mut tensor_rank_1 = zero();
216        tensor_rank_1
217            .iter_mut()
218            .zip(into_iterator)
219            .for_each(|(tensor_rank_1_i, value_i)| *tensor_rank_1_i = value_i);
220        tensor_rank_1
221    }
222}
223
224impl<const D: usize, const I: usize> Index<usize> for TensorRank1<D, I> {
225    type Output = TensorRank0;
226    fn index(&self, index: usize) -> &Self::Output {
227        &self.0[index]
228    }
229}
230
231impl<const D: usize, const I: usize> IndexMut<usize> for TensorRank1<D, I> {
232    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
233        &mut self.0[index]
234    }
235}
236
237impl<const D: usize, const I: usize> Sum for TensorRank1<D, I> {
238    fn sum<Ii>(iter: Ii) -> Self
239    where
240        Ii: Iterator<Item = Self>,
241    {
242        iter.reduce(|mut acc, item| {
243            acc += item;
244            acc
245        })
246        .unwrap_or_else(Self::default)
247    }
248}
249
250impl<const D: usize, const I: usize> Div<TensorRank0> for TensorRank1<D, I> {
251    type Output = Self;
252    fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
253        self /= tensor_rank_0;
254        self
255    }
256}
257
258impl<const D: usize, const I: usize> Div<TensorRank0> for &TensorRank1<D, I> {
259    type Output = TensorRank1<D, I>;
260    fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
261        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
262    }
263}
264
265impl<const D: usize, const I: usize> Div<&TensorRank0> for TensorRank1<D, I> {
266    type Output = Self;
267    fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
268        self /= tensor_rank_0;
269        self
270    }
271}
272
273impl<const D: usize, const I: usize> Div<&TensorRank0> for &TensorRank1<D, I> {
274    type Output = TensorRank1<D, I>;
275    fn div(self, tensor_rank_0: &TensorRank0) -> Self::Output {
276        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
277    }
278}
279
280impl<const D: usize, const I: usize> DivAssign<TensorRank0> for TensorRank1<D, I> {
281    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
282        self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
283    }
284}
285
286impl<const D: usize, const I: usize> DivAssign<&TensorRank0> for TensorRank1<D, I> {
287    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
288        self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
289    }
290}
291
292impl<const D: usize, const I: usize> Mul<TensorRank0> for TensorRank1<D, I> {
293    type Output = Self;
294    fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
295        self *= tensor_rank_0;
296        self
297    }
298}
299
300impl<const D: usize, const I: usize> Mul<TensorRank0> for &TensorRank1<D, I> {
301    type Output = TensorRank1<D, I>;
302    fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
303        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
304    }
305}
306
307impl<const D: usize, const I: usize> Mul<&TensorRank0> for TensorRank1<D, I> {
308    type Output = Self;
309    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
310        self *= tensor_rank_0;
311        self
312    }
313}
314
315impl<const D: usize, const I: usize> Mul<&TensorRank0> for &TensorRank1<D, I> {
316    type Output = TensorRank1<D, I>;
317    fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
318        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
319    }
320}
321
322impl<const D: usize, const I: usize> MulAssign<TensorRank0> for TensorRank1<D, I> {
323    fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
324        self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
325    }
326}
327
328impl<const D: usize, const I: usize> MulAssign<&TensorRank0> for TensorRank1<D, I> {
329    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
330        self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
331    }
332}
333
334impl<const D: usize, const I: usize> Add for TensorRank1<D, I> {
335    type Output = Self;
336    fn add(mut self, tensor_rank_1: Self) -> Self::Output {
337        self += tensor_rank_1;
338        self
339    }
340}
341
342impl<const D: usize, const I: usize> Add<&Self> for TensorRank1<D, I> {
343    type Output = Self;
344    fn add(mut self, tensor_rank_1: &Self) -> Self::Output {
345        self += tensor_rank_1;
346        self
347    }
348}
349
350impl<const D: usize, const I: usize> Add<TensorRank1<D, I>> for &TensorRank1<D, I> {
351    type Output = TensorRank1<D, I>;
352    fn add(self, mut tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
353        tensor_rank_1 += self;
354        tensor_rank_1
355    }
356}
357
358impl<const D: usize, const I: usize> AddAssign for TensorRank1<D, I> {
359    fn add_assign(&mut self, tensor_rank_1: Self) {
360        self.iter_mut()
361            .zip(tensor_rank_1.iter())
362            .for_each(|(self_i, tensor_rank_1_i)| *self_i += tensor_rank_1_i);
363    }
364}
365
366impl<const D: usize, const I: usize> AddAssign<&Self> for TensorRank1<D, I> {
367    fn add_assign(&mut self, tensor_rank_1: &Self) {
368        self.iter_mut()
369            .zip(tensor_rank_1.iter())
370            .for_each(|(self_i, tensor_rank_1_i)| *self_i += tensor_rank_1_i);
371    }
372}
373
374impl<const D: usize, const I: usize> Sub for TensorRank1<D, I> {
375    type Output = Self;
376    fn sub(mut self, tensor_rank_1: Self) -> Self::Output {
377        self -= tensor_rank_1;
378        self
379    }
380}
381
382impl<const D: usize, const I: usize> Sub<&Self> for TensorRank1<D, I> {
383    type Output = Self;
384    fn sub(mut self, tensor_rank_1: &Self) -> Self::Output {
385        self -= tensor_rank_1;
386        self
387    }
388}
389
390impl<const D: usize, const I: usize> Sub<TensorRank1<D, I>> for &TensorRank1<D, I> {
391    type Output = TensorRank1<D, I>;
392    fn sub(self, mut tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
393        tensor_rank_1
394            .iter_mut()
395            .zip(self.iter())
396            .for_each(|(tensor_rank_1_i, self_i)| *tensor_rank_1_i = self_i - *tensor_rank_1_i);
397        tensor_rank_1
398    }
399}
400
401impl<const D: usize, const I: usize> Sub<Self> for &TensorRank1<D, I> {
402    type Output = TensorRank1<D, I>;
403    fn sub(self, tensor_rank_1: Self) -> Self::Output {
404        tensor_rank_1
405            .iter()
406            .zip(self.iter())
407            .map(|(tensor_rank_1_i, self_i)| self_i - *tensor_rank_1_i)
408            .collect()
409    }
410}
411
412impl<const D: usize, const I: usize> SubAssign for TensorRank1<D, I> {
413    fn sub_assign(&mut self, tensor_rank_1: Self) {
414        self.iter_mut()
415            .zip(tensor_rank_1.iter())
416            .for_each(|(self_i, tensor_rank_1_i)| *self_i -= tensor_rank_1_i);
417    }
418}
419
420impl<const D: usize, const I: usize> SubAssign<&Self> for TensorRank1<D, I> {
421    fn sub_assign(&mut self, tensor_rank_1: &Self) {
422        self.iter_mut()
423            .zip(tensor_rank_1.iter())
424            .for_each(|(self_i, tensor_rank_1_i)| *self_i -= tensor_rank_1_i);
425    }
426}
427
428impl<const D: usize, const I: usize> Mul for TensorRank1<D, I> {
429    type Output = TensorRank0;
430    fn mul(self, tensor_rank_1: Self) -> Self::Output {
431        self.iter()
432            .zip(tensor_rank_1.iter())
433            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
434            .sum()
435    }
436}
437
438impl<const D: usize, const I: usize> Mul<&Self> for TensorRank1<D, I> {
439    type Output = TensorRank0;
440    fn mul(self, tensor_rank_1: &Self) -> Self::Output {
441        self.iter()
442            .zip(tensor_rank_1.iter())
443            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
444            .sum()
445    }
446}
447
448impl<const D: usize, const I: usize> Mul<TensorRank1<D, I>> for &TensorRank1<D, I> {
449    type Output = TensorRank0;
450    fn mul(self, tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
451        self.iter()
452            .zip(tensor_rank_1.iter())
453            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
454            .sum()
455    }
456}
457
458impl<const D: usize, const I: usize> Mul for &TensorRank1<D, I> {
459    type Output = TensorRank0;
460    fn mul(self, tensor_rank_1: Self) -> Self::Output {
461        self.iter()
462            .zip(tensor_rank_1.iter())
463            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
464            .sum()
465    }
466}
467
468#[allow(clippy::suspicious_arithmetic_impl)]
469impl<const D: usize, const I: usize, const J: usize> Div<TensorRank2<D, I, J>>
470    for &TensorRank1<D, I>
471{
472    type Output = TensorRank1<D, J>;
473    fn div(self, tensor_rank_2: TensorRank2<D, I, J>) -> Self::Output {
474        tensor_rank_2.inverse() * self
475    }
476}