pub struct RaBitQ { /* private fields */ }Expand description
RaBitQ quantizer
Implements scalar quantization with trained per-dimension ranges. Training computes min/max per dimension from sample data, enabling consistent quantization across all vectors and correct ADC distances.
§Usage
// Create and train quantizer
let mut quantizer = RaBitQ::new(RaBitQParams::bits4());
quantizer.train(&sample_vectors);
// Quantize vectors
let quantized = quantizer.quantize(&vector);
// ADC search (distances are mathematically correct)
let adc = quantizer.build_adc_table(&query);
let dist = adc.distance(&quantized.data);Implementations§
Source§impl RaBitQ
impl RaBitQ
Sourcepub fn new(params: RaBitQParams) -> Self
pub fn new(params: RaBitQParams) -> Self
Create a new RaBitQ quantizer (untrained)
Call train() before use to enable correct ADC distances.
Sourcepub fn new_trained(params: RaBitQParams, trained: TrainedParams) -> Self
pub fn new_trained(params: RaBitQParams, trained: TrainedParams) -> Self
Create a trained RaBitQ quantizer
Sourcepub fn default_4bit() -> Self
pub fn default_4bit() -> Self
Create with default 4-bit quantization
Sourcepub fn params(&self) -> &RaBitQParams
pub fn params(&self) -> &RaBitQParams
Get quantization parameters
Sourcepub fn is_trained(&self) -> bool
pub fn is_trained(&self) -> bool
Check if quantizer has been trained
Sourcepub fn trained_params(&self) -> Option<&TrainedParams>
pub fn trained_params(&self) -> Option<&TrainedParams>
Get trained parameters (if any)
Sourcepub fn train_owned(&mut self, vectors: &[Vec<f32>]) -> Result<(), &'static str>
pub fn train_owned(&mut self, vectors: &[Vec<f32>]) -> Result<(), &'static str>
Train with owned vectors (convenience method)
§Errors
Returns error if vectors is empty or have inconsistent dimensions.
Sourcepub fn quantize(&self, vector: &[f32]) -> QuantizedVector
pub fn quantize(&self, vector: &[f32]) -> QuantizedVector
Quantize a vector using trained parameters
If trained: uses per-dimension min/max for consistent quantization If untrained: falls back to legacy per-vector scaling (deprecated)
Sourcepub fn unpack_quantized(
&self,
packed: &[u8],
bits: u8,
dimensions: usize,
) -> Vec<u8> ⓘ
pub fn unpack_quantized( &self, packed: &[u8], bits: u8, dimensions: usize, ) -> Vec<u8> ⓘ
Unpack quantized bytes into individual values
Sourcepub fn reconstruct(
&self,
quantized: &[u8],
scale: f32,
dimensions: usize,
) -> Vec<f32>
pub fn reconstruct( &self, quantized: &[u8], scale: f32, dimensions: usize, ) -> Vec<f32>
Reconstruct (dequantize) a quantized vector
Algorithm (Extended RaBitQ):
- Unpack bytes to quantized values [0, 2^bits-1]
- Denormalize: v’ = q / (2^bits - 1)
- Unscale: v = v’ / scale
Sourcepub fn distance_l2(&self, qv1: &QuantizedVector, qv2: &QuantizedVector) -> f32
pub fn distance_l2(&self, qv1: &QuantizedVector, qv2: &QuantizedVector) -> f32
Compute L2 (Euclidean) distance between two quantized vectors
This reconstructs both vectors and computes standard L2 distance. For maximum accuracy, use this with original vectors for reranking.
Sourcepub fn distance_cosine(
&self,
qv1: &QuantizedVector,
qv2: &QuantizedVector,
) -> f32
pub fn distance_cosine( &self, qv1: &QuantizedVector, qv2: &QuantizedVector, ) -> f32
Compute cosine distance between two quantized vectors
Cosine distance = 1 - cosine similarity
Sourcepub fn distance_dot(&self, qv1: &QuantizedVector, qv2: &QuantizedVector) -> f32
pub fn distance_dot(&self, qv1: &QuantizedVector, qv2: &QuantizedVector) -> f32
Compute dot product between two quantized vectors
Sourcepub fn distance_approximate(
&self,
qv1: &QuantizedVector,
qv2: &QuantizedVector,
) -> f32
pub fn distance_approximate( &self, qv1: &QuantizedVector, qv2: &QuantizedVector, ) -> f32
Compute approximate distance using quantized values directly (fast path)
This computes distance in the quantized space without full reconstruction.
Faster but less accurate than distance_l2.
Sourcepub fn distance_asymmetric_l2(
&self,
query: &[f32],
quantized: &QuantizedVector,
) -> f32
pub fn distance_asymmetric_l2( &self, query: &[f32], quantized: &QuantizedVector, ) -> f32
Compute asymmetric L2 distance (query vs quantized) without full reconstruction
This is the hot path for search! It unpacks quantized values on the fly and computes distance against the uncompressed query vector.
When trained: Uses per-dimension min/max for correct distance computation. When untrained: Falls back to per-vector scale (deprecated, lower accuracy).
Sourcepub fn distance_asymmetric_l2_flat(
&self,
query: &[f32],
data: &[u8],
scale: f32,
) -> f32
pub fn distance_asymmetric_l2_flat( &self, query: &[f32], data: &[u8], scale: f32, ) -> f32
Asymmetric L2 distance from flat storage (no QuantizedVector wrapper)
This is the preferred method for flat contiguous storage layouts. When trained: Uses per-dimension min/max (scale ignored). When untrained: Falls back to per-vector scale.
Sourcepub fn build_adc_table(&self, query: &[f32]) -> Option<ADCTable>
pub fn build_adc_table(&self, query: &[f32]) -> Option<ADCTable>
Build an ADC (Asymmetric Distance Computation) lookup table for a query
If trained: uses per-dimension min/max for correct distances If untrained: uses provided scale (deprecated, incorrect distances)
§Example
// Preferred: train first, then build ADC table
quantizer.train(&sample_vectors);
let adc_table = quantizer.build_adc_table(&query);
for candidate in candidates {
let dist = adc_table.distance(&candidate.data);
}Sourcepub fn build_adc_table_with_scale(&self, query: &[f32], scale: f32) -> ADCTable
pub fn build_adc_table_with_scale(&self, query: &[f32], scale: f32) -> ADCTable
Build ADC table with explicit scale
§Note
Prefer build_adc_table() on a trained quantizer for correct ADC distances.
This method uses per-vector scale which gives lower accuracy.
Sourcepub fn distance_with_adc(
&self,
query: &[f32],
quantized: &QuantizedVector,
) -> Option<f32>
pub fn distance_with_adc( &self, query: &[f32], quantized: &QuantizedVector, ) -> Option<f32>
Compute distance using ADC table (convenience wrapper)
Returns None if quantizer is not trained.
Sourcepub fn distance_asymmetric_l2_raw(
&self,
query: &[f32],
data: &[u8],
scale: f32,
bits: u8,
) -> f32
pub fn distance_asymmetric_l2_raw( &self, query: &[f32], data: &[u8], scale: f32, bits: u8, ) -> f32
Low-level asymmetric distance computation on raw bytes
Enables zero-copy access from mmap (no QuantizedVector allocation needed).
Uses SmallVec to unpack on stack and SIMD for distance computation.
Sourcepub fn distance_l2_simd(
&self,
qv1: &QuantizedVector,
qv2: &QuantizedVector,
) -> f32
pub fn distance_l2_simd( &self, qv1: &QuantizedVector, qv2: &QuantizedVector, ) -> f32
Compute L2 distance using SIMD acceleration
Uses runtime CPU detection to select the best SIMD implementation:
x86_64: AVX2 > SSE2 > scalar- aarch64: NEON > scalar
Sourcepub fn distance_cosine_simd(
&self,
qv1: &QuantizedVector,
qv2: &QuantizedVector,
) -> f32
pub fn distance_cosine_simd( &self, qv1: &QuantizedVector, qv2: &QuantizedVector, ) -> f32
Compute cosine distance using SIMD acceleration
Trait Implementations§
Source§impl<'de> Deserialize<'de> for RaBitQ
impl<'de> Deserialize<'de> for RaBitQ
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for RaBitQ
impl RefUnwindSafe for RaBitQ
impl Send for RaBitQ
impl Sync for RaBitQ
impl Unpin for RaBitQ
impl UnwindSafe for RaBitQ
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more