conspire/math/tensor/
mod.rs1pub mod test;
2
3pub mod list;
4pub mod rank_0;
5pub mod rank_1;
6pub mod rank_2;
7pub mod rank_3;
8pub mod rank_4;
9pub mod tuple;
10pub mod vec;
11
12use super::{SquareMatrix, Vector};
13use crate::defeat_message;
14use rank_0::{
15 TensorRank0,
16 list::{TensorRank0List, vec::TensorRank0ListVec},
17};
18use std::{
19 fmt::{self, Debug, Display, Formatter},
20 iter::Sum,
21 ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
22};
23
24pub type Scalar = TensorRank0;
26
27pub type Scalars<const W: usize> = TensorRank0List<W>;
29
30pub type ScalarsVec<const W: usize> = TensorRank0ListVec<W>;
32
33#[derive(PartialEq)]
35pub enum TensorError {
36 NotPositiveDefinite,
37 SymmetricMatrixComplexEigenvalues,
38}
39
40impl Debug for TensorError {
41 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
42 let error = match self {
43 Self::NotPositiveDefinite => "\x1b[1;91mResult is not positive definite.".to_string(),
44 Self::SymmetricMatrixComplexEigenvalues => {
45 "\x1b[1;91mSymmetric matrix produced complex eigenvalues".to_string()
46 }
47 };
48 write!(f, "\n{error}\n\x1b[0;2;31m{}\x1b[0m\n", defeat_message())
49 }
50}
51
52impl Display for TensorError {
53 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
54 let error = match self {
55 Self::NotPositiveDefinite => "\x1b[1;91mResult is not positive definite.".to_string(),
56 Self::SymmetricMatrixComplexEigenvalues => {
57 "\x1b[1;91mSymmetric matrix produced complex eigenvalues".to_string()
58 }
59 };
60 write!(f, "{error}\x1b[0m")
61 }
62}
63
64pub trait Solution
66where
67 Self: From<Vector> + Tensor,
68{
69 fn decrement_from(&mut self, other: &Vector);
71 fn decrement_from_chained(&mut self, other: &mut Vector, vector: Vector);
73 fn decrement_from_retained(&mut self, _retained: &[bool], _other: &Vector) {
75 unimplemented!()
76 }
77}
78
79pub trait Jacobian
81where
82 Self:
83 From<Vector> + Tensor + Sub<Vector, Output = Self> + for<'a> Sub<&'a Vector, Output = Self>,
84{
85 fn fill_into(self, vector: &mut Vector);
87 fn fill_into_chained(self, other: Vector, vector: &mut Vector);
89 fn retain_from(self, _retained: &[bool]) -> Vector {
91 unimplemented!()
92 }
93 fn zero_out(&mut self, _indices: &[usize]) {
95 unimplemented!()
96 }
97}
98
99pub trait Hessian
101where
102 Self: Tensor,
103{
104 fn fill_into(self, square_matrix: &mut SquareMatrix);
106 fn retain_from(self, _retained: &[bool]) -> SquareMatrix {
108 unimplemented!()
109 }
110}
111
112pub trait Rank2
114where
115 Self: Sized,
116{
117 type Transpose;
119 fn deviatoric(&self) -> Self;
121 fn deviatoric_and_trace(&self) -> (Self, TensorRank0);
123 fn is_diagonal(&self) -> bool;
125 fn is_identity(&self) -> bool;
127 fn is_symmetric(&self) -> bool;
129 fn second_invariant(&self) -> TensorRank0 {
131 0.5 * (self.trace().powi(2) - self.squared_trace())
132 }
133 fn squared_trace(&self) -> TensorRank0;
135 fn trace(&self) -> TensorRank0;
137 fn transpose(&self) -> Self::Transpose;
139}
140
141#[allow(clippy::len_without_is_empty)]
143pub trait Tensor
144where
145 for<'a> Self: Sized
146 + Add<Self, Output = Self>
147 + Add<&'a Self, Output = Self>
148 + AddAssign
149 + AddAssign<&'a Self>
150 + Clone
151 + Debug
152 + Default
153 + Display
154 + Div<TensorRank0, Output = Self>
155 + DivAssign<TensorRank0>
157 + DivAssign<&'a TensorRank0>
158 + Mul<TensorRank0, Output = Self>
159 + MulAssign<TensorRank0>
161 + MulAssign<&'a TensorRank0>
162 + Sub<Self, Output = Self>
163 + Sub<&'a Self, Output = Self>
164 + SubAssign
165 + SubAssign<&'a Self>
166 + Sum,
167 Self::Item: Tensor,
168{
169 type Item;
171 fn error_count(&self, other: &Self, tol_abs: Scalar, tol_rel: Scalar) -> Option<usize> {
173 let error_count = self
174 .iter()
175 .zip(other.iter())
176 .filter_map(|(self_entry, other_entry)| {
177 self_entry.error_count(other_entry, tol_abs, tol_rel)
178 })
179 .sum();
180 if error_count > 0 {
181 Some(error_count)
182 } else {
183 None
184 }
185 }
186 fn full_contraction(&self, tensor: &Self) -> TensorRank0 {
188 self.iter()
189 .zip(tensor.iter())
190 .map(|(self_entry, tensor_entry)| self_entry.full_contraction(tensor_entry))
191 .sum()
192 }
193 fn is_zero(&self) -> bool {
195 self.iter().filter(|entry| !entry.is_zero()).count() == 0
196 }
197 fn iter(&self) -> impl Iterator<Item = &Self::Item>;
201 fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item>;
205 fn len(&self) -> usize;
207 fn norm(&self) -> TensorRank0 {
209 self.norm_squared().sqrt()
210 }
211 fn norm_inf(&self) -> TensorRank0 {
213 self.iter()
214 .fold(0.0, |acc, entry| entry.norm_inf().max(acc))
215 }
216 fn norm_squared(&self) -> TensorRank0 {
218 self.full_contraction(self)
219 }
220 fn normalize(&mut self) {
222 *self /= self.norm()
223 }
224 fn normalized(self) -> Self {
226 let norm = self.norm();
227 self / norm
228 }
229 fn size(&self) -> usize;
231 fn sub_abs(&self, other: &Self) -> Self {
233 let mut difference = self.clone();
234 difference
235 .iter_mut()
236 .zip(self.iter().zip(other.iter()))
237 .for_each(|(entry, (self_entry, other_entry))| {
238 *entry = self_entry.sub_abs(other_entry)
239 });
240 difference
241 }
242 fn sub_rel(&self, other: &Self) -> Self {
244 let mut difference = self.clone();
245 difference
246 .iter_mut()
247 .zip(self.iter().zip(other.iter()))
248 .for_each(|(entry, (self_entry, other_entry))| {
249 *entry = self_entry.sub_rel(other_entry)
250 });
251 difference
252 }
253}
254
255pub trait TensorArray {
257 type Array;
259 type Item;
261 fn as_array(&self) -> Self::Array;
263 fn identity() -> Self;
265 fn new(array: Self::Array) -> Self;
267 fn zero() -> Self;
269}
270
271pub trait TensorVec
273where
274 Self: FromIterator<Self::Item> + Index<usize, Output = Self::Item> + IndexMut<usize>,
275{
276 type Item;
278 fn append(&mut self, other: &mut Self);
280 fn capacity(&self) -> usize;
282 fn is_empty(&self) -> bool;
284 fn new() -> Self;
286 fn push(&mut self, item: Self::Item);
288 fn remove(&mut self, _index: usize) -> Self::Item;
290 fn retain<F>(&mut self, f: F)
292 where
293 F: FnMut(&Self::Item) -> bool;
294 fn swap_remove(&mut self, _index: usize) -> Self::Item;
296}