Skip to main content

TracedTensor

Struct TracedTensor 

Source
pub struct TracedTensor {
    pub id: TracedTensorId,
    pub rank: usize,
    pub dtype: DType,
    pub fragment: Arc<Fragment<StdTensorOp>>,
    pub val: LocalValId,
    pub data: Option<Arc<Tensor>>,
    /* private fields */
}

Fields§

§id: TracedTensorId§rank: usize§dtype: DType§fragment: Arc<Fragment<StdTensorOp>>§val: LocalValId§data: Option<Arc<Tensor>>

Implementations§

Source§

impl TracedTensor

Source

pub fn from_tensor_concrete_shape(tensor: Tensor) -> Self

Build a TracedTensor leaf from a concrete Tensor, keeping its shape as a concrete shape_hint.

This is the common constructor when you have concrete tensor data that you want to use both for graph building and for evaluation. The resulting tensor is treated as a concrete-shape leaf by downstream passes (binary einsum decomposition, build-time reshape folding, etc.).

§Examples
use tenferro::{Tensor, TracedTensor};

let a = TracedTensor::from_tensor_concrete_shape(
    Tensor::from_vec(vec![2, 3], vec![1.0_f64, 2.0, 3.0, 4.0, 5.0, 6.0]),
);
assert_eq!(a.rank, 2);
assert!(a.is_concrete_shape());
Source

pub fn from_tensor_symbolic_shape(tensor: Tensor) -> Self

Build a TracedTensor leaf from a concrete Tensor but advertise a symbolic shape during graph construction.

The tensor data is still attached (so plain eval works without bindings), but graph passes see the leaf as shape-symbolic. This is useful for building a single traced program that should not bake in shape-specific optimizations — e.g. mixing a known-shape tensor into an einsum with other input_symbolic_shape placeholders forces the einsum to be kept as a single NaryEinsum op rather than decomposing at build time.

§Examples
use tenferro::{Tensor, TracedTensor};

let t = TracedTensor::from_tensor_symbolic_shape(
    Tensor::from_vec(vec![2, 3], vec![1.0_f64, 2.0, 3.0, 4.0, 5.0, 6.0]),
);
assert_eq!(t.rank, 2);
assert!(!t.is_concrete_shape());
Source

pub fn input_concrete_shape(dtype: DType, shape: &[usize]) -> Self

Build a data-less placeholder leaf with a fixed (concrete) shape.

Must be bound via TracedTensor::eval_with_inputs before evaluation. Use this when you know the exact shape of the input but want to build the graph once and feed different concrete tensors at eval time.

§Examples
use tenferro_tensor::DType;
use tenferro::TracedTensor;

let x = TracedTensor::input_concrete_shape(DType::F64, &[2, 3]);
assert_eq!(x.rank, 2);
assert!(x.is_concrete_shape());
Source

pub fn input_symbolic_shape(dtype: DType, rank: usize) -> Self

Build a data-less placeholder leaf with the given rank but fully symbolic shape (every dim is a distinct SymDim::TensorAxis).

Must be bound via TracedTensor::eval_with_inputs before evaluation. Use this to build shape-agnostic graphs — in particular, einsum calls containing at least one input_symbolic_shape input are kept as a single NaryEinsum op so the contraction path can be optimized at eval time against the actual bound shapes.

§Examples
use tenferro_tensor::DType;
use tenferro::TracedTensor;

let x = TracedTensor::input_symbolic_shape(DType::F64, 2);
assert_eq!(x.rank, 2);
assert!(!x.is_concrete_shape());
Source

pub fn from_vec<T: TensorScalar>(shape: Vec<usize>, data: Vec<T>) -> Self

Build a concrete-shape TracedTensor leaf from typed Vec<T> data. Equivalent to TracedTensor::from_tensor_concrete_shape(Tensor::from_vec(shape, data)).

§Examples
use tenferro::TracedTensor;

let a = TracedTensor::from_vec(vec![2, 3], vec![1.0_f64, 2.0, 3.0, 4.0, 5.0, 6.0]);
assert_eq!(a.rank, 2);
Source

pub fn is_concrete_shape(&self) -> bool

Returns true iff every dim of this tensor’s shape_hint is a constant SymDim (i.e. the shape is fully known at graph-build time).

§Examples
use tenferro_tensor::DType;
use tenferro::TracedTensor;

let a = TracedTensor::from_vec(vec![2, 3], vec![1.0_f64; 6]);
let b = TracedTensor::input_symbolic_shape(DType::F64, 2);
assert!(a.is_concrete_shape());
assert!(!b.is_concrete_shape());
Source

pub fn input_key(&self) -> Option<TensorInputKey>

If this TracedTensor is a leaf (single-node input fragment), return its input key. Computed tensors return None.

Source

pub fn eval<B: TensorBackend>( &mut self, engine: &mut Engine<B>, ) -> Result<&Tensor>

Source

pub fn eval_with_inputs<B: TensorBackend>( &mut self, engine: &mut Engine<B>, bindings: &[(&TracedTensor, &Tensor)], ) -> Result<&Tensor>

Evaluate this traced tensor, binding external tensors to any placeholder leaves present in the graph.

Each (placeholder, tensor) pair maps a placeholder TracedTensor (built via TracedTensor::input_concrete_shape or TracedTensor::input_symbolic_shape) to the concrete Tensor that should take its place during execution. Leaves that carry their own data (from TracedTensor::from_vec, TracedTensor::from_tensor_concrete_shape, or TracedTensor::from_tensor_symbolic_shape) must not appear in bindings.

§Errors
§Examples
use tenferro::{CpuBackend, Engine, Tensor, TracedTensor};
use tenferro_tensor::DType;

let mut engine = Engine::new(CpuBackend::new());
let x = TracedTensor::input_symbolic_shape(DType::F64, 1);
let mut y = &x + &x;
let concrete = Tensor::from_vec(vec![3], vec![1.0_f64, 2.0, 3.0]);
let out = y.eval_with_inputs(&mut engine, &[(&x, &concrete)]).unwrap();
assert_eq!(out.shape(), &[3]);
Source

pub fn grad(&self, wrt: &TracedTensor) -> Result<TracedTensor>

Source

pub fn try_grad(&self, wrt: &TracedTensor) -> Result<Option<TracedTensor>>

Like grad but returns None when the scalar output does not depend on wrt.

§Examples
let maybe_dx = loss.try_grad(&x)?;
Source

pub fn checkpoint<B: TensorBackend>( &mut self, engine: &mut Engine<B>, ) -> Result<()>

Evaluate this tensor and replace its graph with a concrete leaf.

This keeps downstream forward evaluation rooted at the concrete value while retaining the original fragment chain for later reverse-mode AD.

§Examples
use tenferro::{CpuBackend, Engine, TracedTensor};

let mut engine = Engine::new(CpuBackend::new());
let x = TracedTensor::from_vec(vec![], vec![3.0_f64]);
let mut y = &x * &x;
y.checkpoint(&mut engine).unwrap();
assert_eq!(y.eval(&mut engine).unwrap().shape(), &[] as &[usize]);
Source

pub fn jvp(&self, wrt: &TracedTensor, tangent: &TracedTensor) -> TracedTensor

Source

pub fn try_jvp( &self, wrt: &TracedTensor, tangent: &TracedTensor, ) -> Option<TracedTensor>

Like jvp but returns None when the output does not depend on wrt (i.e. the tangent is structurally zero).

Source

pub fn vjp(&self, wrt: &TracedTensor, cotangent: &TracedTensor) -> TracedTensor

Source

pub fn add(&self, other: &TracedTensor) -> TracedTensor

Elementwise addition with NumPy-style broadcasting.

Prefer using the + operator when it reads naturally.

§Examples
let y = x.add(&z);
let y2 = &x + &z;
Source

pub fn mul(&self, other: &TracedTensor) -> TracedTensor

Elementwise multiplication with NumPy-style broadcasting.

Prefer using the * operator when it reads naturally.

§Examples
let y = x.mul(&z);
let y2 = &x * &z;
Source

pub fn div(&self, other: &TracedTensor) -> TracedTensor

Elementwise division with NumPy-style broadcasting.

Prefer using the / operator when it reads naturally.

§Examples
let y = x.div(&z);
let y2 = &x / &z;
Source

pub fn neg(&self) -> TracedTensor

Elementwise negation.

Prefer using the unary - operator when it reads naturally.

§Examples
let y = x.neg();
let y2 = -&x;
Source

pub fn conj(&self) -> TracedTensor

Elementwise complex conjugate.

§Examples
let y = x.conj();
Source

pub fn abs(&self) -> TracedTensor

Elementwise absolute value.

§Examples
let y = x.abs();
Source

pub fn sign(&self) -> TracedTensor

Elementwise sign.

§Examples
let y = x.sign();
Source

pub fn scale_real(&self, factor: f64) -> TracedTensor

Scale by a real scalar: y = factor * x.

§Examples
let y = x.scale_real(2.0);
Source

pub fn scale_complex(&self, factor: Complex64) -> TracedTensor

Scale by a complex scalar: y = factor * x.

This currently supports complex tensors only. For real scaling, prefer scale_real.

§Examples
use num_complex::Complex64;
let y = x.scale_complex(Complex64::new(0.0, 1.0)); // multiply by i
Source

pub fn exp(&self) -> TracedTensor

Elementwise exponential.

§Examples
let y = x.exp();
Source

pub fn log(&self) -> TracedTensor

Elementwise natural logarithm.

§Examples
let y = x.log();
Source

pub fn sin(&self) -> TracedTensor

Elementwise sine.

§Examples
let y = x.sin();
Source

pub fn cos(&self) -> TracedTensor

Elementwise cosine.

§Examples
let y = x.cos();
Source

pub fn tanh(&self) -> TracedTensor

Elementwise hyperbolic tangent.

§Examples
let y = x.tanh();
Source

pub fn sqrt(&self) -> TracedTensor

Elementwise square root.

§Examples
let y = x.sqrt();
Source

pub fn rsqrt(&self) -> TracedTensor

Elementwise reciprocal square root.

§Examples
let y = x.rsqrt();
Source

pub fn pow(&self, other: &TracedTensor) -> TracedTensor

Elementwise power with NumPy-style broadcasting.

§Examples
let y = base.pow(&exp);
Source

pub fn expm1(&self) -> TracedTensor

Elementwise exp(x) - 1.

§Examples
let y = x.expm1();
Source

pub fn log1p(&self) -> TracedTensor

Elementwise log(1 + x).

§Examples
let y = x.log1p();
Source

pub fn convert(&self, to: DType) -> TracedTensor

Convert the tensor to a different dtype.

For real-to-complex conversions this embeds the real values as x + 0i. For complex-to-real conversions this extracts the real part.

§Examples
use tenferro::DType;

let y = x.convert(DType::C64);
Source

pub fn dot_general( &self, other: &TracedTensor, config: DotGeneralConfig, ) -> TracedTensor

Generalized tensor contraction.

§Examples
let y = a.dot_general(&b, config);
Source

pub fn reduce_sum(&self, axes: &[usize]) -> TracedTensor

Sum over the given axes.

§Examples
let y = x.reduce_sum(&[0]);
let y2 = x.sum(&[0]);
Source

pub fn reshape(&self, shape: &[usize]) -> TracedTensor

Reshape without changing element order.

§Examples
let y = x.reshape(&[2, 2]);
Source

pub fn sym_size(&self, axis: usize) -> SymDim

Return a symbolic expression for the size of one axis.

§Examples
let rows = x.sym_size(0);
let cols = x.sym_size(1);
let y = x.reshape_sym(&[rows * cols])?;
Source

pub fn reshape_sym(&self, shape: &[SymDim]) -> Result<TracedTensor>

Reshape using symbolic dimensions derived from traced tensor axes.

§Examples
let rows = x.sym_size(0);
let cols = x.sym_size(1);
let y = x.reshape_sym(&[rows * cols])?;
Source

pub fn broadcast_in_dim(&self, shape: &[usize], dims: &[usize]) -> TracedTensor

Broadcast into a larger shape with explicit dimension placement.

§Examples
let y = x.broadcast_in_dim(&[2, 3], &[1]);
let y2 = x.broadcast(&[2, 3], &[1]);
Source

pub fn transpose(&self, perm: &[usize]) -> TracedTensor

Permute tensor axes.

§Examples
let y = x.transpose(&[1, 0]);
Source

pub fn extract_diag(&self, axis_a: usize, axis_b: usize) -> TracedTensor

Extract the diagonal along two axes.

§Examples
let y = x.extract_diag(0, 1);
Source

pub fn embed_diag(&self, axis_a: usize, axis_b: usize) -> TracedTensor

Embed a vector or lower-rank tensor along a diagonal.

§Examples
let y = x.embed_diag(0, 1);
Source

pub fn sum(&self, axes: &[usize]) -> TracedTensor

Alias for Self::reduce_sum.

§Examples
let y = x.sum(&[0]);
Source

pub fn broadcast(&self, shape: &[usize], dims: &[usize]) -> TracedTensor

Alias for Self::broadcast_in_dim.

§Examples
let y = x.broadcast(&[2, 3], &[1]);
Source

pub fn shape_of(&self, axis: usize) -> TracedTensor

Return the runtime size of one axis as a scalar f64 tensor.

The result is metadata-derived and therefore has no gradient.

§Examples
use tenferro::{CpuBackend, Engine, TracedTensor};

let mut engine = Engine::new(CpuBackend::new());
let x = TracedTensor::from_vec(vec![2, 3], vec![1.0_f64, 2.0, 3.0, 4.0, 5.0, 6.0]);
let mut cols = x.shape_of(1);
assert_eq!(cols.eval(&mut engine).unwrap().shape(), &[] as &[usize]);
Source

pub fn dynamic_truncate(&self, size: &TracedTensor, axis: usize) -> TracedTensor

Truncate this tensor along axis to the first size elements.

size is read at runtime from a scalar traced tensor. Values are rounded to the nearest integer, clamped to [0, self.shape[axis]], and the output keeps the same element dtype as the input.

§Examples
use tenferro::{CpuBackend, Engine, TracedTensor};

let mut engine = Engine::new(CpuBackend::new());
let x = TracedTensor::from_vec(vec![4], vec![1.0_f64, 2.0, 3.0, 4.0]);
let size = TracedTensor::from_vec(vec![], vec![2.0_f64]);
let mut y = x.dynamic_truncate(&size, 0);
assert_eq!(y.eval(&mut engine).unwrap().shape(), &[2]);
Source

pub fn pad_to_match( &self, reference: &TracedTensor, axis: usize, ) -> TracedTensor

Pad this tensor with zeros along axis to match reference.shape[axis].

If reference is smaller along that axis, this is a no-op.

§Examples
use tenferro::{CpuBackend, Engine, TracedTensor};

let mut engine = Engine::new(CpuBackend::new());
let x = TracedTensor::from_vec(vec![2], vec![1.0_f64, 2.0]);
let reference = TracedTensor::from_vec(vec![4], vec![0.0_f64, 0.0, 0.0, 0.0]);
let mut y = x.pad_to_match(&reference, 0);
assert_eq!(y.eval(&mut engine).unwrap().shape(), &[4]);

Trait Implementations§

Source§

impl Add for &TracedTensor

Source§

type Output = TracedTensor

The resulting type after applying the + operator.
Source§

fn add(self, rhs: &TracedTensor) -> TracedTensor

Performs the + operation. Read more
Source§

impl Clone for TracedTensor

Source§

fn clone(&self) -> TracedTensor

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 Div for &TracedTensor

Source§

type Output = TracedTensor

The resulting type after applying the / operator.
Source§

fn div(self, rhs: &TracedTensor) -> TracedTensor

Performs the / operation. Read more
Source§

impl Mul<&TracedTensor> for f64

Source§

type Output = TracedTensor

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &TracedTensor) -> TracedTensor

Performs the * operation. Read more
Source§

impl Mul<f64> for &TracedTensor

Source§

type Output = TracedTensor

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: f64) -> TracedTensor

Performs the * operation. Read more
Source§

impl Mul for &TracedTensor

Source§

type Output = TracedTensor

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &TracedTensor) -> TracedTensor

Performs the * operation. Read more
Source§

impl Neg for &TracedTensor

Source§

type Output = TracedTensor

The resulting type after applying the - operator.
Source§

fn neg(self) -> TracedTensor

Performs the unary - operation. Read more

Auto Trait Implementations§

Blanket Implementations§

§

impl<Rhs, Lhs, Output> AddByRef<Rhs> for Lhs
where &'a Lhs: for<'a> Add<&'a Rhs, Output = Output>,

§

type Output = Output

§

fn add_by_ref(&self, rhs: &Rhs) -> <Lhs as AddByRef<Rhs>>::Output

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
§

impl<T> ByRef<T> for T

§

fn by_ref(&self) -> &T

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
§

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

§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

§

impl<Rhs, Lhs, Output> DivByRef<Rhs> for Lhs
where &'a Lhs: for<'a> Div<&'a Rhs, Output = Output>,

§

type Output = Output

§

fn div_by_ref(&self, rhs: &Rhs) -> <Lhs as DivByRef<Rhs>>::Output

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
§

impl<Rhs, Lhs, Output> MulByRef<Rhs> for Lhs
where &'a Lhs: for<'a> Mul<&'a Rhs, Output = Output>,

§

type Output = Output

§

fn mul_by_ref(&self, rhs: &Rhs) -> <Lhs as MulByRef<Rhs>>::Output

§

impl<T, Output> NegByRef for T
where &'a T: for<'a> Neg<Output = Output>,

§

type Output = Output

§

fn neg_by_ref(&self) -> <T as NegByRef>::Output

§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

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

Initializes a with the given initializer. Read more
§

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

Dereferences the given pointer. Read more
§

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

Mutably dereferences the given pointer. Read more
§

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.
§

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

§

fn vzip(self) -> V

§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,

§

impl<T> MaybeSend for T

§

impl<T> MaybeSendSync for T

§

impl<T> MaybeSync for T