Trait Backend
pub trait Backend:
Clone
+ Send
+ Sync
+ Debug
+ 'static {
type Device: BackendDevice;
type Storage: BackendStorage;
Show 21 methods
// Required methods
fn zeros(
shape: &Shape,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>;
fn ones(
shape: &Shape,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>;
fn full(
shape: &Shape,
val: f64,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>;
fn from_f64_slice(
data: &[f64],
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>;
fn rand_uniform(
shape: &Shape,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>;
fn rand_normal(
shape: &Shape,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>;
fn binary_op(
op: BinaryOp,
lhs: &Self::Storage,
lhs_layout: &Layout,
rhs: &Self::Storage,
rhs_layout: &Layout,
) -> Result<Self::Storage, Error>;
fn unary_op(
op: UnaryOp,
input: &Self::Storage,
layout: &Layout,
) -> Result<Self::Storage, Error>;
fn reduce_op(
op: ReduceOp,
input: &Self::Storage,
layout: &Layout,
dims: &[usize],
keep_dim: bool,
) -> Result<Self::Storage, Error>;
fn matmul(
lhs: &Self::Storage,
lhs_layout: &Layout,
rhs: &Self::Storage,
rhs_layout: &Layout,
) -> Result<Self::Storage, Error>;
fn to_contiguous(
input: &Self::Storage,
layout: &Layout,
) -> Result<Self::Storage, Error>;
fn to_f64_vec(
input: &Self::Storage,
layout: &Layout,
) -> Result<Vec<f64>, Error>;
fn cmp_op(
op: CmpOp,
lhs: &Self::Storage,
lhs_layout: &Layout,
rhs: &Self::Storage,
rhs_layout: &Layout,
) -> Result<Self::Storage, Error>;
fn affine(
input: &Self::Storage,
layout: &Layout,
mul: f64,
add: f64,
) -> Result<Self::Storage, Error>;
fn index_select(
input: &Self::Storage,
input_layout: &Layout,
indices: &Self::Storage,
indices_layout: &Layout,
dim: usize,
) -> Result<Self::Storage, Error>;
fn powf(
input: &Self::Storage,
layout: &Layout,
exponent: f64,
) -> Result<Self::Storage, Error>;
fn clamp(
input: &Self::Storage,
layout: &Layout,
min: f64,
max: f64,
) -> Result<Self::Storage, Error>;
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, Error>;
fn gather(
input: &Self::Storage,
input_layout: &Layout,
index: &Self::Storage,
index_layout: &Layout,
dim: usize,
) -> Result<Self::Storage, Error>;
fn cat(
inputs: &[(&Self::Storage, &Layout)],
out_shape: &Shape,
dim: usize,
) -> Result<Self::Storage, Error>;
// Provided method
fn cast(
input: &Self::Storage,
layout: &Layout,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error> { ... }
}Expand description
Re-export core types. The main Backend trait. Implementing this for a struct (e.g., CpuBackend) makes that struct a complete compute backend for Shrew.
All operations take storage + layout (which encodes shape/strides) and return new storage (immutable semantics — no in-place mutation by default).
Required Associated Types§
type Device: BackendDevice
type Device: BackendDevice
The device type for this backend.
type Storage: BackendStorage
type Storage: BackendStorage
The storage type for this backend.
Required Methods§
fn zeros(
shape: &Shape,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>
fn zeros( shape: &Shape, dtype: DType, device: &Self::Device, ) -> Result<Self::Storage, Error>
Allocate storage filled with zeros.
fn ones(
shape: &Shape,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>
fn ones( shape: &Shape, dtype: DType, device: &Self::Device, ) -> Result<Self::Storage, Error>
Allocate storage filled with ones.
fn full(
shape: &Shape,
val: f64,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>
fn full( shape: &Shape, val: f64, dtype: DType, device: &Self::Device, ) -> Result<Self::Storage, Error>
Allocate storage filled with a constant value.
fn from_f64_slice(
data: &[f64],
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>
fn from_f64_slice( data: &[f64], dtype: DType, device: &Self::Device, ) -> Result<Self::Storage, Error>
Create storage from a flat f64 slice, converting to the target dtype.
fn rand_uniform(
shape: &Shape,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>
fn rand_uniform( shape: &Shape, dtype: DType, device: &Self::Device, ) -> Result<Self::Storage, Error>
Create storage with random uniform values in [0, 1).
fn rand_normal(
shape: &Shape,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>
fn rand_normal( shape: &Shape, dtype: DType, device: &Self::Device, ) -> Result<Self::Storage, Error>
Create storage with random normal values (mean=0, std=1).
fn binary_op(
op: BinaryOp,
lhs: &Self::Storage,
lhs_layout: &Layout,
rhs: &Self::Storage,
rhs_layout: &Layout,
) -> Result<Self::Storage, Error>
fn binary_op( op: BinaryOp, lhs: &Self::Storage, lhs_layout: &Layout, rhs: &Self::Storage, rhs_layout: &Layout, ) -> Result<Self::Storage, Error>
Apply a binary op element-wise: result[i] = op(lhs[i], rhs[i]). The layouts handle broadcasting and non-contiguous access.
fn unary_op(
op: UnaryOp,
input: &Self::Storage,
layout: &Layout,
) -> Result<Self::Storage, Error>
fn unary_op( op: UnaryOp, input: &Self::Storage, layout: &Layout, ) -> Result<Self::Storage, Error>
Apply a unary op element-wise: result[i] = op(input[i]).
fn reduce_op(
op: ReduceOp,
input: &Self::Storage,
layout: &Layout,
dims: &[usize],
keep_dim: bool,
) -> Result<Self::Storage, Error>
fn reduce_op( op: ReduceOp, input: &Self::Storage, layout: &Layout, dims: &[usize], keep_dim: bool, ) -> Result<Self::Storage, Error>
Reduce along specific dimensions.
If dims is empty, reduce over all elements.
fn matmul(
lhs: &Self::Storage,
lhs_layout: &Layout,
rhs: &Self::Storage,
rhs_layout: &Layout,
) -> Result<Self::Storage, Error>
fn matmul( lhs: &Self::Storage, lhs_layout: &Layout, rhs: &Self::Storage, rhs_layout: &Layout, ) -> Result<Self::Storage, Error>
General matrix multiply: C = A @ B. Supports batched matmul for tensors with rank > 2.
fn to_contiguous(
input: &Self::Storage,
layout: &Layout,
) -> Result<Self::Storage, Error>
fn to_contiguous( input: &Self::Storage, layout: &Layout, ) -> Result<Self::Storage, Error>
Make a contiguous copy of the storage following the given layout. If the layout is already contiguous, this may just clone the storage.
fn to_f64_vec(input: &Self::Storage, layout: &Layout) -> Result<Vec<f64>, Error>
fn to_f64_vec(input: &Self::Storage, layout: &Layout) -> Result<Vec<f64>, Error>
Copy data from this storage to a Vec
fn cmp_op(
op: CmpOp,
lhs: &Self::Storage,
lhs_layout: &Layout,
rhs: &Self::Storage,
rhs_layout: &Layout,
) -> Result<Self::Storage, Error>
fn cmp_op( op: CmpOp, lhs: &Self::Storage, lhs_layout: &Layout, rhs: &Self::Storage, rhs_layout: &Layout, ) -> Result<Self::Storage, Error>
Element-wise comparison, returns a u8 storage (0 or 1).
fn affine(
input: &Self::Storage,
layout: &Layout,
mul: f64,
add: f64,
) -> Result<Self::Storage, Error>
fn affine( input: &Self::Storage, layout: &Layout, mul: f64, add: f64, ) -> Result<Self::Storage, Error>
Affine transform: result = input * mul + add. Used for normalization and other fused operations.
fn index_select(
input: &Self::Storage,
input_layout: &Layout,
indices: &Self::Storage,
indices_layout: &Layout,
dim: usize,
) -> Result<Self::Storage, Error>
fn index_select( input: &Self::Storage, input_layout: &Layout, indices: &Self::Storage, indices_layout: &Layout, dim: usize, ) -> Result<Self::Storage, Error>
Gather elements along a dimension using index tensor.
fn powf(
input: &Self::Storage,
layout: &Layout,
exponent: f64,
) -> Result<Self::Storage, Error>
fn powf( input: &Self::Storage, layout: &Layout, exponent: f64, ) -> Result<Self::Storage, Error>
Element-wise power: result[i] = input[i] ^ exponent.
fn clamp(
input: &Self::Storage,
layout: &Layout,
min: f64,
max: f64,
) -> Result<Self::Storage, Error>
fn clamp( input: &Self::Storage, layout: &Layout, min: f64, max: f64, ) -> Result<Self::Storage, Error>
Element-wise clamp: result[i] = clamp(input[i], min, max).
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, Error>
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, Error>
Element-wise conditional: result[i] = if mask[i] != 0 { on_true[i] } else { on_false[i] }.
fn gather(
input: &Self::Storage,
input_layout: &Layout,
index: &Self::Storage,
index_layout: &Layout,
dim: usize,
) -> Result<Self::Storage, Error>
fn gather( input: &Self::Storage, input_layout: &Layout, index: &Self::Storage, index_layout: &Layout, dim: usize, ) -> Result<Self::Storage, Error>
Gather elements along dim using index tensor.
output[i][j][k] = input[index[i][j][k]][j][k] (when dim=0)
output[i][j][k] = input[i][index[i][j][k]][k] (when dim=1)
etc.
index must have the same number of dimensions as input.
fn cat(
inputs: &[(&Self::Storage, &Layout)],
out_shape: &Shape,
dim: usize,
) -> Result<Self::Storage, Error>
fn cat( inputs: &[(&Self::Storage, &Layout)], out_shape: &Shape, dim: usize, ) -> Result<Self::Storage, Error>
Concatenate multiple storages along dim into a single contiguous storage.
Each entry is (storage, layout) so non-contiguous inputs are handled correctly.
out_shape is the pre-validated output shape.
Provided Methods§
fn cast(
input: &Self::Storage,
layout: &Layout,
dtype: DType,
device: &Self::Device,
) -> Result<Self::Storage, Error>
fn cast( input: &Self::Storage, layout: &Layout, dtype: DType, device: &Self::Device, ) -> Result<Self::Storage, Error>
Cast storage to a different dtype on-device (no host round-trip).
The default implementation falls back to to_f64_vec + from_f64_slice,
which involves a host round-trip. Backends should override this with
a native on-device kernel when possible.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.