1use alloc::vec::Vec;
2
3use burn_backend::{DType, TensorMetadata};
4use burn_std::{QuantScheme, Shape, quantization::global_scale_dtype};
5
6use crate::{FlexDevice, tensor::FlexTensor};
7
8#[derive(Clone, Debug)]
13pub struct FlexQTensor {
14 pub(crate) tensor: FlexTensor,
16 pub(crate) scheme: QuantScheme,
18 pub(crate) scales: Vec<f32>,
20 pub(crate) global: Option<f32>,
23}
24
25impl FlexQTensor {
26 pub fn new(
31 tensor: FlexTensor,
32 scheme: QuantScheme,
33 scales: Vec<f32>,
34 global: Option<f32>,
35 ) -> Self {
36 assert_eq!(
37 tensor.dtype(),
38 DType::I8,
39 "quantized tensor must store i8 data, got {:?}",
40 tensor.dtype()
41 );
42 assert!(
43 !scales.is_empty(),
44 "quantized tensor must have at least one scale factor"
45 );
46 assert_eq!(
47 global_scale_dtype(&scheme).is_some(),
48 global.is_some(),
49 "{scheme:?} does not match a per-tensor scale of {global:?}"
50 );
51 Self {
52 tensor,
53 scheme,
54 scales,
55 global,
56 }
57 }
58
59 pub fn tensor(&self) -> &FlexTensor {
61 &self.tensor
62 }
63
64 pub fn scales(&self) -> &[f32] {
66 &self.scales
67 }
68}
69
70impl TensorMetadata for FlexQTensor {
71 type Device = FlexDevice;
72
73 fn dtype(&self) -> DType {
74 DType::QFloat(self.scheme)
75 }
76
77 fn shape(&self) -> Shape {
78 self.tensor.shape()
79 }
80
81 fn rank(&self) -> usize {
82 self.tensor.rank()
83 }
84
85 fn device(&self) -> Self::Device {
86 FlexDevice
87 }
88
89 fn can_mut(&self) -> bool {
90 self.tensor.is_unique()
91 }
92}