1pub(super) mod list;
2pub(super) mod norm;
3pub(super) mod rank_0;
4pub(super) mod rank_1;
5pub(super) mod rank_2;
6pub(super) mod rank_3;
7pub(super) mod rank_4;
8pub(super) mod tuple;
9pub(super) mod vec;
10
11pub use norm::Norm;
12
13use super::{SquareMatrix, Vector};
14use crate::math::{Style, StyledError, styled_error};
15use rank_0::{
16 TensorRank0,
17 list::{TensorRank0List, vec::TensorRank0ListVec},
18};
19use std::{
20 fmt::{Debug, Display},
21 iter::Sum,
22 ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
23};
24
25pub type Scalar = TensorRank0;
27
28pub type Scalars = Vector;
30
31pub type ScalarList<const N: usize> = TensorRank0List<N>;
33
34pub type ScalarListVec<const N: usize> = TensorRank0ListVec<N>;
36
37#[derive(PartialEq)]
39pub enum TensorError {
40 NotPositiveDefinite,
41 SymmetricMatrixComplexEigenvalues,
42}
43
44impl StyledError for TensorError {
45 fn message(&self, style: &Style) -> String {
46 let h = style.headline;
47 match self {
48 Self::NotPositiveDefinite => format!("{h}Result is not positive definite."),
49 Self::SymmetricMatrixComplexEigenvalues => {
50 format!("{h}Symmetric matrix produced complex eigenvalues")
51 }
52 }
53 }
54}
55
56styled_error!(TensorError);
57
58pub trait Solution
60where
61 Self: From<Vector> + Tensor,
62{
63 fn decrement_from(&mut self, other: &Vector);
65 fn decrement_from_chained(&mut self, other: &mut Vector, vector: Vector);
67 fn decrement_from_retained(&mut self, _retained: &[bool], _other: &Vector) {
69 unimplemented!()
70 }
71}
72
73pub trait Jacobian
75where
76 Self:
77 From<Vector> + Tensor + Sub<Vector, Output = Self> + for<'a> Sub<&'a Vector, Output = Self>,
78{
79 fn fill_into(self, vector: &mut Vector);
81 fn fill_into_chained(self, other: Vector, vector: &mut Vector);
83 fn retain_from(self, _retained: &[bool]) -> Vector {
85 unimplemented!()
86 }
87 fn zero_out(&mut self, _indices: &[usize]) {
89 unimplemented!()
90 }
91}
92
93pub trait Hessian
95where
96 Self: Tensor,
97{
98 fn entry(&self, row: usize, column: usize) -> Scalar;
100 fn fill_into(self, square_matrix: &mut SquareMatrix);
102 fn retain_from(self, _retained: &[bool]) -> SquareMatrix {
104 unimplemented!()
105 }
106}
107
108pub trait HessianAccumulate<const D: usize, const I: usize> {
114 fn accumulate(&mut self, a: usize, b: usize, block: rank_2::TensorRank2<D, I, I>);
115}
116
117pub trait HessianAccumulateGeneral<const D: usize, const I: usize>:
122 HessianAccumulate<D, I>
123{
124 fn accumulate_general(&mut self, a: usize, b: usize, block: rank_2::TensorRank2<D, I, I>);
125}
126
127pub trait Rank2
129where
130 Self: Sized,
131{
132 type Transpose;
134 fn deviatoric(&self) -> Self;
136 fn deviatoric_and_trace(&self) -> (Self, TensorRank0);
138 fn is_diagonal(&self) -> bool;
140 fn is_identity(&self) -> bool;
142 fn is_symmetric(&self) -> bool;
144 fn second_invariant(&self) -> TensorRank0 {
146 0.5 * (self.trace().powi(2) - self.squared_trace())
147 }
148 fn squared_trace(&self) -> TensorRank0;
150 fn trace(&self) -> TensorRank0;
152 fn transpose(&self) -> Self::Transpose;
154}
155
156#[allow(clippy::len_without_is_empty)]
158pub trait Tensor
159where
160 for<'a> Self: Sized
161 + Add<Self, Output = Self>
162 + Add<&'a Self, Output = Self>
163 + AddAssign
164 + AddAssign<&'a Self>
165 + Clone
166 + Debug
167 + Default
168 + Display
169 + Div<TensorRank0, Output = Self>
170 + DivAssign<TensorRank0>
172 + DivAssign<&'a TensorRank0>
173 + Mul<TensorRank0, Output = Self>
174 + MulAssign<TensorRank0>
176 + MulAssign<&'a TensorRank0>
177 + Sub<Self, Output = Self>
178 + Sub<&'a Self, Output = Self>
179 + SubAssign
180 + SubAssign<&'a Self>
181 + Sum,
182 Self::Item: Tensor,
183{
184 type Item;
186 fn error_count_zero(&self, tol_abs: Scalar, tol_rel: Scalar) -> Option<usize> {
188 let error_count = self
189 .iter()
190 .filter_map(|entry| entry.error_count_zero(tol_abs, tol_rel))
191 .sum();
192 if error_count > 0 {
193 Some(error_count)
194 } else {
195 None
196 }
197 }
198 fn error_count(&self, other: &Self, tol_abs: Scalar, tol_rel: Scalar) -> Option<usize> {
200 let error_count = self
201 .iter()
202 .zip(other.iter())
203 .filter_map(|(self_entry, other_entry)| {
204 self_entry.error_count(other_entry, tol_abs, tol_rel)
205 })
206 .sum();
207 if error_count > 0 {
208 Some(error_count)
209 } else {
210 None
211 }
212 }
213 fn full_contraction(&self, tensor: &Self) -> TensorRank0 {
215 self.iter()
216 .zip(tensor.iter())
217 .map(|(self_entry, tensor_entry)| self_entry.full_contraction(tensor_entry))
218 .sum()
219 }
220 fn is_zero(&self) -> bool {
222 self.iter().filter(|entry| !entry.is_zero()).count() == 0
223 }
224 fn iter(&self) -> impl Iterator<Item = &Self::Item>;
228 fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item>;
232 fn len(&self) -> usize;
234 fn norm(&self) -> TensorRank0 {
236 self.norm_squared().sqrt()
237 }
238 fn norm_inf(&self) -> TensorRank0 {
240 self.iter()
241 .fold(0.0, |acc, entry| entry.norm_inf().max(acc))
242 }
243 fn norm_l1(&self) -> TensorRank0 {
245 self.iter().fold(0.0, |acc, entry| acc + entry.norm_l1())
246 }
247 fn norm_p_sum(&self, p: TensorRank0) -> TensorRank0 {
249 self.iter()
250 .fold(0.0, |acc, entry| acc + entry.norm_p_sum(p))
251 }
252 fn norm_p(&self, p: TensorRank0) -> TensorRank0 {
254 self.norm_p_sum(p).powf(1.0 / p)
255 }
256 fn norm_squared(&self) -> TensorRank0 {
258 self.full_contraction(self)
259 }
260 fn normalize(&mut self) {
262 *self /= self.norm()
263 }
264 fn normalized(self) -> Self {
266 let norm = self.norm();
267 self / norm
268 }
269 fn size(&self) -> usize;
271 fn sub_abs(&self, other: &Self) -> Self {
273 let mut difference = self.clone();
274 difference
275 .iter_mut()
276 .zip(self.iter().zip(other.iter()))
277 .for_each(|(entry, (self_entry, other_entry))| {
278 *entry = self_entry.sub_abs(other_entry)
279 });
280 difference
281 }
282 fn sub_rel(&self, other: &Self) -> Self {
284 let mut difference = self.clone();
285 difference
286 .iter_mut()
287 .zip(self.iter().zip(other.iter()))
288 .for_each(|(entry, (self_entry, other_entry))| {
289 *entry = self_entry.sub_rel(other_entry)
290 });
291 difference
292 }
293}
294
295pub trait TensorArray {
297 type Array;
299 type Item;
301 fn as_array(&self) -> Self::Array;
303 fn identity() -> Self;
305 fn zero() -> Self;
307}
308
309pub trait TensorVec
311where
312 Self: FromIterator<Self::Item> + Index<usize, Output = Self::Item> + IndexMut<usize>,
313{
314 type Item;
316 fn append(&mut self, other: &mut Self);
318 fn capacity(&self) -> usize;
320 fn is_empty(&self) -> bool;
322 fn new() -> Self;
324 fn push(&mut self, item: Self::Item);
326 fn remove(&mut self, index: usize) -> Self::Item;
328 fn reserve(&mut self, additional: usize);
330 fn retain<F>(&mut self, f: F)
332 where
333 F: FnMut(&Self::Item) -> bool;
334 fn swap_remove(&mut self, index: usize) -> Self::Item;
336 fn with_capacity(capacity: usize) -> Self;
338}