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
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
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}