use crate::differentiation::Primitive;
use crate::numeric::extra::{Real, RealRef};
use crate::numeric::{Numeric, NumericRef};
use std::marker::PhantomData;
pub trait FunctionDerivative<T> {
fn function(x: T, y: T) -> T;
fn d_function_dx(x: T, y: T) -> T;
fn d_function_dy(x: T, y: T) -> T;
}
pub trait UnaryFunctionDerivative<T> {
fn function(x: T) -> T;
fn d_function_dx(x: T) -> T;
}
pub struct Addition<T> {
_type: PhantomData<T>,
}
impl<T> FunctionDerivative<T> for Addition<T>
where
T: Numeric + Primitive,
for<'t> &'t T: NumericRef<T>,
{
fn function(x: T, y: T) -> T {
x + y
}
fn d_function_dx(_x: T, _y: T) -> T {
T::one()
}
fn d_function_dy(_x: T, _y: T) -> T {
T::one()
}
}
pub struct Subtraction<T> {
_type: PhantomData<T>,
}
impl<T> FunctionDerivative<T> for Subtraction<T>
where
T: Numeric + Primitive,
for<'t> &'t T: NumericRef<T>,
{
fn function(x: T, y: T) -> T {
x - y
}
fn d_function_dx(_x: T, _y: T) -> T {
T::one()
}
fn d_function_dy(_x: T, _y: T) -> T {
-T::one()
}
}
pub struct Multiplication<T> {
_type: PhantomData<T>,
}
impl<T> FunctionDerivative<T> for Multiplication<T>
where
T: Numeric + Primitive,
for<'t> &'t T: NumericRef<T>,
{
fn function(x: T, y: T) -> T {
x * y
}
fn d_function_dx(_x: T, y: T) -> T {
y
}
fn d_function_dy(x: T, _y: T) -> T {
x
}
}
pub struct Division<T> {
_type: PhantomData<T>,
}
impl<T> FunctionDerivative<T> for Division<T>
where
T: Numeric + Primitive,
for<'t> &'t T: NumericRef<T>,
{
fn function(x: T, y: T) -> T {
x / y
}
fn d_function_dx(_x: T, y: T) -> T {
T::one() / y
}
fn d_function_dy(x: T, y: T) -> T {
-x / (y.clone() * y)
}
}
pub struct Power<T> {
_type: PhantomData<T>,
}
impl<T> FunctionDerivative<T> for Power<T>
where
T: Real + Primitive,
for<'t> &'t T: RealRef<T>,
{
fn function(x: T, y: T) -> T {
x.pow(y)
}
fn d_function_dx(x: T, y: T) -> T {
y.clone() * x.pow(y - T::one())
}
fn d_function_dy(x: T, y: T) -> T {
x.clone().pow(y) * x.ln()
}
}
pub struct Negation<T> {
_type: PhantomData<T>,
}
impl<T> UnaryFunctionDerivative<T> for Negation<T>
where
T: Numeric + Primitive,
for<'t> &'t T: NumericRef<T>,
{
fn function(x: T) -> T {
-x
}
fn d_function_dx(_x: T) -> T {
-T::one()
}
}
pub struct Sine<T> {
_type: PhantomData<T>,
}
impl<T> UnaryFunctionDerivative<T> for Sine<T>
where
T: Real + Primitive,
for<'t> &'t T: RealRef<T>,
{
fn function(x: T) -> T {
x.sin()
}
fn d_function_dx(x: T) -> T {
x.cos()
}
}
pub struct Cosine<T> {
_type: PhantomData<T>,
}
impl<T> UnaryFunctionDerivative<T> for Cosine<T>
where
T: Real + Primitive,
for<'t> &'t T: RealRef<T>,
{
fn function(x: T) -> T {
x.cos()
}
fn d_function_dx(x: T) -> T {
-x.sin()
}
}
pub struct Exponential<T> {
_type: PhantomData<T>,
}
impl<T> UnaryFunctionDerivative<T> for Exponential<T>
where
T: Real + Primitive,
for<'t> &'t T: RealRef<T>,
{
fn function(x: T) -> T {
x.exp()
}
fn d_function_dx(x: T) -> T {
x.exp()
}
}
pub struct NaturalLogarithm<T> {
_type: PhantomData<T>,
}
impl<T> UnaryFunctionDerivative<T> for NaturalLogarithm<T>
where
T: Real + Primitive,
for<'t> &'t T: RealRef<T>,
{
fn function(x: T) -> T {
x.ln()
}
fn d_function_dx(x: T) -> T {
T::one() / x
}
}
pub struct SquareRoot<T> {
_type: PhantomData<T>,
}
impl<T> UnaryFunctionDerivative<T> for SquareRoot<T>
where
T: Real + Primitive,
for<'t> &'t T: RealRef<T>,
{
fn function(x: T) -> T {
x.sqrt()
}
fn d_function_dx(x: T) -> T {
T::one() / ((T::one() + T::one()) * x.sqrt())
}
}