faiss-next 0.6.0

Rust bindings for Faiss (Facebook AI Similarity Search)
Documentation
use std::ptr;

use faiss_next_sys::{self, FaissIndex, FaissIndexIVFScalarQuantizer};

use crate::error::{check_return_code, Error, Result};
use crate::index::native::InnerPtr;
use crate::index::traits::{Index, IvfIndex};
use crate::metric::MetricType;

use super::QuantizerType;

pub struct IndexIVFScalarQuantizer {
    inner: InnerPtr<FaissIndexIVFScalarQuantizer>,
}

impl IndexIVFScalarQuantizer {
    pub fn new(
        quantizer: super::IndexFlat,
        nlist: usize,
        qtype: QuantizerType,
        metric: MetricType,
    ) -> Result<Self> {
        Self::with_options(quantizer, nlist, qtype, metric, false)
    }

    pub fn with_options(
        quantizer: super::IndexFlat,
        nlist: usize,
        qtype: QuantizerType,
        metric: MetricType,
        encode_residual: bool,
    ) -> Result<Self> {
        let d = quantizer.d();
        let quantizer_ptr = quantizer.inner_ptr();

        unsafe {
            let mut inner = ptr::null_mut();
            check_return_code(
                faiss_next_sys::faiss_IndexIVFScalarQuantizer_new_with_metric(
                    &mut inner,
                    quantizer_ptr as *mut FaissIndex,
                    d as usize,
                    nlist,
                    qtype.as_native(),
                    metric.as_native(),
                    encode_residual as i32,
                ),
            )?;

            std::mem::forget(quantizer);

            Ok(Self {
                inner: InnerPtr::new(inner)?,
            })
        }
    }

    pub fn from_index(index: super::IndexImpl) -> Result<Self> {
        unsafe {
            let ivf_sq_ptr = faiss_next_sys::faiss_IndexIVFScalarQuantizer_cast(index.inner_ptr());
            if ivf_sq_ptr.is_null() {
                return Err(Error::invalid_cast(
                    "IndexIVFScalarQuantizer",
                    "index is not an IVF ScalarQuantizer index",
                ));
            }
            std::mem::forget(index);
            Ok(Self {
                inner: InnerPtr::new(ivf_sq_ptr)?,
            })
        }
    }

    pub fn quantizer(&self) -> *mut FaissIndex {
        unsafe { faiss_next_sys::faiss_IndexIVFScalarQuantizer_quantizer(self.inner.as_ptr()) }
    }
}

impl Index for IndexIVFScalarQuantizer {
    fn inner_ptr(&self) -> *mut FaissIndex {
        self.inner.as_ptr() as *mut FaissIndex
    }
}

impl IvfIndex for IndexIVFScalarQuantizer {
    fn nlist(&self) -> usize {
        unsafe { faiss_next_sys::faiss_IndexIVFScalarQuantizer_nlist(self.inner.as_ptr()) }
    }

    fn nprobe(&self) -> usize {
        unsafe { faiss_next_sys::faiss_IndexIVFScalarQuantizer_nprobe(self.inner.as_ptr()) }
    }

    fn set_nprobe(&mut self, nprobe: usize) {
        unsafe {
            faiss_next_sys::faiss_IndexIVFScalarQuantizer_set_nprobe(self.inner.as_ptr(), nprobe)
        }
    }
}

impl Drop for IndexIVFScalarQuantizer {
    fn drop(&mut self) {
        tracing::trace!("dropping IndexIVFScalarQuantizer");
        unsafe {
            faiss_next_sys::faiss_IndexIVFScalarQuantizer_free(self.inner.as_ptr());
        }
    }
}

unsafe impl Send for IndexIVFScalarQuantizer {}
unsafe impl Sync for IndexIVFScalarQuantizer {}