1use std::any::Any;
4use std::sync::Arc;
5
6use oxmera_core::{DType, Device, Error, Result};
7
8#[derive(Debug, Clone)]
13pub enum CpuStorage {
14 F32(Vec<f32>),
16 F64(Vec<f64>),
18 I64(Vec<i64>),
20 U8(Vec<u8>),
22}
23
24impl CpuStorage {
25 pub fn dtype(&self) -> DType {
27 match self {
28 CpuStorage::F32(_) => DType::F32,
29 CpuStorage::F64(_) => DType::F64,
30 CpuStorage::I64(_) => DType::I64,
31 CpuStorage::U8(_) => DType::U8,
32 }
33 }
34
35 pub fn len(&self) -> usize {
37 match self {
38 CpuStorage::F32(v) => v.len(),
39 CpuStorage::F64(v) => v.len(),
40 CpuStorage::I64(v) => v.len(),
41 CpuStorage::U8(v) => v.len(),
42 }
43 }
44
45 pub fn is_empty(&self) -> bool {
47 self.len() == 0
48 }
49
50 pub fn f32s(&self) -> Result<&[f32]> {
52 match self {
53 CpuStorage::F32(v) => Ok(v),
54 other => Err(Error::DTypeMismatch {
55 expected: DType::F32,
56 got: other.dtype(),
57 op: "CpuStorage::f32s",
58 }),
59 }
60 }
61
62 pub fn f64s(&self) -> Result<&[f64]> {
64 match self {
65 CpuStorage::F64(v) => Ok(v),
66 other => Err(Error::DTypeMismatch {
67 expected: DType::F64,
68 got: other.dtype(),
69 op: "CpuStorage::f64s",
70 }),
71 }
72 }
73
74 pub fn i64s(&self) -> Result<&[i64]> {
76 match self {
77 CpuStorage::I64(v) => Ok(v),
78 other => Err(Error::DTypeMismatch {
79 expected: DType::I64,
80 got: other.dtype(),
81 op: "CpuStorage::i64s",
82 }),
83 }
84 }
85}
86
87#[cfg(target_os = "macos")]
91#[derive(Debug)]
92pub struct MetalBuffer {
93 buffer: metal::Buffer,
94 pub device_index: usize,
96}
97
98#[cfg(target_os = "macos")]
99impl MetalBuffer {
100 pub fn new(buffer: metal::Buffer, device_index: usize) -> Self {
102 Self {
103 buffer,
104 device_index,
105 }
106 }
107
108 pub fn buffer(&self) -> &metal::Buffer {
110 &self.buffer
111 }
112}
113
114#[cfg(target_os = "macos")]
120#[allow(unsafe_code)]
121unsafe impl Send for MetalBuffer {}
122#[cfg(target_os = "macos")]
125#[allow(unsafe_code)]
126unsafe impl Sync for MetalBuffer {}
127
128pub struct OpaqueBuffer {
133 inner: Arc<dyn Any + Send + Sync>,
134 len: usize,
135}
136
137impl OpaqueBuffer {
138 pub fn new(inner: Arc<dyn Any + Send + Sync>, len: usize) -> Self {
140 Self { inner, len }
141 }
142
143 pub fn inner(&self) -> &Arc<dyn Any + Send + Sync> {
145 &self.inner
146 }
147
148 pub fn len(&self) -> usize {
150 self.len
151 }
152
153 pub fn is_empty(&self) -> bool {
155 self.len == 0
156 }
157}
158
159impl std::fmt::Debug for OpaqueBuffer {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 f.debug_struct("OpaqueBuffer")
162 .field("len", &self.len)
163 .finish_non_exhaustive()
164 }
165}
166
167#[derive(Debug)]
169pub enum StorageData {
170 Cpu(CpuStorage),
172 #[cfg(target_os = "macos")]
174 Metal(MetalBuffer),
175 Opaque(OpaqueBuffer),
177}
178
179#[derive(Debug)]
184pub struct Storage {
185 data: StorageData,
186 dtype: DType,
187 device: Device,
188}
189
190impl Storage {
191 pub fn cpu_f32_zeros(numel: usize) -> Self {
193 Self::from_f32_vec(vec![0.0; numel])
194 }
195
196 pub fn from_f32_vec(data: Vec<f32>) -> Self {
198 Self {
199 data: StorageData::Cpu(CpuStorage::F32(data)),
200 dtype: DType::F32,
201 device: Device::Cpu,
202 }
203 }
204
205 pub fn from_f64_vec(data: Vec<f64>) -> Self {
207 Self {
208 data: StorageData::Cpu(CpuStorage::F64(data)),
209 dtype: DType::F64,
210 device: Device::Cpu,
211 }
212 }
213
214 pub fn from_i64_vec(data: Vec<i64>) -> Self {
216 Self {
217 data: StorageData::Cpu(CpuStorage::I64(data)),
218 dtype: DType::I64,
219 device: Device::Cpu,
220 }
221 }
222
223 #[cfg(target_os = "macos")]
225 pub fn from_metal(buffer: MetalBuffer, dtype: DType) -> Self {
226 let device = Device::Metal {
227 index: buffer.device_index,
228 };
229 Self {
230 data: StorageData::Metal(buffer),
231 dtype,
232 device,
233 }
234 }
235
236 pub fn dtype(&self) -> DType {
238 self.dtype
239 }
240
241 pub fn device(&self) -> Device {
243 self.device
244 }
245
246 pub fn data(&self) -> &StorageData {
248 &self.data
249 }
250
251 pub fn cpu(&self) -> Result<&CpuStorage> {
254 match &self.data {
255 StorageData::Cpu(c) => Ok(c),
256 _ => Err(Error::DeviceMismatch {
257 lhs: self.device,
258 rhs: Device::Cpu,
259 op: "Storage::cpu",
260 }),
261 }
262 }
263
264 pub fn from_opaque(buffer: OpaqueBuffer, dtype: DType, device: Device) -> Self {
266 Self {
267 data: StorageData::Opaque(buffer),
268 dtype,
269 device,
270 }
271 }
272
273 pub fn opaque(&self) -> Option<&OpaqueBuffer> {
275 match &self.data {
276 StorageData::Opaque(b) => Some(b),
277 _ => None,
278 }
279 }
280}