Files
2026-07-13 12:22:11 +08:00

1909 lines
69 KiB
C

/*
* DeepSeek V4 Flash/Pro HF -> GGUF quantizer.
*
* This is a plain C, model-specific version of the DS4 quantization pipeline.
* It deliberately keeps only the pieces needed by the DeepSeek V4 Flash and
* Pro GGUF recipes used by this repository:
*
* - safetensors index/header loading;
* - FP8 E4M3 + E8M0 dequantization for dense tensors;
* - packed FP4 + E8M0 dequantization for routed experts;
* - local Q8_0, Q4_K, Q2_K, and IQ2_XXS quantization;
* - GGUF metadata/tensor-order reuse from an existing template GGUF.
*
* The optional imatrix is the legacy llama.cpp binary .dat format emitted by
* ds4's collector. DS4 stores one packed vector per routed tensor, laid out as
* n_experts consecutive per-expert importance vectors. When no external
* imatrix is supplied and IQ2_XXS requires one, this tool falls back to the
* same synthetic weight-energy heuristic used by the old generator:
* each column importance is sum(row[column]^2) over the dequantized weight.
*/
#define _DARWIN_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#include "quants.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#if defined(_WIN32)
#error "deepseek4-quantize.c currently targets POSIX systems"
#endif
#define DS4_KV_QUANTIZE_IMATRIX_FILE "quantize.imatrix.file"
#define DS4_KV_QUANTIZE_IMATRIX_DATASET "quantize.imatrix.dataset"
#define DS4_KV_QUANTIZE_IMATRIX_N_ENTRIES "quantize.imatrix.entries_count"
#define DS4_KV_QUANTIZE_IMATRIX_N_CHUNKS "quantize.imatrix.chunks_count"
#define DS4_GGUF_DEFAULT_ALIGNMENT 32
typedef enum {
GGUF_TYPE_UINT8 = 0,
GGUF_TYPE_INT8 = 1,
GGUF_TYPE_UINT16 = 2,
GGUF_TYPE_INT16 = 3,
GGUF_TYPE_UINT32 = 4,
GGUF_TYPE_INT32 = 5,
GGUF_TYPE_FLOAT32 = 6,
GGUF_TYPE_BOOL = 7,
GGUF_TYPE_STRING = 8,
GGUF_TYPE_ARRAY = 9,
GGUF_TYPE_UINT64 = 10,
GGUF_TYPE_INT64 = 11,
GGUF_TYPE_FLOAT64 = 12,
} gguf_value_type;
static void die(const char *msg) {
fprintf(stderr, "error: %s\n", msg);
exit(1);
}
static void die_errno(const char *what, const char *path) {
fprintf(stderr, "error: %s %s: %s\n", what, path ? path : "", strerror(errno));
exit(1);
}
static void *xmalloc(size_t n) {
void *p = malloc(n ? n : 1);
if (!p) die("out of memory");
return p;
}
static void *xcalloc(size_t n, size_t sz) {
void *p = calloc(n ? n : 1, sz ? sz : 1);
if (!p) die("out of memory");
return p;
}
static void *xrealloc(void *p, size_t n) {
void *q = realloc(p, n ? n : 1);
if (!q) die("out of memory");
return q;
}
static char *xstrdup(const char *s) {
size_t n = strlen(s);
char *p = xmalloc(n + 1);
memcpy(p, s, n + 1);
return p;
}
static char *xstrndup(const char *s, size_t n) {
char *p = xmalloc(n + 1);
memcpy(p, s, n);
p[n] = '\0';
return p;
}
static char *path_join(const char *a, const char *b) {
const size_t na = strlen(a);
const size_t nb = strlen(b);
const bool slash = na && a[na - 1] == '/';
char *out = xmalloc(na + (slash ? 0 : 1) + nb + 1);
memcpy(out, a, na);
size_t pos = na;
if (!slash) out[pos++] = '/';
memcpy(out + pos, b, nb + 1);
return out;
}
static bool str_starts(const char *s, const char *prefix) {
return strncmp(s, prefix, strlen(prefix)) == 0;
}
static bool str_ends(const char *s, const char *suffix) {
const size_t ns = strlen(s);
const size_t nf = strlen(suffix);
return ns >= nf && memcmp(s + ns - nf, suffix, nf) == 0;
}
static char *read_file(const char *path, size_t *len_out) {
FILE *fp = fopen(path, "rb");
if (!fp) die_errno("open", path);
if (fseeko(fp, 0, SEEK_END) != 0) die_errno("seek", path);
off_t n = ftello(fp);
if (n < 0) die_errno("tell", path);
if (fseeko(fp, 0, SEEK_SET) != 0) die_errno("seek", path);
char *buf = xmalloc((size_t)n + 1);
if (n && fread(buf, 1, (size_t)n, fp) != (size_t)n) die_errno("read", path);
buf[n] = '\0';
fclose(fp);
if (len_out) *len_out = (size_t)n;
return buf;
}
static uint64_t read_u64_le_fp(FILE *fp, const char *what) {
uint8_t b[8];
if (fread(b, 1, sizeof(b), fp) != sizeof(b)) {
fprintf(stderr, "error: short read while reading %s\n", what);
exit(1);
}
uint64_t v = 0;
for (int i = 0; i < 8; i++) v |= (uint64_t)b[i] << (8 * i);
return v;
}
static uint32_t read_u32_le_fp(FILE *fp, const char *what) {
uint32_t v;
if (fread(&v, 1, sizeof(v), fp) != sizeof(v)) {
fprintf(stderr, "error: short read while reading %s\n", what);
exit(1);
}
return v;
}
static int32_t read_i32_fp(FILE *fp, const char *what) {
int32_t v;
if (fread(&v, 1, sizeof(v), fp) != sizeof(v)) {
fprintf(stderr, "error: short read while reading %s\n", what);
exit(1);
}
return v;
}
static uint16_t load_u16_le(const uint8_t *p) {
return (uint16_t)p[0] | ((uint16_t)p[1] << 8);
}
static int64_t load_i64_le(const uint8_t *p) {
uint64_t v = 0;
for (int i = 0; i < 8; i++) v |= (uint64_t)p[i] << (8 * i);
return (int64_t)v;
}
/* =====
* Minimal JSON tokenizer
*
* Safetensors uses ordinary JSON for the model index and per-shard headers.
* We only need objects, arrays, strings, and primitive numbers; escaped tensor
* names do not occur in the files produced by Hugging Face, so strings are
* copied as raw UTF-8 slices after locating the closing quote.
*/
typedef enum {
JT_OBJECT,
JT_ARRAY,
JT_STRING,
JT_PRIMITIVE,
} json_type;
typedef struct {
json_type type;
int start;
int end;
int parent;
int size;
} json_tok;
typedef struct {
json_tok *v;
int len;
int cap;
const char *js;
int js_len;
} json_doc;
static int json_add(json_doc *d, json_type type, int start, int end, int parent) {
if (d->len == d->cap) {
d->cap = d->cap ? d->cap * 2 : 4096;
d->v = xrealloc(d->v, (size_t)d->cap * sizeof(d->v[0]));
}
int id = d->len++;
d->v[id] = (json_tok){ .type = type, .start = start, .end = end, .parent = parent, .size = 0 };
if (parent >= 0) d->v[parent].size++;
return id;
}
static json_doc json_parse_text(const char *js, size_t len) {
json_doc d = { .js = js, .js_len = (int)len };
int parent = -1;
for (int i = 0; i < (int)len; i++) {
unsigned char c = (unsigned char)js[i];
if (isspace(c) || c == ':' || c == ',') continue;
if (c == '{' || c == '[') {
parent = json_add(&d, c == '{' ? JT_OBJECT : JT_ARRAY, i, -1, parent);
continue;
}
if (c == '}' || c == ']') {
if (parent < 0) die("bad JSON: unmatched close");
d.v[parent].end = i + 1;
parent = d.v[parent].parent;
continue;
}
if (c == '"') {
int start = i + 1;
i++;
bool esc = false;
for (; i < (int)len; i++) {
if (esc) {
esc = false;
} else if (js[i] == '\\') {
esc = true;
} else if (js[i] == '"') {
break;
}
}
if (i >= (int)len) die("bad JSON: unterminated string");
json_add(&d, JT_STRING, start, i, parent);
continue;
}
int start = i;
while (i < (int)len && !isspace((unsigned char)js[i]) &&
js[i] != ',' && js[i] != ']' && js[i] != '}') {
i++;
}
json_add(&d, JT_PRIMITIVE, start, i, parent);
i--;
}
if (parent != -1) die("bad JSON: unterminated object/array");
return d;
}
static void json_free(json_doc *d) {
free(d->v);
memset(d, 0, sizeof(*d));
}
static bool json_tok_eq(const json_doc *d, int tok, const char *s) {
const json_tok *t = &d->v[tok];
const int n = t->end - t->start;
return t->type == JT_STRING && (int)strlen(s) == n && memcmp(d->js + t->start, s, (size_t)n) == 0;
}
static char *json_strdup_tok(const json_doc *d, int tok) {
const json_tok *t = &d->v[tok];
return xstrndup(d->js + t->start, (size_t)(t->end - t->start));
}
static bool json_is_descendant(const json_doc *d, int tok, int parent) {
for (int p = d->v[tok].parent; p >= 0; p = d->v[p].parent) {
if (p == parent) return true;
}
return false;
}
static int json_skip(const json_doc *d, int tok) {
int i = tok + 1;
while (i < d->len && json_is_descendant(d, i, tok)) i++;
return i;
}
static int json_obj_get(const json_doc *d, int obj, const char *key) {
if (obj < 0 || d->v[obj].type != JT_OBJECT) return -1;
for (int i = obj + 1; i < d->len && d->v[i].parent == obj;) {
int k = i;
int v = i + 1;
if (v >= d->len || d->v[v].parent != obj) return -1;
if (json_tok_eq(d, k, key)) return v;
i = json_skip(d, v);
}
return -1;
}
static int64_t json_i64(const json_doc *d, int tok) {
char tmp[64];
const int n = d->v[tok].end - d->v[tok].start;
if (n <= 0 || n >= (int)sizeof(tmp)) die("bad JSON integer");
memcpy(tmp, d->js + d->v[tok].start, (size_t)n);
tmp[n] = '\0';
return strtoll(tmp, NULL, 10);
}
/* =====
* Small string hash map
*/
typedef struct {
char *key;
int value;
} hslot;
typedef struct {
hslot *slots;
int cap;
} hmap;
static uint64_t fnv1a_str(const char *s) {
uint64_t h = 1469598103934665603ull;
while (*s) {
h ^= (uint8_t)*s++;
h *= 1099511628211ull;
}
return h;
}
static void hmap_build(hmap *m, char **keys, int n) {
int cap = 1;
while (cap < n * 3) cap <<= 1;
m->cap = cap ? cap : 2;
m->slots = xcalloc((size_t)m->cap, sizeof(m->slots[0]));
for (int i = 0; i < n; i++) {
uint64_t h = fnv1a_str(keys[i]);
int p = (int)(h & (uint64_t)(m->cap - 1));
while (m->slots[p].key) p = (p + 1) & (m->cap - 1);
m->slots[p].key = keys[i];
m->slots[p].value = i;
}
}
static int hmap_get(const hmap *m, const char *key) {
if (!m->slots) return -1;
uint64_t h = fnv1a_str(key);
int p = (int)(h & (uint64_t)(m->cap - 1));
while (m->slots[p].key) {
if (strcmp(m->slots[p].key, key) == 0) return m->slots[p].value;
p = (p + 1) & (m->cap - 1);
}
return -1;
}
static void hmap_free(hmap *m) {
free(m->slots);
memset(m, 0, sizeof(*m));
}
/* =====
* safetensors database
*/
#define MAX_DIMS 8
typedef struct {
char *dtype;
int n_dims;
int64_t shape[MAX_DIMS];
uint64_t begin;
uint64_t end;
} st_info;
typedef struct {
char *name;
char *file;
} weight_map_entry;
typedef struct {
char *name;
st_info info;
} tensor_entry;
typedef struct {
char *file;
char *path;
uint64_t data_base;
tensor_entry *tensors;
int n_tensors;
int cap_tensors;
hmap tensor_map;
FILE *fp;
pthread_mutex_t lock;
bool loaded;
} shard;
typedef struct {
char *hf_dir;
weight_map_entry *weights;
int n_weights;
hmap weight_map;
shard *shards;
int n_shards;
int cap_shards;
pthread_mutex_t lock;
} st_db;
typedef struct {
char *dtype;
int n_dims;
int64_t shape[MAX_DIMS];
uint8_t *data;
size_t nbytes;
} st_value;
static void st_value_free(st_value *v) {
free(v->dtype);
free(v->data);
memset(v, 0, sizeof(*v));
}
static void parse_shape(const json_doc *d, int arr_tok, st_info *info, const char *name) {
if (d->v[arr_tok].type != JT_ARRAY) {
fprintf(stderr, "error: bad shape for %s\n", name);
exit(1);
}
int nd = 0;
for (int i = arr_tok + 1; i < d->len && d->v[i].parent == arr_tok; i = json_skip(d, i)) {
if (nd >= MAX_DIMS) die("too many safetensors dimensions");
info->shape[nd++] = json_i64(d, i);
}
info->n_dims = nd;
}
static int db_find_shard(st_db *db, const char *file) {
for (int i = 0; i < db->n_shards; i++) {
if (strcmp(db->shards[i].file, file) == 0) return i;
}
if (db->n_shards == db->cap_shards) {
db->cap_shards = db->cap_shards ? db->cap_shards * 2 : 32;
db->shards = xrealloc(db->shards, (size_t)db->cap_shards * sizeof(db->shards[0]));
}
shard *s = &db->shards[db->n_shards];
memset(s, 0, sizeof(*s));
s->file = xstrdup(file);
s->path = path_join(db->hf_dir, file);
pthread_mutex_init(&s->lock, NULL);
return db->n_shards++;
}
static void shard_add_tensor(shard *s, char *name, st_info info) {
if (s->n_tensors == s->cap_tensors) {
s->cap_tensors = s->cap_tensors ? s->cap_tensors * 2 : 256;
s->tensors = xrealloc(s->tensors, (size_t)s->cap_tensors * sizeof(s->tensors[0]));
}
s->tensors[s->n_tensors++] = (tensor_entry){ .name = name, .info = info };
}
static void shard_load(shard *s) {
if (s->loaded) return;
FILE *fp = fopen(s->path, "rb");
if (!fp) die_errno("open", s->path);
uint64_t header_len = read_u64_le_fp(fp, "safetensors header length");
char *header = xmalloc((size_t)header_len + 1);
if (fread(header, 1, (size_t)header_len, fp) != (size_t)header_len) die_errno("read header", s->path);
header[header_len] = '\0';
s->data_base = 8 + header_len;
json_doc d = json_parse_text(header, (size_t)header_len);
if (d.len < 1 || d.v[0].type != JT_OBJECT) die("bad safetensors header");
for (int i = 1; i < d.len && d.v[i].parent == 0;) {
int k = i;
int v = i + 1;
if (v >= d.len || d.v[v].parent != 0) die("bad safetensors header object");
if (!json_tok_eq(&d, k, "__metadata__")) {
char *name = json_strdup_tok(&d, k);
st_info info = {0};
int dtype = json_obj_get(&d, v, "dtype");
int shape = json_obj_get(&d, v, "shape");
int offsets = json_obj_get(&d, v, "data_offsets");
if (dtype < 0 || shape < 0 || offsets < 0) die("bad safetensors tensor entry");
info.dtype = json_strdup_tok(&d, dtype);
parse_shape(&d, shape, &info, name);
int n_off = 0;
for (int j = offsets + 1; j < d.len && d.v[j].parent == offsets; j = json_skip(&d, j)) {
int64_t x = json_i64(&d, j);
if (n_off == 0) info.begin = (uint64_t)x;
else if (n_off == 1) info.end = (uint64_t)x;
n_off++;
}
if (n_off != 2) die("bad safetensors data_offsets");
shard_add_tensor(s, name, info);
}
i = json_skip(&d, v);
}
char **keys = xmalloc((size_t)s->n_tensors * sizeof(keys[0]));
for (int i = 0; i < s->n_tensors; i++) keys[i] = s->tensors[i].name;
hmap_build(&s->tensor_map, keys, s->n_tensors);
free(keys);
json_free(&d);
free(header);
s->fp = fp;
s->loaded = true;
}
static void db_open(st_db *db, const char *hf_dir) {
memset(db, 0, sizeof(*db));
pthread_mutex_init(&db->lock, NULL);
db->hf_dir = xstrdup(hf_dir);
char *index_path = path_join(hf_dir, "model.safetensors.index.json");
size_t len = 0;
char *text = read_file(index_path, &len);
json_doc d = json_parse_text(text, len);
int weight_map = json_obj_get(&d, 0, "weight_map");
if (weight_map < 0 || d.v[weight_map].type != JT_OBJECT) die("safetensors index has no weight_map");
int cap = 4096;
db->weights = xmalloc((size_t)cap * sizeof(db->weights[0]));
for (int i = weight_map + 1; i < d.len && d.v[i].parent == weight_map;) {
int k = i;
int v = i + 1;
if (db->n_weights == cap) {
cap *= 2;
db->weights = xrealloc(db->weights, (size_t)cap * sizeof(db->weights[0]));
}
db->weights[db->n_weights].name = json_strdup_tok(&d, k);
db->weights[db->n_weights].file = json_strdup_tok(&d, v);
db->n_weights++;
i = json_skip(&d, v);
}
char **keys = xmalloc((size_t)db->n_weights * sizeof(keys[0]));
for (int i = 0; i < db->n_weights; i++) {
keys[i] = db->weights[i].name;
db_find_shard(db, db->weights[i].file);
}
hmap_build(&db->weight_map, keys, db->n_weights);
free(keys);
json_free(&d);
free(text);
free(index_path);
}
static void db_close(st_db *db) {
for (int i = 0; i < db->n_weights; i++) {
free(db->weights[i].name);
free(db->weights[i].file);
}
for (int i = 0; i < db->n_shards; i++) {
shard *s = &db->shards[i];
if (s->fp) fclose(s->fp);
for (int j = 0; j < s->n_tensors; j++) {
free(s->tensors[j].name);
free(s->tensors[j].info.dtype);
}
free(s->tensors);
hmap_free(&s->tensor_map);
pthread_mutex_destroy(&s->lock);
free(s->file);
free(s->path);
}
hmap_free(&db->weight_map);
pthread_mutex_destroy(&db->lock);
free(db->weights);
free(db->shards);
free(db->hf_dir);
memset(db, 0, sizeof(*db));
}
static bool db_has(const st_db *db, const char *name) {
return hmap_get(&db->weight_map, name) >= 0;
}
static tensor_entry *db_tensor(st_db *db, const char *name, shard **shard_out) {
pthread_mutex_lock(&db->lock);
int wi = hmap_get(&db->weight_map, name);
if (wi < 0) {
fprintf(stderr, "error: HF tensor not found: %s\n", name);
exit(1);
}
const char *file = db->weights[wi].file;
int si = db_find_shard(db, file);
shard *s = &db->shards[si];
shard_load(s);
int ti = hmap_get(&s->tensor_map, name);
if (ti < 0) {
fprintf(stderr, "error: HF tensor %s missing from shard %s\n", name, file);
exit(1);
}
if (shard_out) *shard_out = s;
tensor_entry *te = &s->tensors[ti];
pthread_mutex_unlock(&db->lock);
return te;
}
static st_value db_read(st_db *db, const char *name) {
shard *s = NULL;
tensor_entry *te = db_tensor(db, name, &s);
const size_t nbytes = (size_t)(te->info.end - te->info.begin);
st_value v = {0};
v.dtype = xstrdup(te->info.dtype);
v.n_dims = te->info.n_dims;
memcpy(v.shape, te->info.shape, sizeof(v.shape));
v.nbytes = nbytes;
v.data = xmalloc(nbytes);
pthread_mutex_lock(&s->lock);
if (fseeko(s->fp, (off_t)(s->data_base + te->info.begin), SEEK_SET) != 0) die_errno("seek", s->path);
if (nbytes && fread(v.data, 1, nbytes, s->fp) != nbytes) die_errno("read tensor", s->path);
pthread_mutex_unlock(&s->lock);
return v;
}
/* =====
* DeepSeek V4 data conversion
*/
static float e8m0_to_f32(uint8_t e) {
const uint32_t bits = e == 0 ? 0x00400000u : ((uint32_t)e << 23);
float result;
memcpy(&result, &bits, sizeof(result));
return result;
}
static float e4m3fn_to_f32(uint8_t x) {
const uint8_t abs = x & 0x7f;
const bool sign = (x & 0x80) != 0;
if (abs == 0) return sign ? -0.0f : 0.0f;
if (abs == 0x7f) return 0.0f;
const int exp = (x >> 3) & 0x0f;
const int man = x & 0x07;
float value = exp == 0 ? ldexpf((float)man, -9)
: ldexpf(1.0f + (float)man / 8.0f, exp - 7);
return sign ? -value : value;
}
static float bf16_to_f32_bits(uint16_t bits) {
return ds4q_bf16_to_f32(bits);
}
static int64_t value_nelements(const st_value *v) {
int64_t n = 1;
for (int i = 0; i < v->n_dims; i++) n *= v->shape[i];
return n;
}
static float *tensor_to_f32(const st_value *t, int64_t *n_out) {
const int64_t n = value_nelements(t);
float *out = xmalloc((size_t)n * sizeof(float));
if (strcmp(t->dtype, "F32") == 0) {
if (t->nbytes != (size_t)n * sizeof(float)) die("bad F32 byte size");
memcpy(out, t->data, t->nbytes);
} else if (strcmp(t->dtype, "BF16") == 0) {
if (t->nbytes != (size_t)n * sizeof(uint16_t)) die("bad BF16 byte size");
for (int64_t i = 0; i < n; i++) out[i] = bf16_to_f32_bits(load_u16_le(t->data + (size_t)i * 2));
} else if (strcmp(t->dtype, "F16") == 0) {
if (t->nbytes != (size_t)n * sizeof(uint16_t)) die("bad F16 byte size");
for (int64_t i = 0; i < n; i++) out[i] = ds4q_f16_to_f32(load_u16_le(t->data + (size_t)i * 2));
} else if (strcmp(t->dtype, "F8_E4M3") == 0) {
if (t->nbytes != (size_t)n) die("bad F8_E4M3 byte size");
for (int64_t i = 0; i < n; i++) out[i] = e4m3fn_to_f32(t->data[i]);
} else {
fprintf(stderr, "error: cannot convert HF dtype directly: %s\n", t->dtype);
exit(1);
}
if (n_out) *n_out = n;
return out;
}
static float *dequant_fp8_weight(const st_value *w, const st_value *scale, int64_t *n_out) {
if (strcmp(w->dtype, "F8_E4M3") != 0 || strcmp(scale->dtype, "F8_E8M0") != 0) die("bad FP8 weight/scale dtype");
if (w->n_dims != 2 || scale->n_dims != 2) die("FP8 tensor must be 2D");
const int64_t out_dim = w->shape[0];
const int64_t in_dim = w->shape[1];
const int64_t block_out = 128;
const int64_t block_in = 128;
if (out_dim % block_out || in_dim % block_in) die("FP8 dims are not divisible by 128");
const int64_t scale_rows = out_dim / block_out;
const int64_t scale_cols = in_dim / block_in;
if (scale->shape[0] != scale_rows || scale->shape[1] != scale_cols) die("FP8 scale shape mismatch");
float *out = xmalloc((size_t)out_dim * (size_t)in_dim * sizeof(float));
for (int64_t ob = 0; ob < scale_rows; ob++) {
for (int64_t ib = 0; ib < scale_cols; ib++) {
const float s = e8m0_to_f32(scale->data[(size_t)ob * (size_t)scale_cols + (size_t)ib]);
for (int64_t r = 0; r < block_out; r++) {
const int64_t row = ob * block_out + r;
const size_t base = (size_t)row * (size_t)in_dim + (size_t)ib * (size_t)block_in;
for (int64_t c = 0; c < block_in; c++) {
out[base + (size_t)c] = e4m3fn_to_f32(w->data[base + (size_t)c]) * s;
}
}
}
}
if (n_out) *n_out = out_dim * in_dim;
return out;
}
static float *dequant_fp4_weight(const st_value *w, const st_value *scale, int64_t *n_out) {
static const float fp4_table[16] = {
0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 6.0f,
0.0f, -0.5f, -1.0f, -1.5f, -2.0f, -3.0f, -4.0f, -6.0f,
};
if (strcmp(w->dtype, "I8") != 0 || strcmp(scale->dtype, "F8_E8M0") != 0) die("bad FP4 weight/scale dtype");
if (w->n_dims != 2 || scale->n_dims != 2) die("FP4 tensor must be 2D");
const int64_t out_dim = w->shape[0];
const int64_t packed_in = w->shape[1];
const int64_t in_dim = packed_in * 2;
if (in_dim % 32) die("FP4 in_dim is not divisible by 32");
const int64_t n_blocks = in_dim / 32;
if (scale->shape[0] != out_dim || scale->shape[1] != n_blocks) die("FP4 scale shape mismatch");
float *out = xmalloc((size_t)out_dim * (size_t)in_dim * sizeof(float));
for (int64_t r = 0; r < out_dim; r++) {
for (int64_t b = 0; b < n_blocks; b++) {
const float s = e8m0_to_f32(scale->data[(size_t)r * (size_t)n_blocks + (size_t)b]);
const size_t wbase = ((size_t)r * (size_t)n_blocks + (size_t)b) * 16;
const size_t obase = (size_t)r * (size_t)in_dim + (size_t)b * 32;
for (int64_t j = 0; j < 16; j++) {
const uint8_t q = w->data[wbase + (size_t)j];
out[obase + (size_t)(2*j + 0)] = fp4_table[q & 0x0f] * s;
out[obase + (size_t)(2*j + 1)] = fp4_table[(q >> 4) & 0x0f] * s;
}
}
}
if (n_out) *n_out = out_dim * in_dim;
return out;
}
/* =====
* Imatrix
*/
typedef struct {
char *name;
float *values;
int n_values;
} imatrix_entry;
typedef struct {
char *file;
char *dataset;
imatrix_entry *entries;
int n_entries;
hmap map;
int chunks;
bool strict;
} imatrix_store;
static void imatrix_load(imatrix_store *im, const char *path, bool strict) {
memset(im, 0, sizeof(*im));
im->file = xstrdup(path);
im->strict = strict;
im->chunks = -1;
FILE *fp = fopen(path, "rb");
if (!fp) die_errno("open imatrix", path);
int32_t n_entries = read_i32_fp(fp, "imatrix entry count");
if (n_entries < 1) die("imatrix has no entries");
im->entries = xcalloc((size_t)n_entries, sizeof(im->entries[0]));
im->n_entries = n_entries;
for (int i = 0; i < n_entries; i++) {
int32_t len = read_i32_fp(fp, "imatrix name length");
if (len <= 0 || len > 4096) die("bad imatrix name length");
char *name = xmalloc((size_t)len + 1);
if (fread(name, 1, (size_t)len, fp) != (size_t)len) die("short imatrix name read");
name[len] = '\0';
int32_t ncall = read_i32_fp(fp, "imatrix calls");
int32_t nval = read_i32_fp(fp, "imatrix values");
if (nval < 1) die("bad imatrix value count");
float *values = xmalloc((size_t)nval * sizeof(float));
if (fread(values, sizeof(float), (size_t)nval, fp) != (size_t)nval) die("short imatrix value read");
if (ncall > 0) {
for (int j = 0; j < nval; j++) values[j] /= (float)ncall;
}
for (int j = 0; j < nval; j++) {
if (!isfinite(values[j])) die("non-finite imatrix value");
}
im->entries[i] = (imatrix_entry){ .name = name, .values = values, .n_values = nval };
}
if (fgetc(fp) != EOF) {
if (fseeko(fp, -1, SEEK_CUR) == 0) {
im->chunks = read_i32_fp(fp, "imatrix chunks");
int32_t dlen = read_i32_fp(fp, "imatrix dataset length");
if (dlen > 0 && dlen < (1 << 20)) {
im->dataset = xmalloc((size_t)dlen + 1);
if (fread(im->dataset, 1, (size_t)dlen, fp) == (size_t)dlen) {
im->dataset[dlen] = '\0';
} else {
free(im->dataset);
im->dataset = NULL;
}
}
}
}
fclose(fp);
char **keys = xmalloc((size_t)n_entries * sizeof(keys[0]));
for (int i = 0; i < n_entries; i++) keys[i] = im->entries[i].name;
hmap_build(&im->map, keys, n_entries);
free(keys);
fprintf(stderr, "loaded imatrix %s: %d entries%s%s\n",
path, n_entries, im->dataset ? ", dataset=" : "", im->dataset ? im->dataset : "");
}
static bool imatrix_enabled(const imatrix_store *im) {
return im && im->n_entries > 0;
}
static const float *imatrix_find(
const imatrix_store *im,
const char **names,
int n_names,
int64_t ncols,
int expert_id,
int n_experts) {
if (!imatrix_enabled(im)) return NULL;
char tmp[4096];
for (int pass = 0; pass < 3; pass++) {
for (int i = 0; i < n_names; i++) {
if (!names[i]) continue;
const char *candidate = names[i];
if (expert_id >= 0 && pass < 2) {
snprintf(tmp, sizeof(tmp), "%s.expert%s%d", names[i], pass == 0 ? "." : "_", expert_id);
candidate = tmp;
} else if (pass < 2) {
continue;
}
int idx = hmap_get(&im->map, candidate);
if (idx < 0) continue;
const imatrix_entry *e = &im->entries[idx];
if ((int64_t)e->n_values == ncols) return e->values;
if (expert_id >= 0 && n_experts > 0 && (int64_t)e->n_values == ncols * (int64_t)n_experts) {
return e->values + (size_t)expert_id * (size_t)ncols;
}
fprintf(stderr, "error: imatrix size mismatch for %s: got %d expected %" PRId64 "\n",
candidate, e->n_values, ncols);
exit(1);
}
}
if (im->strict) {
fprintf(stderr, "error: missing imatrix entry for %s\n", names[0] ? names[0] : "(unnamed)");
exit(1);
}
return NULL;
}
static void imatrix_free(imatrix_store *im) {
for (int i = 0; i < im->n_entries; i++) {
free(im->entries[i].name);
free(im->entries[i].values);
}
free(im->entries);
free(im->file);
free(im->dataset);
hmap_free(&im->map);
memset(im, 0, sizeof(*im));
}
/* =====
* GGUF tensor mapping and quantization policy
*/
typedef enum { EXP_NONE, EXP_W1, EXP_W2, EXP_W3 } expert_part;
typedef struct {
bool is_expert;
int layer;
expert_part part;
} expert_tensor;
static expert_tensor parse_expert_tensor(const char *name) {
expert_tensor e = {0};
int layer = -1;
char kind[16];
int rest = 0;
if (sscanf(name, "blk.%d.ffn_%15[^_]_exps.weight%n", &layer, kind, &rest) == 2
&& rest == (int)strlen(name))
{
if (strcmp(kind, "gate") == 0 || strcmp(kind, "down") == 0 || strcmp(kind, "up") == 0) {
e.is_expert = true;
e.layer = layer;
e.part = strcmp(kind, "gate") == 0 ? EXP_W1 : strcmp(kind, "down") == 0 ? EXP_W2 : EXP_W3;
}
}
return e;
}
static const char *expert_part_name(expert_part p) {
switch (p) {
case EXP_W1: return "w1";
case EXP_W2: return "w2";
case EXP_W3: return "w3";
default: die("bad expert part");
}
return "";
}
typedef struct {
const char *gguf;
const char *hf;
} name_map;
static const name_map top_map[] = {
{ "token_embd.weight", "embed.weight" },
{ "output_norm.weight", "norm.weight" },
{ "output.weight", "head.weight" },
{ "output_hc_base.weight", "hc_head_base" },
{ "output_hc_fn.weight", "hc_head_fn" },
{ "output_hc_scale.weight", "hc_head_scale" },
};
static const name_map layer_map[] = {
{ "hc_attn_base.weight", "hc_attn_base" },
{ "hc_attn_fn.weight", "hc_attn_fn" },
{ "hc_attn_scale.weight", "hc_attn_scale" },
{ "hc_ffn_base.weight", "hc_ffn_base" },
{ "hc_ffn_fn.weight", "hc_ffn_fn" },
{ "hc_ffn_scale.weight", "hc_ffn_scale" },
{ "attn_sinks.weight", "attn.attn_sink" },
{ "attn_q_a.weight", "attn.wq_a.weight" },
{ "attn_q_b.weight", "attn.wq_b.weight" },
{ "attn_q_a_norm.weight", "attn.q_norm.weight" },
{ "attn_kv.weight", "attn.wkv.weight" },
{ "attn_kv_a_norm.weight", "attn.kv_norm.weight" },
{ "attn_output_a.weight", "attn.wo_a.weight" },
{ "attn_output_b.weight", "attn.wo_b.weight" },
{ "attn_compressor_ape.weight", "attn.compressor.ape" },
{ "attn_compressor_kv.weight", "attn.compressor.wkv.weight" },
{ "attn_compressor_gate.weight", "attn.compressor.wgate.weight" },
{ "attn_compressor_norm.weight", "attn.compressor.norm.weight" },
{ "indexer.attn_q_b.weight", "attn.indexer.wq_b.weight" },
{ "indexer.proj.weight", "attn.indexer.weights_proj.weight" },
{ "indexer_compressor_ape.weight", "attn.indexer.compressor.ape" },
{ "indexer_compressor_kv.weight", "attn.indexer.compressor.wkv.weight" },
{ "indexer_compressor_gate.weight", "attn.indexer.compressor.wgate.weight" },
{ "indexer_compressor_norm.weight", "attn.indexer.compressor.norm.weight" },
{ "attn_norm.weight", "attn_norm.weight" },
{ "ffn_norm.weight", "ffn_norm.weight" },
{ "ffn_gate_shexp.weight", "ffn.shared_experts.w1.weight" },
{ "ffn_up_shexp.weight", "ffn.shared_experts.w3.weight" },
{ "ffn_down_shexp.weight", "ffn.shared_experts.w2.weight" },
{ "ffn_gate_inp.weight", "ffn.gate.weight" },
{ "exp_probs_b.bias", "ffn.gate.bias" },
{ "ffn_gate_tid2eid.weight", "ffn.gate.tid2eid" },
};
static char *hf_name_for_regular(const char *gguf_name) {
for (size_t i = 0; i < sizeof(top_map) / sizeof(top_map[0]); i++) {
if (strcmp(gguf_name, top_map[i].gguf) == 0) return xstrdup(top_map[i].hf);
}
int layer = -1;
const char *p = gguf_name;
if (sscanf(p, "blk.%d.", &layer) != 1) {
fprintf(stderr, "error: cannot map GGUF tensor to HF tensor: %s\n", gguf_name);
exit(1);
}
const char *rest = strchr(p + 4, '.');
if (!rest) die("bad layer tensor name");
rest++;
for (size_t i = 0; i < sizeof(layer_map) / sizeof(layer_map[0]); i++) {
if (strcmp(rest, layer_map[i].gguf) == 0) {
char buf[512];
snprintf(buf, sizeof(buf), "layers.%d.%s", layer, layer_map[i].hf);
return xstrdup(buf);
}
}
fprintf(stderr, "error: cannot map GGUF tensor to HF tensor: %s\n", gguf_name);
exit(1);
}
typedef struct {
char *prefix;
ds4q_type type;
} type_override;
typedef struct {
ds4q_type routed_w1, routed_w2, routed_w3;
ds4q_type attention_proj, attention, shared, embedding, output, dense;
type_override *overrides;
int n_overrides;
} quant_policy;
static bool is_attention_projection(const char *name) {
return strstr(name, ".attn_kv.weight") || strstr(name, ".attn_q_a.weight") ||
strstr(name, ".attn_q_b.weight") || strstr(name, ".attn_output_a.weight") ||
strstr(name, ".attn_output_b.weight");
}
static bool is_attention_tensor(const char *name) {
return strstr(name, ".attn") || strstr(name, "attn_") || strstr(name, ".indexer") || strstr(name, "indexer_");
}
static bool is_shared_expert(const char *name) {
return strstr(name, "_shexp.") != NULL;
}
static bool is_output_tensor(const char *name) {
return str_starts(name, "output.");
}
typedef struct {
char *name;
int n_dims;
int64_t ne[DS4Q_MAX_DIMS];
ds4q_type type;
uint64_t old_offset;
uint64_t new_offset;
size_t size;
} tensor_meta;
static int tensor_n_dims(const tensor_meta *t) {
int n = t->n_dims;
while (n > 1 && t->ne[n - 1] == 1) n--;
return n;
}
static ds4q_type policy_type(const quant_policy *p, const char *name, const tensor_meta *tmpl) {
for (int i = 0; i < p->n_overrides; i++) {
if (strcmp(name, p->overrides[i].prefix) == 0 || str_starts(name, p->overrides[i].prefix)) {
return p->overrides[i].type;
}
}
expert_tensor e = parse_expert_tensor(name);
if (e.is_expert) {
if (e.part == EXP_W1 && p->routed_w1 != DS4Q_TYPE_COUNT) return p->routed_w1;
if (e.part == EXP_W2 && p->routed_w2 != DS4Q_TYPE_COUNT) return p->routed_w2;
if (e.part == EXP_W3 && p->routed_w3 != DS4Q_TYPE_COUNT) return p->routed_w3;
return tmpl->type;
}
if (tmpl->type != DS4Q_TYPE_F32 && tmpl->type != DS4Q_TYPE_F16 &&
tmpl->type != DS4Q_TYPE_BF16 && !ds4q_can_quantize(tmpl->type)) {
return tmpl->type;
}
if (tensor_n_dims(tmpl) <= 1) return tmpl->type;
if (strcmp(name, "token_embd.weight") == 0 && p->embedding != DS4Q_TYPE_COUNT) return p->embedding;
if (is_output_tensor(name) && p->output != DS4Q_TYPE_COUNT) return p->output;
if (is_shared_expert(name) && p->shared != DS4Q_TYPE_COUNT) return p->shared;
if (is_attention_projection(name) && p->attention_proj != DS4Q_TYPE_COUNT) return p->attention_proj;
if (is_attention_tensor(name) && p->attention != DS4Q_TYPE_COUNT) return p->attention;
if (p->dense != DS4Q_TYPE_COUNT) return p->dense;
return tmpl->type;
}
static ds4q_type parse_type(const char *raw) {
char wanted[64];
size_t n = 0;
for (const char *p = raw; *p && n + 1 < sizeof(wanted); p++) {
if (*p != '-' && *p != '_') wanted[n++] = (char)tolower((unsigned char)*p);
}
wanted[n] = '\0';
if (strcmp(wanted, "copy") == 0 || strcmp(wanted, "template") == 0) return DS4Q_TYPE_COUNT;
for (int i = 0; i < DS4Q_TYPE_COUNT; i++) {
char name[64];
size_t m = 0;
const char *tn = ds4q_type_name((ds4q_type)i);
if (!tn) continue;
for (const char *p = tn; *p && m + 1 < sizeof(name); p++) {
if (*p != '-' && *p != '_') name[m++] = (char)tolower((unsigned char)*p);
}
name[m] = '\0';
if (strcmp(name, wanted) == 0) return (ds4q_type)i;
}
fprintf(stderr, "error: unknown quant type: %s\n", raw);
exit(1);
}
static bool is_quantizable_target(ds4q_type type) {
return type == DS4Q_TYPE_F32 || type == DS4Q_TYPE_F16 || type == DS4Q_TYPE_BF16 || ds4q_can_quantize(type);
}
/* =====
* Tensor generation
*/
typedef struct {
uint8_t *data;
size_t size;
} byte_buf;
static byte_buf f32_to_type(const float *src, int64_t n, ds4q_type type, int64_t ncols, const float *imat) {
if (ncols <= 0 || n % ncols != 0) die("bad ncols for tensor conversion");
byte_buf out = {0};
if (type == DS4Q_TYPE_F32) {
out.size = (size_t)n * sizeof(float);
out.data = xmalloc(out.size);
memcpy(out.data, src, out.size);
return out;
}
if (type == DS4Q_TYPE_F16) {
out.size = (size_t)n * sizeof(uint16_t);
out.data = xmalloc(out.size);
ds4q_f32_to_f16_row(src, (uint16_t *)out.data, n);
return out;
}
if (type == DS4Q_TYPE_BF16) {
out.size = (size_t)n * sizeof(uint16_t);
out.data = xmalloc(out.size);
ds4q_f32_to_bf16_row(src, (uint16_t *)out.data, n);
return out;
}
if (!ds4q_can_quantize(type)) die("unsupported quant target type");
if (ncols % ds4q_block_size(type) != 0) die("ncols is not divisible by quant block size");
const int64_t nrows = n / ncols;
out.size = (size_t)nrows * ds4q_row_size(type, ncols);
out.data = xmalloc(out.size);
float *synthetic = NULL;
const float *im_ptr = imat;
if (!im_ptr && ds4q_requires_imatrix(type)) {
synthetic = xcalloc((size_t)ncols, sizeof(float));
for (int64_t r = 0; r < nrows; r++) {
const float *row = src + (size_t)r * (size_t)ncols;
for (int64_t c = 0; c < ncols; c++) synthetic[c] += row[c] * row[c];
}
im_ptr = synthetic;
}
size_t written = ds4q_quantize_chunk(type, src, out.data, 0, nrows, ncols, im_ptr);
free(synthetic);
if (written != out.size) die("ds4q_quantize_chunk wrote unexpected byte count");
return out;
}
static byte_buf i64_to_i32(const st_value *src) {
if (strcmp(src->dtype, "I64") != 0) die("expected I64 source for I32 tensor");
const int64_t n = value_nelements(src);
if (src->nbytes != (size_t)n * sizeof(int64_t)) die("bad I64 byte size");
byte_buf out = { .size = (size_t)n * sizeof(int32_t), .data = xmalloc((size_t)n * sizeof(int32_t)) };
int32_t *dst = (int32_t *)out.data;
for (int64_t i = 0; i < n; i++) {
int64_t v = load_i64_le(src->data + (size_t)i * 8);
if (v < INT32_MIN || v > INT32_MAX) die("I64 value out of I32 range");
dst[i] = (int32_t)v;
}
return out;
}
static size_t tensor_nbytes(ds4q_type type, const int64_t *ne, int n_dims) {
size_t nbytes = ds4q_row_size(type, ne[0]);
for (int i = 1; i < n_dims; i++) nbytes *= (size_t)ne[i];
return nbytes;
}
static void check_reversed_shape(const char *gguf_name, const st_info *info, const tensor_meta *tmpl) {
int nd = tensor_n_dims(tmpl);
if (info->n_dims != nd) {
fprintf(stderr, "error: rank mismatch for %s\n", gguf_name);
exit(1);
}
for (int i = 0; i < nd; i++) {
if (tmpl->ne[i] != info->shape[nd - 1 - i]) {
fprintf(stderr, "error: shape mismatch for %s\n", gguf_name);
exit(1);
}
}
}
static byte_buf generate_regular(st_db *db, const char *gguf_name, const tensor_meta *tmpl,
ds4q_type target, const imatrix_store *imatrix) {
char *hf_name = hf_name_for_regular(gguf_name);
tensor_entry *te = db_tensor(db, hf_name, NULL);
check_reversed_shape(gguf_name, &te->info, tmpl);
if (target == DS4Q_TYPE_I32) {
st_value sv = db_read(db, hf_name);
byte_buf b = i64_to_i32(&sv);
st_value_free(&sv);
free(hf_name);
return b;
}
if (!is_quantizable_target(target)) die("unsupported regular target type");
int64_t n = 0;
float *f32 = NULL;
if (strcmp(te->info.dtype, "F8_E4M3") == 0) {
if (!str_ends(hf_name, ".weight")) die("FP8 tensor without .weight suffix");
char *scale_name = xstrdup(hf_name);
strcpy(scale_name + strlen(scale_name) - strlen(".weight"), ".scale");
if (!db_has(db, scale_name)) die("missing FP8 scale tensor");
st_value w = db_read(db, hf_name);
st_value s = db_read(db, scale_name);
f32 = dequant_fp8_weight(&w, &s, &n);
st_value_free(&w);
st_value_free(&s);
free(scale_name);
} else {
st_value w = db_read(db, hf_name);
f32 = tensor_to_f32(&w, &n);
st_value_free(&w);
}
const char *names[2] = { gguf_name, hf_name };
const float *imat = imatrix_find(imatrix, names, 2, tmpl->ne[0], -1, 0);
byte_buf b = f32_to_type(f32, n, target, tmpl->ne[0], imat);
free(f32);
free(hf_name);
return b;
}
typedef struct {
st_db *db;
const char *gguf_name;
const tensor_meta *tmpl;
ds4q_type target;
int n_experts;
const imatrix_store *imatrix;
expert_tensor expert;
const char *wid;
int64_t ncols;
int64_t nrows;
size_t per_expert;
byte_buf *out;
int next;
int done;
pthread_mutex_t lock;
} expert_job;
static void generate_one_expert(expert_job *j, int xid) {
char prefix[256];
snprintf(prefix, sizeof(prefix), "layers.%d.ffn.experts.%d.%s", j->expert.layer, xid, j->wid);
char weight_name[320];
char scale_name[320];
snprintf(weight_name, sizeof(weight_name), "%s.weight", prefix);
snprintf(scale_name, sizeof(scale_name), "%s.scale", prefix);
st_value w = db_read(j->db, weight_name);
st_value s = db_read(j->db, scale_name);
if (w.n_dims != 2 || w.shape[0] != j->nrows || w.shape[1] * 2 != j->ncols) die("expert shape mismatch");
int64_t n = 0;
float *f32 = dequant_fp4_weight(&w, &s, &n);
const char *names[3] = { j->gguf_name, weight_name, NULL };
const float *imat = imatrix_find(j->imatrix, names, 2, j->ncols, xid, j->n_experts);
byte_buf q = f32_to_type(f32, n, j->target, j->ncols, imat);
if (q.size != j->per_expert) die("expert quantized size mismatch");
memcpy(j->out->data + (size_t)xid * j->per_expert, q.data, q.size);
free(q.data);
free(f32);
st_value_free(&w);
st_value_free(&s);
}
static void *expert_worker(void *arg) {
expert_job *j = arg;
for (;;) {
pthread_mutex_lock(&j->lock);
int xid = j->next++;
pthread_mutex_unlock(&j->lock);
if (xid >= j->n_experts) break;
generate_one_expert(j, xid);
pthread_mutex_lock(&j->lock);
int done = ++j->done;
if (done % 32 == 0 || done == j->n_experts) {
fprintf(stderr, "generate_expert_tensor: layer %d %s %d/%d experts\n",
j->expert.layer, j->wid, done, j->n_experts);
}
pthread_mutex_unlock(&j->lock);
}
return NULL;
}
static byte_buf generate_expert(st_db *db, const char *gguf_name, const tensor_meta *tmpl,
ds4q_type target, int n_experts, int n_threads,
const imatrix_store *imatrix) {
expert_tensor e = parse_expert_tensor(gguf_name);
if (!e.is_expert) die("not an expert tensor");
if (!is_quantizable_target(target)) die("unsupported expert target type");
const char *wid = expert_part_name(e.part);
const int64_t ncols = tmpl->ne[0];
const int64_t nrows = tmpl->ne[1];
const size_t per_expert = (size_t)nrows * ds4q_row_size(target, ncols);
byte_buf out = { .size = per_expert * (size_t)n_experts, .data = xmalloc(per_expert * (size_t)n_experts) };
ds4q_quantize_init(target);
int worker_count = n_threads > 0 ? n_threads : 8;
if (worker_count < 1) worker_count = 1;
if (worker_count > n_experts) worker_count = n_experts;
fprintf(stderr, "generate_expert_tensor: layer %d %s using %d worker%s\n",
e.layer, wid, worker_count, worker_count == 1 ? "" : "s");
expert_job job = {
.db = db, .gguf_name = gguf_name, .tmpl = tmpl, .target = target,
.n_experts = n_experts, .imatrix = imatrix, .expert = e, .wid = wid,
.ncols = ncols, .nrows = nrows, .per_expert = per_expert, .out = &out,
};
pthread_mutex_init(&job.lock, NULL);
pthread_t *threads = xcalloc((size_t)worker_count, sizeof(threads[0]));
for (int i = 1; i < worker_count; i++) pthread_create(&threads[i], NULL, expert_worker, &job);
expert_worker(&job);
for (int i = 1; i < worker_count; i++) pthread_join(threads[i], NULL);
pthread_mutex_destroy(&job.lock);
free(threads);
return out;
}
static byte_buf generate_tensor(st_db *db, const char *name, const tensor_meta *tmpl,
ds4q_type target, int n_experts, int n_threads,
const imatrix_store *imatrix) {
if (parse_expert_tensor(name).is_expert) {
return generate_expert(db, name, tmpl, target, n_experts, n_threads, imatrix);
}
return generate_regular(db, name, tmpl, target, imatrix);
}
/* =====
* Minimal GGUF reader/writer
*
* GGUF metadata is copied as raw KV records from the template. Tensor infos
* are rewritten with the new target types and offsets. This keeps the tool C
* only and independent from general-purpose GGUF libraries.
*/
typedef struct {
size_t start;
size_t end;
} byte_span;
typedef struct {
char *path;
uint32_t version;
uint64_t n_kv;
uint64_t n_tensors;
uint8_t *kv_raw;
size_t kv_raw_len;
size_t alignment;
int n_experts;
size_t data_offset;
tensor_meta *tensors;
hmap tensor_map;
} gguf_file;
typedef struct {
tensor_meta *tensors;
uint64_t n_tensors;
uint64_t n_kv_extra;
size_t meta_size;
size_t data_offset;
size_t tensor_bytes;
size_t alignment;
} output_context;
static size_t gguf_scalar_size(uint32_t type) {
switch (type) {
case GGUF_TYPE_UINT8:
case GGUF_TYPE_INT8:
case GGUF_TYPE_BOOL: return 1;
case GGUF_TYPE_UINT16:
case GGUF_TYPE_INT16: return 2;
case GGUF_TYPE_UINT32:
case GGUF_TYPE_INT32:
case GGUF_TYPE_FLOAT32: return 4;
case GGUF_TYPE_UINT64:
case GGUF_TYPE_INT64:
case GGUF_TYPE_FLOAT64: return 8;
default: return 0;
}
}
static char *read_gguf_string_fp(FILE *fp) {
uint64_t n = read_u64_le_fp(fp, "GGUF string length");
char *s = xmalloc((size_t)n + 1);
if (n && fread(s, 1, (size_t)n, fp) != (size_t)n) die("short GGUF string read");
s[n] = '\0';
return s;
}
static void skip_bytes_fp(FILE *fp, uint64_t n) {
if (fseeko(fp, (off_t)n, SEEK_CUR) != 0) die("GGUF seek failed");
}
static void skip_gguf_value_fp(FILE *fp, uint32_t type) {
if (type == GGUF_TYPE_STRING) {
uint64_t n = read_u64_le_fp(fp, "GGUF string length");
skip_bytes_fp(fp, n);
return;
}
if (type == GGUF_TYPE_ARRAY) {
uint32_t elem_type = read_u32_le_fp(fp, "GGUF array type");
uint64_t n = read_u64_le_fp(fp, "GGUF array count");
if (elem_type == GGUF_TYPE_STRING) {
for (uint64_t i = 0; i < n; i++) {
uint64_t len = read_u64_le_fp(fp, "GGUF array string length");
skip_bytes_fp(fp, len);
}
} else {
size_t sz = gguf_scalar_size(elem_type);
if (!sz) die("unsupported GGUF array type");
skip_bytes_fp(fp, n * sz);
}
return;
}
size_t sz = gguf_scalar_size(type);
if (!sz) die("unsupported GGUF value type");
skip_bytes_fp(fp, sz);
}
static size_t gguf_string_size(const char *s) {
return sizeof(uint64_t) + strlen(s);
}
static void write_u32(FILE *fp, uint32_t v) {
if (fwrite(&v, sizeof(v), 1, fp) != 1) die("write u32 failed");
}
static void write_u64(FILE *fp, uint64_t v) {
if (fwrite(&v, sizeof(v), 1, fp) != 1) die("write u64 failed");
}
static void write_gguf_string(FILE *fp, const char *s) {
uint64_t n = strlen(s);
write_u64(fp, n);
if (n && fwrite(s, 1, (size_t)n, fp) != (size_t)n) die("write string failed");
}
static bool is_imatrix_kv_key(const char *key) {
return str_starts(key, "quantize.imatrix.");
}
static size_t extra_imatrix_kv_size(const imatrix_store *im) {
if (!imatrix_enabled(im)) return 0;
size_t n = 0;
n += gguf_string_size(DS4_KV_QUANTIZE_IMATRIX_FILE) + 4 + gguf_string_size(im->file);
n += gguf_string_size(DS4_KV_QUANTIZE_IMATRIX_N_ENTRIES) + 4 + 8;
if (im->dataset) n += gguf_string_size(DS4_KV_QUANTIZE_IMATRIX_DATASET) + 4 + gguf_string_size(im->dataset);
if (im->chunks > 0) n += gguf_string_size(DS4_KV_QUANTIZE_IMATRIX_N_CHUNKS) + 4 + 8;
return n;
}
static uint64_t extra_imatrix_kv_count(const imatrix_store *im) {
if (!imatrix_enabled(im)) return 0;
return 2 + (im->dataset ? 1 : 0) + (im->chunks > 0 ? 1 : 0);
}
static void write_imatrix_kvs(FILE *fp, const imatrix_store *im) {
if (!imatrix_enabled(im)) return;
write_gguf_string(fp, DS4_KV_QUANTIZE_IMATRIX_FILE);
write_u32(fp, GGUF_TYPE_STRING);
write_gguf_string(fp, im->file);
write_gguf_string(fp, DS4_KV_QUANTIZE_IMATRIX_N_ENTRIES);
write_u32(fp, GGUF_TYPE_UINT64);
write_u64(fp, (uint64_t)im->n_entries);
if (im->dataset) {
write_gguf_string(fp, DS4_KV_QUANTIZE_IMATRIX_DATASET);
write_u32(fp, GGUF_TYPE_STRING);
write_gguf_string(fp, im->dataset);
}
if (im->chunks > 0) {
write_gguf_string(fp, DS4_KV_QUANTIZE_IMATRIX_N_CHUNKS);
write_u32(fp, GGUF_TYPE_UINT64);
write_u64(fp, (uint64_t)im->chunks);
}
}
static gguf_file load_gguf_metadata(const char *path) {
gguf_file g = {0};
g.path = xstrdup(path);
FILE *fp = fopen(path, "rb");
if (!fp) die_errno("open GGUF", path);
char magic[4];
if (fread(magic, 1, sizeof(magic), fp) != sizeof(magic) || memcmp(magic, "GGUF", 4) != 0) {
die("bad GGUF template");
}
g.version = read_u32_le_fp(fp, "GGUF version");
g.n_tensors = read_u64_le_fp(fp, "GGUF tensor count");
g.n_kv = read_u64_le_fp(fp, "GGUF KV count");
g.alignment = DS4_GGUF_DEFAULT_ALIGNMENT;
byte_span *kv_keep = xcalloc((size_t)g.n_kv, sizeof(kv_keep[0]));
uint64_t n_kv_keep = 0;
off_t kv_start = ftello(fp);
if (kv_start < 0) die("GGUF ftell failed");
for (uint64_t i = 0; i < g.n_kv; i++) {
off_t rec_start = ftello(fp);
if (rec_start < 0 || rec_start < kv_start) die("GGUF ftell failed");
char *key = read_gguf_string_fp(fp);
uint32_t type = read_u32_le_fp(fp, "GGUF KV type");
if (strcmp(key, "general.alignment") == 0 && type == GGUF_TYPE_UINT32) {
uint32_t a = read_u32_le_fp(fp, "GGUF alignment");
if (a) g.alignment = a;
} else if (strcmp(key, "deepseek4.expert_count") == 0 && type == GGUF_TYPE_UINT32) {
uint32_t n = read_u32_le_fp(fp, "GGUF expert count");
if (n <= (uint32_t)INT_MAX) g.n_experts = (int)n;
} else if (strcmp(key, "deepseek4.expert_count") == 0 && type == GGUF_TYPE_UINT64) {
uint64_t n = read_u64_le_fp(fp, "GGUF expert count");
if (n <= (uint64_t)INT_MAX) g.n_experts = (int)n;
} else {
skip_gguf_value_fp(fp, type);
}
off_t rec_end = ftello(fp);
if (rec_end < 0 || rec_end < rec_start) die("GGUF ftell failed");
/*
* Template GGUFs may already carry imatrix provenance from a previous
* quantization. Drop those keys and write the current run's keys later,
* otherwise the output can contain duplicate GGUF metadata with stale
* and new values.
*/
if (!is_imatrix_kv_key(key)) {
kv_keep[n_kv_keep++] = (byte_span){
.start = (size_t)(rec_start - kv_start),
.end = (size_t)(rec_end - kv_start),
};
}
free(key);
}
off_t tensor_start = ftello(fp);
if (tensor_start < 0 || tensor_start < kv_start) die("GGUF ftell failed");
size_t kv_full_len = (size_t)(tensor_start - kv_start);
uint8_t *kv_full = xmalloc(kv_full_len);
if (fseeko(fp, kv_start, SEEK_SET) != 0) die("GGUF seek failed");
if (kv_full_len && fread(kv_full, 1, kv_full_len, fp) != kv_full_len) die("GGUF KV read failed");
for (uint64_t i = 0; i < n_kv_keep; i++) g.kv_raw_len += kv_keep[i].end - kv_keep[i].start;
g.kv_raw = xmalloc(g.kv_raw_len);
size_t kv_pos = 0;
for (uint64_t i = 0; i < n_kv_keep; i++) {
size_t n = kv_keep[i].end - kv_keep[i].start;
memcpy(g.kv_raw + kv_pos, kv_full + kv_keep[i].start, n);
kv_pos += n;
}
g.n_kv = n_kv_keep;
free(kv_full);
free(kv_keep);
if (fseeko(fp, tensor_start, SEEK_SET) != 0) die("GGUF seek failed");
g.tensors = xcalloc((size_t)g.n_tensors, sizeof(g.tensors[0]));
for (uint64_t i = 0; i < g.n_tensors; i++) {
tensor_meta *t = &g.tensors[i];
t->name = read_gguf_string_fp(fp);
t->n_dims = (int)read_u32_le_fp(fp, "GGUF tensor rank");
if (t->n_dims < 1 || t->n_dims > DS4Q_MAX_DIMS) die("bad GGUF tensor rank");
for (int j = 0; j < t->n_dims; j++) t->ne[j] = (int64_t)read_u64_le_fp(fp, "GGUF tensor dim");
t->type = (ds4q_type)read_u32_le_fp(fp, "GGUF tensor type");
t->old_offset = read_u64_le_fp(fp, "GGUF tensor offset");
t->size = tensor_nbytes(t->type, t->ne, t->n_dims);
}
off_t meta_end = ftello(fp);
if (meta_end < 0) die("GGUF ftell failed");
g.data_offset = ds4q_pad((size_t)meta_end, g.alignment);
char **keys = xmalloc((size_t)g.n_tensors * sizeof(keys[0]));
for (uint64_t i = 0; i < g.n_tensors; i++) keys[i] = g.tensors[i].name;
hmap_build(&g.tensor_map, keys, (int)g.n_tensors);
free(keys);
fclose(fp);
return g;
}
static byte_buf read_gguf_tensor_data(const gguf_file *g, const char *path, const char *name) {
int idx = hmap_get(&g->tensor_map, name);
if (idx < 0) {
fprintf(stderr, "error: tensor not found in GGUF: %s\n", name);
exit(1);
}
const tensor_meta *t = &g->tensors[idx];
byte_buf b = { .size = t->size, .data = xmalloc(t->size) };
FILE *fp = fopen(path, "rb");
if (!fp) die_errno("open GGUF", path);
if (fseeko(fp, (off_t)(g->data_offset + t->old_offset), SEEK_SET) != 0) die_errno("seek GGUF", path);
if (b.size && fread(b.data, 1, b.size, fp) != b.size) die_errno("read GGUF tensor", path);
fclose(fp);
return b;
}
static uint64_t fnv1a64_bytes(const uint8_t *data, size_t n) {
uint64_t h = 1469598103934665603ull;
for (size_t i = 0; i < n; i++) {
h ^= data[i];
h *= 1099511628211ull;
}
return h;
}
static output_context build_output_context(const gguf_file *tmpl, const quant_policy *policy, const imatrix_store *im) {
output_context out = {0};
out.n_tensors = tmpl->n_tensors;
out.n_kv_extra = extra_imatrix_kv_count(im);
out.alignment = tmpl->alignment;
out.tensors = xcalloc((size_t)out.n_tensors, sizeof(out.tensors[0]));
size_t tensor_info = 0;
size_t off = 0;
for (uint64_t i = 0; i < out.n_tensors; i++) {
const tensor_meta *src = &tmpl->tensors[i];
tensor_meta *dst = &out.tensors[i];
*dst = *src;
dst->name = src->name;
ds4q_type type = policy_type(policy, src->name, src);
if (type == DS4Q_TYPE_COUNT) type = src->type;
if (type != DS4Q_TYPE_I32 && !is_quantizable_target(type)) die("unsupported planned tensor type");
if (ds4q_can_quantize(type) && src->ne[0] % ds4q_block_size(type) != 0) die("ne[0] not divisible by block size");
dst->type = type;
dst->size = tensor_nbytes(type, src->ne, src->n_dims);
dst->new_offset = off;
off += ds4q_pad(dst->size, tmpl->alignment);
tensor_info += gguf_string_size(dst->name) + 4 + (size_t)dst->n_dims * 8 + 4 + 8;
}
out.tensor_bytes = off;
out.meta_size = 4 + 4 + 8 + 8 + tmpl->kv_raw_len + extra_imatrix_kv_size(im) + tensor_info;
out.data_offset = ds4q_pad(out.meta_size, tmpl->alignment);
return out;
}
static void write_padding(FILE *fp, size_t n) {
static const uint8_t zeros[4096] = {0};
while (n) {
size_t chunk = n < sizeof(zeros) ? n : sizeof(zeros);
if (fwrite(zeros, 1, chunk, fp) != chunk) die("write padding failed");
n -= chunk;
}
}
static void write_full_gguf(st_db *db, const gguf_file *tmpl, const output_context *out_ctx,
const char *out_path, int n_experts, int n_threads,
const imatrix_store *imatrix) {
FILE *fp = fopen(out_path, "wb");
if (!fp) die_errno("open output", out_path);
if (fwrite("GGUF", 1, 4, fp) != 4) die("write GGUF magic failed");
write_u32(fp, tmpl->version);
write_u64(fp, tmpl->n_tensors);
write_u64(fp, tmpl->n_kv + out_ctx->n_kv_extra);
if (fwrite(tmpl->kv_raw, 1, tmpl->kv_raw_len, fp) != tmpl->kv_raw_len) die("write GGUF KV failed");
write_imatrix_kvs(fp, imatrix);
for (uint64_t i = 0; i < out_ctx->n_tensors; i++) {
const tensor_meta *t = &out_ctx->tensors[i];
write_gguf_string(fp, t->name);
write_u32(fp, (uint32_t)t->n_dims);
for (int j = 0; j < t->n_dims; j++) write_u64(fp, (uint64_t)t->ne[j]);
write_u32(fp, (uint32_t)t->type);
write_u64(fp, t->new_offset);
}
long pos = ftell(fp);
if (pos < 0) die("ftell failed");
if ((size_t)pos > out_ctx->data_offset) die("GGUF metadata larger than planned");
write_padding(fp, out_ctx->data_offset - (size_t)pos);
for (uint64_t i = 0; i < out_ctx->n_tensors; i++) {
const tensor_meta *src = &tmpl->tensors[i];
const tensor_meta *dst = &out_ctx->tensors[i];
fprintf(stderr, "[%4" PRIu64 "/%4" PRIu64 "] %s -> %s\n", i + 1, out_ctx->n_tensors, dst->name, ds4q_type_name(dst->type));
byte_buf data = generate_tensor(db, dst->name, src, dst->type, n_experts, n_threads, imatrix);
size_t expected = dst->size;
if (data.size != expected) {
fprintf(stderr, "error: generated size mismatch for %s: got %zu expected %zu\n", dst->name, data.size, expected);
exit(1);
}
if (fwrite(data.data, 1, data.size, fp) != data.size) die_errno("write tensor", out_path);
size_t padded = ds4q_pad(data.size, out_ctx->alignment);
write_padding(fp, padded - data.size);
fprintf(stderr, " generated %.2f MiB\n", (double)data.size / 1048576.0);
free(data.data);
}
fclose(fp);
}
static void print_plan(const gguf_file *tmpl, const output_context *out_ctx) {
size_t tensor_bytes = 0;
size_t changed = 0;
for (uint64_t i = 0; i < out_ctx->n_tensors; i++) {
tensor_bytes += out_ctx->tensors[i].size;
const tensor_meta *src = &tmpl->tensors[i];
const tensor_meta *dst = &out_ctx->tensors[i];
if (src->type != dst->type) {
changed++;
printf("type_change: %s %s -> %s\n", dst->name, ds4q_type_name(src->type), ds4q_type_name(dst->type));
}
}
printf("n_tensors: %" PRIu64 "\n", out_ctx->n_tensors);
printf("meta_bytes: %zu\n", out_ctx->data_offset);
printf("tensor_bytes_unpadded: %zu\n", tensor_bytes);
printf("approx_file_bytes: %zu\n", out_ctx->data_offset + out_ctx->tensor_bytes);
printf("type_changes: %zu\n", changed);
}
/* =====
* CLI
*/
typedef struct {
char *hf_dir;
char *template_gguf;
char *out_gguf;
char *compare_gguf;
char *compare_tensor;
char *imatrix_file;
quant_policy policy;
int n_experts;
int n_threads;
bool dry_run;
bool overwrite;
bool imatrix_strict;
} params;
static void usage(const char *argv0) {
printf("usage: %s --hf DIR --template MODEL.gguf --out OUT.gguf [options]\n", argv0);
printf("\nDeepSeek V4 Flash/Pro safetensors -> GGUF quantizer in plain C.\n\n");
printf("options:\n");
printf(" --hf DIR Hugging Face model directory with model.safetensors.index.json\n");
printf(" --template FILE existing DS4 GGUF used for metadata, tensor order, shapes\n");
printf(" --out FILE output GGUF path\n");
printf(" --compare-gguf FILE reference GGUF for --compare-tensor, default template\n");
printf(" --compare-tensor NAME regenerate one tensor, byte-compare, and exit\n");
printf(" --overwrite replace --out if it already exists\n");
printf(" --dry-run print output plan without reading HF tensor data\n");
printf(" --imatrix FILE legacy .dat imatrix from ds4 --imatrix-out\n");
printf(" --imatrix-strict fail if a quantized tensor has no matching imatrix vector\n");
printf(" --experts TYPE set routed w1/w2/w3 expert tensors to TYPE\n");
printf(" --routed-w1 TYPE routed gate expert tensor type\n");
printf(" --routed-w2 TYPE routed down expert tensor type\n");
printf(" --routed-w3 TYPE routed up expert tensor type\n");
printf(" --attention-proj TYPE attn_q/kv/output projection type\n");
printf(" --attention TYPE other 2D attention/indexer/compressor type\n");
printf(" --shared TYPE shared expert tensor type\n");
printf(" --embedding TYPE token embedding type\n");
printf(" --output TYPE output.* tensor type\n");
printf(" --dense TYPE remaining 2D+ non-routed tensor type\n");
printf(" --tensor-type PFX=TYPE exact tensor-name or prefix override; may repeat\n");
printf(" --n-experts N routed expert count, default template metadata\n");
printf(" --threads N expert worker count, default 8\n");
printf("\nTYPE examples: f16, f32, bf16, q8_0, q4_k, q2_k, iq2_xxs\n");
}
static char *need_value(int argc, char **argv, int *i, const char *arg) {
if (++*i >= argc) {
fprintf(stderr, "error: missing value for %s\n", arg);
exit(1);
}
return argv[*i];
}
static bool file_exists(const char *path) {
FILE *fp = fopen(path, "rb");
if (!fp) return false;
fclose(fp);
return true;
}
static params parse_args(int argc, char **argv) {
params p = {0};
p.policy.routed_w1 = p.policy.routed_w2 = p.policy.routed_w3 = DS4Q_TYPE_COUNT;
p.policy.attention_proj = p.policy.attention = p.policy.shared = DS4Q_TYPE_COUNT;
p.policy.embedding = p.policy.output = p.policy.dense = DS4Q_TYPE_COUNT;
p.n_experts = 0;
p.n_threads = 8;
for (int i = 1; i < argc; i++) {
const char *arg = argv[i];
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
usage(argv[0]);
exit(0);
} else if (strcmp(arg, "--hf") == 0) {
p.hf_dir = need_value(argc, argv, &i, arg);
} else if (strcmp(arg, "--template") == 0) {
p.template_gguf = need_value(argc, argv, &i, arg);
} else if (strcmp(arg, "--out") == 0) {
p.out_gguf = need_value(argc, argv, &i, arg);
} else if (strcmp(arg, "--compare-gguf") == 0) {
p.compare_gguf = need_value(argc, argv, &i, arg);
} else if (strcmp(arg, "--compare-tensor") == 0) {
p.compare_tensor = need_value(argc, argv, &i, arg);
} else if (strcmp(arg, "--overwrite") == 0) {
p.overwrite = true;
} else if (strcmp(arg, "--dry-run") == 0) {
p.dry_run = true;
} else if (strcmp(arg, "--imatrix") == 0) {
p.imatrix_file = need_value(argc, argv, &i, arg);
} else if (strcmp(arg, "--imatrix-strict") == 0) {
p.imatrix_strict = true;
} else if (strcmp(arg, "--experts") == 0 || strcmp(arg, "--routed") == 0) {
ds4q_type t = parse_type(need_value(argc, argv, &i, arg));
p.policy.routed_w1 = p.policy.routed_w2 = p.policy.routed_w3 = t;
} else if (strcmp(arg, "--routed-w1") == 0 || strcmp(arg, "--routed-gate") == 0) {
p.policy.routed_w1 = parse_type(need_value(argc, argv, &i, arg));
} else if (strcmp(arg, "--routed-w2") == 0 || strcmp(arg, "--routed-down") == 0) {
p.policy.routed_w2 = parse_type(need_value(argc, argv, &i, arg));
} else if (strcmp(arg, "--routed-w3") == 0 || strcmp(arg, "--routed-up") == 0) {
p.policy.routed_w3 = parse_type(need_value(argc, argv, &i, arg));
} else if (strcmp(arg, "--attention-proj") == 0 || strcmp(arg, "--attn-proj") == 0) {
p.policy.attention_proj = parse_type(need_value(argc, argv, &i, arg));
} else if (strcmp(arg, "--attention") == 0) {
p.policy.attention = parse_type(need_value(argc, argv, &i, arg));
} else if (strcmp(arg, "--shared") == 0) {
p.policy.shared = parse_type(need_value(argc, argv, &i, arg));
} else if (strcmp(arg, "--embedding") == 0) {
p.policy.embedding = parse_type(need_value(argc, argv, &i, arg));
} else if (strcmp(arg, "--output") == 0) {
p.policy.output = parse_type(need_value(argc, argv, &i, arg));
} else if (strcmp(arg, "--dense") == 0) {
p.policy.dense = parse_type(need_value(argc, argv, &i, arg));
} else if (strcmp(arg, "--tensor-type") == 0) {
char *spec = need_value(argc, argv, &i, arg);
char *eq = strchr(spec, '=');
if (!eq || eq == spec || !eq[1]) die("bad --tensor-type, expected NAME=TYPE");
*eq = '\0';
p.policy.overrides = xrealloc(p.policy.overrides, (size_t)(p.policy.n_overrides + 1) * sizeof(p.policy.overrides[0]));
p.policy.overrides[p.policy.n_overrides++] = (type_override){ xstrdup(spec), parse_type(eq + 1) };
} else if (strcmp(arg, "--n-experts") == 0) {
p.n_experts = atoi(need_value(argc, argv, &i, arg));
} else if (strcmp(arg, "--threads") == 0) {
p.n_threads = atoi(need_value(argc, argv, &i, arg));
} else {
fprintf(stderr, "error: unknown argument: %s\n", arg);
exit(1);
}
}
if (!p.hf_dir) die("--hf is required");
if (!p.template_gguf) die("--template is required");
if (!p.dry_run && !p.compare_tensor && !p.out_gguf) die("--out is required unless --dry-run or --compare-tensor is used");
if (p.compare_tensor && !p.compare_gguf) p.compare_gguf = p.template_gguf;
if (p.out_gguf && file_exists(p.out_gguf) && !p.overwrite) die("output exists; use --overwrite");
return p;
}
static void free_gguf_file(gguf_file *g) {
free(g->path);
free(g->kv_raw);
for (uint64_t i = 0; i < g->n_tensors; i++) free(g->tensors[i].name);
free(g->tensors);
hmap_free(&g->tensor_map);
memset(g, 0, sizeof(*g));
}
static void compare_one_tensor(st_db *db, const gguf_file *tmpl, const output_context *out_ctx,
const params *p, const imatrix_store *imatrix) {
int idx = hmap_get(&tmpl->tensor_map, p->compare_tensor);
if (idx < 0) {
fprintf(stderr, "error: tensor not found in template: %s\n", p->compare_tensor);
exit(1);
}
fprintf(stderr, "regenerating %s as %s\n",
p->compare_tensor, ds4q_type_name(out_ctx->tensors[idx].type));
byte_buf generated = generate_tensor(db, p->compare_tensor, &tmpl->tensors[idx],
out_ctx->tensors[idx].type, p->n_experts, p->n_threads, imatrix);
gguf_file ref = load_gguf_metadata(p->compare_gguf);
byte_buf reference = read_gguf_tensor_data(&ref, p->compare_gguf, p->compare_tensor);
printf("tensor: %s\n", p->compare_tensor);
printf("type: %s\n", ds4q_type_name(out_ctx->tensors[idx].type));
printf("generated_bytes: %zu\n", generated.size);
printf("reference_bytes: %zu\n", reference.size);
printf("generated_fnv1a64: %016" PRIx64 "\n", fnv1a64_bytes(generated.data, generated.size));
printf("reference_fnv1a64: %016" PRIx64 "\n", fnv1a64_bytes(reference.data, reference.size));
size_t mismatches = 0;
size_t first = SIZE_MAX;
const size_t n = generated.size < reference.size ? generated.size : reference.size;
for (size_t i = 0; i < n; i++) {
if (generated.data[i] != reference.data[i]) {
if (first == SIZE_MAX) first = i;
mismatches++;
}
}
if (generated.size != reference.size) {
if (first == SIZE_MAX) first = n;
mismatches += generated.size > reference.size ? generated.size - reference.size : reference.size - generated.size;
}
if (!mismatches) {
printf("byte_compare: OK\n");
} else {
printf("byte_compare: FAIL mismatches=%zu first=%zu\n", mismatches, first);
}
free(generated.data);
free(reference.data);
free_gguf_file(&ref);
}
int main(int argc, char **argv) {
params p = parse_args(argc, argv);
imatrix_store imatrix = {0};
if (p.imatrix_file) imatrix_load(&imatrix, p.imatrix_file, p.imatrix_strict);
gguf_file tmpl = load_gguf_metadata(p.template_gguf);
if (p.n_experts <= 0) {
if (tmpl.n_experts > 0) {
p.n_experts = tmpl.n_experts;
fprintf(stderr, "using %d routed experts from template metadata\n", p.n_experts);
} else {
p.n_experts = 256;
fprintf(stderr, "warning: template has no deepseek4.expert_count; using Flash default %d routed experts\n", p.n_experts);
}
} else {
fprintf(stderr, "using %d routed experts from --n-experts\n", p.n_experts);
}
output_context out_ctx = build_output_context(&tmpl, &p.policy, &imatrix);
print_plan(&tmpl, &out_ctx);
if (p.dry_run) return 0;
st_db db;
db_open(&db, p.hf_dir);
if (p.compare_tensor) {
compare_one_tensor(&db, &tmpl, &out_ctx, &p, &imatrix);
db_close(&db);
imatrix_free(&imatrix);
free_gguf_file(&tmpl);
free(out_ctx.tensors);
return 0;
}
write_full_gguf(&db, &tmpl, &out_ctx, p.out_gguf, p.n_experts, p.n_threads, &imatrix);
fprintf(stderr, "wrote %s\n", p.out_gguf);
db_close(&db);
imatrix_free(&imatrix);
free_gguf_file(&tmpl);
free(out_ctx.tensors);
for (int i = 0; i < p.policy.n_overrides; i++) free(p.policy.overrides[i].prefix);
free(p.policy.overrides);
return 0;
}