ferrum_quantization/gguf/source/
hadamard.rs1use std::collections::{BTreeMap, BTreeSet};
4use std::num::NonZeroU32;
5
6use ferrum_interfaces::vnext::{
7 ElementType, GroupedFeatureTranspose, HadamardApplication, HadamardSigns,
8 HadamardTransformSpec, ModelFamilyId, PhysicalWeightComponentBinding, PhysicalWeightLayout,
9 VNextError, WeightComponentRole, WeightComponentSpec, WeightEncoding, WeightId, WeightSchema,
10};
11
12use crate::gguf::{GgufHadamard, GgufHadamardDirection, GgufHadamardSigns, NativeGgufFile};
13
14pub fn hadamard_sign_component(width: u64) -> Result<WeightComponentSpec, VNextError> {
15 if width == 0 {
16 return Err(invalid("sign width must be nonzero"));
17 }
18 Ok(WeightComponentSpec {
19 id: WeightId::new(format!("gguf.hadamard.signs.width-{width}"))?,
20 role: WeightComponentRole::TransformSigns,
21 external_names: vec![format!("gguf.metadata.prism.hadamard.signs.{width}")],
22 dimensions: vec![width],
23 encoding: WeightEncoding::Dense {
24 element_type: ElementType::F32,
25 },
26 required: true,
27 })
28}
29
30pub fn hadamard_transform_spec(
31 metadata: &GgufHadamard,
32 name: &str,
33) -> Result<Option<HadamardTransformSpec>, VNextError> {
34 let Some(weight) = metadata.weight(name) else {
35 return Ok(None);
36 };
37 let signs = match metadata.signs() {
38 GgufHadamardSigns::Identity => HadamardSigns::Identity,
39 GgufHadamardSigns::Explicit(_) => {
40 HadamardSigns::Explicit(PhysicalWeightComponentBinding::exact_contiguous(
41 hadamard_sign_component(weight.input_width())?.id,
42 ))
43 }
44 };
45 let application = match weight.direction() {
46 GgufHadamardDirection::BeforeMatmul => HadamardApplication::BeforeMatmul {
47 input_permutation: weight.gdn_permutation().map(|permutation| {
48 GroupedFeatureTranspose {
49 inner_extent: permutation.head_dim,
50 first_outer_extent: permutation.key_heads,
51 second_outer_extent: permutation.repeats,
52 }
53 }),
54 },
55 GgufHadamardDirection::AfterEmbeddingLookup => HadamardApplication::AfterEmbeddingLookup,
56 };
57 Ok(Some(HadamardTransformSpec {
58 block_size: NonZeroU32::new(metadata.block_size())
59 .ok_or_else(|| invalid("zero block size"))?,
60 signs,
61 application,
62 }))
63}
64
65#[derive(Default)]
66pub(super) struct HadamardRegistry {
67 pub(super) components: BTreeMap<WeightId, (WeightComponentSpec, Vec<u8>)>,
68}
69
70impl HadamardRegistry {
71 pub(super) fn bind(file: &NativeGgufFile, schema: &WeightSchema) -> Result<Self, VNextError> {
72 schema.validate(&ModelFamilyId::new("source.gguf.hadamard")?)?;
73 let components: BTreeMap<_, _> = schema
74 .components
75 .iter()
76 .map(|component| (component.id.clone(), component))
77 .collect();
78 let mut consumed = BTreeSet::new();
79 for tensor in &schema.tensors {
80 bind_layout(
81 file,
82 &components,
83 &tensor.physical_layout,
84 None,
85 &mut consumed,
86 )?;
87 }
88 let expected: BTreeSet<_> = file
89 .hadamard()
90 .map(|metadata| metadata.weights().keys().map(String::as_str).collect())
91 .unwrap_or_default();
92 if consumed != expected {
93 return Err(invalid(
94 "weight schema does not consume every declared source transform",
95 ));
96 }
97 let mut registry = Self::default();
98 if let Some(metadata) = file.hadamard() {
99 if let GgufHadamardSigns::Explicit(signs) = metadata.signs() {
100 for weight in metadata.weights().values() {
101 let width = weight.input_width();
102 let spec = hadamard_sign_component(width)?;
103 if components.get(&spec.id).copied() != Some(&spec) {
104 return Err(invalid(
105 "sign component differs from its validated source declaration",
106 ));
107 }
108 if registry.components.contains_key(&spec.id) {
109 continue;
110 }
111 let values = signs
112 .get(&width)
113 .ok_or_else(|| invalid("missing source signs"))?;
114 let bytes = values
115 .iter()
116 .flat_map(|sign| f32::from(*sign).to_le_bytes())
117 .collect();
118 registry.components.insert(spec.id.clone(), (spec, bytes));
119 }
120 }
121 }
122 for component in &schema.components {
123 if component.role == WeightComponentRole::TransformSigns
124 && !registry.components.contains_key(&component.id)
125 {
126 return Err(invalid(
127 "sign component has no source metadata registry entry",
128 ));
129 }
130 }
131 Ok(registry)
132 }
133}
134
135fn bind_layout<'a>(
136 file: &'a NativeGgufFile,
137 components: &BTreeMap<WeightId, &WeightComponentSpec>,
138 layout: &PhysicalWeightLayout,
139 transform: Option<&HadamardTransformSpec>,
140 consumed: &mut BTreeSet<&'a str>,
141) -> Result<(), VNextError> {
142 match layout {
143 PhysicalWeightLayout::Hadamard {
144 values,
145 transform: declared,
146 } => {
147 if transform.is_some() {
148 return Err(invalid("nested source transforms are unsupported"));
149 }
150 bind_layout(file, components, values, Some(declared), consumed)
151 }
152 PhysicalWeightLayout::Composite { parts } if transform.is_none() => {
153 for part in parts {
154 bind_layout(file, components, &part.layout, None, consumed)?;
155 }
156 Ok(())
157 }
158 PhysicalWeightLayout::Dense { component_id } => {
159 bind_leaf(file, components, component_id, transform, consumed)
160 }
161 PhysicalWeightLayout::Stored { component } => bind_leaf(
162 file,
163 components,
164 &component.component_id,
165 transform,
166 consumed,
167 ),
168 PhysicalWeightLayout::BlockQuantized { blocks, .. } => {
169 bind_leaf(file, components, &blocks.component_id, transform, consumed)
170 }
171 _ => Err(invalid(
172 "GGUF transform binding requires per-projection dense or block leaves",
173 )),
174 }
175}
176
177fn bind_leaf<'a>(
178 file: &'a NativeGgufFile,
179 components: &BTreeMap<WeightId, &WeightComponentSpec>,
180 component_id: &WeightId,
181 transform: Option<&HadamardTransformSpec>,
182 consumed: &mut BTreeSet<&'a str>,
183) -> Result<(), VNextError> {
184 let component = components
185 .get(component_id)
186 .ok_or_else(|| invalid("missing weight component"))?;
187 let [name] = component.external_names.as_slice() else {
188 return Err(invalid("GGUF leaf must bind one physical tensor"));
189 };
190 let expected = file
191 .hadamard()
192 .map(|metadata| hadamard_transform_spec(metadata, name))
193 .transpose()?
194 .flatten();
195 if transform != expected.as_ref() {
196 return Err(invalid(format!(
197 "source transform for {name:?} is missing or differs from its declared layout"
198 )));
199 }
200 if expected.is_some() {
201 let (name, _) = file
202 .hadamard()
203 .unwrap()
204 .weights()
205 .get_key_value(name)
206 .unwrap();
207 if !consumed.insert(name.as_str()) {
208 return Err(invalid("source transform is consumed more than once"));
209 }
210 }
211 Ok(())
212}
213
214fn invalid(reason: impl std::fmt::Display) -> VNextError {
215 VNextError::InvalidExecutionPlan {
216 reason: format!("GGUF Hadamard source binding: {reason}"),
217 }
218}