faiss 0.4.1 → 0.4.2

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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/faiss/version.rb +1 -1
  4. data/vendor/faiss/faiss/AutoTune.cpp +39 -29
  5. data/vendor/faiss/faiss/Clustering.cpp +4 -2
  6. data/vendor/faiss/faiss/IVFlib.cpp +14 -7
  7. data/vendor/faiss/faiss/Index.h +72 -3
  8. data/vendor/faiss/faiss/Index2Layer.cpp +2 -4
  9. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +0 -1
  10. data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +1 -0
  11. data/vendor/faiss/faiss/IndexBinary.h +46 -3
  12. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +118 -4
  13. data/vendor/faiss/faiss/IndexBinaryHNSW.h +41 -0
  14. data/vendor/faiss/faiss/IndexBinaryHash.cpp +0 -1
  15. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +18 -7
  16. data/vendor/faiss/faiss/IndexBinaryIVF.h +5 -1
  17. data/vendor/faiss/faiss/IndexFlat.cpp +6 -4
  18. data/vendor/faiss/faiss/IndexHNSW.cpp +65 -24
  19. data/vendor/faiss/faiss/IndexHNSW.h +10 -1
  20. data/vendor/faiss/faiss/IndexIDMap.cpp +96 -18
  21. data/vendor/faiss/faiss/IndexIDMap.h +20 -0
  22. data/vendor/faiss/faiss/IndexIVF.cpp +28 -10
  23. data/vendor/faiss/faiss/IndexIVF.h +16 -1
  24. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +84 -16
  25. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +18 -6
  26. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +33 -21
  27. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +16 -6
  28. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +24 -15
  29. data/vendor/faiss/faiss/IndexIVFFastScan.h +4 -2
  30. data/vendor/faiss/faiss/IndexIVFFlat.cpp +59 -43
  31. data/vendor/faiss/faiss/IndexIVFFlat.h +10 -2
  32. data/vendor/faiss/faiss/IndexIVFPQ.cpp +16 -3
  33. data/vendor/faiss/faiss/IndexIVFPQ.h +8 -1
  34. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +14 -6
  35. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +2 -1
  36. data/vendor/faiss/faiss/IndexIVFPQR.cpp +14 -4
  37. data/vendor/faiss/faiss/IndexIVFPQR.h +2 -1
  38. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +28 -3
  39. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +8 -1
  40. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +9 -2
  41. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +2 -1
  42. data/vendor/faiss/faiss/IndexLattice.cpp +8 -4
  43. data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -7
  44. data/vendor/faiss/faiss/IndexNSG.cpp +3 -3
  45. data/vendor/faiss/faiss/IndexPQ.cpp +0 -1
  46. data/vendor/faiss/faiss/IndexPQ.h +1 -0
  47. data/vendor/faiss/faiss/IndexPQFastScan.cpp +0 -2
  48. data/vendor/faiss/faiss/IndexPreTransform.cpp +4 -2
  49. data/vendor/faiss/faiss/IndexRefine.cpp +11 -6
  50. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +16 -4
  51. data/vendor/faiss/faiss/IndexScalarQuantizer.h +10 -3
  52. data/vendor/faiss/faiss/IndexShards.cpp +7 -6
  53. data/vendor/faiss/faiss/MatrixStats.cpp +16 -8
  54. data/vendor/faiss/faiss/MetaIndexes.cpp +12 -6
  55. data/vendor/faiss/faiss/MetricType.h +5 -3
  56. data/vendor/faiss/faiss/clone_index.cpp +2 -4
  57. data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +6 -0
  58. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +9 -4
  59. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +32 -10
  60. data/vendor/faiss/faiss/gpu/GpuIndex.h +88 -0
  61. data/vendor/faiss/faiss/gpu/GpuIndexBinaryCagra.h +125 -0
  62. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +39 -4
  63. data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +3 -3
  64. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +1 -1
  65. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +3 -2
  66. data/vendor/faiss/faiss/gpu/utils/CuvsFilterConvert.h +41 -0
  67. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +6 -3
  68. data/vendor/faiss/faiss/impl/HNSW.cpp +34 -19
  69. data/vendor/faiss/faiss/impl/IDSelector.cpp +2 -1
  70. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -3
  71. data/vendor/faiss/faiss/impl/NNDescent.cpp +17 -9
  72. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +42 -21
  73. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +6 -24
  74. data/vendor/faiss/faiss/impl/ResultHandler.h +56 -47
  75. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +28 -15
  76. data/vendor/faiss/faiss/impl/index_read.cpp +36 -11
  77. data/vendor/faiss/faiss/impl/index_write.cpp +19 -6
  78. data/vendor/faiss/faiss/impl/io.cpp +9 -5
  79. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +18 -11
  80. data/vendor/faiss/faiss/impl/mapped_io.cpp +4 -7
  81. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +0 -1
  82. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +0 -1
  83. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +6 -6
  84. data/vendor/faiss/faiss/impl/zerocopy_io.cpp +1 -1
  85. data/vendor/faiss/faiss/impl/zerocopy_io.h +2 -2
  86. data/vendor/faiss/faiss/index_factory.cpp +49 -33
  87. data/vendor/faiss/faiss/index_factory.h +8 -2
  88. data/vendor/faiss/faiss/index_io.h +0 -3
  89. data/vendor/faiss/faiss/invlists/DirectMap.cpp +2 -1
  90. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +12 -6
  91. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +8 -4
  92. data/vendor/faiss/faiss/utils/Heap.cpp +15 -8
  93. data/vendor/faiss/faiss/utils/Heap.h +23 -12
  94. data/vendor/faiss/faiss/utils/distances.cpp +42 -21
  95. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +2 -2
  96. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +1 -1
  97. data/vendor/faiss/faiss/utils/distances_simd.cpp +5 -3
  98. data/vendor/faiss/faiss/utils/extra_distances-inl.h +27 -4
  99. data/vendor/faiss/faiss/utils/extra_distances.cpp +8 -4
  100. data/vendor/faiss/faiss/utils/hamming.cpp +20 -10
  101. data/vendor/faiss/faiss/utils/partitioning.cpp +8 -4
  102. data/vendor/faiss/faiss/utils/quantize_lut.cpp +17 -9
  103. data/vendor/faiss/faiss/utils/rabitq_simd.h +539 -0
  104. data/vendor/faiss/faiss/utils/random.cpp +14 -7
  105. data/vendor/faiss/faiss/utils/utils.cpp +0 -3
  106. metadata +5 -2
@@ -79,6 +79,33 @@ struct ResultHandler {
79
79
  virtual ~ResultHandler() {}
80
80
  };
81
81
 
82
+ /*****************************************************************
83
+ * Common ancestor for top-k search results.
84
+ *****************************************************************/
85
+
86
+ template <class C, bool use_sel = false>
87
+ struct TopkBlockResultHandler : BlockResultHandler<C, use_sel> {
88
+ using T = typename C::T;
89
+ using TI = typename C::TI;
90
+ T* dis_tab;
91
+ TI* ids_tab;
92
+
93
+ int64_t k; // number of results to keep
94
+
95
+ TopkBlockResultHandler(
96
+ size_t nq,
97
+ T* dis_tab,
98
+ TI* ids_tab,
99
+ size_t k,
100
+ const IDSelector* sel = nullptr)
101
+ : BlockResultHandler<C, use_sel>(nq, sel),
102
+ dis_tab(dis_tab),
103
+ ids_tab(ids_tab),
104
+ k(k) {}
105
+
106
+ ~TopkBlockResultHandler() {}
107
+ };
108
+
82
109
  /*****************************************************************
83
110
  * Single best result handler.
84
111
  * Tracks the only best result, thus avoiding storing
@@ -86,25 +113,19 @@ struct ResultHandler {
86
113
  *****************************************************************/
87
114
 
88
115
  template <class C, bool use_sel = false>
89
- struct Top1BlockResultHandler : BlockResultHandler<C, use_sel> {
116
+ struct Top1BlockResultHandler : TopkBlockResultHandler<C, use_sel> {
90
117
  using T = typename C::T;
91
118
  using TI = typename C::TI;
92
119
  using BlockResultHandler<C, use_sel>::i0;
93
120
  using BlockResultHandler<C, use_sel>::i1;
94
121
 
95
- // contains exactly nq elements
96
- T* dis_tab;
97
- // contains exactly nq elements
98
- TI* ids_tab;
99
-
100
122
  Top1BlockResultHandler(
101
123
  size_t nq,
102
124
  T* dis_tab,
103
125
  TI* ids_tab,
104
126
  const IDSelector* sel = nullptr)
105
- : BlockResultHandler<C, use_sel>(nq, sel),
106
- dis_tab(dis_tab),
107
- ids_tab(ids_tab) {}
127
+ : TopkBlockResultHandler<C, use_sel>(nq, dis_tab, ids_tab, 1, sel) {
128
+ }
108
129
 
109
130
  struct SingleResultHandler : ResultHandler<C> {
110
131
  Top1BlockResultHandler& hr;
@@ -184,28 +205,21 @@ struct Top1BlockResultHandler : BlockResultHandler<C, use_sel> {
184
205
  *****************************************************************/
185
206
 
186
207
  template <class C, bool use_sel = false>
187
- struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
208
+ struct HeapBlockResultHandler : TopkBlockResultHandler<C, use_sel> {
188
209
  using T = typename C::T;
189
210
  using TI = typename C::TI;
190
211
  using BlockResultHandler<C, use_sel>::i0;
191
212
  using BlockResultHandler<C, use_sel>::i1;
192
-
193
- T* heap_dis_tab;
194
- TI* heap_ids_tab;
195
-
196
- int64_t k; // number of results to keep
213
+ using TopkBlockResultHandler<C, use_sel>::k;
197
214
 
198
215
  HeapBlockResultHandler(
199
216
  size_t nq,
200
- T* heap_dis_tab,
201
- TI* heap_ids_tab,
217
+ T* dis_tab,
218
+ TI* ids_tab,
202
219
  size_t k,
203
220
  const IDSelector* sel = nullptr)
204
- : BlockResultHandler<C, use_sel>(nq, sel),
205
- heap_dis_tab(heap_dis_tab),
206
- heap_ids_tab(heap_ids_tab),
207
- k(k) {}
208
-
221
+ : TopkBlockResultHandler<C, use_sel>(nq, dis_tab, ids_tab, k, sel) {
222
+ }
209
223
  /******************************************************
210
224
  * API for 1 result at a time (each SingleResultHandler is
211
225
  * called from 1 thread)
@@ -224,8 +238,8 @@ struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
224
238
 
225
239
  /// begin results for query # i
226
240
  void begin(size_t i) {
227
- heap_dis = hr.heap_dis_tab + i * k;
228
- heap_ids = hr.heap_ids_tab + i * k;
241
+ heap_dis = hr.dis_tab + i * k;
242
+ heap_ids = hr.ids_tab + i * k;
229
243
  heap_heapify<C>(k, heap_dis, heap_ids);
230
244
  threshold = heap_dis[0];
231
245
  }
@@ -255,7 +269,8 @@ struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
255
269
  this->i0 = i0_2;
256
270
  this->i1 = i1_2;
257
271
  for (size_t i = i0; i < i1; i++) {
258
- heap_heapify<C>(k, heap_dis_tab + i * k, heap_ids_tab + i * k);
272
+ heap_heapify<C>(
273
+ k, this->dis_tab + i * this->k, this->ids_tab + i * k);
259
274
  }
260
275
  }
261
276
 
@@ -263,8 +278,8 @@ struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
263
278
  void add_results(size_t j0, size_t j1, const T* dis_tab) final {
264
279
  #pragma omp parallel for
265
280
  for (int64_t i = i0; i < i1; i++) {
266
- T* heap_dis = heap_dis_tab + i * k;
267
- TI* heap_ids = heap_ids_tab + i * k;
281
+ T* heap_dis = this->dis_tab + i * k;
282
+ TI* heap_ids = this->ids_tab + i * k;
268
283
  const T* dis_tab_i = dis_tab + (j1 - j0) * (i - i0) - j0;
269
284
  T thresh = heap_dis[0];
270
285
  for (size_t j = j0; j < j1; j++) {
@@ -281,7 +296,7 @@ struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
281
296
  void end_multiple() final {
282
297
  // maybe parallel for
283
298
  for (size_t i = i0; i < i1; i++) {
284
- heap_reorder<C>(k, heap_dis_tab + i * k, heap_ids_tab + i * k);
299
+ heap_reorder<C>(k, this->dis_tab + i * k, this->ids_tab + i * k);
285
300
  }
286
301
  }
287
302
  };
@@ -290,9 +305,9 @@ struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
290
305
  * Reservoir result handler
291
306
  *
292
307
  * A reservoir is a result array of size capacity > n (number of requested
293
- * results) all results below a threshold are stored in an arbitrary order. When
294
- * the capacity is reached, a new threshold is chosen by partitionning the
295
- * distance array.
308
+ * results) all results below a threshold are stored in an arbitrary order.
309
+ *When the capacity is reached, a new threshold is chosen by partitionning
310
+ *the distance array.
296
311
  *****************************************************************/
297
312
 
298
313
  /// Reservoir for a single query
@@ -367,28 +382,21 @@ struct ReservoirTopN : ResultHandler<C> {
367
382
  };
368
383
 
369
384
  template <class C, bool use_sel = false>
370
- struct ReservoirBlockResultHandler : BlockResultHandler<C, use_sel> {
385
+ struct ReservoirBlockResultHandler : TopkBlockResultHandler<C, use_sel> {
371
386
  using T = typename C::T;
372
387
  using TI = typename C::TI;
373
388
  using BlockResultHandler<C, use_sel>::i0;
374
389
  using BlockResultHandler<C, use_sel>::i1;
375
390
 
376
- T* heap_dis_tab;
377
- TI* heap_ids_tab;
378
-
379
- int64_t k; // number of results to keep
380
391
  size_t capacity; // capacity of the reservoirs
381
392
 
382
393
  ReservoirBlockResultHandler(
383
394
  size_t nq,
384
- T* heap_dis_tab,
385
- TI* heap_ids_tab,
395
+ T* dis_tab,
396
+ TI* ids_tab,
386
397
  size_t k,
387
398
  const IDSelector* sel = nullptr)
388
- : BlockResultHandler<C, use_sel>(nq, sel),
389
- heap_dis_tab(heap_dis_tab),
390
- heap_ids_tab(heap_ids_tab),
391
- k(k) {
399
+ : TopkBlockResultHandler<C, use_sel>(nq, dis_tab, ids_tab, k, sel) {
392
400
  // double then round up to multiple of 16 (for SIMD alignment)
393
401
  capacity = (2 * k + 15) & ~15;
394
402
  }
@@ -423,8 +431,8 @@ struct ReservoirBlockResultHandler : BlockResultHandler<C, use_sel> {
423
431
 
424
432
  /// series of results for query qno is done
425
433
  void end() {
426
- T* heap_dis = hr.heap_dis_tab + qno * hr.k;
427
- TI* heap_ids = hr.heap_ids_tab + qno * hr.k;
434
+ T* heap_dis = hr.dis_tab + qno * hr.k;
435
+ TI* heap_ids = hr.ids_tab + qno * hr.k;
428
436
  this->to_result(heap_dis, heap_ids);
429
437
  }
430
438
  };
@@ -446,7 +454,7 @@ struct ReservoirBlockResultHandler : BlockResultHandler<C, use_sel> {
446
454
  reservoirs.clear();
447
455
  for (size_t i = i0_2; i < i1_2; i++) {
448
456
  reservoirs.emplace_back(
449
- k,
457
+ this->k,
450
458
  capacity,
451
459
  reservoir_dis.data() + (i - i0_2) * capacity,
452
460
  reservoir_ids.data() + (i - i0_2) * capacity);
@@ -471,7 +479,7 @@ struct ReservoirBlockResultHandler : BlockResultHandler<C, use_sel> {
471
479
  // maybe parallel for
472
480
  for (size_t i = i0; i < i1; i++) {
473
481
  reservoirs[i - i0].to_result(
474
- heap_dis_tab + i * k, heap_ids_tab + i * k);
482
+ this->dis_tab + i * this->k, this->ids_tab + i * this->k);
475
483
  }
476
484
  }
477
485
  };
@@ -535,7 +543,8 @@ struct RangeSearchBlockResultHandler : BlockResultHandler<C, use_sel> {
535
543
  // finalize the partial result
536
544
  pres.finalize();
537
545
  } catch ([[maybe_unused]] const faiss::FaissException& e) {
538
- // Do nothing if allocation fails in finalizing partial results.
546
+ // Do nothing if allocation fails in finalizing partial
547
+ // results.
539
548
  #ifndef NDEBUG
540
549
  std::cerr << e.what() << std::endl;
541
550
  #endif
@@ -13,7 +13,6 @@
13
13
  #include <cstdio>
14
14
 
15
15
  #include <faiss/impl/platform_macros.h>
16
- #include <omp.h>
17
16
 
18
17
  #ifdef __SSE__
19
18
  #include <immintrin.h>
@@ -985,10 +984,12 @@ void train_Uniform(
985
984
  vmin = HUGE_VAL;
986
985
  vmax = -HUGE_VAL;
987
986
  for (size_t i = 0; i < n; i++) {
988
- if (x[i] < vmin)
987
+ if (x[i] < vmin) {
989
988
  vmin = x[i];
990
- if (x[i] > vmax)
989
+ }
990
+ if (x[i] > vmax) {
991
991
  vmax = x[i];
992
+ }
992
993
  }
993
994
  float vexp = (vmax - vmin) * rs_arg;
994
995
  vmin -= vexp;
@@ -1011,10 +1012,12 @@ void train_Uniform(
1011
1012
  // TODO just do a quickselect
1012
1013
  std::sort(x_copy.begin(), x_copy.end());
1013
1014
  int o = int(rs_arg * n);
1014
- if (o < 0)
1015
+ if (o < 0) {
1015
1016
  o = 0;
1016
- if (o > n - o)
1017
+ }
1018
+ if (o > n - o) {
1017
1019
  o = n / 2;
1020
+ }
1018
1021
  vmin = x_copy[o];
1019
1022
  vmax = x_copy[n - 1 - o];
1020
1023
 
@@ -1024,10 +1027,12 @@ void train_Uniform(
1024
1027
  {
1025
1028
  vmin = HUGE_VAL, vmax = -HUGE_VAL;
1026
1029
  for (size_t i = 0; i < n; i++) {
1027
- if (x[i] < vmin)
1030
+ if (x[i] < vmin) {
1028
1031
  vmin = x[i];
1029
- if (x[i] > vmax)
1032
+ }
1033
+ if (x[i] > vmax) {
1030
1034
  vmax = x[i];
1035
+ }
1031
1036
  sx += x[i];
1032
1037
  }
1033
1038
  b = vmin;
@@ -1043,10 +1048,12 @@ void train_Uniform(
1043
1048
  for (idx_t i = 0; i < n; i++) {
1044
1049
  float xi = x[i];
1045
1050
  float ni = floor((xi - b) / a + 0.5);
1046
- if (ni < 0)
1051
+ if (ni < 0) {
1047
1052
  ni = 0;
1048
- if (ni >= k)
1053
+ }
1054
+ if (ni >= k) {
1049
1055
  ni = k - 1;
1056
+ }
1050
1057
  err1 += sqr(xi - (ni * a + b));
1051
1058
  sn += ni;
1052
1059
  sn2 += ni * ni;
@@ -1055,8 +1062,9 @@ void train_Uniform(
1055
1062
 
1056
1063
  if (err1 == last_err) {
1057
1064
  iter_last_err++;
1058
- if (iter_last_err == 16)
1065
+ if (iter_last_err == 16) {
1059
1066
  break;
1067
+ }
1060
1068
  } else {
1061
1069
  last_err = err1;
1062
1070
  iter_last_err = 0;
@@ -1071,8 +1079,9 @@ void train_Uniform(
1071
1079
  fflush(stdout);
1072
1080
  }
1073
1081
  }
1074
- if (verbose)
1082
+ if (verbose) {
1075
1083
  printf("\n");
1084
+ }
1076
1085
 
1077
1086
  vmin = b;
1078
1087
  vmax = b + a * (k - 1);
@@ -1100,10 +1109,12 @@ void train_NonUniform(
1100
1109
  for (size_t i = 1; i < n; i++) {
1101
1110
  const float* xi = x + i * d;
1102
1111
  for (size_t j = 0; j < d; j++) {
1103
- if (xi[j] < vmin[j])
1112
+ if (xi[j] < vmin[j]) {
1104
1113
  vmin[j] = xi[j];
1105
- if (xi[j] > vmax[j])
1114
+ }
1115
+ if (xi[j] > vmax[j]) {
1106
1116
  vmax[j] = xi[j];
1117
+ }
1107
1118
  }
1108
1119
  }
1109
1120
  float* vdiff = vmax;
@@ -2066,16 +2077,18 @@ void ScalarQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
2066
2077
 
2067
2078
  memset(codes, 0, code_size * n);
2068
2079
  #pragma omp parallel for
2069
- for (int64_t i = 0; i < n; i++)
2080
+ for (int64_t i = 0; i < n; i++) {
2070
2081
  squant->encode_vector(x + i * d, codes + i * code_size);
2082
+ }
2071
2083
  }
2072
2084
 
2073
2085
  void ScalarQuantizer::decode(const uint8_t* codes, float* x, size_t n) const {
2074
2086
  std::unique_ptr<SQuantizer> squant(select_quantizer());
2075
2087
 
2076
2088
  #pragma omp parallel for
2077
- for (int64_t i = 0; i < n; i++)
2089
+ for (int64_t i = 0; i < n; i++) {
2078
2090
  squant->decode_vector(codes + i * code_size, x + i * d);
2091
+ }
2079
2092
  }
2080
2093
 
2081
2094
  SQDistanceComputer* ScalarQuantizer::get_distance_computer(
@@ -16,7 +16,6 @@
16
16
 
17
17
  #include <faiss/impl/FaissAssert.h>
18
18
  #include <faiss/impl/io.h>
19
- #include <faiss/impl/io_macros.h>
20
19
  #include <faiss/utils/hamming.h>
21
20
 
22
21
  #include <faiss/invlists/InvertedListsIOHook.h>
@@ -1100,24 +1099,37 @@ Index* read_index(IOReader* f, int io_flags) {
1100
1099
  idx = idxp;
1101
1100
  } else if (
1102
1101
  h == fourcc("IHNf") || h == fourcc("IHNp") || h == fourcc("IHNs") ||
1103
- h == fourcc("IHN2") || h == fourcc("IHNc")) {
1102
+ h == fourcc("IHN2") || h == fourcc("IHNc") || h == fourcc("IHc2")) {
1104
1103
  IndexHNSW* idxhnsw = nullptr;
1105
- if (h == fourcc("IHNf"))
1104
+ if (h == fourcc("IHNf")) {
1106
1105
  idxhnsw = new IndexHNSWFlat();
1107
- if (h == fourcc("IHNp"))
1106
+ }
1107
+ if (h == fourcc("IHNp")) {
1108
1108
  idxhnsw = new IndexHNSWPQ();
1109
- if (h == fourcc("IHNs"))
1109
+ }
1110
+ if (h == fourcc("IHNs")) {
1110
1111
  idxhnsw = new IndexHNSWSQ();
1111
- if (h == fourcc("IHN2"))
1112
+ }
1113
+ if (h == fourcc("IHN2")) {
1112
1114
  idxhnsw = new IndexHNSW2Level();
1113
- if (h == fourcc("IHNc"))
1115
+ }
1116
+ if (h == fourcc("IHNc")) {
1117
+ idxhnsw = new IndexHNSWCagra();
1118
+ }
1119
+ if (h == fourcc("IHc2")) {
1114
1120
  idxhnsw = new IndexHNSWCagra();
1121
+ }
1115
1122
  read_index_header(idxhnsw, f);
1116
- if (h == fourcc("IHNc")) {
1123
+ if (h == fourcc("IHNc") || h == fourcc("IHc2")) {
1117
1124
  READ1(idxhnsw->keep_max_size_level0);
1118
1125
  auto idx_hnsw_cagra = dynamic_cast<IndexHNSWCagra*>(idxhnsw);
1119
1126
  READ1(idx_hnsw_cagra->base_level_only);
1120
1127
  READ1(idx_hnsw_cagra->num_base_level_search_entrypoints);
1128
+ if (h == fourcc("IHc2")) {
1129
+ READ1(idx_hnsw_cagra->numeric_type_);
1130
+ } else { // cagra before numeric_type_ was introduced
1131
+ idx_hnsw_cagra->set_numeric_type(faiss::Float32);
1132
+ }
1121
1133
  }
1122
1134
  read_HNSW(&idxhnsw->hnsw, f);
1123
1135
  idxhnsw->storage = read_index(f, io_flags);
@@ -1129,12 +1141,15 @@ Index* read_index(IOReader* f, int io_flags) {
1129
1141
  } else if (
1130
1142
  h == fourcc("INSf") || h == fourcc("INSp") || h == fourcc("INSs")) {
1131
1143
  IndexNSG* idxnsg;
1132
- if (h == fourcc("INSf"))
1144
+ if (h == fourcc("INSf")) {
1133
1145
  idxnsg = new IndexNSGFlat();
1134
- if (h == fourcc("INSp"))
1146
+ }
1147
+ if (h == fourcc("INSp")) {
1135
1148
  idxnsg = new IndexNSGPQ();
1136
- if (h == fourcc("INSs"))
1149
+ }
1150
+ if (h == fourcc("INSs")) {
1137
1151
  idxnsg = new IndexNSGSQ();
1152
+ }
1138
1153
  read_index_header(idxnsg, f);
1139
1154
  READ1(idxnsg->GK);
1140
1155
  READ1(idxnsg->build_type);
@@ -1384,6 +1399,16 @@ IndexBinary* read_index_binary(IOReader* f, int io_flags) {
1384
1399
  idxhnsw->storage = read_index_binary(f, io_flags);
1385
1400
  idxhnsw->own_fields = true;
1386
1401
  idx = idxhnsw;
1402
+ } else if (h == fourcc("IBHc")) {
1403
+ IndexBinaryHNSWCagra* idxhnsw = new IndexBinaryHNSWCagra();
1404
+ read_index_binary_header(idxhnsw, f);
1405
+ READ1(idxhnsw->keep_max_size_level0);
1406
+ READ1(idxhnsw->base_level_only);
1407
+ READ1(idxhnsw->num_base_level_search_entrypoints);
1408
+ read_HNSW(&idxhnsw->hnsw, f);
1409
+ idxhnsw->storage = read_index_binary(f, io_flags);
1410
+ idxhnsw->own_fields = true;
1411
+ idx = idxhnsw;
1387
1412
  } else if (h == fourcc("IBMp") || h == fourcc("IBM2")) {
1388
1413
  bool is_map2 = h == fourcc("IBM2");
1389
1414
  IndexBinaryIDMap* idxmap =
@@ -16,7 +16,6 @@
16
16
  #include <faiss/invlists/InvertedListsIOHook.h>
17
17
 
18
18
  #include <faiss/impl/FaissAssert.h>
19
- #include <faiss/impl/io_macros.h>
20
19
  #include <faiss/utils/hamming.h>
21
20
 
22
21
  #include <faiss/Index2Layer.h>
@@ -255,8 +254,9 @@ void write_InvertedLists(const InvertedLists* ils, IOWriter* f) {
255
254
  // here we store either as a full or a sparse data buffer
256
255
  size_t n_non0 = 0;
257
256
  for (size_t i = 0; i < ails->nlist; i++) {
258
- if (ails->ids[i].size() > 0)
257
+ if (ails->ids[i].size() > 0) {
259
258
  n_non0++;
259
+ }
260
260
  }
261
261
  if (n_non0 > ails->nlist / 2) {
262
262
  uint32_t list_type = fourcc("full");
@@ -739,8 +739,9 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
739
739
  write_index_header(ixpt, f);
740
740
  int nt = ixpt->chain.size();
741
741
  WRITE1(nt);
742
- for (int i = 0; i < nt; i++)
742
+ for (int i = 0; i < nt; i++) {
743
743
  write_VectorTransform(ixpt->chain[i], f);
744
+ }
744
745
  write_index(ixpt->index, f);
745
746
  } else if (
746
747
  const MultiIndexQuantizer* imiq =
@@ -771,16 +772,17 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
771
772
  : dynamic_cast<const IndexHNSWPQ*>(idx) ? fourcc("IHNp")
772
773
  : dynamic_cast<const IndexHNSWSQ*>(idx) ? fourcc("IHNs")
773
774
  : dynamic_cast<const IndexHNSW2Level*>(idx) ? fourcc("IHN2")
774
- : dynamic_cast<const IndexHNSWCagra*>(idx) ? fourcc("IHNc")
775
+ : dynamic_cast<const IndexHNSWCagra*>(idx) ? fourcc("IHc2")
775
776
  : 0;
776
777
  FAISS_THROW_IF_NOT(h != 0);
777
778
  WRITE1(h);
778
779
  write_index_header(idxhnsw, f);
779
- if (h == fourcc("IHNc")) {
780
+ if (h == fourcc("IHc2")) {
780
781
  WRITE1(idxhnsw->keep_max_size_level0);
781
782
  auto idx_hnsw_cagra = dynamic_cast<const IndexHNSWCagra*>(idxhnsw);
782
783
  WRITE1(idx_hnsw_cagra->base_level_only);
783
784
  WRITE1(idx_hnsw_cagra->num_base_level_search_entrypoints);
785
+ WRITE1(idx_hnsw_cagra->numeric_type_);
784
786
  }
785
787
  write_HNSW(&idxhnsw->hnsw, f);
786
788
  if (io_flags & IO_FLAG_SKIP_STORAGE) {
@@ -1004,9 +1006,20 @@ void write_index_binary(const IndexBinary* idx, IOWriter* f) {
1004
1006
  } else if (
1005
1007
  const IndexBinaryHNSW* idxhnsw =
1006
1008
  dynamic_cast<const IndexBinaryHNSW*>(idx)) {
1007
- uint32_t h = fourcc("IBHf");
1009
+ // Determine which type of binary HNSW index this is
1010
+ uint32_t h = dynamic_cast<const IndexBinaryHNSWCagra*>(idx)
1011
+ ? fourcc("IBHc")
1012
+ : fourcc("IBHf");
1008
1013
  WRITE1(h);
1009
1014
  write_index_binary_header(idxhnsw, f);
1015
+
1016
+ if (h == fourcc("IBHc")) {
1017
+ auto idxcagra = dynamic_cast<const IndexBinaryHNSWCagra*>(idxhnsw);
1018
+ WRITE1(idxcagra->keep_max_size_level0);
1019
+ WRITE1(idxcagra->base_level_only);
1020
+ WRITE1(idxcagra->num_base_level_search_entrypoints);
1021
+ }
1022
+
1010
1023
  write_HNSW(&idxhnsw->hnsw, f);
1011
1024
  write_index_binary(idxhnsw->storage, f);
1012
1025
  } else if (
@@ -43,11 +43,13 @@ size_t VectorIOWriter::operator()(const void* ptr, size_t size, size_t nitems) {
43
43
  }
44
44
 
45
45
  size_t VectorIOReader::operator()(void* ptr, size_t size, size_t nitems) {
46
- if (rp >= data.size())
46
+ if (rp >= data.size()) {
47
47
  return 0;
48
+ }
48
49
  size_t nremain = (data.size() - rp) / size;
49
- if (nremain < nitems)
50
+ if (nremain < nitems) {
50
51
  nitems = nremain;
52
+ }
51
53
  if (size * nitems > 0) {
52
54
  memcpy(ptr, &data[rp], size * nitems);
53
55
  rp += size * nitems;
@@ -143,8 +145,9 @@ BufferedIOReader::BufferedIOReader(IOReader* reader, size_t bsz)
143
145
 
144
146
  size_t BufferedIOReader::operator()(void* ptr, size_t unitsize, size_t nitems) {
145
147
  size_t size = unitsize * nitems;
146
- if (size == 0)
148
+ if (size == 0) {
147
149
  return 0;
150
+ }
148
151
  char* dst = (char*)ptr;
149
152
  size_t nb;
150
153
 
@@ -189,8 +192,9 @@ size_t BufferedIOWriter::operator()(
189
192
  size_t unitsize,
190
193
  size_t nitems) {
191
194
  size_t size = unitsize * nitems;
192
- if (size == 0)
195
+ if (size == 0) {
193
196
  return 0;
197
+ }
194
198
  const char* src = (const char*)ptr;
195
199
  size_t nb;
196
200
 
@@ -260,7 +264,7 @@ std::string fourcc_inv(uint32_t x) {
260
264
  std::string fourcc_inv_printable(uint32_t x) {
261
265
  char cstr[5];
262
266
  fourcc_inv(x, cstr);
263
- std::string str = "";
267
+ std::string str;
264
268
  for (int i = 0; i < 4; i++) {
265
269
  uint8_t c = cstr[i];
266
270
  if (32 <= c && c < 127) {
@@ -18,7 +18,6 @@
18
18
  #include <queue>
19
19
  #include <unordered_set>
20
20
 
21
- #include <faiss/impl/platform_macros.h>
22
21
  #include <faiss/utils/distances.h>
23
22
 
24
23
  namespace faiss {
@@ -53,8 +52,9 @@ struct Comb {
53
52
 
54
53
  uint64_t operator()(int n, int p) const {
55
54
  assert(n < nmax && p < nmax);
56
- if (p > n)
55
+ if (p > n) {
57
56
  return 0;
57
+ }
58
58
  return tab[n * nmax + p];
59
59
  }
60
60
  };
@@ -66,8 +66,9 @@ point_list_t sum_of_sq(float total, int v, int n, float add = 0) {
66
66
  if (total < 0) {
67
67
  return point_list_t();
68
68
  } else if (n == 1) {
69
- while (sqr(v + add) > total)
69
+ while (sqr(v + add) > total) {
70
70
  v--;
71
+ }
71
72
  if (sqr(v + add) == total) {
72
73
  return point_list_t(1, v + add);
73
74
  } else {
@@ -118,8 +119,9 @@ uint64_t repeats_encode_64(
118
119
  code_comb += comb(rank, occ + 1);
119
120
  occ++;
120
121
  coded |= uint64_t{1} << i;
121
- if (occ == r->n)
122
+ if (occ == r->n) {
122
123
  break;
124
+ }
123
125
  }
124
126
  rank++;
125
127
  }
@@ -155,8 +157,9 @@ void repeats_decode_64(
155
157
  decoded |= uint64_t{1} << i;
156
158
  c[i] = r->val;
157
159
  occ++;
158
- if (occ == r->n)
160
+ if (occ == r->n) {
159
161
  break;
162
+ }
160
163
  next_rank = decode_comb_1(&code_comb, r->n - occ, next_rank);
161
164
  }
162
165
  }
@@ -210,8 +213,9 @@ uint64_t Repeats::encode(const float* c) const {
210
213
  code_comb += comb(rank, occ + 1);
211
214
  occ++;
212
215
  coded[i] = true;
213
- if (occ == r->n)
216
+ if (occ == r->n) {
214
217
  break;
218
+ }
215
219
  }
216
220
  rank++;
217
221
  }
@@ -247,8 +251,9 @@ void Repeats::decode(uint64_t code, float* c) const {
247
251
  decoded[i] = true;
248
252
  c[i] = r->val;
249
253
  occ++;
250
- if (occ == r->n)
254
+ if (occ == r->n) {
251
255
  break;
256
+ }
252
257
  next_rank =
253
258
  decode_comb_1(&code_comb, r->n - occ, next_rank);
254
259
  }
@@ -440,10 +445,11 @@ void ZnSphereCodec::decode(uint64_t code, float* c) const {
440
445
  int i0 = 0, i1 = natom;
441
446
  while (i0 + 1 < i1) {
442
447
  int imed = (i0 + i1) / 2;
443
- if (code_segments[imed].c0 <= code)
448
+ if (code_segments[imed].c0 <= code) {
444
449
  i0 = imed;
445
- else
450
+ } else {
446
451
  i1 = imed;
452
+ }
447
453
  }
448
454
  const CodeSegment& cs = code_segments[i0];
449
455
  code -= cs.c0;
@@ -592,10 +598,11 @@ void ZnSphereCodecRec::decode(uint64_t code, float* c) const {
592
598
  &all_nv_cum[(ld * (r2 + 1) + r2sub) * (r2 + 1)];
593
599
  while (i1 > i0 + 1) {
594
600
  int imed = (i0 + i1) / 2;
595
- if (cum[imed] <= codei)
601
+ if (cum[imed] <= codei) {
596
602
  i0 = imed;
597
- else
603
+ } else {
598
604
  i1 = imed;
605
+ }
599
606
  }
600
607
  int r2a = i0, r2b = r2sub - i0;
601
608
  codei -= cum[r2a];