faiss/index/
mod.rs

1//! Index interface and native implementations.
2//!
3//! This module hosts the vital [`Index`] trait, through which index building
4//! and searching is made. It also contains [`index_factory`], a generic
5//! function through which the user can retrieve most of the available index
6//! implementations. A very typical usage scenario of this crate is to create
7//! the index through this function, but some statically verified index types
8//! are available as well.
9//!
10//! [`Index`]: trait.Index.html
11//! [`index_factory`]: fn.index_factory.html
12
13use crate::error::{Error, Result};
14use crate::faiss_try;
15use crate::metric::MetricType;
16use crate::selector::IdSelector;
17use std::ffi::CString;
18use std::fmt::{self, Display, Formatter, Write};
19use std::os::raw::c_uint;
20use std::{mem, ptr};
21
22use faiss_sys::*;
23
24pub mod autotune;
25pub mod flat;
26pub mod id_map;
27pub mod io;
28pub mod io_flags;
29pub mod ivf_flat;
30pub mod lsh;
31pub mod pretransform;
32pub mod refine_flat;
33pub mod scalar_quantizer;
34
35#[cfg(feature = "gpu")]
36pub mod gpu;
37
38/// Primitive data type for identifying a vector in an index (or lack thereof).
39///
40/// Depending on the kind of index, it may be possible for vectors to share the
41/// same ID.
42#[repr(transparent)]
43#[derive(Debug, Copy, Clone)]
44pub struct Idx(idx_t);
45
46impl Display for Idx {
47    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
48        match self.get() {
49            None => f.write_char('x'),
50            Some(i) => i.fmt(f),
51        }
52    }
53}
54
55impl From<idx_t> for Idx {
56    fn from(x: idx_t) -> Self {
57        Idx(x)
58    }
59}
60
61impl Idx {
62    /// Create a vector identifier.
63    ///
64    /// # Panic
65    ///
66    /// Panics if the ID is too large (`>= 2^63`)
67    #[inline]
68    pub fn new(idx: u64) -> Self {
69        assert!(
70            idx < 0x8000_0000_0000_0000,
71            "too large index value provided to Idx::new"
72        );
73        let idx = idx as idx_t;
74        Idx(idx)
75    }
76
77    /// Create an identifier referring to no vector.
78    #[inline]
79    pub fn none() -> Self {
80        Idx(-1)
81    }
82
83    /// Check whether the vector identifier does not point to anything.
84    #[inline]
85    pub fn is_none(self) -> bool {
86        self.0 == -1
87    }
88
89    /// Check whether the vector identifier is not "none".
90    #[inline]
91    pub fn is_some(self) -> bool {
92        self.0 != -1
93    }
94
95    /// Retrieve the vector identifier as a primitive unsigned integer.
96    pub fn get(self) -> Option<u64> {
97        match self.0 {
98            -1 => None,
99            x => Some(x as u64),
100        }
101    }
102
103    /// Convert the vector identifier into a native `idx_t` value.
104    pub fn to_native(self) -> idx_t {
105        self.0
106    }
107}
108
109/// This comparison is not entirely reflexive: it returns always `false` if at
110/// least one of the values is a `none`.
111impl PartialEq<Idx> for Idx {
112    fn eq(&self, idx: &Idx) -> bool {
113        self.0 != -1 && idx.0 != -1 && self.0 == idx.0
114    }
115}
116
117/// This comparison is not entirely reflexive: it returns always `None` if at
118/// least one of the values is a `none`.
119impl PartialOrd<Idx> for Idx {
120    fn partial_cmp(&self, idx: &Idx) -> Option<std::cmp::Ordering> {
121        match (self.get(), idx.get()) {
122            (None, _) => None,
123            (_, None) => None,
124            (Some(a), Some(b)) => Some(a.cmp(&b)),
125        }
126    }
127}
128
129/// Interface for a Faiss index. Most methods in this trait match the ones in
130/// the native library, whereas some others serve as getters to the index'
131/// parameters.
132///
133/// Although all methods appear to be available for all index implementations,
134/// some methods may not be supported. For instance, a [`FlatIndex`] stores
135/// vectors sequentially, and so does not support `add_with_ids` nor
136/// `remove_ids`. Users are advised to read the Faiss wiki pages in order
137/// to understand which index algorithms support which operations.
138///
139/// [`FlatIndex`]: flat/struct.FlatIndex.html
140pub trait Index {
141    /// Whether the Index does not require training, or if training is done already
142    fn is_trained(&self) -> bool;
143
144    /// The total number of vectors indexed
145    fn ntotal(&self) -> u64;
146
147    /// The dimensionality of the indexed vectors
148    fn d(&self) -> u32;
149
150    /// The metric type assumed by the index
151    fn metric_type(&self) -> MetricType;
152
153    /// Add new data vectors to the index.
154    /// This assumes a C-contiguous memory slice of vectors, where the total
155    /// number of vectors is `x.len() / d`.
156    fn add(&mut self, x: &[f32]) -> Result<()>;
157
158    /// Add new data vectors to the index with IDs.
159    /// This assumes a C-contiguous memory slice of vectors, where the total
160    /// number of vectors is `x.len() / d`.
161    /// Not all index types may support this operation.
162    fn add_with_ids(&mut self, x: &[f32], xids: &[Idx]) -> Result<()>;
163
164    /// Train the underlying index with the given data.
165    fn train(&mut self, x: &[f32]) -> Result<()>;
166
167    /// Similar to `search`, but only provides the labels.
168    fn assign(&mut self, q: &[f32], k: usize) -> Result<AssignSearchResult>;
169
170    /// Perform a search for the `k` closest vectors to the given query vectors.
171    fn search(&mut self, q: &[f32], k: usize) -> Result<SearchResult>;
172
173    /// Perform a ranged search for the vectors closest to the given query vectors
174    /// by the given radius.
175    fn range_search(&mut self, q: &[f32], radius: f32) -> Result<RangeSearchResult>;
176
177    /// Clear the entire index.
178    fn reset(&mut self) -> Result<()>;
179
180    /// Remove data vectors represented by IDs.
181    fn remove_ids(&mut self, sel: &IdSelector) -> Result<usize>;
182
183    /// Index verbosity level
184    fn verbose(&self) -> bool;
185
186    /// Set Index verbosity level
187    fn set_verbose(&mut self, value: bool);
188}
189
190impl<I> Index for Box<I>
191where
192    I: Index,
193{
194    fn is_trained(&self) -> bool {
195        (**self).is_trained()
196    }
197
198    fn ntotal(&self) -> u64 {
199        (**self).ntotal()
200    }
201
202    fn d(&self) -> u32 {
203        (**self).d()
204    }
205
206    fn metric_type(&self) -> MetricType {
207        (**self).metric_type()
208    }
209
210    fn add(&mut self, x: &[f32]) -> Result<()> {
211        (**self).add(x)
212    }
213
214    fn add_with_ids(&mut self, x: &[f32], xids: &[Idx]) -> Result<()> {
215        (**self).add_with_ids(x, xids)
216    }
217
218    fn train(&mut self, x: &[f32]) -> Result<()> {
219        (**self).train(x)
220    }
221
222    fn assign(&mut self, q: &[f32], k: usize) -> Result<AssignSearchResult> {
223        (**self).assign(q, k)
224    }
225
226    fn search(&mut self, q: &[f32], k: usize) -> Result<SearchResult> {
227        (**self).search(q, k)
228    }
229
230    fn range_search(&mut self, q: &[f32], radius: f32) -> Result<RangeSearchResult> {
231        (**self).range_search(q, radius)
232    }
233
234    fn reset(&mut self) -> Result<()> {
235        (**self).reset()
236    }
237
238    fn remove_ids(&mut self, sel: &IdSelector) -> Result<usize> {
239        (**self).remove_ids(sel)
240    }
241
242    fn verbose(&self) -> bool {
243        (**self).verbose()
244    }
245
246    fn set_verbose(&mut self, value: bool) {
247        (**self).set_verbose(value)
248    }
249}
250
251/// Sub-trait for native implementations of a Faiss index.
252pub trait NativeIndex: Index {
253    /// Retrieve a pointer to the native index object.
254    fn inner_ptr(&self) -> *mut FaissIndex;
255}
256
257impl<NI: NativeIndex> NativeIndex for Box<NI> {
258    fn inner_ptr(&self) -> *mut FaissIndex {
259        (**self).inner_ptr()
260    }
261}
262
263/// Trait for a Faiss index that can be safely searched over multiple threads.
264/// Operations which do not modify the index are given a method taking an
265/// immutable reference. This is not the default for every index type because
266/// some implementations (such as the ones running on the GPU) do not allow
267/// concurrent searches.
268///
269/// Users of these methods should still note that batched querying is
270/// considerably faster than running queries one by one, even in parallel.
271pub trait ConcurrentIndex: Index {
272    /// Similar to `search`, but only provides the labels.
273    fn assign(&self, q: &[f32], k: usize) -> Result<AssignSearchResult>;
274
275    /// Perform a search for the `k` closest vectors to the given query vectors.
276    fn search(&self, q: &[f32], k: usize) -> Result<SearchResult>;
277
278    /// Perform a ranged search for the vectors closest to the given query vectors
279    /// by the given radius.
280    fn range_search(&self, q: &[f32], radius: f32) -> Result<RangeSearchResult>;
281}
282
283impl<CI: ConcurrentIndex> ConcurrentIndex for Box<CI> {
284    fn assign(&self, q: &[f32], k: usize) -> Result<AssignSearchResult> {
285        (**self).assign(q, k)
286    }
287
288    fn search(&self, q: &[f32], k: usize) -> Result<SearchResult> {
289        (**self).search(q, k)
290    }
291
292    fn range_search(&self, q: &[f32], radius: f32) -> Result<RangeSearchResult> {
293        (**self).range_search(q, radius)
294    }
295}
296
297/// Trait for Faiss index types known to be running on the CPU.
298pub trait CpuIndex: Index {}
299
300impl<CI: CpuIndex> CpuIndex for Box<CI> {}
301
302/// Trait for Faiss index types which can be built from a pointer
303/// to a native implementation.
304pub trait FromInnerPtr: NativeIndex {
305    /// Create an index using the given pointer to a native object.
306    ///
307    /// # Safety
308    ///
309    /// `inner_ptr` must point to a valid, non-freed CPU index, and cannot be
310    /// shared across multiple instances. The inner index must also be
311    /// compatible with the target `NativeIndex` type according to the native
312    /// class hierarchy. For example, creating an `IndexImpl` out of a pointer
313    /// to `FaissIndexFlatL2` is valid, but creating a `FlatIndex` out of a
314    /// plain `FaissIndex` can cause undefined behavior.
315    unsafe fn from_inner_ptr(inner_ptr: *mut FaissIndex) -> Self;
316}
317
318/// Trait for Faiss index types which can be built from a pointer
319/// to a native implementation.
320pub trait TryFromInnerPtr: NativeIndex {
321    /// Create an index using the given pointer to a native object,
322    /// checking that the index behind the given pointer
323    /// is compatible with the target index type.
324    /// If the inner index is not compatible with the intended target type
325    /// (e.g. creating a `FlatIndex` out of a `FaissIndexLSH`),
326    /// an error is returned.
327    ///
328    /// # Safety
329    ///
330    /// This function is unable to check that
331    /// `inner_ptr` points to a valid, non-freed CPU index.
332    /// Moreover, `inner_ptr` must not be shared across multiple instances.
333    unsafe fn try_from_inner_ptr(inner_ptr: *mut FaissIndex) -> Result<Self>
334    where
335        Self: Sized;
336}
337
338/// A trait which provides a Clone implementation to native index types.
339pub trait TryClone {
340    /// Create an independent clone of this index.
341    ///
342    /// # Errors
343    ///
344    /// May result in a native error if the clone operation is not
345    /// supported for the internal type of index.
346    fn try_clone(&self) -> Result<Self>
347    where
348        Self: Sized;
349}
350
351pub fn try_clone_from_inner_ptr<T>(val: &T) -> Result<T>
352where
353    T: FromInnerPtr,
354{
355    unsafe {
356        let mut new_index_ptr = ::std::ptr::null_mut();
357        faiss_try(faiss_clone_index(val.inner_ptr(), &mut new_index_ptr))?;
358        Ok(crate::index::FromInnerPtr::from_inner_ptr(new_index_ptr))
359    }
360}
361
362/// The outcome of an index assign operation.
363#[derive(Debug, Clone, PartialEq)]
364pub struct AssignSearchResult {
365    pub labels: Vec<Idx>,
366}
367
368/// The outcome of an index search operation.
369#[derive(Debug, Clone, PartialEq)]
370pub struct SearchResult {
371    pub distances: Vec<f32>,
372    pub labels: Vec<Idx>,
373}
374
375/// The outcome of an index range search operation.
376#[derive(Debug, Clone, PartialEq)]
377pub struct RangeSearchResult {
378    inner: *mut FaissRangeSearchResult,
379}
380
381impl RangeSearchResult {
382    pub fn nq(&self) -> usize {
383        unsafe { faiss_RangeSearchResult_nq(self.inner) }
384    }
385
386    pub fn lims(&self) -> &[usize] {
387        unsafe {
388            let mut lims_ptr = ptr::null_mut();
389            faiss_RangeSearchResult_lims(self.inner, &mut lims_ptr);
390            ::std::slice::from_raw_parts(lims_ptr, self.nq() + 1)
391        }
392    }
393
394    /// getter for labels and respective distances (not sorted):
395    /// result for query `i` is `labels[lims[i] .. lims[i+1]]`
396    pub fn distance_and_labels(&self) -> (&[f32], &[Idx]) {
397        let lims = self.lims();
398        let full_len = lims.last().cloned().unwrap_or(0);
399        unsafe {
400            let mut distances_ptr = ptr::null_mut();
401            let mut labels_ptr = ptr::null_mut();
402            faiss_RangeSearchResult_labels(self.inner, &mut labels_ptr, &mut distances_ptr);
403            let distances = ::std::slice::from_raw_parts(distances_ptr, full_len);
404            let labels = ::std::slice::from_raw_parts(labels_ptr as *const Idx, full_len);
405            (distances, labels)
406        }
407    }
408
409    /// getter for labels and respective distances (not sorted):
410    /// result for query `i` is `labels[lims[i] .. lims[i+1]]`
411    pub fn distance_and_labels_mut(&self) -> (&mut [f32], &mut [Idx]) {
412        unsafe {
413            let buf_size = faiss_RangeSearchResult_buffer_size(self.inner);
414            let mut distances_ptr = ptr::null_mut();
415            let mut labels_ptr = ptr::null_mut();
416            faiss_RangeSearchResult_labels(self.inner, &mut labels_ptr, &mut distances_ptr);
417            let distances = ::std::slice::from_raw_parts_mut(distances_ptr, buf_size);
418            let labels = ::std::slice::from_raw_parts_mut(labels_ptr as *mut Idx, buf_size);
419            (distances, labels)
420        }
421    }
422
423    /// getter for distances (not sorted):
424    /// result for query `i` is `distances[lims[i] .. lims[i+1]]`
425    pub fn distances(&self) -> &[f32] {
426        self.distance_and_labels().0
427    }
428
429    /// getter for distances (not sorted):
430    /// result for query `i` is `distances[lims[i] .. lims[i+1]]`
431    pub fn distances_mut(&mut self) -> &mut [f32] {
432        self.distance_and_labels_mut().0
433    }
434
435    /// getter for labels (not sorted):
436    /// result for query `i` is `labels[lims[i] .. lims[i+1]]`
437    pub fn labels(&self) -> &[Idx] {
438        self.distance_and_labels().1
439    }
440
441    /// getter for labels (not sorted):
442    /// result for query `i` is `labels[lims[i] .. lims[i+1]]`
443    pub fn labels_mut(&mut self) -> &mut [Idx] {
444        self.distance_and_labels_mut().1
445    }
446}
447
448impl Drop for RangeSearchResult {
449    fn drop(&mut self) {
450        unsafe {
451            faiss_RangeSearchResult_free(self.inner);
452        }
453    }
454}
455
456/// Native implementation of a Faiss Index
457/// running on the CPU.
458#[derive(Debug)]
459pub struct IndexImpl {
460    inner: *mut FaissIndex,
461}
462
463unsafe impl Send for IndexImpl {}
464unsafe impl Sync for IndexImpl {}
465
466impl CpuIndex for IndexImpl {}
467
468impl Drop for IndexImpl {
469    fn drop(&mut self) {
470        unsafe {
471            faiss_Index_free(self.inner);
472        }
473    }
474}
475
476impl IndexImpl {
477    pub fn inner_ptr(&self) -> *mut FaissIndex {
478        self.inner
479    }
480}
481
482impl NativeIndex for IndexImpl {
483    fn inner_ptr(&self) -> *mut FaissIndex {
484        self.inner
485    }
486}
487
488impl FromInnerPtr for IndexImpl {
489    unsafe fn from_inner_ptr(inner_ptr: *mut FaissIndex) -> Self {
490        IndexImpl { inner: inner_ptr }
491    }
492}
493
494impl TryFromInnerPtr for IndexImpl {
495    unsafe fn try_from_inner_ptr(inner_ptr: *mut FaissIndex) -> Result<Self>
496    where
497        Self: Sized,
498    {
499        if inner_ptr.is_null() {
500            Err(Error::BadCast)
501        } else {
502            Ok(IndexImpl { inner: inner_ptr })
503        }
504    }
505}
506
507/// Index upcast trait.
508///
509/// If you need to store several different types of indexes in one collection,
510/// you can cast all indexes to the common type `IndexImpl`.
511/// # Examples
512///
513/// ```
514/// # use faiss::{index::{IndexImpl, UpcastIndex}, FlatIndex, index_factory, MetricType};
515/// let f1 = FlatIndex::new_l2(128).unwrap();
516/// let f2 = index_factory(128, "Flat", MetricType::L2).unwrap();
517/// let v: Vec<IndexImpl> = vec![
518///     f1.upcast(),
519///     f2,
520/// ];
521/// ```
522///
523pub trait UpcastIndex: NativeIndex {
524    /// Convert an index to the base `IndexImpl` type
525    fn upcast(self) -> IndexImpl;
526}
527
528impl<NI: NativeIndex> UpcastIndex for NI {
529    fn upcast(self) -> IndexImpl {
530        let inner_ptr = self.inner_ptr();
531        mem::forget(self);
532
533        unsafe { IndexImpl::from_inner_ptr(inner_ptr) }
534    }
535}
536
537impl_native_index!(IndexImpl);
538
539impl TryClone for IndexImpl {
540    fn try_clone(&self) -> Result<Self>
541    where
542        Self: Sized,
543    {
544        try_clone_from_inner_ptr(self)
545    }
546}
547
548/// Use the index factory to create a native instance of a Faiss index, for `d`-dimensional
549/// vectors. `description` should follow the exact guidelines as the native Faiss interface
550/// (see the [Faiss wiki](https://github.com/facebookresearch/faiss/wiki/Faiss-indexes) for examples).
551///
552/// # Error
553///
554/// This function returns an error if the description contains any byte with the value `\0` (since
555/// it cannot be converted to a C string), or if the internal index factory operation fails.
556pub fn index_factory<D>(d: u32, description: D, metric: MetricType) -> Result<IndexImpl>
557where
558    D: AsRef<str>,
559{
560    unsafe {
561        let metric = metric as c_uint;
562        let description =
563            CString::new(description.as_ref()).map_err(|_| Error::IndexDescription)?;
564        let mut index_ptr = ::std::ptr::null_mut();
565        faiss_try(faiss_index_factory(
566            &mut index_ptr,
567            (d & 0x7FFF_FFFF) as i32,
568            description.as_ptr(),
569            metric,
570        ))?;
571        Ok(IndexImpl { inner: index_ptr })
572    }
573}
574
575#[cfg(test)]
576mod tests {
577    use super::{index_factory, Idx, Index, TryClone};
578    use crate::metric::MetricType;
579
580    #[test]
581    fn index_factory_flat() {
582        let index = index_factory(64, "Flat", MetricType::L2).unwrap();
583        assert_eq!(index.is_trained(), true); // Flat index does not need training
584        assert_eq!(index.ntotal(), 0);
585    }
586
587    #[test]
588    fn index_factory_flat_boxed() {
589        let index = index_factory(64, "Flat", MetricType::L2).unwrap();
590        let boxed = Box::new(index);
591        assert_eq!(boxed.is_trained(), true); // Flat index does not need training
592        assert_eq!(boxed.ntotal(), 0);
593    }
594
595    #[test]
596    fn index_factory_ivf_flat() {
597        let index = index_factory(64, "IVF8,Flat", MetricType::L2).unwrap();
598        assert_eq!(index.is_trained(), false);
599        assert_eq!(index.ntotal(), 0);
600    }
601
602    #[test]
603    fn index_factory_sq() {
604        let index = index_factory(64, "SQ8", MetricType::L2).unwrap();
605        assert_eq!(index.is_trained(), false);
606        assert_eq!(index.ntotal(), 0);
607    }
608
609    #[test]
610    fn index_factory_pq() {
611        let index = index_factory(64, "PQ8", MetricType::L2).unwrap();
612        assert_eq!(index.is_trained(), false);
613        assert_eq!(index.ntotal(), 0);
614    }
615
616    #[test]
617    fn index_factory_ivf_sq() {
618        let index = index_factory(64, "IVF8,SQ4", MetricType::L2).unwrap();
619        assert_eq!(index.is_trained(), false);
620        assert_eq!(index.ntotal(), 0);
621
622        let index = index_factory(64, "IVF8,SQ8", MetricType::L2).unwrap();
623        assert_eq!(index.is_trained(), false);
624        assert_eq!(index.ntotal(), 0);
625    }
626
627    #[test]
628    fn index_factory_hnsw() {
629        let index = index_factory(64, "HNSW8", MetricType::L2).unwrap();
630        assert_eq!(index.is_trained(), true); // training is not required
631        assert_eq!(index.ntotal(), 0);
632    }
633
634    #[test]
635    fn bad_index_factory_description() {
636        let r = index_factory(64, "fdnoyq", MetricType::L2);
637        assert!(r.is_err());
638        let r = index_factory(64, "Flat\0Flat", MetricType::L2);
639        assert!(r.is_err());
640    }
641
642    #[test]
643    fn index_clone() {
644        let mut index = index_factory(4, "Flat", MetricType::L2).unwrap();
645        let some_data = &[
646            7.5_f32, -7.5, 7.5, -7.5, 7.5, 7.5, 7.5, 7.5, -1., 1., 1., 1., 1., 1., 1., -1., 0., 0.,
647            0., 1., 1., 0., 0., -1.,
648        ];
649
650        index.add(some_data).unwrap();
651        assert_eq!(index.ntotal(), 6);
652
653        let mut index2 = index.try_clone().unwrap();
654        assert_eq!(index2.ntotal(), 6);
655
656        let some_more_data = &[
657            100., 100., 100., 100., -100., 100., 100., 100., 120., 100., 100., 105., -100., 100.,
658            100., 105.,
659        ];
660
661        index2.add(some_more_data).unwrap();
662        assert_eq!(index.ntotal(), 6);
663        assert_eq!(index2.ntotal(), 10);
664    }
665
666    #[test]
667    fn flat_index_search() {
668        let mut index = index_factory(8, "Flat", MetricType::L2).unwrap();
669        let some_data = &[
670            7.5_f32, -7.5, 7.5, -7.5, 7.5, 7.5, 7.5, 7.5, -1., 1., 1., 1., 1., 1., 1., -1., 0., 0.,
671            0., 1., 1., 0., 0., -1., 100., 100., 100., 100., -100., 100., 100., 100., 120., 100.,
672            100., 105., -100., 100., 100., 105.,
673        ];
674        index.add(some_data).unwrap();
675        assert_eq!(index.ntotal(), 5);
676
677        let my_query = [0.; 8];
678        let result = index.search(&my_query, 5).unwrap();
679        assert_eq!(result.labels, vec![Idx(2), Idx(1), Idx(0), Idx(3), Idx(4)]);
680        assert!(result.distances.iter().all(|x| *x > 0.));
681
682        let my_query = [100.; 8];
683        let result = index.search(&my_query, 5).unwrap();
684        assert_eq!(result.labels, vec![Idx(3), Idx(4), Idx(0), Idx(1), Idx(2)]);
685        assert!(result.distances.iter().all(|x| *x > 0.));
686
687        let my_query = vec![
688            0., 0., 0., 0., 0., 0., 0., 0., 100., 100., 100., 100., 100., 100., 100., 100.,
689        ];
690        let result = index.search(&my_query, 5).unwrap();
691        assert_eq!(
692            result.labels,
693            vec![
694                Idx(2),
695                Idx(1),
696                Idx(0),
697                Idx(3),
698                Idx(4),
699                Idx(3),
700                Idx(4),
701                Idx(0),
702                Idx(1),
703                Idx(2)
704            ]
705        );
706        assert!(result.distances.iter().all(|x| *x > 0.));
707    }
708
709    #[test]
710    fn flat_index_assign() {
711        let mut index = index_factory(8, "Flat", MetricType::L2).unwrap();
712        assert_eq!(index.d(), 8);
713        assert_eq!(index.ntotal(), 0);
714        let some_data = &[
715            7.5_f32, -7.5, 7.5, -7.5, 7.5, 7.5, 7.5, 7.5, -1., 1., 1., 1., 1., 1., 1., -1., 0., 0.,
716            0., 1., 1., 0., 0., -1., 100., 100., 100., 100., -100., 100., 100., 100., 120., 100.,
717            100., 105., -100., 100., 100., 105.,
718        ];
719        index.add(some_data).unwrap();
720        assert_eq!(index.ntotal(), 5);
721
722        let my_query = [0.; 8];
723        let result = index.assign(&my_query, 5).unwrap();
724        assert_eq!(result.labels, vec![Idx(2), Idx(1), Idx(0), Idx(3), Idx(4)]);
725
726        let my_query = [0.; 32];
727        let result = index.assign(&my_query, 5).unwrap();
728        assert_eq!(
729            result.labels,
730            vec![2, 1, 0, 3, 4, 2, 1, 0, 3, 4, 2, 1, 0, 3, 4, 2, 1, 0, 3, 4]
731                .into_iter()
732                .map(Idx)
733                .collect::<Vec<_>>()
734        );
735
736        let my_query = [100.; 8];
737        let result = index.assign(&my_query, 5).unwrap();
738        assert_eq!(
739            result.labels,
740            vec![3, 4, 0, 1, 2].into_iter().map(Idx).collect::<Vec<_>>()
741        );
742
743        let my_query = vec![
744            0., 0., 0., 0., 0., 0., 0., 0., 100., 100., 100., 100., 100., 100., 100., 100.,
745        ];
746        let result = index.assign(&my_query, 5).unwrap();
747        assert_eq!(
748            result.labels,
749            vec![2, 1, 0, 3, 4, 3, 4, 0, 1, 2]
750                .into_iter()
751                .map(Idx)
752                .collect::<Vec<_>>()
753        );
754
755        index.reset().unwrap();
756        assert_eq!(index.ntotal(), 0);
757    }
758
759    #[test]
760    fn flat_index_range_search() {
761        let mut index = index_factory(8, "Flat", MetricType::L2).unwrap();
762        let some_data = &[
763            7.5_f32, -7.5, 7.5, -7.5, 7.5, 7.5, 7.5, 7.5, -1., 1., 1., 1., 1., 1., 1., -1., 0., 0.,
764            0., 1., 1., 0., 0., -1., 100., 100., 100., 100., -100., 100., 100., 100., 120., 100.,
765            100., 105., -100., 100., 100., 105.,
766        ];
767        index.add(some_data).unwrap();
768        assert_eq!(index.ntotal(), 5);
769
770        let my_query = [0.; 8];
771        let result = index.range_search(&my_query, 8.125).unwrap();
772        let (distances, labels) = result.distance_and_labels();
773        assert!(labels == &[Idx(1), Idx(2)] || labels == &[Idx(2), Idx(1)]);
774        assert!(distances.iter().all(|x| *x > 0.));
775    }
776}