faiss 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/ext/faiss/index.cpp +36 -10
  4. data/ext/faiss/index_binary.cpp +19 -6
  5. data/ext/faiss/kmeans.cpp +6 -6
  6. data/ext/faiss/numo.hpp +273 -123
  7. data/lib/faiss/version.rb +1 -1
  8. data/vendor/faiss/faiss/AutoTune.cpp +2 -3
  9. data/vendor/faiss/faiss/AutoTune.h +1 -1
  10. data/vendor/faiss/faiss/Clustering.cpp +2 -2
  11. data/vendor/faiss/faiss/Clustering.h +2 -2
  12. data/vendor/faiss/faiss/IVFlib.cpp +1 -2
  13. data/vendor/faiss/faiss/IVFlib.h +1 -1
  14. data/vendor/faiss/faiss/Index.h +10 -10
  15. data/vendor/faiss/faiss/Index2Layer.cpp +1 -1
  16. data/vendor/faiss/faiss/Index2Layer.h +2 -2
  17. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +9 -4
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +5 -1
  19. data/vendor/faiss/faiss/IndexBinary.h +7 -7
  20. data/vendor/faiss/faiss/IndexBinaryFromFloat.h +1 -1
  21. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +3 -1
  22. data/vendor/faiss/faiss/IndexBinaryHNSW.h +1 -1
  23. data/vendor/faiss/faiss/IndexBinaryHash.cpp +3 -3
  24. data/vendor/faiss/faiss/IndexBinaryHash.h +5 -5
  25. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +7 -6
  26. data/vendor/faiss/faiss/IndexFastScan.cpp +125 -49
  27. data/vendor/faiss/faiss/IndexFastScan.h +107 -7
  28. data/vendor/faiss/faiss/IndexFlat.h +1 -1
  29. data/vendor/faiss/faiss/IndexHNSW.cpp +3 -1
  30. data/vendor/faiss/faiss/IndexHNSW.h +1 -1
  31. data/vendor/faiss/faiss/IndexIDMap.cpp +14 -13
  32. data/vendor/faiss/faiss/IndexIDMap.h +6 -6
  33. data/vendor/faiss/faiss/IndexIVF.cpp +1 -1
  34. data/vendor/faiss/faiss/IndexIVF.h +5 -5
  35. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +1 -1
  36. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +9 -3
  37. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +3 -1
  38. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +176 -90
  39. data/vendor/faiss/faiss/IndexIVFFastScan.h +173 -18
  40. data/vendor/faiss/faiss/IndexIVFFlat.cpp +1 -0
  41. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +366 -0
  42. data/vendor/faiss/faiss/IndexIVFFlatPanorama.h +64 -0
  43. data/vendor/faiss/faiss/IndexIVFPQ.cpp +3 -1
  44. data/vendor/faiss/faiss/IndexIVFPQ.h +1 -1
  45. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +134 -2
  46. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +7 -1
  47. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +13 -6
  48. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +1 -0
  49. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +650 -0
  50. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +216 -0
  51. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +1 -1
  52. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +1 -1
  53. data/vendor/faiss/faiss/IndexNNDescent.cpp +1 -1
  54. data/vendor/faiss/faiss/IndexNSG.cpp +1 -1
  55. data/vendor/faiss/faiss/IndexNeuralNetCodec.h +1 -1
  56. data/vendor/faiss/faiss/IndexPQ.h +1 -1
  57. data/vendor/faiss/faiss/IndexPQFastScan.cpp +6 -2
  58. data/vendor/faiss/faiss/IndexPQFastScan.h +5 -1
  59. data/vendor/faiss/faiss/IndexRaBitQ.cpp +13 -10
  60. data/vendor/faiss/faiss/IndexRaBitQ.h +7 -2
  61. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +586 -0
  62. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +149 -0
  63. data/vendor/faiss/faiss/IndexShards.cpp +1 -1
  64. data/vendor/faiss/faiss/MatrixStats.cpp +3 -3
  65. data/vendor/faiss/faiss/MetricType.h +1 -1
  66. data/vendor/faiss/faiss/VectorTransform.h +2 -2
  67. data/vendor/faiss/faiss/clone_index.cpp +3 -1
  68. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +1 -1
  69. data/vendor/faiss/faiss/gpu/GpuIndex.h +11 -11
  70. data/vendor/faiss/faiss/gpu/GpuIndexBinaryCagra.h +1 -1
  71. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +1 -1
  72. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +10 -6
  73. data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +2 -0
  74. data/vendor/faiss/faiss/gpu/test/TestGpuIcmEncoder.cpp +7 -0
  75. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +1 -1
  76. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +1 -1
  77. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +1 -1
  78. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +2 -2
  79. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +1 -1
  80. data/vendor/faiss/faiss/impl/CodePacker.h +2 -2
  81. data/vendor/faiss/faiss/impl/DistanceComputer.h +3 -3
  82. data/vendor/faiss/faiss/impl/FastScanDistancePostProcessing.h +53 -0
  83. data/vendor/faiss/faiss/impl/HNSW.cpp +1 -1
  84. data/vendor/faiss/faiss/impl/HNSW.h +4 -4
  85. data/vendor/faiss/faiss/impl/IDSelector.cpp +2 -2
  86. data/vendor/faiss/faiss/impl/IDSelector.h +1 -1
  87. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +4 -4
  88. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +1 -1
  89. data/vendor/faiss/faiss/impl/LookupTableScaler.h +1 -1
  90. data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -1
  91. data/vendor/faiss/faiss/impl/NNDescent.h +2 -2
  92. data/vendor/faiss/faiss/impl/NSG.cpp +1 -1
  93. data/vendor/faiss/faiss/impl/PanoramaStats.cpp +33 -0
  94. data/vendor/faiss/faiss/impl/PanoramaStats.h +38 -0
  95. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +5 -5
  96. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +1 -1
  97. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +1 -1
  98. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +2 -0
  99. data/vendor/faiss/faiss/impl/ProductQuantizer.h +1 -1
  100. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +246 -0
  101. data/vendor/faiss/faiss/impl/RaBitQUtils.h +153 -0
  102. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +54 -158
  103. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +2 -1
  104. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
  105. data/vendor/faiss/faiss/impl/ResultHandler.h +4 -4
  106. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +1 -1
  107. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +1 -1
  108. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +7 -4
  109. data/vendor/faiss/faiss/impl/index_read.cpp +87 -3
  110. data/vendor/faiss/faiss/impl/index_write.cpp +73 -3
  111. data/vendor/faiss/faiss/impl/io.cpp +2 -2
  112. data/vendor/faiss/faiss/impl/io.h +4 -4
  113. data/vendor/faiss/faiss/impl/kmeans1d.cpp +1 -1
  114. data/vendor/faiss/faiss/impl/kmeans1d.h +1 -1
  115. data/vendor/faiss/faiss/impl/lattice_Zn.h +2 -2
  116. data/vendor/faiss/faiss/impl/mapped_io.cpp +2 -2
  117. data/vendor/faiss/faiss/impl/mapped_io.h +4 -3
  118. data/vendor/faiss/faiss/impl/maybe_owned_vector.h +8 -1
  119. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +30 -4
  120. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +14 -8
  121. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +5 -6
  122. data/vendor/faiss/faiss/impl/simd_result_handlers.h +55 -11
  123. data/vendor/faiss/faiss/impl/zerocopy_io.h +1 -1
  124. data/vendor/faiss/faiss/index_factory.cpp +43 -1
  125. data/vendor/faiss/faiss/index_factory.h +1 -1
  126. data/vendor/faiss/faiss/index_io.h +1 -1
  127. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +205 -0
  128. data/vendor/faiss/faiss/invlists/InvertedLists.h +62 -0
  129. data/vendor/faiss/faiss/utils/AlignedTable.h +1 -1
  130. data/vendor/faiss/faiss/utils/Heap.cpp +2 -2
  131. data/vendor/faiss/faiss/utils/Heap.h +3 -3
  132. data/vendor/faiss/faiss/utils/NeuralNet.cpp +1 -1
  133. data/vendor/faiss/faiss/utils/NeuralNet.h +3 -3
  134. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +2 -2
  135. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +2 -2
  136. data/vendor/faiss/faiss/utils/approx_topk/mode.h +1 -1
  137. data/vendor/faiss/faiss/utils/distances.h +2 -2
  138. data/vendor/faiss/faiss/utils/extra_distances-inl.h +3 -1
  139. data/vendor/faiss/faiss/utils/hamming-inl.h +2 -0
  140. data/vendor/faiss/faiss/utils/hamming.cpp +7 -6
  141. data/vendor/faiss/faiss/utils/hamming.h +1 -1
  142. data/vendor/faiss/faiss/utils/hamming_distance/common.h +1 -2
  143. data/vendor/faiss/faiss/utils/partitioning.cpp +5 -5
  144. data/vendor/faiss/faiss/utils/partitioning.h +2 -2
  145. data/vendor/faiss/faiss/utils/rabitq_simd.h +222 -336
  146. data/vendor/faiss/faiss/utils/random.cpp +1 -1
  147. data/vendor/faiss/faiss/utils/simdlib_avx2.h +1 -1
  148. data/vendor/faiss/faiss/utils/simdlib_avx512.h +1 -1
  149. data/vendor/faiss/faiss/utils/simdlib_neon.h +2 -2
  150. data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +1 -1
  151. data/vendor/faiss/faiss/utils/utils.cpp +5 -2
  152. data/vendor/faiss/faiss/utils/utils.h +2 -2
  153. metadata +14 -3
@@ -0,0 +1,64 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ // -*- c++ -*-
9
+
10
+ #ifndef FAISS_INDEX_IVF_FLAT_PANORAMA_H
11
+ #define FAISS_INDEX_IVF_FLAT_PANORAMA_H
12
+
13
+ #include <stdint.h>
14
+ #include "faiss/IndexIVFFlat.h"
15
+
16
+ namespace faiss {
17
+
18
+ /// Panorama adaptation of IndexIVFFlat following
19
+ /// https://www.arxiv.org/pdf/2510.00566.
20
+ ///
21
+ /// IDEA:
22
+ /// Panorama adapts the storage layout within each cluster and uses
23
+ /// pruning with bounds to improve the search performance.
24
+ /// Combined with orthogonal transforms upstream that concentrate the energy
25
+ /// in the early dimensions (like PCA, Cayley, etc.), Panorama can prune up
26
+ /// to 95% of the vectors in the cluster.
27
+ ///
28
+ /// OVERHEAD:
29
+ /// To be more efficient, we compute the residual energies at insertion time
30
+ /// and store them along the vectors, which comes with an additional storage
31
+ /// overhead of exactly (nlevels + 1) floats per vector. Add time is also
32
+ /// slightly higher due to the overhead of transposing the vectors.
33
+ ///
34
+ /// NOTE:
35
+ /// We inherit from IndexIVFFlat instead of IndexIVF so we can keep the same
36
+ /// insertion logic. The code responsible for level-oriented storage is in
37
+ /// `ArrayInvertedListsPanorama`, which is a struct member of `IndexIVF`.
38
+ struct IndexIVFFlatPanorama : IndexIVFFlat {
39
+ size_t n_levels;
40
+
41
+ std::vector<MaybeOwnedVector<float>> cum_sums;
42
+
43
+ explicit IndexIVFFlatPanorama(
44
+ Index* quantizer,
45
+ size_t d,
46
+ size_t nlist_,
47
+ int n_levels,
48
+ MetricType = METRIC_L2,
49
+ bool own_invlists = true);
50
+
51
+ InvertedListScanner* get_InvertedListScanner(
52
+ bool store_pairs,
53
+ const IDSelector* sel,
54
+ const IVFSearchParameters* params) const override;
55
+
56
+ void reconstruct_from_offset(int64_t list_no, int64_t offset, float* recons)
57
+ const override;
58
+
59
+ IndexIVFFlatPanorama();
60
+ };
61
+
62
+ } // namespace faiss
63
+
64
+ #endif
@@ -1163,7 +1163,9 @@ struct IVFPQScannerT : QueryTables {
1163
1163
  }
1164
1164
 
1165
1165
  #pragma omp critical
1166
- { indexIVFPQ_stats.n_hamming_pass += n_hamming_pass; }
1166
+ {
1167
+ indexIVFPQ_stats.n_hamming_pass += n_hamming_pass;
1168
+ }
1167
1169
  }
1168
1170
 
1169
1171
  template <class SearchResultType>
@@ -113,7 +113,7 @@ struct IndexIVFPQ : IndexIVF {
113
113
  */
114
114
  size_t find_duplicates(idx_t* ids, size_t* lims) const;
115
115
 
116
- // map a vector to a binary code knowning the index
116
+ // map a vector to a binary code knowing the index
117
117
  void encode(idx_t key, const float* x, uint8_t* code) const;
118
118
 
119
119
  /** Encode multiple vectors
@@ -7,6 +7,7 @@
7
7
 
8
8
  #include <faiss/IndexIVFPQFastScan.h>
9
9
 
10
+ #include <array>
10
11
  #include <cassert>
11
12
  #include <cstdio>
12
13
 
@@ -14,6 +15,7 @@
14
15
 
15
16
  #include <faiss/impl/AuxIndexStructures.h>
16
17
  #include <faiss/impl/FaissAssert.h>
18
+ #include <faiss/utils/Heap.h>
17
19
  #include <faiss/utils/distances.h>
18
20
  #include <faiss/utils/simdlib.h>
19
21
 
@@ -210,10 +212,11 @@ void IndexIVFPQFastScan::compute_LUT(
210
212
  const float* x,
211
213
  const CoarseQuantized& cq,
212
214
  AlignedTable<float>& dis_tables,
213
- AlignedTable<float>& biases) const {
215
+ AlignedTable<float>& biases,
216
+ const FastScanDistancePostProcessing&) const {
214
217
  size_t dim12 = pq.ksub * pq.M;
215
218
  size_t d = pq.d;
216
- size_t nprobe = this->nprobe;
219
+ size_t nprobe = cq.nprobe;
217
220
 
218
221
  if (by_residual) {
219
222
  if (metric_type == METRIC_L2) {
@@ -292,4 +295,133 @@ void IndexIVFPQFastScan::compute_LUT(
292
295
  }
293
296
  }
294
297
 
298
+ /*********************************************************
299
+ * InvertedListScanner for IVFPQFS
300
+ *********************************************************/
301
+
302
+ namespace {
303
+
304
+ struct IVFPQFastScanScanner : InvertedListScanner {
305
+ static constexpr int impl = 10; // based on search_implem_10
306
+ static constexpr size_t nq = 1; // 1 query at a time.
307
+ const IndexIVFPQFastScan& index;
308
+ AlignedTable<uint8_t> dis_tables;
309
+ AlignedTable<uint16_t> biases;
310
+ std::array<float, 2> normalizers{};
311
+ const float* xi = nullptr;
312
+
313
+ IVFPQFastScanScanner(
314
+ const IndexIVFPQFastScan& index,
315
+ bool store_pairs,
316
+ const IDSelector* sel)
317
+ : InvertedListScanner(store_pairs, sel), index(index) {
318
+ this->keep_max = is_similarity_metric(index.metric_type);
319
+ }
320
+
321
+ void set_query(const float* query) override {
322
+ this->xi = query;
323
+ }
324
+
325
+ void set_list(idx_t list_no, float coarse_dis) override {
326
+ this->list_no = list_no;
327
+ IndexIVFFastScan::CoarseQuantized cq{
328
+ .nprobe = 1, // 1 due to explicitly passing in list_no
329
+ .dis = &coarse_dis, // dis from query to list_no centroid.
330
+ .ids = &list_no, // id of the current list we are scanning
331
+ };
332
+ FastScanDistancePostProcessing empty_context{};
333
+ index.compute_LUT_uint8(
334
+ 1, xi, cq, dis_tables, biases, &normalizers[0], empty_context);
335
+ }
336
+
337
+ float distance_to_code(const uint8_t* /* code */) const override {
338
+ // It's not really possible to implement a distance_to_code since codes
339
+ // for 32 database vectors are intermixed.
340
+ FAISS_THROW_MSG("not implemented");
341
+ }
342
+
343
+ // Based on IVFFastScan search_implem_10, since it also deals with 1 query
344
+ // at a time.
345
+ size_t scan_codes(
346
+ size_t ntotal,
347
+ const uint8_t* codes,
348
+ const idx_t* ids,
349
+ float* distances,
350
+ idx_t* labels,
351
+ size_t k) const override {
352
+ // initialize the current iteration heap to the worst possible value of
353
+ // the prior loop
354
+ std::vector<float> curr_dists(k, distances[0]);
355
+ std::vector<idx_t> curr_labels(k, labels[0]);
356
+ FastScanDistancePostProcessing empty_context{};
357
+ std::unique_ptr<SIMDResultHandlerToFloat> handler(
358
+ index.make_knn_handler(
359
+ !keep_max,
360
+ impl,
361
+ nq,
362
+ k,
363
+ curr_dists.data(),
364
+ curr_labels.data(),
365
+ sel,
366
+ empty_context,
367
+ &normalizers[0]));
368
+
369
+ // This does not quite match search_implem_10, but it is fine because
370
+ // the scanner operates on a single query at a time, and this value is
371
+ // used as the query index. For a single query, the value is always 0.
372
+ int qmap1[1] = {0};
373
+
374
+ handler->q_map = qmap1;
375
+ handler->begin(&normalizers[0]);
376
+
377
+ const uint8_t* LUT = dis_tables.get();
378
+ handler->dbias = biases.get();
379
+
380
+ handler->ntotal = ntotal;
381
+ handler->id_map = ids;
382
+
383
+ pq4_accumulate_loop(
384
+ 1,
385
+ roundup(ntotal, index.bbs),
386
+ index.bbs,
387
+ static_cast<int>(index.M2),
388
+ codes,
389
+ LUT,
390
+ *handler,
391
+ nullptr);
392
+
393
+ // The handler is for the results of this iteration.
394
+ // Then we need a second heap to combine across iterations.
395
+ handler->end();
396
+ if (keep_max) {
397
+ minheap_addn(
398
+ k,
399
+ distances,
400
+ labels,
401
+ curr_dists.data(),
402
+ curr_labels.data(),
403
+ k);
404
+ } else {
405
+ maxheap_addn(
406
+ k,
407
+ distances,
408
+ labels,
409
+ curr_dists.data(),
410
+ curr_labels.data(),
411
+ k);
412
+ }
413
+
414
+ return handler->num_updates();
415
+ }
416
+ };
417
+
418
+ } // anonymous namespace
419
+
420
+ InvertedListScanner* IndexIVFPQFastScan::get_InvertedListScanner(
421
+ bool store_pairs,
422
+ const IDSelector* sel,
423
+ const IVFSearchParameters*) const {
424
+ return new IVFPQFastScanScanner(*this, store_pairs, sel);
425
+ }
426
+
295
427
  } // namespace faiss
@@ -80,7 +80,13 @@ struct IndexIVFPQFastScan : IndexIVFFastScan {
80
80
  const float* x,
81
81
  const CoarseQuantized& cq,
82
82
  AlignedTable<float>& dis_tables,
83
- AlignedTable<float>& biases) const override;
83
+ AlignedTable<float>& biases,
84
+ const FastScanDistancePostProcessing& context) const override;
85
+
86
+ InvertedListScanner* get_InvertedListScanner(
87
+ bool store_pairs,
88
+ const IDSelector* sel,
89
+ const IVFSearchParameters*) const override;
84
90
  };
85
91
 
86
92
  } // namespace faiss
@@ -155,15 +155,18 @@ struct RaBitInvertedListScanner : InvertedListScanner {
155
155
  std::unique_ptr<FlatCodesDistanceComputer> dc;
156
156
 
157
157
  uint8_t qb = 0;
158
+ bool centered = false;
158
159
 
159
- RaBitInvertedListScanner(
160
+ explicit RaBitInvertedListScanner(
160
161
  const IndexIVFRaBitQ& ivf_rabitq_in,
161
162
  bool store_pairs = false,
162
163
  const IDSelector* sel = nullptr,
163
- uint8_t qb_in = 0)
164
+ uint8_t qb_in = 0,
165
+ bool centered = false)
164
166
  : InvertedListScanner(store_pairs, sel),
165
167
  ivf_rabitq{ivf_rabitq_in},
166
- qb{qb_in} {
168
+ qb{qb_in},
169
+ centered(centered) {
167
170
  keep_max = is_similarity_metric(ivf_rabitq.metric_type);
168
171
  code_size = ivf_rabitq.code_size;
169
172
  }
@@ -196,7 +199,7 @@ struct RaBitInvertedListScanner : InvertedListScanner {
196
199
  // both query_vector and centroid are available!
197
200
  // set up DistanceComputer
198
201
  dc.reset(ivf_rabitq.rabitq.get_distance_computer(
199
- qb, reconstructed_centroid.data()));
202
+ qb, reconstructed_centroid.data(), centered));
200
203
 
201
204
  dc->set_query(query_vector.data());
202
205
  }
@@ -208,12 +211,15 @@ InvertedListScanner* IndexIVFRaBitQ::get_InvertedListScanner(
208
211
  const IDSelector* sel,
209
212
  const IVFSearchParameters* search_params_in) const {
210
213
  uint8_t used_qb = qb;
214
+ bool centered = false;
211
215
  if (auto params = dynamic_cast<const IVFRaBitQSearchParameters*>(
212
216
  search_params_in)) {
213
217
  used_qb = params->qb;
218
+ centered = params->centered;
214
219
  }
215
220
 
216
- return new RaBitInvertedListScanner(*this, store_pairs, sel, used_qb);
221
+ return new RaBitInvertedListScanner(
222
+ *this, store_pairs, sel, used_qb, centered);
217
223
  }
218
224
 
219
225
  void IndexIVFRaBitQ::reconstruct_from_offset(
@@ -278,7 +284,8 @@ float IVFRaBitDistanceComputer::operator()(idx_t i) {
278
284
  float distance = 0;
279
285
 
280
286
  std::unique_ptr<FlatCodesDistanceComputer> dc(
281
- parent->rabitq.get_distance_computer(parent->qb, centroid.data()));
287
+ parent->rabitq.get_distance_computer(
288
+ parent->qb, centroid.data(), /*centered=*/false));
282
289
  dc->set_query(q);
283
290
  distance = dc->distance_to_code(code);
284
291
 
@@ -19,6 +19,7 @@ namespace faiss {
19
19
 
20
20
  struct IVFRaBitQSearchParameters : IVFSearchParameters {
21
21
  uint8_t qb = 0;
22
+ bool centered = false;
22
23
  };
23
24
 
24
25
  // * by_residual is true, just by design