Skip to main content

oxmera_tensor/
tensor.rs

1//! The tensor value: a layout over shared storage.
2
3use std::sync::Arc;
4
5use oxmera_core::{DType, Device, Layout, Result, Shape};
6
7use crate::storage::Storage;
8
9/// A tensor: shared storage viewed through a layout.
10///
11/// Cloning a tensor is cheap — it clones the layout and bumps the storage
12/// refcount, never the data. View operations (`reshape`, `permute`,
13/// `narrow`, …) produce new tensors over the same storage whenever the
14/// layout arithmetic allows it.
15#[derive(Debug, Clone)]
16pub struct Tensor {
17    storage: Arc<Storage>,
18    layout: Layout,
19}
20
21impl Tensor {
22    /// A tensor over existing storage with an explicit layout.
23    ///
24    /// Errors when the layout addresses elements outside the storage.
25    pub fn from_storage(storage: Arc<Storage>, layout: Layout) -> Result<Self> {
26        let _ = (storage, layout);
27        todo!("exercise A1: shape and strides")
28    }
29
30    /// A contiguous CPU tensor holding `data` with shape `shape`.
31    ///
32    /// Errors when `data.len()` does not equal `shape.numel()`.
33    pub fn from_vec_f32(data: Vec<f32>, shape: Shape) -> Result<Self> {
34        let _ = (data, shape);
35        todo!("exercise A1: shape and strides")
36    }
37
38    /// The shape of this view.
39    pub fn shape(&self) -> &Shape {
40        &self.layout.shape
41    }
42
43    /// The full layout of this view.
44    pub fn layout(&self) -> &Layout {
45        &self.layout
46    }
47
48    /// The element type.
49    pub fn dtype(&self) -> DType {
50        self.storage.dtype()
51    }
52
53    /// The device the storage lives on.
54    pub fn device(&self) -> Device {
55        self.storage.device()
56    }
57
58    /// The shared storage behind this view.
59    pub fn storage(&self) -> &Arc<Storage> {
60        &self.storage
61    }
62
63    /// A view with the same elements in a new shape.
64    ///
65    /// Succeeds without copying only when the current layout permits it;
66    /// errors on element-count mismatch. Never copies — `contiguous` is the
67    /// explicit spelling for that.
68    pub fn reshape(&self, shape: Shape) -> Result<Self> {
69        let _ = shape;
70        todo!("exercise A3: strided views")
71    }
72
73    /// A view with dimensions reordered by `perm` (a permutation of
74    /// `0..ndim`).
75    pub fn permute(&self, perm: &[usize]) -> Result<Self> {
76        let _ = perm;
77        todo!("exercise A3: strided views")
78    }
79
80    /// A view of `len` elements of dimension `dim` starting at `start`.
81    pub fn narrow(&self, dim: usize, start: usize, len: usize) -> Result<Self> {
82        let _ = (dim, start, len);
83        todo!("exercise A3: strided views")
84    }
85
86    /// This tensor's elements, in logical order, in fresh contiguous
87    /// storage on the same device. A no-op clone when already contiguous.
88    pub fn contiguous(&self) -> Result<Self> {
89        todo!("exercise A3: strided views")
90    }
91
92    /// The element at a logical index, as `f32`, for tests and debugging.
93    ///
94    /// Errors on rank mismatch, out-of-bounds, non-float dtype, or non-CPU
95    /// storage.
96    pub fn get_f32(&self, index: &[usize]) -> Result<f32> {
97        let _ = index;
98        todo!("exercise A1: shape and strides")
99    }
100}