conspire/math/tensor/rank_3/
mod.rs

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