nx_gguf_load_f32.nx source
↩ module page · 110 lines · 3645 B
1// nx_gguf_load_f32.nx -- load a GGUF tensor and dequantize to f32 bits.
2//
3// Composes nx_gguf_find_tensor + nx_gguf_tensor_at + the source-type
4// specific dequant primitives:
5// F32 -> read 4 bytes per value, store as i64-extended raw bits
6// F16 -> nx_f16_to_f32 per value (composes nx_f32_cvt)
7// Q4_K -> nx_q4k_to_f32 (composes nx_q4k_to_f32 brick)
8//
9// Returns a freshly-allocated *i64 buffer holding n_values f32-raw-bit
10// values (one per logical tensor element). Caller owns the buffer.
11//
12// This is the bridge between the L4.5 quant-aware GGUF loader and the
13// L8 f32-only forward-pass substrate. The new NxF32LlamaModel
14// consumes *i64 buffers of f32 raw bits; this function produces them.
15//
16// genealogy_id: standard_gguf_tensor_load_and_dequant
17// lineage_id: substrate_gguf_load_f32_v1
18
19import "nx_syscalls.nx"
20import "nx_tier.nx"
21import "nx_le.nx"
22import "nx_gguf.nx"
23import "nx_gguf_load.nx"
24import "nx_f32_cvt.nx"
25import "nx_q4k_to_f32.nx"
26import "nx_q5_0_to_f32.nx"
27import "nx_q6_k_to_f32.nx"
28import "nx_q8_0_to_f32.nx"
29
30const NX_GLF_OK: nx_int = 0
31const NX_GLF_ERR_NOT_FOUND:nx_int = 1
32const NX_GLF_ERR_BAD_TYPE: nx_int = 2
33const NX_GLF_ERR_BAD_SHAPE:nx_int = 3
34const NX_GLF_ERR_OOM: nx_int = 4
35const NX_GLF_N_VERDICTS: nx_int = 5
36
37func nx_glf_verdict_is_valid(v: nx_int) -> nx_int {
38 if v < 0 { return 0 }
39 if v >= NX_GLF_N_VERDICTS { return 0 }
40 return 1
41}
42
43// Returns a *i64 buffer (n_values entries of raw f32 bits).
44// Returns 0 on failure; verdict written to out_err.
45// n_values is written to n_values_out.
46
47func nx_gguf_load_tensor_to_f32(buf: *u8, hdr: *NxGgufHeader,
48 name: *u8, name_len: nx_int,
49 n_values_out: *i64,
50 out_err: *i64) -> *i64 {
51 let idx: nx_int = nx_gguf_find_tensor(hdr, name, name_len)
52 if idx < 0 {
53 out_err[0] = NX_GLF_ERR_NOT_FOUND
54 return 0 as *i64
55 }
56 let ti: *NxGgufTensorInfo = nx_gguf_tensor_at(hdr, idx)
57 let nv: i64 = nx_gguf_tensor_n_values(ti)
58 if nv <= 0 {
59 out_err[0] = NX_GLF_ERR_BAD_SHAPE
60 return 0 as *i64
61 }
62 n_values_out[0] = nv
63
64 let storage: *i64 = sys_mmap(nv * 8) as *i64
65 let data_off: i64 = hdr.data_off + ti.offset
66
67 if ti.ggml_type == NX_GGML_TYPE_F32 {
68 // Source is 4 bytes per value, native little-endian IEEE 754 binary32.
69 // Just read raw bits and store as i64-extended.
70 var i: i64 = 0
71 while i < nv {
72 storage[i] = nx_le_read_u32(buf, data_off + i * 4)
73 i = i + 1
74 }
75 out_err[0] = NX_GLF_OK
76 return storage
77 }
78 if ti.ggml_type == NX_GGML_TYPE_F16 {
79 var i2: i64 = 0
80 while i2 < nv {
81 let raw_f16: i64 = nx_le_read_u16(buf, data_off + i2 * 2)
82 storage[i2] = nx_f16_to_f32(raw_f16)
83 i2 = i2 + 1
84 }
85 out_err[0] = NX_GLF_OK
86 return storage
87 }
88 if ti.ggml_type == NX_GGML_TYPE_Q4_K {
89 nx_q4k_to_f32(buf, data_off, nv, storage)
90 out_err[0] = NX_GLF_OK
91 return storage
92 }
93 if ti.ggml_type == NX_GGML_TYPE_Q5_0 {
94 nx_q5_0_to_f32(buf, data_off, nv, storage)
95 out_err[0] = NX_GLF_OK
96 return storage
97 }
98 if ti.ggml_type == NX_GGML_TYPE_Q6_K {
99 nx_q6_k_to_f32(buf, data_off, nv, storage)
100 out_err[0] = NX_GLF_OK
101 return storage
102 }
103 if ti.ggml_type == NX_GGML_TYPE_Q8_0 {
104 nx_q8_0_to_f32(buf, data_off, nv, storage)
105 out_err[0] = NX_GLF_OK
106 return storage
107 }
108 out_err[0] = NX_GLF_ERR_BAD_TYPE
109 return 0 as *i64
110}