1use crate::float_layout::FloatLayout;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
18pub struct Digit {
19 pub radix: u16,
20 pub stride_bits: u16,
21}
22
23pub const MAX_DIGITS: usize = 4;
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
30pub struct Plane {
31 pub bits: u8,
32 pub base_bits: u32,
33 pub digits: [Digit; MAX_DIGITS],
34}
35
36impl Plane {
37 #[must_use]
39 pub const fn address(&self, index: usize) -> usize {
40 let mut remaining = index;
41 let mut address = self.base_bits as usize;
42 let mut position = 0;
43 while position < MAX_DIGITS {
44 let digit = self.digits[position];
45 let radix = digit.radix as usize;
46 address += (remaining % radix) * digit.stride_bits as usize;
47 remaining /= radix;
48 position += 1;
49 }
50 address
51 }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
56pub struct Coded {
57 pub code: FloatLayout,
59 pub low: Plane,
60 pub high: Option<Plane>,
61 pub bias: i16,
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
67pub struct Field {
68 pub layout: FloatLayout,
69 pub byte_offset: u16,
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
75pub struct SubBlocks {
76 pub count: u16,
77 pub scale: Coded,
78 pub min: Option<Coded>,
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
83pub struct BlockLayout {
84 pub elements: u16,
86 pub block_bytes: u16,
88 pub element: Coded,
90 pub multiplier: i16,
92 pub scale: Field,
93 pub min: Option<Field>,
94 pub min_multiplier: i8,
96 pub sub: Option<SubBlocks>,
97}
98
99const F16_SCALE: Field = field_at(FloatLayout::F16, 0);
100
101const fn field_at(layout: FloatLayout, byte_offset: u16) -> Field {
102 Field {
103 layout,
104 byte_offset,
105 }
106}
107
108const NO_DIGIT: Digit = Digit {
109 radix: 1,
110 stride_bits: 0,
111};
112
113const fn digit(radix: u16, stride_bits: u16) -> Digit {
114 Digit { radix, stride_bits }
115}
116
117const fn plane(bits: u8, base_bits: u32, digits: [Digit; MAX_DIGITS]) -> Plane {
118 Plane {
119 bits,
120 base_bits,
121 digits,
122 }
123}
124
125const fn coded(code: FloatLayout, low: Plane, high: Option<Plane>, bias: i16) -> Coded {
126 Coded {
127 code,
128 low,
129 high,
130 bias,
131 }
132}
133
134const fn nibbles(base_bits: u32, span: u16) -> Plane {
135 plane(
136 4,
137 base_bits,
138 [digit(span, 8), digit(2, 4), NO_DIGIT, NO_DIGIT],
139 )
140}
141
142const fn run(bits: u8, base_bits: u32, elements: u16) -> Plane {
143 plane(
144 bits,
145 base_bits,
146 [digit(elements, bits as u16), NO_DIGIT, NO_DIGIT, NO_DIGIT],
147 )
148}
149
150const fn linear(
151 elements: u16,
152 block_bytes: u16,
153 element: Coded,
154 multiplier: i16,
155 min: Option<Field>,
156) -> BlockLayout {
157 BlockLayout {
158 elements,
159 block_bytes,
160 element,
161 multiplier,
162 scale: F16_SCALE,
163 min,
164 min_multiplier: 1,
165 sub: None,
166 }
167}
168
169const QK_QS_PAIR_LANES: [Digit; MAX_DIGITS] = [digit(32, 8), digit(2, 4), digit(4, 256), NO_DIGIT];
170
171const K4_SCALE_BASE: u32 = 32;
172
173const fn k4_sub_blocks() -> SubBlocks {
174 let scale = coded(
175 FloatLayout::UINT6,
176 plane(
177 4,
178 K4_SCALE_BASE,
179 [digit(4, 8), digit(2, 64), NO_DIGIT, NO_DIGIT],
180 ),
181 Some(plane(
182 2,
183 K4_SCALE_BASE + 4,
184 [digit(4, 8), digit(2, 2), NO_DIGIT, NO_DIGIT],
185 )),
186 0,
187 );
188 let min = coded(
189 FloatLayout::UINT6,
190 plane(
191 4,
192 K4_SCALE_BASE + 32,
193 [digit(4, 8), digit(2, 36), NO_DIGIT, NO_DIGIT],
194 ),
195 Some(plane(
196 2,
197 K4_SCALE_BASE + 36,
198 [digit(4, 8), digit(2, 2), NO_DIGIT, NO_DIGIT],
199 )),
200 0,
201 );
202 SubBlocks {
203 count: 8,
204 scale,
205 min: Some(min),
206 }
207}
208
209impl BlockLayout {
210 pub const Q4_0: Self = linear(
211 32,
212 18,
213 coded(FloatLayout::UINT4, nibbles(16, 16), None, 8),
214 1,
215 None,
216 );
217 pub const Q4_1: Self = linear(
218 32,
219 20,
220 coded(FloatLayout::UINT4, nibbles(32, 16), None, 0),
221 1,
222 Some(field_at(FloatLayout::F16, 2)),
223 );
224 pub const Q5_0: Self = linear(
225 32,
226 22,
227 coded(
228 FloatLayout::UINT5,
229 nibbles(48, 16),
230 Some(run(1, 16, 32)),
231 16,
232 ),
233 1,
234 None,
235 );
236 pub const Q5_1: Self = linear(
237 32,
238 24,
239 coded(FloatLayout::UINT5, nibbles(64, 16), Some(run(1, 32, 32)), 0),
240 1,
241 Some(field_at(FloatLayout::F16, 2)),
242 );
243 pub const Q8_0: Self = linear(
244 32,
245 34,
246 coded(FloatLayout::INT8, run(8, 16, 32), None, 0),
247 1,
248 None,
249 );
250 pub const Q8_1: Self = linear(
251 32,
252 36,
253 coded(FloatLayout::INT8, run(8, 32, 32), None, 0),
254 1,
255 None,
256 );
257 pub const Q1_0: Self = linear(
258 128,
259 18,
260 coded(FloatLayout::UINT1, run(1, 16, 128), None, 1),
261 2,
262 None,
263 );
264 pub const Q2_0: Self = linear(
265 64,
266 18,
267 coded(FloatLayout::UINT2, run(2, 16, 64), None, 1),
268 1,
269 None,
270 );
271
272 pub const Q2_K: Self = Self {
273 elements: 256,
274 block_bytes: 84,
275 element: coded(
276 FloatLayout::UINT2,
277 plane(
278 2,
279 128,
280 [digit(16, 8), digit(2, 128), digit(4, 2), digit(2, 256)],
281 ),
282 None,
283 0,
284 ),
285 multiplier: 1,
286 scale: field_at(FloatLayout::F16, 80),
287 min: Some(field_at(FloatLayout::F16, 82)),
288 min_multiplier: -1,
289 sub: Some(SubBlocks {
290 count: 16,
291 scale: coded(
292 FloatLayout::UINT4,
293 plane(4, 0, [digit(16, 8), NO_DIGIT, NO_DIGIT, NO_DIGIT]),
294 None,
295 0,
296 ),
297 min: Some(coded(
298 FloatLayout::UINT4,
299 plane(4, 4, [digit(16, 8), NO_DIGIT, NO_DIGIT, NO_DIGIT]),
300 None,
301 0,
302 )),
303 }),
304 };
305 pub const Q3_K: Self = Self {
306 elements: 256,
307 block_bytes: 110,
308 element: coded(
309 FloatLayout::UINT3,
310 plane(
311 2,
312 256,
313 [digit(16, 8), digit(2, 128), digit(4, 2), digit(2, 256)],
314 ),
315 Some(plane(
316 1,
317 0,
318 [digit(16, 8), digit(2, 128), digit(4, 1), digit(2, 4)],
319 )),
320 4,
321 ),
322 multiplier: 1,
323 scale: field_at(FloatLayout::F16, 108),
324 min: None,
325 min_multiplier: 1,
326 sub: Some(SubBlocks {
327 count: 16,
328 scale: coded(
329 FloatLayout::UINT6,
330 plane(4, 768, [digit(4, 8), digit(2, 32), digit(2, 4), NO_DIGIT]),
331 Some(plane(
332 2,
333 832,
334 [digit(4, 8), digit(4, 2), NO_DIGIT, NO_DIGIT],
335 )),
336 32,
337 ),
338 min: None,
339 }),
340 };
341 pub const Q4_K: Self = Self {
342 elements: 256,
343 block_bytes: 144,
344 element: coded(FloatLayout::UINT4, plane(4, 128, QK_QS_PAIR_LANES), None, 0),
345 multiplier: 1,
346 scale: F16_SCALE,
347 min: Some(field_at(FloatLayout::F16, 2)),
348 min_multiplier: -1,
349 sub: Some(k4_sub_blocks()),
350 };
351 pub const Q5_K: Self = Self {
352 elements: 256,
353 block_bytes: 176,
354 element: coded(
355 FloatLayout::UINT5,
356 plane(4, 384, QK_QS_PAIR_LANES),
357 Some(plane(
358 1,
359 128,
360 [digit(32, 8), digit(2, 1), digit(4, 2), NO_DIGIT],
361 )),
362 0,
363 ),
364 multiplier: 1,
365 scale: F16_SCALE,
366 min: Some(field_at(FloatLayout::F16, 2)),
367 min_multiplier: -1,
368 sub: Some(k4_sub_blocks()),
369 };
370 pub const Q6_K: Self = Self {
371 elements: 256,
372 block_bytes: 210,
373 element: coded(
374 FloatLayout::UINT6,
375 plane(
376 4,
377 0,
378 [digit(32, 8), digit(2, 256), digit(2, 4), digit(2, 512)],
379 ),
380 Some(plane(
381 2,
382 1024,
383 [digit(32, 8), digit(4, 2), digit(2, 256), NO_DIGIT],
384 )),
385 32,
386 ),
387 multiplier: 1,
388 scale: field_at(FloatLayout::F16, 208),
389 min: None,
390 min_multiplier: 1,
391 sub: Some(SubBlocks {
392 count: 16,
393 scale: coded(
394 FloatLayout::INT8,
395 plane(8, 1536, [digit(16, 8), NO_DIGIT, NO_DIGIT, NO_DIGIT]),
396 None,
397 0,
398 ),
399 min: None,
400 }),
401 };
402 pub const Q8_K: Self = Self {
403 elements: 256,
404 block_bytes: 292,
405 element: coded(FloatLayout::INT8, run(8, 32, 256), None, 0),
406 multiplier: 1,
407 scale: field_at(FloatLayout::BF32, 0),
408 min: None,
409 min_multiplier: 1,
410 sub: None,
411 };
412}
413
414#[derive(Debug, Clone, Copy)]
417pub struct PlaneCursor {
418 plane: Plane,
419 counters: [u16; MAX_DIGITS],
420 address: usize,
421}
422
423impl Plane {
424 #[must_use]
426 pub const fn cursor(&self) -> PlaneCursor {
427 PlaneCursor {
428 plane: *self,
429 counters: [0; MAX_DIGITS],
430 address: self.base_bits as usize,
431 }
432 }
433}
434
435impl PlaneCursor {
436 #[must_use]
438 pub const fn address(&self) -> usize {
439 self.address
440 }
441
442 pub const fn advance(&mut self) {
444 let mut position = 0;
445 while position < MAX_DIGITS {
446 let digit = self.plane.digits[position];
447 let next = self.counters[position] + 1;
448 if next < digit.radix {
449 self.counters[position] = next;
450 self.address += digit.stride_bits as usize;
451 return;
452 }
453 self.counters[position] = 0;
454 self.address -= (digit.radix as usize - 1) * digit.stride_bits as usize;
455 position += 1;
456 }
457 }
458}