#![allow(unsafe_code)]
use std::os::raw::c_int;
extern "C" {
fn fq_encode_vector_block(
vec: *const f32,
dim: usize,
codebook: *const f32,
codebook_size: usize,
block_dim: usize,
out_indices: *mut u16,
) -> usize;
fn fq_decode_vector_block(
indices: *const u16,
block_count: usize,
codebook: *const f32,
codebook_size: usize,
block_dim: usize,
out_vec: *mut f32,
);
fn fq_compressed_attention_logits(
key_indices: *const u16,
n_keys: usize,
key_norms: *const f32,
gram_table: *const f32,
gram_size: usize,
query_indices: *const u16,
query_count: usize,
query_norm: f32,
scale: f32,
out_logits: *mut f32,
);
fn fq_softmax(logits: *mut f32, n: usize) -> c_int;
}
pub fn c_encode_vector_block(
vec: &[f32],
codebook: &[f32],
codebook_size: usize,
block_dim: usize,
) -> Vec<u16> {
let dim = vec.len();
let block_count = dim / block_dim;
let mut indices = vec![0u16; block_count];
unsafe {
fq_encode_vector_block(
vec.as_ptr(),
dim,
codebook.as_ptr(),
codebook_size,
block_dim,
indices.as_mut_ptr(),
);
}
indices
}
pub fn c_decode_vector_block(
indices: &[u16],
codebook: &[f32],
codebook_size: usize,
block_dim: usize,
) -> Vec<f32> {
let block_count = indices.len();
let mut out = vec![0.0f32; block_count * block_dim];
unsafe {
fq_decode_vector_block(
indices.as_ptr(),
block_count,
codebook.as_ptr(),
codebook_size,
block_dim,
out.as_mut_ptr(),
);
}
out
}
#[allow(clippy::too_many_arguments)]
pub fn c_compressed_attention_logits(
key_indices: &[u16],
n_keys: usize,
key_norms: &[f32],
gram_table: &[f32],
gram_size: usize,
query_indices: &[u16],
query_count: usize,
query_norm: f32,
scale: f32,
) -> Vec<f32> {
let mut logits = vec![0.0f32; n_keys];
unsafe {
fq_compressed_attention_logits(
key_indices.as_ptr(),
n_keys,
key_norms.as_ptr(),
gram_table.as_ptr(),
gram_size,
query_indices.as_ptr(),
query_count,
query_norm,
scale,
logits.as_mut_ptr(),
);
}
logits
}
#[allow(clippy::result_unit_err)]
pub fn c_softmax(logits: &mut [f32]) -> Result<(), ()> {
if logits.is_empty() {
return Err(());
}
let ret = unsafe { fq_softmax(logits.as_mut_ptr(), logits.len()) };
if ret == 0 {
Ok(())
} else {
Err(())
}
}