use crate::backend;
use super::Differentiable;
use super::gemm::GemmTask;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MapOperation {
Exp,
Ln,
Sqrt,
Tanh,
}
pub trait Elementary: Differentiable {
fn exp(&self) -> Self;
fn ln(&self) -> Self;
fn sqrt(&self) -> Self;
fn tanh(&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(operation: MapOperation, elements: &[Self]) -> Option<Vec<Self>>
where
Self: Sized,
{
let _ = (operation, elements);
None
}
}
impl Elementary for f32 {
fn exp(&self) -> Self {
f32::exp(*self)
}
fn ln(&self) -> Self {
f32::ln(*self)
}
fn sqrt(&self) -> Self {
f32::sqrt(*self)
}
fn tanh(&self) -> Self {
f32::tanh(*self)
}
fn powf(&self, exponent: Self) -> Self {
f32::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>> {
backend::gemm_f32(task)
}
fn map(operation: MapOperation, elements: &[Self]) -> Option<Vec<Self>> {
backend::map_f32(operation, elements)
}
}
impl Elementary for f64 {
fn exp(&self) -> Self {
f64::exp(*self)
}
fn ln(&self) -> Self {
f64::ln(*self)
}
fn sqrt(&self) -> Self {
f64::sqrt(*self)
}
fn tanh(&self) -> Self {
f64::tanh(*self)
}
fn powf(&self, exponent: Self) -> Self {
f64::powf(*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>> {
backend::gemm_f64(task)
}
fn map(operation: MapOperation, elements: &[Self]) -> Option<Vec<Self>> {
backend::map_f64(operation, elements)
}
}