diskformer 0.5.4 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,511 @@
1
+ /* iq_quants.js — llama.cpp's block quant formats as WGSL, read straight from the GGUF bytes.
2
+ *
3
+ * Covers the types an imatrix "IQ-mix" GGUF mixes (Underdog Saluki 27B uses all eleven): Q8_0, Q2_K, Q4_K,
4
+ * IQ1_S, IQ1_M, IQ2_XXS, IQ2_XS, IQ2_S, IQ3_XXS, IQ3_S, IQ4_XS; and Q6_K and Q5_0, which a Q4_K_M GGUF adds (Ling 3.0
5
+ * Flash). Q6_K and Q5_0 are read unpadded, so their rows can sit at any even byte offset (a raw copy of GGUF bytes). A tensor stays in (nearly) its GGUF block layout
6
+ * on the GPU, one array<u32>: blocks of 4k+2 bytes get two bytes of padding after their f16 scale (repackKernel),
7
+ * so every field is word-aligned. `deq8(B, s, g)` returns weights 8g..8g+7 of 32-value chunk s of the block at
8
+ * byte offset B, transcribed from ggml-quants.c's dequantize_row_* so the values are the ones llama.cpp computes.
9
+ *
10
+ * Kernels (generated per type, sharing one binding layout):
11
+ * mvKernel(t) y[m] = Σ_k W[m][k]·x[k] bindings: x, wq, grid, y, P{M, N, rowBytes (GPU layout)}
12
+ * mmKernel(t) y[t·M + m] = Σ_k x[t·N + k]·W[m][k] + Q{T, …}; tiles of 64 rows × 64 tokens
13
+ * mmSgKernel(t) the same on subgroup matrices (f16 in, f32 accumulate) where the adapter has them
14
+ * embedKernel(t) y[i] = W[token][i] bindings: wq, grid, y, Tok, P{N, rowBytes}
15
+ * embedBKernel(t) the same for T token ids bindings: wq, grid, ids, y, P, Q
16
+ * The codebooks (iq2 / iq3 / iq1 grids, kvalues_iq4nl) live in one storage buffer: gridData().
17
+ */
18
+
19
+ export const QTYPES = {
20
+ // id: GGML type id. block: bytes per block. qk: values per block.
21
+ Q8_0: { id: 8, block: 34, qk: 32 },
22
+ Q2_K: { id: 10, block: 84, qk: 256 },
23
+ Q4_K: { id: 12, block: 144, qk: 256 },
24
+ // Q6_K and Q5_0 blocks (210, 22 bytes) are 2 mod 4 and stay unpadded: their deq8 reads bytes and halves only.
25
+ Q6_K: { id: 14, block: 210, qk: 256 },
26
+ Q5_0: { id: 6, block: 22, qk: 32 },
27
+ IQ2_XXS: { id: 16, block: 66, qk: 256 },
28
+ IQ2_XS: { id: 17, block: 74, qk: 256 },
29
+ IQ3_XXS: { id: 18, block: 98, qk: 256 },
30
+ IQ1_S: { id: 19, block: 50, qk: 256 },
31
+ IQ3_S: { id: 21, block: 110, qk: 256 },
32
+ IQ2_S: { id: 22, block: 82, qk: 256 },
33
+ IQ4_XS: { id: 23, block: 136, qk: 256 },
34
+ IQ1_M: { id: 29, block: 56, qk: 256 },
35
+ };
36
+ export const QTYPE_BY_ID = Object.fromEntries(Object.entries(QTYPES).map(([name, t]) => [t.id, name]));
37
+ export const rowBytes = (type, cols) => (cols / QTYPES[type].qk) * QTYPES[type].block;
38
+
39
+ // BEGIN GENERATED GRIDS (node scripts/build-iq-grids.mjs)
40
+ const KVALUES_IQ4NL = [-127, -104, -83, -65, -49, -35, -22, -10, 1, 13, 25, 38, 53, 69, 89, 113];
41
+ const GRIDS = {
42
+ iq2xxs: 'AAACAAUACAAKABEAFAAgACIAKAAqAEEARABQAFgAYQBkAIAAggCKAKIAAQEEARABFQFAAYQBmAEAAgICIgKCAgEEBAQQBCEEJARABEIESARgBIEEhASQBKQEAAUCBQgFIAVGBWkFgAWRBQkGEAZABoQGpAYACAUICAgUCCgIQQhECFAIUgiICAQJQAkCChQKARAEEBAQIRBAEGAQhBCQEJUQABEIESARUBFaEYARJBJFEgAUCBQgFCUUSRSAFBgVYhUAFhYWARgEGBAYQBiBGAAZBRmgGVEaACACIAogRCBhIIAggiApIUghACICIgEkBCQQJEAkViQAJUElZCWQJggoICiUKEQqAUAEQBBAGEAhQCRAQEBIQFZAYECBQIRAkEAAQSBBYUGAQYVBAUIQQkhCVkJoQgBECEQgRIBEmUQSRSRFAEYBSARIEEhASEVIAElYSWFJgklFSpBKAFAIUBFQGVAgUIBQiFAEUUJRpFGRUpBUklQKVQFWVFYAWBFYGVhkWEBZCFoEYBBgQGBoYABhVWEYYmBiAGQFZBBlEmWEZUJoAIACgAqAQYCCgASBGIFAgRGCAYQEhBCEFYRAhGCEAIVGhZSFCYZAhmCGAogEiRGKBJAQkCSQQJChkBaRgJFFkgCUIpRElFGVgZggmQKgUKCFoAmhAKIYpFCoBKk=',
43
+ iq2xs: 'AAACAAUACAAKABEAFAAWABkAIAAiACUAKABBAEQARgBJAFAAUgBVAFgAYQBkAIAAggCFAIgAkQCUAJkAoAABAQQBBgEJARABEgEVARgBGgEhASQBQAFCAUUBSAFRAVQBYAFoAYEBhAGQAQACAgIFAggCEQIUAiACQQJEAlACVQKAAooCAQQEBAYECQQQBBIEFQQYBCEEJARABEIERQRIBFEEVARWBGAEgQSEBJAEAAUCBQUFCAURBRQFIAVBBUQFUAVhBYAFAQYEBhAGJgZABkIGhAYACAIIBQgICAoIEQgUCCAIJQhBCEQIUAhYCIAIoAiqCAEJBAkQCUAJgQmJCQAKIAooCpYKoAoBEAQQBhAJEBAQEhAVEBgQIRAkEEAQQhBFEEgQURBUEGAQahCBEIQQkBAAEQIRBREIERERFBEgEUERRBFQEYARlBGWEQESBBIGEhASQBJgEgAUAhQFFAgUERQUFCAUQRREFEkUUBRkFIAUARUEFRAVQBUAFhQWSRYBGAQYEBgSGEAYVBiGGAAZBRlmGVEaqRoAIAIgBSAIIAogESAUICAgQSBEIFAggCCgIAEhBCEQIUAhSCFlIQAiIiKAIqgiASQEJBAkKSRAJAAlQSVSJZklASYaJqYmACgIKAooIChVKIgooihoKZApCCogKoIqiCqKKgFABEAGQAlAEEASQBVAGEAhQCRAQEBCQEVASEBKQFFAVEBgQGVAgUCEQJBAAEECQQVBCEERQRRBIEFBQURBUEGAQYVBokEBQgRCEEISQilCQEIARAJEBUQIRBFEFEQZRCBEQURERFBEgESURAFFBEUQRSRFQEWaRQBGCkZERlBGAUgESBBIQEhFSFRIYkgASRFJRElQSWlJBEoAUAJQBVAIUBFQFFAgUChQQVBEUFBQgFABUQRREFEVUUBRQlEAUkRSqlIBVARUEFQhVEBUYFSBVKFUAFUIVYBViFUhVmhWoVYAWBRYQVhQWJlYGllAWUJZhVoBYARgEGBAYFRgYmCGYKlgAGEkYkpikmIAZBZkEGVAZUVlpGUBaGpoJWkGalRqYmoAgAKABYAIgBGAFIAggCqAQYBEgFCAgICCgKiAqoABgQSBBoEQgUCBUYFZgQCCIIKAgoKCoIKoggGEBIQQhBKEFYRAhGCEiYQAhUSFpYUYhmqGAIgIiCWIWoiAiIKIqIgGiSKKgIqIipaKqIoBkASQEJBAkFaQhJAAkSKRZJFWkomSAJQFlESUUJRYlCmVkJWSlUGWUZimmEmZFZpgmgCgAqAIoAqgIKAqoKCgUaFZoaahAKICogiiKqKAoqCiQKSVpGWmmKYKqCCoIqgoqKCoqKgEqYSphqkoqiqqkaqqqg==',
44
+ iq2s: 'AAACAAUACAAKABEAFAAWABkAIAAiACUAKABBAEQARgBJAFAAUgBVAFgAYQBkAGYAaQCAAIIAhQCIAJEAlACgAKUAqgABAQQBBgEJARABEgEVARgBIQEkAUABQgFFAUgBUQFUAVYBWQFgAWUBaAGBAYQBkAGSAZUBoQGkAQACAgIFAggCEQIUAiACKgJBAkQCRgJJAlACVQKAAoUCigKUAqICAQQEBAYECQQQBBIEFQQYBCEEJAQmBCkEQARCBEUESARKBFEEVARWBFkEYARiBGUEgQSEBIYEiQSQBJUEmAShBKQEAAUCBQUFCAUKBREFFAUWBRkFIAUlBSgFQQVEBUYFSQVQBVIFVQVYBWEFZAWABYIFhQWIBZEFlAWgBQEGBAYGBgkGEAYVBkAGRQZIBlEGVAZgBoEGhAaQBgAIAggFCAgIEQgUCBYIGQggCCUIKghBCEQIRghJCFAIUghVCFgIYQhkCIAIhQiUCKoIAQkECRAJEgkVCRgJIQlACUUJSAlRCVQJYAmBCZAJAAoRChQKIgooCioKUAqZCgEQBBAGEAkQEBASEBUQGBAhECQQJhBAEEIQRRBIEFEQVBBWEFkQYBBiEGUQaBCBEIQQhhCQEJUQmBChEKQQABECEQURCBEKERERFBEWERkRIBEiESURKBFBEUQRRhFJEVARUhFVEVgRYRFkEYARghGFEYgRkRGUEQESBBIJEhASFRIhEiQSQBJFElESVBKBEoQSkBIAFAIUBRQIFBEUFBQWFBkUIBQlFCgUQRREFEYUSRRQFFIUVRRYFGEUZBSAFIIUhRSIFJEUlBSgFAEVBBUGFQkVEBUSFRUVGBUhFSQVQBVCFUUVSBVRFVQVYBWBFYQVkBUAFgUWCBYRFhQWIBZBFkQWUBaAFqoWARgEGAYYCRgQGBUYGBghGEAYQhhFGEgYURhUGGAYgRiEGAAZAhkFGQgZERkUGSAZQRlEGVAZaRmiGQQaEBpAGlYaACACIAUgCCARIBQgFiAZICAgJSAqIEEgRCBQIFIgVSBkIIAgiiCUIKogASEEIRAhEiEVISEhQCFCIUUhUSFUIWAhgSGEIZAhACIKIiIiKCIqIkQiUCKIIooiqCIBJAQkBiQJJBAkFSQYJCEkJCRAJEIkRSRIJFEkVCRgJIEkhCSQJAAlBSUIJRElFCUgJUElRCVQJWYlgCUBJgQmECZAJlkmACgFKBEoFChBKEQoUCiKKKooASkEKRAplSkKKiIqZCqIKooqAUAEQAZACUAQQBJAFUAYQBpAIUAkQCZAQEBCQEVASEBKQFFAVEBWQFlAYEBiQGVAgUCEQJBAlUCYQKFApEAAQQJBBUEIQRFBFEEWQRlBIEEiQSVBQUFEQUZBSUFQQVJBVUFYQWFBZEGAQYJBhUGIQZFBlEGgQQFCBEIQQhJCFUIYQiRCQEJFQkhCUUJUQmBCgUKEQgBEAkQFRAhECkQRRBREFkQZRCBEIkQlRChEQUREREZESURQRFJEVURYRGFEZESARIJEhUSIRJFElESgRAFFBEUGRQlFEEUSRRVFGEUhRSRFQEVCRUVFSEVRRVRFYEVqRYFFhEWQRQBGAkYFRghGEUYURiBGQUZERlBGgEalRgFIBEgJSBBIEkgVSBhIIUgkSEBIQkhFSEhIUUhUSGBIhEiQSABJAkkFSQhJEUkUSSBJQUlESVBJgEmWSQFKBEoQSkBKAFACUAVQCFARUBRQFlAZUCBQIlAlUChQQVBEUEZQSVBQUFJQVVBYUGFQZFCAUIJQhVCIUJFQlFABUQRRBlEJURBRElEVURhRIVEkUUBRQlFFUUhRUVFUUWBRgVGEUZBRAFIFUghSEVIUUiBSQVJEUlBSaVKAUgFUBFQGVAlUEFQSVBVUGFQhVCRUQFRCVEVUSFRRVFRUYFSBVIRUkFQAVQJVBVUIVRFVFFUgVUFVRFVQVYBVAVYEVhBWJlZAVgBYAlgFWAhYEVgUWCBYQVhEWFBYWliAWAFZBFkQWUBZAFoZWoVaqFoBYARgBmAQYBJgFWAYYCFgJGBAYEVgSGBRYFRgYGCEYJBgAGECYQVhCGERYRRhIGFBYURhUGGAYZlhBGIQYkBiVmKhYgBkBWQIZBFkFGQgZEFkRGRQZIBkAWUEZRBlQGVKZWhlkmUAZpRmAWgEaBBoZWiYaABpKmlCaqFqAIACgAWACIARgBSAGYAggCWAQYBEgFCAUoBVgFiAYYCAgIWAkYCUgAGBBIEJgRCBEoEVgRiBIYEkgUCBQoFFgUiBUYFUgYGBhIGQgamBAIIFggqCEYIUgkGCRIJQggGEBIQGhAmEEIQShBWEGIQhhECEQoRFhEiEUYRUhGCEgYSEhJCEAIUChQWFCIURhRSFIIVBhUSFUIWAhYqFAYYEhhCGKYZAhgCIBYgRiBSIQYhEiFCIoogBiQSJQIlliSKKWIpaioKKoooBkASQCZAQkBKQFZAYkCSQQJBCkEWQSJBRkFSQYJCBkISQkJAAkQWREZEUkUGRRJFQkVqRAZIEkhCSQJKmkgCUApQFlAiUEZQUlCCUQZRElFCUgJSWlAGVBJUQlUCVmJWhlQCWRpZklgGYBJgQmCaYQJipmACZSZlSmZCaAKAFoAqgFKAioCqgQaBEoFCgoqCqoEChZaECogqiIqIooiqigqKIooqiqKIBpASkEKRApImkpKQApRmlUaYKqCiooqhUqYapCKoKqiCqIqooqoiqqqo=',
45
+ iq3xxs: 'AAACAAQACQALAA8AEAASABkAIgA7AD0AQQBDAEgASgBRAFUAWABaAGEAbAB4AIAAggCEAIkAkACSAJkAmwCfAKkArwC9AMEAxwDIAMoA1QD4AAsBHwEkAS8BOwE9AUEBRwFaAWoBnQG0AcgBzAHOAeMB8QEBAgMCCAIKAhECEwIYAhoCHAInAigCQAJCAkkCUAJSAoECgwKIAooCkQKYAroCwALCAtAC2QLmAvYCAQMFAygDUANUA2YDeQOFA9ID4AMABAIECQQLBBAEEgQWBBkEIgRBBEMERQRIBEoEUQRYBHMEdwR4BIAEggSJBI8EkASSBJ8EoAStBMEEyATMBPgE/AQdBSsFQwVXBWEFfAXBBcMFzgXlBQEGCAYKBhEGEwYoBjUGOgZABkIGUAZZBmQGZgaBBoMGiAaVBqoGugbJBtsGGAcnBzoHQAdGB1IHbQeMB54HswfbB/AHBAgPCB0IHwgrCC8IfAiQCJ8IoAiwCLYIxwjlCAQJKQk0CVUJYwl4CcUJyAnKCdgJCgohCjgKQApGClYKbQqMCpoKugrCCusKCAsTCxcLOgtCC1kLqAvUC+ILFAwkDCYMNAxRDHEMjwy0DNgM3gwkDUUNag2bDcMN0Q0DDgUOBw4IDhoOKg5WDmAOig6lDqoOwA7NDtsO8A4RDyEPQA9CD1QPmA8=',
46
+ iq3s: 'AAABAAIABQAHAAgACQAKAAwADgAQABEAFQAbACAAIgAlACcAKQArADAAMgA5ADwAPwBAAEEAQgBEAEgASQBNAFAAUwBXAFkAXQBkAHEAdQB6AIAAgQCFAIcAiACLAI4AkQCVAJgAnACiAKUApwCpAKsAuAC7AMMAyQDNANAA0gDZANsA3gDkAOgA6gD3APkA/QAAAQsBDwERARQBGgEgASMBKQE4AUIBRAFQAVIBVgFbAWEBZQFnAXYBewGGAYkBiwGZAaoBuQHAAcIBxAHQAdIB1gHbAegB7AEAAgECAgIEAggCCQILAg0CDwIQAhICGQIcAh4CLAIuAjECOgJAAkECQwJGAkgCTAJRAlgCWwJhAmgCagJ4An4CgAKKAo0CjwKQApQCmgKgAqMCrQKwAroCwQLEAscCyALLAtEC1wLYAtwC4QLyAvgCAwMFAwoDDAMZAxsDIgMmAygDLANBA0gDSwNRA1gDWgNpA5ADlAOXA6QDpgPBA8MDyAPKA9ED3QPhA/ID+AMABAEEAwQFBAcECAQKBAwEDgQRBBMEFwQYBBoEIQQjBCUEKAQqBDcEOAQ7BD0EQARCBEgESwRPBFIEVQRZBFwEYgRpBIEEhASHBJEEkwSYBJ8EoQSrBK8EuQS8BMAEwgTFBMkE0gTUBNkE2wTiBOgE9gQBBQcFEAUTBRoFHQUhBToFPQVEBUkFUgVfBWAFawV4BYAFggWHBZEFrQWxBcUFyQXWBdgF4wXoBQIGCQYLBg0GDwYSBhkGGwYdBiIGJAYnBikGMwY5BkEGQwZFBkwGUQZTBmAGcAZ6Bn4GgAaKBpAGmgacBqgGwQbIBswG0QbTBtcG2AbhBuMG5wbtBvsGAwcJBw4HEgcZByoHMAc0B0EHSAdKB1UHWgdkB24HeweOB6EHwQfDB9AH0gfdBwAIBAgKCBAIFAgXCBoIIQgoCDgIQghHCEkISwhSCFgIXQhjCGkIbQiBCIMIiAiNCJEImwigCK8Isgi4CMQIyQjLCNAI0gjZCN0IAAkCCRQJHwkgCTkJRQlHCVEJcgmLCZwJsAnICc0J2AnjCekJAgoICgwKEgogCiQKJwoqCjYKPApBCkMKRQpKClEKWgp6CoAKiQqTCpgKngqrCsIKxwrICtcK5ArpCvUK+woBCwQLEAsaCyYLSgtWC2kLawuiC8ILxAvSCwkMCwwNDBkMGwwwDEAMUAxXDHQMigycDKIMrQyyDLgMwAzMDNEM4AwVDSMNMg1ADUMNXA1wDYUNoA3JDcsNAA4EDgcOEA4SDh4OIA4sDjIOQg5JDlQOYw5lDoEOhA6IDo4OkQ6YDqkOwg7aDt0O6w4BDwUPCw8QDygPUg9iD4IPmQ/ADw==',
47
+ iq1s: 'AAACAAUACAAKABEAFQAgACIAKAAqAEUAUQBUAFYAZQCAAIIAiACKAJUAoACiAKgAqgAEAQUBEQEUARYBGQEaASUBQQFGAUkBUgFVAVoBYQFkAWYBaAGFAZEBlAGWAaUBAAICAggCCgIVAiACIgIoAioCRQJRAlkCZAJpAoACggKIAooCkQKVApkCoAKiAqgCqgIRBBQEFgQlBEEESQRVBFoEZARlBJEEmQSlBAEFBAUFBQYFFQUYBRoFKQVABUUFSgVQBVEFVAVVBVYFWQVgBWIFZQVoBWoFgQWRBZUFmAWaBaEFpAWlBaYFqQUUBhkGQQZEBlAGUgZVBlgGYAZhBmYGaQaFBpEGlAaZBgAIAggICAoIFQggCCIIKAgqCEUIUQhWCGUIgAiCCIgIigiVCKAIogioCKoIBQkRCRQJGQkkCSUJQQlQCVEJVQlhCWQJaQmRCZQJlgmZCaUJAAoCCggKCgoVCiAKIgooCioKRQpRClkKYQplCoAKggqFCogKigqVCqAKogqoCqoKEBAREBQQGRAkECUQQRBEEFAQVRBYEGEQZBBlEGkQkRCUEJYQoRClEAERBBEGEQkREBESERURGBEhESQRKRFFEUoRUBFREVIRVBFVEVYRWRFgEWURhBGSEZURoRGkERESFBIWEiUSQBJGEkkSUhJVElgSWhJkEmYShRKREpQSlhKlEgEUBhQJFBQUFRQYFBkUIRQmFEEURRRGFEgUShRRFFQUVRRWFFkUYhRlFGgUhBSJFJAUlBSVFJgUmRSaFKEUpBSlFKkUAhUFFQoVERUUFRUVFhUZFSAVIhUlFSgVKhVBFUQVRRVGFVEVUhVUFVUVVhVZFVoVYRVkFWUVZhVpFYAVghWEFYUViBWKFZAVkRWUFZUVlhWZFZoVoBWiFaUVARYEFgUWBhYVFhYWGBYaFiEWJhZAFkIWRBZFFkgWShZRFlUWVhZYFlkWYRZkFmUWaBZpFmoWhhaKFpIWlRakFqkWERgWGCUYQRhEGEYYSRhQGFUYWBhaGGAYYRhkGGYYaRiFGJEYlBilGBAZEhkVGRoZIRklGUIZRBlFGUgZURlUGVUZVhlZGVoZYBllGWoZiRmRGZIZlRmYGaEZphmpGQkaFhokGiYaRBpGGkkaUBpSGlUaWBphGmYaaRqFGpEalhqaGgAgAiAIIAogFSAgICIgJSAoICogRSBRIFkgYSBlIIAggiCIIIoglSCgIKIgpSCoIKogBSERIRQhGSElIUIhRCFJIVUhWCFaIWEhZCFlIWYhhSGQIZYhmSGlIQEiCCIKIhEiFSIgIiIiKCIqIkUiUSJWIlkiZSKBIogiiiKRIpUioCKiIqgiqiIFJBQkFiQZJCUkRCRFJEYkSSRSJFUkWCRaJGYkhSSRJJQkmSShJKUkCSUVJSElKSVAJUUlSCVRJVQlVSVZJWIlZSVoJYklkCWUJZUlmCWaJaElpCWmJaklBSYQJhImGSYlJkEmSSZVJmAmYSZpJoQmhiaQJpomACgCKAgoCigVKCAoIigoKCooRShRKFQoZSiAKIIoiCiKKKAooiioKKooCSkRKRQpGSklKUYpSSlSKVUpYSlkKWYpaSmFKZAplimZKaQppSkAKgIqCCoKKiAqIiooKioqRSpRKlYqWSplKoAqgiqIKooqlSqgKqIqqCqqKgVAEUAWQCVASUBSQFVAWEBaQGFAZEBmQJRAmUChQKZAAEEBQQRBBkEJQRJBFUEWQRhBGkEhQSZBKUFFQUhBSkFRQVRBVUFWQVlBWkFlQWhBakGBQYRBhkGQQZJBlUGgQaFBokEFQhFCFEIWQiVCQUJSQlVCWkJkQmlCiUKUQqVCAUQVRBlEKURFREhESkRRRFREVURWRGFEYkRlRGhEakSBRIZEiUSQRJJElUSgRKFEqUQBRQJFBUUKRRFFFEUVRRZFGUUgRSVFKkVBRURFRUVGRUlFUEVRRVRFVUVWRVhFWUVhRWRFZUVmRWlFgkWERYVFiEWRRZRFlUWWRZlFmkWlRahFqkUBRgVGCUYURhVGGEYaRiFGJEYpRkBGQkZFRkhGUEZRRlJGVUZWRllGYkZlRmhGgUaFRopGlEaVRqFGpEamRgVIEUgVSBpIJUhCSElIUEhVSFhIYUhkSGZIaUiFSJFIlEiWSJlIpUgBSQVJBkkKSRBJFEkVSRhJIUkkSSZJQElFSUpJUUlSSVRJVUlWSVlJYEliSWVJZklqSYZJiUmSSZVJlkmYSaFJpEmmSalJFkpESkZKSUpVSlhKWkpkSmlKlEqlSgFQBFAFUAZQCVASUBVQGlAhUCRQKVBAUEVQSFBRUFRQVVBWUFlQZVBoUIZQiVCVUJhQoFChUKZQqVAFUQhRCVEKURFRFFEVURZRGFEZUSBRJVEmUShRKlFBUURRRVFGUUlRUFFRUVJRVFFVUVZRWFFZUVpRYVFkUWVRZlFpUYJRhVGRUZRRlVGWUZlRoFGlUapRAVIGUhJSFVIaUiFSJFJCUkVSSlJRUlRSVVJWUllSYlJlUoVSkFKSUpVSmVKaUqRSBFQFVBFUFFQVVBZUGFQZVCFUJVQoVCpUQVREVEVURlRJVEpUUFRRVFRUVVRWVFhUWVRaVGFUYlRkVGVUZlRpVIBUiFSKVJFUlFSVVJZUmVShVKRUpVSqVAFVAlUEVQVVBlUJVRBVEVUSVRRVFVUWVRlVGlUhVSRVJVUmVSlVQFVBVUJVRFVFVUZVSFVJVVBVUVVSVVRVVVVWVVhVWVVaVWBVYVVkVWVVZlVoVWlValWBVYRVhVWJVYpVkFWRVZRVlVWWVZhVmVWhVaRVpVWmValVAFYBVgJWBFYGVghWCVYRVhRWFVYYVhlWIFYhViJWJFYlViZWKFYpVkFWRVZGVkhWSVZKVlBWUVZSVlRWVVZWVlhWWVZaVmFWZFZlVmlWglaFVoZWiFaJVopWkVaVVppWolalVqZWqFapVgRYBVgGWAlYEFgVWBhYIVgqWEVYSFhKWFFYVFhVWFZYWFhZWGBYYlhkWGVYgliJWJBYkliVWJhYoVipWAFZAlkFWQpZEVkUWRVZFlkZWSVZQVlEWUVZRllJWVBZUVlSWVRZVVlWWVhZWVlaWWFZZFllWWZZaVmBWYVZiVmRWZRZlVmWWZhZmVmlWQRaCFoVWhpaIFolWiZaKVpFWkhaSVpRWlVaVlpYWllaYlplWmhaalqBWopaklqVWpZamFqaWqFaBWAUYBZgGWAlYERgUGBVYFZgWGBaYGFgZGBmYGlggWCWYKVgAWEEYQZhCWESYRVhIWEiYSZhKWFFYUlhUWFVYVZhWWFlYWZhamGEYYphkmGVYaFhpmGpYRFiFmIZYkBiQWJGYlViVmJYYmBihWKRYpZipWIRZBJkFWQWZBpkIWQmZClkQGRCZEVkSGRKZFFkVGRVZFZkWWRaZGBkYmRlZIRkhWSJZJBkkmSUZJVklmSYZJpkoWSkZKlkBWUIZQplEWUVZRZlGWVEZUVlRmVJZVBlUWVUZVVlVmVZZWFlZGVlZWZlaWWGZYllimWRZZVllmWZZZplomWlZaZlqGUCZglmFWYgZiZmKGYpZkBmRWZIZkpmUWZUZlVmVmZYZlpmYGZlZmhmgGaCZoVmimaUZpZmmGaZZqBmpGamZqpmFmgZaCVoQWhSaFVoWmhhaGlohWiRaJhopmgBaQRpEGkVaSFpJGkmaSlpQGlBaUVpRmlIaVFpVGlVaVZpWWlgaWVpammCaYRpimmVaaFppGmlaalpEWoWahhqQWpEaklqUGpValhqWmpkamVqaWqGapRqmGqaaqZqAIACgAiACoAggCKAKIAqgEWAUIBRgFSAVoBZgGWAgICCgIiAioCVgKCAooCogKqABYERgRSBFoEZgSWBQYFEgUmBUIFSgVWBVoFYgVmBZIFmgWmBhYGJgZSBloGZgaWBAIICggiCCoIVgiCCIoIogiqCUYJUglmCZYKAgoKCiIKKgpWCoIKigqiCqoIUhBmEQYREhFGEVYRahGGEZIRphJSEmYQBhQmFEoUVhRqFJoUphUCFQYVFhUiFUYVUhVWFVoVZhVqFZYVmhWiFaoWBhYSFhoWJhZCFkoWVhZiFpoURhhaGGYYlhkGGRIZJhkqGUIZVhlmGWoZhhmaGaoaFhpGGmoakhgCIAogIiAqIFYggiCKIKIgqiEGIRYhRiFSIWYhliGmIgIiCiIiIioiViKCIooioiKqIBYkGiRGJFIkWiSWJQYlEiUaJSYlQiVKJVYlaiWGJZImFiZaJmYmliQCKAooIigqKFYogiiKKKIoqikWKUYpUilaKgIqCioiKioqViqCKooqoiqqKBZARkBaQGJAZkCWQQZBGkEmQVZBYkFqQaZBqkIWQkZCUkJaQmZClkAGRBJEGkQmREJEVkRiRGpEhkSSRJpEpkUCRRZFQkVGRVJFVkVaRWZFikWWRhJGGkZKRlZGYkaGRpJGmkamRBZIRkhSSGZIlkkSSRpJJklCSUpJVkliSZpJpkoWSlJKWkqmSAZQElAaUEJQVlBiUJpRAlEqUUZRUlFWUVpRYlFmUYJRhlGKUZZSElIaUkpSUlJWUmJShlKmUAJUFlQiVCpUQlRGVFJUVlRaVGZUhlSWVKZUqlUGVRJVFlUaVSZVQlVGVUpVUlVWVVpVYlVmVWpVhlWSVZZVmlWmVgZWFlYiVkZWSlZSVlZWWlZmVmpWglaKVpZWolaqVAZYElhCWFZYZliCWJpYplkWWSJZJllGWUpZVllaWWZZllmiWgpaElomWipaSlpSWlZaklqaWqZYFmBaYGZglmEGYRphQmFKYVZhWmFqYZJhlmIWYkZiWmJmYpZgEmQaZCZkQmRKZFZkYmRqZIJkhmSSZJplAmUKZRZlImUqZUZlUmVWZVplZmWKZZZlmmWqZgZmEmZCZkpmVmZqZoZmmmQWaFZolmkSaRppJmlCaVZpYmmGahZqRmpSalZqWmgCgAqAIoAqgFaAgoCKgKKAqoEWgUaBUoFagWaCAoIKgiKCKoJWgoKCioKigqqAFoQmhEaEUoRahGaEaoUahSaFRoVWhWKFaoWGhZKGFoZChkqGWoZmhAqIIogqiEKIZoiKiKKIqokWiUaJWolmiZaKAooKiiKKKopWioKKioqiiqqIZpCWkQaREpFCkVKRVpFikWqRhpGWkZqRopGmkhaQGpQmlEKUSpRWlGKUmpSmlQqVFpVGlVKVVpValWaVlpWqlgaWEpYWlhqWJpZKllaWYpQWmEaYWphqmIaYlpkSmRqZKplKmVaZWplimYKZipoamkKaVppammaahpqSmpqYAqAKoCKgKqCCoIqgoqCqoUahUqFaoWaiAqIKoiKiKqJWooKiiqKioqqgFqRSpGakhqSWpQalQqVWpWqlhqWapaamQqZapAKoCqgiqCqogqiKqKKoqqlGqVKpWqoCqgqqIqoqqlaqgqqKqqKqqqg==',
48
+ };
49
+ // END GENERATED GRIDS
50
+
51
+ // Offsets (in u32) of each codebook in gridData().
52
+ export const GRID_OFF = { iq2xxs: 0, iq2xs: 512, iq2s: 1536, iq3xxs: 3584, iq3s: 3840, iq1s: 4352, kv4: 8448 };
53
+ const GRID_WORDS = 8464;
54
+
55
+ const b64 = (s) => (typeof atob === 'function' ? Uint8Array.from(atob(s), (c) => c.charCodeAt(0)) : new Uint8Array(Buffer.from(s, 'base64')));
56
+ const codes = (s) => { const u8 = b64(s); return new Uint16Array(u8.buffer, u8.byteOffset, u8.byteLength / 2); };
57
+
58
+ // The full codebooks, unpacked: 8-byte grids as two u32 (bytes 0–3, 4–7), 4-byte grids as one u32,
59
+ // kvalues_iq4nl as i32.
60
+ export function gridData() {
61
+ const out = new Uint32Array(GRID_WORDS);
62
+ const put8 = (off, packed, set) => codes(packed).forEach((c, e) => {
63
+ let lo = 0, hi = 0;
64
+ for (let j = 0; j < 8; j++) { const b = set[(c >> (2 * j)) & 3]; if (j < 4) lo |= b << (8 * j); else hi |= b << (8 * (j - 4)); }
65
+ out[off + 2 * e] = lo >>> 0; out[off + 2 * e + 1] = hi >>> 0;
66
+ });
67
+ const put4 = (off, packed, set) => codes(packed).forEach((c, e) => {
68
+ let w = 0;
69
+ for (let j = 0; j < 4; j++) w |= set[(c >> (3 * j)) & 7] << (8 * j);
70
+ out[off + e] = w >>> 0;
71
+ });
72
+ const IQ2 = [0x08, 0x19, 0x2b], IQ1 = [0xff, 0x00, 0x01];
73
+ put8(GRID_OFF.iq2xxs, GRIDS.iq2xxs, IQ2);
74
+ put8(GRID_OFF.iq2xs, GRIDS.iq2xs, IQ2);
75
+ put8(GRID_OFF.iq2s, GRIDS.iq2s, IQ2);
76
+ put4(GRID_OFF.iq3xxs, GRIDS.iq3xxs, [0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3e]);
77
+ put4(GRID_OFF.iq3s, GRIDS.iq3s, [0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f]);
78
+ put8(GRID_OFF.iq1s, GRIDS.iq1s, IQ1);
79
+ KVALUES_IQ4NL.forEach((v, i) => { out[GRID_OFF.kv4 + i] = v >>> 0; });
80
+ return out;
81
+ }
82
+
83
+ // ── GPU block layout ─────────────────────────────────────────────────────────
84
+ // Seven types have a block of 4k+2 bytes that starts with its f16 scale d. On the GPU those blocks get two zero
85
+ // bytes after d (repackKernel, run once at upload), so every array inside every block starts on a 4-byte boundary
86
+ // and the dequant reads whole u32 words. The other four types keep the GGUF layout, which is aligned already.
87
+ export const PADDED = new Set(['Q8_0', 'IQ2_XXS', 'IQ2_XS', 'IQ2_S', 'IQ3_XXS', 'IQ3_S', 'IQ1_S']);
88
+ export const gpuBlock = (type) => QTYPES[type].block + (PADDED.has(type) ? 2 : 0);
89
+ export const gpuRowBytes = (type, cols) => (cols / QTYPES[type].qk) * gpuBlock(type);
90
+
91
+ // The same transform on the CPU, for tests: GGUF block bytes → GPU block bytes.
92
+ export function repackBlocks(type, u8) {
93
+ if (!PADDED.has(type)) return u8;
94
+ const b = QTYPES[type].block, n = u8.length / b, out = new Uint8Array(n * (b + 2));
95
+ for (let i = 0; i < n; i++) { out.set(u8.subarray(i * b, i * b + 2), i * (b + 2)); out.set(u8.subarray(i * b + 2, (i + 1) * b), i * (b + 2) + 4); }
96
+ return out;
97
+ }
98
+ // One thread per output word: words of nBlocks padded blocks from the GGUF bytes in src. Dispatch
99
+ // ceil(words / 256) (2-D folding allowed).
100
+ export function repackKernel(type) {
101
+ if (!PADDED.has(type)) throw new Error(`${type} needs no repack`);
102
+ const b = QTYPES[type].block, wpb = (b + 2) / 4;
103
+ return `
104
+ struct P { words: u32 }
105
+ @group(0) @binding(0) var<storage, read> src: array<u32>;
106
+ @group(0) @binding(1) var<storage, read_write> dst: array<u32>;
107
+ @group(0) @binding(2) var<uniform> p: P;
108
+ fn h(o: u32) -> u32 { return (src[o >> 2u] >> ((o & 2u) << 3u)) & 0xffffu; }
109
+ @compute @workgroup_size(256) fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(num_workgroups) ng: vec3<u32>, @builtin(local_invocation_id) l: vec3<u32>) {
110
+ let i = (wg.y * ng.x + wg.x) * 256u + l.x; if (i >= p.words) { return; }
111
+ let blk = i / ${wpb}u; let w = i % ${wpb}u; let sb = blk * ${b}u;
112
+ if (w == 0u) { dst[i] = h(sb); return; }
113
+ let o = sb + 4u * w - 2u;
114
+ dst[i] = h(o) | (h(o + 2u) << 16u);
115
+ }`;
116
+ }
117
+
118
+ // ── WGSL ──────────────────────────────────────────────────────────────────────
119
+ // B is the byte offset of a GPU block (4-aligned). w(o) reads the aligned word at o; h16/b8 pick a half or a byte.
120
+ const HELPERS = `
121
+ fn w(o: u32) -> u32 { return wq[o >> 2u]; }
122
+ fn b8(o: u32) -> u32 { return (wq[o >> 2u] >> ((o & 3u) << 3u)) & 0xffu; }
123
+ fn h16(o: u32) -> u32 { return (wq[o >> 2u] >> ((o & 2u) << 3u)) & 0xffffu; }
124
+ fn f16v(o: u32) -> f32 { return unpack2x16float(h16(o)).x; }
125
+ fn byt(x: u32, j: u32) -> u32 { return (x >> (j << 3u)) & 0xffu; }
126
+ fn ksign(i: u32) -> u32 { return i | ((countOneBits(i) & 1u) << 7u); }
127
+ fn sgn(signs: u32, j: u32) -> f32 { return select(1.0, -1.0, (signs & (1u << j)) != 0u); }
128
+ const KV4 = array<f32, 16>(${KVALUES_IQ4NL.map((v) => v.toFixed(1)).join(', ')});
129
+ `;
130
+
131
+ const O = GRID_OFF;
132
+ // deq8(B, s, g): weights 8g..8g+7 of chunk s (values 32s..32s+31 of the block). ggml-quants.c reference noted per type;
133
+ // offsets are the GPU layout's (PADDED types: GGUF offset + 2 after d).
134
+ const DEQ8 = {
135
+ // dequantize_row_q8_0: y = qs[j]·d (one 32-value block per chunk, s = 0).
136
+ Q8_0: `
137
+ let d = f16v(B);
138
+ let q0 = vec4<f32>(unpack4xI8(w(B + 4u + 8u * g))); let q1 = vec4<f32>(unpack4xI8(w(B + 8u + 8u * g)));
139
+ v[0] = d * q0.x; v[1] = d * q0.y; v[2] = d * q0.z; v[3] = d * q0.w;
140
+ v[4] = d * q1.x; v[5] = d * q1.y; v[6] = d * q1.z; v[7] = d * q1.w;`,
141
+ // dequantize_row_q2_K: 256 values = 2 halves × 4 shifts × (16 + 16); each 16 has its own 4-bit scale and min.
142
+ Q2_K: `
143
+ let dm = w(B + 80u); let d = unpack2x16float(dm).x; let dmin = unpack2x16float(dm).y;
144
+ let h = s >> 2u; let sh = 2u * (s & 3u);
145
+ let sc = b8(B + 8u * h + 2u * (s & 3u) + (g >> 1u));
146
+ let dl = d * f32(sc & 15u); let ml = dmin * f32(sc >> 4u);
147
+ let qa = w(B + 16u + 32u * h + 8u * g); let qc = w(B + 20u + 32u * h + 8u * g);
148
+ for (var j = 0u; j < 4u; j++) { v[j] = dl * f32((byt(qa, j) >> sh) & 3u) - ml; v[j + 4u] = dl * f32((byt(qc, j) >> sh) & 3u) - ml; }`,
149
+ // dequantize_row_q4_K: 4 × 64 values, low nibbles then high nibbles of 32 bytes; 6-bit scale/min pairs.
150
+ Q4_K: `
151
+ let dm = w(B); let d = unpack2x16float(dm).x; let dmin = unpack2x16float(dm).y;
152
+ var sc = 0u; var mn = 0u;
153
+ if (s < 4u) { sc = b8(B + 4u + s) & 63u; mn = b8(B + 8u + s) & 63u; }
154
+ else { sc = (b8(B + 8u + s) & 15u) | ((b8(B + s) >> 6u) << 4u); mn = (b8(B + 8u + s) >> 4u) | ((b8(B + 4u + s) >> 6u) << 4u); }
155
+ let dl = d * f32(sc); let ml = dmin * f32(mn);
156
+ let qb = B + 16u + 32u * (s >> 1u) + 8u * g; let hi = (s & 1u) * 4u;
157
+ let qa = w(qb) >> hi; let qc = w(qb + 4u) >> hi;
158
+ for (var j = 0u; j < 4u; j++) { v[j] = dl * f32(byt(qa, j) & 15u) - ml; v[j + 4u] = dl * f32(byt(qc, j) & 15u) - ml; }`,
159
+ // dequantize_row_q6_K: 2 halves × 128 values; value l of quarter k (k = 0..3) of half n takes ql[64n + l + 32(k&1)]
160
+ // (low nibble for k < 2, high for k ≥ 2), 2 bits of qh[32n + l] at shift 2k, and int8 scale sc[8n + l/16 + 2k]; d last.
161
+ Q6_K: `
162
+ let d = f16v(B + 208u);
163
+ let n = s >> 2u; let k = s & 3u; let l0 = 8u * g;
164
+ let sc = f32(i32(b8(B + 192u + 8u * n + (l0 >> 4u) + 2u * k) << 24u) >> 24u) * d;
165
+ let qlB = B + 64u * n + 32u * (k & 1u) + l0; let qhB = B + 128u + 32u * n + l0; let hiNib = (k >> 1u) * 4u;
166
+ for (var j = 0u; j < 8u; j++) {
167
+ let q = ((b8(qlB + j) >> hiNib) & 15u) | (((b8(qhB + j) >> (2u * k)) & 3u) << 4u);
168
+ v[j] = sc * f32(i32(q) - 32);
169
+ }`,
170
+ // dequantize_row_q5_0: value i of 32 = (low nibble of qs[i] for i < 16, else high nibble of qs[i-16]) | bit i of qh
171
+ // as bit 4, minus 16, times d. qh is the u32 at bytes 2..5, read as two halves.
172
+ Q5_0: `
173
+ let d = f16v(B);
174
+ let qh = h16(B + 2u) | (h16(B + 4u) << 16u);
175
+ for (var j = 0u; j < 8u; j++) {
176
+ let i = 8u * g + j;
177
+ let lo = select(b8(B + 6u + i - 16u) >> 4u, b8(B + 6u + i) & 15u, i < 16u);
178
+ v[j] = d * f32(i32(lo | (((qh >> i) & 1u) << 4u)) - 16);
179
+ }`,
180
+ // dequantize_row_iq2_xxs: per chunk two u32: 4 grid indices, then 4×7 sign bits + a 4-bit scale.
181
+ IQ2_XXS: `
182
+ let d = f16v(B);
183
+ let a0 = w(B + 4u + 8u * s); let a1 = w(B + 8u + 8u * s);
184
+ let db = d * (0.5 + f32(a1 >> 28u)) * 0.25;
185
+ let e = byt(a0, g); let signs = ksign((a1 >> (7u * g)) & 127u);
186
+ let lo = grid[${O.iq2xxs}u + 2u * e]; let hi = grid[${O.iq2xxs}u + 2u * e + 1u];
187
+ for (var j = 0u; j < 4u; j++) { v[j] = db * f32(byt(lo, j)) * sgn(signs, j); v[j + 4u] = db * f32(byt(hi, j)) * sgn(signs, j + 4u); }`,
188
+ // dequantize_row_iq2_xs: u16 per 8 values (9-bit grid index, 7 sign bits); two 4-bit scales per chunk.
189
+ IQ2_XS: `
190
+ let d = f16v(B);
191
+ let sc = b8(B + 68u + s);
192
+ let db = d * (0.5 + f32(select(sc >> 4u, sc & 15u, g < 2u))) * 0.25;
193
+ let q = h16(B + 4u + 2u * (4u * s + g));
194
+ let e = q & 511u; let signs = ksign(q >> 9u);
195
+ let lo = grid[${O.iq2xs}u + 2u * e]; let hi = grid[${O.iq2xs}u + 2u * e + 1u];
196
+ for (var j = 0u; j < 4u; j++) { v[j] = db * f32(byt(lo, j)) * sgn(signs, j); v[j + 4u] = db * f32(byt(hi, j)) * sgn(signs, j + 4u); }`,
197
+ // dequantize_row_iq2_s: 10-bit grid index (qs | 2 bits of qh), explicit sign bytes after the 32 index bytes.
198
+ IQ2_S: `
199
+ let d = f16v(B);
200
+ let sc = b8(B + 76u + s);
201
+ let db = d * (0.5 + f32(select(sc >> 4u, sc & 15u, g < 2u))) * 0.25;
202
+ let e = b8(B + 4u + 4u * s + g) | ((b8(B + 68u + s) << (8u - 2u * g)) & 0x300u);
203
+ let signs = b8(B + 36u + 4u * s + g);
204
+ let lo = grid[${O.iq2s}u + 2u * e]; let hi = grid[${O.iq2s}u + 2u * e + 1u];
205
+ for (var j = 0u; j < 4u; j++) { v[j] = db * f32(byt(lo, j)) * sgn(signs, j); v[j + 4u] = db * f32(byt(hi, j)) * sgn(signs, j + 4u); }`,
206
+ // dequantize_row_iq3_xxs: two 4-value grid entries per 8 values; a u32 of 4×7 sign bits + a 4-bit scale per chunk.
207
+ IQ3_XXS: `
208
+ let d = f16v(B);
209
+ let aux = w(B + 68u + 4u * s);
210
+ let db = d * (0.5 + f32(aux >> 28u)) * 0.5;
211
+ let signs = ksign((aux >> (7u * g)) & 127u);
212
+ let ee = h16(B + 4u + 8u * s + 2u * g);
213
+ let g1 = grid[${O.iq3xxs}u + (ee & 255u)]; let g2 = grid[${O.iq3xxs}u + (ee >> 8u)];
214
+ for (var j = 0u; j < 4u; j++) { v[j] = db * f32(byt(g1, j)) * sgn(signs, j); v[j + 4u] = db * f32(byt(g2, j)) * sgn(signs, j + 4u); }`,
215
+ // dequantize_row_iq3_s: 9-bit grid indices (qs | a bit of qh), sign bytes, a 4-bit scale per chunk (two per byte).
216
+ IQ3_S: `
217
+ let d = f16v(B);
218
+ let sc = b8(B + 108u + (s >> 1u));
219
+ let db = d * f32(1u + 2u * ((sc >> (4u * (s & 1u))) & 15u));
220
+ let qh = b8(B + 68u + s);
221
+ let ee = h16(B + 4u + 8u * s + 2u * g);
222
+ let e1 = (ee & 255u) | ((qh << (8u - 2u * g)) & 256u);
223
+ let e2 = (ee >> 8u) | ((qh << (7u - 2u * g)) & 256u);
224
+ let signs = b8(B + 76u + 4u * s + g);
225
+ let g1 = grid[${O.iq3s}u + e1]; let g2 = grid[${O.iq3s}u + e2];
226
+ for (var j = 0u; j < 4u; j++) { v[j] = db * f32(byt(g1, j)) * sgn(signs, j); v[j + 4u] = db * f32(byt(g2, j)) * sgn(signs, j + 4u); }`,
227
+ // dequantize_row_iq1_s: 11-bit grid index (qs | 3 bits of qh) of int8 {-1, 0, 1}; per-chunk 3-bit scale and ±delta.
228
+ IQ1_S: `
229
+ let d = f16v(B);
230
+ let qh = h16(B + 36u + 2u * s);
231
+ let dl = d * f32(2u * ((qh >> 12u) & 7u) + 1u);
232
+ let delta = select(0.125, -0.125, (qh & 0x8000u) != 0u);
233
+ let e = b8(B + 4u + 4u * s + g) | (((qh >> (3u * g)) & 7u) << 8u);
234
+ let lo = vec4<f32>(unpack4xI8(grid[${O.iq1s}u + 2u * e])); let hi = vec4<f32>(unpack4xI8(grid[${O.iq1s}u + 2u * e + 1u]));
235
+ v[0] = dl * (lo.x + delta); v[1] = dl * (lo.y + delta); v[2] = dl * (lo.z + delta); v[3] = dl * (lo.w + delta);
236
+ v[4] = dl * (hi.x + delta); v[5] = dl * (hi.y + delta); v[6] = dl * (hi.z + delta); v[7] = dl * (hi.w + delta);`,
237
+ // dequantize_row_iq1_m: the f16 scale is spread over the top nibbles of 4 u16 scale words; 3-bit scales per
238
+ // 16 values; qh holds 3 index bits + a delta sign per 8 values.
239
+ IQ1_M: `
240
+ let s01 = w(B + 48u); let s23 = w(B + 52u);
241
+ let d = unpack2x16float(((s01 & 0xffffu) >> 12u) | ((s01 >> 24u) & 0xf0u) | (((s23 & 0xffffu) >> 4u) & 0xf00u) | ((s23 >> 16u) & 0xf000u)).x;
242
+ let scw = select(s23, s01, s < 4u) >> (16u * ((s >> 1u) & 1u));
243
+ let dl = d * f32(2u * ((scw >> (6u * (s & 1u) + 3u * (g >> 1u))) & 7u) + 1u);
244
+ let qh = b8(B + 32u + 2u * s + (g >> 1u));
245
+ let odd = (g & 1u) == 1u;
246
+ let e = b8(B + 4u * s + g) | select((qh << 8u) & 0x700u, (qh << 4u) & 0x700u, odd);
247
+ let delta = select(0.125, -0.125, (qh & select(0x08u, 0x80u, odd)) != 0u);
248
+ let lo = vec4<f32>(unpack4xI8(grid[${O.iq1s}u + 2u * e])); let hi = vec4<f32>(unpack4xI8(grid[${O.iq1s}u + 2u * e + 1u]));
249
+ v[0] = dl * (lo.x + delta); v[1] = dl * (lo.y + delta); v[2] = dl * (lo.z + delta); v[3] = dl * (lo.w + delta);
250
+ v[4] = dl * (hi.x + delta); v[5] = dl * (hi.y + delta); v[6] = dl * (hi.z + delta); v[7] = dl * (hi.w + delta);`,
251
+ // dequantize_row_iq4_xs: 6-bit scale per chunk (4 low bits in scales_l, 2 high in scales_h); non-linear 4-bit values.
252
+ IQ4_XS: `
253
+ let dh = w(B); let d = unpack2x16float(dh).x;
254
+ let ls = ((b8(B + 4u + (s >> 1u)) >> (4u * (s & 1u))) & 15u) | ((((dh >> 16u) >> (2u * s)) & 3u) << 4u);
255
+ let dl = d * f32(i32(ls) - 32);
256
+ let hi = (g >> 1u) * 4u; let qb = B + 8u + 16u * s + 8u * (g & 1u);
257
+ let qa = w(qb) >> hi; let qc = w(qb + 4u) >> hi;
258
+ for (var j = 0u; j < 4u; j++) { v[j] = dl * KV4[byt(qa, j) & 15u]; v[j + 4u] = dl * KV4[byt(qc, j) & 15u]; }`,
259
+ };
260
+
261
+ export function deqFn(type) {
262
+ const body = DEQ8[type];
263
+ if (!body) throw new Error(`no deq8 for ${type}`);
264
+ return `${HELPERS}
265
+ fn deq8(B: u32, s: u32, g: u32) -> array<f32, 8> {
266
+ var v: array<f32, 8>;${body}
267
+ return v;
268
+ }`;
269
+ }
270
+ const CPB = (type) => QTYPES[type].qk / 32; // 32-value chunks per block
271
+
272
+ // Matrix × vector. A 64-thread workgroup computes MV_ROWS rows: thread t takes chunks t, t+64, …, loads that
273
+ // chunk's 32 activations into registers once and dots them with the chunk of every row, so x is read once per
274
+ // workgroup instead of once per row. Dispatch ceil(M / MV_ROWS) workgroups (dispatch() folds x > 65535 into y).
275
+ export const MV_ROWS = 16;
276
+ export function mvKernel(type) {
277
+ return `
278
+ struct P { M: u32, N: u32, rowBytes: u32, pad: u32 }
279
+ @group(0) @binding(0) var<storage, read> x: array<vec4<f32>>;
280
+ @group(0) @binding(1) var<storage, read> wq: array<u32>;
281
+ @group(0) @binding(2) var<storage, read> grid: array<u32>;
282
+ @group(0) @binding(3) var<storage, read_write> y: array<f32>;
283
+ @group(0) @binding(4) var<uniform> p: P;
284
+ ${deqFn(type)}
285
+ const R = ${MV_ROWS}u;
286
+ var<workgroup> red: array<f32, ${MV_ROWS * 64}>;
287
+ @compute @workgroup_size(64) fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(num_workgroups) ng: vec3<u32>, @builtin(local_invocation_id) l: vec3<u32>) {
288
+ _ = grid[0];
289
+ let m0 = (wg.y * ng.x + wg.x) * R; let t = l.x; let nc = p.N / 32u;
290
+ var acc: array<f32, ${MV_ROWS}>;
291
+ for (var c = t; c < nc; c += 64u) {
292
+ var xv: array<vec4<f32>, 8>;
293
+ for (var i = 0u; i < 8u; i++) { xv[i] = x[c * 8u + i]; }
294
+ let bo = (c / ${CPB(type)}u) * ${gpuBlock(type)}u; let s = c % ${CPB(type)}u;
295
+ for (var r = 0u; r < R; r++) {
296
+ let B = min(m0 + r, p.M - 1u) * p.rowBytes + bo;
297
+ var a = 0.0;
298
+ for (var g = 0u; g < 4u; g++) {
299
+ let v = deq8(B, s, g);
300
+ a += dot(vec4<f32>(v[0], v[1], v[2], v[3]), xv[2u * g]) + dot(vec4<f32>(v[4], v[5], v[6], v[7]), xv[2u * g + 1u]);
301
+ }
302
+ acc[r] += a;
303
+ }
304
+ }
305
+ for (var r = 0u; r < R; r++) { red[r * 64u + t] = acc[r]; }
306
+ workgroupBarrier();
307
+ for (var st = 32u; st > 0u; st >>= 1u) {
308
+ if (t < st) { for (var r = 0u; r < R; r++) { red[r * 64u + t] += red[r * 64u + t + st]; } }
309
+ workgroupBarrier();
310
+ }
311
+ if (t < R && m0 + t < p.M) { y[m0 + t] = red[t * 64u]; }
312
+ }`;
313
+ }
314
+
315
+ // A few tokens at once (a speculative verify block): y[t·M + m] = Σ_k x[t·N + k]·W[m][k] for T ≤ MVT_TOKENS, each
316
+ // weight read and dequantized once. One row per lane (MVT_ROWS rows per workgroup) with one sum per token; per
317
+ // 256-wide k block the T activation rows go through shared memory, where every lane reads the same addresses (a
318
+ // broadcast). The token loop has a constant trip count TT so the sums stay in registers (4 rows per lane spilled them:
319
+ // 520 ms a block); the cost grows with TT, so short blocks take the TT = 8 build. N must be a multiple of 256.
320
+ // Dispatch (ceil(M / MVT_ROWS)). Measured on an M4 Pro, Qwen3-4B Q8_0, 17 tokens: 88 ms of matrix work, against 98 ms
321
+ // for a subgroup-matrix version (64 rows × 32 tokens, 128-wide k steps) and 172 ms with the weights staged through
322
+ // shared memory for coalesced reads (plan/2026-10-22-flashmap/results.md).
323
+ export const MVT_TOKENS = 17, MVT_ROWS = 256;
324
+ export function mvTKernel(type, TTn = MVT_TOKENS) {
325
+ return `
326
+ struct P { M: u32, N: u32, rowBytes: u32, pad: u32 }
327
+ struct Q { T: u32, pos0: u32, S: u32, pad: u32 }
328
+ @group(0) @binding(0) var<storage, read> x: array<f32>;
329
+ @group(0) @binding(1) var<storage, read> wq: array<u32>;
330
+ @group(0) @binding(2) var<storage, read> grid: array<u32>;
331
+ @group(0) @binding(3) var<storage, read_write> y: array<f32>;
332
+ @group(0) @binding(4) var<uniform> p: P;
333
+ @group(0) @binding(5) var<uniform> qd: Q;
334
+ ${deqFn(type)}
335
+ const TT = ${TTn}u;
336
+ var<workgroup> xs: array<vec4<f32>, ${TTn * 64}>; // [token][k / 4] for one 256-wide k block
337
+ @compute @workgroup_size(${MVT_ROWS}) fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(num_workgroups) ng: vec3<u32>, @builtin(local_invocation_id) l: vec3<u32>) {
338
+ _ = grid[0];
339
+ let t = l.x; let row = (wg.y * ng.x + wg.x) * ${MVT_ROWS}u + t; let rr = min(row, p.M - 1u); let T = min(qd.T, TT);
340
+ var acc: array<f32, ${TTn}>;
341
+ for (var kb = 0u; kb < p.N; kb += 256u) {
342
+ workgroupBarrier();
343
+ for (var i = t; i < TT * 64u; i += ${MVT_ROWS}u) {
344
+ let tk = i / 64u; let o = tk * p.N + kb + (i % 64u) * 4u;
345
+ xs[i] = select(vec4<f32>(0.0), vec4<f32>(x[o], x[o + 1u], x[o + 2u], x[o + 3u]), tk < T);
346
+ }
347
+ workgroupBarrier();
348
+ for (var c = 0u; c < 8u; c++) {
349
+ let cc = kb / 32u + c;
350
+ let B = rr * p.rowBytes + (cc / ${CPB(type)}u) * ${gpuBlock(type)}u; let s = cc % ${CPB(type)}u;
351
+ for (var g = 0u; g < 4u; g++) {
352
+ let v = deq8(B, s, g);
353
+ let w0 = vec4<f32>(v[0], v[1], v[2], v[3]); let w1 = vec4<f32>(v[4], v[5], v[6], v[7]);
354
+ let xi = c * 8u + g * 2u;
355
+ for (var tk = 0u; tk < TT; tk++) { acc[tk] += dot(w0, xs[tk * 64u + xi]) + dot(w1, xs[tk * 64u + xi + 1u]); }
356
+ }
357
+ }
358
+ }
359
+ if (row < p.M) { for (var tk = 0u; tk < TT; tk++) { if (tk < T) { y[tk * p.M + row] = acc[tk]; } } }
360
+ }`;
361
+ }
362
+
363
+ // Token-major batch: y[t·M + m] = Σ_k x[t·N + k]·W[m][k]. A 256-thread workgroup computes a 64-row × 64-token tile.
364
+ // Per 32-wide k chunk every thread dequantizes 8 weights (64 rows × 4 groups) and loads 8 activations into shared
365
+ // memory (k-major f32 tiles, 16 KB in all), then accumulates a 4-row × 4-token block: each weight read from
366
+ // memory serves 64 tokens. Dispatch (ceil(M / MM_TILE), ceil(T / MM_TILE)).
367
+ export const MM_TILE = 64;
368
+ export function mmKernel(type) {
369
+ return `
370
+ struct P { M: u32, N: u32, rowBytes: u32, pad: u32 }
371
+ struct Q { T: u32, pos0: u32, S: u32, pad: u32 }
372
+ @group(0) @binding(0) var<storage, read> x: array<f32>;
373
+ @group(0) @binding(1) var<storage, read> wq: array<u32>;
374
+ @group(0) @binding(2) var<storage, read> grid: array<u32>;
375
+ @group(0) @binding(3) var<storage, read_write> y: array<f32>;
376
+ @group(0) @binding(4) var<uniform> p: P;
377
+ @group(0) @binding(5) var<uniform> qd: Q;
378
+ ${deqFn(type)}
379
+ var<workgroup> ws: array<f32, 2048>; // [k][row]: 32 × 64 (each thread writes whole f32s; no shared vec4 lanes)
380
+ var<workgroup> xs: array<f32, 2048>; // [k][token]
381
+ @compute @workgroup_size(256) fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(local_invocation_id) l: vec3<u32>) {
382
+ _ = grid[0];
383
+ let m0 = wg.x * 64u; let t0 = wg.y * 64u; let i = l.x;
384
+ let lr = i >> 2u; let lg = i & 3u; // loader: row / token lr, 8-value group lg
385
+ let rr = (i >> 4u) * 4u; let tc = (i & 15u) * 4u; // compute: rows rr..rr+3, tokens tc..tc+3
386
+ let wrow = min(m0 + lr, p.M - 1u) * p.rowBytes;
387
+ let xt = t0 + lr; let xok = xt < qd.T;
388
+ let nc = p.N / 32u;
389
+ var acc: array<vec4<f32>, 4>;
390
+ for (var c = 0u; c < nc; c++) {
391
+ let v = deq8(wrow + (c / ${CPB(type)}u) * ${gpuBlock(type)}u, c % ${CPB(type)}u, lg);
392
+ let xb = min(xt, qd.T - 1u) * p.N + c * 32u + lg * 8u;
393
+ for (var j = 0u; j < 8u; j++) {
394
+ let k = lg * 8u + j;
395
+ ws[k * 64u + lr] = v[j];
396
+ xs[k * 64u + lr] = select(0.0, x[xb + j], xok);
397
+ }
398
+ workgroupBarrier();
399
+ for (var k = 0u; k < 32u; k++) {
400
+ let wb = k * 64u + rr; let xb4 = k * 64u + tc;
401
+ let a = vec4<f32>(ws[wb], ws[wb + 1u], ws[wb + 2u], ws[wb + 3u]);
402
+ let b = vec4<f32>(xs[xb4], xs[xb4 + 1u], xs[xb4 + 2u], xs[xb4 + 3u]);
403
+ acc[0] += a.x * b; acc[1] += a.y * b; acc[2] += a.z * b; acc[3] += a.w * b;
404
+ }
405
+ workgroupBarrier();
406
+ }
407
+ for (var a = 0u; a < 4u; a++) {
408
+ let m = m0 + rr + a; if (m >= p.M) { continue; }
409
+ for (var b = 0u; b < 4u; b++) { let t = t0 + tc + b; if (t < qd.T) { y[t * p.M + m] = acc[a][b]; } }
410
+ }
411
+ }`;
412
+ }
413
+
414
+ // The same GEMM on subgroup matrices (chromium-experimental-subgroup-matrix; Apple's 8×8 simdgroup units): weights and
415
+ // activations go through shared memory as f16, products accumulate in f32 — llama.cpp Metal's mul_mm recipe. A
416
+ // workgroup computes 64 rows × MM_SG_TOKENS tokens. The 256 threads are 8 subgroups of 32; subgroup s owns rows
417
+ // 16·(s/2)..+15 and tokens (MM_SG_TOKENS/2)·(s%2).. as 2 × (MM_SG_TOKENS/16) accumulators
418
+ // of 8 × 8. Results store straight into token-major y; 8-row blocks past M and 8-token blocks past T are skipped
419
+ // (rows T..ceil8(T)-1 of a stored block may receive values: callers size y for whole 8-token blocks and read only
420
+ // t < T). Needs M % 8 == 0 and subgroups of exactly 32. Dispatch (ceil(M / 64), ceil(T / MM_SG_TOKENS)).
421
+ export const MM_SG_TOKENS = 64; // 128 measured slower on an M4 Pro (3.7 vs 2.8 s per 256-token chunk): register pressure
422
+ export function mmSgKernel(type) {
423
+ const TB = MM_SG_TOKENS / 16; // 8-token blocks per subgroup
424
+ const R = (n) => Array.from({ length: n }, (_, i) => i);
425
+ const acc = R(2).flatMap((a) => R(TB).map((b) => `c${a}_${b}`));
426
+ return `enable f16;
427
+ enable subgroups;
428
+ enable chromium_experimental_subgroup_matrix;
429
+ diagnostic(off, chromium.subgroup_matrix_uniformity);
430
+ struct P { M: u32, N: u32, rowBytes: u32, pad: u32 }
431
+ struct Q { T: u32, pos0: u32, S: u32, pad: u32 }
432
+ @group(0) @binding(0) var<storage, read> x: array<f32>;
433
+ @group(0) @binding(1) var<storage, read> wq: array<u32>;
434
+ @group(0) @binding(2) var<storage, read> grid: array<u32>;
435
+ @group(0) @binding(3) var<storage, read_write> y: array<f32>;
436
+ @group(0) @binding(4) var<uniform> p: P;
437
+ @group(0) @binding(5) var<uniform> qd: Q;
438
+ ${deqFn(type)}
439
+ var<workgroup> ws: array<f16, 2048>; // [row][k], 64 × 32
440
+ var<workgroup> xs: array<f16, ${MM_SG_TOKENS * 32}>; // [token][k], ${MM_SG_TOKENS} × 32
441
+ @compute @workgroup_size(256) fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(local_invocation_id) l: vec3<u32>) {
442
+ _ = grid[0];
443
+ let m0 = wg.x * 64u; let t0 = wg.y * ${MM_SG_TOKENS}u; let i = l.x;
444
+ let lr = i >> 2u; let lg = i & 3u;
445
+ let sg = i >> 5u; let rb = (sg >> 1u) * 16u; let tb = (sg & 1u) * ${MM_SG_TOKENS / 2}u;
446
+ let wrow = min(m0 + lr, p.M - 1u) * p.rowBytes;
447
+ let nc = p.N / 32u;
448
+ ${acc.map((v) => ` var ${v}: subgroup_matrix_result<f32, 8, 8>;`).join('\n')}
449
+ for (var c = 0u; c < nc; c++) {
450
+ let v = deq8(wrow + (c / ${CPB(type)}u) * ${gpuBlock(type)}u, c % ${CPB(type)}u, lg);
451
+ for (var j = 0u; j < 8u; j++) { ws[lr * 32u + lg * 8u + j] = f16(v[j]); }
452
+ for (var e = i; e < ${MM_SG_TOKENS * 32}u; e += 256u) {
453
+ let t = t0 + (e >> 5u);
454
+ xs[e] = select(f16(0.0), f16(x[min(t, qd.T - 1u) * p.N + c * 32u + (e & 31u)]), t < qd.T);
455
+ }
456
+ workgroupBarrier();
457
+ for (var k = 0u; k < 32u; k += 8u) {
458
+ let a0 = subgroupMatrixLoad<subgroup_matrix_left<f16, 8, 8>, row_major>(&ws, rb * 32u + k, 32u);
459
+ let a1 = subgroupMatrixLoad<subgroup_matrix_left<f16, 8, 8>, row_major>(&ws, (rb + 8u) * 32u + k, 32u);
460
+ ${R(TB).map((b) => ` let b${b} = subgroupMatrixLoad<subgroup_matrix_right<f16, 8, 8>, col_major>(&xs, (tb + ${8 * b}u) * 32u + k, 32u);`).join('\n')}
461
+ ${R(2).flatMap((a) => R(TB).map((b) => ` c${a}_${b} = subgroupMatrixMultiplyAccumulate(a${a}, b${b}, c${a}_${b});`)).join('\n')}
462
+ }
463
+ workgroupBarrier();
464
+ }
465
+ let tA = t0 + tb;
466
+ ${R(2).map((a) => ` if (m0 + rb + ${8 * a}u < p.M) {
467
+ ${R(TB).map((b) => ` if (tA + ${8 * b}u < qd.T) { subgroupMatrixStore<col_major>(&y, (tA + ${8 * b}u) * p.M + m0 + rb + ${8 * a}u, c${a}_${b}, p.M); }`).join('\n')}
468
+ }`).join('\n')}
469
+ }`;
470
+ }
471
+
472
+ // One token's embedding row: thread i dequantizes values 8i..8i+7. Dispatch ceil(N/8/256).
473
+ export function embedKernel(type) {
474
+ return `
475
+ struct Tok { token: u32, pos: u32, seqLen: u32, pad: u32 }
476
+ struct P { N: u32, rowBytes: u32 }
477
+ @group(0) @binding(0) var<storage, read> wq: array<u32>;
478
+ @group(0) @binding(1) var<storage, read> grid: array<u32>;
479
+ @group(0) @binding(2) var<storage, read_write> y: array<f32>;
480
+ @group(0) @binding(3) var<uniform> tok: Tok;
481
+ @group(0) @binding(4) var<uniform> p: P;
482
+ ${deqFn(type)}
483
+ @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gi: vec3<u32>) {
484
+ _ = grid[0];
485
+ let i = gi.x; if (i * 8u >= p.N) { return; }
486
+ let c = i >> 2u; let g = i & 3u;
487
+ let v = deq8(tok.token * p.rowBytes + (c / ${CPB(type)}u) * ${gpuBlock(type)}u, c % ${CPB(type)}u, g);
488
+ for (var j = 0u; j < 8u; j++) { y[i * 8u + j] = v[j]; }
489
+ }`;
490
+ }
491
+
492
+ // T tokens' embedding rows into token-major y. Dispatch (ceil(N/8/256), T).
493
+ export function embedBKernel(type) {
494
+ return `
495
+ struct P { N: u32, rowBytes: u32 }
496
+ struct Q { T: u32, pos0: u32, S: u32, pad: u32 }
497
+ @group(0) @binding(0) var<storage, read> wq: array<u32>;
498
+ @group(0) @binding(1) var<storage, read> grid: array<u32>;
499
+ @group(0) @binding(2) var<storage, read> ids: array<u32>;
500
+ @group(0) @binding(3) var<storage, read_write> y: array<f32>;
501
+ @group(0) @binding(4) var<uniform> p: P;
502
+ @group(0) @binding(5) var<uniform> qd: Q;
503
+ ${deqFn(type)}
504
+ @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gi: vec3<u32>) {
505
+ _ = grid[0];
506
+ let i = gi.x; let t = gi.y; if (i * 8u >= p.N || t >= qd.T) { return; }
507
+ let c = i >> 2u; let g = i & 3u;
508
+ let v = deq8(ids[t] * p.rowBytes + (c / ${CPB(type)}u) * ${gpuBlock(type)}u, c % ${CPB(type)}u, g);
509
+ for (var j = 0u; j < 8u; j++) { y[t * p.N + i * 8u + j] = v[j]; }
510
+ }`;
511
+ }