conspire/math/tensor/
mod.rs

1pub mod test;
2
3pub mod rank_0;
4pub mod rank_1;
5pub mod rank_2;
6pub mod rank_3;
7pub mod rank_4;
8
9use super::{SquareMatrix, Vector};
10use crate::defeat_message;
11use rank_0::TensorRank0;
12use std::{
13    fmt::{self, Debug, Display, Formatter},
14    ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
15};
16
17/// A scalar.
18pub type Scalar = TensorRank0;
19
20/// Possible errors for tensors.
21#[derive(PartialEq)]
22pub enum TensorError {
23    NotPositiveDefinite,
24}
25
26impl Debug for TensorError {
27    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
28        let error = match self {
29            Self::NotPositiveDefinite => "\x1b[1;91mResult is not positive definite.".to_string(),
30        };
31        write!(f, "\n{error}\n\x1b[0;2;31m{}\x1b[0m\n", defeat_message())
32    }
33}
34
35impl Display for TensorError {
36    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
37        let error = match self {
38            Self::NotPositiveDefinite => "\x1b[1;91mResult is not positive definite.".to_string(),
39        };
40        write!(f, "{error}\x1b[0m")
41    }
42}
43
44/// Common methods for solutions.
45pub trait Solution
46where
47    Self: Tensor,
48{
49    /// Decrements the solution chained with a vector from another vector.
50    fn decrement_from_chained(&mut self, other: &mut Vector, vector: Vector);
51}
52
53/// Common methods for Jacobians.
54pub trait Jacobian
55where
56    Self: Tensor + Sub<Vector, Output = Self> + for<'a> Sub<&'a Vector, Output = Self>,
57{
58    /// Fills the Jacobian into a vector.
59    fn fill_into(self, vector: &mut Vector);
60    /// Fills the Jacobian chained with a vector into another vector.
61    fn fill_into_chained(self, other: Vector, vector: &mut Vector);
62}
63
64/// Common methods for Hessians.
65pub trait Hessian
66where
67    Self: Tensor,
68{
69    /// Fills the Hessian into a square matrix.
70    fn fill_into(self, square_matrix: &mut SquareMatrix);
71}
72
73/// Common methods for rank-2 tensors.
74pub trait Rank2
75where
76    Self: Sized,
77{
78    /// The type that is the transpose of the tensor.
79    type Transpose;
80    /// Returns the deviatoric component of the rank-2 tensor.
81    fn deviatoric(&self) -> Self;
82    /// Returns the deviatoric component and trace of the rank-2 tensor.
83    fn deviatoric_and_trace(&self) -> (Self, TensorRank0);
84    /// Checks whether the tensor is a diagonal tensor.
85    fn is_diagonal(&self) -> bool;
86    /// Checks whether the tensor is the identity tensor.
87    fn is_identity(&self) -> bool;
88    /// Checks whether the tensor is a symmetric tensor.
89    fn is_symmetric(&self) -> bool;
90    /// Returns the second invariant of the rank-2 tensor.
91    fn second_invariant(&self) -> TensorRank0 {
92        0.5 * (self.trace().powi(2) - self.squared_trace())
93    }
94    /// Returns the trace of the rank-2 tensor squared.
95    fn squared_trace(&self) -> TensorRank0;
96    /// Returns the trace of the rank-2 tensor.
97    fn trace(&self) -> TensorRank0;
98    /// Returns the transpose of the rank-2 tensor.
99    fn transpose(&self) -> Self::Transpose;
100}
101
102/// Common methods for tensors.
103pub trait Tensor
104where
105    for<'a> Self: Sized
106        + Debug
107        + Display
108        + Add<Self, Output = Self>
109        + Add<&'a Self, Output = Self>
110        + AddAssign
111        + AddAssign<&'a Self>
112        + Clone
113        + Div<TensorRank0, Output = Self>
114        + DivAssign<TensorRank0>
115        + Mul<TensorRank0, Output = Self>
116        + MulAssign<TensorRank0>
117        + Sub<Self, Output = Self>
118        + Sub<&'a Self, Output = Self>
119        + SubAssign
120        + SubAssign<&'a Self>,
121    Self::Item: Tensor,
122{
123    /// The type of item encountered when iterating over the tensor.
124    type Item;
125    /// Returns number of different entries given absolute and relative tolerances.
126    fn error_count(&self, other: &Self, tol_abs: &Scalar, tol_rel: &Scalar) -> Option<usize> {
127        let error_count = self
128            .iter()
129            .zip(other.iter())
130            .filter_map(|(self_entry, other_entry)| {
131                self_entry.error_count(other_entry, tol_abs, tol_rel)
132            })
133            .sum();
134        if error_count > 0 {
135            Some(error_count)
136        } else {
137            None
138        }
139    }
140    /// Returns the full contraction with another tensor.
141    fn full_contraction(&self, tensor: &Self) -> TensorRank0 {
142        self.iter()
143            .zip(tensor.iter())
144            .map(|(self_entry, tensor_entry)| self_entry.full_contraction(tensor_entry))
145            .sum()
146    }
147    /// Checks whether the tensor is the zero tensor.
148    fn is_zero(&self) -> bool {
149        self.iter().filter(|entry| !entry.is_zero()).count() == 0
150    }
151    /// Returns an iterator.
152    ///
153    /// The iterator yields all items from start to end. [Read more](https://doc.rust-lang.org/std/iter/)
154    fn iter(&self) -> impl Iterator<Item = &Self::Item>;
155    /// Returns an iterator that allows modifying each value.
156    ///
157    /// The iterator yields all items from start to end. [Read more](https://doc.rust-lang.org/std/iter/)
158    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item>;
159    /// Returns the tensor norm.
160    fn norm(&self) -> TensorRank0 {
161        self.norm_squared().sqrt()
162    }
163    /// Returns the infinity norm.
164    fn norm_inf(&self) -> TensorRank0 {
165        unimplemented!()
166    }
167    /// Returns the tensor norm squared.
168    fn norm_squared(&self) -> TensorRank0 {
169        self.full_contraction(self)
170    }
171    /// Normalizes the tensor.
172    fn normalize(&mut self) {
173        *self /= self.norm()
174    }
175    /// Returns the tensor normalized.
176    fn normalized(self) -> Self {
177        let norm = self.norm();
178        self / norm
179    }
180    /// Returns the total number of entries.
181    fn num_entries(&self) -> usize {
182        unimplemented!()
183    }
184    /// Returns the positive difference of the two tensors.
185    fn sub_abs(&self, other: &Self) -> Self {
186        let mut difference = self.clone();
187        difference
188            .iter_mut()
189            .zip(self.iter().zip(other.iter()))
190            .for_each(|(entry, (self_entry, other_entry))| {
191                *entry = self_entry.sub_abs(other_entry)
192            });
193        difference
194    }
195    /// Returns the relative difference of the two tensors.
196    fn sub_rel(&self, other: &Self) -> Self {
197        let mut difference = self.clone();
198        difference
199            .iter_mut()
200            .zip(self.iter().zip(other.iter()))
201            .for_each(|(entry, (self_entry, other_entry))| {
202                *entry = self_entry.sub_rel(other_entry)
203            });
204        difference
205    }
206}
207
208/// Common methods for tensors derived from arrays.
209pub trait TensorArray {
210    /// The type of array corresponding to the tensor.
211    type Array;
212    /// The type of item encountered when iterating over the tensor.
213    type Item;
214    /// Returns the tensor as an array.
215    fn as_array(&self) -> Self::Array;
216    /// Returns the identity tensor.
217    fn identity() -> Self;
218    /// Returns a tensor given an array.
219    fn new(array: Self::Array) -> Self;
220    /// Returns the zero tensor.
221    fn zero() -> Self;
222}
223
224/// Common methods for tensors derived from Vec.
225pub trait TensorVec
226where
227    Self: FromIterator<Self::Item> + Index<usize, Output = Self::Item> + IndexMut<usize>,
228{
229    /// The type of item encountered when iterating over the tensor.
230    type Item;
231    /// The type of slice corresponding to the tensor.
232    type Slice<'a>;
233    /// Moves all the items of other into self, leaving other empty.
234    fn append(&mut self, other: &mut Self);
235    /// Returns `true` if the vector contains no items.
236    fn is_empty(&self) -> bool;
237    /// Returns the number of items in the vector, also referred to as its ‘length’.
238    fn len(&self) -> usize;
239    /// Returns a tensor given a slice.
240    fn new(slice: Self::Slice<'_>) -> Self;
241    /// Appends an item to the back of the Vec.
242    fn push(&mut self, item: Self::Item);
243    /// Removes an item from the Vec and returns it, shifting items to the left.
244    fn remove(&mut self, _index: usize) -> Self::Item;
245    /// Retains only the items specified by the predicate.
246    fn retain<F>(&mut self, f: F)
247    where
248        F: FnMut(&Self::Item) -> bool;
249    /// Removes an item from the Vec and returns it, replacing it the last item.
250    fn swap_remove(&mut self, _index: usize) -> Self::Item;
251    /// Returns the zero tensor.
252    fn zero(len: usize) -> Self;
253}