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
23pub 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#[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<const D: usize, const I: usize, const J: usize, const K: usize> Div<TensorRank0>
209 for TensorRank3<D, I, J, K>
210{
211 type Output = Self;
212 fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
213 self /= &tensor_rank_0;
214 self
215 }
216}
217
218impl<const D: usize, const I: usize, const J: usize, const K: usize> Div<TensorRank0>
219 for &TensorRank3<D, I, J, K>
220{
221 type Output = TensorRank3<D, I, J, K>;
222 fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
223 self.iter().map(|self_i| self_i / tensor_rank_0).collect()
224 }
225}
226
227impl<const D: usize, const I: usize, const J: usize, const K: usize> Div<&TensorRank0>
228 for TensorRank3<D, I, J, K>
229{
230 type Output = Self;
231 fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
232 self /= tensor_rank_0;
233 self
234 }
235}
236
237impl<const D: usize, const I: usize, const J: usize, const K: usize> DivAssign<TensorRank0>
238 for TensorRank3<D, I, J, K>
239{
240 fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
241 self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
242 }
243}
244
245impl<const D: usize, const I: usize, const J: usize, const K: usize> DivAssign<&TensorRank0>
246 for TensorRank3<D, I, J, K>
247{
248 fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
249 self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
250 }
251}
252
253impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank0>
254 for TensorRank3<D, I, J, K>
255{
256 type Output = Self;
257 fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
258 self *= &tensor_rank_0;
259 self
260 }
261}
262
263impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<&TensorRank0>
264 for TensorRank3<D, I, J, K>
265{
266 type Output = Self;
267 fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
268 self *= tensor_rank_0;
269 self
270 }
271}
272
273impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank0>
274 for &TensorRank3<D, I, J, K>
275{
276 type Output = TensorRank3<D, I, J, K>;
277 fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
278 self.iter().map(|self_i| self_i * tensor_rank_0).collect()
279 }
280}
281
282impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<&TensorRank0>
283 for &TensorRank3<D, I, J, K>
284{
285 type Output = TensorRank3<D, I, J, K>;
286 fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
287 self.iter().map(|self_i| self_i * tensor_rank_0).collect()
288 }
289}
290
291impl<const D: usize, const I: usize, const J: usize, const K: usize> MulAssign<TensorRank0>
292 for TensorRank3<D, I, J, K>
293{
294 fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
295 self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
296 }
297}
298
299impl<const D: usize, const I: usize, const J: usize, const K: usize> MulAssign<&TensorRank0>
300 for TensorRank3<D, I, J, K>
301{
302 fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
303 self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
304 }
305}
306
307impl<const D: usize, const I: usize, const J: usize, const K: usize> Add
308 for TensorRank3<D, I, J, K>
309{
310 type Output = Self;
311 fn add(mut self, tensor_rank_3: Self) -> Self::Output {
312 self += tensor_rank_3;
313 self
314 }
315}
316
317impl<const D: usize, const I: usize, const J: usize, const K: usize> Add<&Self>
318 for TensorRank3<D, I, J, K>
319{
320 type Output = Self;
321 fn add(mut self, tensor_rank_3: &Self) -> Self::Output {
322 self += tensor_rank_3;
323 self
324 }
325}
326
327impl<const D: usize, const I: usize, const J: usize, const K: usize> Add<TensorRank3<D, I, J, K>>
328 for &TensorRank3<D, I, J, K>
329{
330 type Output = TensorRank3<D, I, J, K>;
331 fn add(self, mut tensor_rank_3: TensorRank3<D, I, J, K>) -> Self::Output {
332 tensor_rank_3 += self;
333 tensor_rank_3
334 }
335}
336
337impl<const D: usize, const I: usize, const J: usize, const K: usize> AddAssign
338 for TensorRank3<D, I, J, K>
339{
340 fn add_assign(&mut self, tensor_rank_3: Self) {
341 self.iter_mut()
342 .zip(tensor_rank_3)
343 .for_each(|(self_i, tensor_rank_3_i)| *self_i += tensor_rank_3_i);
344 }
345}
346
347impl<const D: usize, const I: usize, const J: usize, const K: usize> AddAssign<&Self>
348 for TensorRank3<D, I, J, K>
349{
350 fn add_assign(&mut self, tensor_rank_3: &Self) {
351 self.iter_mut()
352 .zip(tensor_rank_3.iter())
353 .for_each(|(self_i, tensor_rank_3_i)| *self_i += tensor_rank_3_i);
354 }
355}
356
357impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub
358 for TensorRank3<D, I, J, K>
359{
360 type Output = Self;
361 fn sub(mut self, tensor_rank_3: Self) -> Self::Output {
362 self -= tensor_rank_3;
363 self
364 }
365}
366
367impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub<&Self>
368 for TensorRank3<D, I, J, K>
369{
370 type Output = Self;
371 fn sub(mut self, tensor_rank_3: &Self) -> Self::Output {
372 self -= tensor_rank_3;
373 self
374 }
375}
376
377impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub
378 for &TensorRank3<D, I, J, K>
379{
380 type Output = TensorRank3<D, I, J, K>;
381 fn sub(self, tensor_rank_3: Self) -> Self::Output {
382 tensor_rank_3
383 .iter()
384 .zip(self.iter())
385 .map(|(tensor_rank_3_i, self_i)| self_i - tensor_rank_3_i)
386 .collect()
387 }
388}
389
390impl<const D: usize, const I: usize, const J: usize, const K: usize> SubAssign
391 for TensorRank3<D, I, J, K>
392{
393 fn sub_assign(&mut self, tensor_rank_3: Self) {
394 self.iter_mut()
395 .zip(tensor_rank_3)
396 .for_each(|(self_i, tensor_rank_3_i)| *self_i -= tensor_rank_3_i);
397 }
398}
399
400impl<const D: usize, const I: usize, const J: usize, const K: usize> SubAssign<&Self>
401 for TensorRank3<D, I, J, K>
402{
403 fn sub_assign(&mut self, tensor_rank_3: &Self) {
404 self.iter_mut()
405 .zip(tensor_rank_3.iter())
406 .for_each(|(self_i, tensor_rank_3_i)| *self_i -= tensor_rank_3_i);
407 }
408}