Skip to main content

torsh_tensor/
lib.rs

1//! Tensor implementation for ToRSh with PyTorch-compatible API
2//!
3//! This crate provides a high-level tensor API that wraps scirs2's autograd
4//! functionality with a familiar PyTorch-like interface.
5//!
6//! # Architecture
7//!
8//! The tensor implementation is organized into specialized modules:
9//!
10//! - [`storage`] - Storage management with automatic memory mapping optimization
11//! - [`core_ops`] - Core tensor operations, creation, and gradient management
12//! - [`shape_ops`] - Shape manipulation, views, and dimension operations
13//! - [`data_ops`] - Data access, indexing, and manipulation operations
14//! - [`advanced_ops`] - Advanced operations, reductions, and backend integration
15//! - [`math_ops`] - Mathematical operations and functions
16//! - [`complex_ops`] - Complex number operations and specialized autograd
17//!
18//! # Quick Start
19//!
20//! ```rust
21//! use torsh_tensor::Tensor;
22//! use torsh_core::device::DeviceType;
23//!
24//! // Create a tensor
25//! let data = vec![1.0f32, 2.0, 3.0, 4.0];
26//! let tensor = Tensor::from_data(data, vec![2, 2], DeviceType::Cpu)?;
27//!
28//! // Basic operations
29//! let reshaped = tensor.view(&[4, 1])?;
30//! let sum = tensor.sum()?;
31//! let norm_val = tensor.norm()?.item()?;
32//! let normalized = tensor.div_scalar(norm_val)?;
33//!
34//! // Enable gradients for autograd
35//! let x = tensor.requires_grad_(true);
36//! let y = x.pow(2.0)?;
37//! let loss = y.sum()?;  // Create scalar for backward pass
38//! loss.backward()?;
39//! # Ok::<(), torsh_core::error::TorshError>(())
40//! ```
41//!
42//! # Features
43//!
44//! - **Automatic memory management**: Optimized storage with memory mapping for large tensors
45//! - **Zero-copy views**: Efficient tensor views with shared underlying data
46//! - **PyTorch compatibility**: Familiar API for easy migration from PyTorch
47//! - **Automatic differentiation**: Full gradient computation support
48//! - **Device abstraction**: CPU and GPU device support
49//! - **Complex numbers**: Native complex tensor operations
50//! - **SciRS2 integration**: Optimized backend operations for performance
51
52#![cfg_attr(not(feature = "std"), no_std)]
53
54#[cfg(not(feature = "std"))]
55extern crate alloc;
56
57/// Decide whether an operation should record an autograd graph node.
58///
59/// Recording needs *both* halves to be true: at least one operand must require
60/// gradients, and gradient mode must be enabled. The second half is what makes
61/// `torsh_autograd::guards::no_grad()` (and `inference_mode()`) actually
62/// suppress graph construction — the flag lives in [`torsh_core::grad_mode`]
63/// rather than in `torsh-autograd`, because that crate sits *above* this one and
64/// its state would otherwise be invisible here.
65///
66/// `requires_grad` is passed pre-combined (e.g. `lhs.requires_grad ||
67/// rhs.requires_grad`) and checked first: it is a plain field read, so the
68/// common non-differentiable case never touches the mode at all, and the mode
69/// itself is a single relaxed atomic load.
70#[inline]
71pub(crate) fn should_record_grad(requires_grad: bool) -> bool {
72    requires_grad && torsh_core::grad_mode::is_grad_enabled()
73}
74
75// Core modules providing the tensor implementation
76pub mod adaptive_auto_tuner;
77pub mod advanced_ops;
78pub mod advanced_simd_ops;
79pub mod algorithmic_optimizations;
80pub mod complex_ops;
81pub mod comprehensive_integration_tests;
82pub mod computation_graph;
83pub mod core_ops;
84pub mod cross_platform_validator;
85pub mod data_ops;
86pub mod dim_ops;
87pub mod expression_optimizer;
88pub mod expression_templates;
89pub mod hardware_accelerators;
90pub mod manipulation;
91pub mod math_ops;
92pub mod matmul_ops;
93pub mod memory_optimization;
94pub mod optimization_cli;
95pub mod shape_ops;
96pub mod storage;
97pub mod ultimate_integration_optimizer;
98pub mod ultra_performance_profiler;
99
100// Utility and integration modules
101#[cfg(feature = "async")]
102pub mod async_ops;
103pub mod auto_batching;
104pub mod backend_integration;
105pub mod bfloat16_ops;
106pub mod broadcast;
107pub mod cache_optimization;
108pub mod conv;
109pub mod convenience;
110pub mod creation;
111/// ToRSh-owned thin CUDA backend over oxicuda leaf crates (used by gpu_dispatch).
112#[cfg(feature = "cuda")]
113mod cuda_backend;
114pub mod custom_dtype;
115pub mod custom_ops;
116pub mod fft;
117/// GPU compute dispatch backed by oxicuda's `ComputeBackend` (replaces scirs2-core GPU).
118#[cfg(feature = "gpu")]
119pub mod gpu_dispatch;
120pub mod indexing;
121pub mod lazy_loading;
122pub mod lockfree_cache;
123pub mod memory_pool;
124#[cfg(feature = "memory-profiling")]
125pub mod memory_profiler;
126pub mod nan_inf_detection;
127#[cfg(feature = "operation-logging")]
128pub mod operation_logging;
129pub mod scirs2_backend;
130pub mod scirs2_stats_integration;
131pub mod shape_inference_debugger;
132pub mod simd_ops_f32;
133pub mod sparse;
134pub mod stats;
135pub mod tensor_comprehension;
136pub mod tensor_tracker;
137pub mod tensor_utils;
138pub mod tensor_view; // Zero-copy tensor views (CRITICAL #1)
139pub mod tensor_views;
140pub mod type_conversions;
141
142// TODO: Implement custom data types module
143// #[cfg(feature = "custom-types")]
144// pub mod custom_data_types;
145
146#[cfg(feature = "serialize")]
147pub mod serialize;
148
149// Re-export core types and traits
150use torsh_core::{
151    device::DeviceType,
152    dtype::{FloatElement, TensorElement},
153    error::Result,
154};
155
156// Re-export the main tensor type
157pub use core_ops::{Operation, Tensor};
158
159// Re-export convenience methods
160pub use convenience::{FluentTensor, TensorConvenience, TensorFluentExt};
161
162// Re-export sparse tensor functionality (COO, CSR, CSC formats)
163pub use sparse::{SparseCSC, SparseCSR, SparseTensor};
164
165// Re-export custom operation functionality
166pub use custom_ops::{
167    global_registry, CustomOperation, CustomOperationRegistry, OperationMetadata, OperationParams,
168    TensorCustomOps,
169};
170
171// Re-export storage types for advanced usage
172#[cfg(feature = "gpu")]
173pub use storage::DeviceBuffer;
174pub use storage::{MemoryMappedStorage, TensorStorage};
175
176// Re-export zero-copy view types (CRITICAL #1)
177pub use tensor_view::{TensorView, TensorViewMut};
178
179// Version information
180pub const VERSION: &str = env!("CARGO_PKG_VERSION");
181pub const VERSION_MAJOR: u32 = 0;
182pub const VERSION_MINOR: u32 = 1;
183pub const VERSION_PATCH: u32 = 0;
184
185/// Tensor creation macro similar to PyTorch
186#[macro_export]
187macro_rules! tensor {
188    // 1D array from bracketed values
189    ([$($val:expr),+ $(,)?]) => {
190        $crate::creation::tensor_1d(&[$($val),+])
191    };
192
193    // Multiple values without brackets (at least 2 values to avoid scalar conflict)
194    ($val1:expr, $val2:expr $(, $val:expr)* $(,)?) => {
195        $crate::creation::tensor_1d(&[$val1, $val2 $(, $val)*])
196    };
197
198    // Single value (scalar)
199    ($val:expr) => {
200        $crate::creation::tensor_scalar($val)
201    };
202}
203
204/// 2D tensor creation macro
205#[macro_export]
206macro_rules! tensor_2d {
207    ([$($row:expr),+ $(,)?]) => {{
208        let rows: Vec<Vec<_>> = vec![$($row.to_vec()),+];
209        let row_refs: Vec<&[_]> = rows.iter().map(|row| row.as_slice()).collect();
210        $crate::creation::tensor_2d(&row_refs)
211    }};
212}
213
214// Display implementation for Tensor
215impl<T: TensorElement> std::fmt::Debug for Tensor<T> {
216    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217        write!(
218            f,
219            "Tensor(shape={:?}, dtype={}, device={})",
220            self.shape().dims(),
221            self.dtype(),
222            self.device
223        )
224    }
225}
226
227// Additional utility implementations
228impl<T: TensorElement> Tensor<T> {
229    /// Get the reference count of the underlying storage Arc (for testing CoW behavior)
230    #[cfg(test)]
231    pub fn data_ref_count(&self) -> usize {
232        use std::sync::Arc;
233        match &self.storage {
234            TensorStorage::InMemory(data) => Arc::strong_count(data),
235            TensorStorage::MemoryMapped(storage) => Arc::strong_count(storage),
236            #[cfg(feature = "simd")]
237            TensorStorage::Aligned(data) => Arc::strong_count(data),
238            #[cfg(feature = "simd")]
239            TensorStorage::SimdOptimized(storage) => Arc::strong_count(storage),
240            #[cfg(feature = "gpu")]
241            TensorStorage::Device { buffer, .. } => Arc::strong_count(buffer),
242        }
243    }
244
245    /// Create from vec with shape (convenience method).
246    ///
247    /// Rejects a `data` length that does not match `shape`'s element count so
248    /// the mismatch is reported here rather than as a later out-of-bounds error.
249    pub fn from_vec(data: Vec<T>, shape: &[usize]) -> Result<Self>
250    where
251        T: Copy,
252    {
253        let numel: usize = shape.iter().product();
254        if data.len() != numel {
255            return Err(torsh_core::error::TorshError::InvalidArgument(format!(
256                "from_vec: data has {} elements but shape {:?} requires {}",
257                data.len(),
258                shape,
259                numel
260            )));
261        }
262        Self::from_data(data, shape.to_vec(), DeviceType::Cpu)
263    }
264}
265
266// Re-export commonly used functions and types for convenience
267pub mod prelude {
268    pub use crate::advanced_simd_ops::{
269        AdvancedSimdOps, ReductionType, SimdConfig, SimdPerformanceInfo,
270    };
271    pub use crate::algorithmic_optimizations::{
272        AlgorithmConfig, AlgorithmPerformanceStats, AlgorithmicOptimizer, SchedulingStrategy,
273    };
274    pub use crate::comprehensive_integration_tests::{
275        run_comprehensive_integration_tests, ComprehensiveIntegrationTestSuite,
276        ComprehensiveTestReport, IntegrationAnalysis, IntegrationTestConfig, PerformanceAnalysis,
277        StabilityAnalysis, TestCategory,
278    };
279    pub use crate::core_ops::Operation;
280    pub use crate::creation::{eye, ones, rand, randn, zeros};
281    pub use crate::cross_platform_validator::{
282        CpuArchitecture, CrossPlatformReport, CrossPlatformValidator, GpuVendor,
283        HardwareDetectionReport, HardwareDetector, OptimizationConfig, OptimizationReport,
284        Platform, PlatformOptimizer, ValidationConfig, ValidationFramework, ValidationReport,
285    };
286    pub use crate::expression_optimizer::{
287        ExpressionGraph, ExpressionNode, ExpressionOptimizer, NodeId, OperationType,
288        OptimizationStats, OptimizationStrategy, OptimizerConfig, TensorExpressionOps,
289    };
290    pub use crate::hardware_accelerators::{
291        AccelerationWorkload, ComplexityLevel, CpuAccelerationMetrics, CpuAcceleratorEngine,
292        GpuAccelerationMetrics, GpuAcceleratorEngine, HardwareAcceleratorReport,
293        HardwareAcceleratorSystem, MemoryAccelerationMetrics, MemoryAcceleratorEngine,
294        NetworkAccelerationMetrics, OptimizationCoordinator, SpecializedAcceleratorEngine,
295        WorkloadType,
296    };
297    pub use crate::memory_optimization::{
298        AdvancedMemoryPool, AggregateMemoryStats, DefragmentationReport, GlobalMemoryOptimizer,
299        MemoryConfig, MemoryStats,
300    };
301    pub use crate::optimization_cli::{
302        run_cli_command, run_optimization_cli, CLICommand, CLIConfig, OptimizationCLI,
303        OptimizationLevel, OptimizationType,
304    };
305    pub use crate::ultimate_integration_optimizer::{
306        CrossLayerSynergyGains, EfficiencyImprovements, EnergyEfficiencyImprovements,
307        GlobalPerformanceCache, IntelligentLearningSystem, LayerSpecificImprovements,
308        OptimizationComplexity, OptimizationStatus, ScalabilityImprovements,
309        SystemOptimizationCoordinator, UltimateIntegrationOptimizer, UltimateOptimizationResult,
310    };
311    pub use crate::{Tensor, TensorConvenience, TensorStorage};
312    pub use torsh_core::{
313        device::DeviceType,
314        dtype::{DType, FloatElement, TensorElement},
315        error::{Result, TorshError},
316        shape::Shape,
317    };
318}
319
320#[cfg(test)]
321mod integration_tests {
322    use super::*;
323    use torsh_core::device::DeviceType;
324    use torsh_core::dtype::DType;
325
326    #[test]
327    fn test_tensor_creation_and_basic_ops() {
328        let data = vec![1.0f32, 2.0, 3.0, 4.0];
329        let tensor = Tensor::from_data(data, vec![2, 2], DeviceType::Cpu)
330            .expect("tensor creation should succeed");
331
332        assert_eq!(tensor.shape().dims(), &[2, 2]);
333        assert_eq!(tensor.numel(), 4);
334        assert_eq!(tensor.dtype(), DType::F32);
335    }
336
337    #[test]
338    fn test_tensor_reshape_and_view() {
339        let data = vec![1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0];
340        let tensor = Tensor::from_data(data, vec![2, 3], DeviceType::Cpu)
341            .expect("tensor creation should succeed");
342
343        let reshaped = tensor.view(&[3, 2]).expect("view should succeed");
344        assert_eq!(reshaped.shape().dims(), &[3, 2]);
345
346        let slice = tensor
347            .slice_tensor(0, 0, 1)
348            .expect("slice_tensor should succeed");
349        assert_eq!(slice.shape().dims(), &[1, 3]);
350    }
351
352    #[test]
353    fn test_tensor_math_operations() {
354        let a = Tensor::from_data(vec![1.0f32, 2.0, 3.0], vec![3], DeviceType::Cpu)
355            .expect("tensor creation should succeed");
356        let b = Tensor::from_data(vec![4.0f32, 5.0, 6.0], vec![3], DeviceType::Cpu)
357            .expect("tensor creation should succeed");
358
359        let sum = a.add(&b).expect("addition should succeed");
360        assert_eq!(
361            sum.data().expect("data retrieval should succeed"),
362            vec![5.0, 7.0, 9.0]
363        );
364
365        let product = a.mul(&b).expect("multiplication should succeed");
366        assert_eq!(
367            product.data().expect("data retrieval should succeed"),
368            vec![4.0, 10.0, 18.0]
369        );
370    }
371
372    #[test]
373    fn test_tensor_advanced_operations() {
374        let data = vec![1.0f32, 4.0, 9.0, 16.0];
375        let tensor = Tensor::from_data(data, vec![4], DeviceType::Cpu)
376            .expect("tensor creation should succeed");
377
378        let sqrt_result = tensor.sqrt().expect("sqrt should succeed");
379        assert_eq!(
380            sqrt_result.data().expect("data retrieval should succeed"),
381            vec![1.0, 2.0, 3.0, 4.0]
382        );
383
384        let norm = tensor.norm().expect("norm should succeed");
385        assert!(norm.item().expect("item extraction should succeed") > 0.0);
386    }
387
388    #[test]
389    fn test_tensor_data_operations() {
390        let mut tensor =
391            Tensor::<f32>::zeros(&[2, 3], DeviceType::Cpu).expect("zeros creation should succeed");
392
393        tensor.fill_(5.0).expect("fill should succeed");
394        assert_eq!(
395            tensor.get_item(&[0, 0]).expect("get_item should succeed"),
396            5.0
397        );
398
399        let indices = Tensor::from_data(vec![0i64, 2], vec![2], DeviceType::Cpu)
400            .expect("tensor creation should succeed");
401        let _src = Tensor::from_data(vec![10.0f32, 20.0], vec![2], DeviceType::Cpu)
402            .expect("tensor creation should succeed");
403
404        let data_1d = vec![1.0f32, 2.0, 3.0, 4.0, 5.0];
405        let tensor_1d = Tensor::from_data(data_1d, vec![5], DeviceType::Cpu)
406            .expect("tensor creation should succeed");
407        let gathered = tensor_1d
408            .gather(0, &indices)
409            .expect("gather should succeed");
410        assert_eq!(
411            gathered.data().expect("data retrieval should succeed"),
412            vec![1.0, 3.0]
413        );
414    }
415
416    #[test]
417    fn test_tensor_storage_optimization() {
418        // Small tensor should use in-memory storage
419        let small =
420            Tensor::<f32>::zeros(&[10], DeviceType::Cpu).expect("zeros creation should succeed");
421        assert_eq!(small.storage_type(), "in_memory");
422
423        // Test copy-on-write behavior
424        let tensor1 =
425            Tensor::<f32>::ones(&[5], DeviceType::Cpu).expect("ones creation should succeed");
426        let tensor2 = tensor1.clone();
427        assert!(tensor1.shares_storage(&tensor2));
428    }
429
430    #[test]
431    fn test_gradient_operations() {
432        let tensor = Tensor::<f32>::ones(&[2, 2], DeviceType::Cpu)
433            .expect("ones creation should succeed")
434            .requires_grad_(true);
435
436        assert!(tensor.requires_grad());
437        assert!(!tensor.has_grad());
438
439        let detached = tensor.detach();
440        assert!(!detached.requires_grad());
441    }
442}