#[cfg(test)]
pub mod test;
pub mod rank_0;
pub mod rank_1;
pub mod rank_2;
pub mod rank_3;
pub mod rank_4;
use rank_0::TensorRank0;
use std::{
fmt::{Debug, Display},
ops::{Add, AddAssign, Div, Mul, Sub, SubAssign},
};
pub trait Convert<T> {
fn convert(&self) -> T;
}
#[derive(Debug)]
pub enum TensorError {
NotPositiveDefinite,
}
impl PartialEq for TensorError {
fn eq(&self, other: &Self) -> bool {
match self {
Self::NotPositiveDefinite => match other {
Self::NotPositiveDefinite => true,
},
}
}
}
pub trait Hessian {
fn is_positive_definite(&self) -> bool;
}
pub trait Rank2: Sized {
type Transpose;
fn cholesky_decomposition(&self) -> Result<Self, TensorError>;
fn deviatoric(&self) -> Self;
fn deviatoric_and_trace(&self) -> (Self, TensorRank0);
fn is_diagonal(&self) -> bool;
fn is_identity(&self) -> bool;
fn second_invariant(&self) -> TensorRank0 {
0.5 * (self.trace().powi(2) - self.squared_trace())
}
fn squared_trace(&self) -> TensorRank0;
fn trace(&self) -> TensorRank0;
fn transpose(&self) -> Self::Transpose;
}
pub trait Tensor
where
for<'a> Self: Sized
+ Debug
+ Display
+ Add<Self, Output = Self>
+ Add<&'a Self, Output = Self>
+ AddAssign
+ AddAssign<&'a Self>
+ Div<TensorRank0, Output = Self>
+ Mul<TensorRank0, Output = Self>
+ Sub<Self, Output = Self>
+ Sub<&'a Self, Output = Self>
+ SubAssign
+ SubAssign<&'a Self>,
Self::Item: Tensor,
{
type Item;
fn copy(&self) -> Self;
fn full_contraction(&self, tensor: &Self) -> TensorRank0 {
self.iter()
.zip(tensor.iter())
.map(|(self_entry, tensor_entry)| self_entry.full_contraction(tensor_entry))
.sum()
}
fn get_at(&self, _indices: &[usize]) -> &TensorRank0 {
panic!("Need to implement get_at() for {:?}.", self)
}
fn get_at_mut(&mut self, _indices: &[usize]) -> &mut TensorRank0 {
panic!("Need to implement get_at_mut() for {:?}.", self)
}
fn is_zero(&self) -> bool {
self.iter().filter(|entry| !entry.is_zero()).count() == 0
}
fn iter(&self) -> impl Iterator<Item = &Self::Item>;
fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item>;
fn norm(&self) -> TensorRank0 {
self.norm_squared().sqrt()
}
fn norm_squared(&self) -> TensorRank0 {
self.full_contraction(self)
}
fn normalized(self) -> Self {
let norm = self.norm();
self / norm
}
}
pub trait TensorArray {
type Array;
type Item;
fn as_array(&self) -> Self::Array;
fn identity() -> Self;
fn new(array: Self::Array) -> Self;
fn zero() -> Self;
}
pub trait TensorVec<'a> {
type Item;
type Slice;
fn is_empty(&self) -> bool;
fn len(&self) -> usize;
fn new(slice: Self::Slice) -> Self;
fn zero(len: usize) -> Self;
}