use super::format::{decode_u16s, decode_u64s, take};
use crate::error::SearchError;
use crate::quantized::{QuantizationKind, QuantizedStorage};
impl QuantizedStorage {
pub(super) fn byte_len(&self) -> Option<usize> {
match self {
Self::BFloat16(values) | Self::Float16(values) => values.len().checked_mul(2),
Self::Float8E4M3(values) => Some(values.len()),
Self::Int8(values) => Some(values.len()),
Self::Binary(values) => values.len().checked_mul(8),
}
}
pub(super) fn encode_into(&self, bytes: &mut Vec<u8>) {
match self {
Self::BFloat16(values) | Self::Float16(values) => {
for value in values {
bytes.extend_from_slice(&value.to_le_bytes());
}
}
Self::Float8E4M3(values) => bytes.extend_from_slice(values),
Self::Int8(values) => bytes.extend(values.iter().map(|value| value.to_le_bytes()[0])),
Self::Binary(values) => {
for value in values {
bytes.extend_from_slice(&value.to_le_bytes());
}
}
}
}
}
pub(super) fn decode_storage(
kind: QuantizationKind,
bytes: &[u8],
cursor: &mut usize,
length: usize,
) -> Result<QuantizedStorage, SearchError> {
Ok(match kind {
QuantizationKind::BFloat16 | QuantizationKind::Float16 => {
let values = decode_u16s(bytes, cursor, length)?;
if kind == QuantizationKind::BFloat16 {
QuantizedStorage::BFloat16(values)
} else {
QuantizedStorage::Float16(values)
}
}
QuantizationKind::Float8E4M3 => {
QuantizedStorage::Float8E4M3(take(bytes, cursor, length)?.to_vec())
}
QuantizationKind::Int8 => QuantizedStorage::Int8(
take(bytes, cursor, length)?
.iter()
.map(|value| i8::from_le_bytes([*value]))
.collect(),
),
QuantizationKind::Binary => QuantizedStorage::Binary(decode_u64s(bytes, cursor, length)?),
})
}