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;