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