Skip to content

Commit 6abff46

Browse files
committed
feat: add TurboQuant support
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
1 parent 36dafba commit 6abff46

14 files changed

Lines changed: 690 additions & 2 deletions

File tree

ggml/include/ggml.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,9 @@ extern "C" {
428428
// GGML_TYPE_IQ4_NL_8_8 = 38,
429429
GGML_TYPE_MXFP4 = 39, // MXFP4 (1 block)
430430
GGML_TYPE_NVFP4 = 40, // NVFP4 (4 blocks, E4M3 scale)
431-
GGML_TYPE_COUNT = 41,
431+
GGML_TYPE_TBQ3_0 = 41, // TurboQuant 3-bit
432+
GGML_TYPE_TBQ4_0 = 42, // TurboQuant 4-bit
433+
GGML_TYPE_COUNT = 43,
432434
};
433435

434436
// precision

ggml/src/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ add_library(ggml-base
205205
ggml-threading.h
206206
ggml-quants.c
207207
ggml-quants.h
208+
ggml-turboq.c
209+
ggml-turboq.h
210+
ggml-turboq-tables.h
208211
gguf.cpp)
209212

210213
set_target_properties(ggml-base PROPERTIES

ggml/src/ggml-common.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,27 @@ typedef struct {
266266
} block_tq2_0;
267267
static_assert(sizeof(block_tq2_0) == sizeof(ggml_half) + QK_K / 4, "wrong tq2_0 block size/padding");
268268

269+
//
270+
// TurboQuant quantization structures
271+
// Uses dense QR random rotation + Max-Lloyd codebook quantization
272+
//
273+
274+
// TurboQuant 3-bit: 3.0625 bpw
275+
// 256 elements * 3 bits = 96 bytes packed indices + 2 bytes norm (stored in block 0 only)
276+
typedef struct {
277+
uint8_t qs[QK_K * 3 / 8]; // 96 bytes: 3-bit codebook indices, packed
278+
ggml_half d; // L2 norm of the row (only block 0 is read)
279+
} block_tbq3_0;
280+
static_assert(sizeof(block_tbq3_0) == sizeof(ggml_half) + QK_K * 3 / 8, "wrong tbq3_0 block size/padding");
281+
282+
// TurboQuant 4-bit: 4.0625 bpw
283+
// 256 elements * 4 bits = 128 bytes packed indices + 2 bytes norm (stored in block 0 only)
284+
typedef struct {
285+
uint8_t qs[QK_K / 2]; // 128 bytes: 4-bit codebook indices as nibbles
286+
ggml_half d; // L2 norm of the row (only block 0 is read)
287+
} block_tbq4_0;
288+
static_assert(sizeof(block_tbq4_0) == sizeof(ggml_half) + QK_K / 2, "wrong tbq4_0 block size/padding");
289+
269290
//
270291
// Super-block quantization structures
271292
//

ggml/src/ggml-cpu/arch-fallback.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#define ggml_vec_dot_nvfp4_q8_0_generic ggml_vec_dot_nvfp4_q8_0
1919
#define ggml_vec_dot_tq1_0_q8_K_generic ggml_vec_dot_tq1_0_q8_K
2020
#define ggml_vec_dot_tq2_0_q8_K_generic ggml_vec_dot_tq2_0_q8_K
21+
#define ggml_vec_dot_tbq3_0_q8_K_generic ggml_vec_dot_tbq3_0_q8_K
22+
#define ggml_vec_dot_tbq4_0_q8_K_generic ggml_vec_dot_tbq4_0_q8_K
2123
#define ggml_vec_dot_q2_K_q8_K_generic ggml_vec_dot_q2_K_q8_K
2224
#define ggml_vec_dot_q3_K_q8_K_generic ggml_vec_dot_q3_K_q8_K
2325
#define ggml_vec_dot_q4_K_q8_K_generic ggml_vec_dot_q4_K_q8_K
@@ -82,6 +84,8 @@
8284
#elif defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)
8385
// quants.c
8486
#define ggml_vec_dot_nvfp4_q8_0_generic ggml_vec_dot_nvfp4_q8_0
87+
#define ggml_vec_dot_tbq3_0_q8_K_generic ggml_vec_dot_tbq3_0_q8_K
88+
#define ggml_vec_dot_tbq4_0_q8_K_generic ggml_vec_dot_tbq4_0_q8_K
8589
// repack.cpp
8690
#define ggml_quantize_mat_q8_0_4x4_generic ggml_quantize_mat_q8_0_4x4
8791
#define ggml_quantize_mat_q8_K_4x4_generic ggml_quantize_mat_q8_K_4x4
@@ -114,6 +118,8 @@
114118
#define ggml_vec_dot_nvfp4_q8_0_generic ggml_vec_dot_nvfp4_q8_0
115119
#define ggml_vec_dot_tq1_0_q8_K_generic ggml_vec_dot_tq1_0_q8_K
116120
#define ggml_vec_dot_tq2_0_q8_K_generic ggml_vec_dot_tq2_0_q8_K
121+
#define ggml_vec_dot_tbq3_0_q8_K_generic ggml_vec_dot_tbq3_0_q8_K
122+
#define ggml_vec_dot_tbq4_0_q8_K_generic ggml_vec_dot_tbq4_0_q8_K
117123
#define ggml_vec_dot_iq1_m_q8_K_generic ggml_vec_dot_iq1_m_q8_K
118124
// repack.cpp
119125
#define ggml_quantize_mat_q8_0_4x4_generic ggml_quantize_mat_q8_0_4x4
@@ -157,6 +163,8 @@
157163
#define quantize_row_q8_K_generic quantize_row_q8_K
158164
#define ggml_vec_dot_tq1_0_q8_K_generic ggml_vec_dot_tq1_0_q8_K
159165
#define ggml_vec_dot_tq2_0_q8_K_generic ggml_vec_dot_tq2_0_q8_K
166+
#define ggml_vec_dot_tbq3_0_q8_K_generic ggml_vec_dot_tbq3_0_q8_K
167+
#define ggml_vec_dot_tbq4_0_q8_K_generic ggml_vec_dot_tbq4_0_q8_K
160168
#define ggml_vec_dot_iq1_m_q8_K_generic ggml_vec_dot_iq1_m_q8_K
161169
#define ggml_vec_dot_mxfp4_q8_0_generic ggml_vec_dot_mxfp4_q8_0
162170
#define ggml_vec_dot_nvfp4_q8_0_generic ggml_vec_dot_nvfp4_q8_0
@@ -242,6 +250,8 @@
242250
#define ggml_vec_dot_nvfp4_q8_0_generic ggml_vec_dot_nvfp4_q8_0
243251
#define ggml_vec_dot_tq1_0_q8_K_generic ggml_vec_dot_tq1_0_q8_K
244252
#define ggml_vec_dot_tq2_0_q8_K_generic ggml_vec_dot_tq2_0_q8_K
253+
#define ggml_vec_dot_tbq3_0_q8_K_generic ggml_vec_dot_tbq3_0_q8_K
254+
#define ggml_vec_dot_tbq4_0_q8_K_generic ggml_vec_dot_tbq4_0_q8_K
245255
#define ggml_vec_dot_q2_K_q8_K_generic ggml_vec_dot_q2_K_q8_K
246256
#define ggml_vec_dot_iq2_xxs_q8_K_generic ggml_vec_dot_iq2_xxs_q8_K
247257
#define ggml_vec_dot_iq2_xs_q8_K_generic ggml_vec_dot_iq2_xs_q8_K
@@ -292,6 +302,8 @@
292302
#define ggml_vec_dot_q4_1_q8_1_generic ggml_vec_dot_q4_1_q8_1
293303
#define ggml_vec_dot_tq1_0_q8_K_generic ggml_vec_dot_tq1_0_q8_K
294304
#define ggml_vec_dot_tq2_0_q8_K_generic ggml_vec_dot_tq2_0_q8_K
305+
#define ggml_vec_dot_tbq3_0_q8_K_generic ggml_vec_dot_tbq3_0_q8_K
306+
#define ggml_vec_dot_tbq4_0_q8_K_generic ggml_vec_dot_tbq4_0_q8_K
295307
#define ggml_vec_dot_iq2_xxs_q8_K_generic ggml_vec_dot_iq2_xxs_q8_K
296308
#define ggml_vec_dot_iq2_xs_q8_K_generic ggml_vec_dot_iq2_xs_q8_K
297309
#define ggml_vec_dot_iq2_s_q8_K_generic ggml_vec_dot_iq2_s_q8_K

ggml/src/ggml-cpu/ggml-cpu.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,18 @@ static const struct ggml_type_traits_cpu type_traits_cpu[GGML_TYPE_COUNT] = {
390390
.vec_dot_type = GGML_TYPE_Q8_K,
391391
.nrows = 1,
392392
},
393+
[GGML_TYPE_TBQ3_0] = {
394+
.from_float = quantize_row_tbq3_0,
395+
.vec_dot = ggml_vec_dot_tbq3_0_q8_K,
396+
.vec_dot_type = GGML_TYPE_Q8_K,
397+
.nrows = 1,
398+
},
399+
[GGML_TYPE_TBQ4_0] = {
400+
.from_float = quantize_row_tbq4_0,
401+
.vec_dot = ggml_vec_dot_tbq4_0_q8_K,
402+
.vec_dot_type = GGML_TYPE_Q8_K,
403+
.nrows = 1,
404+
},
393405
[GGML_TYPE_I32] = {
394406
.from_float = (ggml_from_float_t) ggml_cpu_fp32_to_i32,
395407
},

ggml/src/ggml-cpu/quants.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,20 @@ void quantize_row_tq2_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy,
108108
quantize_row_tq2_0_ref(x, y, k);
109109
}
110110

111+
// ====================== TurboQuant (TBQ) quantization ========================
112+
113+
void quantize_row_tbq3_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) {
114+
assert(k % QK_K == 0);
115+
block_tbq3_0 * GGML_RESTRICT y = vy;
116+
quantize_row_tbq3_0_ref(x, y, k);
117+
}
118+
119+
void quantize_row_tbq4_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) {
120+
assert(k % QK_K == 0);
121+
block_tbq4_0 * GGML_RESTRICT y = vy;
122+
quantize_row_tbq4_0_ref(x, y, k);
123+
}
124+
111125
//===================================== Q8_K ==============================================
112126

113127
void quantize_row_q8_K_generic(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k) {
@@ -456,6 +470,89 @@ void ggml_vec_dot_tq2_0_q8_K_generic(int n, float * GGML_RESTRICT s, size_t bs,
456470
*s = sumf;
457471
}
458472

473+
// ====================== TurboQuant vec_dot (dequant-then-dot) ====================
474+
//
475+
// These implementations fully dequantize the TBQ row (including inverse rotation),
476+
// then compute the dot product with the Q8_K row. The inverse rotation is O(d²).
477+
//
478+
// TODO: A faster approach would rotate the activation into the codebook domain
479+
// (Q^T · activation) and dot directly with codebook entries, avoiding inverse rotation.
480+
// This would require the rotation matrix to be accessible here.
481+
482+
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
483+
#define TURBOQ_VD_TL _Thread_local
484+
#elif defined(__GNUC__) || defined(__clang__)
485+
#define TURBOQ_VD_TL __thread
486+
#elif defined(_MSC_VER)
487+
#define TURBOQ_VD_TL __declspec(thread)
488+
#else
489+
#define TURBOQ_VD_TL
490+
#endif
491+
492+
static TURBOQ_VD_TL float * tbq_vd_buf = NULL;
493+
static TURBOQ_VD_TL int64_t tbq_vd_buf_size = 0;
494+
495+
static float * tbq_vd_get_scratch(int64_t n) {
496+
if (n > tbq_vd_buf_size) {
497+
free(tbq_vd_buf);
498+
tbq_vd_buf = (float *)malloc(n * sizeof(float));
499+
tbq_vd_buf_size = n;
500+
}
501+
return tbq_vd_buf;
502+
}
503+
504+
void ggml_vec_dot_tbq3_0_q8_K_generic(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
505+
assert(nrc == 1);
506+
UNUSED(nrc);
507+
UNUSED(bx);
508+
UNUSED(by);
509+
UNUSED(bs);
510+
511+
float * tmp = tbq_vd_get_scratch(n);
512+
dequantize_row_tbq3_0((const block_tbq3_0 *)vx, tmp, n);
513+
514+
const block_q8_K * GGML_RESTRICT y = vy;
515+
const int nb = n / QK_K;
516+
517+
float sumf = 0.0f;
518+
int64_t idx = 0;
519+
for (int i = 0; i < nb; i++) {
520+
const float d = y[i].d;
521+
for (int j = 0; j < QK_K; j++) {
522+
sumf += tmp[idx] * (d * y[i].qs[j]);
523+
idx++;
524+
}
525+
}
526+
527+
*s = sumf;
528+
}
529+
530+
void ggml_vec_dot_tbq4_0_q8_K_generic(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
531+
assert(nrc == 1);
532+
UNUSED(nrc);
533+
UNUSED(bx);
534+
UNUSED(by);
535+
UNUSED(bs);
536+
537+
float * tmp = tbq_vd_get_scratch(n);
538+
dequantize_row_tbq4_0((const block_tbq4_0 *)vx, tmp, n);
539+
540+
const block_q8_K * GGML_RESTRICT y = vy;
541+
const int nb = n / QK_K;
542+
543+
float sumf = 0.0f;
544+
int64_t idx = 0;
545+
for (int i = 0; i < nb; i++) {
546+
const float d = y[i].d;
547+
for (int j = 0; j < QK_K; j++) {
548+
sumf += tmp[idx] * (d * y[i].qs[j]);
549+
idx++;
550+
}
551+
}
552+
553+
*s = sumf;
554+
}
555+
459556
void ggml_vec_dot_q2_K_q8_K_generic(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
460557
assert(nrc == 1);
461558
UNUSED(nrc);

ggml/src/ggml-cpu/quants.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ void quantize_row_q8_K(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, in
3232
void quantize_row_tq1_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k);
3333
void quantize_row_tq2_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k);
3434

35+
void quantize_row_tbq3_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k);
36+
void quantize_row_tbq4_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k);
37+
3538
void quantize_row_iq4_nl (const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k);
3639
void quantize_row_iq4_xs (const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k);
3740

@@ -54,6 +57,9 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
5457
void ggml_vec_dot_tq1_0_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);
5558
void ggml_vec_dot_tq2_0_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);
5659

60+
void ggml_vec_dot_tbq3_0_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);
61+
void ggml_vec_dot_tbq4_0_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);
62+
5763
void ggml_vec_dot_iq2_xxs_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);
5864
void ggml_vec_dot_iq2_xs_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);
5965
void ggml_vec_dot_iq2_s_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);

ggml/src/ggml-quants.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5399,6 +5399,14 @@ bool ggml_validate_row_data(enum ggml_type type, const void * data, size_t nbyte
53995399
VALIDATE_ROW_DATA_D_F16_IMPL(block_iq4_nl, data, nb);
54005400
} break;
54015401

5402+
case GGML_TYPE_TBQ3_0:
5403+
{
5404+
VALIDATE_ROW_DATA_D_F16_IMPL(block_tbq3_0, data, nb);
5405+
} break;
5406+
case GGML_TYPE_TBQ4_0:
5407+
{
5408+
VALIDATE_ROW_DATA_D_F16_IMPL(block_tbq4_0, data, nb);
5409+
} break;
54025410
case GGML_TYPE_I8:
54035411
case GGML_TYPE_I16:
54045412
case GGML_TYPE_I32:

ggml/src/ggml-quants.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ GGML_API void quantize_row_q8_K_ref(const float * GGML_RESTRICT x, block_q8_K *
3434
GGML_API void quantize_row_tq1_0_ref(const float * GGML_RESTRICT x, block_tq1_0 * GGML_RESTRICT y, int64_t k);
3535
GGML_API void quantize_row_tq2_0_ref(const float * GGML_RESTRICT x, block_tq2_0 * GGML_RESTRICT y, int64_t k);
3636

37+
GGML_API void quantize_row_tbq3_0_ref(const float * GGML_RESTRICT x, block_tbq3_0 * GGML_RESTRICT y, int64_t k);
38+
GGML_API void quantize_row_tbq4_0_ref(const float * GGML_RESTRICT x, block_tbq4_0 * GGML_RESTRICT y, int64_t k);
39+
3740
GGML_API void quantize_row_iq3_xxs_ref(const float * GGML_RESTRICT x, block_iq3_xxs * GGML_RESTRICT y, int64_t k);
3841
GGML_API void quantize_row_iq4_nl_ref (const float * GGML_RESTRICT x, block_iq4_nl * GGML_RESTRICT y, int64_t k);
3942
GGML_API void quantize_row_iq4_xs_ref (const float * GGML_RESTRICT x, block_iq4_xs * GGML_RESTRICT y, int64_t k);
@@ -61,6 +64,9 @@ GGML_API void dequantize_row_q8_K(const block_q8_K * GGML_RESTRICT x, float * GG
6164
GGML_API void dequantize_row_tq1_0(const block_tq1_0 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k);
6265
GGML_API void dequantize_row_tq2_0(const block_tq2_0 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k);
6366

67+
GGML_API void dequantize_row_tbq3_0(const block_tbq3_0 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k);
68+
GGML_API void dequantize_row_tbq4_0(const block_tbq4_0 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k);
69+
6470
GGML_API void dequantize_row_iq2_xxs(const block_iq2_xxs * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k);
6571
GGML_API void dequantize_row_iq2_xs (const block_iq2_xs * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k);
6672
GGML_API void dequantize_row_iq2_s (const block_iq2_s * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k);
@@ -85,6 +91,9 @@ GGML_API size_t quantize_iq3_s (const float * GGML_RESTRICT src, void * GGML_RE
8591
GGML_API size_t quantize_tq1_0(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix);
8692
GGML_API size_t quantize_tq2_0(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix);
8793

94+
GGML_API size_t quantize_tbq3_0(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix);
95+
GGML_API size_t quantize_tbq4_0(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix);
96+
8897
GGML_API size_t quantize_q2_K(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix);
8998
GGML_API size_t quantize_q3_K(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix);
9099
GGML_API size_t quantize_q4_K(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix);

ggml/src/ggml-turboq-tables.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
// TurboQuant precomputed codebook tables (Lloyd-Max optimal for N(0,1))
4+
//
5+
// After random orthogonal rotation, coordinates of a unit vector follow
6+
// approximately Beta((d-1)/2, (d-1)/2) on [-1,1], which converges to
7+
// N(0, 1/d) for large d. The code scales by sqrt(d) before lookup.
8+
// Reference: "TurboQuant" (arXiv 2504.19874), Lloyd-Max quantizer.
9+
10+
static const float turboq_codebook_3bit[8] = {
11+
-2.1520f, -1.3440f, -0.7560f, -0.2451f,
12+
0.2451f, 0.7560f, 1.3440f, 2.1520f,
13+
};
14+
15+
static const float turboq_codebook_4bit[16] = {
16+
-2.7326f, -2.0690f, -1.6180f, -1.2562f,
17+
-0.9424f, -0.6568f, -0.3881f, -0.1284f,
18+
0.1284f, 0.3881f, 0.6568f, 0.9424f,
19+
1.2562f, 1.6180f, 2.0690f, 2.7326f,
20+
};
21+
22+
// Decision boundaries: midpoint between consecutive centroids
23+
24+
static const float turboq_boundaries_3bit[7] = {
25+
-1.7480f, -1.0500f, -0.5006f, 0.0000f,
26+
0.5006f, 1.0500f, 1.7480f,
27+
};
28+
29+
static const float turboq_boundaries_4bit[15] = {
30+
-2.4008f, -1.8435f, -1.4371f, -1.0993f,
31+
-0.7996f, -0.5225f, -0.2583f, 0.0000f,
32+
0.2583f, 0.5225f, 0.7996f, 1.0993f,
33+
1.4371f, 1.8435f, 2.4008f,
34+
};

0 commit comments

Comments
 (0)