#![allow(clippy::identity_op)]
#![allow(clippy::explicit_counter_loop)]
#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone, Debug)]
#[repr(C)]
pub struct BlockF16 {
pub data: u16,
}
impl BlockF16 {
pub fn dequantize(self) -> f32 {
decode_f16(self.data)
}
}
#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone, Debug)]
#[repr(C)]
pub struct BlockQ8_0 {
pub scale: u16, pub data: [i8; 32],
}
impl BlockQ8_0 {
pub const ELEMENTS_PER_BLOCK: usize = 32;
pub fn dequantize(self) -> [f32; 32] {
let scale = decode_f16(self.scale);
self.data.map(|v| v as f32 * scale)
}
}
#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone, Debug)]
#[repr(C)]
pub struct BlockQ4_0 {
pub d: u16, pub qs: [u8; 32 / 2],
}
impl BlockQ4_0 {
pub const ELEMENTS_PER_BLOCK: usize = 32;
pub fn dequantize(self) -> [f32; 32] {
let mut result = [0.0; 32];
let d = decode_f16(self.d);
for j in 0..Self::ELEMENTS_PER_BLOCK / 2 {
let x0 = (self.qs[j] & 0x0F) as i32 - 8;
let x1 = (self.qs[j] >> 4) as i32 - 8;
result[j] = x0 as f32 * d;
result[j + Self::ELEMENTS_PER_BLOCK / 2] = x1 as f32 * d;
}
result
}
}
#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone, Debug)]
#[repr(C)]
pub struct BlockQ4_1 {
pub d: u16, pub m: u16,
pub qs: [u8; 32 / 2],
}
impl BlockQ4_1 {
pub const ELEMENTS_PER_BLOCK: usize = 32;
pub fn dequantize(self) -> [f32; 32] {
let mut result = [0.0; 32];
let d = decode_f16(self.d);
let m = decode_f16(self.m);
for j in 0..Self::ELEMENTS_PER_BLOCK / 2 {
let x0 = self.qs[j] & 0x0F;
let x1 = self.qs[j] >> 4;
result[j] = x0 as f32 * d + m;
result[j + Self::ELEMENTS_PER_BLOCK / 2] = x1 as f32 * d + m;
}
result
}
}
#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone, Debug)]
#[repr(C)]
pub struct BlockQ5_0 {
pub d: u16, pub qh: [u8; 4],
pub qs: [u8; 32 / 2],
}
impl BlockQ5_0 {
pub const ELEMENTS_PER_BLOCK: usize = 32;
pub fn dequantize(self) -> [f32; 32] {
let mut result = [0.0; 32];
let d = decode_f16(self.d);
let qh: u32 = bytemuck::cast(self.qh);
for j in 0..Self::ELEMENTS_PER_BLOCK / 2 {
let xh_0 = ((qh >> j) << 4) & 0x10;
let xh_1 = (qh >> (j + 12)) & 0x10;
let x0 = ((self.qs[j] as u32 & 0x0F) | xh_0) as i32 - 16;
let x1 = ((self.qs[j] as u32 >> 4) | xh_1) as i32 - 16;
result[j] = x0 as f32 * d;
result[j + Self::ELEMENTS_PER_BLOCK / 2] = x1 as f32 * d;
}
result
}
}
#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone, Debug)]
#[repr(C)]
pub struct BlockQ5_1 {
pub d: u16, pub m: u16, pub qh: [u8; 4], pub qs: [u8; 32 / 2], }
impl BlockQ5_1 {
pub const ELEMENTS_PER_BLOCK: usize = 32;
pub fn dequantize(self) -> [f32; 32] {
let mut result = [0.0; 32];
let d = decode_f16(self.d);
let m = decode_f16(self.m);
let qh: u32 = bytemuck::cast(self.qh);
for j in 0..Self::ELEMENTS_PER_BLOCK / 2 {
let xh_0 = ((qh >> j) << 4) & 0x10;
let xh_1 = (qh >> (j + 12)) & 0x10;
let x0 = (self.qs[j] as u32 & 0x0F) | xh_0;
let x1 = (self.qs[j] as u32 >> 4) | xh_1;
result[j] = x0 as f32 * d + m;
result[j + Self::ELEMENTS_PER_BLOCK / 2] = x1 as f32 * d + m;
}
result
}
}
const QK_K: usize = 256;
const K_SCALE_SIZE: usize = 12;
#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone, Debug)]
#[repr(C)]
pub struct BlockQ8_K {
pub d: f32, pub qs: [i8; QK_K], pub bsums: [i16; QK_K / 16], }
impl BlockQ8_K {
pub const ELEMENTS_PER_BLOCK: usize = QK_K;
pub fn dequantize(self) -> [f32; QK_K] {
let mut result = [0.0; QK_K];
for j in 0..QK_K {
result[j] = self.d * self.qs[j] as f32;
}
result
}
}
#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone, Debug)]
#[repr(C)]
pub struct BlockQ6_K {
pub ql: [u8; QK_K / 2], pub qh: [u8; QK_K / 4], pub scales: [i8; QK_K / 16], pub d: u16, }
impl BlockQ6_K {
pub const ELEMENTS_PER_BLOCK: usize = QK_K;
pub fn dequantize(self) -> [f32; QK_K] {
let mut result = [0.0; QK_K];
let d = decode_f16(self.d);
let mut i = 0;
for _ in (0..QK_K).step_by(128) {
for l in 0..32 {
let is = l / 16;
let q1 = ((self.ql[i * 64 + l + 0] & 0xF) | (((self.qh[i * 32 + l] >> 0) & 3) << 4))
as i8
- 32;
let q2 = ((self.ql[i * 64 + l + 32] & 0xF)
| (((self.qh[i * 32 + l] >> 2) & 3) << 4)) as i8
- 32;
let q3 = ((self.ql[i * 64 + l + 0] >> 4) | (((self.qh[i * 32 + l] >> 4) & 3) << 4))
as i8
- 32;
let q4 = ((self.ql[i * 64 + l + 32] >> 4) | (((self.qh[i * 32 + l] >> 6) & 3) << 4))
as i8
- 32;
result[i * 128 + l + 0] = d * self.scales[i * 8 + is + 0] as f32 * q1 as f32;
result[i * 128 + l + 32] = d * self.scales[i * 8 + is + 2] as f32 * q2 as f32;
result[i * 128 + l + 64] = d * self.scales[i * 8 + is + 4] as f32 * q3 as f32;
result[i * 128 + l + 96] = d * self.scales[i * 8 + is + 6] as f32 * q4 as f32;
}
i += 1;
}
result
}
}
#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone, Debug)]
#[repr(C)]
pub struct BlockQ5_K {
pub d: u16, pub dmin: u16, pub scales: [u8; K_SCALE_SIZE], pub qh: [u8; QK_K / 8], pub qs: [u8; QK_K / 2], }
impl BlockQ5_K {
pub const ELEMENTS_PER_BLOCK: usize = QK_K;
pub fn dequantize(self) -> [f32; QK_K] {
let mut result = [0.0; QK_K];
let mut iq = 0;
let mut is = 0;
let d = decode_f16(self.d);
let min = decode_f16(self.dmin);
let mut sc = 0;
let mut m = 0;
let mut u1 = 1;
let mut u2 = 2;
for j in (0..QK_K).step_by(64) {
get_scale_min_k4(is, &self.scales, &mut sc, &mut m);
let d1 = d * sc as f32;
let m1 = min * m as f32;
get_scale_min_k4(is + 1, &self.scales, &mut sc, &mut m);
let d2 = d * sc as f32;
let m2 = min * m as f32;
for l in 0..32 {
result[j + l] = d1
* ((self.qs[iq + l] & 0xF) + (if self.qh[l] & u1 != 0 { 16 } else { 0 }))
as f32
- m1;
}
for l in 0..32 {
result[j + l + 32] = d2
* ((self.qs[iq + l] >> 4) + (if self.qh[l] & u2 != 0 { 16 } else { 0 })) as f32
- m2;
}
iq += 32;
is += 2;
u1 <<= 2;
u2 <<= 2;
}
result
}
}
#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone, Debug)]
#[repr(C)]
pub struct BlockQ4_K {
pub d: u16, pub dmin: u16, pub scales: [u8; K_SCALE_SIZE], pub qs: [u8; QK_K / 2], }
impl BlockQ4_K {
pub const ELEMENTS_PER_BLOCK: usize = QK_K;
pub fn dequantize(self) -> [f32; QK_K] {
let mut result = [0.0; QK_K];
let d = decode_f16(self.d);
let min = decode_f16(self.dmin);
let mut is = 0;
let mut sc = 0u8;
let mut m = 0u8;
let mut iq = 0;
for j in (0..QK_K).step_by(64) {
get_scale_min_k4(is, &self.scales, &mut sc, &mut m);
let d1 = d * sc as f32;
let m1 = min * m as f32;
get_scale_min_k4(is + 1, &self.scales, &mut sc, &mut m);
let d2 = d * sc as f32;
let m2 = min * m as f32;
for l in 0..32 {
result[j + l] = d1 * (self.qs[iq + l] & 0xF) as f32 - m1;
}
for l in 0..32 {
result[j + l + 32] = d2 * (self.qs[iq + l] >> 4) as f32 - m2;
}
iq += 32;
is += 2;
}
result
}
}
fn get_scale_min_k4(j: usize, q: &[u8], d: &mut u8, m: &mut u8) {
if j < 4 {
*d = q[j] & 63;
*m = q[j + 4] & 63;
} else {
*d = (q[j + 4] & 0xf) | ((q[j - 4] >> 6) << 4);
*m = (q[j + 4] >> 4) | ((q[j] >> 6) << 4);
}
}
pub fn decode_f16(half: u16) -> f32 {
let exp: u16 = half >> 10 & 0x1f;
let mant: u16 = half & 0x3ff;
let val: f32 = if exp == 0 {
(mant as f32) * (2.0f32).powi(-24)
} else if exp != 31 {
(mant as f32 + 1024f32) * (2.0f32).powi(exp as i32 - 25)
} else if mant == 0 {
f32::INFINITY
} else {
f32::NAN
};
if half & 0x8000 != 0 {
-val
} else {
val
}
}