use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
pub trait Differentiable:
Copy
+ Clone
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
+ Div<Output = Self>
+ Neg<Output = Self>
+ Add<f64, Output = Self>
+ Sub<f64, Output = Self>
+ Mul<f64, Output = Self>
+ Div<f64, Output = Self>
+ AddAssign
+ SubAssign
+ AddAssign<f64>
+ SubAssign<f64>
+ MulAssign<f64>
+ DivAssign<f64>
{
fn value(&self) -> f64;
fn constant(value: f64) -> Self;
fn variable(value: f64, param_idx: usize) -> Self;
}
pub trait FirstOrder: Differentiable {
fn grad(&self, i: usize) -> f64;
fn grad_mut(&mut self, i: usize) -> &mut f64;
fn extract_grad<const M: usize>(&self) -> [f64; M] {
std::array::from_fn(|i| self.grad(i))
}
}
pub trait SecondOrder: FirstOrder {
fn hess(&self, i: usize, j: usize) -> f64;
fn hess_mut(&mut self, i: usize, j: usize) -> &mut f64;
fn extract_hess<const M: usize>(&self) -> [[f64; M]; M] {
let mut h = [[0.0; M]; M];
#[allow(clippy::needless_range_loop)]
for i in 0..M {
for j in 0..=i {
let v = self.hess(i, j);
h[i][j] = v;
h[j][i] = v;
}
}
h
}
}
pub trait HigherOrder: SecondOrder {
}
pub trait ThirdOrder: SecondOrder {
fn tens(&self, i: usize, j: usize, k: usize) -> f64;
fn tens_mut(&mut self, i: usize, j: usize, k: usize) -> &mut f64;
fn extract_tens<const M: usize>(&self) -> [[[f64; M]; M]; M] {
let mut t = [[[0.0; M]; M]; M];
for i in 0..M {
for j in 0..=i {
for k in 0..=j {
let v = self.tens(i, j, k);
t[i][j][k] = v;
t[i][k][j] = v;
t[j][i][k] = v;
t[j][k][i] = v;
t[k][i][j] = v;
t[k][j][i] = v;
}
}
}
t
}
}
pub trait DifferentiableMath: Differentiable {
fn sin(self) -> Self;
fn cos(self) -> Self;
fn tan(self) -> Self;
fn asin(self) -> Self;
fn acos(self) -> Self;
fn atan(self) -> Self;
fn atan2(y: Self, x: Self) -> Self;
fn sin_cos(self) -> (Self, Self);
fn sinh(self) -> Self;
fn cosh(self) -> Self;
fn tanh(self) -> Self;
fn exp(self) -> Self;
fn log(self, base: f64) -> Self;
fn log10(self) -> Self;
fn ln(self) -> Self;
fn sqrt(self) -> Self;
fn powf(self, n: f64) -> Self;
fn powi(self, n: i32) -> Self;
fn abs(self) -> Self;
}
pub trait AutoDiff: DifferentiableMath + FirstOrder {}