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 ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
11};
12
13use super::{
14 Hessian, Rank2, SquareMatrix, Tensor, TensorArray, Vector,
15 rank_0::TensorRank0,
16 rank_1::TensorRank1,
17 rank_2::TensorRank2,
18 rank_3::{TensorRank3, get_identity_1010_parts},
19};
20
21pub mod list;
22
23#[derive(Clone, Debug, PartialEq)]
27pub struct TensorRank4<
28 const D: usize,
29 const I: usize,
30 const J: usize,
31 const K: usize,
32 const L: usize,
33>([TensorRank3<D, J, K, L>; D]);
34
35pub const IDENTITY_1010: TensorRank4<3, 1, 0, 1, 0> = TensorRank4(get_identity_1010_parts());
36
37impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
38 From<Vec<Vec<Vec<Vec<TensorRank0>>>>> for TensorRank4<D, I, J, K, L>
39{
40 fn from(vec_rank_4: Vec<Vec<Vec<Vec<TensorRank0>>>>) -> Self {
41 vec_rank_4
42 .into_iter()
43 .map(|vec_rank_3| {
44 vec_rank_3
45 .into_iter()
46 .map(|vec_rank_2| {
47 vec_rank_2
48 .into_iter()
49 .map(|vec_rank_1| vec_rank_1.into_iter().collect())
50 .collect()
51 })
52 .collect()
53 })
54 .collect()
55 }
56}
57
58impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
59 From<TensorRank4<D, I, J, K, L>> for Vec<Vec<Vec<Vec<TensorRank0>>>>
60{
61 fn from(tensor_rank_4: TensorRank4<D, I, J, K, L>) -> Self {
62 tensor_rank_4
63 .iter()
64 .map(|tensor_rank_3| {
65 tensor_rank_3
66 .iter()
67 .map(|tensor_rank_2| {
68 tensor_rank_2
69 .iter()
70 .map(|tensor_rank_1| tensor_rank_1.iter().copied().collect())
71 .collect()
72 })
73 .collect()
74 })
75 .collect()
76 }
77}
78
79impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
80 From<TensorRank4<D, I, J, K, L>> for Vec<TensorRank0>
81{
82 fn from(tensor_rank_4: TensorRank4<D, I, J, K, L>) -> Self {
83 tensor_rank_4
84 .iter()
85 .flat_map(|tensor_rank_3| {
86 tensor_rank_3.iter().flat_map(|tensor_rank_2| {
87 tensor_rank_2
88 .iter()
89 .flat_map(|tensor_rank_1| tensor_rank_1.iter().copied())
90 })
91 })
92 .collect()
93 }
94}
95
96impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
97 From<TensorRank4<D, I, J, K, L>> for Vector
98{
99 fn from(tensor_rank_4: TensorRank4<D, I, J, K, L>) -> Self {
100 tensor_rank_4
101 .iter()
102 .flat_map(|tensor_rank_3| {
103 tensor_rank_3.iter().flat_map(|tensor_rank_2| {
104 tensor_rank_2
105 .iter()
106 .flat_map(|tensor_rank_1| tensor_rank_1.iter().copied())
107 })
108 })
109 .collect()
110 }
111}
112
113impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> Display
114 for TensorRank4<D, I, J, K, L>
115{
116 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
117 write!(f, "[")?;
118 self.iter()
119 .enumerate()
120 .try_for_each(|(i, entry)| write!(f, "{entry},\n\x1B[u\x1B[{}B\x1B[2D", i + 1))?;
121 write!(f, "\x1B[u\x1B[1A\x1B[{}C]", 16 * D + 2)
122 }
123}
124
125#[cfg(test)]
126impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> ErrorTensor
127 for TensorRank4<D, I, J, K, L>
128{
129 fn error_fd(&self, comparator: &Self, epsilon: &TensorRank0) -> Option<(bool, usize)> {
130 let error_count = self
131 .iter()
132 .zip(comparator.iter())
133 .map(|(self_i, comparator_i)| {
134 self_i
135 .iter()
136 .zip(comparator_i.iter())
137 .map(|(self_ij, comparator_ij)| {
138 self_ij
139 .iter()
140 .zip(comparator_ij.iter())
141 .map(|(self_ijk, comparator_ijk)| {
142 self_ijk
143 .iter()
144 .zip(comparator_ijk.iter())
145 .filter(|&(&self_ijkl, &comparator_ijkl)| {
146 &(self_ijkl / comparator_ijkl - 1.0).abs() >= epsilon
147 && (&self_ijkl.abs() >= epsilon
148 || &comparator_ijkl.abs() >= epsilon)
149 })
150 .count()
151 })
152 .sum::<usize>()
153 })
154 .sum::<usize>()
155 })
156 .sum();
157 if error_count > 0 {
158 let auxiliary = self
159 .iter()
160 .zip(comparator.iter())
161 .map(|(self_i, comparator_i)| {
162 self_i
163 .iter()
164 .zip(comparator_i.iter())
165 .map(|(self_ij, comparator_ij)| {
166 self_ij
167 .iter()
168 .zip(comparator_ij.iter())
169 .map(|(self_ijk, comparator_ijk)| {
170 self_ijk
171 .iter()
172 .zip(comparator_ijk.iter())
173 .filter(|&(&self_ijkl, &comparator_ijkl)| {
174 &(self_ijkl / comparator_ijkl - 1.0).abs() >= epsilon
175 && &(self_ijkl - comparator_ijkl).abs() >= epsilon
176 && (&self_ijkl.abs() >= epsilon
177 || &comparator_ijkl.abs() >= epsilon)
178 })
179 .count()
180 })
181 .sum::<usize>()
182 })
183 .sum::<usize>()
184 })
185 .sum::<usize>()
186 > 0;
187 Some((auxiliary, error_count))
188 } else {
189 None
190 }
191 }
192}
193
194impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
195 TensorRank4<D, I, J, K, L>
196{
197 pub fn dyad_ij_kl(
198 tensor_rank_2_a: &TensorRank2<D, I, J>,
199 tensor_rank_2_b: &TensorRank2<D, K, L>,
200 ) -> Self {
201 tensor_rank_2_a
202 .iter()
203 .map(|tensor_rank_2_a_i| {
204 tensor_rank_2_a_i
205 .iter()
206 .map(|tensor_rank_2_a_ij| tensor_rank_2_b * tensor_rank_2_a_ij)
207 .collect()
208 })
209 .collect()
210 }
211 pub fn dyad_ik_jl(
212 tensor_rank_2_a: &TensorRank2<D, I, K>,
213 tensor_rank_2_b: &TensorRank2<D, J, L>,
214 ) -> Self {
215 tensor_rank_2_a
216 .iter()
217 .map(|tensor_rank_2_a_i| {
218 tensor_rank_2_b
219 .iter()
220 .map(|tensor_rank_2_b_j| {
221 tensor_rank_2_a_i
222 .iter()
223 .map(|tensor_rank_2_a_ik| tensor_rank_2_b_j * tensor_rank_2_a_ik)
224 .collect()
225 })
226 .collect()
227 })
228 .collect()
229 }
230 pub fn dyad_il_jk(
231 tensor_rank_2_a: &TensorRank2<D, I, L>,
232 tensor_rank_2_b: &TensorRank2<D, J, K>,
233 ) -> Self {
234 tensor_rank_2_a
235 .iter()
236 .map(|tensor_rank_2_a_i| {
237 tensor_rank_2_b
238 .iter()
239 .map(|tensor_rank_2_b_j| {
240 tensor_rank_2_b_j
241 .iter()
242 .map(|tensor_rank_2_b_jk| tensor_rank_2_a_i * tensor_rank_2_b_jk)
243 .collect()
244 })
245 .collect()
246 })
247 .collect()
248 }
249 pub fn dyad_il_kj(
250 tensor_rank_2_a: &TensorRank2<D, I, L>,
251 tensor_rank_2_b: &TensorRank2<D, K, J>,
252 ) -> Self {
253 Self::dyad_il_jk(tensor_rank_2_a, &(tensor_rank_2_b.transpose()))
254 }
255}
256
257impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> Hessian
258 for TensorRank4<D, I, J, K, L>
259{
260 fn fill_into(self, square_matrix: &mut SquareMatrix) {
261 self.into_iter().enumerate().for_each(|(i, self_i)| {
262 self_i.into_iter().enumerate().for_each(|(j, self_ij)| {
263 self_ij.into_iter().enumerate().for_each(|(k, self_ijk)| {
264 self_ijk
265 .into_iter()
266 .enumerate()
267 .for_each(|(l, self_ijkl)| square_matrix[D * i + j][D * k + l] = self_ijkl)
268 })
269 })
270 })
271 }
272}
273
274impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> Tensor
275 for TensorRank4<D, I, J, K, L>
276{
277 type Item = TensorRank3<D, J, K, L>;
278 fn iter(&self) -> impl Iterator<Item = &Self::Item> {
279 self.0.iter()
280 }
281 fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
282 self.0.iter_mut()
283 }
284}
285
286impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> IntoIterator
287 for TensorRank4<D, I, J, K, L>
288{
289 type Item = TensorRank3<D, J, K, L>;
290 type IntoIter = std::array::IntoIter<Self::Item, D>;
291 fn into_iter(self) -> Self::IntoIter {
292 self.0.into_iter()
293 }
294}
295
296impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> TensorArray
297 for TensorRank4<D, I, J, K, L>
298{
299 type Array = [[[[TensorRank0; D]; D]; D]; D];
300 type Item = TensorRank3<D, J, K, L>;
301 fn as_array(&self) -> Self::Array {
302 let mut array = [[[[0.0; D]; D]; D]; D];
303 array
304 .iter_mut()
305 .zip(self.iter())
306 .for_each(|(entry_rank_3, tensor_rank_3)| *entry_rank_3 = tensor_rank_3.as_array());
307 array
308 }
309 fn identity() -> Self {
310 Self::dyad_ij_kl(&TensorRank2::identity(), &TensorRank2::identity())
311 }
312 fn new(array: Self::Array) -> Self {
313 array.into_iter().map(Self::Item::new).collect()
314 }
315 fn zero() -> Self {
316 Self(from_fn(|_| Self::Item::zero()))
317 }
318}
319
320impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
321 FromIterator<TensorRank3<D, J, K, L>> for TensorRank4<D, I, J, K, L>
322{
323 fn from_iter<Ii: IntoIterator<Item = TensorRank3<D, J, K, L>>>(into_iterator: Ii) -> Self {
324 let mut tensor_rank_4 = Self::zero();
325 tensor_rank_4
326 .iter_mut()
327 .zip(into_iterator)
328 .for_each(|(tensor_rank_4_i, value_i)| *tensor_rank_4_i = value_i);
329 tensor_rank_4
330 }
331}
332
333impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> Index<usize>
334 for TensorRank4<D, I, J, K, L>
335{
336 type Output = TensorRank3<D, J, K, L>;
337 fn index(&self, index: usize) -> &Self::Output {
338 &self.0[index]
339 }
340}
341
342impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> IndexMut<usize>
343 for TensorRank4<D, I, J, K, L>
344{
345 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
346 &mut self.0[index]
347 }
348}
349
350impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> std::iter::Sum
351 for TensorRank4<D, I, J, K, L>
352{
353 fn sum<Ii>(iter: Ii) -> Self
354 where
355 Ii: Iterator<Item = Self>,
356 {
357 let mut output = TensorRank4::zero();
358 iter.for_each(|item| output += item);
359 output
360 }
361}
362
363pub trait ContractAllIndicesWithFirstIndicesOf<TIM, TJN, TKO, TLP> {
364 type Output;
365 fn contract_all_indices_with_first_indices_of(
366 &self,
367 tensor_rank_2_a: TIM,
368 tensor_rank_2_b: TJN,
369 tensor_rank_2_c: TKO,
370 tensor_rank_2_d: TLP,
371 ) -> Self::Output;
372}
373
374impl<
375 const D: usize,
376 const I: usize,
377 const J: usize,
378 const K: usize,
379 const L: usize,
380 const M: usize,
381 const N: usize,
382 const O: usize,
383 const P: usize,
384>
385 ContractAllIndicesWithFirstIndicesOf<
386 &TensorRank2<D, I, M>,
387 &TensorRank2<D, J, N>,
388 &TensorRank2<D, K, O>,
389 &TensorRank2<D, L, P>,
390 > for TensorRank4<D, I, J, K, L>
391{
392 type Output = TensorRank4<D, M, N, O, P>;
393 fn contract_all_indices_with_first_indices_of(
394 &self,
395 tensor_rank_2_a: &TensorRank2<D, I, M>,
396 tensor_rank_2_b: &TensorRank2<D, J, N>,
397 tensor_rank_2_c: &TensorRank2<D, K, O>,
398 tensor_rank_2_d: &TensorRank2<D, L, P>,
399 ) -> Self::Output {
400 let mut output = TensorRank4::zero();
401 self.iter().zip(tensor_rank_2_a.iter()).for_each(|(self_m, tensor_rank_2_a_m)|
402 self_m.iter().zip(tensor_rank_2_b.iter()).for_each(|(self_mn, tensor_rank_2_b_n)|
403 self_mn.iter().zip(tensor_rank_2_c.iter()).for_each(|(self_mno, tensor_rank_2_c_o)|
404 self_mno.iter().zip(tensor_rank_2_d.iter()).for_each(|(self_mnop, tensor_rank_2_d_p)|
405 output.iter_mut().zip(tensor_rank_2_a_m.iter()).for_each(|(output_i, tensor_rank_2_a_mi)|
406 output_i.iter_mut().zip(tensor_rank_2_b_n.iter()).for_each(|(output_ij, tensor_rank_2_b_nj)|
407 output_ij.iter_mut().zip(tensor_rank_2_c_o.iter()).for_each(|(output_ijk, tensor_rank_2_c_ok)|
408 output_ijk.iter_mut().zip(tensor_rank_2_d_p.iter()).for_each(|(output_ijkl, tensor_rank_2_dp)|
409 *output_ijkl += self_mnop*tensor_rank_2_a_mi*tensor_rank_2_b_nj*tensor_rank_2_c_ok*tensor_rank_2_dp
410 )
411 )
412 )
413 )
414 )
415 )
416 )
417 );
418 output
419 }
420}
421
422pub trait ContractFirstThirdFourthIndicesWithFirstIndicesOf<TIM, TKO, TLP> {
423 type Output;
424 fn contract_first_third_fourth_indices_with_first_indices_of(
425 &self,
426 tensor_rank_2_a: TIM,
427 tensor_rank_2_c: TKO,
428 tensor_rank_2_d: TLP,
429 ) -> Self::Output;
430}
431
432impl<
433 const D: usize,
434 const I: usize,
435 const J: usize,
436 const K: usize,
437 const L: usize,
438 const M: usize,
439 const O: usize,
440 const P: usize,
441>
442 ContractFirstThirdFourthIndicesWithFirstIndicesOf<
443 &TensorRank2<D, I, M>,
444 &TensorRank2<D, K, O>,
445 &TensorRank2<D, L, P>,
446 > for TensorRank4<D, I, J, K, L>
447{
448 type Output = TensorRank4<D, M, J, O, P>;
449 fn contract_first_third_fourth_indices_with_first_indices_of(
450 &self,
451 tensor_rank_2_a: &TensorRank2<D, I, M>,
452 tensor_rank_2_b: &TensorRank2<D, K, O>,
453 tensor_rank_2_c: &TensorRank2<D, L, P>,
454 ) -> Self::Output {
455 let mut output = TensorRank4::zero();
456 self.iter().zip(tensor_rank_2_a.iter()).for_each(|(self_q, tensor_rank_2_a_q)|
457 output.iter_mut().zip(tensor_rank_2_a_q.iter()).for_each(|(output_i, tensor_rank_2_a_qi)|
458 output_i.iter_mut().zip(self_q.iter()).for_each(|(output_ij, self_qj)|
459 self_qj.iter().zip(tensor_rank_2_b.iter()).for_each(|(self_qjm, tensor_rank_2_b_m)|
460 self_qjm.iter().zip(tensor_rank_2_c.iter()).for_each(|(self_qjmn, tensor_rank_2_c_n)|
461 output_ij.iter_mut().zip(tensor_rank_2_b_m.iter()).for_each(|(output_ijk, tensor_rank_2_b_mk)|
462 output_ijk.iter_mut().zip(tensor_rank_2_c_n.iter()).for_each(|(output_ijkl, tensor_rank_2_c_nl)|
463 *output_ijkl += self_qjmn*tensor_rank_2_a_qi*tensor_rank_2_b_mk*tensor_rank_2_c_nl
464 )
465 )
466 )
467 )
468 )
469 )
470 );
471 output
472 }
473}
474
475pub trait ContractSecondIndexWithFirstIndexOf<TJN> {
476 type Output;
477 fn contract_second_index_with_first_index_of(&self, tensor_rank_2: TJN) -> Self::Output;
478}
479
480impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize, const N: usize>
481 ContractSecondIndexWithFirstIndexOf<&TensorRank2<D, J, N>> for TensorRank4<D, I, J, K, L>
482{
483 type Output = TensorRank4<D, I, N, K, L>;
484 fn contract_second_index_with_first_index_of(
485 &self,
486 tensor_rank_2: &TensorRank2<D, J, N>,
487 ) -> Self::Output {
488 let mut output = TensorRank4::zero();
489 output
490 .iter_mut()
491 .zip(self.iter())
492 .for_each(|(output_i, self_i)| {
493 self_i
494 .iter()
495 .zip(tensor_rank_2.iter())
496 .for_each(|(self_is, tensor_rank_2_s)| {
497 output_i.iter_mut().zip(tensor_rank_2_s.iter()).for_each(
498 |(output_ij, tensor_rank_2_sj)| {
499 *output_ij += self_is * tensor_rank_2_sj
500 },
501 )
502 })
503 });
504 output
505 }
506}
507
508pub trait ContractSecondFourthIndicesWithFirstIndicesOf<TJ, TL> {
509 type Output;
510 fn contract_second_fourth_indices_with_first_indices_of(
511 &self,
512 object_a: TJ,
513 object_b: TL,
514 ) -> Self::Output;
515}
516
517impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
518 ContractSecondFourthIndicesWithFirstIndicesOf<&TensorRank1<D, J>, &TensorRank1<D, L>>
519 for TensorRank4<D, I, J, K, L>
520{
521 type Output = TensorRank2<D, I, K>;
522 fn contract_second_fourth_indices_with_first_indices_of(
523 &self,
524 tensor_rank_1_a: &TensorRank1<D, J>,
525 tensor_rank_1_b: &TensorRank1<D, L>,
526 ) -> Self::Output {
527 self.iter()
528 .map(|self_i| {
529 self_i
530 .iter()
531 .zip(tensor_rank_1_a.iter())
532 .map(|(self_ij, tensor_rank_1_a_j)| {
533 self_ij
534 .iter()
535 .map(|self_ijk| self_ijk * (tensor_rank_1_b * tensor_rank_1_a_j))
536 .collect()
537 })
538 .sum()
539 })
540 .collect()
541 }
542}
543
544pub trait ContractThirdFourthIndicesWithFirstSecondIndicesOf<TKL> {
545 type Output;
546 fn contract_third_fourth_indices_with_first_second_indices_of(
547 &self,
548 tensor: TKL,
549 ) -> Self::Output;
550}
551
552impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
553 ContractThirdFourthIndicesWithFirstSecondIndicesOf<&TensorRank2<D, K, L>>
554 for TensorRank4<D, I, J, K, L>
555{
556 type Output = TensorRank2<D, I, J>;
557 fn contract_third_fourth_indices_with_first_second_indices_of(
558 &self,
559 tensor_rank_2: &TensorRank2<D, K, L>,
560 ) -> Self::Output {
561 self.iter()
562 .map(|self_i| {
563 self_i
564 .iter()
565 .map(|self_ij| self_ij.full_contraction(tensor_rank_2))
566 .collect()
567 })
568 .collect()
569 }
570}
571
572impl<
573 const D: usize,
574 const I: usize,
575 const J: usize,
576 const K: usize,
577 const L: usize,
578 const M: usize,
579 const N: usize,
580> ContractThirdFourthIndicesWithFirstSecondIndicesOf<&TensorRank4<D, K, L, M, N>>
581 for TensorRank4<D, I, J, K, L>
582{
583 type Output = TensorRank4<D, I, J, M, N>;
584 fn contract_third_fourth_indices_with_first_second_indices_of(
585 &self,
586 tensor: &TensorRank4<D, K, L, M, N>,
587 ) -> Self::Output {
588 self.iter()
589 .map(|self_i| {
590 self_i
591 .iter()
592 .map(|self_ij| {
593 self_ij
594 .iter()
595 .zip(tensor.iter())
596 .map(|(self_ijk, tensor_k)| {
597 self_ijk
598 .iter()
599 .zip(tensor_k.iter())
600 .map(|(self_ijkl, tensor_kl)| tensor_kl * self_ijkl)
601 .sum()
602 })
603 .sum()
604 })
605 .collect()
606 })
607 .collect()
608 }
609}
610
611pub trait ContractFirstSecondIndicesWithSecondIndicesOf<TI, TJ> {
612 type Output;
613 fn contract_first_second_indices_with_second_indices_of(
614 &self,
615 object_a: TI,
616 object_b: TJ,
617 ) -> Self::Output;
618}
619
620impl<
621 const D: usize,
622 const I: usize,
623 const J: usize,
624 const K: usize,
625 const L: usize,
626 const M: usize,
627 const N: usize,
628> ContractFirstSecondIndicesWithSecondIndicesOf<&TensorRank2<D, I, M>, &TensorRank2<D, J, N>>
629 for TensorRank4<D, M, N, K, L>
630{
631 type Output = TensorRank4<D, I, J, K, L>;
632 fn contract_first_second_indices_with_second_indices_of(
633 &self,
634 tensor_rank_2_a: &TensorRank2<D, I, M>,
635 tensor_rank_2_b: &TensorRank2<D, J, N>,
636 ) -> Self::Output {
637 let mut output = TensorRank4::zero();
638 output
639 .iter_mut()
640 .zip(tensor_rank_2_a.iter())
641 .for_each(|(output_i, tensor_rank_2_a_i)| {
642 output_i.iter_mut().zip(tensor_rank_2_b.iter()).for_each(
643 |(output_ij, tensor_rank_2_b_j)| {
644 self.iter().zip(tensor_rank_2_a_i.iter()).for_each(
645 |(self_m, tensor_rank_2_a_im)| {
646 self_m.iter().zip(tensor_rank_2_b_j.iter()).for_each(
647 |(self_mn, tensor_rank_2_b_jn)| {
648 *output_ij +=
649 self_mn * tensor_rank_2_a_im * tensor_rank_2_b_jn
650 },
651 )
652 },
653 )
654 },
655 )
656 });
657 output
658 }
659}
660
661impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
662 Div<TensorRank0> for TensorRank4<D, I, J, K, L>
663{
664 type Output = Self;
665 fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
666 self /= &tensor_rank_0;
667 self
668 }
669}
670
671impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
672 Div<TensorRank0> for &TensorRank4<D, I, J, K, L>
673{
674 type Output = TensorRank4<D, I, J, K, L>;
675 fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
676 self.iter().map(|self_i| self_i / tensor_rank_0).collect()
677 }
678}
679
680impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
681 Div<&TensorRank0> for TensorRank4<D, I, J, K, L>
682{
683 type Output = Self;
684 fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
685 self /= tensor_rank_0;
686 self
687 }
688}
689
690impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
691 DivAssign<TensorRank0> for TensorRank4<D, I, J, K, L>
692{
693 fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
694 self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
695 }
696}
697
698impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
699 DivAssign<&TensorRank0> for TensorRank4<D, I, J, K, L>
700{
701 fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
702 self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
703 }
704}
705
706impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
707 Mul<TensorRank0> for TensorRank4<D, I, J, K, L>
708{
709 type Output = Self;
710 fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
711 self *= &tensor_rank_0;
712 self
713 }
714}
715
716impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
717 Mul<&TensorRank0> for TensorRank4<D, I, J, K, L>
718{
719 type Output = Self;
720 fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
721 self *= tensor_rank_0;
722 self
723 }
724}
725
726impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
727 MulAssign<TensorRank0> for TensorRank4<D, I, J, K, L>
728{
729 fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
730 self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
731 }
732}
733
734impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
735 MulAssign<&TensorRank0> for TensorRank4<D, I, J, K, L>
736{
737 fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
738 self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
739 }
740}
741
742impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize, const M: usize>
743 Mul<TensorRank2<D, L, M>> for TensorRank4<D, I, J, K, L>
744{
745 type Output = TensorRank4<D, I, J, K, M>;
746 fn mul(self, tensor_rank_2: TensorRank2<D, L, M>) -> Self::Output {
747 self.iter()
748 .map(|self_i| {
749 self_i
750 .iter()
751 .map(|self_ij| self_ij * &tensor_rank_2)
752 .collect()
753 })
754 .collect()
755 }
756}
757
758impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize, const M: usize>
759 Mul<&TensorRank2<D, L, M>> for TensorRank4<D, I, J, K, L>
760{
761 type Output = TensorRank4<D, I, J, K, M>;
762 fn mul(self, tensor_rank_2: &TensorRank2<D, L, M>) -> Self::Output {
763 self.iter()
764 .map(|self_i| {
765 self_i
766 .iter()
767 .map(|self_ij| self_ij * tensor_rank_2)
768 .collect()
769 })
770 .collect()
771 }
772}
773
774impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> Add
775 for TensorRank4<D, I, J, K, L>
776{
777 type Output = Self;
778 fn add(mut self, tensor_rank_4: Self) -> Self::Output {
779 self += tensor_rank_4;
780 self
781 }
782}
783
784impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> Add<&Self>
785 for TensorRank4<D, I, J, K, L>
786{
787 type Output = Self;
788 fn add(mut self, tensor_rank_4: &Self) -> Self::Output {
789 self += tensor_rank_4;
790 self
791 }
792}
793
794impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
795 Add<TensorRank4<D, I, J, K, L>> for &TensorRank4<D, I, J, K, L>
796{
797 type Output = TensorRank4<D, I, J, K, L>;
798 fn add(self, mut tensor_rank_4: TensorRank4<D, I, J, K, L>) -> Self::Output {
799 tensor_rank_4 += self;
800 tensor_rank_4
801 }
802}
803
804impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> AddAssign
805 for TensorRank4<D, I, J, K, L>
806{
807 fn add_assign(&mut self, tensor_rank_4: Self) {
808 self.iter_mut()
809 .zip(tensor_rank_4.iter())
810 .for_each(|(self_i, tensor_rank_4_i)| *self_i += tensor_rank_4_i);
811 }
812}
813
814impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
815 AddAssign<&Self> for TensorRank4<D, I, J, K, L>
816{
817 fn add_assign(&mut self, tensor_rank_4: &Self) {
818 self.iter_mut()
819 .zip(tensor_rank_4.iter())
820 .for_each(|(self_i, tensor_rank_4_i)| *self_i += tensor_rank_4_i);
821 }
822}
823
824impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> Sub
825 for TensorRank4<D, I, J, K, L>
826{
827 type Output = Self;
828 fn sub(mut self, tensor_rank_4: Self) -> Self::Output {
829 self -= tensor_rank_4;
830 self
831 }
832}
833
834impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> Sub<&Self>
835 for TensorRank4<D, I, J, K, L>
836{
837 type Output = Self;
838 fn sub(mut self, tensor_rank_4: &Self) -> Self::Output {
839 self -= tensor_rank_4;
840 self
841 }
842}
843
844impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> Sub
845 for &TensorRank4<D, I, J, K, L>
846{
847 type Output = TensorRank4<D, I, J, K, L>;
848 fn sub(self, tensor_rank_4: Self) -> Self::Output {
849 tensor_rank_4
850 .iter()
851 .zip(self.iter())
852 .map(|(tensor_rank_4_i, self_i)| self_i - tensor_rank_4_i)
853 .collect()
854 }
855}
856
857impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize> SubAssign
858 for TensorRank4<D, I, J, K, L>
859{
860 fn sub_assign(&mut self, tensor_rank_4: Self) {
861 self.iter_mut()
862 .zip(tensor_rank_4.iter())
863 .for_each(|(self_i, tensor_rank_4_i)| *self_i -= tensor_rank_4_i);
864 }
865}
866
867impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
868 SubAssign<&Self> for TensorRank4<D, I, J, K, L>
869{
870 fn sub_assign(&mut self, tensor_rank_4: &Self) {
871 self.iter_mut()
872 .zip(tensor_rank_4.iter())
873 .for_each(|(self_i, tensor_rank_4_i)| *self_i -= tensor_rank_4_i);
874 }
875}