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