1use alloc::vec::Vec;
2use burn_backend::{TensorMetadata, TensorPrimitive, get_device_settings};
3use burn_dispatch::{Dispatch, DispatchTensor};
4use burn_std::DeviceSettings;
5
6#[derive(Clone, Debug)]
8pub struct Float;
9
10#[derive(Clone, Debug)]
12pub struct Int;
13
14#[derive(Clone, Debug)]
16pub struct Bool;
17
18mod sealed {
19 pub trait Sealed {}
20}
21
22impl sealed::Sealed for Float {}
23impl sealed::Sealed for Int {}
24impl sealed::Sealed for Bool {}
25
26pub trait TensorKind: sealed::Sealed + Clone + Send + Sync + core::fmt::Debug {
37 const KIND: Kind;
39
40 fn name() -> &'static str {
42 Self::KIND.as_str()
43 }
44}
45
46impl TensorKind for Float {
47 const KIND: Kind = Kind::Float;
48}
49
50impl TensorKind for Int {
51 const KIND: Kind = Kind::Int;
52}
53
54impl TensorKind for Bool {
55 const KIND: Kind = Kind::Bool;
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Eq)]
60pub enum Kind {
61 Float,
63 Int,
65 Bool,
67}
68
69impl Kind {
70 pub fn as_str(&self) -> &'static str {
72 match self {
73 Kind::Float => "Float",
74 Kind::Int => "Int",
75 Kind::Bool => "Bool",
76 }
77 }
78}
79
80pub struct BridgeTensor {
89 blob: bridge_opaque::Opaque,
90}
91
92burn_std::obfuscate!(
96 type: BridgeTensorVariant,
97 module: bridge_opaque,
98 derives: [Send, Sync]
99);
100
101impl core::fmt::Debug for BridgeTensor {
102 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
103 f.debug_struct("BridgeTensor")
104 .field("kind", &self.kind())
105 .finish()
106 }
107}
108
109impl Clone for BridgeTensor {
110 fn clone(&self) -> Self {
111 Self::new(self.as_variant().clone())
112 }
113}
114
115impl BridgeTensor {
116 fn as_variant(&self) -> &BridgeTensorVariant {
117 self.blob.as_ref()
118 }
119
120 fn into_variant(self) -> BridgeTensorVariant {
121 self.blob.into_inner()
122 }
123
124 fn new(inner: BridgeTensorVariant) -> Self {
125 Self {
126 blob: bridge_opaque::Opaque::new(inner),
127 }
128 }
129}
130
131#[derive(Clone, Debug)]
132enum BridgeTensorVariant {
134 Bool(DispatchTensor),
136 Int(DispatchTensor),
138 Float(DispatchTensor),
140 QFloat(DispatchTensor),
142}
143
144#[derive(Clone, Copy, Debug, PartialEq, Eq)]
149pub enum BridgeKind {
150 Bool,
152 Int,
154 Float,
156 QFloat,
158}
159
160macro_rules! ext_fn {
164 ($(#[$meta:meta])* fn $($tt:tt)+) => {
165 #[cfg(feature = "extension")]
166 $(#[$meta])*
167 pub fn $($tt)+
168 #[cfg(not(feature = "extension"))]
169 $(#[$meta])*
170 pub(crate) fn $($tt)+
171 };
172}
173
174impl BridgeTensor {
175 ext_fn! {
176 fn float(tensor: DispatchTensor) -> Self {
180 Self::new(BridgeTensorVariant::Float(tensor))
181 }
182 }
183
184 ext_fn! {
185 fn int(tensor: DispatchTensor) -> Self {
189 Self::new(BridgeTensorVariant::Int(tensor))
190 }
191 }
192
193 ext_fn! {
194 fn bool(tensor: DispatchTensor) -> Self {
198 Self::new(BridgeTensorVariant::Bool(tensor))
199 }
200 }
201
202 ext_fn! {
203 fn qfloat(tensor: DispatchTensor) -> Self {
207 Self::new(BridgeTensorVariant::QFloat(tensor))
208 }
209 }
210
211 pub fn kind(&self) -> BridgeKind {
213 match self.as_variant() {
214 BridgeTensorVariant::Bool(_) => BridgeKind::Bool,
215 BridgeTensorVariant::Int(_) => BridgeKind::Int,
216 BridgeTensorVariant::Float(_) => BridgeKind::Float,
217 BridgeTensorVariant::QFloat(_) => BridgeKind::QFloat,
218 }
219 }
220
221 pub fn is_float(&self) -> bool {
223 matches!(self.kind(), BridgeKind::Float)
224 }
225
226 pub fn is_int(&self) -> bool {
228 matches!(self.kind(), BridgeKind::Int)
229 }
230
231 pub fn is_bool(&self) -> bool {
233 matches!(self.kind(), BridgeKind::Bool)
234 }
235
236 pub fn is_qfloat(&self) -> bool {
238 matches!(self.kind(), BridgeKind::QFloat)
239 }
240
241 ext_fn! {
242 fn into_parts(self) -> (BridgeKind, DispatchTensor) {
247 match self.into_variant() {
248 BridgeTensorVariant::Bool(t) => (BridgeKind::Bool, t),
249 BridgeTensorVariant::Int(t) => (BridgeKind::Int, t),
250 BridgeTensorVariant::Float(t) => (BridgeKind::Float, t),
251 BridgeTensorVariant::QFloat(t) => (BridgeKind::QFloat, t),
252 }
253 }
254 }
255
256 ext_fn! {
257 fn as_parts(&self) -> (BridgeKind, &DispatchTensor) {
262 match self.as_variant() {
263 BridgeTensorVariant::Bool(t) => (BridgeKind::Bool, t),
264 BridgeTensorVariant::Int(t) => (BridgeKind::Int, t),
265 BridgeTensorVariant::Float(t) => (BridgeKind::Float, t),
266 BridgeTensorVariant::QFloat(t) => (BridgeKind::QFloat, t),
267 }
268 }
269 }
270
271 pub fn dtype(&self) -> burn_std::DType {
273 match self.as_variant() {
274 BridgeTensorVariant::Bool(tensor) => tensor.dtype(),
275 BridgeTensorVariant::Int(tensor) => tensor.dtype(),
276 BridgeTensorVariant::Float(tensor) => tensor.dtype(),
277 BridgeTensorVariant::QFloat(tensor) => tensor.dtype(),
278 }
279 }
280
281 pub fn can_mut(&self) -> bool {
284 match self.as_variant() {
285 BridgeTensorVariant::Bool(tensor) => tensor.can_mut(),
286 BridgeTensorVariant::Int(tensor) => tensor.can_mut(),
287 BridgeTensorVariant::Float(tensor) => tensor.can_mut(),
288 BridgeTensorVariant::QFloat(tensor) => tensor.can_mut(),
289 }
290 }
291
292 pub fn shape(&self) -> burn_std::Shape {
294 match self.as_variant() {
295 BridgeTensorVariant::Bool(tensor) => tensor.shape(),
296 BridgeTensorVariant::Int(tensor) => tensor.shape(),
297 BridgeTensorVariant::Float(tensor) => tensor.shape(),
298 BridgeTensorVariant::QFloat(tensor) => tensor.shape(),
299 }
300 }
301
302 pub fn rank(&self) -> usize {
304 match self.as_variant() {
305 BridgeTensorVariant::Bool(tensor) => tensor.rank(),
306 BridgeTensorVariant::Int(tensor) => tensor.rank(),
307 BridgeTensorVariant::Float(tensor) => tensor.rank(),
308 BridgeTensorVariant::QFloat(tensor) => tensor.rank(),
309 }
310 }
311
312 pub(crate) fn as_dispatch(&self) -> &DispatchTensor {
313 match self.as_variant() {
314 BridgeTensorVariant::Bool(tensor) => tensor,
315 BridgeTensorVariant::Int(tensor) => tensor,
316 BridgeTensorVariant::Float(tensor) => tensor,
317 BridgeTensorVariant::QFloat(tensor) => tensor,
318 }
319 }
320
321 #[cfg(feature = "autodiff")]
322 pub(crate) fn as_float(&self) -> &DispatchTensor {
323 match self.as_variant() {
324 BridgeTensorVariant::Float(tensor) => tensor,
325 _ => panic!("Should be Float primitive kind"),
326 }
327 }
328
329 pub(crate) fn into_dispatch_vec(tensors: Vec<Self>) -> Vec<DispatchTensor> {
330 tensors.into_iter().map(Into::into).collect()
331 }
332
333 pub(crate) fn into_float(self) -> DispatchTensor {
334 match self.into_variant() {
335 BridgeTensorVariant::Float(tensor) => tensor,
336 BridgeTensorVariant::QFloat(tensor) => {
338 TensorPrimitive::<Dispatch>::QFloat(tensor).tensor()
339 }
340 _ => panic!("Should be Float primitive kind"),
341 }
342 }
343
344 pub(crate) fn device_settings(&self) -> DeviceSettings {
345 let device = match self.as_variant() {
346 BridgeTensorVariant::Bool(tensor) => tensor.device(),
347 BridgeTensorVariant::Int(tensor) => tensor.device(),
348 BridgeTensorVariant::Float(tensor) => tensor.device(),
349 BridgeTensorVariant::QFloat(tensor) => tensor.device(),
350 };
351
352 get_device_settings::<Dispatch>(&device)
353 }
354}
355
356impl From<BridgeTensor> for DispatchTensor {
357 fn from(value: BridgeTensor) -> Self {
358 match value.into_variant() {
359 BridgeTensorVariant::Bool(tensor) => tensor,
360 BridgeTensorVariant::Int(tensor) => tensor,
361 BridgeTensorVariant::Float(tensor) => tensor,
362 BridgeTensorVariant::QFloat(tensor) => tensor,
363 }
364 }
365}