pub struct Tensor<B: Backend> { /* private fields */ }Expand description
An n-dimensional array of numbers on a specific backend.
Tensors are the fundamental data type in Shrew. All neural network operations accept and return tensors.
§Type Parameter
B: Backend— the compute backend (e.g.,CpuBackend,CudaBackend)
§Example
use shrew_core::Tensor;
use shrew_cpu::CpuBackend;
let a = Tensor::<CpuBackend>::from_slice(&[1.0, 2.0, 3.0, 4.0], (2, 2))?;
let b = Tensor::<CpuBackend>::ones((2, 2), DType::F32, &CpuDevice)?;
let c = a.add(&b)?;Implementations§
Source§impl<B: Backend> Tensor<B>
impl<B: Backend> Tensor<B>
Sourcepub fn elem_count(&self) -> usize
pub fn elem_count(&self) -> usize
Total number of elements.
Sourcepub fn is_contiguous(&self) -> bool
pub fn is_contiguous(&self) -> bool
Whether this tensor is contiguous in memory.
Sourcepub fn is_variable(&self) -> bool
pub fn is_variable(&self) -> bool
Whether this tensor tracks gradients.
Sourcepub fn storage(&self) -> RwLockReadGuard<'_, B::Storage>
pub fn storage(&self) -> RwLockReadGuard<'_, B::Storage>
Access the underlying storage (read lock).
Sourcepub fn update_data_inplace(&self, new_data: &[f64]) -> Result<()>
pub fn update_data_inplace(&self, new_data: &[f64]) -> Result<()>
Update the underlying storage data in place.
This writes new_data directly into the existing Arc<RwLock<Storage>>,
so any other tensor sharing this storage (e.g., a clone held by a Module)
will also see the updated values.
This is the mechanism that makes optimizer parameter updates visible to model layers without needing to re-assign parameters.
§Safety (logical)
The new data must have the same number of elements and dtype as the current storage. The shape is not changed.
Sourcepub fn zeros(
shape: impl Into<Shape>,
dtype: DType,
device: &B::Device,
) -> Result<Self>
pub fn zeros( shape: impl Into<Shape>, dtype: DType, device: &B::Device, ) -> Result<Self>
Create a tensor filled with zeros.
Sourcepub fn ones(
shape: impl Into<Shape>,
dtype: DType,
device: &B::Device,
) -> Result<Self>
pub fn ones( shape: impl Into<Shape>, dtype: DType, device: &B::Device, ) -> Result<Self>
Create a tensor filled with ones.
Sourcepub fn full(
shape: impl Into<Shape>,
val: f64,
dtype: DType,
device: &B::Device,
) -> Result<Self>
pub fn full( shape: impl Into<Shape>, val: f64, dtype: DType, device: &B::Device, ) -> Result<Self>
Create a tensor filled with a constant value.
Sourcepub fn from_f64_slice(
data: &[f64],
shape: impl Into<Shape>,
dtype: DType,
device: &B::Device,
) -> Result<Self>
pub fn from_f64_slice( data: &[f64], shape: impl Into<Shape>, dtype: DType, device: &B::Device, ) -> Result<Self>
Create a tensor from a flat slice of f64 values. The data is converted to the specified dtype.
Sourcepub fn rand(
shape: impl Into<Shape>,
dtype: DType,
device: &B::Device,
) -> Result<Self>
pub fn rand( shape: impl Into<Shape>, dtype: DType, device: &B::Device, ) -> Result<Self>
Create a tensor with random uniform values in [0, 1).
Sourcepub fn randn(
shape: impl Into<Shape>,
dtype: DType,
device: &B::Device,
) -> Result<Self>
pub fn randn( shape: impl Into<Shape>, dtype: DType, device: &B::Device, ) -> Result<Self>
Create a tensor with random normal values (mean=0, std=1).
Sourcepub fn linspace(
start: f64,
end: f64,
steps: usize,
dtype: DType,
device: &B::Device,
) -> Result<Self>
pub fn linspace( start: f64, end: f64, steps: usize, dtype: DType, device: &B::Device, ) -> Result<Self>
Create a 1-D tensor with steps evenly spaced values from start to end (inclusive).
let t = Tensor::linspace(0.0, 1.0, 5, DType::F64, &dev)?;
// => [0.0, 0.25, 0.5, 0.75, 1.0]Sourcepub fn eye(n: usize, dtype: DType, device: &B::Device) -> Result<Self>
pub fn eye(n: usize, dtype: DType, device: &B::Device) -> Result<Self>
Create an identity matrix of size n × n.
let I = Tensor::eye(3, DType::F64, &dev)?;
// [[1, 0, 0],
// [0, 1, 0],
// [0, 0, 1]]Sourcepub fn zeros_like(other: &Self) -> Result<Self>
pub fn zeros_like(other: &Self) -> Result<Self>
Create a tensor of zeros with the same shape, dtype, and device as other.
Sourcepub fn ones_like(other: &Self) -> Result<Self>
pub fn ones_like(other: &Self) -> Result<Self>
Create a tensor of ones with the same shape, dtype, and device as other.
Sourcepub fn full_like(other: &Self, val: f64) -> Result<Self>
pub fn full_like(other: &Self, val: f64) -> Result<Self>
Create a tensor filled with val, with the same shape, dtype, and device as other.
Sourcepub fn set_variable(self) -> Self
pub fn set_variable(self) -> Self
Mark this tensor as a variable (trainable parameter). Variables accumulate gradients during backward().
Sourcepub fn transpose(&self, dim0: usize, dim1: usize) -> Result<Self>
pub fn transpose(&self, dim0: usize, dim1: usize) -> Result<Self>
Transpose two dimensions (no data copy).
Sourcepub fn narrow(&self, dim: usize, start: usize, len: usize) -> Result<Self>
pub fn narrow(&self, dim: usize, start: usize, len: usize) -> Result<Self>
Narrow (slice) along a dimension.
Sourcepub fn reshape(&self, new_shape: impl Into<Shape>) -> Result<Self>
pub fn reshape(&self, new_shape: impl Into<Shape>) -> Result<Self>
Reshape to a new shape. The new shape must have the same total elements. If the tensor is not contiguous, it will be made contiguous first.
Sourcepub fn contiguous(&self) -> Result<Self>
pub fn contiguous(&self) -> Result<Self>
Ensure the tensor is contiguous in memory. If already contiguous, returns a clone (cheap Arc copy). Otherwise, copies the data into a new contiguous storage.
Sourcepub fn unsqueeze(&self, dim: usize) -> Result<Self>
pub fn unsqueeze(&self, dim: usize) -> Result<Self>
Add a dimension of size 1 at the given position. unsqueeze(0) on [3, 4] → [1, 3, 4] unsqueeze(2) on [3, 4] → [3, 4, 1]
Sourcepub fn squeeze_all(&self) -> Self
pub fn squeeze_all(&self) -> Self
Remove dimensions of size 1. squeeze on [1, 3, 1, 4] → [3, 4]
Sourcepub fn squeeze(&self, dim: usize) -> Result<Self>
pub fn squeeze(&self, dim: usize) -> Result<Self>
Remove a specific dimension of size 1.
squeeze(1) on [3, 1, 4] → [3, 4]
Returns an error if the specified dimension is not size 1.
Sourcepub fn permute(&self, dims: &[usize]) -> Result<Self>
pub fn permute(&self, dims: &[usize]) -> Result<Self>
Permute the dimensions of this tensor.
permute(&[2, 0, 1]) on [A, B, C] → [C, A, B]
This is a generalization of transpose to arbitrary dimension orderings. No data copy — just changes strides.
Sourcepub fn cumsum(&self, dim: usize) -> Result<Self>
pub fn cumsum(&self, dim: usize) -> Result<Self>
Cumulative sum along dimension dim.
// [1, 2, 3] → [1, 3, 6]
let y = x.cumsum(0)?;Sourcepub fn sort(&self, dim: usize, descending: bool) -> Result<(Self, Self)>
pub fn sort(&self, dim: usize, descending: bool) -> Result<(Self, Self)>
Sort along a dimension. Returns (sorted_values, sorted_indices).
let (vals, idxs) = x.sort(0, false)?; // ascending along dim 0Sourcepub fn argsort(&self, dim: usize, descending: bool) -> Result<Self>
pub fn argsort(&self, dim: usize, descending: bool) -> Result<Self>
Argsort: returns indices that would sort the tensor along dim.
let indices = x.argsort(0, false)?; // ascendingSourcepub fn eq(&self, rhs: &Self) -> Result<Self>
pub fn eq(&self, rhs: &Self) -> Result<Self>
Element-wise equal: self == rhs. Returns a U8 tensor (0 or 1).
Sourcepub fn ne(&self, rhs: &Self) -> Result<Self>
pub fn ne(&self, rhs: &Self) -> Result<Self>
Element-wise not-equal: self != rhs. Returns a U8 tensor (0 or 1).
Sourcepub fn gt(&self, rhs: &Self) -> Result<Self>
pub fn gt(&self, rhs: &Self) -> Result<Self>
Element-wise greater-than: self > rhs. Returns a U8 tensor (0 or 1).
Sourcepub fn ge(&self, rhs: &Self) -> Result<Self>
pub fn ge(&self, rhs: &Self) -> Result<Self>
Element-wise greater-or-equal: self >= rhs. Returns a U8 tensor (0 or 1).
Sourcepub fn lt(&self, rhs: &Self) -> Result<Self>
pub fn lt(&self, rhs: &Self) -> Result<Self>
Element-wise less-than: self < rhs. Returns a U8 tensor (0 or 1).
Sourcepub fn le(&self, rhs: &Self) -> Result<Self>
pub fn le(&self, rhs: &Self) -> Result<Self>
Element-wise less-or-equal: self <= rhs. Returns a U8 tensor (0 or 1).
Sourcepub fn where_cond(mask: &Self, on_true: &Self, on_false: &Self) -> Result<Self>
pub fn where_cond(mask: &Self, on_true: &Self, on_false: &Self) -> Result<Self>
Conditional select: result[i] = if mask[i] != 0 { on_true[i] } else { on_false[i] }.
mask is typically a U8 tensor from comparison ops.
on_true and on_false must have the same shape and dtype.
Sourcepub fn gather(&self, dim: usize, index: &Self) -> Result<Self>
pub fn gather(&self, dim: usize, index: &Self) -> Result<Self>
Gather elements along dim using an index tensor.
output[i][j][k] = input[index[i][j][k]][j][k] (when dim=0)
The index tensor must have the same number of dimensions as self. The output has the same shape as the index tensor.
Sourcepub fn masked_fill(&self, mask: &Self, value: f64) -> Result<Self>
pub fn masked_fill(&self, mask: &Self, value: f64) -> Result<Self>
Fill elements where mask != 0 with value, keeping other elements.
result[i] = if mask[i] != 0 { value } else { self[i] }
This is implemented via where_cond so autograd is automatic.
Sourcepub fn pad(&self, padding: &[[usize; 2]], value: f64) -> Result<Self>
pub fn pad(&self, padding: &[[usize; 2]], value: f64) -> Result<Self>
Pad the last N dimensions with constant value.
padding is a list of [before, after] pairs, one per dimension,
applied to the last dimensions of the tensor.
Example: pad(&[[1, 1], [2, 2]], 0.0) pads the last 2 dims.
Sourcepub fn topk(&self, k: usize, dim: usize) -> Result<(Self, Vec<usize>)>
pub fn topk(&self, k: usize, dim: usize) -> Result<(Self, Vec<usize>)>
Return the k largest elements along dim.
Returns (values, indices) where both have the same shape as self
except dimension dim has size k.
Non-differentiable (returns detached values).
Sourcepub fn mean(&self, dim: usize, keep_dim: bool) -> Result<Self>
pub fn mean(&self, dim: usize, keep_dim: bool) -> Result<Self>
Mean along a specific dimension.
Sourcepub fn argmax(&self, dim: usize, keep_dim: bool) -> Result<Self>
pub fn argmax(&self, dim: usize, keep_dim: bool) -> Result<Self>
ArgMax along a specific dimension (returns i64 indices).
Sourcepub fn argmin(&self, dim: usize, keep_dim: bool) -> Result<Self>
pub fn argmin(&self, dim: usize, keep_dim: bool) -> Result<Self>
ArgMin along a specific dimension (returns i64 indices).
Sourcepub fn softmax(&self, dim: usize) -> Result<Self>
pub fn softmax(&self, dim: usize) -> Result<Self>
Softmax along a dimension: softmax(x)_i = exp(x_i) / sum(exp(x_j))
Uses the numerically stable trick: subtract max before exp. This is built from existing differentiable ops (exp, sum, div, sub) so gradients flow through automatically.
Sourcepub fn log_softmax(&self, dim: usize) -> Result<Self>
pub fn log_softmax(&self, dim: usize) -> Result<Self>
Log-softmax along a dimension: log(softmax(x)) but numerically stable.
log_softmax(x)_i = x_i - max(x) - log(sum(exp(x - max(x))))
Sourcepub fn var(&self, dim: usize, keep_dim: bool) -> Result<Self>
pub fn var(&self, dim: usize, keep_dim: bool) -> Result<Self>
Variance along a dimension: var(x) = mean((x - mean(x))²)
Sourcepub fn cat(tensors: &[Self], dim: usize) -> Result<Self>
pub fn cat(tensors: &[Self], dim: usize) -> Result<Self>
Concatenate tensors along a dimension.
All tensors must have the same shape except in the concatenation dimension. This creates a new tensor by copying data from all inputs.
Sourcepub fn chunk(&self, n: usize, dim: usize) -> Result<Vec<Self>>
pub fn chunk(&self, n: usize, dim: usize) -> Result<Vec<Self>>
Split a tensor into n equal chunks along a dimension.
If the dimension size is not evenly divisible, the last chunk is smaller.
Sourcepub fn expand(&self, target_shape: impl Into<Shape>) -> Result<Self>
pub fn expand(&self, target_shape: impl Into<Shape>) -> Result<Self>
Expand a tensor to a larger shape by repeating data along size-1 dims. Only dims that are currently size 1 can be expanded. A size of -1 (usize::MAX) means don’t change that dim.
Sourcepub fn stack(tensors: &[Self], dim: usize) -> Result<Self>
pub fn stack(tensors: &[Self], dim: usize) -> Result<Self>
Stack tensors along a new dimension.
All tensors must have the same shape. Inserts a new dimension at dim.
stack([a, b], dim=0) where a,b are shape [2,3] → [2, 2, 3].
Sourcepub fn arange(n: usize, dtype: DType, device: &B::Device) -> Result<Self>
pub fn arange(n: usize, dtype: DType, device: &B::Device) -> Result<Self>
Create a 1-D tensor with values [0, 1, …, n-1].
Sourcepub fn arange_step(
start: f64,
end: f64,
step: f64,
dtype: DType,
device: &B::Device,
) -> Result<Self>
pub fn arange_step( start: f64, end: f64, step: f64, dtype: DType, device: &B::Device, ) -> Result<Self>
Create a 1-D tensor with values [start, start+step, …, <end).
Sourcepub fn triu(
n: usize,
m: usize,
diagonal: i64,
dtype: DType,
device: &B::Device,
) -> Result<Self>
pub fn triu( n: usize, m: usize, diagonal: i64, dtype: DType, device: &B::Device, ) -> Result<Self>
Upper triangular mask: returns a 2-D tensor of shape [n, m] where
elements on and above the diagonal-th diagonal are 1.0, rest 0.0.
diagonal = 0 → main diagonal. diagonal > 0 → above. diagonal < 0 → below.
Sourcepub fn tril(
n: usize,
m: usize,
diagonal: i64,
dtype: DType,
device: &B::Device,
) -> Result<Self>
pub fn tril( n: usize, m: usize, diagonal: i64, dtype: DType, device: &B::Device, ) -> Result<Self>
Lower triangular mask: returns a 2-D tensor of shape [n, m] where
elements on and below the diagonal-th diagonal are 1.0, rest 0.0.
Sourcepub fn matmul(&self, rhs: &Self) -> Result<Self>
pub fn matmul(&self, rhs: &Self) -> Result<Self>
Matrix multiplication: self @ rhs.
- [m, k] @ [k, n] → [m, n]
- Batched: [b, m, k] @ [b, k, n] → [b, m, n]
Sourcepub fn conv2d(
&self,
weight: &Self,
bias: Option<&Self>,
stride: [usize; 2],
padding: [usize; 2],
) -> Result<Self>
pub fn conv2d( &self, weight: &Self, bias: Option<&Self>, stride: [usize; 2], padding: [usize; 2], ) -> Result<Self>
2D convolution: applies convolution filters to a 4D input tensor.
self(input):[N, C_in, H, W]weight:[C_out, C_in, kH, kW]bias: optional[C_out]stride:[sH, sW]padding:[pH, pW]
Returns tensor of shape [N, C_out, H_out, W_out] where
H_out = (H + 2*pH - kH) / sH + 1.
Sourcepub fn max_pool2d(
&self,
kernel_size: [usize; 2],
stride: [usize; 2],
padding: [usize; 2],
) -> Result<Self>
pub fn max_pool2d( &self, kernel_size: [usize; 2], stride: [usize; 2], padding: [usize; 2], ) -> Result<Self>
2D max pooling on a 4D input tensor [N, C, H, W].
Returns (output, indices) where indices stores argmax positions
(flat indices into the input) for backward.
Sourcepub fn avg_pool2d(
&self,
kernel_size: [usize; 2],
stride: [usize; 2],
padding: [usize; 2],
) -> Result<Self>
pub fn avg_pool2d( &self, kernel_size: [usize; 2], stride: [usize; 2], padding: [usize; 2], ) -> Result<Self>
Apply 2D average pooling to a 4D tensor [N, C, H, W].
Sourcepub fn conv1d(
&self,
weight: &Self,
bias: Option<&Self>,
stride: usize,
padding: usize,
) -> Result<Self>
pub fn conv1d( &self, weight: &Self, bias: Option<&Self>, stride: usize, padding: usize, ) -> Result<Self>
Apply 1D convolution to a 3D tensor [N, C_in, L]. weight: [C_out, C_in, K]
Sourcepub fn affine(&self, mul: f64, add: f64) -> Result<Self>
pub fn affine(&self, mul: f64, add: f64) -> Result<Self>
Affine transform: result[i] = self[i] * mul + add. Useful for normalization and scaling.
Sourcepub fn to_f64_vec(&self) -> Result<Vec<f64>>
pub fn to_f64_vec(&self) -> Result<Vec<f64>>
Extract all elements as a flat Vec
Sourcepub fn to_scalar_f64(&self) -> Result<f64>
pub fn to_scalar_f64(&self) -> Result<f64>
Extract a scalar value (tensor must have exactly 1 element).
Sourcepub fn to_dtype(&self, dtype: DType) -> Result<Self>
pub fn to_dtype(&self, dtype: DType) -> Result<Self>
Convert this tensor to a different dtype.
Returns a new tensor with the same shape but different element type. Uses the backend’s on-device cast when available, avoiding host round-trips. Records Op::ToDtype so gradients flow back through dtype conversions.
Sourcepub fn to_string_with_data(&self) -> Result<String>
pub fn to_string_with_data(&self) -> Result<String>
Display the tensor contents in a human-readable format.
Sourcepub fn backward(&self) -> Result<GradStore<B>>
pub fn backward(&self) -> Result<GradStore<B>>
Compute gradients via reverse-mode automatic differentiation.
This tensor must be a scalar (single element). Returns a GradStore containing gradients for all tensors in the computation graph.
§Example
let a = Tensor::from_f64_slice(&[2.0], 1, DType::F32, &dev)?.set_variable();
let b = Tensor::from_f64_slice(&[3.0], 1, DType::F32, &dev)?.set_variable();
let c = a.mul(&b)?;
let grads = c.backward()?;
// grad_a = b = 3.0, grad_b = a = 2.0Sourcepub fn detach(&self) -> Self
pub fn detach(&self) -> Self
Create a detached copy: same data but no gradient tracking. The new tensor has Op::None and a fresh TensorId.
Sourcepub fn freeze(&self) -> Self
pub fn freeze(&self) -> Self
Freeze this tensor: same data and id, but is_variable = false.
Frozen tensors do NOT accumulate gradients during backward().
This is the functional equivalent of PyTorch’s param.requires_grad_(False).
Sourcepub fn unfreeze(&self) -> Self
pub fn unfreeze(&self) -> Self
Unfreeze this tensor: same data and id, but is_variable = true.
This is the opposite of freeze().
Sourcepub fn index_select(&self, dim: usize, indices: &Self) -> Result<Self>
pub fn index_select(&self, dim: usize, indices: &Self) -> Result<Self>
Select entries along dim using the given 1-D index tensor.
The output has the same rank, with dim resized to indices.len().
Wraps the Backend::index_select kernel.
Sourcepub fn split(&self, split_size: usize, dim: usize) -> Result<Vec<Self>>
pub fn split(&self, split_size: usize, dim: usize) -> Result<Vec<Self>>
Split a tensor into chunks of split_size along dim.
The last chunk may be smaller if the dimension is not evenly divisible.
Sourcepub fn flatten(&self, start_dim: usize, end_dim: usize) -> Result<Self>
pub fn flatten(&self, start_dim: usize, end_dim: usize) -> Result<Self>
Flatten dimensions start_dim..=end_dim into a single dimension.
Negative-style indexing is not supported; both bounds are inclusive and zero-based.
Sourcepub fn std(&self, dim: usize, keep_dim: bool) -> Result<Self>
pub fn std(&self, dim: usize, keep_dim: bool) -> Result<Self>
Standard deviation along a dimension.
Computed as sqrt(var(x, dim)).
Sourcepub fn reciprocal(&self) -> Result<Self>
pub fn reciprocal(&self) -> Result<Self>
Element-wise reciprocal: 1 / x.
Sourcepub fn sign(&self) -> Result<Self>
pub fn sign(&self) -> Result<Self>
Element-wise sign: returns -1, 0, or +1.
Implemented via x / (|x| + eps) clamped to [-1, 1], with exact 0 for
inputs that are exactly zero.