conspire/math/tensor/rank_3/
mod.rs

1#[cfg(test)]
2mod test;
3
4#[cfg(test)]
5use super::test::ErrorTensor;
6
7use std::{
8    array::from_fn,
9    fmt::{self, Display, Formatter},
10    iter::Sum,
11    ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
12};
13
14use super::{
15    Tensor, TensorArray,
16    rank_0::TensorRank0,
17    rank_2::{
18        TensorRank2, get_identity_1010_parts_1, get_identity_1010_parts_2,
19        get_identity_1010_parts_3, get_levi_civita_parts,
20    },
21};
22
23/// Returns the rank-3 Levi-Civita symbol.
24pub fn levi_civita<const I: usize, const J: usize, const K: usize>() -> TensorRank3<3, I, J, K> {
25    TensorRank3::from([
26        [[0.0, 0.0, 0.0], [0.0, 0.0, 1.0], [0.0, -1.0, 0.0]],
27        [[0.0, 0.0, -1.0], [0.0, 0.0, 0.0], [1.0, 0.0, 0.0]],
28        [[0.0, 1.0, 0.0], [-1.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
29    ])
30}
31
32/// A *d*-dimensional tensor of rank 3.
33///
34/// `D` is the dimension, `I`, `J`, `K` are the configurations.
35#[repr(transparent)]
36#[derive(Clone, Debug, PartialEq)]
37pub struct TensorRank3<const D: usize, const I: usize, const J: usize, const K: usize>(
38    [TensorRank2<D, J, K>; D],
39);
40
41impl<const D: usize, const I: usize, const J: usize, const K: usize> Default
42    for TensorRank3<D, I, J, K>
43{
44    fn default() -> Self {
45        Self::zero()
46    }
47}
48
49impl<const D: usize, const I: usize, const J: usize, const K: usize>
50    From<[[[TensorRank0; D]; D]; D]> for TensorRank3<D, I, J, K>
51{
52    fn from(array: [[[TensorRank0; D]; D]; D]) -> Self {
53        array.into_iter().map(|entry| entry.into()).collect()
54    }
55}
56
57pub const LEVI_CIVITA: TensorRank3<3, 1, 1, 1> = TensorRank3(get_levi_civita_parts());
58
59pub const fn get_identity_1010_parts<const I: usize, const J: usize, const K: usize>()
60-> [TensorRank3<3, I, J, K>; 3] {
61    [
62        TensorRank3(get_identity_1010_parts_1()),
63        TensorRank3(get_identity_1010_parts_2()),
64        TensorRank3(get_identity_1010_parts_3()),
65    ]
66}
67
68impl<const D: usize, const I: usize, const J: usize, const K: usize> Display
69    for TensorRank3<D, I, J, K>
70{
71    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
72        write!(f, "[")?;
73        self.iter()
74            .enumerate()
75            .try_for_each(|(i, entry)| write!(f, "{entry},\n\x1B[u\x1B[{}B\x1B[1D", i + 1))?;
76        write!(f, "\x1B[u\x1B[1A\x1B[{}C]", 16 * D + 1)
77    }
78}
79
80#[cfg(test)]
81impl<const D: usize, const I: usize, const J: usize, const K: usize> ErrorTensor
82    for TensorRank3<D, I, J, K>
83{
84    fn error_fd(&self, comparator: &Self, epsilon: TensorRank0) -> Option<(bool, usize)> {
85        let error_count = self
86            .iter()
87            .zip(comparator.iter())
88            .map(|(self_i, comparator_i)| {
89                self_i
90                    .iter()
91                    .zip(comparator_i.iter())
92                    .map(|(self_ij, comparator_ij)| {
93                        self_ij
94                            .iter()
95                            .zip(comparator_ij.iter())
96                            .filter(|&(&self_ijk, &comparator_ijk)| {
97                                (self_ijk / comparator_ijk - 1.0).abs() >= epsilon
98                                    && (self_ijk.abs() >= epsilon
99                                        || comparator_ijk.abs() >= epsilon)
100                            })
101                            .count()
102                    })
103                    .sum::<usize>()
104            })
105            .sum();
106        if error_count > 0 {
107            Some((true, error_count))
108        } else {
109            None
110        }
111    }
112}
113
114impl<const D: usize, const I: usize, const J: usize, const K: usize> Tensor
115    for TensorRank3<D, I, J, K>
116{
117    type Item = TensorRank2<D, J, K>;
118    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
119        self.0.iter()
120    }
121    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
122        self.0.iter_mut()
123    }
124    fn len(&self) -> usize {
125        D
126    }
127    fn size(&self) -> usize {
128        D * D * D
129    }
130}
131
132impl<const D: usize, const I: usize, const J: usize, const K: usize> IntoIterator
133    for TensorRank3<D, I, J, K>
134{
135    type Item = TensorRank2<D, J, K>;
136    type IntoIter = std::array::IntoIter<Self::Item, D>;
137    fn into_iter(self) -> Self::IntoIter {
138        self.0.into_iter()
139    }
140}
141
142impl<const D: usize, const I: usize, const J: usize, const K: usize> TensorArray
143    for TensorRank3<D, I, J, K>
144{
145    type Array = [[[TensorRank0; D]; D]; D];
146    type Item = TensorRank2<D, J, K>;
147    fn as_array(&self) -> Self::Array {
148        let mut array = [[[0.0; D]; D]; D];
149        array
150            .iter_mut()
151            .zip(self.iter())
152            .for_each(|(entry_rank_2, tensor_rank_2)| *entry_rank_2 = tensor_rank_2.as_array());
153        array
154    }
155    fn identity() -> Self {
156        panic!()
157    }
158    fn zero() -> Self {
159        Self(from_fn(|_| Self::Item::zero()))
160    }
161}
162
163impl<const D: usize, const I: usize, const J: usize, const K: usize>
164    FromIterator<TensorRank2<D, J, K>> for TensorRank3<D, I, J, K>
165{
166    fn from_iter<Ii: IntoIterator<Item = TensorRank2<D, J, K>>>(into_iterator: Ii) -> Self {
167        let mut tensor_rank_3 = Self::zero();
168        tensor_rank_3
169            .iter_mut()
170            .zip(into_iterator)
171            .for_each(|(tensor_rank_3_i, value_i)| *tensor_rank_3_i = value_i);
172        tensor_rank_3
173    }
174}
175
176impl<const D: usize, const I: usize, const J: usize, const K: usize> Index<usize>
177    for TensorRank3<D, I, J, K>
178{
179    type Output = TensorRank2<D, J, K>;
180    fn index(&self, index: usize) -> &Self::Output {
181        &self.0[index]
182    }
183}
184
185impl<const D: usize, const I: usize, const J: usize, const K: usize> IndexMut<usize>
186    for TensorRank3<D, I, J, K>
187{
188    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
189        &mut self.0[index]
190    }
191}
192
193impl<const D: usize, const I: usize, const J: usize, const K: usize> Sum
194    for TensorRank3<D, I, J, K>
195{
196    fn sum<Ii>(iter: Ii) -> Self
197    where
198        Ii: Iterator<Item = Self>,
199    {
200        iter.reduce(|mut acc, item| {
201            acc += item;
202            acc
203        })
204        .unwrap_or_else(Self::default)
205    }
206}
207
208impl<'a, const D: usize, const I: usize, const J: usize, const K: usize> Sum<&'a Self>
209    for TensorRank3<D, I, J, K>
210{
211    fn sum<Ii>(iter: Ii) -> Self
212    where
213        Ii: Iterator<Item = &'a Self>,
214    {
215        iter.fold(Self::default(), |mut acc, item| {
216            acc += item;
217            acc
218        })
219    }
220}
221
222impl<const D: usize, const I: usize, const J: usize, const K: usize> Div<TensorRank0>
223    for TensorRank3<D, I, J, K>
224{
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, const J: usize, const K: usize> Div<TensorRank0>
233    for &TensorRank3<D, I, J, K>
234{
235    type Output = TensorRank3<D, I, J, K>;
236    fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
237        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
238    }
239}
240
241impl<const D: usize, const I: usize, const J: usize, const K: usize> Div<&TensorRank0>
242    for TensorRank3<D, I, J, K>
243{
244    type Output = Self;
245    fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
246        self /= tensor_rank_0;
247        self
248    }
249}
250
251impl<const D: usize, const I: usize, const J: usize, const K: usize> DivAssign<TensorRank0>
252    for TensorRank3<D, I, J, K>
253{
254    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
255        self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
256    }
257}
258
259impl<const D: usize, const I: usize, const J: usize, const K: usize> DivAssign<&TensorRank0>
260    for TensorRank3<D, I, J, K>
261{
262    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
263        self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
264    }
265}
266
267impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank0>
268    for TensorRank3<D, I, J, K>
269{
270    type Output = Self;
271    fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
272        self *= &tensor_rank_0;
273        self
274    }
275}
276
277impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<&TensorRank0>
278    for TensorRank3<D, I, J, K>
279{
280    type Output = Self;
281    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
282        self *= tensor_rank_0;
283        self
284    }
285}
286
287impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank0>
288    for &TensorRank3<D, I, J, K>
289{
290    type Output = TensorRank3<D, I, J, K>;
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, const J: usize, const K: usize> Mul<&TensorRank0>
297    for &TensorRank3<D, I, J, K>
298{
299    type Output = TensorRank3<D, I, J, K>;
300    fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
301        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
302    }
303}
304
305impl<const D: usize, const I: usize, const J: usize, const K: usize> MulAssign<TensorRank0>
306    for TensorRank3<D, I, J, K>
307{
308    fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
309        self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
310    }
311}
312
313impl<const D: usize, const I: usize, const J: usize, const K: usize> MulAssign<&TensorRank0>
314    for TensorRank3<D, I, J, K>
315{
316    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
317        self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
318    }
319}
320
321impl<const D: usize, const I: usize, const J: usize, const K: usize> Add
322    for TensorRank3<D, I, J, K>
323{
324    type Output = Self;
325    fn add(mut self, tensor_rank_3: Self) -> Self::Output {
326        self += tensor_rank_3;
327        self
328    }
329}
330
331impl<const D: usize, const I: usize, const J: usize, const K: usize> Add<&Self>
332    for TensorRank3<D, I, J, K>
333{
334    type Output = Self;
335    fn add(mut self, tensor_rank_3: &Self) -> Self::Output {
336        self += tensor_rank_3;
337        self
338    }
339}
340
341impl<const D: usize, const I: usize, const J: usize, const K: usize> Add<TensorRank3<D, I, J, K>>
342    for &TensorRank3<D, I, J, K>
343{
344    type Output = TensorRank3<D, I, J, K>;
345    fn add(self, mut tensor_rank_3: TensorRank3<D, I, J, K>) -> Self::Output {
346        tensor_rank_3 += self;
347        tensor_rank_3
348    }
349}
350
351impl<const D: usize, const I: usize, const J: usize, const K: usize> AddAssign
352    for TensorRank3<D, I, J, K>
353{
354    fn add_assign(&mut self, tensor_rank_3: Self) {
355        self.iter_mut()
356            .zip(tensor_rank_3)
357            .for_each(|(self_i, tensor_rank_3_i)| *self_i += tensor_rank_3_i);
358    }
359}
360
361impl<const D: usize, const I: usize, const J: usize, const K: usize> AddAssign<&Self>
362    for TensorRank3<D, I, J, K>
363{
364    fn add_assign(&mut self, tensor_rank_3: &Self) {
365        self.iter_mut()
366            .zip(tensor_rank_3.iter())
367            .for_each(|(self_i, tensor_rank_3_i)| *self_i += tensor_rank_3_i);
368    }
369}
370
371impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub
372    for TensorRank3<D, I, J, K>
373{
374    type Output = Self;
375    fn sub(mut self, tensor_rank_3: Self) -> Self::Output {
376        self -= tensor_rank_3;
377        self
378    }
379}
380
381impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub<&Self>
382    for TensorRank3<D, I, J, K>
383{
384    type Output = Self;
385    fn sub(mut self, tensor_rank_3: &Self) -> Self::Output {
386        self -= tensor_rank_3;
387        self
388    }
389}
390
391impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub
392    for &TensorRank3<D, I, J, K>
393{
394    type Output = TensorRank3<D, I, J, K>;
395    fn sub(self, tensor_rank_3: Self) -> Self::Output {
396        tensor_rank_3
397            .iter()
398            .zip(self.iter())
399            .map(|(tensor_rank_3_i, self_i)| self_i - tensor_rank_3_i)
400            .collect()
401    }
402}
403
404impl<const D: usize, const I: usize, const J: usize, const K: usize> SubAssign
405    for TensorRank3<D, I, J, K>
406{
407    fn sub_assign(&mut self, tensor_rank_3: Self) {
408        self.iter_mut()
409            .zip(tensor_rank_3)
410            .for_each(|(self_i, tensor_rank_3_i)| *self_i -= tensor_rank_3_i);
411    }
412}
413
414impl<const D: usize, const I: usize, const J: usize, const K: usize> SubAssign<&Self>
415    for TensorRank3<D, I, J, K>
416{
417    fn sub_assign(&mut self, tensor_rank_3: &Self) {
418        self.iter_mut()
419            .zip(tensor_rank_3.iter())
420            .for_each(|(self_i, tensor_rank_3_i)| *self_i -= tensor_rank_3_i);
421    }
422}