faiss 0.5.2 → 0.6.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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/LICENSE.txt +1 -1
  4. data/ext/faiss/ext.cpp +1 -1
  5. data/ext/faiss/extconf.rb +5 -6
  6. data/ext/faiss/index_binary.cpp +76 -17
  7. data/ext/faiss/{index.cpp → index_rb.cpp} +108 -35
  8. data/ext/faiss/kmeans.cpp +12 -9
  9. data/ext/faiss/numo.hpp +11 -9
  10. data/ext/faiss/pca_matrix.cpp +10 -8
  11. data/ext/faiss/product_quantizer.cpp +14 -12
  12. data/ext/faiss/{utils.cpp → utils_rb.cpp} +10 -3
  13. data/ext/faiss/{utils.h → utils_rb.h} +6 -0
  14. data/lib/faiss/version.rb +1 -1
  15. data/lib/faiss.rb +1 -1
  16. data/vendor/faiss/faiss/AutoTune.cpp +130 -11
  17. data/vendor/faiss/faiss/AutoTune.h +14 -1
  18. data/vendor/faiss/faiss/Clustering.cpp +59 -10
  19. data/vendor/faiss/faiss/Clustering.h +12 -0
  20. data/vendor/faiss/faiss/IVFlib.cpp +31 -28
  21. data/vendor/faiss/faiss/Index.cpp +20 -8
  22. data/vendor/faiss/faiss/Index.h +25 -3
  23. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +19 -24
  24. data/vendor/faiss/faiss/IndexBinary.cpp +1 -0
  25. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +9 -4
  26. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +45 -11
  27. data/vendor/faiss/faiss/IndexFastScan.cpp +35 -22
  28. data/vendor/faiss/faiss/IndexFastScan.h +10 -1
  29. data/vendor/faiss/faiss/IndexFlat.cpp +193 -136
  30. data/vendor/faiss/faiss/IndexFlat.h +16 -1
  31. data/vendor/faiss/faiss/IndexFlatCodes.cpp +46 -22
  32. data/vendor/faiss/faiss/IndexFlatCodes.h +7 -1
  33. data/vendor/faiss/faiss/IndexHNSW.cpp +24 -50
  34. data/vendor/faiss/faiss/IndexHNSW.h +14 -12
  35. data/vendor/faiss/faiss/IndexIDMap.cpp +1 -1
  36. data/vendor/faiss/faiss/IndexIVF.cpp +76 -49
  37. data/vendor/faiss/faiss/IndexIVF.h +14 -4
  38. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +11 -8
  39. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +2 -2
  40. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +25 -14
  41. data/vendor/faiss/faiss/IndexIVFFastScan.h +26 -22
  42. data/vendor/faiss/faiss/IndexIVFFlat.cpp +10 -61
  43. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +39 -111
  44. data/vendor/faiss/faiss/IndexIVFPQ.cpp +89 -147
  45. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +37 -5
  46. data/vendor/faiss/faiss/IndexIVFPQR.cpp +2 -1
  47. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +42 -30
  48. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +2 -2
  49. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +246 -97
  50. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +32 -29
  51. data/vendor/faiss/faiss/IndexLSH.cpp +8 -6
  52. data/vendor/faiss/faiss/IndexLattice.cpp +29 -24
  53. data/vendor/faiss/faiss/IndexNNDescent.cpp +1 -0
  54. data/vendor/faiss/faiss/IndexNSG.cpp +2 -1
  55. data/vendor/faiss/faiss/IndexNSG.h +0 -2
  56. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +1 -1
  57. data/vendor/faiss/faiss/IndexPQ.cpp +19 -10
  58. data/vendor/faiss/faiss/IndexRaBitQ.cpp +26 -13
  59. data/vendor/faiss/faiss/IndexRaBitQ.h +2 -2
  60. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +132 -78
  61. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +14 -12
  62. data/vendor/faiss/faiss/IndexRefine.cpp +0 -30
  63. data/vendor/faiss/faiss/IndexShards.cpp +3 -4
  64. data/vendor/faiss/faiss/MetricType.h +16 -0
  65. data/vendor/faiss/faiss/VectorTransform.cpp +120 -0
  66. data/vendor/faiss/faiss/VectorTransform.h +23 -0
  67. data/vendor/faiss/faiss/clone_index.cpp +7 -4
  68. data/vendor/faiss/faiss/{cppcontrib/factory_tools.cpp → factory_tools.cpp} +1 -1
  69. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +1 -1
  70. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +37 -11
  71. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +0 -28
  72. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +367 -0
  73. data/vendor/faiss/faiss/impl/ClusteringInitialization.h +107 -0
  74. data/vendor/faiss/faiss/impl/CodePacker.cpp +4 -0
  75. data/vendor/faiss/faiss/impl/CodePacker.h +11 -3
  76. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +83 -0
  77. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.h +47 -0
  78. data/vendor/faiss/faiss/impl/FaissAssert.h +60 -2
  79. data/vendor/faiss/faiss/impl/HNSW.cpp +25 -34
  80. data/vendor/faiss/faiss/impl/HNSW.h +8 -6
  81. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +34 -27
  82. data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -1
  83. data/vendor/faiss/faiss/impl/NSG.cpp +6 -5
  84. data/vendor/faiss/faiss/impl/NSG.h +17 -7
  85. data/vendor/faiss/faiss/impl/Panorama.cpp +53 -46
  86. data/vendor/faiss/faiss/impl/Panorama.h +22 -6
  87. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +16 -5
  88. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +70 -58
  89. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +92 -0
  90. data/vendor/faiss/faiss/impl/RaBitQUtils.h +93 -31
  91. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +12 -28
  92. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +3 -10
  93. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +15 -41
  94. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.h +0 -4
  95. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +14 -9
  96. data/vendor/faiss/faiss/impl/ResultHandler.h +131 -50
  97. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +67 -2358
  98. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +0 -2
  99. data/vendor/faiss/faiss/impl/VisitedTable.cpp +42 -0
  100. data/vendor/faiss/faiss/impl/VisitedTable.h +69 -0
  101. data/vendor/faiss/faiss/impl/expanded_scanners.h +158 -0
  102. data/vendor/faiss/faiss/impl/index_read.cpp +829 -471
  103. data/vendor/faiss/faiss/impl/index_read_utils.h +0 -1
  104. data/vendor/faiss/faiss/impl/index_write.cpp +17 -8
  105. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +47 -20
  106. data/vendor/faiss/faiss/impl/mapped_io.cpp +9 -2
  107. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +7 -2
  108. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +11 -3
  109. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +19 -13
  110. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +29 -21
  111. data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx2.h → pq_code_distance/pq_code_distance-avx2.cpp} +42 -215
  112. data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx512.h → pq_code_distance/pq_code_distance-avx512.cpp} +68 -107
  113. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +141 -0
  114. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +23 -0
  115. data/vendor/faiss/faiss/impl/{code_distance/code_distance-sve.h → pq_code_distance/pq_code_distance-sve.cpp} +57 -144
  116. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +9 -6
  117. data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +121 -0
  118. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +136 -0
  119. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +280 -0
  120. data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +164 -0
  121. data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +94 -0
  122. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +455 -0
  123. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +430 -0
  124. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +329 -0
  125. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +467 -0
  126. data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +203 -0
  127. data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +42 -0
  128. data/vendor/faiss/faiss/impl/simd_dispatch.h +139 -0
  129. data/vendor/faiss/faiss/impl/simd_result_handlers.h +18 -18
  130. data/vendor/faiss/faiss/index_factory.cpp +35 -16
  131. data/vendor/faiss/faiss/index_io.h +29 -3
  132. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +7 -4
  133. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +1 -1
  134. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +9 -19
  135. data/vendor/faiss/faiss/svs/IndexSVSFlat.h +2 -0
  136. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +2 -1
  137. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +9 -1
  138. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +9 -0
  139. data/vendor/faiss/faiss/utils/Heap.cpp +46 -0
  140. data/vendor/faiss/faiss/utils/Heap.h +21 -0
  141. data/vendor/faiss/faiss/utils/NeuralNet.cpp +10 -7
  142. data/vendor/faiss/faiss/utils/distances.cpp +141 -23
  143. data/vendor/faiss/faiss/utils/distances.h +98 -0
  144. data/vendor/faiss/faiss/utils/distances_dispatch.h +170 -0
  145. data/vendor/faiss/faiss/utils/distances_simd.cpp +74 -3511
  146. data/vendor/faiss/faiss/utils/extra_distances-inl.h +164 -157
  147. data/vendor/faiss/faiss/utils/extra_distances.cpp +52 -95
  148. data/vendor/faiss/faiss/utils/extra_distances.h +47 -1
  149. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -1
  150. data/vendor/faiss/faiss/utils/partitioning.cpp +1 -1
  151. data/vendor/faiss/faiss/utils/pq_code_distance.h +251 -0
  152. data/vendor/faiss/faiss/utils/rabitq_simd.h +260 -0
  153. data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +150 -0
  154. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +568 -0
  155. data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +153 -0
  156. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +1185 -0
  157. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +1092 -0
  158. data/vendor/faiss/faiss/utils/simd_impl/distances_sse-inl.h +391 -0
  159. data/vendor/faiss/faiss/utils/simd_levels.cpp +322 -0
  160. data/vendor/faiss/faiss/utils/simd_levels.h +91 -0
  161. data/vendor/faiss/faiss/utils/simdlib_avx2.h +12 -1
  162. data/vendor/faiss/faiss/utils/simdlib_avx512.h +69 -0
  163. data/vendor/faiss/faiss/utils/simdlib_neon.h +6 -0
  164. data/vendor/faiss/faiss/utils/sorting.cpp +4 -4
  165. data/vendor/faiss/faiss/utils/utils.cpp +16 -9
  166. metadata +47 -18
  167. data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +0 -81
  168. data/vendor/faiss/faiss/impl/code_distance/code_distance.h +0 -186
  169. /data/vendor/faiss/faiss/{cppcontrib/factory_tools.h → factory_tools.h} +0 -0
@@ -58,36 +58,6 @@ void IndexRefine::reset() {
58
58
  ntotal = 0;
59
59
  }
60
60
 
61
- namespace {
62
-
63
- using idx_t = faiss::idx_t;
64
-
65
- template <class C>
66
- static void reorder_2_heaps(
67
- idx_t n,
68
- idx_t k,
69
- idx_t* __restrict labels,
70
- float* __restrict distances,
71
- idx_t k_base,
72
- const idx_t* __restrict base_labels,
73
- const float* __restrict base_distances) {
74
- #pragma omp parallel for if (n > 1)
75
- for (idx_t i = 0; i < n; i++) {
76
- idx_t* idxo = labels + i * k;
77
- float* diso = distances + i * k;
78
- const idx_t* idxi = base_labels + i * k_base;
79
- const float* disi = base_distances + i * k_base;
80
-
81
- heap_heapify<C>(k, diso, idxo, disi, idxi, k);
82
- if (k_base != k) { // add remaining elements
83
- heap_addn<C>(k, diso, idxo, disi + k, idxi + k, k_base - k);
84
- }
85
- heap_reorder<C>(k, diso, idxo);
86
- }
87
- }
88
-
89
- } // anonymous namespace
90
-
91
61
  void IndexRefine::search(
92
62
  idx_t n,
93
63
  const float* x,
@@ -22,7 +22,7 @@ namespace {
22
22
 
23
23
  // IndexBinary needs to update the code_size when d is set...
24
24
 
25
- void sync_d(Index* index) {}
25
+ void sync_d(Index* /*index*/) {}
26
26
 
27
27
  void sync_d(IndexBinary* index) {
28
28
  FAISS_THROW_IF_NOT(index->d % 8 == 0);
@@ -71,13 +71,12 @@ IndexShardsTemplate<IndexT>::IndexShardsTemplate(
71
71
  }
72
72
 
73
73
  template <typename IndexT>
74
- void IndexShardsTemplate<IndexT>::onAfterAddIndex(IndexT* index /* unused */) {
74
+ void IndexShardsTemplate<IndexT>::onAfterAddIndex(IndexT* /*index*/) {
75
75
  syncWithSubIndexes();
76
76
  }
77
77
 
78
78
  template <typename IndexT>
79
- void IndexShardsTemplate<IndexT>::onAfterRemoveIndex(
80
- IndexT* index /* unused */) {
79
+ void IndexShardsTemplate<IndexT>::onAfterRemoveIndex(IndexT* /*index*/) {
81
80
  syncWithSubIndexes();
82
81
  }
83
82
 
@@ -12,6 +12,9 @@
12
12
 
13
13
  #include <cstdint>
14
14
  #include <cstdio>
15
+ #include <cstdlib>
16
+
17
+ #include <faiss/impl/FaissAssert.h>
15
18
 
16
19
  namespace faiss {
17
20
 
@@ -20,6 +23,8 @@ namespace faiss {
20
23
  /// Most algorithms support both inner product and L2, with the flat
21
24
  /// (brute-force) indices supporting additional metric types for vector
22
25
  /// comparison.
26
+ ///
27
+ /// NOTE: when adding or removing values, update metric_type_from_int() below.
23
28
  enum MetricType {
24
29
  METRIC_INNER_PRODUCT = 0, ///< maximum inner product search
25
30
  METRIC_L2 = 1, ///< squared L2 search
@@ -52,6 +57,17 @@ constexpr bool is_similarity_metric(MetricType metric_type) {
52
57
  (metric_type == METRIC_Jaccard));
53
58
  }
54
59
 
60
+ /// Convert an integer to MetricType with range validation.
61
+ /// Throws FaissException if the value is not a valid MetricType.
62
+ inline MetricType metric_type_from_int(int x) {
63
+ FAISS_THROW_IF_NOT_FMT(
64
+ (x >= METRIC_INNER_PRODUCT && x <= METRIC_Lp) ||
65
+ (x >= METRIC_Canberra && x <= METRIC_GOWER),
66
+ "invalid metric type %d",
67
+ x);
68
+ return static_cast<MetricType>(x);
69
+ }
70
+
55
71
  } // namespace faiss
56
72
 
57
73
  #endif
@@ -352,6 +352,126 @@ void RandomRotationMatrix::train(idx_t /*n*/, const float* /*x*/) {
352
352
  init(12345);
353
353
  }
354
354
 
355
+ /*********************************************
356
+ * HadamardRotation
357
+ *********************************************/
358
+
359
+ // In-place Fast Walsh-Hadamard Transform. n must be a power of 2.
360
+ // Applies the unnormalized Hadamard butterfly: O(n log n) add/sub, no
361
+ // multiplies.
362
+ static void fwht_inplace(float* buf, size_t n) {
363
+ for (size_t step = 1; step < n; step *= 2) {
364
+ for (size_t i = 0; i < n; i += step * 2) {
365
+ for (size_t j = i; j < i + step; j++) {
366
+ float a = buf[j];
367
+ float b = buf[j + step];
368
+ buf[j] = a + b;
369
+ buf[j + step] = a - b;
370
+ }
371
+ }
372
+ }
373
+ }
374
+
375
+ // Smallest power of 2 >= n.
376
+ static int next_power_of_2(int n) {
377
+ int p = 1;
378
+ while (p < n) {
379
+ p *= 2;
380
+ }
381
+ return p;
382
+ }
383
+
384
+ // Generate three sign-flip vectors from the given seed.
385
+ static void generate_signs(
386
+ uint32_t seed,
387
+ size_t p,
388
+ std::vector<float>& s1,
389
+ std::vector<float>& s2,
390
+ std::vector<float>& s3) {
391
+ FAISS_THROW_IF_NOT(p > 0);
392
+ SplitMix64RandomGenerator rng(seed);
393
+ s1.resize(p);
394
+ s2.resize(p);
395
+ s3.resize(p);
396
+ for (size_t j = 0; j < p; j++) {
397
+ s1[j] = (rng.rand_int(2) == 0) ? -1.0f : 1.0f;
398
+ }
399
+ for (size_t j = 0; j < p; j++) {
400
+ s2[j] = (rng.rand_int(2) == 0) ? -1.0f : 1.0f;
401
+ }
402
+ for (size_t j = 0; j < p; j++) {
403
+ s3[j] = (rng.rand_int(2) == 0) ? -1.0f : 1.0f;
404
+ }
405
+ }
406
+
407
+ HadamardRotation::HadamardRotation(int d, uint32_t seed_in)
408
+ : VectorTransform(d, next_power_of_2(d)), seed(seed_in) {
409
+ init(seed_in);
410
+ }
411
+
412
+ void HadamardRotation::init(uint32_t seed_in) {
413
+ seed = seed_in;
414
+ is_trained = true;
415
+ generate_signs(seed, d_out, signs1, signs2, signs3);
416
+ }
417
+
418
+ void HadamardRotation::train(idx_t, const float*) {
419
+ init(seed != 0 ? seed : 12345);
420
+ }
421
+
422
+ void HadamardRotation::apply_noalloc(idx_t n, const float* x, float* xt) const {
423
+ FAISS_THROW_IF_NOT_MSG(is_trained, "Transformation not trained yet");
424
+
425
+ size_t d = d_in;
426
+ size_t p = d_out;
427
+ FAISS_THROW_IF_NOT(signs1.size() == p);
428
+ FAISS_THROW_IF_NOT(signs2.size() == p);
429
+ FAISS_THROW_IF_NOT(signs3.size() == p);
430
+
431
+ // Each unnormalized FWHT scales norms by sqrt(p).
432
+ // Three rounds scale by p^(3/2). Normalize once at the end.
433
+ float total_scale = 1.0f / (p * std::sqrt(static_cast<float>(p)));
434
+
435
+ #pragma omp parallel for schedule(dynamic)
436
+ for (idx_t i = 0; i < n; i++) {
437
+ const float* xi = x + i * d;
438
+ float* xo = xt + i * p;
439
+
440
+ // Round 1: copy + zero-pad + sign-flip + FWHT
441
+ for (size_t j = 0; j < d; j++) {
442
+ xo[j] = xi[j] * signs1[j];
443
+ }
444
+ for (size_t j = d; j < p; j++) {
445
+ xo[j] = 0.0f;
446
+ }
447
+ fwht_inplace(xo, p);
448
+
449
+ // Round 2: sign-flip + FWHT
450
+ for (size_t j = 0; j < p; j++) {
451
+ xo[j] *= signs2[j];
452
+ }
453
+ fwht_inplace(xo, p);
454
+
455
+ // Round 3: sign-flip + FWHT + normalize
456
+ for (size_t j = 0; j < p; j++) {
457
+ xo[j] *= signs3[j];
458
+ }
459
+ fwht_inplace(xo, p);
460
+
461
+ for (size_t j = 0; j < p; j++) {
462
+ xo[j] *= total_scale;
463
+ }
464
+ }
465
+ }
466
+
467
+ void HadamardRotation::check_identical(const VectorTransform& other) const {
468
+ auto* hr = dynamic_cast<const HadamardRotation*>(&other);
469
+ FAISS_THROW_IF_NOT(hr);
470
+ FAISS_THROW_IF_NOT(d_in == hr->d_in);
471
+ FAISS_THROW_IF_NOT(d_out == hr->d_out);
472
+ FAISS_THROW_IF_NOT(seed == hr->seed);
473
+ }
474
+
355
475
  /*********************************************
356
476
  * PCAMatrix
357
477
  *********************************************/
@@ -126,6 +126,29 @@ struct RandomRotationMatrix : LinearTransform {
126
126
  RandomRotationMatrix() {}
127
127
  };
128
128
 
129
+ /** Three rounds of random sign-flip + Fast Walsh-Hadamard Transform.
130
+ * Produces a pseudo-random rotation in O(d log d) time.
131
+ * d_out is the smallest power of 2 >= d_in (zero-padded as needed).
132
+ */
133
+ struct HadamardRotation : VectorTransform {
134
+ uint32_t seed{};
135
+
136
+ /// Sign-flip vectors, each of size d_out, generated from seed.
137
+ std::vector<float> signs1, signs2, signs3;
138
+
139
+ explicit HadamardRotation(int d, uint32_t seed = 12345);
140
+
141
+ void init(uint32_t seed_in);
142
+
143
+ void train(idx_t n, const float* x) override;
144
+
145
+ void apply_noalloc(idx_t n, const float* x, float* xt) const override;
146
+
147
+ void check_identical(const VectorTransform& other) const override;
148
+
149
+ HadamardRotation() {}
150
+ };
151
+
129
152
  /** Applies a principal component analysis on a set of vectors,
130
153
  * with optionally whitening and random rotation. */
131
154
  struct PCAMatrix : LinearTransform {
@@ -27,6 +27,8 @@
27
27
  #include <faiss/IndexIVFPQ.h>
28
28
  #include <faiss/IndexIVFPQFastScan.h>
29
29
  #include <faiss/IndexIVFPQR.h>
30
+ #include <faiss/IndexIVFRaBitQ.h>
31
+ #include <faiss/IndexIVFRaBitQFastScan.h>
30
32
  #include <faiss/IndexIVFSpectralHash.h>
31
33
  #include <faiss/IndexLSH.h>
32
34
  #include <faiss/IndexLattice.h>
@@ -41,11 +43,11 @@
41
43
  #include <faiss/MetaIndexes.h>
42
44
  #include <faiss/VectorTransform.h>
43
45
 
46
+ #include <faiss/impl/CodePacker.h>
44
47
  #include <faiss/impl/LocalSearchQuantizer.h>
45
48
  #include <faiss/impl/ProductQuantizer.h>
46
49
  #include <faiss/impl/ResidualQuantizer.h>
47
50
  #include <faiss/impl/ScalarQuantizer.h>
48
- #include <faiss/impl/pq4_fast_scan.h>
49
51
 
50
52
  #include <faiss/invlists/BlockInvertedLists.h>
51
53
 
@@ -96,6 +98,9 @@ IndexIVF* Cloner::clone_IndexIVF(const IndexIVF* ivf) {
96
98
  TRYCLONE(IndexIVFResidualQuantizerFastScan, ivf)
97
99
  TRYCLONE(IndexIVFPQFastScan, ivf)
98
100
 
101
+ TRYCLONE(IndexIVFRaBitQFastScan, ivf)
102
+ TRYCLONE(IndexIVFRaBitQ, ivf)
103
+
99
104
  TRYCLONE(IndexIVFFlatDedup, ivf)
100
105
  TRYCLONE(IndexIVFFlat, ivf)
101
106
  TRYCLONE(IndexIVFFlatPanorama, ivf)
@@ -257,9 +262,7 @@ InvertedLists* clone_InvertedLists(const InvertedLists* invlists) {
257
262
  if (auto* bils = dynamic_cast<const BlockInvertedLists*>(invlists)) {
258
263
  auto* bils2 = new BlockInvertedLists(*bils);
259
264
  if (bils->packer) {
260
- auto* packerPQ4 = dynamic_cast<const CodePackerPQ4*>(bils->packer);
261
- FAISS_THROW_IF_NOT(packerPQ4);
262
- bils2->packer = new CodePackerPQ4(*packerPQ4);
265
+ bils2->packer = bils->packer->clone();
263
266
  }
264
267
  return bils2;
265
268
  }
@@ -7,7 +7,7 @@
7
7
 
8
8
  // -*- c++ -*-
9
9
 
10
- #include <faiss/cppcontrib/factory_tools.h>
10
+ #include <faiss/factory_tools.h>
11
11
 
12
12
  #include <map>
13
13
 
@@ -64,7 +64,7 @@ void ToCPUCloner::merge_index(Index* dst, Index* src, bool successive_ids) {
64
64
  FAISS_ASSERT(ifl2);
65
65
  ifl->merge_from(*ifl2, successive_ids ? ifl->ntotal : 0);
66
66
  } else {
67
- FAISS_ASSERT(!"merging not implemented for this type of class");
67
+ FAISS_ASSERT(false && "merging not implemented for this type of class");
68
68
  }
69
69
  }
70
70
 
@@ -21,6 +21,7 @@
21
21
  #include <faiss/impl/FaissAssert.h>
22
22
  #include <faiss/impl/LocalSearchQuantizer.h>
23
23
  #include <faiss/impl/ResidualQuantizer.h>
24
+ #include <faiss/impl/simd_dispatch.h>
24
25
  #include <faiss/utils/Heap.h>
25
26
  #include <faiss/utils/distances.h>
26
27
  #include <faiss/utils/hamming.h>
@@ -66,8 +67,10 @@ void AdditiveQuantizer::set_derived_values() {
66
67
  codebook_offsets.resize(M + 1, 0);
67
68
  for (int i = 0; i < M; i++) {
68
69
  int nbit = nbits[i];
69
- size_t k = 1 << nbit;
70
- codebook_offsets[i + 1] = codebook_offsets[i] + k;
70
+ FAISS_CHECK_RANGE(nbit, 0, 31);
71
+ size_t k = (size_t)1 << nbit;
72
+ codebook_offsets[i + 1] =
73
+ add_no_overflow(codebook_offsets[i], k, "codebook_offsets");
71
74
  tot_bits += nbit;
72
75
  if (nbit != 0) {
73
76
  only_8bit = false;
@@ -153,12 +156,24 @@ void AdditiveQuantizer::train_norm(size_t n, const float* norms) {
153
156
 
154
157
  void AdditiveQuantizer::compute_codebook_tables() {
155
158
  centroid_norms.resize(total_codebook_size);
159
+ FAISS_THROW_IF_NOT_FMT(
160
+ codebooks.size() >=
161
+ mul_no_overflow(
162
+ total_codebook_size, d, "codebooks validation"),
163
+ "codebooks size %zd too small for total_codebook_size=%zd * d=%zd",
164
+ codebooks.size(),
165
+ total_codebook_size,
166
+ d);
156
167
  fvec_norms_L2sqr(
157
168
  centroid_norms.data(), codebooks.data(), d, total_codebook_size);
158
169
  size_t cross_table_size = 0;
159
170
  for (int m = 0; m < M; m++) {
171
+ FAISS_CHECK_RANGE(nbits[m], 0, 31);
160
172
  size_t K = (size_t)1 << nbits[m];
161
- cross_table_size += K * codebook_offsets[m];
173
+ size_t product =
174
+ mul_no_overflow(K, codebook_offsets[m], "cross_table_size");
175
+ cross_table_size = add_no_overflow(
176
+ cross_table_size, product, "cross_table_size accumulation");
162
177
  }
163
178
  codebook_cross_products.resize(cross_table_size);
164
179
  size_t ofs = 0;
@@ -167,7 +182,16 @@ void AdditiveQuantizer::compute_codebook_tables() {
167
182
  FINTEGER kk = codebook_offsets[m];
168
183
  FINTEGER di = d;
169
184
  float zero = 0, one = 1;
170
- assert(ofs + ki * kk <= cross_table_size);
185
+ size_t step_size = (size_t)ki * (size_t)kk;
186
+ FAISS_THROW_IF_NOT_FMT(
187
+ add_no_overflow(ofs, step_size, "cross product table offset") <=
188
+ cross_table_size,
189
+ "cross product table overflow at step %d: "
190
+ "%zd + %zd > %zd",
191
+ m,
192
+ ofs,
193
+ step_size,
194
+ cross_table_size);
171
195
  sgemm_("Transposed",
172
196
  "Not transposed",
173
197
  &ki,
@@ -181,7 +205,7 @@ void AdditiveQuantizer::compute_codebook_tables() {
181
205
  &zero,
182
206
  codebook_cross_products.data() + ofs,
183
207
  &ki);
184
- ofs += ki * kk;
208
+ ofs += step_size;
185
209
  }
186
210
  }
187
211
 
@@ -348,15 +372,17 @@ AdditiveQuantizer::~AdditiveQuantizer() {}
348
372
  void AdditiveQuantizer::compute_centroid_norms(float* norms) const {
349
373
  size_t ntotal = (size_t)1 << tot_bits;
350
374
  // TODO: make tree of partial sums
375
+ with_simd_level([&]<SIMDLevel SL>() {
351
376
  #pragma omp parallel
352
- {
353
- std::vector<float> tmp(d);
377
+ {
378
+ std::vector<float> tmp(d);
354
379
  #pragma omp for
355
- for (int64_t i = 0; i < ntotal; i++) {
356
- decode_64bit(i, tmp.data());
357
- norms[i] = fvec_norm_L2sqr(tmp.data(), d);
380
+ for (int64_t i = 0; i < ntotal; i++) {
381
+ decode_64bit(i, tmp.data());
382
+ norms[i] = fvec_norm_L2sqr<SL>(tmp.data(), d);
383
+ }
358
384
  }
359
- }
385
+ });
360
386
  }
361
387
 
362
388
  void AdditiveQuantizer::decode_64bit(idx_t bits, float* xi) const {
@@ -169,34 +169,6 @@ struct TimeoutCallback : InterruptCallback {
169
169
  static void reset(double timeout_in_seconds);
170
170
  };
171
171
 
172
- /// set implementation optimized for fast access.
173
- struct VisitedTable {
174
- std::vector<uint8_t> visited;
175
- uint8_t visno;
176
-
177
- explicit VisitedTable(int size) : visited(size), visno(1) {}
178
-
179
- /// set flag #no to true
180
- void set(int no) {
181
- visited[no] = visno;
182
- }
183
-
184
- /// get flag #no
185
- bool get(int no) const {
186
- return visited[no] == visno;
187
- }
188
-
189
- /// reset all flags to false
190
- void advance() {
191
- visno++;
192
- if (visno == 250) {
193
- // 250 rather than 255 because sometimes we use visno and visno+1
194
- memset(visited.data(), 0, sizeof(visited[0]) * visited.size());
195
- visno = 1;
196
- }
197
- }
198
- };
199
-
200
172
  } // namespace faiss
201
173
 
202
174
  #endif