Skip to main content

Tensor

Struct Tensor 

Source
pub struct Tensor<T = f32>
where T: TensorElement,
{ /* private fields */ }
Expand description

The main Tensor type for ToRSh

A tensor implementation with automatic memory mapping for large tensors and efficient views with reference counting

Implementations§

Source§

impl<T> Tensor<T>
where T: FloatElement + Copy,

Source

pub fn scalar(value: T) -> Result<Tensor<T>, TorshError>

Create a 0-dimensional tensor (scalar) from a single value

Source

pub fn as_ndarray( &self, ) -> Result<ArrayBase<OwnedRepr<T>, Dim<IxDynImpl>>, TorshError>

Convert tensor to ndarray (temporary placeholder implementation)

TODO: Implement proper ndarray conversion following SciRS2 POLICY This should use scirs2_core::ndarray for array operations

Source

pub fn from_ndarray( array: ArrayBase<OwnedRepr<T>, Dim<IxDynImpl>>, device: DeviceType, ) -> Result<Tensor<T>, TorshError>

Create tensor from ndarray (temporary placeholder implementation)

TODO: Implement proper ndarray conversion following SciRS2 POLICY This should use scirs2_core::ndarray for array operations

Source

pub fn max( &self, dim: Option<usize>, keepdim: bool, ) -> Result<Tensor<T>, TorshError>

Maximum element in tensor

Source

pub fn max_dim(&self, dim: i32, keepdim: bool) -> Result<Tensor<T>, TorshError>

Maximum along specified dimension

Source

pub fn min_dim(&self, dim: i32, keepdim: bool) -> Result<Tensor<T>, TorshError>

Minimum along specified dimension

Source§

impl<T> Tensor<T>

Boolean reduction operations for tensors

Source

pub fn all(&self) -> Result<Tensor<bool>, TorshError>

Check if all elements are non-zero (true)

Source

pub fn any(&self) -> Result<Tensor<bool>, TorshError>

Check if any element is non-zero (true)

Source

pub fn all_dim( &self, dim: i32, _keepdim: bool, ) -> Result<Tensor<bool>, TorshError>

Check if all elements along dimension are non-zero (true)

Source

pub fn any_dim( &self, dim: i32, _keepdim: bool, ) -> Result<Tensor<bool>, TorshError>

Check if any element along dimension is non-zero (true)

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn sum(&self) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T> + Zero,

Compute sum of all elements

Source

pub fn sum_dim( &self, dims: &[i32], keepdim: bool, ) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T> + Zero,

Compute sum along specified dimensions

Source

pub fn mean( &self, dims: Option<&[usize]>, keepdim: bool, ) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T> + Div<Output = T> + Zero + One + FromPrimitive,

Compute mean along specified dimensions

Source

pub fn cumprod(&self, dim: i32) -> Result<Tensor<T>, TorshError>
where T: Mul<Output = T> + One + Copy,

Compute cumulative product along specified dimension

Source

pub fn matmul(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Float + Sum,

Matrix multiplication

Source

pub fn sort( &self, _dim: Option<i32>, _descending: bool, ) -> Result<(Tensor<T>, Tensor<T>), TorshError>

Sort tensor along specified dimension

Source

pub fn min(&self) -> Result<Tensor<T>, TorshError>
where T: PartialOrd + Copy,

Min reduction method without trait bounds (for Iterator compatibility)

Source

pub fn t(&self) -> Result<Tensor<T>, TorshError>
where T: Copy + Zero,

Transpose operation (2D tensor)

Source

pub fn shares_storage(&self, other: &Tensor<T>) -> bool

Check if two tensors share the same underlying storage

Source

pub fn data(&self) -> Result<Vec<T>, TorshError>
where T: Copy,

Get data as a vector (backward compatibility method)

Source

pub fn data_mut_apply<F>(&mut self, func: F) -> Result<(), TorshError>
where F: FnMut(&mut T), T: Copy,

Apply a function to all elements in-place using direct storage access

Source

pub fn clone_data(&self) -> Tensor<T>
where T: Copy,

Clone the tensor with independent data (deep copy)

Source

pub fn make_unique(&mut self) -> Result<(), TorshError>

Ensure tensor has unique data (copy-on-write semantics)

Source

pub fn apply_<F>(&mut self, func: F) -> Result<(), TorshError>
where F: Fn(T) -> T, T: Copy,

Apply function in-place

Source

pub fn map<F>(&self, func: F) -> Result<Tensor<T>, TorshError>
where F: Fn(T) -> T, T: Copy,

Apply function element-wise to create new tensor

Source

pub fn item(&self) -> Result<T, TorshError>
where T: Copy,

Extract a scalar value from a single-element tensor

Source

pub fn cat(tensors: &[&Tensor<T>], dim: i32) -> Result<Tensor<T>, TorshError>
where T: Copy,

Concatenate tensors along a dimension

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy + Float,

Source

pub fn norm(&self) -> Result<Tensor<T>, TorshError>

Compute the L2 norm of the tensor

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn matmul_scirs2(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Float + Zero + One + Sum,

Use SciRS2 backend for optimized matrix multiplication

Source

pub fn sum_scirs2(&self) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T> + Zero,

Use SciRS2 backend for optimized sum reduction

Source

pub fn mean_scirs2(&self) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T> + Div<Output = T> + Zero + From<usize> + FromPrimitive,

Use SciRS2 backend for optimized mean reduction

Source

pub fn relu_scirs2(&self) -> Result<Tensor<T>, TorshError>
where T: PartialOrd + Zero,

Use SciRS2 backend for optimized ReLU activation

Source

pub fn sigmoid_scirs2(&self) -> Result<Tensor<T>, TorshError>
where T: Float,

Use SciRS2 backend for optimized sigmoid activation

Source

pub fn tanh_scirs2(&self) -> Result<Tensor<T>, TorshError>
where T: Float,

Use SciRS2 backend for optimized tanh activation

Source

pub fn softmax(&self, dim: i32) -> Result<Tensor<T>, TorshError>
where T: FloatElement<Output = T, Output = T> + Copy + Sub + Div,

Softmax activation along specified dimension Computes softmax(x_i) = exp(x_i) / sum(exp(x_j)) for all j

Source

pub fn log_softmax(&self, dim: i32) -> Result<Tensor<T>, TorshError>
where T: FloatElement<Output = T> + Copy + Sub,

Log softmax activation along specified dimension Computes log_softmax(x_i) = log(softmax(x_i))

Source

pub fn cumsum(&self, dim: i32) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T> + Zero + Copy,

Computes cumulative sum along a dimension

Source

pub fn argmin(&self, dim: Option<i32>) -> Result<Tensor<i64>, TorshError>
where T: PartialOrd + Copy,

Find the indices of minimum values along a dimension

Source

pub fn argmax(&self, dim: Option<i32>) -> Result<Tensor<i64>, TorshError>
where T: PartialOrd + Copy,

Find the indices of maximum values along a dimension

Source

pub fn topk( &self, k: usize, dim: Option<i32>, largest: bool, sorted: bool, ) -> Result<(Tensor<T>, Tensor<i64>), TorshError>
where T: PartialOrd + Copy + Zero,

Returns the k largest elements along a dimension

Source§

impl<T> Tensor<T>
where T: ComplexElement + Copy,

Source

pub fn complex_conj(&self) -> Result<Tensor<T>, TorshError>
where T: Copy,

Complex conjugate for complex tensors

Source

pub fn real(&self) -> Result<Tensor<<T as ComplexElement>::Real>, TorshError>

Get real part of complex tensor

Source

pub fn imag(&self) -> Result<Tensor<<T as ComplexElement>::Real>, TorshError>

Get imaginary part of complex tensor

Source

pub fn abs(&self) -> Result<Tensor<<T as ComplexElement>::Real>, TorshError>

Get magnitude (absolute value) of complex tensor

Source

pub fn angle(&self) -> Result<Tensor<<T as ComplexElement>::Real>, TorshError>

Get phase (argument) of complex tensor

Source

pub fn complex( real: &Tensor<<T as ComplexElement>::Real>, imag: &Tensor<<T as ComplexElement>::Real>, ) -> Result<Tensor<T>, TorshError>

Create complex tensor from real and imaginary parts

Source

pub fn polar( magnitude: &Tensor<<T as ComplexElement>::Real>, phase: &Tensor<<T as ComplexElement>::Real>, ) -> Result<Tensor<T>, TorshError>

Create complex tensor from polar representation (magnitude and phase)

Source

pub fn backward_complex(&self) -> Result<(), TorshError>
where T: Copy + Default + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>,

Backward pass for complex tensors (compute gradients)

Complex autograd follows PyTorch’s approach where gradients are computed treating complex numbers as 2D vectors of real numbers.

Source

pub fn complex_mul(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Mul<Output = T> + Add<Output = T> + Sub<Output = T>,

Element-wise complex multiplication with proper gradient tracking

Source

pub fn complex_add(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T>,

Element-wise complex addition with proper gradient tracking

Source

pub fn is_real(&self) -> Result<bool, TorshError>
where <T as ComplexElement>::Real: PartialEq + Zero,

Check if all elements in the tensor are real (imaginary part is zero)

Source

pub fn is_complex(&self) -> Result<bool, TorshError>
where <T as ComplexElement>::Real: PartialEq + Zero,

Check if any elements in the tensor are complex (imaginary part is non-zero)

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn cleanup_operation_refs(&mut self)

Clean up dead weak references in custom operations to improve memory efficiency

Source

pub fn from_data( data: Vec<T>, shape: Vec<usize>, device: DeviceType, ) -> Result<Tensor<T>, TorshError>

Create from raw data

Source

pub fn from_data_fast( data: Vec<T>, shape: Vec<usize>, device: DeviceType, ) -> Tensor<T>

🚀 Phase 7: Create tensor with fast result storage (skips alignment copy)

For SIMD operation results, uses simple InMemory storage to avoid the ~10µs overhead of copying data to aligned memory.

§Performance
  • Skips AlignedVec copy (saves ~10µs for 50K elements)
  • Best for intermediate/result tensors
  • Input tensors should still use from_data for optimal SIMD input access
Source

pub fn from_data_with_storage( data: Vec<T>, shape: Vec<usize>, device: DeviceType, use_memory_mapping: bool, ) -> Result<Tensor<T>, TorshError>

Create from raw data with explicit storage type

Source

pub fn from_data_memory_mapped( data: Vec<T>, shape: Vec<usize>, device: DeviceType, file_path: PathBuf, ) -> Result<Tensor<T>, TorshError>

Create from raw data with specified memory-mapped file path

Source

pub fn zeros( shape: &[usize], device: DeviceType, ) -> Result<Tensor<T>, TorshError>

Create a tensor filled with zeros

Source

pub fn ones( shape: &[usize], device: DeviceType, ) -> Result<Tensor<T>, TorshError>

Create a tensor filled with ones

Source

pub fn shape(&self) -> Shape

Get the shape of the tensor

Source

pub fn ndim(&self) -> usize

Get the number of dimensions

Source

pub fn numel(&self) -> usize

Get the total number of elements

Source

pub fn dtype(&self) -> DType

Get the data type

Source

pub fn to_dtype(&self, dtype: DType) -> Result<Tensor<T>, TorshError>

Convert tensor to a different data type

Source

pub fn device(&self) -> DeviceType

Get the device

Source

pub fn get(&self, indices: &[usize]) -> Result<T, TorshError>
where T: Copy,

Get element at multi-dimensional index

Source

pub fn get_flat(&self, index: usize) -> Result<T, TorshError>
where T: Copy,

Get element at single flat index

Source

pub fn set(&self, indices: &[usize], value: T) -> Result<(), TorshError>
where T: Copy,

Set element at index (requires multi-dimensional indices for views)

Source

pub fn get_slice(&self, start: usize, len: usize) -> Result<Vec<T>, TorshError>
where T: Copy,

Get slice of elements

Source

pub fn set_slice(&self, start: usize, values: &[T]) -> Result<(), TorshError>
where T: Copy,

Set slice of elements

Source

pub fn to_vec(&self) -> Result<Vec<T>, TorshError>
where T: Copy,

Get all data as a vector (may be expensive for large memory-mapped tensors) For views, extracts only the data visible by this view

Source

pub fn storage_type(&self) -> &'static str

Get storage type information

Source

pub fn memory_usage(&self) -> usize

Get estimated memory usage in bytes

Source

pub fn is_memory_mapped(&self) -> bool

Check if tensor uses memory mapping

Source

pub fn is_view(&self) -> bool

Check if this tensor is a view of another tensor

Source

pub fn strides(&self) -> Vec<usize>

Get the strides for this tensor (either custom strides for views or default contiguous strides)

Source

pub fn with_data_slice<R, F>(&self, f: F) -> Result<R, TorshError>
where F: FnOnce(&[T]) -> Result<R, TorshError>, T: Copy,

Execute a function with zero-copy access to tensor data (immutable)

This enables SIMD operations without memory copies by providing direct access to the underlying buffer within a scoped context.

§Arguments
  • f - Closure that receives &[T] and returns Result<R>
§Returns

Result from the closure

§Performance
  • Zero memory copies for InMemory and Aligned storage
  • One allocation for MemoryMapped storage
  • Enables 2-4x SIMD speedup (per SciRS2 docs)
§Examples
// Direct SIMD operation without copies
let result = tensor.with_data_slice(|data| {
    other_tensor.with_data_slice(|other_data| {
        // Zero-copy SIMD addition
        f32::simd_add(&data, &other_data)
    })
})?;
Source

pub fn with_data_slice_mut<R, F>(&self, f: F) -> Result<R, TorshError>
where F: FnOnce(&mut [T]) -> Result<R, TorshError>, T: Copy,

Execute a function with zero-copy access to tensor data (mutable)

This enables in-place SIMD operations without memory copies.

§Arguments
  • f - Closure that receives &mut [T] and returns Result<R>
§Returns

Result from the closure

§Performance
  • Zero memory copies for InMemory storage
  • Not supported for MemoryMapped or Aligned storage (returns error)
§Examples
// In-place SIMD operation without copies
tensor.with_data_slice_mut(|data| {
    other_tensor.with_data_slice(|other_data| {
        // Zero-copy in-place SIMD addition
        for (x, y) in data.iter_mut().zip(other_data.iter()) {
            *x = *x + *y;
        }
        Ok(())
    })
})?;
Source

pub fn ones_like(&self) -> Result<Tensor<T>, TorshError>

Create a tensor of ones with the same shape as this tensor

Source

pub fn zeros_like(&self) -> Result<Tensor<T>, TorshError>

Create a tensor of zeros with the same shape as this tensor

Source

pub fn requires_grad_(self, requires_grad: bool) -> Tensor<T>

Enable or disable gradient tracking for this tensor.

This method marks the tensor as requiring (or not requiring) gradient computation during the backward pass. It consumes self and returns the modified tensor, allowing for method chaining in the builder pattern.

§Parameters
  • requires_grad: If true, gradients will be computed and stored for this tensor during backward passes. If false, gradients will not be computed.
§Important Notes
  • Only leaf tensors (tensors created directly, not from operations) store gradients
  • Intermediate tensors in the computation graph don’t store gradients, only leaf tensors do
  • Setting requires_grad=true enables tracking for all subsequent operations
  • You should typically set this for model parameters and input data you want to optimize
§Examples
§Basic Usage
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// Create tensor and enable gradient tracking
let x = Tensor::from_data(vec![1.0, 2.0, 3.0], vec![3], DeviceType::Cpu)?
    .requires_grad_(true);

assert!(x.requires_grad());
§Neural Network Parameters
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// Create trainable weights
let weights = Tensor::randn(&[784, 128], DeviceType::Cpu)?
    .requires_grad_(true);

let bias = Tensor::zeros(&[128], DeviceType::Cpu)?
    .requires_grad_(true);

// Use in forward pass
let input = Tensor::randn(&[32, 784], DeviceType::Cpu)?;
let output = input.matmul(&weights)?.add(&bias)?;
§Freezing Layers (Transfer Learning)
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// Pretrained layer - don't compute gradients
let frozen_weights = Tensor::randn(&[512, 256], DeviceType::Cpu)?
    .requires_grad_(false);

// New layer - compute gradients
let trainable_weights = Tensor::randn(&[256, 10], DeviceType::Cpu)?
    .requires_grad_(true);
§Method Chaining
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// Chain multiple operations
let x = Tensor::ones(&[5], DeviceType::Cpu)?
    .requires_grad_(true)
    .mul_scalar(2.0)?
    .add_scalar(1.0)?;

assert!(x.requires_grad());
§Gradient Propagation

When a tensor has requires_grad=true, all operations on it will also have requires_grad=true, building the computation graph:

use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let x = Tensor::from_data(vec![2.0], vec![1], DeviceType::Cpu)?
    .requires_grad_(true);

let y = x.pow(2.0)?;        // y also requires grad
let z = y.mul_scalar(3.0)?;  // z also requires grad
let w = z.add_scalar(1.0)?;  // w also requires grad

assert!(y.requires_grad());
assert!(z.requires_grad());
assert!(w.requires_grad());
§See Also
Source

pub fn requires_grad(&self) -> bool

Check if this tensor requires gradient computation.

Returns true if gradients will be computed for this tensor during backward passes, false otherwise.

§Examples
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let x = Tensor::ones(&[3], DeviceType::Cpu)?.requires_grad_(true);
assert!(x.requires_grad());

let y = Tensor::ones(&[3], DeviceType::Cpu)?;
assert!(!y.requires_grad());
§See Also
Source

pub fn set_grad(&self, grad: Option<Tensor<T>>)

Set gradient tensor

Source

pub fn grad_mut(&mut self) -> Option<&mut Tensor<T>>

Get mutable access to gradient

Source

pub fn to<D>(self, device: D) -> Result<Tensor<T>, TorshError>
where D: Into<DeviceType>,

🚀 Enhanced device transfer with multi-backend GPU support Automatically selects optimal transfer strategy and backend

Source

pub fn distribute_multi_gpu_wrapper( &self, gpu_count: usize, ) -> Result<Vec<Tensor<T>>, TorshError>

Source

pub fn detach(&self) -> Tensor<T>

Create a detached copy of this tensor that doesn’t track gradients.

This method creates a new tensor with the same data as the original, but with requires_grad=false. The detached tensor is not part of the computation graph and will not participate in gradient computation, even if the original tensor did.

§Use Cases
  • Inference with trained parameters: Use detached weights for forward-only computation
  • Custom gradient logic: Manually control which tensors participate in backprop
  • Debugging: Inspect intermediate values without affecting the gradient flow
  • Mixed training: Some computations need gradients, others don’t
  • Memory optimization: Reduce memory usage by not tracking gradients for certain operations
§Important Notes
  • The returned tensor shares no gradient history with the original
  • Operations on the detached tensor will also have requires_grad=false
  • This creates a copy of the data (not a view) - consider memory implications
  • The detached tensor is a “leaf” tensor with no computation history
§Examples
§Basic Detachment
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let x = Tensor::from_data(vec![1.0, 2.0, 3.0], vec![3], DeviceType::Cpu)?
    .requires_grad_(true);

// Create detached copy
let x_detached = x.detach();

// Original tracks gradients, detached does not
assert!(x.requires_grad());
assert!(!x_detached.requires_grad());

// Operations on detached tensor don't track gradients
let y_detached = x_detached.pow(2.0)?;
assert!(!y_detached.requires_grad());
§Stopping Gradient Flow
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// This pattern prevents gradients from flowing through certain operations
let x = Tensor::from_data(vec![2.0], vec![1], DeviceType::Cpu)?
    .requires_grad_(true);

// Compute something we want to use but not backpropagate through
let intermediate = x.pow(2.0)?;
let intermediate_detached = intermediate.detach();

// Use detached version in further computation
let y = intermediate_detached.mul_scalar(3.0)?;
let loss = y.sum()?;

// Backward won't compute gradients for x
// (because gradient flow is stopped at detach point)
§Target Tensor Pattern (No Gradients for Labels)
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// Predictions need gradients
let predictions = Tensor::randn(&[32, 10], DeviceType::Cpu)?
    .requires_grad_(true);

// Target labels should NOT have gradients
let targets = Tensor::from_data(
    vec![0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
    vec![1, 10],
    DeviceType::Cpu
)?.detach();  // Explicitly detach to ensure no gradients

assert!(predictions.requires_grad());
assert!(!targets.requires_grad());

// Compute loss - only predictions will have gradients
let diff = predictions.sub(&targets)?;
let loss = diff.pow(2.0)?.mean()?;
loss.backward()?;
§Debugging Intermediate Values
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let x = Tensor::randn(&[100], DeviceType::Cpu)?
    .requires_grad_(true);

// Complex computation
let y = x.pow(2.0)?.add_scalar(1.0)?;

// Detach to inspect values without affecting gradient computation
let y_values = y.detach();
let max_val = y_values.to_vec()?.iter().cloned().fold(f32::NEG_INFINITY, f32::max);
println!("Max value: {}", max_val);

// Continue with original gradient-tracking tensor
let loss = y.sum()?;
loss.backward()?;
§Feature Extraction (Transfer Learning)
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// Pretrained model features - don't need gradients
fn pretrained_feature_extractor(input: &Tensor<f32>) -> Result<Tensor<f32>, torsh_core::error::TorshError> {
    // Complex pretrained network...
    let features = input.matmul(&Tensor::randn(&[784, 512], DeviceType::Cpu)?)?;
    // Detach to stop gradient flow
    Ok(features.detach())
}

// New trainable classifier head
let input = Tensor::randn(&[32, 784], DeviceType::Cpu)?;
let features = pretrained_feature_extractor(&input)?;

// Only this part will have gradients
let weights = Tensor::randn(&[512, 10], DeviceType::Cpu)?
    .requires_grad_(true);
let output = features.matmul(&weights)?;
§Memory Optimization Example
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let x = Tensor::randn(&[1000, 1000], DeviceType::Cpu)?
    .requires_grad_(true);

// Large intermediate computation
let intermediate = x.matmul(&x.transpose(&[1, 0])?)?;

// If we only need the values, not gradients
let result = intermediate.detach();

// Now intermediate computation graph can be freed
drop(intermediate);

// Use result without gradient tracking
let final_result = result.mul_scalar(0.5)?;
§Comparison with no_grad Context
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;
use torsh_autograd::guards::no_grad;

let x = Tensor::randn(&[5], DeviceType::Cpu)?
    .requires_grad_(true);

// Method 1: Detach - creates a copy
let y1 = x.detach().pow(2.0)?;
assert!(!y1.requires_grad());

// Method 2: no_grad context - affects all operations in scope
let y2 = {
    let _guard = no_grad();
    x.pow(2.0)?
};
assert!(!y2.requires_grad());

// Note: detach() is for selective detachment of specific tensors
// no_grad() is for disabling gradient tracking in a code block
§Detach vs Clone
  • detach(): Creates a copy with requires_grad=false
  • clone(): Creates a copy preserving requires_grad status
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let x = Tensor::ones(&[3], DeviceType::Cpu)?
    .requires_grad_(true);

let x_clone = x.clone();
let x_detach = x.detach();

assert!(x_clone.requires_grad());   // Preserves gradient tracking
assert!(!x_detach.requires_grad()); // Disables gradient tracking
§See Also
  • requires_grad_() - Set gradient tracking
  • torsh_autograd::guards::no_grad() - Disable gradients in a scope
  • backward() - Compute gradients
Source

pub fn grad(&self) -> Option<Tensor<T>>

Access the computed gradient for this tensor.

Returns Some(gradient_tensor) if gradients have been computed via backward(), or None if no gradients exist yet.

§Important Notes
  • Only leaf tensors store gradients (tensors created directly, not from operations)
  • You must call backward() on a scalar output before gradients exist
  • Gradients accumulate across multiple backward() calls unless cleared with zero_grad()
  • The returned gradient tensor has the same shape as the original tensor
§Returns
  • Some(Tensor) - The gradient tensor if computed
  • None - If backward has not been called or gradients were cleared
§Examples
§Basic Gradient Access
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let x = Tensor::from_data(vec![2.0], vec![1], DeviceType::Cpu)?
    .requires_grad_(true);

// Before backward: no gradient
assert!(x.grad().is_none());

// Compute gradient
let y = x.pow(2.0)?;
y.backward()?;

// After backward: gradient exists
let grad = x.grad().expect("gradient should exist");
assert_eq!(grad.item()?, 4.0);  // dy/dx = 2x = 4
§Multi-Dimensional Gradients
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let x = Tensor::from_data(
    vec![1.0, 2.0, 3.0, 4.0],
    vec![2, 2],
    DeviceType::Cpu
)?.requires_grad_(true);

// Loss function: sum of squares
let y = x.pow(2.0)?;
let loss = y.sum()?;
loss.backward()?;

// Gradient has same shape as input
let grad = x.grad().expect("gradient should exist");
assert_eq!(grad.shape().dims(), &[2, 2]);
// Gradient values: [2, 4, 6, 8] (2 * each input)
§Using Gradients for Optimization
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let mut weights = Tensor::randn(&[10], DeviceType::Cpu)?
    .requires_grad_(true);

let learning_rate = 0.01;

// Training loop
for step in 0..100 {
    // Forward pass
    let output = weights.mul_scalar(2.0)?;
    let loss = output.sum()?;

    // Backward pass
    loss.backward()?;

    // Get gradients and update weights
    if let Some(grad) = weights.grad() {
        // weights = weights - learning_rate * grad
        let update = grad.mul_scalar(learning_rate)?;
        weights = weights.sub(&update)?;
    }

    // Clear gradients for next iteration
    weights.zero_grad();
}
§Gradient Accumulation Check
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let mut x = Tensor::from_data(vec![1.0], vec![1], DeviceType::Cpu)?
    .requires_grad_(true);

// First backward pass
let y1 = x.pow(2.0)?;
y1.backward()?;
let grad1 = x.grad().expect("gradient should exist").item()?;
assert_eq!(grad1, 2.0);

// Second backward pass without zeroing - accumulates!
let y2 = x.pow(2.0)?;
y2.backward()?;
let grad2 = x.grad().expect("gradient should exist").item()?;
assert_eq!(grad2, 4.0);  // 2.0 + 2.0 = 4.0

// Clear for next iteration
x.zero_grad();
assert!(x.grad().is_none());
§Common Patterns
§Safe Gradient Extraction
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// Option 1: Unwrap (panics if no gradient)
let grad = x.grad().expect("gradient should exist");

// Option 2: Pattern matching (safer)
match x.grad() {
    Some(grad) => {
        // Use gradient
        println!("Gradient: {:?}", grad);
    }
    None => {
        println!("No gradient computed yet");
    }
}

// Option 3: if-let pattern
if let Some(grad) = x.grad() {
    // Use gradient
}
§See Also
Source

pub fn has_grad(&self) -> bool

Check if this tensor has a computed gradient.

Returns true if gradients have been computed and stored, false otherwise. This is equivalent to tensor.grad().is_some() but more explicit.

§Examples
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let x = Tensor::from_data(vec![2.0], vec![1], DeviceType::Cpu)?
    .requires_grad_(true);

assert!(!x.has_grad());  // No gradient yet

let y = x.pow(2.0)?;
y.backward()?;

assert!(x.has_grad());   // Gradient now exists
§See Also
  • grad() - Access the gradient tensor
Source

pub fn zero_grad(&mut self)

Clear the gradient for this tensor.

This method sets the gradient to None, effectively resetting it. You should call this method between training iterations to prevent gradient accumulation when you don’t want it.

§When to Use
  • After optimizer step: Clear gradients before the next training iteration
  • Between validation runs: Ensure clean state for evaluation
  • After gradient accumulation: Clear after applying accumulated gradients
§Important Notes
  • Gradients accumulate by default across multiple backward() calls
  • Always call zero_grad() between training iterations unless you explicitly want gradient accumulation
  • This only clears the gradient; it doesn’t affect requires_grad status
§Examples
§Standard Training Loop
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let mut weights = Tensor::randn(&[10], DeviceType::Cpu)?
    .requires_grad_(true);

for epoch in 0..100 {
    // Forward pass
    let output = weights.mul_scalar(2.0)?;
    let loss = output.sum()?;

    // Backward pass
    loss.backward()?;

    // Update weights (simplified)
    if let Some(grad) = weights.grad() {
        weights = weights.sub(&grad.mul_scalar(0.01)?)?;
    }

    // CRITICAL: Clear gradients for next iteration
    weights.zero_grad();
}
§Gradient Accumulation Pattern
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let mut model_params = Tensor::randn(&[100], DeviceType::Cpu)?
    .requires_grad_(true);

let accumulation_steps = 4;

// Zero gradients at start
model_params.zero_grad();

for step in 0..accumulation_steps {
    // Forward and backward for mini-batch
    let output = model_params.mul_scalar(2.0)?;
    let loss = output.sum()?;
    loss.backward()?;

    // DON'T zero gradients here - let them accumulate
}

// After accumulation, update weights
if let Some(grad) = model_params.grad() {
    // Scale by number of accumulation steps
    let scaled_grad = grad.div_scalar(accumulation_steps as f32)?;
    model_params = model_params.sub(&scaled_grad.mul_scalar(0.01)?)?;
}

// NOW clear gradients for next accumulation cycle
model_params.zero_grad();
§Multiple Parameter Update
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let mut weights = Tensor::randn(&[10, 5], DeviceType::Cpu)?
    .requires_grad_(true);
let mut bias = Tensor::zeros(&[5], DeviceType::Cpu)?
    .requires_grad_(true);

// Training step
let input = Tensor::randn(&[32, 10], DeviceType::Cpu)?;
let output = input.matmul(&weights)?.add(&bias)?;
let loss = output.sum()?;

loss.backward()?;

// Update both parameters
// ... (weight updates)

// Clear gradients for both
weights.zero_grad();
bias.zero_grad();
§Validation Without Gradient Tracking
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;
use torsh_autograd::guards::no_grad;

let weights = Tensor::randn(&[10], DeviceType::Cpu)?
    .requires_grad_(true);

// During validation, use no_grad guard
let validation_loss = {
    let _guard = no_grad();
    let output = weights.mul_scalar(2.0)?;
    output.sum()?
};

// No gradients computed during validation, so nothing to zero
// But good practice to ensure clean state
// weights.zero_grad();
§Common Mistake
§Forgetting to Zero Gradients
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let mut x = Tensor::from_data(vec![1.0], vec![1], DeviceType::Cpu)?
    .requires_grad_(true);

// Iteration 1
let y1 = x.pow(2.0)?;
y1.backward()?;
let grad1 = x.grad().expect("gradient should exist").item()?;
println!("Grad 1: {}", grad1);  // 2.0

// Iteration 2 - FORGOT TO ZERO!
let y2 = x.pow(2.0)?;
y2.backward()?;
let grad2 = x.grad().expect("gradient should exist").item()?;
println!("Grad 2: {}", grad2);  // 4.0 (WRONG! Should be 2.0)

// Correct approach:
x.zero_grad();  // Clear between iterations
let y3 = x.pow(2.0)?;
y3.backward()?;
let grad3 = x.grad().expect("gradient should exist").item()?;
println!("Grad 3: {}", grad3);  // 2.0 (CORRECT!)
§See Also
Source

pub fn backward(&self) -> Result<(), TorshError>
where T: FloatElement<Output = T, Output = T, Output = T, Output = T> + Copy + Default + Add + Sub + Mul + Div + Clone + Debug, f32: From<T>,

Computes gradients for all tensors in the computation graph.

This method performs backpropagation through the computation graph, computing gradients for all tensors with requires_grad=true. The backward pass starts from this tensor (which must be a scalar) and propagates gradients back through the computational graph to all leaf tensors.

§Requirements
  • This tensor must be a scalar (single element) - use .sum() or similar reduction operations to create a scalar from multi-dimensional tensors
  • This tensor must have requires_grad=true
  • All tensors in the computation graph are retained during backward pass
§How It Works

The backward pass:

  1. Starts with a gradient of 1.0 for the output (scalar) tensor
  2. Traverses the computation graph in reverse topological order
  3. Applies the chain rule at each operation node
  4. Accumulates gradients at leaf nodes (input tensors)
§Gradient Accumulation

If you call backward() multiple times without zeroing gradients, the gradients will accumulate (add together). This is useful for:

  • Gradient accumulation across mini-batches
  • Computing gradients for multiple outputs

Use zero_grad() to clear gradients between iterations.

§Examples
§Basic Gradient Computation
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// Create input tensor with gradient tracking enabled
let x = Tensor::from_data(vec![2.0f32], vec![1], DeviceType::Cpu)?
    .requires_grad_(true);

// Forward pass: y = x^2
let y = x.pow(2.0)?;

// Backward pass: compute dy/dx = 2x
y.backward()?;

// Access gradient: should be 2 * 2.0 = 4.0
let grad = x.grad().expect("gradient should exist");
assert_eq!(grad.item()?, 4.0);
§Multi-Variable Function
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// f(x, y) = x^2 + 2xy + y^2
let x = Tensor::from_data(vec![3.0f32], vec![1], DeviceType::Cpu)?
    .requires_grad_(true);
let y = Tensor::from_data(vec![4.0f32], vec![1], DeviceType::Cpu)?
    .requires_grad_(true);

// Forward pass
let x_squared = x.pow(2.0)?;
let xy = x.mul(&y)?;
let two_xy = xy.mul_scalar(2.0)?;
let y_squared = y.pow(2.0)?;
let result = x_squared.add(&two_xy)?.add(&y_squared)?;

// Backward pass
result.backward()?;

// df/dx = 2x + 2y = 6 + 8 = 14
// df/dy = 2x + 2y = 6 + 8 = 14
let grad_x = x.grad().expect("gradient should exist");
let grad_y = y.grad().expect("gradient should exist");
§Vector to Scalar (Loss Function)
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

// Create predictions and targets
let predictions = Tensor::from_data(
    vec![0.8, 0.6, 0.9],
    vec![3],
    DeviceType::Cpu
)?.requires_grad_(true);

let targets = Tensor::from_data(
    vec![1.0, 0.0, 1.0],
    vec![3],
    DeviceType::Cpu
)?;

// Compute MSE loss: mean((pred - target)^2)
let diff = predictions.sub(&targets)?;
let squared = diff.pow(2.0)?;
let loss = squared.mean()?; // Reduces to scalar

// Compute gradients
loss.backward()?;

// Gradient shows direction to reduce loss
let grad = predictions.grad().expect("gradient should exist");
§Gradient Accumulation Pattern
use torsh_tensor::Tensor;
use torsh_core::device::DeviceType;

let mut weights = Tensor::from_data(
    vec![0.5f32; 10],
    vec![10],
    DeviceType::Cpu
)?.requires_grad_(true);

// Accumulate gradients over multiple batches
for batch in 0..4 {
    // Forward pass for this batch
    let output = weights.mul_scalar(2.0)?;
    let loss = output.sum()?;

    // Backward pass - gradients accumulate
    loss.backward()?;

    // Don't zero gradients yet
}

// After accumulation, update weights
// optimizer.step();

// Clear gradients for next iteration
weights.zero_grad();
§Errors

Returns an error if:

  • The tensor doesn’t have requires_grad=true
  • The tensor is not a scalar (has more than 1 element)
  • An error occurs during gradient computation
§Common Pitfalls
§1. Forgetting to Create Scalar Output
let x = Tensor::from_data(vec![1.0, 2.0, 3.0], vec![3], DeviceType::Cpu)
    .expect("tensor creation should succeed")
    .requires_grad_(true);
let y = x.pow(2.0).expect("pow should succeed");

// ERROR: y has 3 elements, not a scalar!
y.backward().expect("backward pass should succeed");  // This will panic

Solution: Use reduction operations:

let y = x.pow(2.0)?.sum()?;  // Reduce to scalar
y.backward()?;
§2. Forgetting to Enable Gradient Tracking
let x = Tensor::from_data(vec![2.0], vec![1], DeviceType::Cpu).expect("tensor creation should succeed");
// Forgot .requires_grad_(true)
let y = x.pow(2.0).expect("pow should succeed");
y.backward().expect("backward pass should succeed");  // ERROR: requires_grad not set
§3. Not Zeroing Gradients Between Training Steps
let mut x = Tensor::from_data(vec![1.0], vec![1], DeviceType::Cpu)?
    .requires_grad_(true);

for epoch in 0..3 {
    let y = x.pow(2.0)?.sum()?;
    y.backward()?;

    // Gradients accumulate without this!
    x.zero_grad();  // IMPORTANT: Clear gradients
}
§See Also
Source

pub fn backward_with_grad( &self, _gradient: Option<&Tensor<T>>, ) -> Result<(), TorshError>
where T: FloatElement<Output = T, Output = T, Output = T, Output = T> + Copy + Default + Add + Sub + Mul + Div + Clone + Debug, f32: From<T>,

Backward pass with gradient - integrated with autograd system

Source§

impl<T> Tensor<T>

Comparison operations for tensors

Source

pub fn gt(&self, other: &Tensor<T>) -> Result<Tensor<bool>, TorshError>

Element-wise greater than comparison

Source

pub fn lt(&self, other: &Tensor<T>) -> Result<Tensor<bool>, TorshError>

Element-wise less than comparison

Source

pub fn ge(&self, other: &Tensor<T>) -> Result<Tensor<bool>, TorshError>

Element-wise greater than or equal comparison

Source

pub fn le(&self, other: &Tensor<T>) -> Result<Tensor<bool>, TorshError>

Element-wise less than or equal comparison

Source

pub fn eq(&self, other: &Tensor<T>) -> Result<Tensor<bool>, TorshError>

Element-wise equality comparison

Source

pub fn ne(&self, other: &Tensor<T>) -> Result<Tensor<bool>, TorshError>

Element-wise inequality comparison

Source

pub fn eq_scalar(&self, value: T) -> Result<Tensor<bool>, TorshError>
where T: PartialEq + Copy,

Scalar comparison methods Element-wise equality comparison with scalar

Source

pub fn ne_scalar(&self, value: T) -> Result<Tensor<bool>, TorshError>
where T: PartialEq + Copy,

Element-wise inequality comparison with scalar

Source

pub fn gt_scalar(&self, value: T) -> Result<Tensor<bool>, TorshError>
where T: PartialOrd + Copy,

Element-wise greater than comparison with scalar

Source

pub fn lt_scalar(&self, value: T) -> Result<Tensor<bool>, TorshError>
where T: PartialOrd + Copy,

Element-wise less than comparison with scalar

Source

pub fn le_scalar(&self, value: T) -> Result<Tensor<bool>, TorshError>
where T: PartialOrd + Copy,

Element-wise less than or equal comparison with scalar

Source

pub fn ge_scalar(&self, value: T) -> Result<Tensor<bool>, TorshError>
where T: PartialOrd + Copy,

Element-wise greater than or equal comparison with scalar

Source§

impl<T> Tensor<T>
where T: TensorElement,

Shape manipulation operations for tensors

Source

pub fn flatten(&self) -> Result<Tensor<T>, TorshError>

Flatten tensor to 1D

Source

pub fn where_tensor( &self, condition: &Tensor<bool>, other: &Tensor<T>, ) -> Result<Tensor<T>, TorshError>

Conditional tensor selection - where condition is true, select from self, otherwise from other

Source

pub fn add_bias(&self, bias: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T>,

Add bias vector to tensor (element-wise addition)

Source§

impl Tensor<bool>

Logical operations for boolean tensors

Source

pub fn logical_and( &self, other: &Tensor<bool>, ) -> Result<Tensor<bool>, TorshError>

Element-wise logical AND operation

Source

pub fn logical_or( &self, other: &Tensor<bool>, ) -> Result<Tensor<bool>, TorshError>

Element-wise logical OR operation

Source

pub fn logical_xor( &self, other: &Tensor<bool>, ) -> Result<Tensor<bool>, TorshError>

Element-wise logical XOR operation

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn from_scalar( value: T, shape: &[usize], device: DeviceType, ) -> Result<Tensor<T>, TorshError>
where T: Copy,

Create tensor from a scalar value repeated to fill the shape

Source

pub fn fill_(&mut self, value: T) -> Result<(), TorshError>
where T: Copy,

Fill tensor with a single value (in-place)

Source

pub fn zero_(&mut self) -> Result<(), TorshError>
where T: Copy,

Zero out the tensor (in-place)

Source

pub fn ones_(&mut self) -> Result<(), TorshError>
where T: Copy,

Fill with ones (in-place)

Source

pub fn copy_(&mut self, other: &Tensor<T>) -> Result<(), TorshError>
where T: Copy,

Copy data from another tensor (in-place)

Source

pub fn get_item(&self, indices: &[usize]) -> Result<T, TorshError>
where T: Copy,

Get an element by multi-dimensional index

Source

pub fn set_item( &mut self, indices: &[usize], value: T, ) -> Result<(), TorshError>
where T: Copy,

Set an element by multi-dimensional index

Source

pub fn get_item_flat(&self, index: usize) -> Result<T, TorshError>
where T: Copy,

Get element by flat index

Source

pub fn set_item_flat( &mut self, index: usize, value: T, ) -> Result<(), TorshError>
where T: Copy,

Set element by flat index

Source

pub fn multi_to_flat_index( &self, indices: &[usize], ) -> Result<usize, TorshError>

Convert multi-dimensional indices to flat index

Source

pub fn gather( &self, dim: usize, indices: &Tensor<i64>, ) -> Result<Tensor<T>, TorshError>

Gather values along an axis using indices

Source

pub fn scatter( &self, dim: usize, indices: &Tensor<i64>, src: &Tensor<T>, ) -> Result<Tensor<T>, TorshError>

Scatter values along an axis using indices

Source

pub fn scatter_add( &self, dim: usize, indices: &Tensor<i64>, src: &Tensor<T>, ) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T>,

Scatter values along an axis using indices and add to existing values

§PyTorch Compatibility

Equivalent to torch.scatter_add(tensor, dim, index, src)

§Arguments
  • dim - Dimension along which to index
  • indices - Index tensor (same shape as src)
  • src - Source tensor containing values to add
§Examples
let tensor = Tensor::zeros(&[5], DeviceType::Cpu)?;
let indices = Tensor::from_data(vec![0i64, 1, 2, 0, 1], vec![5], DeviceType::Cpu)?;
let src = Tensor::from_data(vec![1.0f32, 2.0, 3.0, 4.0, 5.0], vec![5], DeviceType::Cpu)?;
let result = tensor.scatter_add(0, &indices, &src)?;
// result[0] += 1.0 + 4.0 = 5.0
// result[1] += 2.0 + 5.0 = 7.0
// result[2] += 3.0 = 3.0
Source

pub fn repeat(&self, repeats: &[usize]) -> Result<Tensor<T>, TorshError>

Repeat tensor along specified dimensions

Source

pub fn index_add( &self, dim: isize, index: &Tensor<i64>, source: &Tensor<T>, ) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T>,

Add values to tensor at specified indices along a dimension

§PyTorch Compatibility

Equivalent to torch.index_add(tensor, dim, index, source, alpha=1.0)

§Arguments
  • dim - Dimension along which to index
  • index - 1D tensor containing indices
  • source - Source tensor to add
§Examples
let tensor = Tensor::zeros(&[3, 5], DeviceType::Cpu)?;
let index = Tensor::from_data(vec![0i64, 2], vec![2], DeviceType::Cpu)?;
let source = Tensor::ones(&[2, 5], DeviceType::Cpu)?;
let result = tensor.index_add(0, &index, &source)?;
Source

pub fn index_copy( &self, dim: isize, index: &Tensor<i64>, source: &Tensor<T>, ) -> Result<Tensor<T>, TorshError>

Copy values from source to tensor at specified indices along a dimension

§PyTorch Compatibility

Equivalent to torch.index_copy(tensor, dim, index, source)

§Arguments
  • dim - Dimension along which to index
  • index - 1D tensor containing indices
  • source - Source tensor to copy from
§Examples
let tensor = Tensor::zeros(&[3, 5], DeviceType::Cpu)?;
let index = Tensor::from_data(vec![0i64, 2], vec![2], DeviceType::Cpu)?;
let source = Tensor::ones(&[2, 5], DeviceType::Cpu)?;
let result = tensor.index_copy(0, &index, &source)?;
Source

pub fn index_fill( &self, dim: isize, index: &Tensor<i64>, value: T, ) -> Result<Tensor<T>, TorshError>

Fill values in tensor at specified indices along a dimension

§PyTorch Compatibility

Equivalent to torch.index_fill(tensor, dim, index, value)

§Arguments
  • dim - Dimension along which to index
  • index - 1D tensor containing indices
  • value - Scalar value to fill
§Examples
let tensor = Tensor::zeros(&[3, 5], DeviceType::Cpu)?;
let index = Tensor::from_data(vec![0i64, 2], vec![2], DeviceType::Cpu)?;
let result = tensor.index_fill(0, &index, 3.14)?;
Source

pub fn put_( &self, indices: &Tensor<i64>, values: &Tensor<T>, ) -> Result<Tensor<T>, TorshError>

Place values at specified flat indices (in-place-like operation, returns new tensor)

§PyTorch Compatibility

Equivalent to torch.put_(tensor, indices, values) but returns new tensor

§Arguments
  • indices - 1D tensor of flat indices
  • values - 1D tensor of values (must match indices length or be broadcastable)
§Examples
let tensor = Tensor::zeros(&[3, 3], DeviceType::Cpu)?;  // [[0,0,0],[0,0,0],[0,0,0]]
let indices = Tensor::from_data(vec![0i64, 4, 8], vec![3], DeviceType::Cpu)?;
let values = Tensor::from_data(vec![1.0f32, 2.0, 3.0], vec![3], DeviceType::Cpu)?;
let result = tensor.put_(&indices, &values)?;  // [[1,0,0],[0,2,0],[0,0,3]]
Source

pub fn masked_scatter( &self, mask: &Tensor<bool>, source: &Tensor<T>, ) -> Result<Tensor<T>, TorshError>

Scatter values from source tensor where mask is true (PyTorch-compatible)

Copies values from the source tensor to positions where the mask is true. The mask must have the same shape as self. Source values are taken sequentially and placed at positions where mask is true.

§PyTorch Compatibility

Equivalent to torch.masked_scatter(tensor, mask, source)

§Arguments
  • mask - Boolean tensor with same shape as self
  • source - Tensor containing values to scatter (must have at least as many elements as true values in mask)
§Examples
let tensor = Tensor::zeros(&[3, 3], DeviceType::Cpu)?;
let mask = Tensor::from_data(
    vec![true, false, false, false, true, false, false, false, true],
    vec![3, 3],
    DeviceType::Cpu
)?;
let source = Tensor::from_data(vec![1.0f32, 2.0, 3.0], vec![3], DeviceType::Cpu)?;
let result = tensor.masked_scatter(&mask, &source)?;  // [[1,0,0],[0,2,0],[0,0,3]]
Source

pub fn index_put( &self, indices: &[Tensor<i64>], values: &Tensor<T>, ) -> Result<Tensor<T>, TorshError>

Multi-dimensional indexed put operation (PyTorch-compatible)

Places values from source tensor at positions specified by index tensors. Each index tensor specifies indices along one dimension. Index tensors must be broadcastable to the same shape.

§PyTorch Compatibility

Equivalent to torch.index_put(tensor, indices, values) where indices is a tuple of index tensors

§Arguments
  • indices - Slice of index tensors, one per dimension to index
  • values - Tensor of values to place (must broadcast to indexed positions)
§Examples
// 2D example: index_put a 3x3 matrix with row=[0,1] col=[1,2]
let tensor = Tensor::zeros(&[3, 3], DeviceType::Cpu)?;
let row_idx = Tensor::from_data(vec![0i64, 1], vec![2], DeviceType::Cpu)?;
let col_idx = Tensor::from_data(vec![1i64, 2], vec![2], DeviceType::Cpu)?;
let values = Tensor::from_data(vec![10.0f32, 20.0], vec![2], DeviceType::Cpu)?;
let result = tensor.index_put(&[row_idx, col_idx], &values)?;
// result[0,1] = 10.0, result[1,2] = 20.0
Source

pub fn scatter_reduce( &self, dim: usize, indices: &Tensor<i64>, src: &Tensor<T>, reduce: &str, ) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T> + Mul<Output = T> + Div<Output = T> + PartialOrd + FromPrimitive,

Scatter with reduction operation (PyTorch-compatible)

Generalized scatter operation that applies a reduction operation (sum, prod, mean, etc.) when scattering values to the same index position.

§PyTorch Compatibility

Equivalent to torch.scatter_reduce(tensor, dim, index, src, reduce)

§Arguments
  • dim - Dimension along which to scatter
  • indices - Index tensor specifying where to scatter values
  • src - Source tensor containing values to scatter
  • reduce - Reduction operation (“sum”, “prod”, “mean”, “amax”, “amin”)
§Examples
let tensor = Tensor::zeros(&[5], DeviceType::Cpu)?;
let indices = Tensor::from_data(vec![0i64, 1, 2, 0, 1], vec![5], DeviceType::Cpu)?;
let src = Tensor::from_data(vec![1.0f32, 2.0, 3.0, 4.0, 5.0], vec![5], DeviceType::Cpu)?;
let result = tensor.scatter_reduce(0, &indices, &src, "sum")?;
// result[0] = 1.0 + 4.0 = 5.0 (sum reduction)
// result[1] = 2.0 + 5.0 = 7.0
Source

pub fn diagonal_scatter( &self, src: &Tensor<T>, offset: isize, dim1: usize, dim2: usize, ) -> Result<Tensor<T>, TorshError>

Scatter values to the diagonal (PyTorch-compatible)

Embeds the values of src tensor into self along the diagonal elements, with respect to dim1 and dim2. The offset determines which diagonal to use.

§PyTorch Compatibility

Equivalent to torch.diagonal_scatter(tensor, src, offset, dim1, dim2)

§Arguments
  • src - Source tensor containing values for the diagonal
  • offset - Diagonal offset (0=main diagonal, >0=above, <0=below)
  • dim1 - First dimension (default: 0)
  • dim2 - Second dimension (default: 1)
§Examples
let tensor = Tensor::zeros(&[3, 3], DeviceType::Cpu)?;
let src = Tensor::from_data(vec![1.0f32, 2.0, 3.0], vec![3], DeviceType::Cpu)?;
let result = tensor.diagonal_scatter(&src, 0, 0, 1)?;
// result = [[1, 0, 0], [0, 2, 0], [0, 0, 3]]
Source

pub fn select_scatter( &self, src: &Tensor<T>, dim: isize, index: isize, ) -> Result<Tensor<T>, TorshError>

Scatter values to a selected slice along dimension (PyTorch-compatible)

Embeds the values of src tensor into self at the given index along dimension dim. This is the inverse of select() operation.

§PyTorch Compatibility

Equivalent to torch.select_scatter(tensor, src, dim, index)

§Arguments
  • src - Source tensor to scatter (shape should match self with dim removed)
  • dim - Dimension along which to select
  • index - Index position to scatter to
§Examples
let tensor = Tensor::zeros(&[3, 4, 5], DeviceType::Cpu)?;
let src = Tensor::ones(&[3, 5], DeviceType::Cpu)?; // dim=1 removed
let result = tensor.select_scatter(&src, 1, 2)?;
// result[:, 2, :] = src
Source

pub fn slice_scatter( &self, src: &Tensor<T>, dim: isize, start: Option<isize>, end: Option<isize>, step: usize, ) -> Result<Tensor<T>, TorshError>

Scatter values to a slice along dimension (PyTorch-compatible)

Embeds the values of src tensor into self along dimension dim, starting at start index, ending at end index, with the given step.

§PyTorch Compatibility

Equivalent to torch.slice_scatter(tensor, src, dim, start, end, step)

§Arguments
  • src - Source tensor to scatter
  • dim - Dimension along which to slice
  • start - Starting index (None means 0)
  • end - Ending index (None means size of dim)
  • step - Step size (default: 1)
§Examples
let tensor = Tensor::zeros(&[5, 5], DeviceType::Cpu)?;
let src = Tensor::ones(&[2, 5], DeviceType::Cpu)?;
let result = tensor.slice_scatter(&src, 0, Some(1), Some(3), 1)?;
// result[1:3, :] = src
Source§

impl<T> Tensor<T>
where T: TensorElement + Copy + Default,

Source

pub fn stack(tensors: &[Tensor<T>], dim: isize) -> Result<Tensor<T>, TorshError>

Stack tensors along a new dimension

§PyTorch Compatibility

Equivalent to torch.stack(tensors, dim)

§Arguments
  • tensors - Sequence of tensors to stack
  • dim - Dimension along which to stack
§Examples
let a = Tensor::from_data(vec![1.0, 2.0], vec![2], DeviceType::Cpu)?;
let b = Tensor::from_data(vec![3.0, 4.0], vec![2], DeviceType::Cpu)?;
let result = Tensor::stack(&[a, b], 0)?; // shape: [2, 2]
Source

pub fn chunk( &self, chunks: usize, dim: isize, ) -> Result<Vec<Tensor<T>>, TorshError>

Split tensor into chunks

§PyTorch Compatibility

Equivalent to torch.chunk(tensor, chunks, dim)

Source

pub fn split( &self, split_size: usize, dim: isize, ) -> Result<Vec<Tensor<T>>, TorshError>

Split tensor into parts of given size

§PyTorch Compatibility

Equivalent to torch.split(tensor, split_size, dim)

Source

pub fn flip(&self, dims: &[isize]) -> Result<Tensor<T>, TorshError>

Flip tensor along given dimensions

§PyTorch Compatibility

Equivalent to torch.flip(tensor, dims)

Source

pub fn fliplr(&self) -> Result<Tensor<T>, TorshError>

Flip tensor left-right (last dimension)

§PyTorch Compatibility

Equivalent to torch.fliplr(tensor)

Source

pub fn flipud(&self) -> Result<Tensor<T>, TorshError>

Flip tensor up-down (first dimension)

§PyTorch Compatibility

Equivalent to torch.flipud(tensor)

Source

pub fn roll( &self, shifts: &[isize], dims: &[isize], ) -> Result<Tensor<T>, TorshError>

Roll tensor elements along given dimensions

§PyTorch Compatibility

Equivalent to torch.roll(tensor, shifts, dims)

Source

pub fn rot90(&self, k: isize, dims: &[isize]) -> Result<Tensor<T>, TorshError>

Rotate tensor 90 degrees

§PyTorch Compatibility

Equivalent to torch.rot90(tensor, k, dims)

Source

pub fn tile(&self, repeats: &[usize]) -> Result<Tensor<T>, TorshError>

Tile tensor by repeating

§PyTorch Compatibility

Equivalent to torch.tile(tensor, repeats)

Source

pub fn repeat_interleave( &self, repeats: usize, dim: Option<isize>, ) -> Result<Tensor<T>, TorshError>

Repeat elements of a tensor along a dimension

§PyTorch Compatibility

Equivalent to torch.repeat_interleave(tensor, repeats, dim)

§Arguments
  • repeats - Number of times to repeat each element
  • dim - Dimension along which to repeat (None = flatten first)
§Examples
let x = Tensor::from_data(vec![1.0, 2.0, 3.0], vec![3], DeviceType::Cpu)?;
let y = x.repeat_interleave(2, None)?; // [1.0, 1.0, 2.0, 2.0, 3.0, 3.0]
Source

pub fn unflatten( &self, dim: isize, sizes: &[usize], ) -> Result<Tensor<T>, TorshError>

Unflatten a dimension into multiple dimensions

§PyTorch Compatibility

Equivalent to torch.unflatten(tensor, dim, sizes)

§Arguments
  • dim - Dimension to unflatten
  • sizes - Target sizes for the unflattened dimensions
§Examples
let x = Tensor::from_data(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0], vec![6], DeviceType::Cpu)?;
let y = x.unflatten(0, &[2, 3])?; // Shape becomes [2, 3]
Source

pub fn take_along_dim( &self, indices: &Tensor<i64>, dim: Option<isize>, ) -> Result<Tensor<T>, TorshError>

Gather values along a dimension using indices

§PyTorch Compatibility

Equivalent to torch.take_along_dim(tensor, indices, dim)

§Arguments
  • indices - Indices to gather
  • dim - Dimension along which to gather (None = flatten first)
§Examples
let x = Tensor::from_data(vec![1.0, 2.0, 3.0, 4.0], vec![4], DeviceType::Cpu)?;
let indices = Tensor::from_data(vec![0i64, 2], vec![2], DeviceType::Cpu)?;
let y = x.take_along_dim(&indices, None)?; // [1.0, 3.0]
Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn add_scalar_(&mut self, scalar: T) -> Result<(), TorshError>
where T: Copy + Add<Output = T>,

Add scalar to all elements in-place

Source

pub fn add_scalar(&self, scalar: T) -> Result<Tensor<T>, TorshError>
where T: Copy + Add<Output = T>,

Add scalar to all elements (returns new tensor)

Source

pub fn sub_scalar_(&mut self, scalar: T) -> Result<(), TorshError>
where T: Copy + Sub<Output = T>,

Subtract scalar from all elements in-place

Source

pub fn sub_scalar(&self, scalar: T) -> Result<Tensor<T>, TorshError>
where T: Copy + Sub<Output = T>,

Subtract scalar from all elements (returns new tensor)

Source

pub fn mul_scalar_(&mut self, scalar: T) -> Result<(), TorshError>
where T: Copy + Mul<Output = T>,

Multiply all elements by scalar in-place

Source

pub fn mul_scalar(&self, scalar: T) -> Result<Tensor<T>, TorshError>
where T: Copy + Mul<Output = T>,

Multiply all elements by scalar (returns new tensor)

Source

pub fn div_scalar_(&mut self, scalar: T) -> Result<(), TorshError>
where T: Copy + Div<Output = T>,

Divide all elements by scalar in-place

Source

pub fn div_scalar(&self, scalar: T) -> Result<Tensor<T>, TorshError>
where T: Copy + Div<Output = T>,

Divide all elements by scalar (returns new tensor)

Source

pub fn add(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T>,

Element-wise addition with another tensor (supports broadcasting)

Source

pub fn sub(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Sub<Output = T>,

Element-wise subtraction with another tensor

Source

pub fn mul(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Mul<Output = T>,

Element-wise multiplication with another tensor

Source

pub fn div(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Div<Output = T>,

Element-wise division with another tensor

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn add_(&mut self, other: &Tensor<T>) -> Result<&mut Tensor<T>, TorshError>
where T: Add<Output = T>,

Element-wise in-place addition: self += other.

For f32 tensors with ≥ 1024 elements and matching shapes, this routes through the SIMD-backed simd_ops_f32::add_assign_f32 without any additional allocation.

§Errors

Returns an error if requires_grad is true (autograd cannot be tracked through in-place mutations).

Source

pub fn sub_(&mut self, other: &Tensor<T>) -> Result<&mut Tensor<T>, TorshError>
where T: Sub<Output = T>,

Element-wise in-place subtraction: self -= other.

For f32 tensors with ≥ 1024 elements and matching shapes, this routes through simd_ops_f32::sub_assign_f32.

Source

pub fn mul_(&mut self, other: &Tensor<T>) -> Result<&mut Tensor<T>, TorshError>
where T: Mul<Output = T>,

Element-wise in-place multiplication: self *= other.

For f32 tensors with ≥ 1024 elements and matching shapes, this routes through simd_ops_f32::mul_assign_f32.

Source

pub fn div_(&mut self, other: &Tensor<T>) -> Result<&mut Tensor<T>, TorshError>
where T: Div<Output = T>,

Element-wise in-place division: self /= other.

For f32 tensors with ≥ 1024 elements and matching shapes, this routes through simd_ops_f32::div_assign_f32.

Source§

impl<T> Tensor<T>

Source

pub fn sqrt(&self) -> Result<Tensor<T>, TorshError>

Square root of all elements

Source

pub fn square(&self) -> Result<Tensor<T>, TorshError>

Square of all elements

Source

pub fn rsqrt(&self) -> Result<Tensor<T>, TorshError>

Reciprocal square root of all elements (1/sqrt(x))

Source

pub fn reciprocal(&self) -> Result<Tensor<T>, TorshError>

Reciprocal of all elements (1/x)

Source

pub fn exp(&self) -> Result<Tensor<T>, TorshError>

Exponential of all elements

Source

pub fn ln(&self) -> Result<Tensor<T>, TorshError>

Natural logarithm of all elements

Source

pub fn log10(&self) -> Result<Tensor<T>, TorshError>

Logarithm base 10 of all elements

Source

pub fn log2(&self) -> Result<Tensor<T>, TorshError>

Logarithm base 2 of all elements

Source

pub fn log(&self) -> Result<Tensor<T>, TorshError>

Natural logarithm of all elements

Source

pub fn sin(&self) -> Result<Tensor<T>, TorshError>

Sine of all elements

Source

pub fn cos(&self) -> Result<Tensor<T>, TorshError>

Cosine of all elements

Source

pub fn tan(&self) -> Result<Tensor<T>, TorshError>

Tangent of all elements

Source

pub fn gelu(&self) -> Result<Tensor<T>, TorshError>

GELU (Gaussian Error Linear Unit) activation function with GPU and SIMD optimization

Source

pub fn leaky_relu(&self, negative_slope: T) -> Result<Tensor<T>, TorshError>

Leaky ReLU activation function with negative slope

Source

pub fn asin(&self) -> Result<Tensor<T>, TorshError>

Arcsine of all elements

Source

pub fn acos(&self) -> Result<Tensor<T>, TorshError>

Arccosine of all elements

Source

pub fn atan(&self) -> Result<Tensor<T>, TorshError>

Arctangent of all elements

Source

pub fn sinh(&self) -> Result<Tensor<T>, TorshError>

Hyperbolic sine of all elements

Source

pub fn cosh(&self) -> Result<Tensor<T>, TorshError>

Hyperbolic cosine of all elements

Source

pub fn tanh(&self) -> Result<Tensor<T>, TorshError>

Hyperbolic tangent of all elements

Source

pub fn pow(&self, exponent: T) -> Result<Tensor<T>, TorshError>
where T: TensorElement + Into<f32>,

Power function (element-wise)

Source

pub fn pow_scalar(&self, exponent: T) -> Result<Tensor<T>, TorshError>
where T: TensorElement + Into<f32>,

Power function with scalar exponent (alias for pow)

Source

pub fn pow_tensor(&self, exponent: &Tensor<T>) -> Result<Tensor<T>, TorshError>

Power function with tensor exponents

Source

pub fn floor(&self) -> Result<Tensor<T>, TorshError>

Floor of all elements

Source

pub fn ceil(&self) -> Result<Tensor<T>, TorshError>

Ceiling of all elements

Source

pub fn round(&self) -> Result<Tensor<T>, TorshError>

Round to nearest integer

Source

pub fn trunc(&self) -> Result<Tensor<T>, TorshError>

Truncate to integer part

Source

pub fn fract(&self) -> Result<Tensor<T>, TorshError>

Fractional part

Source

pub fn neg(&self) -> Result<Tensor<T>, TorshError>
where T: Neg<Output = T>,

Negation of all elements

Source

pub fn sign(&self) -> Result<Tensor<T>, TorshError>

Sign of all elements (-1, 0, or 1)

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn add_op(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T>,

Add operation (used by autograd backward pass)

Source

pub fn mul_op(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Mul<Output = T>,

Multiply operation (used by autograd backward pass)

Source

pub fn sigmoid(&self) -> Result<Tensor<T>, TorshError>
where T: FloatElement,

Sigmoid activation function with SIMD optimization

Source

pub fn relu(&self) -> Result<Tensor<T>, TorshError>
where T: PartialOrd + Zero,

ReLU activation function (Rectified Linear Unit) with SIMD optimization

Source

pub fn minimum(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: PartialOrd,

Element-wise minimum with another tensor

Source

pub fn maximum(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: PartialOrd,

Element-wise maximum with another tensor

Source

pub fn clamp(&self, min: T, max: T) -> Result<Tensor<T>, TorshError>
where T: PartialOrd + Copy,

Clamp tensor values between min and max bounds

Source

pub fn dot(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Mul<Output = T> + Add<Output = T> + Zero,

Dot product with another tensor (for 1D tensors)

Source§

impl<T> Tensor<T>

Source

pub fn add_scirs2(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Add<Output = T> + Float,

Use SciRS2 backend for optimized tensor addition

Source

pub fn mul_scirs2(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Mul<Output = T> + Float,

Use SciRS2 backend for optimized tensor multiplication

Source

pub fn sub_scirs2(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Sub<Output = T> + Float,

Use SciRS2 backend for optimized tensor subtraction

Source

pub fn div_scirs2(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: Div<Output = T> + Float,

Use SciRS2 backend for optimized tensor division

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy + Float,

Source

pub fn add_simd(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: SimdUnifiedOps,

Element-wise addition with SIMD acceleration (SciRS2)

Uses real hardware SIMD instructions (AVX2/NEON) via scirs2_core::simd_ops::SimdUnifiedOps

Source

pub fn mul_simd(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>
where T: SimdUnifiedOps,

Element-wise multiplication with SIMD acceleration (SciRS2)

Uses real hardware SIMD instructions (AVX2/NEON) via scirs2_core::simd_ops::SimdUnifiedOps

Source

pub fn dot_simd(&self, other: &Tensor<T>) -> Result<T, TorshError>
where T: SimdUnifiedOps,

Dot product with SIMD acceleration (SciRS2)

Uses real hardware SIMD instructions (AVX2/NEON) via scirs2_core::simd_ops::SimdUnifiedOps

Returns a scalar value (sum of element-wise products)

Source

pub fn reduce_memory_efficient<F>(&self, func: F) -> Result<T, TorshError>
where F: Fn(T, T) -> T + Send + Sync,

Memory-efficient reduction using SciRS2 intelligent chunking and lazy evaluation

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy + Mul<Output = T>,

Source

pub fn relu_(&mut self) -> Result<&mut Tensor<T>, TorshError>
where T: PartialOrd + Zero,

In-place ReLU activation: self = max(0, self)

§PyTorch Compatibility

Equivalent to PyTorch’s tensor.relu_()

§Errors
  • Returns error if requires_grad is true
Source

pub fn sigmoid_(&mut self) -> Result<&mut Tensor<T>, TorshError>
where T: FloatElement,

In-place sigmoid activation: self = 1 / (1 + exp(-self))

§PyTorch Compatibility

Equivalent to PyTorch’s tensor.sigmoid_()

Source

pub fn tanh_(&mut self) -> Result<&mut Tensor<T>, TorshError>
where T: FloatElement,

In-place tanh activation: self = tanh(self)

§PyTorch Compatibility

Equivalent to PyTorch’s tensor.tanh_()

Source

pub fn gelu_(&mut self) -> Result<&mut Tensor<T>, TorshError>
where T: FloatElement,

In-place GELU activation

§PyTorch Compatibility

Equivalent to PyTorch’s tensor.gelu_()

Source

pub fn leaky_relu_( &mut self, negative_slope: T, ) -> Result<&mut Tensor<T>, TorshError>
where T: PartialOrd + Zero,

In-place leaky ReLU activation

§PyTorch Compatibility

Equivalent to PyTorch’s tensor.leaky_relu_(negative_slope)

Source

pub fn clamp_(&mut self, min: T, max: T) -> Result<&mut Tensor<T>, TorshError>
where T: PartialOrd,

In-place clamp operation: self = clamp(self, min, max)

§PyTorch Compatibility

Equivalent to PyTorch’s tensor.clamp_(min, max)

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn size(&self, dim: i32) -> Result<usize, TorshError>

Get size of a specific dimension

Source

pub fn view(&self, shape: &[i32]) -> Result<Tensor<T>, TorshError>

Reshapes the tensor to a new shape (creates a view or copy if needed).

This is equivalent to PyTorch’s view() operation. The total number of elements must remain the same. You can use -1 for one dimension to have it inferred automatically.

§Arguments
  • shape - The new shape as a slice of dimensions. Use -1 to infer one dimension.
§Returns

A reshaped tensor, or an error if the reshape is invalid.

§Examples
use torsh_tensor::creation::zeros;

// Reshape a 1D tensor to 2D
let t = zeros::<f32>(&[6]).expect("tensor creation should succeed");
let reshaped = t.view(&[2, 3]).expect("view should succeed");
assert_eq!(reshaped.shape().dims(), &[2, 3]);

// Use -1 to infer a dimension
let t2 = zeros::<f32>(&[12]).expect("tensor creation should succeed");
let auto = t2.view(&[-1, 4]).expect("view should succeed");  // Infers 3 for first dimension
assert_eq!(auto.shape().dims(), &[3, 4]);

// Flatten to 1D
let matrix = zeros::<f32>(&[3, 4, 5]).expect("tensor creation should succeed");
let flat = matrix.view(&[-1]).expect("view should succeed");
assert_eq!(flat.shape().dims(), &[60]);
§Errors

Returns an error if:

  • More than one dimension is -1
  • The total number of elements doesn’t match
  • Any dimension would overflow
§See Also
Source

pub fn view_as(&self, shape: &[usize]) -> Result<Tensor<T>, TorshError>

Create an efficient view with different shape (shares data, no copying) This is the zero-copy version of view() for compatible shapes

Source

pub fn slice_tensor( &self, dim: usize, start: usize, end: usize, ) -> Result<Tensor<T>, TorshError>

Create a view of a slice along a dimension (shares data, no copying)

Source

pub fn transpose_view( &self, dim0: usize, dim1: usize, ) -> Result<Tensor<T>, TorshError>

Create a transposed view (shares data, no copying)

Source

pub fn squeeze_tensor(&self, dim: usize) -> Result<Tensor<T>, TorshError>

Squeeze a tensor along a specific dimension (removes dimension of size 1)

Source

pub fn unsqueeze_tensor(&self, dim: usize) -> Result<Tensor<T>, TorshError>

Unsqueeze a tensor at a specific dimension (adds dimension of size 1)

Source

pub fn transpose(&self, dim0: i32, dim1: i32) -> Result<Tensor<T>, TorshError>

Transposes two dimensions of the tensor.

Swaps the specified dimensions, creating a new tensor. For 2D tensors, calling transpose(0, 1) produces the standard matrix transpose operation.

§Arguments
  • dim0 - The first dimension to swap. Negative values count from the end.
  • dim1 - The second dimension to swap. Negative values count from the end.
§Returns

A tensor with the specified dimensions transposed.

§Examples
use torsh_tensor::creation::{zeros, arange};

// Standard matrix transpose
let matrix = zeros::<f32>(&[3, 4]).expect("tensor creation should succeed");
let transposed = matrix.transpose(0, 1).expect("transpose should succeed");
assert_eq!(transposed.shape().dims(), &[4, 3]);

// Transpose in 3D tensor
let cube = zeros::<f32>(&[2, 3, 4]).expect("tensor creation should succeed");
let swapped = cube.transpose(0, 2).expect("transpose should succeed");
assert_eq!(swapped.shape().dims(), &[4, 3, 2]);

// Use negative indexing
let t = zeros::<f32>(&[5, 6, 7]).expect("tensor creation should succeed");
let result = t.transpose(-2, -1).expect("transpose should succeed");
assert_eq!(result.shape().dims(), &[5, 7, 6]);

// Practical use: convert between row-major and column-major
let data = arange(0, 12, 1).expect("arange should succeed");
let row_major = data.reshape(&[3, 4]).expect("reshape should succeed");
let col_major = row_major.transpose(0, 1).expect("transpose should succeed");
§See Also
Source

pub fn permute(&self, dims: &[i32]) -> Result<Tensor<T>, TorshError>

Permute dimensions according to the given order

Source

pub fn squeeze(&self, dim: i32) -> Result<Tensor<T>, TorshError>

Removes a dimension of size 1 at the specified position.

This operation reduces the dimensionality of the tensor by removing dimensions that have size 1. Commonly used to remove singleton dimensions after reductions or to match tensor shapes for operations.

§Arguments
  • dim - The dimension to squeeze. Negative values count from the end.
§Returns

A tensor with the specified dimension removed, or an error if the dimension doesn’t have size 1.

§Examples
use torsh_tensor::creation::zeros;

// Remove a singleton dimension
let t = zeros::<f32>(&[3, 1, 4]).expect("tensor creation should succeed");
let squeezed = t.squeeze(1).expect("squeeze should succeed");
assert_eq!(squeezed.shape().dims(), &[3, 4]);

// Use negative indexing
let t2 = zeros::<f32>(&[2, 3, 1]).expect("tensor creation should succeed");
let squeezed2 = t2.squeeze(-1).expect("squeeze should succeed");
assert_eq!(squeezed2.shape().dims(), &[2, 3]);

// After a reduction operation
let matrix = zeros::<f32>(&[5, 10]).expect("tensor creation should succeed");
let reduced = matrix.sum_dim(&[1], true).expect("sum_dim should succeed");  // Shape: [5, 1]
let final_result = reduced.squeeze(1).expect("squeeze should succeed");  // Shape: [5]
§See Also
Source

pub fn squeeze_all(&self) -> Result<Tensor<T>, TorshError>

Squeeze all dimensions with size 1

Source

pub fn unsqueeze(&self, dim: i32) -> Result<Tensor<T>, TorshError>

Adds a dimension of size 1 at the specified position.

This operation increases the dimensionality of the tensor by inserting a new dimension of size 1. Commonly used to add batch dimensions or to match tensor shapes for broadcasting operations.

§Arguments
  • dim - The position to insert the new dimension. Negative values count from the end.
§Returns

A tensor with an additional dimension of size 1 inserted.

§Examples
use torsh_tensor::creation::zeros;

// Add a batch dimension at the beginning
let t = zeros::<f32>(&[3, 4]).expect("tensor creation should succeed");
let batched = t.unsqueeze(0).expect("unsqueeze should succeed");
assert_eq!(batched.shape().dims(), &[1, 3, 4]);

// Add a dimension at the end
let t2 = zeros::<f32>(&[5]).expect("tensor creation should succeed");
let expanded = t2.unsqueeze(-1).expect("unsqueeze should succeed");
assert_eq!(expanded.shape().dims(), &[5, 1]);

// Prepare for broadcasting
let weights = zeros::<f32>(&[64]).expect("tensor creation should succeed");
let weights_2d = weights.unsqueeze(0).expect("unsqueeze should succeed");  // Shape: [1, 64]
// Now can broadcast with shape [batch_size, 64]
§See Also
Source

pub fn reshape(&self, shape: &[i32]) -> Result<Tensor<T>, TorshError>

Reshapes the tensor to a new shape.

This is an alias for view() and provides the same functionality. The total number of elements must remain the same.

§Arguments
  • shape - The new shape as a slice of dimensions. Use -1 to infer one dimension.
§Returns

A reshaped tensor, or an error if the reshape is invalid.

§Examples
use torsh_tensor::creation::arange;

// Reshape a sequence to a matrix
let t = arange(0, 12, 1).expect("arange should succeed");
let matrix = t.reshape(&[3, 4]).expect("reshape should succeed");
assert_eq!(matrix.shape().dims(), &[3, 4]);

// Reshape with automatic dimension inference
let cube = t.reshape(&[2, -1, 3]).expect("reshape should succeed");  // Infers 2 for middle dimension
assert_eq!(cube.shape().dims(), &[2, 2, 3]);
§See Also
Source

pub fn is_contiguous(&self) -> bool

Check if tensor is contiguous in memory

Source

pub fn contiguous(&self) -> Result<Tensor<T>, TorshError>

Make tensor contiguous if it isn’t already

Source

pub fn expand(&self, shape: &[usize]) -> Result<Tensor<T>, TorshError>

Expand tensor to a larger size

Source

pub fn movedim( &self, source: &[isize], destination: &[isize], ) -> Result<Tensor<T>, TorshError>

Move dimensions from source positions to destination positions

§PyTorch Compatibility

Equivalent to torch.movedim(tensor, source, destination)

§Arguments
  • source - Original positions of dimensions to move
  • destination - Target positions for the dimensions
§Examples
let x = Tensor::from_data(vec![1.0; 24], vec![2, 3, 4], DeviceType::Cpu)?;
let y = x.movedim(&[0, 1], &[2, 0])?; // [2,3,4] -> [3,4,2]
Source

pub fn moveaxis( &self, source: &[isize], destination: &[isize], ) -> Result<Tensor<T>, TorshError>

Move axis from source position to destination position (alias for movedim)

§PyTorch Compatibility

Equivalent to torch.moveaxis(tensor, source, destination)

§Arguments
  • source - Original positions of axes to move
  • destination - Target positions for the axes
Source

pub fn swapaxes( &self, axis0: isize, axis1: isize, ) -> Result<Tensor<T>, TorshError>

Swap two dimensions

§PyTorch Compatibility

Equivalent to torch.swapaxes(tensor, axis0, axis1) or torch.swapdims(tensor, dim0, dim1)

§Arguments
  • axis0 - First dimension
  • axis1 - Second dimension
§Examples
let x = Tensor::from_data(vec![1.0; 12], vec![2, 3, 2], DeviceType::Cpu)?;
let y = x.swapaxes(0, 2)?; // [2,3,2] -> [2,3,2] with dims 0 and 2 swapped
Source

pub fn swapdims( &self, dim0: isize, dim1: isize, ) -> Result<Tensor<T>, TorshError>

Swap two dimensions (alias for swapaxes)

§PyTorch Compatibility

Equivalent to torch.swapdims(tensor, dim0, dim1)

Source

pub fn broadcast_to(&self, shape: &[usize]) -> Result<Tensor<T>, TorshError>

Broadcast tensor to a new shape

§PyTorch Compatibility

Equivalent to torch.broadcast_to(tensor, shape)

§Arguments
  • shape - Target shape for broadcasting
§Examples
let x = Tensor::from_data(vec![1.0, 2.0], vec![2], DeviceType::Cpu)?;
let y = x.broadcast_to(&[3, 2])?; // Broadcast [2] to [3, 2]
Source

pub fn expand_as(&self, other: &Tensor<T>) -> Result<Tensor<T>, TorshError>

Expand tensor to match another tensor’s shape

§PyTorch Compatibility

Equivalent to torch.expand_as(tensor, other)

§Arguments
  • other - Target tensor whose shape to match
§Examples
let x = Tensor::from_data(vec![1.0, 2.0], vec![2], DeviceType::Cpu)?;
let y = Tensor::from_data(vec![0.0; 6], vec![3, 2], DeviceType::Cpu)?;
let z = x.expand_as(&y)?; // Expand x to match y's shape [3, 2]
Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn to_device( &self, target_device: DeviceType, ) -> Result<Tensor<T>, TorshError>

Transfer tensor to another device with optimization

Source

pub fn synchronize_devices( &self, devices: &[DeviceType], ) -> Result<(), TorshError>

Synchronize operations across devices

Source

pub fn can_transfer_efficiently(&self, target_device: DeviceType) -> bool

Check if tensor can be efficiently transferred to target device

Source

pub fn get_transfer_strategy( &self, target_device: DeviceType, ) -> TransferStrategy

Get optimal transfer strategy for device pair

Source§

impl Tensor<bf16>

Specialized bf16 arithmetic operations with proper rounding

Source

pub fn add_with_rounding( &self, other: &Tensor<bf16>, mode: BF16RoundingMode, ) -> Result<Tensor<bf16>, TorshError>

Add two bf16 tensors with specified rounding mode

Source

pub fn mul_with_rounding( &self, other: &Tensor<bf16>, mode: BF16RoundingMode, ) -> Result<Tensor<bf16>, TorshError>

Multiply two bf16 tensors with specified rounding mode

Source

pub fn fma_with_rounding( &self, other: &Tensor<bf16>, addend: &Tensor<bf16>, mode: BF16RoundingMode, ) -> Result<Tensor<bf16>, TorshError>

Fused multiply-add with proper bf16 rounding

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn optimize_cache_layout(&mut self) -> Result<(), TorshError>

Memory layout optimization for cache efficiency Analyzes and optimizes the tensor’s memory layout to improve cache performance

Source

pub fn analyze_cache_performance(&self) -> CacheAnalysisReport

Analyze memory access patterns and provide optimization recommendations

Source

pub fn to_cache_optimized(&self) -> Result<Tensor<T>, TorshError>

Create a cache-optimized copy of the tensor

Source

pub fn memory_stats(&self) -> MemoryStats

Get memory usage statistics for the tensor

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy + Default,

Source

pub fn optimize_memory_layout( &mut self, numa_hint: Option<NumaAllocationHint>, ) -> Result<(), TorshError>

Advanced memory optimization with NUMA awareness

Source

pub fn create_memory_mapped_optimized( data: Vec<T>, shape: Vec<usize>, numa_hint: Option<NumaAllocationHint>, ) -> Result<Tensor<T>, TorshError>

Memory-mapped tensor creation with optimization hints

Source

pub fn prefetch_data(&self) -> Result<(), TorshError>

Prefetch memory pages for better performance

Source§

impl<T> Tensor<T>
where T: FloatElement,

Source

pub fn conv1d( &self, weight: &Tensor<T>, bias: Option<&Tensor<T>>, stride: usize, padding: usize, dilation: usize, groups: usize, ) -> Result<Tensor<T>, TorshError>

1D convolution operation

Source

pub fn conv2d( &self, weight: &Tensor<T>, bias: Option<&Tensor<T>>, stride: (usize, usize), padding: (usize, usize), dilation: (usize, usize), groups: usize, ) -> Result<Tensor<T>, TorshError>

2D convolution operation

Source

pub fn conv3d( &self, weight: &Tensor<T>, bias: Option<&Tensor<T>>, stride: (usize, usize, usize), padding: (usize, usize, usize), dilation: (usize, usize, usize), groups: usize, ) -> Result<Tensor<T>, TorshError>

3D convolution operation

Source

pub fn depthwise_conv2d( &self, weight: &Tensor<T>, bias: Option<&Tensor<T>>, stride: (usize, usize), padding: (usize, usize), dilation: (usize, usize), ) -> Result<Tensor<T>, TorshError>

Depthwise 2D convolution operation Each input channel is convolved with its own kernel independently

Source

pub fn separable_conv2d( &self, depthwise_weight: &Tensor<T>, pointwise_weight: &Tensor<T>, bias: Option<&Tensor<T>>, stride: (usize, usize), padding: (usize, usize), dilation: (usize, usize), ) -> Result<Tensor<T>, TorshError>

Separable 2D convolution operation Factorized into depthwise convolution followed by pointwise (1x1) convolution

Source

pub fn conv_transpose2d( &self, weight: &Tensor<T>, bias: Option<&Tensor<T>>, stride: (usize, usize), padding: (usize, usize), output_padding: (usize, usize), dilation: (usize, usize), groups: usize, ) -> Result<Tensor<T>, TorshError>

Transposed (deconvolution) 2D convolution operation

Source

pub fn xcorr1d( &self, other: &Tensor<T>, mode: CorrelationMode, ) -> Result<Tensor<T>, TorshError>

1D cross-correlation operation Computes the cross-correlation between two 1D signals

Source

pub fn autocorr1d( &self, max_lag: Option<usize>, ) -> Result<Tensor<T>, TorshError>

1D auto-correlation operation Computes the auto-correlation of a 1D signal

Source

pub fn xcorr2d( &self, other: &Tensor<T>, mode: CorrelationMode, ) -> Result<Tensor<T>, TorshError>

2D cross-correlation operation Computes the 2D cross-correlation between two signals

Source

pub fn median_filter1d( &self, window_size: usize, ) -> Result<Tensor<T>, TorshError>

1D median filter Applies a median filter with the specified window size

Source

pub fn median_filter2d( &self, window_size: (usize, usize), ) -> Result<Tensor<T>, TorshError>

2D median filter Applies a 2D median filter with the specified window size

Source

pub fn gaussian_filter1d( &self, sigma: f32, kernel_size: Option<usize>, ) -> Result<Tensor<T>, TorshError>

1D Gaussian filter Applies a Gaussian filter with specified sigma (standard deviation)

Source

pub fn gaussian_filter2d( &self, sigma: (f32, f32), kernel_size: Option<(usize, usize)>, ) -> Result<Tensor<T>, TorshError>

2D Gaussian filter Applies a 2D Gaussian filter with specified sigma values

Source§

impl<T> Tensor<T>
where T: TensorElement,

Indexing implementation

Source

pub fn index(&self, indices: &[TensorIndex]) -> Result<Tensor<T>, TorshError>

Index into the tensor

Source

pub fn get_1d(&self, index: usize) -> Result<T, TorshError>

Get a single element (1D indexing)

Source

pub fn get_2d(&self, row: usize, col: usize) -> Result<T, TorshError>

Get a single element (2D indexing)

Source

pub fn get_3d(&self, x: usize, y: usize, z: usize) -> Result<T, TorshError>

Get a single element (3D indexing)

Source

pub fn set_1d(&mut self, index: usize, value: T) -> Result<(), TorshError>

Set a single element (1D indexing)

Source

pub fn set_2d( &mut self, row: usize, col: usize, value: T, ) -> Result<(), TorshError>

Set a single element (2D indexing)

Source

pub fn set_3d( &mut self, x: usize, y: usize, z: usize, value: T, ) -> Result<(), TorshError>

Set a single element (3D indexing)

Source

pub fn select(&self, dim: i32, index: i64) -> Result<Tensor<T>, TorshError>

Select along a dimension

Source

pub fn slice_with_step( &self, dim: i32, start: Option<i64>, end: Option<i64>, step: Option<i64>, ) -> Result<Tensor<T>, TorshError>

Slice along a dimension with PyTorch-style parameters

Source

pub fn narrow( &self, dim: i32, start: i64, length: usize, ) -> Result<Tensor<T>, TorshError>

Narrow along a dimension

Source

pub fn masked_select( &self, mask: &Tensor<bool>, ) -> Result<Tensor<T>, TorshError>

Boolean indexing (masking)

Source

pub fn take(&self, indices: &Tensor<i64>) -> Result<Tensor<T>, TorshError>

Source

pub fn put( &self, indices: &Tensor<i64>, values: &Tensor<T>, ) -> Result<Tensor<T>, TorshError>

Put values at indices

Source

pub fn index_select( &self, dim: i32, index: &Tensor<i64>, ) -> Result<Tensor<T>, TorshError>

Select indices along a dimension

Source§

impl<T> Tensor<T>
where T: TensorElement,

Convenient indexing syntax

Source

pub fn index_with_list( &self, dim: i32, indices: &[i64], ) -> Result<Tensor<T>, TorshError>

Advanced indexing with list of indices (fancy indexing)

Source

pub fn index_with_mask( &self, dim: i32, mask: &Tensor<bool>, ) -> Result<Tensor<T>, TorshError>

Boolean mask indexing for a specific dimension

Source

pub fn mask_select(&self, mask: &Tensor<bool>) -> Result<Tensor<T>, TorshError>

Global boolean mask indexing (flattens to 1D result)

Source

pub fn where_condition<F>( &self, condition: F, ) -> Result<Tensor<bool>, TorshError>
where F: Fn(&T) -> bool, T: Clone,

Create boolean mask from condition

Source

pub fn scatter_indexed( &self, dim: i32, index: &Tensor<i64>, src: &Tensor<T>, ) -> Result<Tensor<T>, TorshError>

Scatter values along an axis using indices (indexing version)

Source§

impl<T> Tensor<T>
where T: TensorElement,

✅ Enhanced Tensor creation interface with SciRS2 memory optimization

Source

pub fn create_efficient( shape: &[usize], device: DeviceType, ) -> Result<Tensor<T>, TorshError>
where T: Clone + Default,

Create memory-efficient tensor with automatic strategy selection

Source

pub fn lazy( shape: &[usize], device: DeviceType, ) -> Result<Tensor<T>, TorshError>
where T: Clone + Default,

Create lazy tensor that defers allocation until first access

Source

pub fn memory_mapped( shape: &[usize], device: DeviceType, ) -> Result<Tensor<T>, TorshError>
where T: Clone + Default,

Create zero-copy view of existing tensor (disabled due to conflict with shape_ops) ✅ SciRS2 Memory-Mapped Tensor for very large datasets

Source

pub fn chunked( shape: &[usize], chunk_size: usize, device: DeviceType, ) -> Result<Tensor<T>, TorshError>
where T: Clone + Default,

✅ SciRS2 Chunked Tensor for cache-efficient large data processing

Creates a tensor optimized for chunk-wise processing with the specified chunk size. This is useful for large tensors that benefit from cache-friendly access patterns.

§Arguments
  • shape - The shape of the tensor
  • chunk_size - Preferred chunk size for processing (in elements)
  • device - Device to allocate the tensor on
Source

pub fn disk_backed( shape: &[usize], device: DeviceType, file_path: Option<&str>, ) -> Result<Tensor<T>, TorshError>
where T: Clone + Default,

✅ SciRS2 Disk-Backed Tensor for datasets larger than RAM

Creates a tensor that can be backed by disk storage for large datasets. This is useful when working with datasets larger than available RAM.

§Arguments
  • shape - The shape of the tensor
  • device - Device to allocate the tensor on
  • file_path - Optional file path for persistent storage. If None, uses temporary file.
§Note

Current implementation creates an in-memory tensor. Full memory-mapped file support requires the mmap-support feature and will be used automatically when available.

Source

pub fn process_chunked<F, R>( &self, chunk_size: usize, processor: F, ) -> Result<Vec<R>, TorshError>
where F: FnMut(&[T]) -> Result<R, TorshError>, T: Clone,

Process tensor in memory-efficient chunks

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy + Default,

Convenient functions for creating pooled tensors

Source

pub fn pooled( shape: &[usize], device: DeviceType, ) -> Result<PooledTensor<T>, TorshError>

Create a tensor using the memory pool

Source

pub fn temporary( shape: &[usize], device: DeviceType, ) -> Result<PooledTensor<T>, TorshError>

Create temporary tensor for intermediate calculations

Source§

impl<T> Tensor<T>

NaN/Inf detection utilities for tensors

Source

pub fn has_nan_inf(&self) -> bool

Quick check if tensor contains any NaN or infinite values (optimized fast path)

This is the fastest check - it returns true if any issues are found, false if the tensor is clean. No detailed information is provided.

§Examples
let clean = Tensor::from_data(vec![1.0, 2.0, 3.0], vec![3], DeviceType::Cpu).expect("tensor creation should succeed");
assert!(!clean.has_nan_inf());

let dirty = Tensor::from_data(vec![1.0, f32::NAN, 3.0], vec![3], DeviceType::Cpu).expect("tensor creation should succeed");
assert!(dirty.has_nan_inf());
Source

pub fn has_nan(&self) -> bool

Check for NaN values only

Source

pub fn has_inf(&self) -> bool

Check for infinite values only

Source

pub fn count_nan_inf(&self) -> NanInfStats

Count NaN and infinite values

Source

pub fn check_nan_inf_with_config(&self, config: &NanInfConfig) -> NanInfReport

Comprehensive NaN/Inf detection with detailed reporting

§Examples
let tensor = Tensor::from_data(
    vec![1.0, f32::NAN, f32::INFINITY, -f32::INFINITY],
    vec![4],
    DeviceType::Cpu
).expect("tensor creation should succeed");

let config = NanInfConfig::detailed();
let report = tensor.check_nan_inf_with_config(&config);

assert_eq!(report.stats.nan_count, 1);
assert_eq!(report.stats.pos_inf_count, 1);
assert_eq!(report.stats.neg_inf_count, 1);
assert_eq!(report.locations.len(), 3);
Source

pub fn assert_finite(&self)

Assert that tensor contains no NaN or infinite values

§Panics

Panics if any NaN or infinite values are found

§Examples
let tensor = Tensor::from_data(vec![1.0, 2.0, 3.0], vec![3], DeviceType::Cpu).expect("tensor creation should succeed");
tensor.assert_finite(); // OK

// This would panic:
// let bad = Tensor::from_data(vec![1.0, f32::NAN], vec![2], DeviceType::Cpu).expect("tensor creation should succeed");
// bad.assert_finite(); // Panics!
Source

pub fn replace_nan_inf( &self, nan_replacement: T, pos_inf_replacement: T, neg_inf_replacement: T, ) -> Result<Tensor<T>, TorshError>

Replace NaN and infinite values with specified replacements

§Examples
let mut tensor = Tensor::from_data(
    vec![1.0, f32::NAN, f32::INFINITY, -f32::INFINITY],
    vec![4],
    DeviceType::Cpu
).expect("tensor creation should succeed");

let cleaned = tensor.replace_nan_inf(0.0, 1e6, -1e6).expect("replace_nan_inf should succeed");
assert!(!cleaned.has_nan_inf());
Source

pub fn nan_inf_mask(&self) -> Result<Tensor<bool>, TorshError>

Create a boolean mask indicating locations of NaN/Inf values

§Examples
let tensor = Tensor::from_data(
    vec![1.0, f32::NAN, 3.0, f32::INFINITY],
    vec![4],
    DeviceType::Cpu
).expect("tensor creation should succeed");

let mask = tensor.nan_inf_mask().expect("nan_inf_mask should succeed");
let mask_data = mask.to_vec().expect("to_vec conversion should succeed");
assert_eq!(mask_data, vec![false, true, false, true]);
Source§

impl<T> Tensor<T>
where T: TensorElement + Into<f64> + From<f64>,

FFT operations for tensors

Source

pub fn fft(&self) -> Result<Tensor<Complex<f64>>, TorshError>

Compute 1D FFT along the last dimension

Source

pub fn fft_with_plan( &self, plan: Option<&FFTPlan>, ) -> Result<Tensor<Complex<f64>>, TorshError>

Compute 1D FFT with a precomputed plan

Source

pub fn ifft(&self) -> Result<Tensor<T>, TorshError>
where T: TensorElement + From<f64>,

Compute 1D inverse FFT along the last dimension

Source

pub fn fft2(&self) -> Result<Tensor<Complex<f64>>, TorshError>

Compute 2D FFT on the last two dimensions

Source

pub fn ifft2(&self) -> Result<Tensor<T>, TorshError>
where T: TensorElement + From<f64>,

Compute 2D inverse FFT on the last two dimensions

Source

pub fn fft_along_dim_real( &self, dim: usize, ) -> Result<Tensor<Complex<f64>>, TorshError>

Compute FFT along a specific dimension for real tensors

Source

pub fn rfft(&self) -> Result<Tensor<Complex<f64>>, TorshError>

Real-to-complex FFT (more efficient for real inputs)

Source

pub fn irfft(&self, output_size: Option<usize>) -> Result<Tensor<T>, TorshError>
where T: TensorElement + From<f64>,

Complex-to-real inverse FFT

Source

pub fn power_spectrum(&self) -> Result<Tensor<T>, TorshError>
where T: TensorElement + From<f64>,

Compute power spectral density

Source

pub fn magnitude_spectrum(&self) -> Result<Tensor<T>, TorshError>
where T: TensorElement + From<f64>,

Compute magnitude spectrum

Source

pub fn phase_spectrum(&self) -> Result<Tensor<T>, TorshError>
where T: TensorElement + From<f64>,

Compute phase spectrum

Source§

impl<T> Tensor<T>
where T: TensorElement,

This impl block contains no public items.

General tensor operations that don’t require Into

Source§

impl Tensor<Complex<f64>>

Operations specific to complex tensors

Source

pub fn from_complex_data( data: Vec<Complex<f64>>, shape: Vec<usize>, device: DeviceType, ) -> Result<Tensor<Complex<f64>>, TorshError>

Create tensor from complex data

Source

pub fn to_real<T>(&self) -> Result<Tensor<T>, TorshError>
where T: TensorElement + From<f64>,

Convert complex tensor to real by taking the real part

Source

pub fn power_spectrum_from_fft<T>(&self) -> Result<Tensor<T>, TorshError>
where T: TensorElement + From<f64>,

Compute power spectrum from FFT result

Source

pub fn magnitude_spectrum_from_fft<T>(&self) -> Result<Tensor<T>, TorshError>
where T: TensorElement + From<f64>,

Compute magnitude spectrum from FFT result

Source

pub fn phase_spectrum_from_fft<T>(&self) -> Result<Tensor<T>, TorshError>
where T: TensorElement + From<f64>,

Compute phase spectrum from FFT result

Source

pub fn fft_complex(&self) -> Result<Tensor<Complex<f64>>, TorshError>

Compute FFT for complex data

Source

pub fn ifft_complex(&self) -> Result<Tensor<Complex<f64>>, TorshError>

Compute inverse FFT for complex data

Source

pub fn ifft2_complex(&self) -> Result<Tensor<Complex<f64>>, TorshError>

Compute 2D inverse FFT for complex data

Source

pub fn ifft_along_dim( &self, dim: usize, ) -> Result<Tensor<Complex<f64>>, TorshError>

Compute inverse FFT along a specific dimension

Source

pub fn fft2_complex(&self) -> Result<Tensor<Complex<f64>>, TorshError>

2D FFT for complex tensors

Source

pub fn fft_along_dim( &self, dim: usize, ) -> Result<Tensor<Complex<f64>>, TorshError>

Compute FFT along a specific dimension for complex tensors

Source

pub fn fft_along_dim_complex( &self, dim: usize, ) -> Result<Tensor<Complex<f64>>, TorshError>

Internal implementation of FFT along dimension for complex tensors

Source

pub fn slice_last_dim_complex( &self, start: usize, size: usize, ) -> Result<Tensor<Complex<f64>>, TorshError>

Slice along the last dimension for complex tensors

Source§

impl<T> Tensor<T>
where T: Default + Add<Output = T> + AddAssign + Sub<Output = T> + TensorElement + Mul<Output = T> + FloatElement<Output = T> + MulAssign + Div + Copy + PartialOrd + FromPrimitive + Sum,

Statistical operations for tensors

Source

pub fn mean_stats( &self, dims: Option<&[usize]>, keepdim: bool, ) -> Result<Tensor<T>, TorshError>

Compute mean along specified dimensions (legacy stats implementation)

Source

pub fn var( &self, dims: Option<&[usize]>, keepdim: bool, mode: StatMode, ) -> Result<Tensor<T>, TorshError>

Compute variance along specified dimensions

Source

pub fn std( &self, dims: Option<&[usize]>, keepdim: bool, mode: StatMode, ) -> Result<Tensor<T>, TorshError>

Compute standard deviation along specified dimensions

Source

pub fn percentile( &self, q: f64, dim: Option<usize>, _keepdim: bool, ) -> Result<Tensor<T>, TorshError>

Compute percentile along the last dimension

Source

pub fn median( &self, dim: Option<usize>, keepdim: bool, ) -> Result<Tensor<T>, TorshError>

Compute median (50th percentile)

Source

pub fn quantile( &self, q: &[f64], dim: Option<usize>, keepdim: bool, ) -> Result<Vec<Tensor<T>>, TorshError>

Compute quantiles at specified levels

Source

pub fn histogram( &self, config: &HistogramConfig, ) -> Result<Histogram, TorshError>

Create histogram of tensor values

Source

pub fn correlation( &self, other: &Tensor<T>, method: CorrelationMethod, ) -> Result<T, TorshError>

Compute correlation coefficient with another tensor

Source

pub fn describe(&self) -> Result<StatSummary, TorshError>

Generate comprehensive statistical summary

Source

pub fn cov(&self, mode: StatMode) -> Result<Tensor<T>, TorshError>

Compute covariance matrix for 2D tensor (each column is a variable)

Source

pub fn corrcoef(&self) -> Result<Tensor<T>, TorshError>

Compute correlation matrix for 2D tensor

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Source

pub fn calculate_strides(&self) -> Vec<usize>

Calculate strides for current tensor shape

Source

pub fn create_view( &self, new_shape: &[usize], ) -> Result<TensorView<T>, TorshError>

Create a view of this tensor with a new shape (must have same number of elements)

Source

pub fn view_with_strides( &self, new_shape: &[usize], strides: &[usize], ) -> Result<TensorView<T>, TorshError>

Create a view with custom strides (advanced usage)

Source

pub fn slice( &self, dim: usize, start: usize, end: usize, ) -> Result<TensorView<T>, TorshError>

Create a slice view of the tensor along a specific dimension

Source

pub fn alias(&self) -> TensorAlias<T>

Create an alias (shared reference) to this tensor

Source

pub fn alias_mut(&mut self) -> TensorAlias<T>

Create a mutable alias to this tensor

Source§

impl Tensor

f32 tensor conversions with SIMD optimization

Source

pub fn to_f64_simd(&self) -> Result<Tensor<f64>, TorshError>

Convert to f64 tensor with SIMD optimization

Source

pub fn to_i32_simd(&self) -> Result<Tensor<i32>, TorshError>

Convert to i32 tensor with SIMD optimization (with bounds checking)

Source§

impl Tensor<i32>

i32 tensor conversions with SIMD optimization

Source

pub fn to_f32_simd(&self) -> Result<Tensor, TorshError>

Convert to f32 tensor with SIMD optimization

Source

pub fn to_f64_simd(&self) -> Result<Tensor<f64>, TorshError>

Convert to f64 tensor with SIMD optimization

Source

pub fn to_i64_simd(&self) -> Result<Tensor<i64>, TorshError>

Convert to i64 tensor with SIMD optimization

Source§

impl Tensor<i64>

i64 tensor conversions with SIMD optimization

Source

pub fn to_f32_simd(&self) -> Result<Tensor, TorshError>

Convert to f32 tensor with SIMD optimization

Source

pub fn to_f64_simd(&self) -> Result<Tensor<f64>, TorshError>

Convert to f64 tensor with SIMD optimization

Source

pub fn to_i32_simd(&self) -> Result<Tensor<i32>, TorshError>

Convert to i32 tensor with SIMD optimization (with bounds checking)

Source§

impl Tensor<f64>

f64 tensor conversions with SIMD optimization

Source

pub fn to_f32_simd(&self) -> Result<Tensor, TorshError>

Convert to f32 tensor with SIMD optimization

Source§

impl<T> Tensor<T>
where T: TensorElement + Copy,

Generic SIMD conversion implementations

Source

pub fn convert_with_optimal_simd<U>(&self) -> Result<Tensor<U>, TorshError>
where U: TensorElement + Copy + From<T>,

Convert tensor using optimal SIMD strategy for this system

Source

pub fn convert_with_strategy<U>( &self, strategy: SIMDStrategy, ) -> Result<Tensor<U>, TorshError>
where U: TensorElement + Copy + From<T>,

Convert tensor using specific SIMD strategy

Source§

impl<T> Tensor<T>
where T: TensorElement,

Source

pub fn from_vec(data: Vec<T>, shape: &[usize]) -> Result<Tensor<T>, TorshError>
where T: Copy,

Create from vec with shape (convenience method)

Trait Implementations§

Source§

impl<T> Add for &Tensor<T>
where T: TensorElement + Copy + Add<Output = T>,

Source§

type Output = Tensor<T>

The resulting type after applying the + operator.
Source§

fn add(self, rhs: &Tensor<T>) -> <&Tensor<T> as Add>::Output

Performs the + operation. Read more
Source§

impl BFloat16TensorOps<bf16> for Tensor<bf16>

Source§

fn to_bf16_with_rounding( &self, _mode: BF16RoundingMode, ) -> Result<Tensor<bf16>, TorshError>

Convert tensor to bf16 with specified rounding mode
Source§

fn to_f32(&self) -> Result<Tensor, TorshError>

Convert from bf16 tensor to higher precision
Source§

fn bf16_high_precision_op<F>(&self, op: F) -> Result<Tensor<bf16>, TorshError>
where F: Fn(&Tensor) -> Result<Tensor, TorshError>,

Perform operation in higher precision then round back to bf16
Source§

impl BFloat16TensorOps<f32> for Tensor

Source§

fn to_bf16_with_rounding( &self, mode: BF16RoundingMode, ) -> Result<Tensor<bf16>, TorshError>

Convert tensor to bf16 with specified rounding mode
Source§

fn to_f32(&self) -> Result<Tensor, TorshError>

Convert from bf16 tensor to higher precision
Source§

fn bf16_high_precision_op<F>(&self, op: F) -> Result<Tensor<bf16>, TorshError>
where F: Fn(&Tensor) -> Result<Tensor, TorshError>,

Perform operation in higher precision then round back to bf16
Source§

impl<T> Clone for Tensor<T>
where T: Clone + TensorElement,

Source§

fn clone(&self) -> Tensor<T>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T> Debug for Tensor<T>
where T: TensorElement,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl<T> Div for &Tensor<T>
where T: TensorElement + Copy + Div<Output = T>,

Source§

type Output = Tensor<T>

The resulting type after applying the / operator.
Source§

fn div(self, rhs: &Tensor<T>) -> <&Tensor<T> as Div>::Output

Performs the / operation. Read more
Source§

impl<T> Mul for &Tensor<T>
where T: TensorElement + Copy + Mul<Output = T>,

Source§

type Output = Tensor<T>

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Tensor<T>) -> <&Tensor<T> as Mul>::Output

Performs the * operation. Read more
Source§

impl<T> Neg for &Tensor<T>
where T: TensorElement + Copy + Neg<Output = T>,

Source§

type Output = Tensor<T>

The resulting type after applying the - operator.
Source§

fn neg(self) -> <&Tensor<T> as Neg>::Output

Performs the unary - operation. Read more
Source§

impl<T> Sub for &Tensor<T>
where T: TensorElement + Copy + Sub<Output = T>,

Source§

type Output = Tensor<T>

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: &Tensor<T>) -> <&Tensor<T> as Sub>::Output

Performs the - operation. Read more
Source§

impl<T> TensorConvenience<T> for Tensor<T>

Source§

fn T(&self) -> Result<Tensor<T>, TorshError>

Transpose shortcut (equivalent to .transpose()) Read more
Source§

fn mT(&self) -> Result<Tensor<T>, TorshError>

Matrix transpose (alias for .T())
Source§

fn H(&self) -> Result<Tensor<T>, TorshError>

Hermitian transpose (conjugate transpose for complex numbers)
Source§

fn t(&self) -> Result<Tensor<T>, TorshError>

Transpose shortcut (snake_case version)
Source§

fn m_t(&self) -> Result<Tensor<T>, TorshError>

Matrix transpose (snake_case version)
Source§

fn h(&self) -> Result<Tensor<T>, TorshError>

Hermitian transpose (snake_case version)
Source§

fn detach(&self) -> Tensor<T>

Detach tensor from computational graph (creates a new tensor without gradients)
Source§

fn clone_tensor(&self) -> Result<Tensor<T>, TorshError>

Clone tensor data (creates a deep copy)
Source§

fn is_contiguous(&self) -> bool

Check if tensor is contiguous in memory
Source§

fn contiguous(&self) -> Result<Tensor<T>, TorshError>

Make tensor contiguous (reorganize memory layout)
Source§

fn numel(&self) -> usize

Get number of elements in tensor
Source§

fn size(&self) -> Vec<usize>

Get tensor size (alias for shape().dims())
Source§

fn is_empty(&self) -> bool

Check if tensor is empty (has zero elements)
Source§

fn is_scalar(&self) -> bool

Check if tensor is scalar (zero dimensions)
Source§

fn item(&self) -> T

Get tensor item as scalar (only works for scalar tensors)
Source§

fn to_scalar(&self) -> Result<T, TorshError>

Convert tensor to scalar (squeezes all dimensions of size 1 first)
Source§

impl<T> TensorCustomOps<T> for Tensor<T>
where T: TensorElement + 'static,

Source§

fn apply_custom_op( &self, op_name: &str, other_inputs: &[&Tensor<T>], params: &OperationParams, ) -> Result<Vec<Tensor<T>>, TorshError>

Apply a custom operation to this tensor Read more
Source§

fn apply_custom_op_with_registry( &self, registry: &CustomOperationRegistry, op_name: &str, other_inputs: &[&Tensor<T>], params: &OperationParams, ) -> Result<Vec<Tensor<T>>, TorshError>

Apply a custom operation using a specific registry
Source§

impl<T> TensorExprExt<T> for Tensor<T>
where T: TensorElement + Copy,

Source§

fn expr(&self) -> Result<ExprBuilder<T, TensorExpr<'_, T>>, TorshError>

Convert the tensor to an expression builder
Source§

impl<T> TensorExpressionOps<T> for Tensor<T>
where T: TensorElement,

Source§

fn build_expression_graph(&self) -> ExpressionGraph

Build an expression graph from tensor operations
Source§

fn optimize_expressions( &self, config: OptimizerConfig, ) -> Result<OptimizationStats, TorshError>

Optimize tensor expressions using the expression optimizer
Source§

impl<T> TensorFluentExt<T> for Tensor<T>
where T: TensorElement,

Source§

fn fluent(self) -> FluentTensor<T>

Start fluent chaining
Source§

impl<T> TensorManipulationExt<T> for Tensor<T>
where T: TensorElement + Copy,

Source§

fn squeeze_all(&self) -> Result<Tensor<T>, TorshError>

Squeeze all dimensions of size 1
Source§

fn squeeze_dims(&self, dims: &[i32]) -> Result<Tensor<T>, TorshError>

Squeeze specific dimensions
Source§

fn unsqueeze_dims(&self, dims: &[i32]) -> Result<Tensor<T>, TorshError>

Unsqueeze at multiple positions
Source§

fn add_batch_dim(&self) -> Result<Tensor<T>, TorshError>

Add a batch dimension at the front
Source§

fn remove_batch_dim(&self) -> Result<Tensor<T>, TorshError>

Remove the batch dimension (first dimension)
Source§

fn atleast_nd(&self, n: usize) -> Result<Tensor<T>, TorshError>

Ensure tensor has at least N dimensions (add trailing dimensions)
Source§

fn to_channel_last(&self) -> Result<Tensor<T>, TorshError>

Transpose to channel-last format (NCHW -> NHWC)
Source§

fn to_channel_first(&self) -> Result<Tensor<T>, TorshError>

Transpose to channel-first format (NHWC -> NCHW)
Source§

fn swap_dims(&self, dim0: i32, dim1: i32) -> Result<Tensor<T>, TorshError>

Swap two dimensions
Source§

fn move_dim(&self, src: i32, dst: i32) -> Result<Tensor<T>, TorshError>

Move a dimension to a new position
Source§

fn expand_to(&self, target_shape: &[usize]) -> Result<Tensor<T>, TorshError>

Expand singleton dimensions to match target shape
Source§

fn repeat_along( &self, dim: i32, repeats: usize, ) -> Result<Tensor<T>, TorshError>

Repeat tensor along new dimension
Source§

impl<T> TensorShapeConvenience<T> for Tensor<T>
where T: TensorElement + Copy,

Source§

fn unsqueeze_at(&self, dim: i32) -> Result<Tensor<T>, TorshError>

Add singleton dimension at specified position
Source§

fn squeeze_all(&self) -> Result<Tensor<T>, TorshError>

Remove all singleton dimensions
Source§

fn flatten(&self) -> Result<Tensor<T>, TorshError>

Flatten tensor to 1D (preserving total number of elements)
Source§

fn flatten_from(&self, start_dim: i32) -> Result<Tensor<T>, TorshError>

Flatten tensor starting from specified dimension
Source§

fn unflatten(&self, dim: i32, sizes: &[usize]) -> Result<Tensor<T>, TorshError>

Unflatten tensor back to specified shape

Auto Trait Implementations§

§

impl<T = f32> !Freeze for Tensor<T>

§

impl<T> RefUnwindSafe for Tensor<T>
where T: RefUnwindSafe,

§

impl<T> Send for Tensor<T>

§

impl<T> Sync for Tensor<T>

§

impl<T> Unpin for Tensor<T>

§

impl<T> UnsafeUnpin for Tensor<T>

§

impl<T> UnwindSafe for Tensor<T>
where T: RefUnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V