faiss 0.6.2 → 0.6.4

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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/lib/faiss/version.rb +1 -1
  4. data/vendor/faiss/faiss/AutoTune.cpp +3 -1
  5. data/vendor/faiss/faiss/Clustering.cpp +9 -1
  6. data/vendor/faiss/faiss/Clustering.h +8 -0
  7. data/vendor/faiss/faiss/IVFlib.cpp +14 -3
  8. data/vendor/faiss/faiss/Index.h +2 -2
  9. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +9 -10
  10. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +2 -3
  11. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +24 -4
  12. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +16 -145
  13. data/vendor/faiss/faiss/IndexBinaryHNSW.h +0 -6
  14. data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
  15. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +8 -18
  16. data/vendor/faiss/faiss/IndexBinaryIVF.h +8 -1
  17. data/vendor/faiss/faiss/IndexEDEN.cpp +273 -0
  18. data/vendor/faiss/faiss/IndexEDEN.h +57 -0
  19. data/vendor/faiss/faiss/IndexFastScan.cpp +15 -4
  20. data/vendor/faiss/faiss/IndexFlat.cpp +21 -54
  21. data/vendor/faiss/faiss/IndexFlat.h +2 -2
  22. data/vendor/faiss/faiss/IndexHNSW.cpp +311 -102
  23. data/vendor/faiss/faiss/IndexHNSW.h +31 -7
  24. data/vendor/faiss/faiss/IndexIDMap.cpp +26 -8
  25. data/vendor/faiss/faiss/IndexIDMap.h +2 -0
  26. data/vendor/faiss/faiss/IndexIVF.cpp +36 -10
  27. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +1 -1
  28. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -4
  29. data/vendor/faiss/faiss/IndexIVFEDEN.cpp +302 -0
  30. data/vendor/faiss/faiss/IndexIVFEDEN.h +70 -0
  31. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +5 -6
  32. data/vendor/faiss/faiss/IndexIVFFlat.cpp +3 -4
  33. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
  34. data/vendor/faiss/faiss/IndexIVFPQ.cpp +49 -23
  35. data/vendor/faiss/faiss/IndexIVFPQ.h +11 -0
  36. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
  37. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +19 -49
  38. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
  39. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
  40. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
  41. data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
  42. data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
  43. data/vendor/faiss/faiss/IndexNNDescent.cpp +9 -2
  44. data/vendor/faiss/faiss/IndexNSG.cpp +7 -2
  45. data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
  46. data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
  47. data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
  48. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
  49. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
  50. data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
  51. data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
  52. data/vendor/faiss/faiss/IndexShards.cpp +5 -5
  53. data/vendor/faiss/faiss/IndexShardsIVF.cpp +6 -5
  54. data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
  55. data/vendor/faiss/faiss/SuperKMeans.cpp +286 -247
  56. data/vendor/faiss/faiss/SuperKMeans.h +33 -2
  57. data/vendor/faiss/faiss/VectorTransform.cpp +71 -2
  58. data/vendor/faiss/faiss/VectorTransform.h +3 -0
  59. data/vendor/faiss/faiss/clone_index.cpp +8 -0
  60. data/vendor/faiss/faiss/factory_tools.cpp +47 -4
  61. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
  62. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +1 -5
  63. data/vendor/faiss/faiss/gpu/GpuDistance.h +2 -5
  64. data/vendor/faiss/faiss/gpu/GpuIndex.h +38 -16
  65. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +71 -1
  66. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
  67. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
  68. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
  69. data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
  70. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
  71. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +1 -5
  72. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
  73. data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
  74. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +1 -1
  75. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +7 -4
  76. data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
  77. data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
  78. data/vendor/faiss/faiss/impl/HNSW.cpp +528 -267
  79. data/vendor/faiss/faiss/impl/HNSW.h +46 -7
  80. data/vendor/faiss/faiss/impl/IDSelector.h +44 -0
  81. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
  82. data/vendor/faiss/faiss/impl/NNDescent.cpp +10 -3
  83. data/vendor/faiss/faiss/impl/NSG.cpp +3 -1
  84. data/vendor/faiss/faiss/impl/Panorama.h +20 -9
  85. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
  86. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +38 -26
  87. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +45 -37
  88. data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
  89. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +239 -72
  90. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +66 -4
  91. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +4 -13
  92. data/vendor/faiss/faiss/impl/ResultHandler.h +34 -34
  93. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +287 -84
  94. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +26 -10
  95. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
  96. data/vendor/faiss/faiss/impl/VisitedTable.cpp +22 -2
  97. data/vendor/faiss/faiss/impl/VisitedTable.h +20 -0
  98. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +90 -14
  99. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
  100. data/vendor/faiss/faiss/impl/expanded_scanners.h +5 -1
  101. data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +1 -0
  102. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +35 -2
  103. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
  104. data/vendor/faiss/faiss/impl/index_read.cpp +491 -50
  105. data/vendor/faiss/faiss/impl/index_write.cpp +86 -30
  106. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
  107. data/vendor/faiss/faiss/impl/platform_macros.h +3 -1
  108. data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
  109. data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
  110. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +73 -39
  111. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
  112. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
  113. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +4 -4
  114. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +4 -4
  115. data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
  116. data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
  117. data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
  118. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
  119. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
  120. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +887 -0
  121. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +2 -2
  122. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +9 -8
  123. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +90 -24
  124. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +30 -30
  125. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +4 -5
  126. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +101 -34
  127. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +169 -13
  128. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +125 -26
  129. data/vendor/faiss/faiss/impl/simd_dispatch.h +70 -31
  130. data/vendor/faiss/faiss/index_factory.cpp +40 -7
  131. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
  132. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +9 -6
  133. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +29 -8
  134. data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
  135. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
  136. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
  137. data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
  138. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
  139. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
  140. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +47 -5
  141. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +23 -3
  142. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +4 -2
  143. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
  144. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +10 -4
  145. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +2 -1
  146. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
  147. data/vendor/faiss/faiss/utils/distances.cpp +30 -11
  148. data/vendor/faiss/faiss/utils/distances_dispatch.h +30 -24
  149. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +1 -1
  150. data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -3
  151. data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
  152. data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
  153. data/vendor/faiss/faiss/utils/hamming.cpp +16 -10
  154. data/vendor/faiss/faiss/utils/hamming.h +10 -1
  155. data/vendor/faiss/faiss/utils/hamming_distance/common.h +14 -3
  156. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_vpopcnt.cpp +24 -0
  157. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +1 -1
  158. data/vendor/faiss/faiss/utils/hamming_distance/{hamming_computer-avx512_spr.h → hamming_computer-avx512_vpopcnt.h} +85 -24
  159. data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +141 -0
  160. data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
  161. data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
  162. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +194 -30
  163. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
  164. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
  165. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +198 -18
  166. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
  167. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +330 -40
  168. data/vendor/faiss/faiss/utils/simd_impl/{rabitq_avx512_spr.cpp → rabitq_avx512_vpopcnt.cpp} +112 -23
  169. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
  170. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
  171. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +2 -7
  172. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +6 -1
  173. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_sve.cpp +34 -0
  174. data/vendor/faiss/faiss/utils/simd_levels.cpp +196 -47
  175. data/vendor/faiss/faiss/utils/simd_levels.h +33 -8
  176. data/vendor/faiss/faiss/utils/utils.cpp +9 -27
  177. metadata +21 -5
  178. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +0 -15
@@ -0,0 +1,273 @@
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
+ #include <faiss/IndexEDEN.h>
9
+
10
+ #include <faiss/impl/FaissAssert.h>
11
+ #include <faiss/impl/ResultHandler.h>
12
+ #include <memory>
13
+
14
+ namespace faiss {
15
+
16
+ IndexEDEN::IndexEDEN() = default;
17
+
18
+ IndexEDEN::IndexEDEN(
19
+ idx_t d_in,
20
+ MetricType metric,
21
+ uint8_t nb_bits_in,
22
+ EDENScaleType scale_type_in)
23
+ : IndexFlatCodes(0, d_in, metric),
24
+ sq(d_in, eden_utils::quantizer_type_for_bits(nb_bits_in)),
25
+ scale_type(scale_type_in) {
26
+ FAISS_THROW_IF_NOT_MSG(
27
+ scale_type == EDENScaleType_UNBIASED ||
28
+ scale_type == EDENScaleType_BIASED,
29
+ "invalid EDEN scale type");
30
+ sq.train(0, nullptr);
31
+ code_size = eden_utils::code_size(d, sq.bits);
32
+ is_trained = false;
33
+ }
34
+
35
+ void IndexEDEN::train(idx_t n, const float* x) {
36
+ std::vector<float> centroid(d, 0.0f);
37
+ for (idx_t i = 0; i < n; i++) {
38
+ for (size_t j = 0; j < static_cast<size_t>(d); j++) {
39
+ centroid[j] += x[i * d + j];
40
+ }
41
+ }
42
+
43
+ if (n != 0) {
44
+ for (size_t j = 0; j < static_cast<size_t>(d); j++) {
45
+ centroid[j] /= static_cast<float>(n);
46
+ }
47
+ }
48
+
49
+ center = std::move(centroid);
50
+ sq.train(n, x);
51
+ is_trained = true;
52
+ }
53
+
54
+ void IndexEDEN::sa_encode(idx_t n, const float* x, uint8_t* bytes) const {
55
+ FAISS_THROW_IF_NOT(is_trained);
56
+ eden_utils::compute_codes(
57
+ sq, metric_type, scale_type, x, bytes, n, center.data());
58
+ }
59
+
60
+ void IndexEDEN::sa_decode(idx_t n, const uint8_t* bytes, float* x) const {
61
+ FAISS_THROW_IF_NOT(is_trained);
62
+ eden_utils::decode(sq, bytes, x, n, center.data());
63
+ }
64
+
65
+ FlatCodesDistanceComputer* IndexEDEN::get_FlatCodesDistanceComputer() const {
66
+ FlatCodesDistanceComputer* dc =
67
+ eden_utils::get_distance_computer(sq, metric_type, center.data());
68
+ dc->code_size = code_size;
69
+ dc->codes = codes.data();
70
+ return dc;
71
+ }
72
+
73
+ namespace {
74
+
75
+ bool use_eden_batch_scan(size_t d, size_t nb_bits) {
76
+ const size_t values_per_byte = 8 / nb_bits;
77
+ const size_t num_bytes = (d + values_per_byte - 1) / values_per_byte;
78
+ if (nb_bits == 1) {
79
+ return num_bytes >= 32;
80
+ }
81
+ if (nb_bits == 2) {
82
+ return num_bytes >= 16;
83
+ }
84
+ if (nb_bits == 4) {
85
+ return num_bytes >= 128;
86
+ }
87
+ return false;
88
+ }
89
+
90
+ struct Run_search_with_eden_dc {
91
+ using T = void;
92
+
93
+ template <class BlockResultHandler>
94
+ void f(BlockResultHandler& res, const IndexEDEN* index, const float* xq) {
95
+ const size_t ntotal = index->ntotal;
96
+ using SingleResultHandler =
97
+ typename BlockResultHandler::SingleResultHandler;
98
+ const int d = index->d;
99
+ const bool use_batch_scan = use_eden_batch_scan(d, index->sq.bits);
100
+
101
+ #pragma omp parallel
102
+ {
103
+ std::unique_ptr<EDENFlatCodesDistanceComputer> dc(
104
+ eden_utils::get_distance_computer(
105
+ index->sq,
106
+ index->metric_type,
107
+ index->center.data()));
108
+ dc->code_size = index->code_size;
109
+ dc->codes = index->codes.data();
110
+ SingleResultHandler resi(res);
111
+
112
+ #pragma omp for
113
+ for (int64_t q = 0; q < static_cast<int64_t>(res.nq); q++) {
114
+ resi.begin(q);
115
+ dc->set_query(xq + d * q);
116
+
117
+ if (use_batch_scan) {
118
+ size_t i = 0;
119
+ for (; i + 16 <= ntotal; i += 16) {
120
+ bool keep[16];
121
+ bool keep_all = true;
122
+ for (size_t j = 0; j < 16; j++) {
123
+ keep[j] = res.is_in_selection(i + j);
124
+ keep_all &= keep[j];
125
+ }
126
+
127
+ if (keep_all) {
128
+ float dis[16];
129
+ dc->consecutive_distances_batch_16(i, dis);
130
+ for (size_t j = 0; j < 16; j++) {
131
+ resi.add_result(dis[j], i + j);
132
+ }
133
+ } else {
134
+ for (size_t j = 0; j < 16; j++) {
135
+ if (keep[j]) {
136
+ resi.add_result((*dc)(i + j), i + j);
137
+ }
138
+ }
139
+ }
140
+ }
141
+ for (; i + 8 <= ntotal; i += 8) {
142
+ const bool keep0 = res.is_in_selection(i);
143
+ const bool keep1 = res.is_in_selection(i + 1);
144
+ const bool keep2 = res.is_in_selection(i + 2);
145
+ const bool keep3 = res.is_in_selection(i + 3);
146
+ const bool keep4 = res.is_in_selection(i + 4);
147
+ const bool keep5 = res.is_in_selection(i + 5);
148
+ const bool keep6 = res.is_in_selection(i + 6);
149
+ const bool keep7 = res.is_in_selection(i + 7);
150
+ if (keep0 && keep1 && keep2 && keep3 && keep4 &&
151
+ keep5 && keep6 && keep7) {
152
+ float dis[8];
153
+ dc->consecutive_distances_batch_8(i, dis);
154
+ resi.add_result(dis[0], i);
155
+ resi.add_result(dis[1], i + 1);
156
+ resi.add_result(dis[2], i + 2);
157
+ resi.add_result(dis[3], i + 3);
158
+ resi.add_result(dis[4], i + 4);
159
+ resi.add_result(dis[5], i + 5);
160
+ resi.add_result(dis[6], i + 6);
161
+ resi.add_result(dis[7], i + 7);
162
+ } else {
163
+ if (keep0) {
164
+ resi.add_result((*dc)(i), i);
165
+ }
166
+ if (keep1) {
167
+ resi.add_result((*dc)(i + 1), i + 1);
168
+ }
169
+ if (keep2) {
170
+ resi.add_result((*dc)(i + 2), i + 2);
171
+ }
172
+ if (keep3) {
173
+ resi.add_result((*dc)(i + 3), i + 3);
174
+ }
175
+ if (keep4) {
176
+ resi.add_result((*dc)(i + 4), i + 4);
177
+ }
178
+ if (keep5) {
179
+ resi.add_result((*dc)(i + 5), i + 5);
180
+ }
181
+ if (keep6) {
182
+ resi.add_result((*dc)(i + 6), i + 6);
183
+ }
184
+ if (keep7) {
185
+ resi.add_result((*dc)(i + 7), i + 7);
186
+ }
187
+ }
188
+ }
189
+ for (; i + 4 <= ntotal; i += 4) {
190
+ const bool keep0 = res.is_in_selection(i);
191
+ const bool keep1 = res.is_in_selection(i + 1);
192
+ const bool keep2 = res.is_in_selection(i + 2);
193
+ const bool keep3 = res.is_in_selection(i + 3);
194
+ if (keep0 && keep1 && keep2 && keep3) {
195
+ float dis0;
196
+ float dis1;
197
+ float dis2;
198
+ float dis3;
199
+ dc->distances_batch_4(
200
+ i,
201
+ i + 1,
202
+ i + 2,
203
+ i + 3,
204
+ dis0,
205
+ dis1,
206
+ dis2,
207
+ dis3);
208
+ resi.add_result(dis0, i);
209
+ resi.add_result(dis1, i + 1);
210
+ resi.add_result(dis2, i + 2);
211
+ resi.add_result(dis3, i + 3);
212
+ } else {
213
+ if (keep0) {
214
+ resi.add_result((*dc)(i), i);
215
+ }
216
+ if (keep1) {
217
+ resi.add_result((*dc)(i + 1), i + 1);
218
+ }
219
+ if (keep2) {
220
+ resi.add_result((*dc)(i + 2), i + 2);
221
+ }
222
+ if (keep3) {
223
+ resi.add_result((*dc)(i + 3), i + 3);
224
+ }
225
+ }
226
+ }
227
+ for (; i < ntotal; i++) {
228
+ if (res.is_in_selection(i)) {
229
+ resi.add_result((*dc)(i), i);
230
+ }
231
+ }
232
+ } else {
233
+ for (size_t i = 0; i < ntotal; i++) {
234
+ if (res.is_in_selection(i)) {
235
+ resi.add_result((*dc)(i), i);
236
+ }
237
+ }
238
+ }
239
+
240
+ resi.end();
241
+ }
242
+ }
243
+ }
244
+ };
245
+
246
+ } // namespace
247
+
248
+ void IndexEDEN::search(
249
+ idx_t n,
250
+ const float* x,
251
+ idx_t k,
252
+ float* distances,
253
+ idx_t* labels,
254
+ const SearchParameters* params) const {
255
+ FAISS_THROW_IF_NOT(is_trained);
256
+ const IDSelector* sel = params != nullptr ? params->sel : nullptr;
257
+ Run_search_with_eden_dc r;
258
+ dispatch_knn_ResultHandler(
259
+ n, distances, labels, k, metric_type, sel, r, this, x);
260
+ }
261
+
262
+ void IndexEDEN::range_search(
263
+ idx_t /*n*/,
264
+ const float* x,
265
+ float radius,
266
+ RangeSearchResult* result,
267
+ const SearchParameters* params) const {
268
+ const IDSelector* sel = params != nullptr ? params->sel : nullptr;
269
+ Run_search_with_eden_dc r;
270
+ dispatch_range_ResultHandler(result, radius, metric_type, sel, r, this, x);
271
+ }
272
+
273
+ } // namespace faiss
@@ -0,0 +1,57 @@
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
+ #pragma once
9
+
10
+ #include <faiss/IndexFlatCodes.h>
11
+ #include <faiss/impl/EDENQuantizer.h>
12
+
13
+ namespace faiss {
14
+
15
+ struct IndexEDEN : IndexFlatCodes {
16
+ ScalarQuantizer sq;
17
+ EDENScaleType scale_type = EDENScaleType_UNBIASED;
18
+
19
+ // Center of all training points. Random rotation, if desired, is expected
20
+ // to be supplied externally via IndexPreTransform.
21
+ std::vector<float> center;
22
+
23
+ IndexEDEN();
24
+
25
+ // Factory strings: EDEN, EDEN<n>, EDENBIASED, EDEN<n>BIASED.
26
+ // <n> is the Lloyd-Max bit budget, 1..8. The default is EDEN's original
27
+ // unbiased scale; the BIASED suffix selects the MSE-minimizing scale.
28
+ explicit IndexEDEN(
29
+ idx_t d,
30
+ MetricType metric = METRIC_L2,
31
+ uint8_t nb_bits = 1,
32
+ EDENScaleType scale_type = EDENScaleType_UNBIASED);
33
+
34
+ void train(idx_t n, const float* x) override;
35
+
36
+ void sa_encode(idx_t n, const float* x, uint8_t* bytes) const override;
37
+ void sa_decode(idx_t n, const uint8_t* bytes, float* x) const override;
38
+
39
+ FlatCodesDistanceComputer* get_FlatCodesDistanceComputer() const override;
40
+
41
+ void search(
42
+ idx_t n,
43
+ const float* x,
44
+ idx_t k,
45
+ float* distances,
46
+ idx_t* labels,
47
+ const SearchParameters* params = nullptr) const override;
48
+
49
+ void range_search(
50
+ idx_t n,
51
+ const float* x,
52
+ float radius,
53
+ RangeSearchResult* result,
54
+ const SearchParameters* params = nullptr) const override;
55
+ };
56
+
57
+ } // namespace faiss
@@ -8,6 +8,7 @@
8
8
  #include <faiss/IndexFastScan.h>
9
9
 
10
10
  #include <omp.h>
11
+ #include <algorithm>
11
12
  #include <cstring>
12
13
  #include <memory>
13
14
 
@@ -266,8 +267,7 @@ void IndexFastScan::search(
266
267
  float* distances,
267
268
  idx_t* labels,
268
269
  const SearchParameters* params) const {
269
- FAISS_THROW_IF_NOT_MSG(
270
- !params, "search params not supported for this index");
270
+ FAISS_THROW_IF_MSG(params, "search params not supported for this index");
271
271
  FAISS_THROW_IF_NOT(k > 0);
272
272
 
273
273
  FastScanDistancePostProcessing empty_context{};
@@ -316,7 +316,7 @@ void IndexFastScan::search_dispatch_implem(
316
316
  if (implem == 1) {
317
317
  FAISS_THROW_MSG("not implemented");
318
318
  } else if (implem == 2 || implem == 3 || implem == 4) {
319
- FAISS_THROW_IF_NOT(orig_codes != nullptr);
319
+ FAISS_THROW_IF_NOT(orig_codes);
320
320
  search_implem_234<Cfloat>(n, x, k, distances, labels, context);
321
321
  } else if (impl >= 12 && impl <= 15) {
322
322
  FAISS_THROW_IF_NOT(ntotal < INT_MAX);
@@ -617,8 +617,19 @@ template void IndexFastScan::search_dispatch_implem<false>(
617
617
  const FastScanDistancePostProcessing& context) const;
618
618
 
619
619
  void IndexFastScan::reconstruct(idx_t key, float* recons) const {
620
- std::vector<uint8_t> code(code_size, 0);
620
+ FAISS_THROW_IF_NOT_FMT(
621
+ key >= 0 && key < ntotal,
622
+ "IndexFastScan::reconstruct: key %zd out of range (ntotal=%zd)",
623
+ (size_t)key,
624
+ (size_t)ntotal);
621
625
  std::unique_ptr<CodePacker> packer(get_CodePacker());
626
+ size_t block_no = (size_t)key / packer->nvec;
627
+ FAISS_THROW_IF_NOT_MSG(
628
+ mul_no_overflow(
629
+ block_no + 1, packer->block_size, "IndexFastScan codes") <=
630
+ codes.size(),
631
+ "IndexFastScan::reconstruct: packed codes buffer too small");
632
+ std::vector<uint8_t> code(std::max(code_size, packer->code_size), 0);
622
633
  packer->unpack_1(codes.data(), key, code.data());
623
634
  sa_decode(1, code.data(), recons);
624
635
  }
@@ -77,7 +77,8 @@ void IndexFlat::range_search(
77
77
  range_search_L2sqr(x, get_xb(), d, n, ntotal, radius, result, sel);
78
78
  break;
79
79
  default:
80
- FAISS_THROW_MSG("metric type not supported");
80
+ IndexFlatCodes::range_search(n, x, radius, result, params);
81
+ break;
81
82
  }
82
83
  }
83
84
 
@@ -105,13 +106,8 @@ namespace {
105
106
  template <SIMDLevel SL>
106
107
  struct FlatL2Dis : FlatCodesDistanceComputer {
107
108
  size_t d;
108
- idx_t nb;
109
- const float* b;
110
- size_t ndis;
111
- size_t npartial_dot_products;
112
109
 
113
110
  float distance_to_code(const uint8_t* code) final {
114
- ndis++;
115
111
  return fvec_L2sqr<SL>(q, (float*)code, d);
116
112
  }
117
113
 
@@ -119,25 +115,21 @@ struct FlatL2Dis : FlatCodesDistanceComputer {
119
115
  const idx_t i,
120
116
  const uint32_t offset,
121
117
  const uint32_t num_components) final override {
122
- npartial_dot_products++;
118
+ const float* b = (const float*)this->codes;
123
119
  return fvec_inner_product<SL>(
124
120
  q + offset, b + i * d + offset, num_components);
125
121
  }
126
122
 
127
123
  float symmetric_dis(idx_t i, idx_t j) override {
124
+ const float* b = (const float*)this->codes;
128
125
  return fvec_L2sqr<SL>(b + j * d, b + i * d, d);
129
126
  }
130
127
 
131
- explicit FlatL2Dis(const IndexFlat& storage, const float* q_ = nullptr)
128
+ explicit FlatL2Dis(const IndexFlat& storage)
132
129
  : FlatCodesDistanceComputer(
133
130
  storage.codes.data(),
134
- storage.code_size,
135
- q_),
136
- d(storage.d),
137
- nb(storage.ntotal),
138
- b(storage.get_xb()),
139
- ndis(0),
140
- npartial_dot_products(0) {}
131
+ storage.code_size),
132
+ d(storage.d) {}
141
133
 
142
134
  void set_query(const float* x) override {
143
135
  q = x;
@@ -153,8 +145,6 @@ struct FlatL2Dis : FlatCodesDistanceComputer {
153
145
  float& dis1,
154
146
  float& dis2,
155
147
  float& dis3) final override {
156
- ndis += 4;
157
-
158
148
  // compute first, assign next
159
149
  const float* __restrict y0 =
160
150
  reinterpret_cast<const float*>(codes + idx0 * code_size);
@@ -187,8 +177,6 @@ struct FlatL2Dis : FlatCodesDistanceComputer {
187
177
  float& dp3,
188
178
  const uint32_t offset,
189
179
  const uint32_t num_components) final override {
190
- npartial_dot_products += 4;
191
-
192
180
  // compute first, assign next
193
181
  const float* __restrict y0 =
194
182
  reinterpret_cast<const float*>(codes + idx0 * code_size);
@@ -224,29 +212,21 @@ struct FlatL2Dis : FlatCodesDistanceComputer {
224
212
  template <SIMDLevel SL>
225
213
  struct FlatIPDis : FlatCodesDistanceComputer {
226
214
  size_t d;
227
- idx_t nb;
228
- const float* q;
229
- const float* b;
230
- size_t ndis;
231
215
 
232
216
  float symmetric_dis(idx_t i, idx_t j) final override {
217
+ const float* b = (const float*)this->codes;
233
218
  return fvec_inner_product<SL>(b + j * d, b + i * d, d);
234
219
  }
235
220
 
236
221
  float distance_to_code(const uint8_t* code) final override {
237
- ndis++;
238
222
  return fvec_inner_product<SL>(q, (const float*)code, d);
239
223
  }
240
224
 
241
- explicit FlatIPDis(const IndexFlat& storage, const float* q_in = nullptr)
225
+ explicit FlatIPDis(const IndexFlat& storage)
242
226
  : FlatCodesDistanceComputer(
243
227
  storage.codes.data(),
244
228
  storage.code_size),
245
- d(storage.d),
246
- nb(storage.ntotal),
247
- q(q_in),
248
- b(storage.get_xb()),
249
- ndis(0) {}
229
+ d(storage.d) {}
250
230
 
251
231
  void set_query(const float* x) override {
252
232
  q = x;
@@ -262,8 +242,6 @@ struct FlatIPDis : FlatCodesDistanceComputer {
262
242
  float& dis1,
263
243
  float& dis2,
264
244
  float& dis3) final override {
265
- ndis += 4;
266
-
267
245
  // compute first, assign next
268
246
  const float* __restrict y0 =
269
247
  reinterpret_cast<const float*>(codes + idx0 * code_size);
@@ -292,12 +270,13 @@ struct FlatIPDis : FlatCodesDistanceComputer {
292
270
  FlatCodesDistanceComputer* IndexFlat::get_FlatCodesDistanceComputer() const {
293
271
  FlatCodesDistanceComputer* dc = nullptr;
294
272
  if (metric_type == METRIC_L2) {
295
- with_simd_level([&]<SIMDLevel SL>() { dc = new FlatL2Dis<SL>(*this); });
273
+ with_simd_level_with_sve(
274
+ [&]<SIMDLevel SL>() { dc = new FlatL2Dis<SL>(*this); });
296
275
  } else if (metric_type == METRIC_INNER_PRODUCT) {
297
- with_simd_level([&]<SIMDLevel SL>() { dc = new FlatIPDis<SL>(*this); });
276
+ with_simd_level_with_sve(
277
+ [&]<SIMDLevel SL>() { dc = new FlatIPDis<SL>(*this); });
298
278
  } else {
299
- dc = get_extra_distance_computer(
300
- d, metric_type, metric_arg, ntotal, get_xb());
279
+ dc = get_extra_distance_computer(d, metric_type, metric_arg, get_xb());
301
280
  }
302
281
  return dc;
303
282
  }
@@ -327,16 +306,11 @@ namespace {
327
306
  template <SIMDLevel SL>
328
307
  struct FlatL2WithNormsDis : FlatCodesDistanceComputer {
329
308
  size_t d;
330
- idx_t nb;
331
- const float* q;
332
- const float* b;
333
- size_t ndis;
334
309
 
335
310
  const float* l2norms;
336
311
  float query_l2norm;
337
312
 
338
313
  float distance_to_code(const uint8_t* code) final override {
339
- ndis++;
340
314
  return fvec_L2sqr<SL>(q, (float*)code, d);
341
315
  }
342
316
 
@@ -361,17 +335,11 @@ struct FlatL2WithNormsDis : FlatCodesDistanceComputer {
361
335
  return l2norms[i] + l2norms[j] - 2 * dp0;
362
336
  }
363
337
 
364
- explicit FlatL2WithNormsDis(
365
- const IndexFlatL2& storage,
366
- const float* q_in = nullptr)
338
+ explicit FlatL2WithNormsDis(const IndexFlatL2& storage)
367
339
  : FlatCodesDistanceComputer(
368
340
  storage.codes.data(),
369
341
  storage.code_size),
370
342
  d(storage.d),
371
- nb(storage.ntotal),
372
- q(q_in),
373
- b(storage.get_xb()),
374
- ndis(0),
375
343
  l2norms(storage.cached_l2norms.data()),
376
344
  query_l2norm(0) {}
377
345
 
@@ -390,8 +358,6 @@ struct FlatL2WithNormsDis : FlatCodesDistanceComputer {
390
358
  float& dis1,
391
359
  float& dis2,
392
360
  float& dis3) final override {
393
- ndis += 4;
394
-
395
361
  // compute first, assign next
396
362
  const float* __restrict y0 =
397
363
  reinterpret_cast<const float*>(codes + idx0 * code_size);
@@ -440,7 +406,7 @@ FlatCodesDistanceComputer* IndexFlatL2::get_FlatCodesDistanceComputer() const {
440
406
  if (metric_type == METRIC_L2) {
441
407
  if (!cached_l2norms.empty()) {
442
408
  FlatCodesDistanceComputer* dc = nullptr;
443
- with_simd_level([&]<SIMDLevel SL>() {
409
+ with_simd_level_with_sve([&]<SIMDLevel SL>() {
444
410
  dc = new FlatL2WithNormsDis<SL>(*this);
445
411
  });
446
412
  return dc;
@@ -487,8 +453,7 @@ void IndexFlat1D::search(
487
453
  float* distances,
488
454
  idx_t* labels,
489
455
  const SearchParameters* params) const {
490
- FAISS_THROW_IF_NOT_MSG(
491
- !params, "search params not supported for this index");
456
+ FAISS_THROW_IF_MSG(params, "search params not supported for this index");
492
457
  FAISS_THROW_IF_NOT(k > 0);
493
458
  FAISS_THROW_IF_NOT_MSG(
494
459
  perm.size() == static_cast<size_t>(ntotal),
@@ -741,10 +706,12 @@ void IndexFlatPanorama::reset() {
741
706
  }
742
707
 
743
708
  void IndexFlatPanorama::reconstruct(idx_t key, float* recons) const {
709
+ FAISS_THROW_IF_NOT(key >= 0 && key < ntotal);
744
710
  pano.reconstruct(key, recons, codes.data());
745
711
  }
746
712
 
747
713
  void IndexFlatPanorama::reconstruct_n(idx_t i, idx_t n, float* recons) const {
714
+ FAISS_THROW_IF_NOT(i >= 0 && i <= ntotal && n >= 0 && n <= ntotal - i);
748
715
  Index::reconstruct_n(i, n, recons);
749
716
  }
750
717
 
@@ -821,7 +788,7 @@ void IndexFlatPanorama::search_subset(
821
788
  idx_t k,
822
789
  float* distances,
823
790
  idx_t* labels) const {
824
- with_simd_level([&]<SIMDLevel SL>() {
791
+ with_simd_level_with_sve([&]<SIMDLevel SL>() {
825
792
  with_metric_type(metric_type, [&]<MetricType M>() {
826
793
  constexpr bool is_sim = is_similarity_metric(M);
827
794
  using C = std::conditional_t<
@@ -176,7 +176,7 @@ struct IndexFlatL2Panorama : IndexFlatPanorama {
176
176
  explicit IndexFlatL2Panorama(
177
177
  idx_t d_in,
178
178
  size_t n_levels_in,
179
- size_t batch_size_in = 512)
179
+ size_t batch_size_in = Panorama::kDefaultBatchSize)
180
180
  : IndexFlatPanorama(d_in, METRIC_L2, n_levels_in, batch_size_in) {}
181
181
  };
182
182
 
@@ -189,7 +189,7 @@ struct IndexFlatIPPanorama : IndexFlatPanorama {
189
189
  explicit IndexFlatIPPanorama(
190
190
  idx_t d_in,
191
191
  size_t n_levels_in,
192
- size_t batch_size_in = 512)
192
+ size_t batch_size_in = Panorama::kDefaultBatchSize)
193
193
  : IndexFlatPanorama(
194
194
  d_in,
195
195
  METRIC_INNER_PRODUCT,