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::from_fn,
11 fmt::{self, Display, Formatter},
12 iter::Sum,
13 ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign},
14};
15
16use crate::{
17 ABS_TOL,
18 math::{
19 matrix::vector::Vector,
20 tensor::{
21 Jacobian, Solution, Tensor, TensorArray, rank_0::TensorRank0,
22 rank_1::list::TensorRank1List, rank_2::TensorRank2,
23 },
24 write_tensor_rank_0,
25 },
26};
27
28#[cfg(test)]
29use super::test::ErrorTensor;
30
31#[derive(Clone, Debug, PartialEq)]
35pub struct TensorRank1<const D: usize, const I: usize>([TensorRank0; D]);
36
37impl<const D: usize, const I: usize> TensorRank1<D, I> {
38 pub const fn const_from(array: [TensorRank0; D]) -> Self {
40 Self(array)
41 }
42}
43
44impl<const D: usize, const I: usize> Default for TensorRank1<D, I> {
45 fn default() -> Self {
46 Self::zero()
47 }
48}
49
50impl<const D: usize> From<TensorRank1<D, 0>> for TensorRank1<D, 1> {
51 fn from(tensor_rank_1: TensorRank1<D, 0>) -> Self {
52 Self(tensor_rank_1.0)
53 }
54}
55
56impl<const D: usize> From<&TensorRank1<D, 0>> for TensorRank1<D, 1> {
57 fn from(tensor_rank_1: &TensorRank1<D, 0>) -> Self {
58 Self(tensor_rank_1.0)
59 }
60}
61
62impl<const D: usize> From<TensorRank1<D, 1>> for TensorRank1<D, 0> {
63 fn from(tensor_rank_1: TensorRank1<D, 1>) -> Self {
64 Self(tensor_rank_1.0)
65 }
66}
67
68impl<const D: usize> From<&TensorRank1<D, 1>> for TensorRank1<D, 0> {
69 fn from(tensor_rank_1: &TensorRank1<D, 1>) -> Self {
70 Self(tensor_rank_1.0)
71 }
72}
73
74impl<const D: usize> From<TensorRank1<D, 9>> for TensorRank1<D, 0> {
75 fn from(tensor_rank_1: TensorRank1<D, 9>) -> Self {
76 Self(tensor_rank_1.0)
77 }
78}
79
80impl<const D: usize> From<&TensorRank1<D, 9>> for TensorRank1<D, 0> {
81 fn from(tensor_rank_1: &TensorRank1<D, 9>) -> Self {
82 Self(tensor_rank_1.0)
83 }
84}
85
86impl<const D: usize, const I: usize> Display for TensorRank1<D, I> {
87 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
88 write!(f, "\x1B[s")?;
89 write!(f, "[")?;
90 self.iter()
91 .try_for_each(|entry| write_tensor_rank_0(f, entry))?;
92 write!(f, "\x1B[2D]")
93 }
94}
95
96impl<const D: usize, const I: usize> TensorRank1<D, I> {
97 pub const fn as_ptr(&self) -> *const TensorRank0 {
99 self.0.as_ptr()
100 }
101 pub fn orthonormal_basis(&self) -> TensorRank1List<D, I, D> {
102 let norm = self.norm();
103 assert!(
104 norm > ABS_TOL,
105 "Cannot build an orthonormal basis from the zero vector"
106 );
107 let mut basis = TensorRank1List::zero();
108 basis[0] = self / norm;
109 let mut filled = 1;
110 for i in 0..D {
111 if filled == D {
112 break;
113 }
114 let mut v = zero();
115 v[i] = 1.0;
116 basis.iter().take(filled).for_each(|q| v -= q * (&v * q));
117 let v_norm = v.norm();
118 if v_norm > ABS_TOL {
119 basis[filled] = v / v_norm;
120 filled += 1;
121 }
122 }
123 assert!(filled == D, "Failed to construct full orthonormal basis");
124 basis
125 }
126}
127
128pub trait CrossProduct<T> {
129 type Output;
130 fn cross(self, other: T) -> Self::Output;
132}
133
134impl<const I: usize> CrossProduct<TensorRank1<3, I>> for &TensorRank1<3, I> {
157 type Output = TensorRank1<3, I>;
158 fn cross(self, other: TensorRank1<3, I>) -> Self::Output {
159 TensorRank1::const_from([
160 self[1] * other[2] - self[2] * other[1],
161 self[2] * other[0] - self[0] * other[2],
162 self[0] * other[1] - self[1] * other[0],
163 ])
164 }
165}
166
167impl<const I: usize> CrossProduct<Self> for &TensorRank1<3, I> {
168 type Output = TensorRank1<3, I>;
169 fn cross(self, other: Self) -> Self::Output {
170 TensorRank1::const_from([
171 self[1] * other[2] - self[2] * other[1],
172 self[2] * other[0] - self[0] * other[2],
173 self[0] * other[1] - self[1] * other[0],
174 ])
175 }
176}
177
178#[cfg(test)]
179impl<const D: usize, const I: usize> ErrorTensor for TensorRank1<D, I> {
180 fn error_fd(&self, comparator: &Self, epsilon: TensorRank0) -> Option<(bool, usize)> {
181 let error_count = self
182 .iter()
183 .zip(comparator.iter())
184 .filter(|&(&self_i, &comparator_i)| {
185 (self_i / comparator_i - 1.0).abs() >= epsilon
186 && (self_i.abs() >= epsilon || comparator_i.abs() >= epsilon)
187 })
188 .count();
189 if error_count > 0 {
190 Some((true, error_count))
191 } else {
192 None
193 }
194 }
195}
196
197impl<const D: usize, const I: usize> Solution for TensorRank1<D, I> {
198 fn decrement_from(&mut self, _other: &Vector) {
199 unimplemented!()
200 }
201 fn decrement_from_chained(&mut self, _other: &mut Vector, _vector: Vector) {
202 unimplemented!()
203 }
204}
205
206impl<const D: usize, const I: usize> Jacobian for TensorRank1<D, I> {
207 fn fill_into(self, _vector: &mut Vector) {
208 unimplemented!()
209 }
210 fn fill_into_chained(self, _other: Vector, _vector: &mut Vector) {
211 unimplemented!()
212 }
213}
214
215impl<const D: usize, const I: usize> Sub<Vector> for TensorRank1<D, I> {
216 type Output = Self;
217 fn sub(self, _vector: Vector) -> Self::Output {
218 unimplemented!()
219 }
220}
221
222impl<const D: usize, const I: usize> Sub<&Vector> for TensorRank1<D, I> {
223 type Output = Self;
224 fn sub(self, _vector: &Vector) -> Self::Output {
225 unimplemented!()
226 }
227}
228
229impl<const D: usize, const I: usize> Tensor for TensorRank1<D, I> {
230 type Item = TensorRank0;
231 fn full_contraction(&self, tensor_rank_1: &Self) -> TensorRank0 {
232 self * tensor_rank_1
233 }
234 fn iter(&self) -> impl Iterator<Item = &Self::Item> {
235 self.0.iter()
236 }
237 fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
238 self.0.iter_mut()
239 }
240 fn len(&self) -> usize {
241 D
242 }
243 fn size(&self) -> usize {
244 D
245 }
246}
247
248impl<const D: usize, const I: usize> IntoIterator for TensorRank1<D, I> {
249 type Item = TensorRank0;
250 type IntoIter = std::array::IntoIter<Self::Item, D>;
251 fn into_iter(self) -> Self::IntoIter {
252 self.0.into_iter()
253 }
254}
255
256impl<const D: usize, const I: usize> TensorArray for TensorRank1<D, I> {
257 type Array = [TensorRank0; D];
258 type Item = TensorRank0;
259 fn as_array(&self) -> Self::Array {
260 self.0
261 }
262 fn identity() -> Self {
263 ones()
264 }
265 fn zero() -> Self {
266 zero()
267 }
268}
269
270pub const fn ones<const D: usize, const I: usize>() -> TensorRank1<D, I> {
272 TensorRank1([1.0; D])
273}
274
275pub const fn zero<const D: usize, const I: usize>() -> TensorRank1<D, I> {
277 TensorRank1([0.0; D])
278}
279
280impl<const D: usize, const I: usize> From<[TensorRank0; D]> for TensorRank1<D, I> {
281 fn from(array: [TensorRank0; D]) -> Self {
282 Self(array)
283 }
284}
285
286impl<const D: usize, const I: usize> From<TensorRank1<D, I>> for [TensorRank0; D] {
287 fn from(tensor_rank_1: TensorRank1<D, I>) -> Self {
288 tensor_rank_1.0
289 }
290}
291
292impl<const D: usize, const I: usize> From<Vec<TensorRank0>> for TensorRank1<D, I> {
293 fn from(vec: Vec<TensorRank0>) -> Self {
294 Self(vec.try_into().unwrap())
295 }
296}
297
298impl<const D: usize, const I: usize> From<TensorRank1<D, I>> for Vec<TensorRank0> {
299 fn from(tensor_rank_1: TensorRank1<D, I>) -> Self {
300 tensor_rank_1.0.to_vec()
301 }
302}
303
304impl<const D: usize, const I: usize> From<Vector> for TensorRank1<D, I> {
305 fn from(_vector: Vector) -> Self {
306 unimplemented!()
307 }
308}
309
310impl<const D: usize, const I: usize> FromIterator<TensorRank0> for TensorRank1<D, I> {
311 fn from_iter<Ii: IntoIterator<Item = TensorRank0>>(into_iterator: Ii) -> Self {
312 let mut tensor_rank_1 = zero();
313 tensor_rank_1
314 .iter_mut()
315 .zip(into_iterator)
316 .for_each(|(tensor_rank_1_i, value_i)| *tensor_rank_1_i = value_i);
317 tensor_rank_1
318 }
319}
320
321impl<const D: usize, const I: usize> Index<usize> for TensorRank1<D, I> {
322 type Output = TensorRank0;
323 fn index(&self, index: usize) -> &Self::Output {
324 &self.0[index]
325 }
326}
327
328impl<const D: usize, const I: usize> IndexMut<usize> for TensorRank1<D, I> {
329 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
330 &mut self.0[index]
331 }
332}
333
334impl<const D: usize, const I: usize> Sum for TensorRank1<D, I> {
335 fn sum<Ii>(iter: Ii) -> Self
336 where
337 Ii: Iterator<Item = Self>,
338 {
339 iter.reduce(|mut acc, item| {
340 acc += item;
341 acc
342 })
343 .unwrap_or_else(Self::default)
344 }
345}
346
347impl<'a, const D: usize, const I: usize> Sum<&'a Self> for TensorRank1<D, I> {
348 fn sum<Ii>(iter: Ii) -> Self
349 where
350 Ii: Iterator<Item = &'a Self>,
351 {
352 iter.fold(Self::default(), |mut acc, item| {
353 acc += item;
354 acc
355 })
356 }
357}
358
359impl<const D: usize, const I: usize> Neg for TensorRank1<D, I> {
360 type Output = Self;
361 fn neg(self) -> Self::Output {
362 from_fn(|i| -self[i]).into()
363 }
364}
365
366impl<const D: usize, const I: usize> Neg for &TensorRank1<D, I> {
367 type Output = TensorRank1<D, I>;
368 fn neg(self) -> Self::Output {
369 from_fn(|i| -self[i]).into()
370 }
371}
372
373impl<const D: usize, const I: usize> Div<TensorRank0> for TensorRank1<D, I> {
374 type Output = Self;
375 fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
376 self /= tensor_rank_0;
377 self
378 }
379}
380
381impl<const D: usize, const I: usize> Div<TensorRank0> for &TensorRank1<D, I> {
382 type Output = TensorRank1<D, I>;
383 fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
384 self.iter().map(|self_i| self_i / tensor_rank_0).collect()
385 }
386}
387
388impl<const D: usize, const I: usize> Div<&TensorRank0> for TensorRank1<D, I> {
389 type Output = Self;
390 fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
391 self /= tensor_rank_0;
392 self
393 }
394}
395
396impl<const D: usize, const I: usize> Div<&TensorRank0> for &TensorRank1<D, I> {
397 type Output = TensorRank1<D, I>;
398 fn div(self, tensor_rank_0: &TensorRank0) -> Self::Output {
399 self.iter().map(|self_i| self_i / tensor_rank_0).collect()
400 }
401}
402
403impl<const D: usize, const I: usize> DivAssign<TensorRank0> for TensorRank1<D, I> {
404 fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
405 self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
406 }
407}
408
409impl<const D: usize, const I: usize> DivAssign<&TensorRank0> for TensorRank1<D, I> {
410 fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
411 self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
412 }
413}
414
415impl<const D: usize, const I: usize> Mul<TensorRank0> for TensorRank1<D, I> {
416 type Output = Self;
417 fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
418 self *= tensor_rank_0;
419 self
420 }
421}
422
423impl<const D: usize, const I: usize> Mul<TensorRank0> for &TensorRank1<D, I> {
424 type Output = TensorRank1<D, I>;
425 fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
426 self.iter().map(|self_i| self_i * tensor_rank_0).collect()
427 }
428}
429
430impl<const D: usize, const I: usize> Mul<&TensorRank0> for TensorRank1<D, I> {
431 type Output = Self;
432 fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
433 self *= tensor_rank_0;
434 self
435 }
436}
437
438impl<const D: usize, const I: usize> Mul<&TensorRank0> for &TensorRank1<D, I> {
439 type Output = TensorRank1<D, I>;
440 fn mul(self, tensor_rank_0: &TensorRank0) -> Self::Output {
441 self.iter().map(|self_i| self_i * tensor_rank_0).collect()
442 }
443}
444
445impl<const D: usize, const I: usize> MulAssign<TensorRank0> for TensorRank1<D, I> {
446 fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
447 self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
448 }
449}
450
451impl<const D: usize, const I: usize> MulAssign<&TensorRank0> for TensorRank1<D, I> {
452 fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
453 self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
454 }
455}
456
457impl<const D: usize, const I: usize> Add for TensorRank1<D, I> {
458 type Output = Self;
459 fn add(mut self, tensor_rank_1: Self) -> Self::Output {
460 self += tensor_rank_1;
461 self
462 }
463}
464
465impl<const D: usize, const I: usize> Add<&Self> for TensorRank1<D, I> {
466 type Output = Self;
467 fn add(mut self, tensor_rank_1: &Self) -> Self::Output {
468 self += tensor_rank_1;
469 self
470 }
471}
472
473impl<const D: usize, const I: usize> Add<TensorRank1<D, I>> for &TensorRank1<D, I> {
474 type Output = TensorRank1<D, I>;
475 fn add(self, mut tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
476 tensor_rank_1 += self;
477 tensor_rank_1
478 }
479}
480
481impl<const D: usize, const I: usize> Add<Self> for &TensorRank1<D, I> {
482 type Output = TensorRank1<D, I>;
483 fn add(self, tensor_rank_1: Self) -> Self::Output {
484 tensor_rank_1
485 .iter()
486 .zip(self.iter())
487 .map(|(tensor_rank_1_i, self_i)| self_i + *tensor_rank_1_i)
488 .collect()
489 }
490}
491
492impl<const D: usize, const I: usize> AddAssign for TensorRank1<D, I> {
493 fn add_assign(&mut self, tensor_rank_1: Self) {
494 self.iter_mut()
495 .zip(tensor_rank_1)
496 .for_each(|(self_i, tensor_rank_1_i)| *self_i += tensor_rank_1_i);
497 }
498}
499
500impl<const D: usize, const I: usize> AddAssign<&Self> for TensorRank1<D, I> {
501 fn add_assign(&mut self, tensor_rank_1: &Self) {
502 self.iter_mut()
503 .zip(tensor_rank_1.iter())
504 .for_each(|(self_i, tensor_rank_1_i)| *self_i += tensor_rank_1_i);
505 }
506}
507
508impl<const D: usize, const I: usize> Sub for TensorRank1<D, I> {
509 type Output = Self;
510 fn sub(mut self, tensor_rank_1: Self) -> Self::Output {
511 self -= tensor_rank_1;
512 self
513 }
514}
515
516impl<const D: usize, const I: usize> Sub<&Self> for TensorRank1<D, I> {
517 type Output = Self;
518 fn sub(mut self, tensor_rank_1: &Self) -> Self::Output {
519 self -= tensor_rank_1;
520 self
521 }
522}
523
524impl<const D: usize, const I: usize> Sub<TensorRank1<D, I>> for &TensorRank1<D, I> {
525 type Output = TensorRank1<D, I>;
526 fn sub(self, mut tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
527 tensor_rank_1
528 .iter_mut()
529 .zip(self.iter())
530 .for_each(|(tensor_rank_1_i, self_i)| *tensor_rank_1_i = self_i - *tensor_rank_1_i);
531 tensor_rank_1
532 }
533}
534
535impl<const D: usize, const I: usize> Sub<Self> for &TensorRank1<D, I> {
536 type Output = TensorRank1<D, I>;
537 fn sub(self, tensor_rank_1: Self) -> Self::Output {
538 tensor_rank_1
539 .iter()
540 .zip(self.iter())
541 .map(|(tensor_rank_1_i, self_i)| self_i - *tensor_rank_1_i)
542 .collect()
543 }
544}
545
546impl<const D: usize, const I: usize> SubAssign for TensorRank1<D, I> {
547 fn sub_assign(&mut self, tensor_rank_1: Self) {
548 self.iter_mut()
549 .zip(tensor_rank_1)
550 .for_each(|(self_i, tensor_rank_1_i)| *self_i -= tensor_rank_1_i);
551 }
552}
553
554impl<const D: usize, const I: usize> SubAssign<&Self> for TensorRank1<D, I> {
555 fn sub_assign(&mut self, tensor_rank_1: &Self) {
556 self.iter_mut()
557 .zip(tensor_rank_1.iter())
558 .for_each(|(self_i, tensor_rank_1_i)| *self_i -= tensor_rank_1_i);
559 }
560}
561
562impl<const D: usize, const I: usize> Mul for TensorRank1<D, I> {
563 type Output = TensorRank0;
564 fn mul(self, tensor_rank_1: Self) -> Self::Output {
565 self.into_iter()
566 .zip(tensor_rank_1)
567 .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
568 .sum()
569 }
570}
571
572impl<const D: usize, const I: usize> Mul<&Self> for TensorRank1<D, I> {
573 type Output = TensorRank0;
574 fn mul(self, tensor_rank_1: &Self) -> Self::Output {
575 self.into_iter()
576 .zip(tensor_rank_1.iter())
577 .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
578 .sum()
579 }
580}
581
582impl<const D: usize, const I: usize> Mul<TensorRank1<D, I>> for &TensorRank1<D, I> {
583 type Output = TensorRank0;
584 fn mul(self, tensor_rank_1: TensorRank1<D, I>) -> Self::Output {
585 self.iter()
586 .zip(tensor_rank_1)
587 .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
588 .sum()
589 }
590}
591
592impl<const D: usize, const I: usize> Mul for &TensorRank1<D, I> {
593 type Output = TensorRank0;
594 fn mul(self, tensor_rank_1: Self) -> Self::Output {
595 self.iter()
596 .zip(tensor_rank_1.iter())
597 .map(|(self_i, tensor_rank_1_i)| self_i * tensor_rank_1_i)
598 .sum()
599 }
600}
601
602#[allow(clippy::suspicious_arithmetic_impl)]
603impl<const D: usize, const I: usize, const J: usize> Div<TensorRank2<D, I, J>>
604 for &TensorRank1<D, I>
605{
606 type Output = TensorRank1<D, J>;
607 fn div(self, tensor_rank_2: TensorRank2<D, I, J>) -> Self::Output {
608 tensor_rank_2.inverse() * self
609 }
610}