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