metrale_core/
dtype.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-25: Element types for weights and scales, and the quantization layout of a weight tensor.
4//!
5//! Owner: core.
6//! Invariants: none beyond the types.
7
8use serde::{Deserialize, Serialize};
9
10/// 2026-09-25: Element type of a weight or scale tensor; the width is
11/// [`DType::element_size_bits`].
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub enum DType {
14    /// 2026-09-25: 4-bit float, 1 sign + 2 exponent + 1 mantissa bits; the
15    /// weight type of [`QuantConfig::nvfp4`].
16    E2M1,
17
18    /// 2026-09-25: 8-bit float, 1 sign + 4 exponent + 3 mantissa bits; the
19    /// block-scale type of [`QuantConfig::nvfp4`] and the weight type of
20    /// [`QuantConfig::fp8`].
21    FP8E4M3,
22
23    /// 2026-09-25: 8-bit float, 1 sign + 5 exponent + 2 mantissa bits.
24    FP8E5M2,
25
26    BF16,
27
28    FP16,
29
30    FP32,
31}
32
33impl DType {
34    /// 2026-09-25: Width of one element in bits (4 for `E2M1`).
35    pub const fn element_size_bits(&self) -> usize {
36        match self {
37            DType::E2M1 => 4,
38            DType::FP8E4M3 | DType::FP8E5M2 => 8,
39            DType::BF16 | DType::FP16 => 16,
40            DType::FP32 => 32,
41        }
42    }
43
44    pub const fn elements_per_u32(&self) -> usize {
45        32 / self.element_size_bits()
46    }
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct QuantConfig {
51    pub weight_type: DType,
52
53    pub scale_type: DType,
54
55    /// 2026-09-25: Weights per scale factor; 0 means one scale for the whole
56    /// tensor ([`QuantConfig::fp8`]).
57    pub group_size: usize,
58
59    pub global_scale_type: DType,
60}
61
62impl QuantConfig {
63    /// 2026-09-25: NVFP4: E2M1 weights, one FP8E4M3 scale per 16 weights, and
64    /// an FP32 tensor scale.
65    pub fn nvfp4() -> Self {
66        Self {
67            weight_type: DType::E2M1,
68            scale_type: DType::FP8E4M3,
69            group_size: 16,
70            global_scale_type: DType::FP32,
71        }
72    }
73
74    /// 2026-09-25: FP8E4M3 weights with FP32 per-tensor scales.
75    pub fn fp8() -> Self {
76        Self {
77            weight_type: DType::FP8E4M3,
78            scale_type: DType::FP32,
79            group_size: 0,
80            global_scale_type: DType::FP32,
81        }
82    }
83}