@@ -277,6 +277,97 @@ typedef struct {
277277} block_tq2_0;
278278static_assert (sizeof (block_tq2_0) == sizeof (ggml_half) + QK_K / 4 , " wrong tq2_0 block size/padding" );
279279
280+ // TurboQuant 3-bit MSE-only: 3-bit PolarQuant indices (no QJL)
281+ // Storage block size = 32 (matches q4_0 for optimal GPU parallelism)
282+ // Transform group size = 128 (head_dim, for rotation Gaussianization)
283+ // Per block: norm(fp16) + 2-bit indices (8 bytes) + 1-bit extra (4 bytes) = 14 bytes per 32 values
284+ // = 3.5 bits/value → 4.6× compression vs fp16
285+ // The 3-bit index is split: lower 2 bits in qs[], upper 1 bit in signs[]
286+ #define QK_TURBO3 128 // Block size 128: one block per rotation group, eliminates redundant norms
287+ #define QK_TURBO3_GROUP 128 // rotation group size = head_dim
288+ // Derived: FA template nl parameters (auto-scale with block size)
289+ #define NL_TURBO3 (QK_TURBO3 / 16 ) // non-vec FA iterations per block
290+ #define NL_TURBO3_VEC (QK_TURBO3 / 4 ) // vec FA iterations per block
291+ typedef struct {
292+ ggml_half norm; // 2 bytes: vector L2 norm (for rescaling)
293+ uint8_t qs[QK_TURBO3 / 4 ]; // 8 bytes: lower 2-bit indices (4 per byte)
294+ uint8_t signs[QK_TURBO3 / 8 ]; // 4 bytes: upper 1-bit of 3-bit index (8 per byte)
295+ } block_turbo3_0; // 14 bytes total
296+ static_assert (sizeof (block_turbo3_0) == sizeof (ggml_half) + QK_TURBO3 /4 + QK_TURBO3 /8 , " wrong turbo3_0 block size/padding" );
297+
298+ // TurboQuant 4-bit: 3-bit PolarQuant indices + 1-bit QJL signs
299+ // TURBO4_USE_4BIT: switch between 4-bit PolarQuant (new) and 3-bit+QJL (legacy)
300+ // Default: 4-bit on all backends (Metal + CUDA validated)
301+ #ifndef TURBO4_USE_4BIT
302+ # define TURBO4_USE_4BIT 1
303+ #endif
304+
305+ #define QK_TURBO4 128
306+
307+ #if TURBO4_USE_4BIT
308+ // 4-bit PolarQuant: 16 optimal centroids, nibble packed, no QJL
309+ // Per block: norm(fp16) + rnorm(fp16, reserved) + 4-bit indices (64 bytes)
310+ // = 68 bytes per 128 values = 4.25 bits/value → 3.8× compression vs fp16
311+ typedef struct {
312+ ggml_half norm; // 2 bytes
313+ ggml_half rnorm; // 2 bytes (reserved, unused in 4-bit mode)
314+ uint8_t qs[QK_TURBO4 / 2 ]; // 64 bytes: 4-bit PolarQuant indices (nibble packed)
315+ } block_turbo4_0; // 68 bytes total
316+ static_assert (sizeof (block_turbo4_0) == 68 , " wrong turbo4_0 block size" );
317+ #else
318+ // Legacy 3-bit PolarQuant + 1-bit QJL (original paper design)
319+ // Per block: norm(fp16) + rnorm(fp16) + 3-bit indices (48 bytes) + 1-bit QJL signs (16 bytes)
320+ // = 68 bytes per 128 values = 4.25 bits/value → 3.8× compression vs fp16
321+ typedef struct {
322+ ggml_half norm; // 2 bytes
323+ ggml_half rnorm; // 2 bytes: residual norm for QJL scale
324+ uint8_t qs[QK_TURBO4 * 3 / 8 ]; // 48 bytes: 3-bit PolarQuant indices
325+ uint8_t signs[QK_TURBO4 / 8 ]; // 16 bytes: 1-bit QJL signs
326+ } block_turbo4_0; // 68 bytes total
327+ static_assert (sizeof (block_turbo4_0) == 2 *sizeof (ggml_half) + QK_TURBO4 *3 /8 + QK_TURBO4 /8 , " wrong turbo4_0 block size" );
328+ #endif
329+
330+ static_assert (QK_TURBO4 == 128 , " turbo4 kernels assume QK_TURBO4 == 128" );
331+
332+ // TurboQuant 2-bit: 2-bit PolarQuant indices only (no QJL)
333+ // Per block: norm(fp16) + 2-bit indices (8 bytes) = 10 bytes per 32 values
334+ // = 2.5 bits/value → 6.4× compression vs fp16
335+ // 4 centroids (Lloyd-Max for N(0, 1/128)): {-0.133462, -0.039994, 0.039994, 0.133462}
336+ #define QK_TURBO2 128 // Block size 128: one block per rotation group
337+ #define QK_TURBO2_GROUP 128 // rotation group size = head_dim
338+ // Derived: FA template nl parameters (auto-scale with block size)
339+ #define NL_TURBO2 (QK_TURBO2 / 16 ) // non-vec FA iterations per block
340+ #define NL_TURBO2_VEC (QK_TURBO2 / 4 ) // vec FA iterations per block
341+ typedef struct {
342+ ggml_half norm; // 2 bytes: corrected L2 norm
343+ uint8_t qs[QK_TURBO2 / 4 ]; // 8 bytes: 2-bit indices (4 per byte)
344+ } block_turbo2_0; // 10 bytes total
345+ static_assert (sizeof (block_turbo2_0) == sizeof (ggml_half) + QK_TURBO2 /4 , " wrong turbo2_0 block size/padding" );
346+
347+ // TQ3_1S: WHT-rotated 3-bit weight quantization (8-level Lloyd-Max for N(0,1))
348+ // Block size 32, dual half-block scales (d0 for [0..15], d1 for [16..31])
349+ // Per block: d0(fp16) + d1(fp16) + 3-bit indices packed (12 bytes) = 16 bytes per 32 values
350+ // = 4.0 bits/value
351+ #define QK_TQ3_0 32
352+ typedef struct {
353+ ggml_half d0; // 2 bytes: scale for first 16 elements
354+ ggml_half d1; // 2 bytes: scale for last 16 elements
355+ uint8_t qs[QK_TQ3_0 * 3 / 8 ]; // 12 bytes: 3-bit indices packed (4 groups of 8 in 3 bytes)
356+ } block_tq3_1s; // 16 bytes total
357+ static_assert (sizeof (block_tq3_1s) == 16 , " wrong tq3_1s block size" );
358+
359+ // TQ4_1S: WHT-rotated 4-bit weight quantization (16-level Lloyd-Max for N(0,1))
360+ // Block size 32, dual half-block scales (d0 for [0..15], d1 for [16..31])
361+ // Per block: d0(fp16) + d1(fp16) + 4-bit indices packed (16 bytes) = 20 bytes per 32 values
362+ // = 5.0 bits/value
363+ #define QK_TQ4_1S 32
364+ typedef struct {
365+ ggml_half d0; // 2 bytes: scale for first 16 elements
366+ ggml_half d1; // 2 bytes: scale for last 16 elements
367+ uint8_t qs[QK_TQ4_1S / 2 ]; // 16 bytes: 4-bit indices nibble-packed
368+ } block_tq4_1s; // 20 bytes total
369+ static_assert (sizeof (block_tq4_1s) == 20 , " wrong tq4_1s block size" );
370+
280371//
281372// Super-block quantization structures
282373//
0 commit comments