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