use crate::dtype::DType;
use crate::error::Result;
use crate::layout::Layout;
use crate::shape::Shape;
use std::fmt;
pub trait BackendDevice: Clone + fmt::Debug + Send + Sync + 'static {
fn name(&self) -> String;
}
pub trait BackendStorage: Clone + Send + Sync + 'static {
fn dtype(&self) -> DType;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Neg,
Abs,
Exp,
Log,
Sqrt,
Relu,
Sigmoid,
Tanh,
Gelu,
Silu,
Sin,
Cos,
Square,
Floor,
Ceil,
Round,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReduceOp {
Sum,
Mean,
Max,
Min,
ArgMax,
ArgMin,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CmpOp {
Eq,
Ne,
Gt,
Ge,
Lt,
Le,
}
pub trait Backend: Clone + Send + Sync + fmt::Debug + 'static {
type Device: BackendDevice;
type Storage: BackendStorage;
fn zeros(shape: &Shape, dtype: DType, device: &Self::Device) -> Result<Self::Storage>;
fn ones(shape: &Shape, dtype: DType, device: &Self::Device) -> Result<Self::Storage>;
fn full(shape: &Shape, val: f64, dtype: DType, device: &Self::Device) -> Result<Self::Storage>;
fn from_f64_slice(data: &[f64], dtype: DType, device: &Self::Device) -> Result<Self::Storage>;
fn rand_uniform(shape: &Shape, dtype: DType, device: &Self::Device) -> Result<Self::Storage>;
fn rand_normal(shape: &Shape, dtype: DType, device: &Self::Device) -> Result<Self::Storage>;
fn binary_op(
op: BinaryOp,
lhs: &Self::Storage,
lhs_layout: &Layout,
rhs: &Self::Storage,
rhs_layout: &Layout,
) -> Result<Self::Storage>;
fn unary_op(op: UnaryOp, input: &Self::Storage, layout: &Layout) -> Result<Self::Storage>;
fn reduce_op(
op: ReduceOp,
input: &Self::Storage,
layout: &Layout,
dims: &[usize],
keep_dim: bool,
) -> Result<Self::Storage>;
fn matmul(
lhs: &Self::Storage,
lhs_layout: &Layout,
rhs: &Self::Storage,
rhs_layout: &Layout,
) -> Result<Self::Storage>;
fn to_contiguous(input: &Self::Storage, layout: &Layout) -> Result<Self::Storage>;
fn to_f64_vec(input: &Self::Storage, layout: &Layout) -> Result<Vec<f64>>;
fn cmp_op(
op: CmpOp,
lhs: &Self::Storage,
lhs_layout: &Layout,
rhs: &Self::Storage,
rhs_layout: &Layout,
) -> Result<Self::Storage>;
fn affine(input: &Self::Storage, layout: &Layout, mul: f64, add: f64) -> Result<Self::Storage>;
fn index_select(
input: &Self::Storage,
input_layout: &Layout,
indices: &Self::Storage,
indices_layout: &Layout,
dim: usize,
) -> Result<Self::Storage>;
fn powf(input: &Self::Storage, layout: &Layout, exponent: f64) -> Result<Self::Storage>;
fn clamp(input: &Self::Storage, layout: &Layout, min: f64, max: f64) -> Result<Self::Storage>;
fn where_cond(
mask: &Self::Storage,
mask_layout: &Layout,
on_true: &Self::Storage,
on_true_layout: &Layout,
on_false: &Self::Storage,
on_false_layout: &Layout,
) -> Result<Self::Storage>;
fn gather(
input: &Self::Storage,
input_layout: &Layout,
index: &Self::Storage,
index_layout: &Layout,
dim: usize,
) -> Result<Self::Storage>;
fn cat(
inputs: &[(&Self::Storage, &Layout)],
out_shape: &Shape,
dim: usize,
) -> Result<Self::Storage>;
fn cast(
input: &Self::Storage,
layout: &Layout,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage> {
let data = Self::to_f64_vec(input, layout)?;
Self::from_f64_slice(&data, dtype, device)
}
}