use crate::backend::{MapTask, offered};
use super::Differentiable;
use super::gemm::GemmTask;
use super::normalized::{BatchNormTask, Normalized};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MapOperation {
Exp,
Ln,
Sqrt,
Tanh,
Sin,
Cos,
Log1p,
Expm1,
Erf,
ErfDerivative,
}
pub trait Elementary: Differentiable {
fn exp(&self) -> Self;
fn ln(&self) -> Self;
fn sqrt(&self) -> Self;
fn tanh(&self) -> Self;
fn sin(&self) -> Self;
fn cos(&self) -> Self;
fn log1p(&self) -> Self;
fn expm1(&self) -> Self;
fn erf(&self) -> Self;
fn erf_derivative(&self) -> Self;
fn powf(&self, exponent: Self) -> Self;
fn maximum(&self, other: &Self) -> Self;
fn step(&self, threshold: &Self) -> Self;
fn gemm(task: &GemmTask<'_, Self>) -> Option<Vec<Self>>
where
Self: Sized,
{
let _ = task;
None
}
fn map(task: &MapTask<'_, Self>) -> Option<Vec<Self>>
where
Self: Sized,
{
let _ = task;
None
}
fn batch_norm(task: &BatchNormTask<'_, Self>) -> Option<Normalized<Self>>
where
Self: Sized,
{
let _ = task;
None
}
}
impl Elementary for f32 {
fn exp(&self) -> Self {
libm::expf(*self)
}
fn ln(&self) -> Self {
libm::logf(*self)
}
fn sqrt(&self) -> Self {
f32::sqrt(*self)
}
fn tanh(&self) -> Self {
libm::tanhf(*self)
}
fn sin(&self) -> Self {
libm::sinf(*self)
}
fn cos(&self) -> Self {
libm::cosf(*self)
}
fn log1p(&self) -> Self {
libm::log1pf(*self)
}
fn expm1(&self) -> Self {
libm::expm1f(*self)
}
fn erf(&self) -> Self {
super::erf::erf(f64::from(*self)) as f32
}
fn erf_derivative(&self) -> Self {
super::erf::erf_derivative(f64::from(*self)) as f32
}
fn powf(&self, exponent: Self) -> Self {
libm::powf(*self, exponent)
}
fn maximum(&self, other: &Self) -> Self {
f32::max(*self, *other)
}
fn step(&self, threshold: &Self) -> Self {
if *self >= *threshold { 1.0 } else { 0.0 }
}
fn gemm(task: &GemmTask<'_, Self>) -> Option<Vec<Self>> {
offered(task)
}
fn map(task: &MapTask<'_, Self>) -> Option<Vec<Self>> {
offered(task)
}
fn batch_norm(task: &BatchNormTask<'_, Self>) -> Option<Normalized<Self>> {
offered(task)
}
}
impl Elementary for f64 {
fn exp(&self) -> Self {
libm::exp(*self)
}
fn ln(&self) -> Self {
libm::log(*self)
}
fn sqrt(&self) -> Self {
f64::sqrt(*self)
}
fn tanh(&self) -> Self {
libm::tanh(*self)
}
fn sin(&self) -> Self {
libm::sin(*self)
}
fn cos(&self) -> Self {
libm::cos(*self)
}
fn log1p(&self) -> Self {
libm::log1p(*self)
}
fn expm1(&self) -> Self {
libm::expm1(*self)
}
fn erf(&self) -> Self {
super::erf::erf(*self)
}
fn erf_derivative(&self) -> Self {
super::erf::erf_derivative(*self)
}
fn powf(&self, exponent: Self) -> Self {
libm::pow(*self, exponent)
}
fn maximum(&self, other: &Self) -> Self {
f64::max(*self, *other)
}
fn step(&self, threshold: &Self) -> Self {
if *self >= *threshold { 1.0 } else { 0.0 }
}
fn gemm(task: &GemmTask<'_, Self>) -> Option<Vec<Self>> {
offered(task)
}
fn map(task: &MapTask<'_, Self>) -> Option<Vec<Self>> {
offered(task)
}
fn batch_norm(task: &BatchNormTask<'_, Self>) -> Option<Normalized<Self>> {
offered(task)
}
}