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