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 moreimpl Copy for PerChannelAffine
Source§impl Debug for PerChannelAffine
impl Debug for PerChannelAffine
impl Eq for PerChannelAffine
Source§impl Hash for PerChannelAffine
impl Hash for PerChannelAffine
Source§impl PartialEq for PerChannelAffine
impl PartialEq for PerChannelAffine
Source§fn eq(&self, other: &PerChannelAffine) -> bool
fn eq(&self, other: &PerChannelAffine) -> bool
self and other values to be equal, and is used by ==.