1#[cfg(test)]
2mod test;
3
4pub mod list;
5pub mod list_2d;
6pub mod vec;
7pub mod vec_2d;
8
9use std::{
10 array::{IntoIter, from_fn},
11 f64::consts::TAU,
12 fmt::{self, Display, Formatter},
13 iter::Sum,
14 mem::transmute,
15 ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
16};
17
18use super::{
19 super::assert_eq_within_tols,
20 Hessian, Jacobian, Rank2, Solution, SquareMatrix, Tensor, TensorArray, TensorError, Vector,
21 rank_0::{TensorRank0, list::TensorRank0List},
22 rank_1::{
23 TensorRank1, list::TensorRank1List, tensor_rank_1, vec::TensorRank1Vec,
24 zero as tensor_rank_1_zero,
25 },
26 rank_4::TensorRank4,
27};
28use crate::ABS_TOL;
29use list_2d::TensorRank2List2D;
30use vec_2d::TensorRank2Vec2D;
31
32#[cfg(test)]
33use super::test::ErrorTensor;
34
35#[repr(transparent)]
39#[derive(Clone, Debug, PartialEq)]
40pub struct TensorRank2<const D: usize, const I: usize, const J: usize>([TensorRank1<D, J>; D]);
41
42impl<const D: usize, const I: usize, const J: usize> Default for TensorRank2<D, I, J> {
43 fn default() -> Self {
44 Self::zero()
45 }
46}
47
48pub const fn tensor_rank_2<const D: usize, const I: usize, const J: usize>(
49 array: [TensorRank1<D, J>; D],
50) -> TensorRank2<D, I, J> {
51 TensorRank2(array)
52}
53
54pub const fn get_levi_civita_parts<const I: usize, const J: usize>() -> [TensorRank2<3, I, J>; 3] {
55 [
56 TensorRank2([
57 tensor_rank_1_zero(),
58 tensor_rank_1([0.0, 0.0, 1.0]),
59 tensor_rank_1([0.0, -1.0, 0.0]),
60 ]),
61 TensorRank2([
62 tensor_rank_1([0.0, 0.0, -1.0]),
63 tensor_rank_1_zero(),
64 tensor_rank_1([1.0, 0.0, 0.0]),
65 ]),
66 TensorRank2([
67 tensor_rank_1([0.0, 1.0, 0.0]),
68 tensor_rank_1([-1.0, 0.0, 0.0]),
69 tensor_rank_1_zero(),
70 ]),
71 ]
72}
73
74pub const fn get_identity_1010_parts_1<const I: usize, const J: usize>() -> [TensorRank2<3, I, J>; 3]
75{
76 [
77 TensorRank2([
78 tensor_rank_1([1.0, 0.0, 0.0]),
79 tensor_rank_1_zero(),
80 tensor_rank_1_zero(),
81 ]),
82 TensorRank2([
83 tensor_rank_1([0.0, 1.0, 0.0]),
84 tensor_rank_1_zero(),
85 tensor_rank_1_zero(),
86 ]),
87 TensorRank2([
88 tensor_rank_1([0.0, 0.0, 1.0]),
89 tensor_rank_1_zero(),
90 tensor_rank_1_zero(),
91 ]),
92 ]
93}
94
95pub const fn get_identity_1010_parts_2<const I: usize, const J: usize>() -> [TensorRank2<3, I, J>; 3]
96{
97 [
98 TensorRank2([
99 tensor_rank_1_zero(),
100 tensor_rank_1([1.0, 0.0, 0.0]),
101 tensor_rank_1_zero(),
102 ]),
103 TensorRank2([
104 tensor_rank_1_zero(),
105 tensor_rank_1([0.0, 1.0, 0.0]),
106 tensor_rank_1_zero(),
107 ]),
108 TensorRank2([
109 tensor_rank_1_zero(),
110 tensor_rank_1([0.0, 0.0, 1.0]),
111 tensor_rank_1_zero(),
112 ]),
113 ]
114}
115
116pub const fn get_identity_1010_parts_3<const I: usize, const J: usize>() -> [TensorRank2<3, I, J>; 3]
117{
118 [
119 TensorRank2([
120 tensor_rank_1_zero(),
121 tensor_rank_1_zero(),
122 tensor_rank_1([1.0, 0.0, 0.0]),
123 ]),
124 TensorRank2([
125 tensor_rank_1_zero(),
126 tensor_rank_1_zero(),
127 tensor_rank_1([0.0, 1.0, 0.0]),
128 ]),
129 TensorRank2([
130 tensor_rank_1_zero(),
131 tensor_rank_1_zero(),
132 tensor_rank_1([0.0, 0.0, 1.0]),
133 ]),
134 ]
135}
136
137pub const IDENTITY: TensorRank2<3, 1, 1> = TensorRank2([
138 tensor_rank_1([1.0, 0.0, 0.0]),
139 tensor_rank_1([0.0, 1.0, 0.0]),
140 tensor_rank_1([0.0, 0.0, 1.0]),
141]);
142
143pub const IDENTITY_00: TensorRank2<3, 0, 0> = TensorRank2([
144 tensor_rank_1([1.0, 0.0, 0.0]),
145 tensor_rank_1([0.0, 1.0, 0.0]),
146 tensor_rank_1([0.0, 0.0, 1.0]),
147]);
148
149pub const IDENTITY_10: TensorRank2<3, 1, 0> = TensorRank2([
150 tensor_rank_1([1.0, 0.0, 0.0]),
151 tensor_rank_1([0.0, 1.0, 0.0]),
152 tensor_rank_1([0.0, 0.0, 1.0]),
153]);
154
155pub const IDENTITY_22: TensorRank2<3, 2, 2> = TensorRank2([
156 tensor_rank_1([1.0, 0.0, 0.0]),
157 tensor_rank_1([0.0, 1.0, 0.0]),
158 tensor_rank_1([0.0, 0.0, 1.0]),
159]);
160
161pub const ZERO: TensorRank2<3, 1, 1> = TensorRank2([
162 tensor_rank_1_zero(),
163 tensor_rank_1_zero(),
164 tensor_rank_1_zero(),
165]);
166
167pub const ZERO_10: TensorRank2<3, 1, 0> = TensorRank2([
168 tensor_rank_1_zero(),
169 tensor_rank_1_zero(),
170 tensor_rank_1_zero(),
171]);
172
173impl<const D: usize, const I: usize, const J: usize> From<(TensorRank1<D, I>, TensorRank1<D, J>)>
174 for TensorRank2<D, I, J>
175{
176 fn from((vector_a, vector_b): (TensorRank1<D, I>, TensorRank1<D, J>)) -> Self {
177 vector_a
178 .into_iter()
179 .map(|vector_a_i| {
180 vector_b
181 .iter()
182 .map(|vector_b_j| vector_a_i * vector_b_j)
183 .collect()
184 })
185 .collect()
186 }
187}
188
189impl<const D: usize, const I: usize, const J: usize> From<(TensorRank1<D, I>, &TensorRank1<D, J>)>
190 for TensorRank2<D, I, J>
191{
192 fn from((vector_a, vector_b): (TensorRank1<D, I>, &TensorRank1<D, J>)) -> Self {
193 vector_a
194 .into_iter()
195 .map(|vector_a_i| {
196 vector_b
197 .iter()
198 .map(|vector_b_j| vector_a_i * vector_b_j)
199 .collect()
200 })
201 .collect()
202 }
203}
204
205impl<const D: usize, const I: usize, const J: usize> From<(&TensorRank1<D, I>, TensorRank1<D, J>)>
206 for TensorRank2<D, I, J>
207{
208 fn from((vector_a, vector_b): (&TensorRank1<D, I>, TensorRank1<D, J>)) -> Self {
209 vector_a
210 .iter()
211 .map(|vector_a_i| {
212 vector_b
213 .iter()
214 .map(|vector_b_j| vector_a_i * vector_b_j)
215 .collect()
216 })
217 .collect()
218 }
219}
220
221impl<const D: usize, const I: usize, const J: usize> From<(&TensorRank1<D, I>, &TensorRank1<D, J>)>
222 for TensorRank2<D, I, J>
223{
224 fn from((vector_a, vector_b): (&TensorRank1<D, I>, &TensorRank1<D, J>)) -> Self {
225 vector_a
226 .iter()
227 .map(|vector_a_i| {
228 vector_b
229 .iter()
230 .map(|vector_b_j| vector_a_i * vector_b_j)
231 .collect()
232 })
233 .collect()
234 }
235}
236
237impl<const D: usize, const I: usize, const J: usize> From<Vec<Vec<TensorRank0>>>
238 for TensorRank2<D, I, J>
239{
240 fn from(vec: Vec<Vec<TensorRank0>>) -> Self {
241 assert_eq!(vec.len(), D);
242 vec.iter().for_each(|entry| assert_eq!(entry.len(), D));
243 vec.into_iter()
244 .map(|entry| entry.into_iter().collect())
245 .collect()
246 }
247}
248
249impl<const D: usize, const I: usize, const J: usize> From<TensorRank2<D, I, J>>
250 for Vec<Vec<TensorRank0>>
251{
252 fn from(tensor: TensorRank2<D, I, J>) -> Self {
253 tensor
254 .iter()
255 .map(|entry| entry.iter().copied().collect())
256 .collect()
257 }
258}
259
260impl<const D: usize, const I: usize, const J: usize> Display for TensorRank2<D, I, J> {
261 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
262 write!(f, "[")?;
263 self.iter()
264 .enumerate()
265 .try_for_each(|(i, row)| write!(f, "{row},\n\x1B[u\x1B[{}B", i + 1))?;
266 write!(f, "\x1B[u\x1B[1A\x1B[{}C]", 16 * D)
267 }
268}
269
270#[cfg(test)]
271impl<const D: usize, const I: usize, const J: usize> ErrorTensor for TensorRank2<D, I, J> {
272 fn error_fd(&self, comparator: &Self, epsilon: TensorRank0) -> Option<(bool, usize)> {
273 let error_count = self
274 .iter()
275 .zip(comparator.iter())
276 .map(|(self_i, comparator_i)| {
277 self_i
278 .iter()
279 .zip(comparator_i.iter())
280 .filter(|&(&self_ij, &comparator_ij)| {
281 (self_ij / comparator_ij - 1.0).abs() >= epsilon
282 && (self_ij.abs() >= epsilon || comparator_ij.abs() >= epsilon)
283 })
284 .count()
285 })
286 .sum();
287 if error_count > 0 {
288 Some((true, error_count))
289 } else {
290 None
291 }
292 }
293}
294
295impl<const D: usize, const I: usize, const J: usize> TensorRank2<D, I, J> {
296 pub const fn as_ptr(&self) -> *const TensorRank1<D, J> {
298 self.0.as_ptr()
299 }
300 pub fn as_tensor_rank_1(&self) -> TensorRank1<9, 88> {
302 assert_eq!(D, 3);
303 let mut tensor_rank_1 = TensorRank1::<9, 88>::zero();
304 self.iter().enumerate().for_each(|(i, self_i)| {
305 self_i
306 .iter()
307 .enumerate()
308 .for_each(|(j, self_ij)| tensor_rank_1[3 * i + j] = *self_ij)
309 });
310 tensor_rank_1
311 }
312 pub fn determinant(&self) -> TensorRank0 {
314 if D == 2 {
315 self[0][0] * self[1][1] - self[0][1] * self[1][0]
316 } else if D == 3 {
317 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
318 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
319 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
320 self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20
321 } else if D == 4 {
322 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
323 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
324 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
325 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
326 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
327 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
328 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
329 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
330 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
331 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
332 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
333 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
334 s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0
335 } else {
336 let (_, u, p) = self.lu_decomposition();
337 let num_swaps = p.iter().enumerate().filter(|(i, p_i)| p_i != &i).count();
338 u.into_iter()
339 .enumerate()
340 .map(|(i, u_i)| u_i[i])
341 .product::<TensorRank0>()
342 * if num_swaps % 2 == 0 { 1.0 } else { -1.0 }
343 }
344 }
345 pub fn inverse(&self) -> TensorRank2<D, J, I> {
347 if D == 2 {
348 let mut adjugate = TensorRank2::<D, J, I>::zero();
349 adjugate[0][0] = self[1][1];
350 adjugate[0][1] = -self[0][1];
351 adjugate[1][0] = -self[1][0];
352 adjugate[1][1] = self[0][0];
353 adjugate / self.determinant()
354 } else if D == 3 {
355 let mut adjugate = TensorRank2::<D, J, I>::zero();
356 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
357 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
358 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
359 adjugate[0][0] = c_00;
360 adjugate[0][1] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
361 adjugate[0][2] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
362 adjugate[1][0] = c_10;
363 adjugate[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
364 adjugate[1][2] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
365 adjugate[2][0] = c_20;
366 adjugate[2][1] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
367 adjugate[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
368 adjugate / (self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20)
369 } else if D == 4 {
370 let mut adjugate = TensorRank2::<D, J, I>::zero();
371 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
372 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
373 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
374 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
375 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
376 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
377 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
378 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
379 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
380 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
381 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
382 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
383 adjugate[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
384 adjugate[0][1] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
385 adjugate[0][2] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
386 adjugate[0][3] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
387 adjugate[1][0] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
388 adjugate[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
389 adjugate[1][2] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
390 adjugate[1][3] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
391 adjugate[2][0] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
392 adjugate[2][1] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
393 adjugate[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
394 adjugate[2][3] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
395 adjugate[3][0] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
396 adjugate[3][1] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
397 adjugate[3][2] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
398 adjugate[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
399 adjugate / (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0)
400 } else {
401 let (l_inverse, u_inverse, p) = self.lu_decomposition_inverse();
402 let mut q = [0; D];
403 p.into_iter().enumerate().for_each(|(i, p_i)| q[p_i] = i);
404 u_inverse
405 .into_iter()
406 .map(|u_inverse_i| {
407 q.iter()
408 .map(|&q_j| {
409 u_inverse_i
410 .iter()
411 .zip(l_inverse.iter())
412 .map(|(u_inverse_ik, l_inverse_k)| u_inverse_ik * l_inverse_k[q_j])
413 .sum()
414 })
415 .collect()
416 })
417 .collect()
418 }
419 }
420 pub fn inverse_and_determinant(&self) -> (TensorRank2<D, J, I>, TensorRank0) {
422 if D == 2 {
423 let mut adjugate = TensorRank2::<D, J, I>::zero();
424 adjugate[0][0] = self[1][1];
425 adjugate[0][1] = -self[0][1];
426 adjugate[1][0] = -self[1][0];
427 adjugate[1][1] = self[0][0];
428 let determinant = self.determinant();
429 (adjugate / determinant, determinant)
430 } else if D == 3 {
431 let mut adjugate = TensorRank2::<D, J, I>::zero();
432 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
433 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
434 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
435 let determinant = self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20;
436 adjugate[0][0] = c_00;
437 adjugate[0][1] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
438 adjugate[0][2] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
439 adjugate[1][0] = c_10;
440 adjugate[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
441 adjugate[1][2] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
442 adjugate[2][0] = c_20;
443 adjugate[2][1] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
444 adjugate[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
445 (adjugate / determinant, determinant)
446 } else if D == 4 {
447 let mut adjugate = TensorRank2::<D, J, I>::zero();
448 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
449 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
450 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
451 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
452 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
453 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
454 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
455 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
456 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
457 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
458 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
459 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
460 let determinant = s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0;
461 adjugate[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
462 adjugate[0][1] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
463 adjugate[0][2] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
464 adjugate[0][3] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
465 adjugate[1][0] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
466 adjugate[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
467 adjugate[1][2] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
468 adjugate[1][3] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
469 adjugate[2][0] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
470 adjugate[2][1] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
471 adjugate[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
472 adjugate[2][3] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
473 adjugate[3][0] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
474 adjugate[3][1] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
475 adjugate[3][2] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
476 adjugate[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
477 (adjugate / determinant, determinant)
478 } else {
479 panic!()
480 }
481 }
482 pub fn inverse_transpose(&self) -> Self {
484 if D == 2 {
485 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
486 adjugate_transpose[0][0] = self[1][1];
487 adjugate_transpose[0][1] = -self[1][0];
488 adjugate_transpose[1][0] = -self[0][1];
489 adjugate_transpose[1][1] = self[0][0];
490 adjugate_transpose / self.determinant()
491 } else if D == 3 {
492 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
493 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
494 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
495 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
496 adjugate_transpose[0][0] = c_00;
497 adjugate_transpose[1][0] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
498 adjugate_transpose[2][0] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
499 adjugate_transpose[0][1] = c_10;
500 adjugate_transpose[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
501 adjugate_transpose[2][1] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
502 adjugate_transpose[0][2] = c_20;
503 adjugate_transpose[1][2] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
504 adjugate_transpose[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
505 adjugate_transpose / (self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20)
506 } else if D == 4 {
507 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
508 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
509 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
510 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
511 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
512 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
513 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
514 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
515 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
516 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
517 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
518 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
519 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
520 adjugate_transpose[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
521 adjugate_transpose[1][0] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
522 adjugate_transpose[2][0] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
523 adjugate_transpose[3][0] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
524 adjugate_transpose[0][1] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
525 adjugate_transpose[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
526 adjugate_transpose[2][1] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
527 adjugate_transpose[3][1] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
528 adjugate_transpose[0][2] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
529 adjugate_transpose[1][2] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
530 adjugate_transpose[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
531 adjugate_transpose[3][2] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
532 adjugate_transpose[0][3] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
533 adjugate_transpose[1][3] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
534 adjugate_transpose[2][3] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
535 adjugate_transpose[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
536 adjugate_transpose / (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0)
537 } else {
538 self.inverse().transpose()
539 }
540 }
541 pub fn inverse_transpose_and_determinant(&self) -> (Self, TensorRank0) {
543 if D == 2 {
544 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
545 adjugate_transpose[0][0] = self[1][1];
546 adjugate_transpose[0][1] = -self[1][0];
547 adjugate_transpose[1][0] = -self[0][1];
548 adjugate_transpose[1][1] = self[0][0];
549 let determinant = self.determinant();
550 (adjugate_transpose / determinant, determinant)
551 } else if D == 3 {
552 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
553 let c_00 = self[1][1] * self[2][2] - self[1][2] * self[2][1];
554 let c_10 = self[1][2] * self[2][0] - self[1][0] * self[2][2];
555 let c_20 = self[1][0] * self[2][1] - self[1][1] * self[2][0];
556 let determinant = self[0][0] * c_00 + self[0][1] * c_10 + self[0][2] * c_20;
557 adjugate_transpose[0][0] = c_00;
558 adjugate_transpose[1][0] = self[0][2] * self[2][1] - self[0][1] * self[2][2];
559 adjugate_transpose[2][0] = self[0][1] * self[1][2] - self[0][2] * self[1][1];
560 adjugate_transpose[0][1] = c_10;
561 adjugate_transpose[1][1] = self[0][0] * self[2][2] - self[0][2] * self[2][0];
562 adjugate_transpose[2][1] = self[0][2] * self[1][0] - self[0][0] * self[1][2];
563 adjugate_transpose[0][2] = c_20;
564 adjugate_transpose[1][2] = self[0][1] * self[2][0] - self[0][0] * self[2][1];
565 adjugate_transpose[2][2] = self[0][0] * self[1][1] - self[0][1] * self[1][0];
566 (adjugate_transpose / determinant, determinant)
567 } else if D == 4 {
568 let mut adjugate_transpose = TensorRank2::<D, I, J>::zero();
569 let s0 = self[0][0] * self[1][1] - self[0][1] * self[1][0];
570 let s1 = self[0][0] * self[1][2] - self[0][2] * self[1][0];
571 let s2 = self[0][0] * self[1][3] - self[0][3] * self[1][0];
572 let s3 = self[0][1] * self[1][2] - self[0][2] * self[1][1];
573 let s4 = self[0][1] * self[1][3] - self[0][3] * self[1][1];
574 let s5 = self[0][2] * self[1][3] - self[0][3] * self[1][2];
575 let c5 = self[2][2] * self[3][3] - self[2][3] * self[3][2];
576 let c4 = self[2][1] * self[3][3] - self[2][3] * self[3][1];
577 let c3 = self[2][1] * self[3][2] - self[2][2] * self[3][1];
578 let c2 = self[2][0] * self[3][3] - self[2][3] * self[3][0];
579 let c1 = self[2][0] * self[3][2] - self[2][2] * self[3][0];
580 let c0 = self[2][0] * self[3][1] - self[2][1] * self[3][0];
581 let determinant = s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0;
582 adjugate_transpose[0][0] = self[1][1] * c5 - self[1][2] * c4 + self[1][3] * c3;
583 adjugate_transpose[1][0] = self[0][2] * c4 - self[0][1] * c5 - self[0][3] * c3;
584 adjugate_transpose[2][0] = self[3][1] * s5 - self[3][2] * s4 + self[3][3] * s3;
585 adjugate_transpose[3][0] = self[2][2] * s4 - self[2][1] * s5 - self[2][3] * s3;
586 adjugate_transpose[0][1] = self[1][2] * c2 - self[1][0] * c5 - self[1][3] * c1;
587 adjugate_transpose[1][1] = self[0][0] * c5 - self[0][2] * c2 + self[0][3] * c1;
588 adjugate_transpose[2][1] = self[3][2] * s2 - self[3][0] * s5 - self[3][3] * s1;
589 adjugate_transpose[3][1] = self[2][0] * s5 - self[2][2] * s2 + self[2][3] * s1;
590 adjugate_transpose[0][2] = self[1][0] * c4 - self[1][1] * c2 + self[1][3] * c0;
591 adjugate_transpose[1][2] = self[0][1] * c2 - self[0][0] * c4 - self[0][3] * c0;
592 adjugate_transpose[2][2] = self[3][0] * s4 - self[3][1] * s2 + self[3][3] * s0;
593 adjugate_transpose[3][2] = self[2][1] * s2 - self[2][0] * s4 - self[2][3] * s0;
594 adjugate_transpose[0][3] = self[1][1] * c1 - self[1][0] * c3 - self[1][2] * c0;
595 adjugate_transpose[1][3] = self[0][0] * c3 - self[0][1] * c1 + self[0][2] * c0;
596 adjugate_transpose[2][3] = self[3][1] * s1 - self[3][0] * s3 - self[3][2] * s0;
597 adjugate_transpose[3][3] = self[2][0] * s3 - self[2][1] * s1 + self[2][2] * s0;
598 (adjugate_transpose / determinant, determinant)
599 } else {
600 panic!()
601 }
602 }
603 pub fn lu_decomposition(&self) -> (TensorRank2<D, I, 88>, TensorRank2<D, 88, J>, Vec<usize>) {
605 let n = D;
606 let mut p: Vec<usize> = (0..n).collect();
607 let mut factor;
608 let mut lu = self.clone();
609 let mut max_row;
610 let mut max_val;
611 let mut pivot;
612 for i in 0..n {
613 max_row = i;
614 max_val = lu[max_row][i].abs();
615 for k in i + 1..n {
616 if lu[k][i].abs() > max_val {
617 max_row = k;
618 max_val = lu[max_row][i].abs();
619 }
620 }
621 if max_row != i {
622 lu.0.swap(i, max_row);
623 p.swap(i, max_row);
624 }
625 pivot = lu[i][i];
626 if pivot.abs() < ABS_TOL {
627 panic!("LU decomposition failed (zero pivot).")
628 }
629 for j in i + 1..n {
630 if lu[j][i] != 0.0 {
631 lu[j][i] /= pivot;
632 factor = lu[j][i];
633 for k in i + 1..n {
634 lu[j][k] -= factor * lu[i][k];
635 }
636 }
637 }
638 }
639 let mut l = TensorRank2::identity();
640 for i in 0..D {
641 for j in 0..i {
642 l[i][j] = lu[i][j]
643 }
644 }
645 let mut u = TensorRank2::zero();
646 for i in 0..D {
647 for j in i..D {
648 u[i][j] = lu[i][j]
649 }
650 }
651 (l, u, p)
652 }
653 pub fn lu_decomposition_inverse(
655 &self,
656 ) -> (TensorRank2<D, I, 88>, TensorRank2<D, 88, J>, Vec<usize>) {
657 let (mut tensor_l, mut tensor_u, p) = self.lu_decomposition();
658 let mut sum;
659 for i in 0..D {
660 tensor_l[i][i] = 1.0 / tensor_l[i][i];
661 for j in 0..i {
662 sum = 0.0;
663 for k in j..i {
664 sum += tensor_l[i][k] * tensor_l[k][j];
665 }
666 tensor_l[i][j] = -sum * tensor_l[i][i];
667 }
668 }
669 for i in 0..D {
670 tensor_u[i][i] = 1.0 / tensor_u[i][i];
671 for j in 0..i {
672 sum = 0.0;
673 for k in j..i {
674 sum += tensor_u[j][k] * tensor_u[k][i];
675 }
676 tensor_u[j][i] = -sum * tensor_u[i][i];
677 }
678 }
679 (tensor_l, tensor_u, p)
680 }
681}
682
683impl<const I: usize> TensorRank2<3, I, I> {
684 pub fn logm(&self) -> Result<Self, TensorError> {
686 if self.is_diagonal() {
687 let mut logm = TensorRank2::zero();
688 logm.iter_mut()
689 .enumerate()
690 .zip(self.iter())
691 .for_each(|((i, logm_i), self_i)| logm_i[i] = self_i[i].ln());
692 Ok(logm)
693 } else {
694 let tensor = self - &TensorRank2::identity();
695 let norm = tensor.norm();
696 if norm < 1e-2 {
697 let num_terms = if norm < 1e-4 {
698 2
699 } else if norm < 1e-3 {
700 3
701 } else {
702 5
703 };
704 let mut logm = tensor.clone();
705 let mut power = tensor.clone();
706 (2..=num_terms).for_each(|k| {
707 power *= &tensor;
708 logm += &power / (if k % 2 == 0 { -1.0 } else { 1.0 } / k as f64);
709 });
710 Ok(logm)
711 } else if self.is_symmetric() {
712 let mut eigenvalues = solve_cubic_symmetric(self.invariants())?;
713 if eigenvalues.iter().any(|eigenvalue| eigenvalue <= &0.0) {
714 panic!("Symmetric matrix has a non-positive eigenvalue")
715 }
716 let eigenvectors = find_orthonormal_eigenvectors(&eigenvalues, self);
717 eigenvalues
718 .iter_mut()
719 .for_each(|eigenvalue| *eigenvalue = eigenvalue.ln());
720 Ok(reconstruct_symmetric(eigenvalues, eigenvectors))
721 } else {
722 panic!("Matrix logarithm only implemented for symmetric cases")
723 }
724 }
725 }
726 pub fn dlogm(&self) -> Result<TensorRank4<3, I, I, I, I>, TensorError> {
728 if self.is_diagonal() {
729 let mut dlogm = TensorRank4::zero();
730 dlogm.iter_mut().enumerate().for_each(|(i, dlogm_i)| {
731 dlogm_i.iter_mut().enumerate().for_each(|(j, dlogm_ij)| {
732 dlogm_ij.iter_mut().enumerate().for_each(|(k, dlogm_ijk)| {
733 dlogm_ijk
734 .iter_mut()
735 .enumerate()
736 .filter(|(l, _)| i == k && &j == l)
737 .for_each(|(_, dlogm_ijkl)| {
738 *dlogm_ijkl = if assert_eq_within_tols(&self[i][i], &self[j][j])
739 .is_ok()
740 {
741 1.0 / self[j][j]
742 } else {
743 (self[i][i].ln() - self[j][j].ln()) / (self[i][i] - self[j][j])
744 }
745 })
746 })
747 })
748 });
749 Ok(dlogm)
750 } else if self.is_symmetric() {
751 let eigenvalues = solve_cubic_symmetric(self.invariants())?;
752 if eigenvalues.iter().any(|eigenvalue| eigenvalue <= &0.0) {
753 panic!("Symmetric matrix has a non-positive eigenvalue")
754 }
755 let divided_difference: Self = eigenvalues
756 .iter()
757 .map(|eigenvalue_i| {
758 eigenvalues
759 .iter()
760 .map(|eigenvalue_j| {
761 if assert_eq_within_tols(eigenvalue_i, eigenvalue_j).is_ok() {
762 1.0 / eigenvalue_j
763 } else {
764 (eigenvalue_i.ln() - eigenvalue_j.ln())
765 / (eigenvalue_i - eigenvalue_j)
766 }
767 })
768 .collect()
769 })
770 .collect();
771 let eigenvectors = find_orthonormal_eigenvectors(&eigenvalues, self).transpose();
772 Ok(eigenvectors.iter().map(|eigenvector_i|
773 eigenvectors.iter().map(|eigenvector_j|
774 eigenvectors.iter().map(|eigenvector_k|
775 eigenvectors.iter().map(|eigenvector_l|
776 eigenvector_i.iter().zip(eigenvector_k.iter().zip(divided_difference.iter())).map(|(eigenvector_ip, (eigenvector_kp, divided_difference_p))|
777 eigenvector_j.iter().zip(eigenvector_l.iter().zip(divided_difference_p.iter())).map(|(eigenvector_jq, (eigenvector_lq, divided_difference_pq))|
778 eigenvector_ip * eigenvector_kp * divided_difference_pq * eigenvector_jq * eigenvector_lq
779 ).sum::<TensorRank0>()
780 ).sum()
781 ).collect()
782 ).collect()
783 ).collect()
784 ).collect())
785 } else {
786 panic!("Matrix logarithm only implemented for symmetric cases")
787 }
788 }
789 pub fn invariants(&self) -> TensorRank0List<3> {
791 let trace = self.trace();
792 TensorRank0List::new([
793 trace,
794 0.5 * (trace.powi(2) - self.squared_trace()),
795 self.determinant(),
796 ])
797 }
798}
799
800fn solve_cubic_symmetric(
801 coefficients: TensorRank0List<3>,
802) -> Result<TensorRank0List<3>, TensorError> {
803 let c2 = coefficients[0];
804 let c1 = coefficients[1];
805 let c0 = coefficients[2];
806 let p = c1 - c2 * c2 / 3.0;
807 let q = -(2.0 * c2.powi(3) - 9.0 * c2 * c1 + 27.0 * c0) / 27.0;
808 if p.abs() < ABS_TOL {
809 let t = (-q).cbrt();
810 let lambda = t + c2 / 3.0;
811 return Ok(TensorRank0List::new([lambda; _]));
812 }
813 let discriminant = -4.0 * p * p * p - 27.0 * q * q;
814 if discriminant >= ABS_TOL {
815 let sqrt_term = (-p / 3.0).sqrt();
816 let cos_arg = 3.0 * q / (2.0 * p * (-p / 3.0).sqrt());
817 let cos_arg = cos_arg.clamp(-1.0, 1.0);
818 let theta = cos_arg.acos();
819 let mut lambdas = [
820 2.0 * sqrt_term * (theta / 3.0).cos() + c2 / 3.0,
821 2.0 * sqrt_term * ((theta + TAU) / 3.0).cos() + c2 / 3.0,
822 2.0 * sqrt_term * ((theta + 2.0 * TAU) / 3.0).cos() + c2 / 3.0,
823 ];
824 lambdas.sort_by(|a, b| b.partial_cmp(a).unwrap());
825 Ok(TensorRank0List::new(lambdas))
826 } else {
827 Err(TensorError::SymmetricMatrixComplexEigenvalues)
828 }
829}
830
831fn find_orthonormal_eigenvectors<const I: usize>(
832 eigenvalues: &TensorRank0List<3>,
833 tensor: &TensorRank2<3, I, I>,
834) -> TensorRank2<3, I, I> {
835 let mut eigenvectors = eigenvalues
836 .iter()
837 .map(|&eigenvalue| eigenvector_symmetric(eigenvalue, tensor))
838 .collect::<TensorRank2<3, I, I>>();
839 eigenvectors[0].normalize();
840 let proj1 = &eigenvectors[1] * &eigenvectors[0];
841 for i in 0..3 {
842 eigenvectors[1][i] -= proj1 * eigenvectors[0][i];
843 }
844 eigenvectors[1].normalize();
845 eigenvectors[2] = eigenvectors[0].cross(&eigenvectors[1]);
846 eigenvectors
847}
848
849fn eigenvector_symmetric<const I: usize>(
850 eigenvalue: TensorRank0,
851 tensor: &TensorRank2<3, I, I>,
852) -> TensorRank1<3, I> {
853 let m = tensor - TensorRank2::identity() * eigenvalue;
854 let mut pivot_row = 0;
855 m.iter().enumerate().for_each(|(i, m_i)| {
856 if m_i[i].abs() < m[pivot_row][pivot_row].abs() {
857 pivot_row = i;
858 }
859 });
860 if pivot_row == 0 {
861 m[1].cross(&m[2])
862 } else if pivot_row == 1 {
863 m[0].cross(&m[2])
864 } else {
865 m[0].cross(&m[1])
866 }
867 .normalized()
868}
869
870fn reconstruct_symmetric<const I: usize>(
871 eigenvalues: TensorRank0List<3>,
872 eigenvectors: TensorRank2<3, I, I>,
873) -> TensorRank2<3, I, I> {
874 let mut tensor = TensorRank2::zero();
875 eigenvalues
876 .iter()
877 .zip(eigenvectors.iter())
878 .for_each(|(eigenvalue, eigenvector)| {
879 tensor
880 .iter_mut()
881 .zip(eigenvector.iter())
882 .for_each(|(tensor_i, eigenvector_i)| {
883 tensor_i.iter_mut().zip(eigenvector.iter()).for_each(
884 |(tensor_ij, eigenvector_j)| {
885 *tensor_ij += eigenvalue * eigenvector_i * eigenvector_j
886 },
887 )
888 })
889 });
890 tensor
891}
892
893impl<const D: usize, const I: usize, const J: usize> Hessian for TensorRank2<D, I, J> {
894 fn fill_into(self, square_matrix: &mut SquareMatrix) {
895 self.into_iter().enumerate().for_each(|(i, self_i)| {
896 self_i
897 .into_iter()
898 .enumerate()
899 .for_each(|(j, self_ij)| square_matrix[i][j] = self_ij)
900 })
901 }
902}
903
904impl<const D: usize, const I: usize, const J: usize> Rank2 for TensorRank2<D, I, J> {
905 type Transpose = TensorRank2<D, J, I>;
906 fn deviatoric(&self) -> Self {
907 Self::identity() * (self.trace() / -(D as TensorRank0)) + self
908 }
909 fn deviatoric_and_trace(&self) -> (Self, TensorRank0) {
910 let trace = self.trace();
911 (
912 Self::identity() * (trace / -(D as TensorRank0)) + self,
913 trace,
914 )
915 }
916 fn is_diagonal(&self) -> bool {
917 self.iter()
918 .enumerate()
919 .map(|(i, self_i)| {
920 self_i
921 .iter()
922 .enumerate()
923 .map(|(j, self_ij)| (self_ij.abs() < ABS_TOL) as u8 * (i != j) as u8)
924 .sum::<u8>()
925 })
926 .sum::<u8>()
927 == (D.pow(2) - D) as u8
928 }
929 fn is_identity(&self) -> bool {
930 self.iter().enumerate().all(|(i, self_i)| {
931 self_i
932 .iter()
933 .enumerate()
934 .all(|(j, self_ij)| self_ij == &((i == j) as u8 as TensorRank0))
935 })
936 }
937 fn is_symmetric(&self) -> bool {
938 self.iter().enumerate().all(|(i, self_i)| {
939 self_i
940 .iter()
941 .zip(self.iter())
942 .all(|(self_ij, self_j)| self_ij == &self_j[i])
943 })
944 }
945 fn squared_trace(&self) -> TensorRank0 {
946 self.iter()
947 .enumerate()
948 .map(|(i, self_i)| {
949 self_i
950 .iter()
951 .zip(self.iter())
952 .map(|(self_ij, self_j)| self_ij * self_j[i])
953 .sum::<TensorRank0>()
954 })
955 .sum()
956 }
957 fn trace(&self) -> TensorRank0 {
958 self.iter().enumerate().map(|(i, self_i)| self_i[i]).sum()
959 }
960 fn transpose(&self) -> Self::Transpose {
961 (0..D)
962 .map(|i| (0..D).map(|j| self[j][i]).collect())
963 .collect()
965 }
966}
967
968impl<const D: usize, const I: usize, const J: usize> Tensor for TensorRank2<D, I, J> {
969 type Item = TensorRank1<D, J>;
970 fn iter(&self) -> impl Iterator<Item = &Self::Item> {
971 self.0.iter()
972 }
973 fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
974 self.0.iter_mut()
975 }
976 fn len(&self) -> usize {
977 D
978 }
979 fn size(&self) -> usize {
980 D * D
981 }
982}
983
984impl<const D: usize, const I: usize, const J: usize> IntoIterator for TensorRank2<D, I, J> {
985 type Item = TensorRank1<D, J>;
986 type IntoIter = IntoIter<Self::Item, D>;
987 fn into_iter(self) -> Self::IntoIter {
988 self.0.into_iter()
989 }
990}
991
992impl<const D: usize, const I: usize, const J: usize> TensorArray for TensorRank2<D, I, J> {
993 type Array = [[TensorRank0; D]; D];
994 type Item = TensorRank1<D, J>;
995 fn as_array(&self) -> Self::Array {
996 let mut array = [[0.0; D]; D];
997 array
998 .iter_mut()
999 .zip(self.iter())
1000 .for_each(|(entry, tensor_rank_1)| *entry = tensor_rank_1.as_array());
1001 array
1002 }
1003 fn identity() -> Self {
1004 (0..D)
1005 .map(|i| (0..D).map(|j| ((i == j) as u8) as TensorRank0).collect())
1006 .collect()
1007 }
1008 fn new(array: Self::Array) -> Self {
1009 array.into_iter().map(Self::Item::new).collect()
1010 }
1011 fn zero() -> Self {
1012 Self(from_fn(|_| Self::Item::zero()))
1013 }
1014}
1015
1016impl<const D: usize, const I: usize, const J: usize> Solution for TensorRank2<D, I, J> {
1017 fn decrement_from(&mut self, other: &Vector) {
1018 self.iter_mut()
1019 .flat_map(|x| x.iter_mut())
1020 .zip(other.iter())
1021 .for_each(|(self_i, vector_i)| *self_i -= vector_i)
1022 }
1023 fn decrement_from_chained(&mut self, other: &mut Vector, vector: Vector) {
1024 self.iter_mut()
1025 .flat_map(|x| x.iter_mut())
1026 .chain(other.iter_mut())
1027 .zip(vector)
1028 .for_each(|(entry_i, vector_i)| *entry_i -= vector_i)
1029 }
1030}
1031
1032impl<const D: usize, const I: usize, const J: usize> Jacobian for TensorRank2<D, I, J> {
1033 fn fill_into(self, vector: &mut Vector) {
1034 self.into_iter()
1035 .flatten()
1036 .zip(vector.iter_mut())
1037 .for_each(|(self_i, vector_i)| *vector_i = self_i)
1038 }
1039 fn fill_into_chained(self, other: Vector, vector: &mut Vector) {
1040 self.into_iter()
1041 .flatten()
1042 .chain(other)
1043 .zip(vector.iter_mut())
1044 .for_each(|(self_i, vector_i)| *vector_i = self_i)
1045 }
1046}
1047
1048impl<const D: usize, const I: usize, const J: usize> Sub<Vector> for TensorRank2<D, I, J> {
1049 type Output = Self;
1050 fn sub(mut self, vector: Vector) -> Self::Output {
1051 self.iter_mut().enumerate().for_each(|(i, self_i)| {
1052 self_i
1053 .iter_mut()
1054 .enumerate()
1055 .for_each(|(j, self_ij)| *self_ij -= vector[D * i + j])
1056 });
1057 self
1058 }
1059}
1060
1061impl<const D: usize, const I: usize, const J: usize> Sub<&Vector> for TensorRank2<D, I, J> {
1062 type Output = Self;
1063 fn sub(mut self, vector: &Vector) -> Self::Output {
1064 self.iter_mut().enumerate().for_each(|(i, self_i)| {
1065 self_i
1066 .iter_mut()
1067 .enumerate()
1068 .for_each(|(j, self_ij)| *self_ij -= vector[D * i + j])
1069 });
1070 self
1071 }
1072}
1073
1074impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
1075 From<TensorRank4<D, I, J, K, L>> for TensorRank2<9, 88, 99>
1076{
1077 fn from(tensor_rank_4: TensorRank4<D, I, J, K, L>) -> Self {
1078 assert_eq!(D, 3);
1079 tensor_rank_4
1080 .into_iter()
1081 .flatten()
1082 .map(|entry_ij| entry_ij.into_iter().flatten().collect())
1083 .collect()
1084 }
1085}
1086
1087impl<const D: usize, const I: usize, const J: usize, const K: usize, const L: usize>
1088 From<&TensorRank4<D, I, J, K, L>> for TensorRank2<9, 88, 99>
1089{
1090 fn from(tensor_rank_4: &TensorRank4<D, I, J, K, L>) -> Self {
1091 assert_eq!(D, 3);
1092 tensor_rank_4
1093 .clone()
1094 .into_iter()
1095 .flatten()
1096 .map(|entry_ij| entry_ij.into_iter().flatten().collect())
1097 .collect()
1098 }
1099}
1100
1101impl From<TensorRank2<3, 0, 0>> for TensorRank2<3, 2, 2> {
1102 fn from(tensor_rank_2: TensorRank2<3, 0, 0>) -> Self {
1103 unsafe { transmute::<TensorRank2<3, 0, 0>, TensorRank2<3, 2, 2>>(tensor_rank_2) }
1104 }
1105}
1106
1107impl<const I: usize> From<TensorRank2<3, I, 0>> for TensorRank2<3, I, 2> {
1108 fn from(tensor_rank_2: TensorRank2<3, I, 0>) -> Self {
1109 unsafe { transmute::<TensorRank2<3, I, 0>, TensorRank2<3, I, 2>>(tensor_rank_2) }
1110 }
1111}
1112
1113impl<const I: usize> From<TensorRank2<3, I, 1>> for TensorRank2<3, I, 0> {
1114 fn from(tensor_rank_2: TensorRank2<3, I, 1>) -> Self {
1115 unsafe { transmute::<TensorRank2<3, I, 1>, TensorRank2<3, I, 0>>(tensor_rank_2) }
1116 }
1117}
1118
1119impl<const I: usize> From<TensorRank2<3, I, 2>> for TensorRank2<3, I, 0> {
1120 fn from(tensor_rank_2: TensorRank2<3, I, 2>) -> Self {
1121 unsafe { transmute::<TensorRank2<3, I, 2>, TensorRank2<3, I, 0>>(tensor_rank_2) }
1122 }
1123}
1124
1125impl<const J: usize> From<TensorRank2<3, 0, J>> for TensorRank2<3, 1, J> {
1126 fn from(tensor_rank_2: TensorRank2<3, 0, J>) -> Self {
1127 unsafe { transmute::<TensorRank2<3, 0, J>, TensorRank2<3, 1, J>>(tensor_rank_2) }
1128 }
1129}
1130
1131impl<const J: usize> From<TensorRank2<3, 1, J>> for TensorRank2<3, 0, J> {
1132 fn from(tensor_rank_2: TensorRank2<3, 1, J>) -> Self {
1133 unsafe { transmute::<TensorRank2<3, 1, J>, TensorRank2<3, 0, J>>(tensor_rank_2) }
1134 }
1135}
1136
1137impl<const J: usize> From<TensorRank2<3, 1, J>> for TensorRank2<3, 2, J> {
1138 fn from(tensor_rank_2: TensorRank2<3, 1, J>) -> Self {
1139 unsafe { transmute::<TensorRank2<3, 1, J>, TensorRank2<3, 2, J>>(tensor_rank_2) }
1140 }
1141}
1142
1143impl<const J: usize> From<TensorRank2<3, 2, J>> for TensorRank2<3, 1, J> {
1144 fn from(tensor_rank_2: TensorRank2<3, 2, J>) -> Self {
1145 unsafe { transmute::<TensorRank2<3, 2, J>, TensorRank2<3, 1, J>>(tensor_rank_2) }
1146 }
1147}
1148
1149impl<const J: usize> From<&TensorRank2<3, 2, J>> for &TensorRank2<3, 1, J> {
1150 fn from(tensor_rank_2: &TensorRank2<3, 2, J>) -> Self {
1151 unsafe { transmute::<&TensorRank2<3, 2, J>, &TensorRank2<3, 1, J>>(tensor_rank_2) }
1152 }
1153}
1154
1155impl From<TensorRank2<3, 0, 0>> for TensorRank2<3, 1, 1> {
1156 fn from(tensor_rank_2: TensorRank2<3, 0, 0>) -> Self {
1157 unsafe { transmute::<TensorRank2<3, 0, 0>, TensorRank2<3, 1, 1>>(tensor_rank_2) }
1158 }
1159}
1160
1161impl<const D: usize, const I: usize, const J: usize> From<Vector> for TensorRank2<D, I, J> {
1162 fn from(_vector: Vector) -> Self {
1163 unimplemented!()
1164 }
1165}
1166
1167impl<const D: usize, const I: usize, const J: usize> FromIterator<TensorRank1<D, J>>
1168 for TensorRank2<D, I, J>
1169{
1170 fn from_iter<Ii: IntoIterator<Item = TensorRank1<D, J>>>(into_iterator: Ii) -> Self {
1171 let mut tensor_rank_2 = Self::zero();
1172 tensor_rank_2
1173 .iter_mut()
1174 .zip(into_iterator)
1175 .for_each(|(tensor_rank_2_i, value_i)| *tensor_rank_2_i = value_i);
1176 tensor_rank_2
1177 }
1178}
1179
1180impl<const D: usize, const I: usize, const J: usize> Index<usize> for TensorRank2<D, I, J> {
1181 type Output = TensorRank1<D, J>;
1182 fn index(&self, index: usize) -> &Self::Output {
1183 &self.0[index]
1184 }
1185}
1186
1187impl<const D: usize, const I: usize, const J: usize> IndexMut<usize> for TensorRank2<D, I, J> {
1188 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1189 &mut self.0[index]
1190 }
1191}
1192
1193impl<const D: usize, const I: usize, const J: usize> Sum for TensorRank2<D, I, J> {
1194 fn sum<Ii>(iter: Ii) -> Self
1195 where
1196 Ii: Iterator<Item = Self>,
1197 {
1198 iter.reduce(|mut acc, item| {
1199 acc += item;
1200 acc
1201 })
1202 .unwrap_or_else(Self::default)
1203 }
1204}
1205
1206impl<const D: usize, const I: usize, const J: usize> Div<TensorRank0> for TensorRank2<D, I, J> {
1207 type Output = Self;
1208 fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
1209 self /= &tensor_rank_0;
1210 self
1211 }
1212}
1213
1214impl<const D: usize, const I: usize, const J: usize> Div<TensorRank0> for &TensorRank2<D, I, J> {
1215 type Output = TensorRank2<D, I, J>;
1216 fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
1217 self.iter().map(|self_i| self_i / tensor_rank_0).collect()
1218 }
1219}
1220
1221impl<const D: usize, const I: usize, const J: usize> Div<&TensorRank0> for TensorRank2<D, I, J> {
1222 type Output = Self;
1223 fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
1224 self /= tensor_rank_0;
1225 self
1226 }
1227}
1228
1229impl<const D: usize, const I: usize, const J: usize> Div<&TensorRank0> for &TensorRank2<D, I, J> {
1230 type Output = TensorRank2<D, I, J>;
1231 fn div(self, tensor_rank_0: &TensorRank0) -> Self::Output {
1232 self.iter().map(|self_i| self_i / tensor_rank_0).collect()
1233 }
1234}
1235
1236impl<const D: usize, const I: usize, const J: usize> DivAssign<TensorRank0>
1237 for TensorRank2<D, I, J>
1238{
1239 fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
1240 self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
1241 }
1242}
1243
1244impl<const D: usize, const I: usize, const J: usize> DivAssign<&TensorRank0>
1245 for TensorRank2<D, I, J>
1246{
1247 fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
1248 self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
1249 }
1250}
1251
1252impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank0> for TensorRank2<D, I, J> {
1253 type Output = Self;
1254 fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
1255 self *= &tensor_rank_0;
1256 self
1257 }
1258}
1259
1260impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank0> for &TensorRank2<D, I, J> {
1261 type Output = TensorRank2<D, I, J>;
1262 fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
1263 self.iter().map(|self_i| self_i * tensor_rank_0).collect()
1264 }
1265}
1266
1267impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank0> for TensorRank2<D, I, J> {
1268 type Output = Self;
1269 fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
1270 self *= tensor_rank_0;
1271 self
1272 }
1273}
1274
1275impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank0> for &TensorRank2<D, I, J> {
1276 type Output = TensorRank2<D, I, J>;
1277 fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
1278 self.iter().map(|self_i| self_i * tensor_rank_0).collect()
1279 }
1280}
1281
1282impl<const D: usize, const I: usize, const J: usize> MulAssign<TensorRank0>
1283 for TensorRank2<D, I, J>
1284{
1285 fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
1286 self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
1287 }
1288}
1289
1290impl<const D: usize, const I: usize, const J: usize> MulAssign<&TensorRank0>
1291 for TensorRank2<D, I, J>
1292{
1293 fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
1294 self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
1295 }
1296}
1297
1298impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank1<D, J>>
1299 for TensorRank2<D, I, J>
1300{
1301 type Output = TensorRank1<D, I>;
1302 fn mul(self, tensor_rank_1: TensorRank1<D, J>) -> Self::Output {
1303 self.into_iter()
1304 .map(|self_i| self_i * &tensor_rank_1)
1305 .collect()
1306 }
1307}
1308
1309impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank1<D, J>>
1310 for TensorRank2<D, I, J>
1311{
1312 type Output = TensorRank1<D, I>;
1313 fn mul(self, tensor_rank_1: &TensorRank1<D, J>) -> Self::Output {
1314 self.into_iter()
1315 .map(|self_i| self_i * tensor_rank_1)
1316 .collect()
1317 }
1318}
1319
1320impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank1<D, J>>
1321 for &TensorRank2<D, I, J>
1322{
1323 type Output = TensorRank1<D, I>;
1324 fn mul(self, tensor_rank_1: TensorRank1<D, J>) -> Self::Output {
1325 self.iter().map(|self_i| self_i * &tensor_rank_1).collect()
1326 }
1327}
1328
1329impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank1<D, J>>
1330 for &TensorRank2<D, I, J>
1331{
1332 type Output = TensorRank1<D, I>;
1333 fn mul(self, tensor_rank_1: &TensorRank1<D, J>) -> Self::Output {
1334 self.iter().map(|self_i| self_i * tensor_rank_1).collect()
1335 }
1336}
1337
1338impl<const D: usize, const I: usize, const J: usize> Add for TensorRank2<D, I, J> {
1339 type Output = Self;
1340 fn add(mut self, tensor_rank_2: Self) -> Self::Output {
1341 self += tensor_rank_2;
1342 self
1343 }
1344}
1345
1346impl<const D: usize, const I: usize, const J: usize> Add<&Self> for TensorRank2<D, I, J> {
1347 type Output = Self;
1348 fn add(mut self, tensor_rank_2: &Self) -> Self::Output {
1349 self += tensor_rank_2;
1350 self
1351 }
1352}
1353
1354impl<const D: usize, const I: usize, const J: usize> Add<TensorRank2<D, I, J>>
1355 for &TensorRank2<D, I, J>
1356{
1357 type Output = TensorRank2<D, I, J>;
1358 fn add(self, mut tensor_rank_2: TensorRank2<D, I, J>) -> Self::Output {
1359 tensor_rank_2 += self;
1360 tensor_rank_2
1361 }
1362}
1363
1364impl<const D: usize, const I: usize, const J: usize> AddAssign for TensorRank2<D, I, J> {
1365 fn add_assign(&mut self, tensor_rank_2: Self) {
1366 self.iter_mut()
1367 .zip(tensor_rank_2)
1368 .for_each(|(self_i, tensor_rank_2_i)| *self_i += tensor_rank_2_i);
1369 }
1370}
1371
1372impl<const D: usize, const I: usize, const J: usize> AddAssign<&Self> for TensorRank2<D, I, J> {
1373 fn add_assign(&mut self, tensor_rank_2: &Self) {
1374 self.iter_mut()
1375 .zip(tensor_rank_2.iter())
1376 .for_each(|(self_i, tensor_rank_2_i)| *self_i += tensor_rank_2_i);
1377 }
1378}
1379
1380impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank2<D, J, K>>
1381 for TensorRank2<D, I, J>
1382{
1383 type Output = TensorRank2<D, I, K>;
1384 fn mul(self, tensor_rank_2: TensorRank2<D, J, K>) -> Self::Output {
1385 self.into_iter()
1386 .map(|self_i| {
1387 self_i
1388 .into_iter()
1389 .zip(tensor_rank_2.iter())
1390 .map(|(self_ij, tensor_rank_2_j)| tensor_rank_2_j * self_ij)
1391 .sum()
1392 })
1393 .collect()
1394 }
1395}
1396
1397impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<&TensorRank2<D, J, K>>
1398 for TensorRank2<D, I, J>
1399{
1400 type Output = TensorRank2<D, I, K>;
1401 fn mul(self, tensor_rank_2: &TensorRank2<D, J, K>) -> Self::Output {
1402 self.into_iter()
1403 .map(|self_i| {
1404 self_i
1405 .into_iter()
1406 .zip(tensor_rank_2.iter())
1407 .map(|(self_ij, tensor_rank_2_j)| tensor_rank_2_j * self_ij)
1408 .sum()
1409 })
1410 .collect()
1411 }
1412}
1413
1414impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank2<D, J, K>>
1415 for &TensorRank2<D, I, J>
1416{
1417 type Output = TensorRank2<D, I, K>;
1418 fn mul(self, tensor_rank_2: TensorRank2<D, J, K>) -> Self::Output {
1419 self.iter()
1420 .map(|self_i| {
1421 self_i
1422 .iter()
1423 .zip(tensor_rank_2.iter())
1424 .map(|(self_ij, tensor_rank_2_j)| tensor_rank_2_j * self_ij)
1425 .sum()
1426 })
1427 .collect()
1428 }
1429}
1430
1431impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<&TensorRank2<D, J, K>>
1432 for &TensorRank2<D, I, J>
1433{
1434 type Output = TensorRank2<D, I, K>;
1435 fn mul(self, tensor_rank_2: &TensorRank2<D, J, K>) -> Self::Output {
1436 self.iter()
1437 .map(|self_i| {
1438 self_i
1439 .iter()
1440 .zip(tensor_rank_2.iter())
1441 .map(|(self_ij, tensor_rank_2_j)| tensor_rank_2_j * self_ij)
1442 .sum()
1443 })
1444 .collect()
1445 }
1446}
1447
1448impl<const D: usize, const I: usize, const J: usize> MulAssign<TensorRank2<D, J, J>>
1449 for TensorRank2<D, I, J>
1450{
1451 fn mul_assign(&mut self, tensor_rank_2: TensorRank2<D, J, J>) {
1452 *self = &*self * tensor_rank_2
1453 }
1454}
1455
1456impl<const D: usize, const I: usize, const J: usize> MulAssign<&TensorRank2<D, J, J>>
1457 for TensorRank2<D, I, J>
1458{
1459 fn mul_assign(&mut self, tensor_rank_2: &TensorRank2<D, J, J>) {
1460 *self = &*self * tensor_rank_2
1461 }
1462}
1463
1464impl<const D: usize, const I: usize, const J: usize> Sub for TensorRank2<D, I, J> {
1465 type Output = Self;
1466 fn sub(mut self, tensor_rank_2: Self) -> Self::Output {
1467 self -= tensor_rank_2;
1468 self
1469 }
1470}
1471
1472impl<const D: usize, const I: usize, const J: usize> Sub<&Self> for TensorRank2<D, I, J> {
1473 type Output = Self;
1474 fn sub(mut self, tensor_rank_2: &Self) -> Self::Output {
1475 self -= tensor_rank_2;
1476 self
1477 }
1478}
1479
1480impl<const D: usize, const I: usize, const J: usize> Sub<TensorRank2<D, I, J>>
1481 for &TensorRank2<D, I, J>
1482{
1483 type Output = TensorRank2<D, I, J>;
1484 fn sub(self, tensor_rank_2: TensorRank2<D, I, J>) -> Self::Output {
1485 let mut output = self.clone();
1486 output -= tensor_rank_2;
1487 output
1488 }
1489}
1490
1491impl<const D: usize, const I: usize, const J: usize> Sub for &TensorRank2<D, I, J> {
1492 type Output = TensorRank2<D, I, J>;
1493 fn sub(self, tensor_rank_2: Self) -> Self::Output {
1494 let mut output = self.clone();
1495 output -= tensor_rank_2;
1496 output
1497 }
1498}
1499
1500impl<const D: usize, const I: usize, const J: usize> SubAssign for TensorRank2<D, I, J> {
1501 fn sub_assign(&mut self, tensor_rank_2: Self) {
1502 self.iter_mut()
1503 .zip(tensor_rank_2)
1504 .for_each(|(self_i, tensor_rank_2_i)| *self_i -= tensor_rank_2_i);
1505 }
1506}
1507
1508impl<const D: usize, const I: usize, const J: usize> SubAssign<&Self> for TensorRank2<D, I, J> {
1509 fn sub_assign(&mut self, tensor_rank_2: &Self) {
1510 self.iter_mut()
1511 .zip(tensor_rank_2.iter())
1512 .for_each(|(self_i, tensor_rank_2_i)| *self_i -= tensor_rank_2_i);
1513 }
1514}
1515
1516impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<TensorRank1List<D, J, W>>
1517 for TensorRank2<D, I, J>
1518{
1519 type Output = TensorRank1List<D, I, W>;
1520 fn mul(self, tensor_rank_1_list: TensorRank1List<D, J, W>) -> Self::Output {
1521 tensor_rank_1_list
1522 .into_iter()
1523 .map(|tensor_rank_1| &self * tensor_rank_1)
1524 .collect()
1525 }
1526}
1527
1528impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<&TensorRank1List<D, J, W>>
1529 for TensorRank2<D, I, J>
1530{
1531 type Output = TensorRank1List<D, I, W>;
1532 fn mul(self, tensor_rank_1_list: &TensorRank1List<D, J, W>) -> Self::Output {
1533 tensor_rank_1_list
1534 .iter()
1535 .map(|tensor_rank_1| &self * tensor_rank_1)
1536 .collect()
1537 }
1538}
1539
1540impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<TensorRank1List<D, J, W>>
1541 for &TensorRank2<D, I, J>
1542{
1543 type Output = TensorRank1List<D, I, W>;
1544 fn mul(self, tensor_rank_1_list: TensorRank1List<D, J, W>) -> Self::Output {
1545 tensor_rank_1_list
1546 .into_iter()
1547 .map(|tensor_rank_1| self * tensor_rank_1)
1548 .collect()
1549 }
1550}
1551
1552impl<const D: usize, const I: usize, const J: usize, const W: usize> Mul<&TensorRank1List<D, J, W>>
1553 for &TensorRank2<D, I, J>
1554{
1555 type Output = TensorRank1List<D, I, W>;
1556 fn mul(self, tensor_rank_1_list: &TensorRank1List<D, J, W>) -> Self::Output {
1557 tensor_rank_1_list
1558 .iter()
1559 .map(|tensor_rank_1| self * tensor_rank_1)
1560 .collect()
1561 }
1562}
1563
1564impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank1Vec<D, J>>
1565 for TensorRank2<D, I, J>
1566{
1567 type Output = TensorRank1Vec<D, I>;
1568 fn mul(self, tensor_rank_1_vec: TensorRank1Vec<D, J>) -> Self::Output {
1569 tensor_rank_1_vec
1570 .into_iter()
1571 .map(|tensor_rank_1| &self * tensor_rank_1)
1572 .collect()
1573 }
1574}
1575
1576impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank1Vec<D, J>>
1577 for TensorRank2<D, I, J>
1578{
1579 type Output = TensorRank1Vec<D, I>;
1580 fn mul(self, tensor_rank_1_vec: &TensorRank1Vec<D, J>) -> Self::Output {
1581 tensor_rank_1_vec
1582 .iter()
1583 .map(|tensor_rank_1| &self * tensor_rank_1)
1584 .collect()
1585 }
1586}
1587
1588impl<const D: usize, const I: usize, const J: usize> Mul<TensorRank1Vec<D, J>>
1589 for &TensorRank2<D, I, J>
1590{
1591 type Output = TensorRank1Vec<D, I>;
1592 fn mul(self, tensor_rank_1_vec: TensorRank1Vec<D, J>) -> Self::Output {
1593 tensor_rank_1_vec
1594 .into_iter()
1595 .map(|tensor_rank_1| self * tensor_rank_1)
1596 .collect()
1597 }
1598}
1599
1600impl<const D: usize, const I: usize, const J: usize> Mul<&TensorRank1Vec<D, J>>
1601 for &TensorRank2<D, I, J>
1602{
1603 type Output = TensorRank1Vec<D, I>;
1604 fn mul(self, tensor_rank_1_vec: &TensorRank1Vec<D, J>) -> Self::Output {
1605 tensor_rank_1_vec
1606 .iter()
1607 .map(|tensor_rank_1| self * tensor_rank_1)
1608 .collect()
1609 }
1610}
1611
1612impl<const D: usize, const I: usize, const J: usize, const K: usize, const W: usize, const X: usize>
1613 Mul<TensorRank2List2D<D, J, K, W, X>> for TensorRank2<D, I, J>
1614{
1615 type Output = TensorRank2List2D<D, I, K, W, X>;
1616 fn mul(self, tensor_rank_2_list_2d: TensorRank2List2D<D, J, K, W, X>) -> Self::Output {
1617 tensor_rank_2_list_2d
1618 .into_iter()
1619 .map(|tensor_rank_2_list_2d_entry| {
1620 tensor_rank_2_list_2d_entry
1621 .into_iter()
1622 .map(|tensor_rank_2| &self * tensor_rank_2)
1623 .collect()
1624 })
1625 .collect()
1626 }
1627}
1628
1629impl<const D: usize, const I: usize, const J: usize, const K: usize, const W: usize, const X: usize>
1630 Mul<TensorRank2List2D<D, J, K, W, X>> for &TensorRank2<D, I, J>
1631{
1632 type Output = TensorRank2List2D<D, I, K, W, X>;
1633 fn mul(self, tensor_rank_2_list_2d: TensorRank2List2D<D, J, K, W, X>) -> Self::Output {
1634 tensor_rank_2_list_2d
1635 .into_iter()
1636 .map(|tensor_rank_2_list_2d_entry| {
1637 tensor_rank_2_list_2d_entry
1638 .into_iter()
1639 .map(|tensor_rank_2| self * tensor_rank_2)
1640 .collect()
1641 })
1642 .collect()
1643 }
1644}
1645
1646impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank2Vec2D<D, J, K>>
1647 for TensorRank2<D, I, J>
1648{
1649 type Output = TensorRank2Vec2D<D, I, K>;
1650 fn mul(self, tensor_rank_2_list_2d: TensorRank2Vec2D<D, J, K>) -> Self::Output {
1651 tensor_rank_2_list_2d
1652 .into_iter()
1653 .map(|tensor_rank_2_list_2d_entry| {
1654 tensor_rank_2_list_2d_entry
1655 .into_iter()
1656 .map(|tensor_rank_2| &self * tensor_rank_2)
1657 .collect()
1658 })
1659 .collect()
1660 }
1661}
1662
1663impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank2Vec2D<D, J, K>>
1664 for &TensorRank2<D, I, J>
1665{
1666 type Output = TensorRank2Vec2D<D, I, K>;
1667 fn mul(self, tensor_rank_2_list_2d: TensorRank2Vec2D<D, J, K>) -> Self::Output {
1668 tensor_rank_2_list_2d
1669 .into_iter()
1670 .map(|tensor_rank_2_list_2d_entry| {
1671 tensor_rank_2_list_2d_entry
1672 .into_iter()
1673 .map(|tensor_rank_2| self * tensor_rank_2)
1674 .collect()
1675 })
1676 .collect()
1677 }
1678}
1679
1680#[allow(clippy::suspicious_arithmetic_impl)]
1681impl<const I: usize, const J: usize, const K: usize, const L: usize> Div<TensorRank4<3, I, J, K, L>>
1682 for &TensorRank2<3, I, J>
1683{
1684 type Output = TensorRank2<3, K, L>;
1685 fn div(self, tensor_rank_4: TensorRank4<3, I, J, K, L>) -> Self::Output {
1686 let tensor_rank_2: TensorRank2<9, 88, 99> = tensor_rank_4.into();
1687 let output_tensor_rank_1 = tensor_rank_2.inverse() * self.as_tensor_rank_1();
1688 let mut output = TensorRank2::zero();
1689 output.iter_mut().enumerate().for_each(|(i, output_i)| {
1690 output_i
1691 .iter_mut()
1692 .enumerate()
1693 .for_each(|(j, output_ij)| *output_ij = output_tensor_rank_1[3 * i + j])
1694 });
1695 output
1696 }
1697}