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::new([
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
49pub const LEVI_CIVITA: TensorRank3<3, 1, 1, 1> = TensorRank3(get_levi_civita_parts());
50
51pub const fn get_identity_1010_parts<const I: usize, const J: usize, const K: usize>()
52-> [TensorRank3<3, I, J, K>; 3] {
53    [
54        TensorRank3(get_identity_1010_parts_1()),
55        TensorRank3(get_identity_1010_parts_2()),
56        TensorRank3(get_identity_1010_parts_3()),
57    ]
58}
59
60impl<const D: usize, const I: usize, const J: usize, const K: usize> Display
61    for TensorRank3<D, I, J, K>
62{
63    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
64        write!(f, "[")?;
65        self.iter()
66            .enumerate()
67            .try_for_each(|(i, entry)| write!(f, "{entry},\n\x1B[u\x1B[{}B\x1B[1D", i + 1))?;
68        write!(f, "\x1B[u\x1B[1A\x1B[{}C]", 16 * D + 1)
69    }
70}
71
72#[cfg(test)]
73impl<const D: usize, const I: usize, const J: usize, const K: usize> ErrorTensor
74    for TensorRank3<D, I, J, K>
75{
76    fn error_fd(&self, comparator: &Self, epsilon: TensorRank0) -> Option<(bool, usize)> {
77        let error_count = self
78            .iter()
79            .zip(comparator.iter())
80            .map(|(self_i, comparator_i)| {
81                self_i
82                    .iter()
83                    .zip(comparator_i.iter())
84                    .map(|(self_ij, comparator_ij)| {
85                        self_ij
86                            .iter()
87                            .zip(comparator_ij.iter())
88                            .filter(|&(&self_ijk, &comparator_ijk)| {
89                                (self_ijk / comparator_ijk - 1.0).abs() >= epsilon
90                                    && (self_ijk.abs() >= epsilon
91                                        || comparator_ijk.abs() >= epsilon)
92                            })
93                            .count()
94                    })
95                    .sum::<usize>()
96            })
97            .sum();
98        if error_count > 0 {
99            Some((true, error_count))
100        } else {
101            None
102        }
103    }
104}
105
106impl<const D: usize, const I: usize, const J: usize, const K: usize> Tensor
107    for TensorRank3<D, I, J, K>
108{
109    type Item = TensorRank2<D, J, K>;
110    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
111        self.0.iter()
112    }
113    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
114        self.0.iter_mut()
115    }
116    fn len(&self) -> usize {
117        D
118    }
119    fn size(&self) -> usize {
120        D * D * D
121    }
122}
123
124impl<const D: usize, const I: usize, const J: usize, const K: usize> IntoIterator
125    for TensorRank3<D, I, J, K>
126{
127    type Item = TensorRank2<D, J, K>;
128    type IntoIter = std::array::IntoIter<Self::Item, D>;
129    fn into_iter(self) -> Self::IntoIter {
130        self.0.into_iter()
131    }
132}
133
134impl<const D: usize, const I: usize, const J: usize, const K: usize> TensorArray
135    for TensorRank3<D, I, J, K>
136{
137    type Array = [[[TensorRank0; D]; D]; D];
138    type Item = TensorRank2<D, J, K>;
139    fn as_array(&self) -> Self::Array {
140        let mut array = [[[0.0; D]; D]; D];
141        array
142            .iter_mut()
143            .zip(self.iter())
144            .for_each(|(entry_rank_2, tensor_rank_2)| *entry_rank_2 = tensor_rank_2.as_array());
145        array
146    }
147    fn identity() -> Self {
148        panic!()
149    }
150    fn new(array: Self::Array) -> Self {
151        array.into_iter().map(Self::Item::new).collect()
152    }
153    fn zero() -> Self {
154        Self(from_fn(|_| Self::Item::zero()))
155    }
156}
157
158impl<const D: usize, const I: usize, const J: usize, const K: usize>
159    FromIterator<TensorRank2<D, J, K>> for TensorRank3<D, I, J, K>
160{
161    fn from_iter<Ii: IntoIterator<Item = TensorRank2<D, J, K>>>(into_iterator: Ii) -> Self {
162        let mut tensor_rank_3 = Self::zero();
163        tensor_rank_3
164            .iter_mut()
165            .zip(into_iterator)
166            .for_each(|(tensor_rank_3_i, value_i)| *tensor_rank_3_i = value_i);
167        tensor_rank_3
168    }
169}
170
171impl<const D: usize, const I: usize, const J: usize, const K: usize> Index<usize>
172    for TensorRank3<D, I, J, K>
173{
174    type Output = TensorRank2<D, J, K>;
175    fn index(&self, index: usize) -> &Self::Output {
176        &self.0[index]
177    }
178}
179
180impl<const D: usize, const I: usize, const J: usize, const K: usize> IndexMut<usize>
181    for TensorRank3<D, I, J, K>
182{
183    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
184        &mut self.0[index]
185    }
186}
187
188impl<const D: usize, const I: usize, const J: usize, const K: usize> Sum
189    for TensorRank3<D, I, J, K>
190{
191    fn sum<Ii>(iter: Ii) -> Self
192    where
193        Ii: Iterator<Item = Self>,
194    {
195        iter.reduce(|mut acc, item| {
196            acc += item;
197            acc
198        })
199        .unwrap_or_else(Self::default)
200    }
201}
202
203impl<const D: usize, const I: usize, const J: usize, const K: usize> Div<TensorRank0>
204    for TensorRank3<D, I, J, K>
205{
206    type Output = Self;
207    fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
208        self /= &tensor_rank_0;
209        self
210    }
211}
212
213impl<const D: usize, const I: usize, const J: usize, const K: usize> Div<TensorRank0>
214    for &TensorRank3<D, I, J, K>
215{
216    type Output = TensorRank3<D, I, J, K>;
217    fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
218        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
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> DivAssign<TensorRank0>
233    for TensorRank3<D, I, J, K>
234{
235    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
236        self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
237    }
238}
239
240impl<const D: usize, const I: usize, const J: usize, const K: usize> DivAssign<&TensorRank0>
241    for TensorRank3<D, I, J, K>
242{
243    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
244        self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
245    }
246}
247
248impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank0>
249    for TensorRank3<D, I, J, K>
250{
251    type Output = Self;
252    fn mul(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, const J: usize, const K: usize> Mul<&TensorRank0>
259    for TensorRank3<D, I, J, K>
260{
261    type Output = Self;
262    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
263        self *= tensor_rank_0;
264        self
265    }
266}
267
268impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank0>
269    for &TensorRank3<D, I, J, K>
270{
271    type Output = TensorRank3<D, I, J, K>;
272    fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
273        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
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 = TensorRank3<D, I, J, K>;
281    fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
282        self.iter().map(|self_i| self_i * tensor_rank_0).collect()
283    }
284}
285
286impl<const D: usize, const I: usize, const J: usize, const K: usize> MulAssign<TensorRank0>
287    for TensorRank3<D, I, J, K>
288{
289    fn mul_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, const J: usize, const K: usize> MulAssign<&TensorRank0>
295    for TensorRank3<D, I, J, K>
296{
297    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
298        self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
299    }
300}
301
302impl<const D: usize, const I: usize, const J: usize, const K: usize> Add
303    for TensorRank3<D, I, J, K>
304{
305    type Output = Self;
306    fn add(mut self, tensor_rank_3: Self) -> Self::Output {
307        self += tensor_rank_3;
308        self
309    }
310}
311
312impl<const D: usize, const I: usize, const J: usize, const K: usize> Add<&Self>
313    for TensorRank3<D, I, J, K>
314{
315    type Output = Self;
316    fn add(mut self, tensor_rank_3: &Self) -> Self::Output {
317        self += tensor_rank_3;
318        self
319    }
320}
321
322impl<const D: usize, const I: usize, const J: usize, const K: usize> Add<TensorRank3<D, I, J, K>>
323    for &TensorRank3<D, I, J, K>
324{
325    type Output = TensorRank3<D, I, J, K>;
326    fn add(self, mut tensor_rank_3: TensorRank3<D, I, J, K>) -> Self::Output {
327        tensor_rank_3 += self;
328        tensor_rank_3
329    }
330}
331
332impl<const D: usize, const I: usize, const J: usize, const K: usize> AddAssign
333    for TensorRank3<D, I, J, K>
334{
335    fn add_assign(&mut self, tensor_rank_3: Self) {
336        self.iter_mut()
337            .zip(tensor_rank_3)
338            .for_each(|(self_i, tensor_rank_3_i)| *self_i += tensor_rank_3_i);
339    }
340}
341
342impl<const D: usize, const I: usize, const J: usize, const K: usize> AddAssign<&Self>
343    for TensorRank3<D, I, J, K>
344{
345    fn add_assign(&mut self, tensor_rank_3: &Self) {
346        self.iter_mut()
347            .zip(tensor_rank_3.iter())
348            .for_each(|(self_i, tensor_rank_3_i)| *self_i += tensor_rank_3_i);
349    }
350}
351
352impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub
353    for TensorRank3<D, I, J, K>
354{
355    type Output = Self;
356    fn sub(mut self, tensor_rank_3: Self) -> Self::Output {
357        self -= tensor_rank_3;
358        self
359    }
360}
361
362impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub<&Self>
363    for TensorRank3<D, I, J, K>
364{
365    type Output = Self;
366    fn sub(mut self, tensor_rank_3: &Self) -> Self::Output {
367        self -= tensor_rank_3;
368        self
369    }
370}
371
372impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub
373    for &TensorRank3<D, I, J, K>
374{
375    type Output = TensorRank3<D, I, J, K>;
376    fn sub(self, tensor_rank_3: Self) -> Self::Output {
377        tensor_rank_3
378            .iter()
379            .zip(self.iter())
380            .map(|(tensor_rank_3_i, self_i)| self_i - tensor_rank_3_i)
381            .collect()
382    }
383}
384
385impl<const D: usize, const I: usize, const J: usize, const K: usize> SubAssign
386    for TensorRank3<D, I, J, K>
387{
388    fn sub_assign(&mut self, tensor_rank_3: Self) {
389        self.iter_mut()
390            .zip(tensor_rank_3)
391            .for_each(|(self_i, tensor_rank_3_i)| *self_i -= tensor_rank_3_i);
392    }
393}
394
395impl<const D: usize, const I: usize, const J: usize, const K: usize> SubAssign<&Self>
396    for TensorRank3<D, I, J, K>
397{
398    fn sub_assign(&mut self, tensor_rank_3: &Self) {
399        self.iter_mut()
400            .zip(tensor_rank_3.iter())
401            .for_each(|(self_i, tensor_rank_3_i)| *self_i -= tensor_rank_3_i);
402    }
403}