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    array::from_fn,
11    fmt::{self, Display, Formatter},
12    iter::Sum,
13    ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, 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#[derive(Clone, Debug, PartialEq)]
28pub struct TensorRank1<const D: usize, const I: usize>([TensorRank0; D]);
29
30impl<const D: usize, const I: usize> TensorRank1<D, I> {
31    /// Associated function for const type conversion.
32    pub const fn const_from(array: [TensorRank0; D]) -> Self {
33        Self(array)
34    }
35}
36
37impl<const D: usize, const I: usize> Default for TensorRank1<D, I> {
38    fn default() -> Self {
39        Self::zero()
40    }
41}
42
43impl<const D: usize> From<TensorRank1<D, 0>> for TensorRank1<D, 1> {
44    fn from(tensor_rank_1: TensorRank1<D, 0>) -> Self {
45        Self(tensor_rank_1.0)
46    }
47}
48
49impl<const D: usize> From<&TensorRank1<D, 0>> for TensorRank1<D, 1> {
50    fn from(tensor_rank_1: &TensorRank1<D, 0>) -> Self {
51        Self(tensor_rank_1.0)
52    }
53}
54
55impl<const D: usize> From<TensorRank1<D, 1>> for TensorRank1<D, 0> {
56    fn from(tensor_rank_1: TensorRank1<D, 1>) -> Self {
57        Self(tensor_rank_1.0)
58    }
59}
60
61impl<const D: usize> From<&TensorRank1<D, 1>> for TensorRank1<D, 0> {
62    fn from(tensor_rank_1: &TensorRank1<D, 1>) -> Self {
63        Self(tensor_rank_1.0)
64    }
65}
66
67impl<const D: usize> From<TensorRank1<D, 9>> for TensorRank1<D, 0> {
68    fn from(tensor_rank_1: TensorRank1<D, 9>) -> Self {
69        Self(tensor_rank_1.0)
70    }
71}
72
73impl<const D: usize> From<&TensorRank1<D, 9>> for TensorRank1<D, 0> {
74    fn from(tensor_rank_1: &TensorRank1<D, 9>) -> Self {
75        Self(tensor_rank_1.0)
76    }
77}
78
79impl<const D: usize, const I: usize> Display for TensorRank1<D, I> {
80    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
81        write!(f, "\x1B[s")?;
82        write!(f, "[")?;
83        self.iter()
84            .try_for_each(|entry| write_tensor_rank_0(f, entry))?;
85        write!(f, "\x1B[2D]")
86    }
87}
88
89impl<const D: usize, const I: usize> TensorRank1<D, I> {
90    /// Returns a raw pointer to the slice’s buffer.
91    pub const fn as_ptr(&self) -> *const TensorRank0 {
92        self.0.as_ptr()
93    }
94    /// Returns the cross product with another rank-1 tensor.
95    pub fn cross(&self, tensor_rank_1: &Self) -> Self {
96        if D == 3 {
97            let mut output = zero();
98            output[0] = self[1] * tensor_rank_1[2] - self[2] * tensor_rank_1[1];
99            output[1] = self[2] * tensor_rank_1[0] - self[0] * tensor_rank_1[2];
100            output[2] = self[0] * tensor_rank_1[1] - self[1] * tensor_rank_1[0];
101            output
102        } else {
103            panic!()
104        }
105    }
106}
107
108#[cfg(test)]
109impl<const D: usize, const I: usize> ErrorTensor for TensorRank1<D, I> {
110    fn error_fd(&self, comparator: &Self, epsilon: TensorRank0) -> Option<(bool, usize)> {
111        let error_count = self
112            .iter()
113            .zip(comparator.iter())
114            .filter(|&(&self_i, &comparator_i)| {
115                (self_i / comparator_i - 1.0).abs() >= epsilon
116                    && (self_i.abs() >= epsilon || comparator_i.abs() >= epsilon)
117            })
118            .count();
119        if error_count > 0 {
120            Some((true, error_count))
121        } else {
122            None
123        }
124    }
125}
126
127impl<const D: usize, const I: usize> Solution for TensorRank1<D, I> {
128    fn decrement_from(&mut self, _other: &Vector) {
129        unimplemented!()
130    }
131    fn decrement_from_chained(&mut self, _other: &mut Vector, _vector: Vector) {
132        unimplemented!()
133    }
134}
135
136impl<const D: usize, const I: usize> Jacobian for TensorRank1<D, I> {
137    fn fill_into(self, _vector: &mut Vector) {
138        unimplemented!()
139    }
140    fn fill_into_chained(self, _other: Vector, _vector: &mut Vector) {
141        unimplemented!()
142    }
143}
144
145impl<const D: usize, const I: usize> Sub<Vector> for TensorRank1<D, I> {
146    type Output = Self;
147    fn sub(self, _vector: Vector) -> Self::Output {
148        unimplemented!()
149    }
150}
151
152impl<const D: usize, const I: usize> Sub<&Vector> for TensorRank1<D, I> {
153    type Output = Self;
154    fn sub(self, _vector: &Vector) -> Self::Output {
155        unimplemented!()
156    }
157}
158
159impl<const D: usize, const I: usize> Tensor for TensorRank1<D, I> {
160    type Item = TensorRank0;
161    fn full_contraction(&self, tensor_rank_1: &Self) -> TensorRank0 {
162        self * tensor_rank_1
163    }
164    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
165        self.0.iter()
166    }
167    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
168        self.0.iter_mut()
169    }
170    fn len(&self) -> usize {
171        D
172    }
173    fn size(&self) -> usize {
174        D
175    }
176}
177
178impl<const D: usize, const I: usize> IntoIterator for TensorRank1<D, I> {
179    type Item = TensorRank0;
180    type IntoIter = std::array::IntoIter<Self::Item, D>;
181    fn into_iter(self) -> Self::IntoIter {
182        self.0.into_iter()
183    }
184}
185
186impl<const D: usize, const I: usize> TensorArray for TensorRank1<D, I> {
187    type Array = [TensorRank0; D];
188    type Item = TensorRank0;
189    fn as_array(&self) -> Self::Array {
190        self.0
191    }
192    fn identity() -> Self {
193        ones()
194    }
195    fn zero() -> Self {
196        zero()
197    }
198}
199
200/// Returns the rank-1 tensor of ones as a constant.
201pub const fn ones<const D: usize, const I: usize>() -> TensorRank1<D, I> {
202    TensorRank1([1.0; D])
203}
204
205/// Returns the rank-1 zero tensor as a constant.
206pub const fn zero<const D: usize, const I: usize>() -> TensorRank1<D, I> {
207    TensorRank1([0.0; D])
208}
209
210impl<const D: usize, const I: usize> From<[TensorRank0; D]> for TensorRank1<D, I> {
211    fn from(array: [TensorRank0; D]) -> Self {
212        Self(array)
213    }
214}
215
216impl<const D: usize, const I: usize> From<TensorRank1<D, I>> for [TensorRank0; D] {
217    fn from(tensor_rank_1: TensorRank1<D, I>) -> Self {
218        tensor_rank_1.0
219    }
220}
221
222impl<const D: usize, const I: usize> From<Vec<TensorRank0>> for TensorRank1<D, I> {
223    fn from(vec: Vec<TensorRank0>) -> Self {
224        Self(vec.try_into().unwrap())
225    }
226}
227
228impl<const D: usize, const I: usize> From<TensorRank1<D, I>> for Vec<TensorRank0> {
229    fn from(tensor_rank_1: TensorRank1<D, I>) -> Self {
230        tensor_rank_1.0.to_vec()
231    }
232}
233
234impl<const D: usize, const I: usize> From<Vector> for TensorRank1<D, I> {
235    fn from(_vector: Vector) -> Self {
236        unimplemented!()
237    }
238}
239
240impl<const D: usize, const I: usize> FromIterator<TensorRank0> for TensorRank1<D, I> {
241    fn from_iter<Ii: IntoIterator<Item = TensorRank0>>(into_iterator: Ii) -> Self {
242        let mut tensor_rank_1 = zero();
243        tensor_rank_1
244            .iter_mut()
245            .zip(into_iterator)
246            .for_each(|(tensor_rank_1_i, value_i)| *tensor_rank_1_i = value_i);
247        tensor_rank_1
248    }
249}
250
251impl<const D: usize, const I: usize> Index<usize> for TensorRank1<D, I> {
252    type Output = TensorRank0;
253    fn index(&self, index: usize) -> &Self::Output {
254        &self.0[index]
255    }
256}
257
258impl<const D: usize, const I: usize> IndexMut<usize> for TensorRank1<D, I> {
259    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
260        &mut self.0[index]
261    }
262}
263
264impl<const D: usize, const I: usize> Sum for TensorRank1<D, I> {
265    fn sum<Ii>(iter: Ii) -> Self
266    where
267        Ii: Iterator<Item = Self>,
268    {
269        iter.reduce(|mut acc, item| {
270            acc += item;
271            acc
272        })
273        .unwrap_or_else(Self::default)
274    }
275}
276
277impl<'a, const D: usize, const I: usize> Sum<&'a Self> for TensorRank1<D, I> {
278    fn sum<Ii>(iter: Ii) -> Self
279    where
280        Ii: Iterator<Item = &'a Self>,
281    {
282        iter.fold(Self::default(), |mut acc, item| {
283            acc += item;
284            acc
285        })
286    }
287}
288
289impl<const D: usize, const I: usize> Neg for TensorRank1<D, I> {
290    type Output = Self;
291    fn neg(self) -> Self::Output {
292        from_fn(|i| -self[i]).into()
293    }
294}
295
296impl<const D: usize, const I: usize> Neg for &TensorRank1<D, I> {
297    type Output = TensorRank1<D, I>;
298    fn neg(self) -> Self::Output {
299        from_fn(|i| -self[i]).into()
300    }
301}
302
303impl<const D: usize, const I: usize> Div<TensorRank0> for TensorRank1<D, I> {
304    type Output = Self;
305    fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
306        self /= tensor_rank_0;
307        self
308    }
309}
310
311impl<const D: usize, const I: usize> Div<TensorRank0> for &TensorRank1<D, I> {
312    type Output = TensorRank1<D, I>;
313    fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
314        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
315    }
316}
317
318impl<const D: usize, const I: usize> Div<&TensorRank0> for TensorRank1<D, I> {
319    type Output = Self;
320    fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
321        self /= tensor_rank_0;
322        self
323    }
324}
325
326impl<const D: usize, const I: usize> Div<&TensorRank0> for &TensorRank1<D, I> {
327    type Output = TensorRank1<D, I>;
328    fn div(self, tensor_rank_0: &TensorRank0) -> Self::Output {
329        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
330    }
331}
332
333impl<const D: usize, const I: usize> DivAssign<TensorRank0> for TensorRank1<D, I> {
334    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
335        self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
336    }
337}
338
339impl<const D: usize, const I: usize> DivAssign<&TensorRank0> for TensorRank1<D, I> {
340    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
341        self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
342    }
343}
344
345impl<const D: usize, const I: usize> Mul<TensorRank0> for TensorRank1<D, I> {
346    type Output = Self;
347    fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
348        self *= tensor_rank_0;
349        self
350    }
351}
352
353impl<const D: usize, const I: usize> Mul<TensorRank0> for &TensorRank1<D, I> {
354    type Output = TensorRank1<D, I>;
355    fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
356        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
357    }
358}
359
360impl<const D: usize, const I: usize> Mul<&TensorRank0> for TensorRank1<D, I> {
361    type Output = Self;
362    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
363        self *= tensor_rank_0;
364        self
365    }
366}
367
368impl<const D: usize, const I: usize> Mul<&TensorRank0> for &TensorRank1<D, I> {
369    type Output = TensorRank1<D, I>;
370    fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
371        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
372    }
373}
374
375impl<const D: usize, const I: usize> MulAssign<TensorRank0> for TensorRank1<D, I> {
376    fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
377        self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
378    }
379}
380
381impl<const D: usize, const I: usize> MulAssign<&TensorRank0> for TensorRank1<D, I> {
382    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
383        self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
384    }
385}
386
387impl<const D: usize, const I: usize> Add for TensorRank1<D, I> {
388    type Output = Self;
389    fn add(mut self, tensor_rank_1: Self) -> Self::Output {
390        self += tensor_rank_1;
391        self
392    }
393}
394
395impl<const D: usize, const I: usize> Add<&Self> for TensorRank1<D, I> {
396    type Output = Self;
397    fn add(mut self, tensor_rank_1: &Self) -> Self::Output {
398        self += tensor_rank_1;
399        self
400    }
401}
402
403impl<const D: usize, const I: usize> Add<TensorRank1<D, I>> for &TensorRank1<D, I> {
404    type Output = TensorRank1<D, I>;
405    fn add(self, mut tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
406        tensor_rank_1 += self;
407        tensor_rank_1
408    }
409}
410
411impl<const D: usize, const I: usize> Add<Self> for &TensorRank1<D, I> {
412    type Output = TensorRank1<D, I>;
413    fn add(self, tensor_rank_1: Self) -> Self::Output {
414        tensor_rank_1
415            .iter()
416            .zip(self.iter())
417            .map(|(tensor_rank_1_i, self_i)| self_i + *tensor_rank_1_i)
418            .collect()
419    }
420}
421
422impl<const D: usize, const I: usize> AddAssign for TensorRank1<D, I> {
423    fn add_assign(&mut self, tensor_rank_1: Self) {
424        self.iter_mut()
425            .zip(tensor_rank_1)
426            .for_each(|(self_i, tensor_rank_1_i)| *self_i += tensor_rank_1_i);
427    }
428}
429
430impl<const D: usize, const I: usize> AddAssign<&Self> for TensorRank1<D, I> {
431    fn add_assign(&mut self, tensor_rank_1: &Self) {
432        self.iter_mut()
433            .zip(tensor_rank_1.iter())
434            .for_each(|(self_i, tensor_rank_1_i)| *self_i += tensor_rank_1_i);
435    }
436}
437
438impl<const D: usize, const I: usize> Sub for TensorRank1<D, I> {
439    type Output = Self;
440    fn sub(mut self, tensor_rank_1: Self) -> Self::Output {
441        self -= tensor_rank_1;
442        self
443    }
444}
445
446impl<const D: usize, const I: usize> Sub<&Self> for TensorRank1<D, I> {
447    type Output = Self;
448    fn sub(mut self, tensor_rank_1: &Self) -> Self::Output {
449        self -= tensor_rank_1;
450        self
451    }
452}
453
454impl<const D: usize, const I: usize> Sub<TensorRank1<D, I>> for &TensorRank1<D, I> {
455    type Output = TensorRank1<D, I>;
456    fn sub(self, mut tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
457        tensor_rank_1
458            .iter_mut()
459            .zip(self.iter())
460            .for_each(|(tensor_rank_1_i, self_i)| *tensor_rank_1_i = self_i - *tensor_rank_1_i);
461        tensor_rank_1
462    }
463}
464
465impl<const D: usize, const I: usize> Sub<Self> for &TensorRank1<D, I> {
466    type Output = TensorRank1<D, I>;
467    fn sub(self, tensor_rank_1: Self) -> Self::Output {
468        tensor_rank_1
469            .iter()
470            .zip(self.iter())
471            .map(|(tensor_rank_1_i, self_i)| self_i - *tensor_rank_1_i)
472            .collect()
473    }
474}
475
476impl<const D: usize, const I: usize> SubAssign for TensorRank1<D, I> {
477    fn sub_assign(&mut self, tensor_rank_1: Self) {
478        self.iter_mut()
479            .zip(tensor_rank_1)
480            .for_each(|(self_i, tensor_rank_1_i)| *self_i -= tensor_rank_1_i);
481    }
482}
483
484impl<const D: usize, const I: usize> SubAssign<&Self> for TensorRank1<D, I> {
485    fn sub_assign(&mut self, tensor_rank_1: &Self) {
486        self.iter_mut()
487            .zip(tensor_rank_1.iter())
488            .for_each(|(self_i, tensor_rank_1_i)| *self_i -= tensor_rank_1_i);
489    }
490}
491
492impl<const D: usize, const I: usize> Mul for TensorRank1<D, I> {
493    type Output = TensorRank0;
494    fn mul(self, tensor_rank_1: Self) -> Self::Output {
495        self.into_iter()
496            .zip(tensor_rank_1)
497            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
498            .sum()
499    }
500}
501
502impl<const D: usize, const I: usize> Mul<&Self> for TensorRank1<D, I> {
503    type Output = TensorRank0;
504    fn mul(self, tensor_rank_1: &Self) -> Self::Output {
505        self.into_iter()
506            .zip(tensor_rank_1.iter())
507            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
508            .sum()
509    }
510}
511
512impl<const D: usize, const I: usize> Mul<TensorRank1<D, I>> for &TensorRank1<D, I> {
513    type Output = TensorRank0;
514    fn mul(self, tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
515        self.iter()
516            .zip(tensor_rank_1)
517            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
518            .sum()
519    }
520}
521
522impl<const D: usize, const I: usize> Mul for &TensorRank1<D, I> {
523    type Output = TensorRank0;
524    fn mul(self, tensor_rank_1: Self) -> Self::Output {
525        self.iter()
526            .zip(tensor_rank_1.iter())
527            .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
528            .sum()
529    }
530}
531
532#[allow(clippy::suspicious_arithmetic_impl)]
533impl<const D: usize, const I: usize, const J: usize> Div<TensorRank2<D, I, J>>
534    for &TensorRank1<D, I>
535{
536    type Output = TensorRank1<D, J>;
537    fn div(self, tensor_rank_2: TensorRank2<D, I, J>) -> Self::Output {
538        tensor_rank_2.inverse() * self
539    }
540}