radient 0.3.0

Radient is a Rust library designed for automatic differentiation. It leverages the power of computational graphs to perform forward and backward passes for gradient calculations.
Documentation
use peroxide::fuga::{Matrix, matrix, FPMatrix};
use crate::core::Expr;

pub trait Matrizable {
    fn hadamard(&self, rhs: &Self) -> Self;
    fn transpose(&self) -> Self;
    fn ones_like(&self) -> Self;

    fn zeros_like(&self) -> Self;
}

impl Matrizable for f64 {
    fn hadamard(&self, rhs: &Self) -> Self {
        self * rhs
    }

    fn transpose(&self) -> Self {
        *self
    }

    fn ones_like(&self) -> Self {
        1.0
    }

    fn zeros_like(&self) -> Self {
        0.0
    }
}

impl Matrizable for Matrix {
    fn hadamard(&self, rhs: &Self) -> Self {
        self.zip_with(|x, y| x * y, rhs)
    }

    fn transpose(&self) -> Self {
        self.transpose()
    }

    fn ones_like(&self) -> Self {
        matrix(vec![1.0; self.row * self.col], self.row, self.col, self.shape)
    }

    fn zeros_like(&self) -> Self {
        matrix(vec![0.0; self.row * self.col], self.row, self.col, self.shape)
    }
}

pub trait ActivationFunction {
    fn sigmoid(&self) -> Self;
    fn relu(&self) -> Self;
    fn heaviside_zero(&self) -> Self;
}

impl ActivationFunction for f64 {
    fn sigmoid(&self) -> Self {
        1.0 / (1.0 + (-self).exp())
    }

    fn relu(&self) -> Self {
        self.max(0.0)
    }

    fn heaviside_zero(&self) -> Self {
        if self.is_sign_positive() {
            1.0
        } else {
            0.0
        }
    }
}

impl ActivationFunction for Expr {
    fn sigmoid(&self) -> Self {
        Expr::Sigmoid(Box::new(self.clone()))
    }

    fn relu(&self) -> Self {
        Expr::ReLU(Box::new(self.clone()))
    }

    fn heaviside_zero(&self) -> Self {
        unimplemented!()
    }
}

impl ActivationFunction for Matrix {
    fn sigmoid(&self) -> Self {
        let data = self.data.iter().map(|x| x.sigmoid()).collect();
        matrix(data, self.row, self.col, self.shape)
    }

    fn relu(&self) -> Self {
        let data = self.data.iter().map(|x| x.relu()).collect();
        matrix(data, self.row, self.col, self.shape)
    }

    fn heaviside_zero(&self) -> Self {
        let data = self.data.iter().map(|x| x.heaviside_zero()).collect();
        matrix(data, self.row, self.col, self.shape)
    }
}