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}