1use std::borrow::Cow;
2
3use crate::{
4 Bool, DTypeKind, Device, Float, Int, Layout, Shape, Tensor,
5 dtype::{BoolDType, FloatDType, IntDType},
6};
7
8pub struct TensorCreationOptions<D: Device, K: DTypeKind<D>> {
9 pub device: D,
10 pub dtype: K::DType,
11}
12
13impl<D: Device, K: DTypeKind<D>> From<&D> for TensorCreationOptions<D, K> {
14 fn from(device: &D) -> Self {
15 Self { device: device.clone(), dtype: K::DType::default() }
16 }
17}
18
19impl<D: Device, K: DTypeKind<D>> From<D> for TensorCreationOptions<D, K> {
20 fn from(device: D) -> Self {
21 Self { device, dtype: K::DType::default() }
22 }
23}
24
25impl<D: Device> From<FloatDType> for TensorCreationOptions<D, Float> {
26 fn from(dtype: FloatDType) -> Self {
27 Self { device: D::default(), dtype }
28 }
29}
30
31impl<D: Device> From<IntDType> for TensorCreationOptions<D, Int> {
32 fn from(dtype: IntDType) -> Self {
33 Self { device: D::default(), dtype }
34 }
35}
36
37impl<D: Device> From<BoolDType> for TensorCreationOptions<D, Bool> {
38 fn from(dtype: BoolDType) -> Self {
39 Self { device: D::default(), dtype }
40 }
41}
42
43impl<D: Device, K: DTypeKind<D>> From<()> for TensorCreationOptions<D, K> {
44 fn from(_: ()) -> Self {
45 Self { device: D::default(), dtype: K::DType::default() }
46 }
47}
48
49impl<D: Device, K: DTypeKind<D>> From<(&D, K::DType)> for TensorCreationOptions<D, K> {
50 fn from((device, dtype): (&D, K::DType)) -> Self {
51 Self { device: device.clone(), dtype }
52 }
53}
54
55impl<D: Device, K: DTypeKind<D>> From<(D, K::DType)> for TensorCreationOptions<D, K> {
56 fn from((device, dtype): (D, K::DType)) -> Self {
57 Self { device, dtype }
58 }
59}
60
61pub trait ConstructDTypeKind<D: Device>: DTypeKind<D> {
62 fn zeros_dispatch(shape: &Shape, device: &D, dtype: Self::DType) -> crate::Result<Self::Storage>;
63 fn ones_dispatch(shape: &Shape, device: &D, dtype: Self::DType) -> crate::Result<Self::Storage>;
64 fn full_dispatch(shape: &Shape, value: Self::Scalar, device: &D, dtype: Self::DType) -> crate::Result<Self::Storage>;
65}
66
67impl<D: Device> ConstructDTypeKind<D> for Float {
68 fn zeros_dispatch(shape: &Shape, device: &D, dtype: FloatDType) -> crate::Result<Self::Storage> {
69 D::f_zeros(shape, device, dtype)
70 }
71
72 fn ones_dispatch(shape: &Shape, device: &D, dtype: FloatDType) -> crate::Result<Self::Storage> {
73 D::f_ones(shape, device, dtype)
74 }
75
76 fn full_dispatch(shape: &Shape, value: f64, device: &D, dtype: FloatDType) -> crate::Result<Self::Storage> {
77 D::f_full(shape, value, device, dtype)
78 }
79}
80
81impl<D: Device> ConstructDTypeKind<D> for Int {
82 fn zeros_dispatch(shape: &Shape, device: &D, dtype: IntDType) -> crate::Result<Self::Storage> {
83 D::i_zeros(shape, device, dtype)
84 }
85
86 fn ones_dispatch(shape: &Shape, device: &D, dtype: IntDType) -> crate::Result<Self::Storage> {
87 D::i_ones(shape, device, dtype)
88 }
89
90 fn full_dispatch(shape: &Shape, value: Self::Scalar, device: &D, dtype: IntDType) -> crate::Result<Self::Storage> {
91 D::i_full(shape, value, device, dtype)
92 }
93}
94
95impl<D: Device, K: DTypeKind<D>> Tensor<D, K> {
96 pub fn phantom<S: Into<Shape>>(shape: S, options: impl Into<TensorCreationOptions<D, K>>) -> crate::Result<Self> {
97 let options: TensorCreationOptions<D, K> = options.into();
98 let shape = shape.into();
99 Ok(Self::phantom_storage(shape, options.dtype, options.device))
100 }
101}
102
103impl<D: Device, K: ConstructDTypeKind<D>> Tensor<D, K> {
104 pub fn zeros<S: Into<Shape>>(shape: S, options: impl Into<TensorCreationOptions<D, K>>) -> crate::Result<Self> {
105 let options: TensorCreationOptions<D, K> = options.into();
106 let shape = shape.into();
107 let storage = K::zeros_dispatch(&shape, &options.device, options.dtype)?;
108 Ok(Self::from_storage(storage, shape, K::Meta::default()))
109 }
110
111 pub fn ones<S: Into<Shape>>(shape: S, options: impl Into<TensorCreationOptions<D, K>>) -> crate::Result<Self> {
112 let options: TensorCreationOptions<D, K> = options.into();
113 let shape = shape.into();
114 let storage = K::ones_dispatch(&shape, &options.device, options.dtype)?;
115 Ok(Self::from_storage(storage, shape, K::Meta::default()))
116 }
117
118 pub fn full<S: Into<Shape>>(shape: S, value: K::Scalar, options: impl Into<TensorCreationOptions<D, K>>) -> crate::Result<Self> {
119 let options: TensorCreationOptions<D, K> = options.into();
120 let shape = shape.into();
121 let storage = K::full_dispatch(&shape, value, &options.device, options.dtype)?;
122 Ok(Self::from_storage(storage, shape, K::Meta::default()))
123 }
124
125 pub fn zeros_like(&self) -> crate::Result<Self> {
126 Self::zeros(self.shape().clone(), (self.device(), self.dtype()))
127 }
128
129 pub fn ones_like(&self) -> crate::Result<Self> {
130 Self::ones(self.shape().clone(), (self.device(), self.dtype()))
131 }
132}
133
134pub trait BytesDTypeKind<D: Device>: DTypeKind<D> {
143 fn from_bytes_dispatch(bytes: &[u8], shape: &Shape, device: &D, dtype: Self::DType) -> crate::Result<Self::Storage>;
144 fn to_bytes_dispatch<'a>(storage: &'a Self::Storage, layout: &Layout) -> crate::Result<Cow<'a, [u8]>>;
145}
146
147impl<D: Device> BytesDTypeKind<D> for Float {
148 fn from_bytes_dispatch(bytes: &[u8], shape: &Shape, device: &D, dtype: FloatDType) -> crate::Result<Self::Storage> {
149 D::f_from_bytes(bytes, shape, device, dtype)
150 }
151
152 fn to_bytes_dispatch<'a>(storage: &'a Self::Storage, layout: &Layout) -> crate::Result<Cow<'a, [u8]>> {
153 D::f_to_bytes(storage, layout)
154 }
155}
156
157impl<D: Device> BytesDTypeKind<D> for Int {
158 fn from_bytes_dispatch(bytes: &[u8], shape: &Shape, device: &D, dtype: IntDType) -> crate::Result<Self::Storage> {
159 D::i_from_bytes(bytes, shape, device, dtype)
160 }
161
162 fn to_bytes_dispatch<'a>(storage: &'a Self::Storage, layout: &Layout) -> crate::Result<Cow<'a, [u8]>> {
163 D::i_to_bytes(storage, layout)
164 }
165}
166
167impl<D: Device> BytesDTypeKind<D> for Bool {
168 fn from_bytes_dispatch(bytes: &[u8], shape: &Shape, device: &D, _dtype: BoolDType) -> crate::Result<Self::Storage> {
169 D::b_from_bytes(bytes, shape, device, BoolDType::Bool)
170 }
171
172 fn to_bytes_dispatch<'a>(storage: &'a Self::Storage, layout: &Layout) -> crate::Result<Cow<'a, [u8]>> {
173 D::b_to_bytes(storage, layout)
174 }
175}
176
177impl<D: Device, K: BytesDTypeKind<D>> Tensor<D, K> {
178 pub fn from_bytes<'a>(
182 bytes: impl Into<Cow<'a, [u8]>>,
183 shape: impl Into<Shape>,
184 options: impl Into<TensorCreationOptions<D, K>>,
185 ) -> crate::Result<Self> {
186 let options: TensorCreationOptions<D, K> = options.into();
187 let shape = shape.into();
188 let storage = K::from_bytes_dispatch(&bytes.into(), &shape, &options.device, options.dtype)?;
189 Ok(Self::from_storage(storage, shape, K::Meta::default()))
190 }
191
192 pub fn to_bytes(&self) -> crate::Result<Vec<u8>> {
198 let guard = self.storage_read()?;
199 Ok(K::to_bytes_dispatch(&*guard, self.layout())?.into_owned())
200 }
201}