Skip to main content

tenferro_runtime/
lib.rs

1//! Traced graph runtime and extension dispatch infrastructure for tenferro.
2//!
3//! This crate owns graph construction, lowering to execution IR, graph
4//! execution, and backend-parametric extension runtime dispatch. Standard
5//! operations are lowered through the runtime's internal operation vocabulary;
6//! tensor storage and backend kernels live in `tenferro-tensor`.
7//!
8//! Use this crate directly when you want concrete tensor helpers or reusable
9//! traced graph execution without opting into autodiff. Start with
10//! [`TypedTensor`] when the scalar type is fixed in Rust, [`Tensor`] when dtype
11//! is selected at runtime, and [`TracedTensor`] plus [`GraphCompiler`] and
12//! [`GraphExecutor`] when the same expression should be compiled once and run
13//! repeatedly. Operation-family crates such as `tenferro-einsum`,
14//! `tenferro-linalg`, and `tenferro-fft` register extension runtimes with
15//! [`GraphExecutor`] when compiled execution reaches those operations.
16//!
17//! User-facing guides live at
18//! <https://tensor4all.org/tenferro-rs/guides/choosing-an-api.html> and
19//! <https://tensor4all.org/tenferro-rs/guides/execution-models.html>.
20//!
21//! # Examples
22//!
23//! ```rust
24//! use tenferro_runtime::{GraphCompiler, GraphExecutor, TracedTensor};
25//! use tenferro_cpu::CpuBackend;
26//!
27//! let x = TracedTensor::from_vec_col_major(vec![2], vec![1.0_f64, 2.0]).unwrap();
28//! let y = (&x + &x).unwrap();
29//! let mut compiler = GraphCompiler::new();
30//! let program = compiler.compile(&y).unwrap();
31//! let out = GraphExecutor::new(CpuBackend::default()).run(&program).unwrap();
32//! assert_eq!(out.as_slice::<f64>().unwrap(), &[2.0, 4.0]);
33//! ```
34
35#[doc(hidden)]
36pub mod ad_support;
37mod checkpoint;
38mod compiler;
39pub mod error;
40mod exec;
41pub mod extension;
42pub mod extension_cache;
43pub mod extension_runtime;
44pub mod graph;
45mod metadata;
46#[doc(hidden)]
47pub mod scalar_semantics;
48mod segment;
49mod shape_infer;
50mod shape_packing;
51pub mod sym_dim;
52mod tensor;
53pub mod traced;
54mod typed_tensor;
55
56pub use compiler::{CompilerOptions, OptimizerConfig};
57pub use error::{ContextId, Error, Result};
58pub use extension_cache::{
59    ExtensionCacheKey, ExtensionCacheLimits, ExtensionCacheSelector, ExtensionCacheStore,
60};
61pub use extension_runtime::{
62    ExtensionExecutionContext, ExtensionExecutor, ExtensionRegistry, ExtensionRuntime,
63    ExtensionRuntimeRegistryError,
64};
65pub use graph::{
66    GraphCompiler, GraphCompilerCacheStats, GraphExecutor, GraphExecutorCacheStats,
67    GraphInstructionView, GraphOpView, GraphProgram, GraphProgramInput,
68    GraphProgramLoweringShapeError, GraphProgramLoweringView,
69};
70pub use sym_dim::SymDim;
71pub use tenferro_tensor::{
72    CacheStats, CompareDir, DType, DotGeneralConfig, GatherConfig, PadConfig, ScatterConfig,
73    SliceConfig, Tensor, TensorBackend, TensorRead, TensorScalar, TensorValue, TensorView,
74    TypedTensor, TypedTensorView,
75};
76
77/// Backend-explicit concrete tensor operations.
78///
79/// `Tensor` is owned by `tenferro-tensor`, so `tenferro-runtime` exposes these
80/// operations as a crate-root extension trait rather than as inherent methods.
81///
82/// # Public API rationale
83///
84/// This trait is intentionally public: it is the supported non-AD concrete
85/// tensor operation surface for downstream users who want to run operations on
86/// an explicit backend. The old public module/free-function surface was
87/// removed; the private `tensor` module now contains implementation helpers
88/// only and must not be treated as a compatibility API.
89///
90/// # Examples
91///
92/// ```rust
93/// use tenferro_cpu::CpuBackend;
94/// use tenferro_runtime::{Tensor, TensorOpsExt};
95///
96/// let mut backend = CpuBackend::new();
97/// let a = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64; 4]).unwrap();
98/// let b = Tensor::from_vec_col_major(vec![2, 2], vec![2.0_f64; 4]).unwrap();
99/// let c = a.matmul(&b, &mut backend).unwrap();
100/// assert_eq!(c.shape(), &[2, 2]);
101/// ```
102pub trait TensorOpsExt {
103    /// Convert to a different dtype using the checked conversion lattice.
104    fn convert<B: TensorBackend>(
105        &self,
106        to: DType,
107        backend: &mut B,
108    ) -> tenferro_tensor::Result<Tensor>;
109    /// Cast to a different dtype using explicit lossy projection.
110    fn cast<B: TensorBackend>(&self, to: DType, backend: &mut B)
111        -> tenferro_tensor::Result<Tensor>;
112    /// Elementwise addition with NumPy-style broadcasting.
113    fn add<B: TensorBackend>(
114        &self,
115        rhs: &Tensor,
116        backend: &mut B,
117    ) -> tenferro_tensor::Result<Tensor>;
118    /// Elementwise subtraction with NumPy-style broadcasting.
119    fn sub<B: TensorBackend>(
120        &self,
121        rhs: &Tensor,
122        backend: &mut B,
123    ) -> tenferro_tensor::Result<Tensor>;
124    /// Elementwise multiplication with NumPy-style broadcasting.
125    fn mul<B: TensorBackend>(
126        &self,
127        rhs: &Tensor,
128        backend: &mut B,
129    ) -> tenferro_tensor::Result<Tensor>;
130    /// Elementwise division with NumPy-style broadcasting.
131    fn div<B: TensorBackend>(
132        &self,
133        rhs: &Tensor,
134        backend: &mut B,
135    ) -> tenferro_tensor::Result<Tensor>;
136    /// Elementwise power with NumPy-style broadcasting.
137    fn pow<B: TensorBackend>(
138        &self,
139        rhs: &Tensor,
140        backend: &mut B,
141    ) -> tenferro_tensor::Result<Tensor>;
142    /// Elementwise maximum with NumPy-style broadcasting.
143    fn maximum<B: TensorBackend>(
144        &self,
145        rhs: &Tensor,
146        backend: &mut B,
147    ) -> tenferro_tensor::Result<Tensor>;
148    /// Elementwise minimum with NumPy-style broadcasting.
149    fn minimum<B: TensorBackend>(
150        &self,
151        rhs: &Tensor,
152        backend: &mut B,
153    ) -> tenferro_tensor::Result<Tensor>;
154    /// Elementwise negation.
155    fn neg<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
156    /// Elementwise absolute value.
157    fn abs<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
158    /// Elementwise sign.
159    fn sign<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
160    /// Elementwise complex conjugate.
161    fn conj<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
162    /// Elementwise exponential.
163    fn exp<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
164    /// Elementwise natural logarithm.
165    fn log<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
166    /// Elementwise sine.
167    fn sin<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
168    /// Elementwise cosine.
169    fn cos<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
170    /// Elementwise hyperbolic tangent.
171    fn tanh<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
172    /// Elementwise square root.
173    fn sqrt<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
174    /// Elementwise reciprocal square root.
175    fn rsqrt<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
176    /// Elementwise `exp(x) - 1`.
177    fn expm1<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
178    /// Elementwise `log(1 + x)`.
179    fn log1p<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<Tensor>;
180    /// Elementwise comparison with NumPy-style broadcasting.
181    fn compare<B: TensorBackend>(
182        &self,
183        rhs: &Tensor,
184        dir: CompareDir,
185        backend: &mut B,
186    ) -> tenferro_tensor::Result<Tensor>;
187    /// Select values from `on_true` or `on_false` using this tensor as condition.
188    fn where_select<B: TensorBackend>(
189        &self,
190        on_true: &Tensor,
191        on_false: &Tensor,
192        backend: &mut B,
193    ) -> tenferro_tensor::Result<Tensor>;
194    /// Clamp values elementwise between lower and upper bounds.
195    fn clamp<B: TensorBackend>(
196        &self,
197        lower: &Tensor,
198        upper: &Tensor,
199        backend: &mut B,
200    ) -> tenferro_tensor::Result<Tensor>;
201    /// Rank-2 matrix multiplication.
202    fn matmul<B: TensorBackend>(
203        &self,
204        rhs: &Tensor,
205        backend: &mut B,
206    ) -> tenferro_tensor::Result<Tensor>;
207    /// Reshape without changing element order.
208    fn reshape<B: TensorBackend>(
209        &self,
210        shape: &[usize],
211        backend: &mut B,
212    ) -> tenferro_tensor::Result<Tensor>;
213    /// Permute axes.
214    fn transpose<B: TensorBackend>(
215        &self,
216        perm: &[usize],
217        backend: &mut B,
218    ) -> tenferro_tensor::Result<Tensor>;
219    /// Sum over one or more axes.
220    fn reduce_sum<B: TensorBackend>(
221        &self,
222        axes: &[usize],
223        backend: &mut B,
224    ) -> tenferro_tensor::Result<Tensor>;
225}
226
227/// Backend-explicit operations for dynamic-rank typed tensors.
228///
229/// `TypedTensor` is owned by `tenferro-tensor`, so `tenferro-runtime` exposes
230/// these operations as a crate-root extension trait rather than as inherent
231/// methods.
232///
233/// # Public API rationale
234///
235/// This trait is intentionally public for the same reason as [`TensorOpsExt`]:
236/// downstream users need a supported backend-explicit typed tensor surface, and
237/// `tenferro-runtime` cannot add inherent methods to a type owned by
238/// `tenferro-tensor`. The private `typed_tensor` module is implementation
239/// detail, not a retained module/free-function API.
240///
241/// # Examples
242///
243/// ```rust
244/// use tenferro_cpu::CpuBackend;
245/// use tenferro_runtime::{TypedTensor, TypedTensorOpsExt};
246///
247/// let mut backend = CpuBackend::new();
248/// let x = TypedTensor::<f64>::from_vec_col_major(vec![2], vec![1.0, 2.0]).unwrap();
249/// let y = TypedTensor::<f64>::from_vec_col_major(vec![2], vec![3.0, 4.0]).unwrap();
250/// let sum = x.add(&y, &mut backend).unwrap();
251/// assert_eq!(sum.host_data().unwrap(), &[4.0, 6.0]);
252/// ```
253pub trait TypedTensorOpsExt<T: TensorScalar> {
254    /// Elementwise addition with NumPy-style broadcasting.
255    fn add<B: TensorBackend>(
256        &self,
257        rhs: &TypedTensor<T>,
258        backend: &mut B,
259    ) -> tenferro_tensor::Result<TypedTensor<T>>;
260    /// Elementwise subtraction with NumPy-style broadcasting.
261    fn sub<B: TensorBackend>(
262        &self,
263        rhs: &TypedTensor<T>,
264        backend: &mut B,
265    ) -> tenferro_tensor::Result<TypedTensor<T>>;
266    /// Elementwise multiplication with NumPy-style broadcasting.
267    fn mul<B: TensorBackend>(
268        &self,
269        rhs: &TypedTensor<T>,
270        backend: &mut B,
271    ) -> tenferro_tensor::Result<TypedTensor<T>>;
272    /// Elementwise division with NumPy-style broadcasting.
273    fn div<B: TensorBackend>(
274        &self,
275        rhs: &TypedTensor<T>,
276        backend: &mut B,
277    ) -> tenferro_tensor::Result<TypedTensor<T>>;
278    /// Elementwise power with NumPy-style broadcasting.
279    fn pow<B: TensorBackend>(
280        &self,
281        rhs: &TypedTensor<T>,
282        backend: &mut B,
283    ) -> tenferro_tensor::Result<TypedTensor<T>>;
284    /// Elementwise maximum with NumPy-style broadcasting.
285    fn maximum<B: TensorBackend>(
286        &self,
287        rhs: &TypedTensor<T>,
288        backend: &mut B,
289    ) -> tenferro_tensor::Result<TypedTensor<T>>;
290    /// Elementwise minimum with NumPy-style broadcasting.
291    fn minimum<B: TensorBackend>(
292        &self,
293        rhs: &TypedTensor<T>,
294        backend: &mut B,
295    ) -> tenferro_tensor::Result<TypedTensor<T>>;
296    /// Elementwise negation.
297    fn neg<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
298    /// Elementwise absolute value.
299    fn abs<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
300    /// Elementwise sign.
301    fn sign<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
302    /// Elementwise complex conjugate.
303    fn conj<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
304    /// Elementwise exponential.
305    fn exp<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
306    /// Elementwise natural logarithm.
307    fn log<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
308    /// Elementwise sine.
309    fn sin<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
310    /// Elementwise cosine.
311    fn cos<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
312    /// Elementwise hyperbolic tangent.
313    fn tanh<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
314    /// Elementwise square root.
315    fn sqrt<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
316    /// Elementwise reciprocal square root.
317    fn rsqrt<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
318    /// Elementwise `exp(x) - 1`.
319    fn expm1<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
320    /// Elementwise `log(1 + x)`.
321    fn log1p<B: TensorBackend>(&self, backend: &mut B) -> tenferro_tensor::Result<TypedTensor<T>>;
322    /// Elementwise comparison with NumPy-style broadcasting.
323    fn compare<B: TensorBackend>(
324        &self,
325        rhs: &TypedTensor<T>,
326        dir: CompareDir,
327        backend: &mut B,
328    ) -> tenferro_tensor::Result<TypedTensor<bool>>;
329    /// Clamp values elementwise between lower and upper bounds.
330    fn clamp<B: TensorBackend>(
331        &self,
332        lower: &TypedTensor<T>,
333        upper: &TypedTensor<T>,
334        backend: &mut B,
335    ) -> tenferro_tensor::Result<TypedTensor<T>>;
336    /// Rank-2 matrix multiplication.
337    fn matmul<B: TensorBackend>(
338        &self,
339        rhs: &TypedTensor<T>,
340        backend: &mut B,
341    ) -> tenferro_tensor::Result<TypedTensor<T>>;
342    /// Sum over one or more axes.
343    fn reduce_sum<B: TensorBackend>(
344        &self,
345        axes: &[usize],
346        backend: &mut B,
347    ) -> tenferro_tensor::Result<TypedTensor<T>>;
348    /// Reshape through the backend structural operation.
349    fn reshape<B: TensorBackend>(
350        &self,
351        shape: &[usize],
352        backend: &mut B,
353    ) -> tenferro_tensor::Result<TypedTensor<T>>;
354    /// Permute axes through the backend structural operation.
355    fn transpose<B: TensorBackend>(
356        &self,
357        perm: &[usize],
358        backend: &mut B,
359    ) -> tenferro_tensor::Result<TypedTensor<T>>;
360    /// Broadcast into a larger shape.
361    fn broadcast_in_dim<B: TensorBackend>(
362        &self,
363        shape: &[usize],
364        dims: &[usize],
365        backend: &mut B,
366    ) -> tenferro_tensor::Result<TypedTensor<T>>;
367}
368
369/// Backend-explicit bool-mask operations for typed tensors.
370///
371/// # Public API rationale
372///
373/// This trait keeps `where_select` available as a method on bool
374/// `TypedTensor`s while preserving the crate-root extension-trait surface. It
375/// is public because downstream users call it directly; the implementation
376/// helper in the private `typed_tensor` module is not a compatibility API.
377pub trait TypedTensorMaskOpsExt {
378    /// Select typed values using this bool tensor as condition.
379    fn where_select<T: TensorScalar, B: TensorBackend>(
380        &self,
381        on_true: &TypedTensor<T>,
382        on_false: &TypedTensor<T>,
383        backend: &mut B,
384    ) -> tenferro_tensor::Result<TypedTensor<T>>;
385}
386
387pub use traced::TracedTensor;