pub struct PerChannelAffine { /* private fields */ }Expand description
Quantization parameters for per-channel affine quantization.
Each slice along axis has its own scale (and optionally zero_point).
The parameter arrays are stored in separate buffers referenced by index in
the tensor descriptor’s buffer table.
The dequantization formula for element q at logical index
[i_0, …, i_{rank-1}] is:
c = i_axis
x_real = scale[c] * (q - zero_point[c])When the SYMMETRIC flag is set, zero_point[c] is treated as 0.
§Wire format
Total descriptor length: 20 bytes (including the 4-byte header).
| Offset | Field | Type |
|---|---|---|
| 4 | axis | uint32 LE |
| 8 | scale_buffer_index | uint32 LE |
| 12 | zero_point_buffer_index | uint32 LE (0xFFFFFFFF if symmetric) |
| 16 | scale_type_tag | uint8 (must be 0x03 in v1) |
| 17 | _reserved | uint8[3] (must be 0x00) |
§Design notes
PartialEq, Eq, and Hash are all derived because this struct contains
no floating-point fields — all fields are integers or Option<u32>.
Copy because the struct is ≤ 24 bytes with no Drop glue.
§Examples
use hurray_core::PerChannelAffine;
// Asymmetric: separate scale (buffer 1) and zero-point (buffer 2) arrays.
let q = PerChannelAffine::new_asymmetric(0, 1, 2).unwrap();
assert!(!q.is_symmetric());
assert_eq!(q.zero_point_buffer_index(), Some(2));
// Symmetric: only a scale buffer, zero-point is implicitly zero.
let s = PerChannelAffine::new_symmetric(0, 1).unwrap();
assert!(s.is_symmetric());
assert_eq!(s.zero_point_buffer_index(), None);Implementations§
Source§impl PerChannelAffine
impl PerChannelAffine
Sourcepub fn new_asymmetric(
axis: u32,
scale_buffer_index: u32,
zero_point_buffer_index: u32,
) -> Result<Self>
pub fn new_asymmetric( axis: u32, scale_buffer_index: u32, zero_point_buffer_index: u32, ) -> Result<Self>
Creates an asymmetric PerChannelAffine descriptor.
§Errors
Error::InvalidQuantization—scale_bufequals0xFFFFFFFF(the zero-point sentinel value, which is not a valid scale buffer index).
§Examples
use hurray_core::PerChannelAffine;
let q = PerChannelAffine::new_asymmetric(0, 1, 2).unwrap();
assert!(!q.is_symmetric());
assert_eq!(q.scale_buffer_index(), 1);
assert_eq!(q.zero_point_buffer_index(), Some(2));Sourcepub fn new_symmetric(axis: u32, scale_buffer_index: u32) -> Result<Self>
pub fn new_symmetric(axis: u32, scale_buffer_index: u32) -> Result<Self>
Creates a symmetric PerChannelAffine descriptor.
In symmetric mode the zero-point array is implicit (all zeros); no zero-point buffer entry is required in the tensor descriptor’s buffer table.
§Errors
Error::InvalidQuantization—scale_bufequals0xFFFFFFFF.
§Examples
use hurray_core::PerChannelAffine;
let q = PerChannelAffine::new_symmetric(1, 2).unwrap();
assert!(q.is_symmetric());
assert_eq!(q.zero_point_buffer_index(), None);Sourcepub fn is_symmetric(&self) -> bool
pub fn is_symmetric(&self) -> bool
Returns true if this descriptor uses symmetric quantization (no zero point).
§Examples
use hurray_core::PerChannelAffine;
assert!(PerChannelAffine::new_symmetric(0, 1).unwrap().is_symmetric());
assert!(!PerChannelAffine::new_asymmetric(0, 1, 2).unwrap().is_symmetric());Sourcepub fn axis(&self) -> u32
pub fn axis(&self) -> u32
Returns the quantization axis index.
§Examples
use hurray_core::PerChannelAffine;
let q = PerChannelAffine::new_symmetric(3, 1).unwrap();
assert_eq!(q.axis(), 3);Sourcepub fn scale_buffer_index(&self) -> u32
pub fn scale_buffer_index(&self) -> u32
Returns the buffer table index of the per-channel scale array.
§Examples
use hurray_core::PerChannelAffine;
let q = PerChannelAffine::new_symmetric(0, 5).unwrap();
assert_eq!(q.scale_buffer_index(), 5);Sourcepub fn zero_point_buffer_index(&self) -> Option<u32>
pub fn zero_point_buffer_index(&self) -> Option<u32>
Returns the buffer table index of the per-channel zero-point array, or
None if this descriptor is symmetric.
None maps to the wire sentinel 0xFFFFFFFF.
§Examples
use hurray_core::PerChannelAffine;
let asym = PerChannelAffine::new_asymmetric(0, 1, 2).unwrap();
assert_eq!(asym.zero_point_buffer_index(), Some(2));
let sym = PerChannelAffine::new_symmetric(0, 1).unwrap();
assert_eq!(sym.zero_point_buffer_index(), None);Sourcepub fn scale_type(&self) -> ElementType
pub fn scale_type(&self) -> ElementType
Returns the element type used for scale values (always Float32 in v1).
§Examples
use hurray_core::{ElementType, PerChannelAffine};
let q = PerChannelAffine::new_symmetric(0, 1).unwrap();
assert_eq!(q.scale_type(), ElementType::Float32);Sourcepub fn valid_storage_types() -> &'static [ElementType]
pub fn valid_storage_types() -> &'static [ElementType]
Returns the set of storage ElementTypes that are valid for this scheme.
Per docs/spec/quantization/per-channel-affine.md § Valid Storage Types.
WHY &'static [ElementType]: no allocation per call; slice::contains
over ≤10 items beats any hash structure (design decision #5).
§Examples
use hurray_core::{ElementType, PerChannelAffine};
assert!(PerChannelAffine::valid_storage_types().contains(&ElementType::Int8));
assert!(!PerChannelAffine::valid_storage_types().contains(&ElementType::Float32));Trait Implementations§
Source§impl Clone for PerChannelAffine
impl Clone for PerChannelAffine
Source§fn clone(&self) -> PerChannelAffine
fn clone(&self) -> PerChannelAffine
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more