Coverage Report

Created: 2026-01-25 15:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/noah/src/trueno/src/backends/q4k/dequant.rs
Line
Count
Source
1
//! Q4_K dequantization to F32.
2
//!
3
//! Provides full dequantization of Q4_K compressed data for golden test comparison.
4
5
use super::{parse_q4k_header, SUPER_BLOCK_BYTES, SUPER_BLOCK_SIZE};
6
7
/// Dequantize Q4_K data to F32 (for golden test comparison)
8
///
9
/// This function fully dequantizes Q4K data to F32, matching the
10
/// `dequantize_q4_k_to_f32` in aprender/src/format/converter.rs.
11
0
pub fn dequantize_q4k_to_f32(data: &[u8], num_elements: usize) -> Vec<f32> {
12
0
    let num_blocks = (num_elements + SUPER_BLOCK_SIZE - 1) / SUPER_BLOCK_SIZE;
13
0
    let mut result = vec![0.0f32; num_blocks * SUPER_BLOCK_SIZE];
14
15
0
    for sb_idx in 0..num_blocks {
16
0
        let sb_start = sb_idx * SUPER_BLOCK_BYTES;
17
0
        let out_start = sb_idx * SUPER_BLOCK_SIZE;
18
19
0
        if sb_start + SUPER_BLOCK_BYTES > data.len() {
20
0
            break;
21
0
        }
22
23
0
        let sb_data = &data[sb_start..sb_start + SUPER_BLOCK_BYTES];
24
0
        let (d, dmin, scales, mins) = parse_q4k_header(sb_data);
25
0
        let qs = &sb_data[16..144];
26
27
0
        let mut ys_index = out_start;
28
29
0
        for chunk in 0..4 {
30
0
            let q = &qs[chunk * 32..(chunk + 1) * 32];
31
32
0
            let scale_idx_low = chunk * 2;
33
0
            let scale_idx_high = chunk * 2 + 1;
34
35
0
            let d1 = d * f32::from(scales[scale_idx_low]);
36
0
            let dm1 = dmin * f32::from(mins[scale_idx_low]);
37
0
            let d2 = d * f32::from(scales[scale_idx_high]);
38
0
            let dm2 = dmin * f32::from(mins[scale_idx_high]);
39
40
            // First pass: 32 low nibbles
41
0
            for &byte in q {
42
0
                result[ys_index] = d1 * (byte & 0xF) as f32 - dm1;
43
0
                ys_index += 1;
44
0
            }
45
46
            // Second pass: 32 high nibbles
47
0
            for &byte in q {
48
0
                result[ys_index] = d2 * (byte >> 4) as f32 - dm2;
49
0
                ys_index += 1;
50
0
            }
51
        }
52
    }
53
54
0
    result.truncate(num_elements);
55
0
    result
56
0
}