faiss 0.5.3 → 0.6.1

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 (379) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/ext/faiss/ext.cpp +1 -1
  4. data/ext/faiss/extconf.rb +4 -4
  5. data/ext/faiss/index.cpp +63 -45
  6. data/ext/faiss/index_binary.cpp +37 -27
  7. data/ext/faiss/kmeans.cpp +9 -8
  8. data/ext/faiss/pca_matrix.cpp +9 -7
  9. data/ext/faiss/product_quantizer.cpp +13 -11
  10. data/ext/faiss/utils.cpp +4 -2
  11. data/ext/faiss/utils.h +4 -0
  12. data/lib/faiss/version.rb +1 -1
  13. data/lib/faiss.rb +1 -1
  14. data/vendor/faiss/faiss/AutoTune.cpp +214 -82
  15. data/vendor/faiss/faiss/AutoTune.h +14 -1
  16. data/vendor/faiss/faiss/Clustering.cpp +97 -249
  17. data/vendor/faiss/faiss/Clustering.h +18 -0
  18. data/vendor/faiss/faiss/IVFlib.cpp +67 -44
  19. data/vendor/faiss/faiss/Index.cpp +25 -12
  20. data/vendor/faiss/faiss/Index.h +26 -4
  21. data/vendor/faiss/faiss/Index2Layer.cpp +37 -53
  22. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +68 -61
  23. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +36 -34
  24. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +4 -1
  25. data/vendor/faiss/faiss/IndexBinary.cpp +6 -3
  26. data/vendor/faiss/faiss/IndexBinary.h +4 -4
  27. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +1 -1
  28. data/vendor/faiss/faiss/IndexBinaryFlat.h +1 -1
  29. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -4
  30. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +92 -95
  31. data/vendor/faiss/faiss/IndexBinaryHNSW.h +9 -3
  32. data/vendor/faiss/faiss/IndexBinaryHash.cpp +45 -236
  33. data/vendor/faiss/faiss/IndexBinaryHash.h +6 -6
  34. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +120 -414
  35. data/vendor/faiss/faiss/IndexFastScan.cpp +105 -129
  36. data/vendor/faiss/faiss/IndexFastScan.h +35 -24
  37. data/vendor/faiss/faiss/IndexFlat.cpp +216 -152
  38. data/vendor/faiss/faiss/IndexFlat.h +32 -14
  39. data/vendor/faiss/faiss/IndexFlatCodes.cpp +88 -41
  40. data/vendor/faiss/faiss/IndexFlatCodes.h +7 -1
  41. data/vendor/faiss/faiss/IndexHNSW.cpp +299 -187
  42. data/vendor/faiss/faiss/IndexHNSW.h +30 -14
  43. data/vendor/faiss/faiss/IndexIDMap.cpp +26 -22
  44. data/vendor/faiss/faiss/IndexIDMap.h +9 -7
  45. data/vendor/faiss/faiss/IndexIVF.cpp +535 -405
  46. data/vendor/faiss/faiss/IndexIVF.h +47 -16
  47. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +77 -74
  48. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +105 -99
  49. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +6 -3
  50. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +379 -249
  51. data/vendor/faiss/faiss/IndexIVFFastScan.h +65 -60
  52. data/vendor/faiss/faiss/IndexIVFFlat.cpp +41 -124
  53. data/vendor/faiss/faiss/IndexIVFFlat.h +32 -0
  54. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +89 -138
  55. data/vendor/faiss/faiss/IndexIVFFlatPanorama.h +3 -1
  56. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +18 -15
  57. data/vendor/faiss/faiss/IndexIVFPQ.cpp +77 -907
  58. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +184 -122
  59. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +3 -0
  60. data/vendor/faiss/faiss/IndexIVFPQR.cpp +23 -18
  61. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +59 -60
  62. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +4 -3
  63. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +564 -416
  64. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +269 -111
  65. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +41 -127
  66. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +1 -1
  67. data/vendor/faiss/faiss/IndexLSH.cpp +44 -25
  68. data/vendor/faiss/faiss/IndexLattice.cpp +41 -36
  69. data/vendor/faiss/faiss/IndexNNDescent.cpp +37 -21
  70. data/vendor/faiss/faiss/IndexNNDescent.h +2 -2
  71. data/vendor/faiss/faiss/IndexNSG.cpp +40 -23
  72. data/vendor/faiss/faiss/IndexNSG.h +0 -2
  73. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +32 -12
  74. data/vendor/faiss/faiss/IndexPQ.cpp +129 -213
  75. data/vendor/faiss/faiss/IndexPQ.h +3 -2
  76. data/vendor/faiss/faiss/IndexPQFastScan.cpp +20 -14
  77. data/vendor/faiss/faiss/IndexPQFastScan.h +3 -0
  78. data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -18
  79. data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
  80. data/vendor/faiss/faiss/IndexRaBitQ.cpp +31 -43
  81. data/vendor/faiss/faiss/IndexRaBitQ.h +4 -3
  82. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +135 -317
  83. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +192 -34
  84. data/vendor/faiss/faiss/IndexRefine.cpp +30 -55
  85. data/vendor/faiss/faiss/IndexRefine.h +4 -4
  86. data/vendor/faiss/faiss/IndexReplicas.cpp +6 -6
  87. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +15 -14
  88. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +1 -1
  89. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +82 -14
  90. data/vendor/faiss/faiss/IndexShards.cpp +13 -13
  91. data/vendor/faiss/faiss/IndexShardsIVF.cpp +21 -15
  92. data/vendor/faiss/faiss/MatrixStats.cpp +5 -4
  93. data/vendor/faiss/faiss/MetaIndexes.cpp +19 -17
  94. data/vendor/faiss/faiss/MetaIndexes.h +1 -1
  95. data/vendor/faiss/faiss/MetricType.h +29 -6
  96. data/vendor/faiss/faiss/SuperKMeans.cpp +656 -0
  97. data/vendor/faiss/faiss/SuperKMeans.h +97 -0
  98. data/vendor/faiss/faiss/VectorTransform.cpp +349 -141
  99. data/vendor/faiss/faiss/VectorTransform.h +39 -16
  100. data/vendor/faiss/faiss/build.cpp +23 -0
  101. data/vendor/faiss/faiss/build.h +15 -0
  102. data/vendor/faiss/faiss/clone_index.cpp +55 -51
  103. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +47 -47
  104. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +11 -0
  105. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +38 -38
  106. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +11 -0
  107. data/vendor/faiss/faiss/{cppcontrib/factory_tools.cpp → factory_tools.cpp} +6 -1
  108. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +1 -1
  109. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +6 -5
  110. data/vendor/faiss/faiss/gpu/GpuResources.h +1 -1
  111. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +9 -9
  112. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +4 -3
  113. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +46 -0
  114. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +56 -0
  115. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +78 -1
  116. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +72 -0
  117. data/vendor/faiss/faiss/gpu/test/TestUtils.h +23 -0
  118. data/vendor/faiss/faiss/gpu/utils/CuvsFilterConvert.h +1 -1
  119. data/vendor/faiss/faiss/gpu/utils/CuvsUtils.h +21 -10
  120. data/vendor/faiss/faiss/gpu_metal/GpuIndexFlat.h +22 -0
  121. data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +35 -0
  122. data/vendor/faiss/faiss/gpu_metal/MetalFlatKernels.h +40 -0
  123. data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +51 -0
  124. data/vendor/faiss/faiss/gpu_metal/MetalIndexFlat.h +65 -0
  125. data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +66 -0
  126. data/vendor/faiss/faiss/gpu_metal/MetalResources.h +79 -0
  127. data/vendor/faiss/faiss/gpu_metal/StandardMetalResources.h +35 -0
  128. data/vendor/faiss/faiss/impl/AdSampling.cpp +103 -0
  129. data/vendor/faiss/faiss/impl/AdSampling.h +35 -0
  130. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +64 -34
  131. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +1 -0
  132. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +10 -9
  133. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +3 -28
  134. data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +244 -0
  135. data/vendor/faiss/faiss/impl/ClusteringHelpers.h +94 -0
  136. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +367 -0
  137. data/vendor/faiss/faiss/impl/ClusteringInitialization.h +107 -0
  138. data/vendor/faiss/faiss/impl/CodePacker.cpp +7 -3
  139. data/vendor/faiss/faiss/impl/CodePacker.h +11 -3
  140. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +83 -0
  141. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.h +47 -0
  142. data/vendor/faiss/faiss/impl/DistanceComputer.h +8 -8
  143. data/vendor/faiss/faiss/impl/FaissAssert.h +64 -3
  144. data/vendor/faiss/faiss/impl/FaissException.h +50 -3
  145. data/vendor/faiss/faiss/impl/HNSW.cpp +117 -351
  146. data/vendor/faiss/faiss/impl/HNSW.h +21 -40
  147. data/vendor/faiss/faiss/impl/IDSelector.cpp +15 -11
  148. data/vendor/faiss/faiss/impl/IDSelector.h +8 -8
  149. data/vendor/faiss/faiss/impl/InvertedListScannerStats.h +26 -0
  150. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +114 -102
  151. data/vendor/faiss/faiss/impl/NNDescent.cpp +63 -26
  152. data/vendor/faiss/faiss/impl/NNDescent.h +6 -2
  153. data/vendor/faiss/faiss/impl/NSG.cpp +44 -26
  154. data/vendor/faiss/faiss/impl/NSG.h +20 -10
  155. data/vendor/faiss/faiss/impl/Panorama.cpp +76 -52
  156. data/vendor/faiss/faiss/impl/Panorama.h +265 -78
  157. data/vendor/faiss/faiss/impl/PdxLayout.cpp +93 -0
  158. data/vendor/faiss/faiss/impl/PdxLayout.h +41 -0
  159. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +62 -37
  160. data/vendor/faiss/faiss/impl/PolysemousTraining.h +3 -3
  161. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +35 -35
  162. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +21 -16
  163. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +99 -80
  164. data/vendor/faiss/faiss/impl/Quantizer.h +2 -2
  165. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +135 -37
  166. data/vendor/faiss/faiss/impl/RaBitQUtils.h +148 -21
  167. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +298 -301
  168. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +3 -10
  169. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +15 -41
  170. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.h +0 -4
  171. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +40 -32
  172. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
  173. data/vendor/faiss/faiss/impl/ResultHandler.h +218 -113
  174. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +119 -2362
  175. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +27 -3
  176. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +14 -11
  177. data/vendor/faiss/faiss/impl/VisitedTable.cpp +42 -0
  178. data/vendor/faiss/faiss/impl/VisitedTable.h +76 -0
  179. data/vendor/faiss/faiss/impl/approx_topk/approx_topk.h +276 -0
  180. data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +68 -0
  181. data/vendor/faiss/faiss/{utils → impl}/approx_topk/generic.h +15 -8
  182. data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +68 -0
  183. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab-inl.h +169 -0
  184. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab.h +117 -0
  185. data/vendor/faiss/faiss/impl/approx_topk/simdlib256-inl.h +146 -0
  186. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h +73 -0
  187. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +270 -0
  188. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +460 -0
  189. data/vendor/faiss/faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h +159 -0
  190. data/vendor/faiss/faiss/impl/binary_hamming/IndexPQ_impl.h +92 -0
  191. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +26 -0
  192. data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +26 -0
  193. data/vendor/faiss/faiss/impl/binary_hamming/dispatch.h +143 -0
  194. data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +26 -0
  195. data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +26 -0
  196. data/vendor/faiss/faiss/impl/expanded_scanners.h +163 -0
  197. data/vendor/faiss/faiss/impl/{FastScanDistancePostProcessing.h → fast_scan/FastScanDistancePostProcessing.h} +13 -6
  198. data/vendor/faiss/faiss/impl/{LookupTableScaler.h → fast_scan/LookupTableScaler.h} +16 -5
  199. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +237 -0
  200. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +185 -0
  201. data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +229 -0
  202. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +268 -0
  203. data/vendor/faiss/faiss/impl/{pq4_fast_scan.cpp → fast_scan/fast_scan.cpp} +176 -4
  204. data/vendor/faiss/faiss/impl/fast_scan/fast_scan.h +341 -0
  205. data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +36 -0
  206. data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +40 -0
  207. data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +120 -0
  208. data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +104 -0
  209. data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +213 -0
  210. data/vendor/faiss/faiss/impl/{pq4_fast_scan_search_qbs.cpp → fast_scan/kernels_simd512.h} +26 -348
  211. data/vendor/faiss/faiss/impl/fast_scan/rabitq_dispatching.h +90 -0
  212. data/vendor/faiss/faiss/impl/fast_scan/rabitq_result_handler.h +108 -0
  213. data/vendor/faiss/faiss/impl/{simd_result_handlers.h → fast_scan/simd_result_handlers.h} +290 -142
  214. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +54 -0
  215. data/vendor/faiss/faiss/impl/hnsw/LockVector.h +64 -0
  216. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +91 -0
  217. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -0
  218. data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +104 -0
  219. data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +111 -0
  220. data/vendor/faiss/faiss/impl/index_read.cpp +1950 -505
  221. data/vendor/faiss/faiss/impl/index_read_utils.h +1 -2
  222. data/vendor/faiss/faiss/impl/index_write.cpp +112 -21
  223. data/vendor/faiss/faiss/impl/io.cpp +6 -6
  224. data/vendor/faiss/faiss/impl/io_macros.h +33 -16
  225. data/vendor/faiss/faiss/impl/kmeans1d.cpp +10 -10
  226. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +81 -40
  227. data/vendor/faiss/faiss/impl/lattice_Zn.h +6 -6
  228. data/vendor/faiss/faiss/impl/mapped_io.cpp +15 -8
  229. data/vendor/faiss/faiss/impl/platform_macros.h +11 -4
  230. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +549 -0
  231. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +245 -0
  232. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.h +105 -0
  233. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +106 -0
  234. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +21 -0
  235. data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +21 -0
  236. data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +21 -0
  237. data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx2.h → pq_code_distance/pq_code_distance-avx2.h} +43 -220
  238. data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx512.h → pq_code_distance/pq_code_distance-avx512.h} +25 -112
  239. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +59 -0
  240. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +96 -0
  241. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +256 -0
  242. data/vendor/faiss/faiss/impl/{code_distance/code_distance-sve.h → pq_code_distance/pq_code_distance-sve.cpp} +57 -146
  243. data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +68 -0
  244. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +320 -483
  245. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
  246. data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +121 -0
  247. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +137 -0
  248. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +371 -0
  249. data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +190 -0
  250. data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +94 -0
  251. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +603 -0
  252. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +597 -0
  253. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +388 -0
  254. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +630 -0
  255. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +311 -0
  256. data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +387 -0
  257. data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +54 -0
  258. data/vendor/faiss/faiss/impl/simd_dispatch.h +173 -0
  259. data/vendor/faiss/faiss/impl/simdlib/simdlib.h +57 -0
  260. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_avx2.h +274 -171
  261. data/vendor/faiss/faiss/impl/simdlib/simdlib_avx512.h +414 -0
  262. data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +44 -0
  263. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_emulated.h +231 -166
  264. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_neon.h +275 -217
  265. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_ppc64.h +201 -160
  266. data/vendor/faiss/faiss/impl/svs_io.cpp +12 -3
  267. data/vendor/faiss/faiss/impl/svs_io.h +8 -2
  268. data/vendor/faiss/faiss/index_factory.cpp +115 -28
  269. data/vendor/faiss/faiss/index_io.h +53 -3
  270. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +73 -20
  271. data/vendor/faiss/faiss/invlists/DirectMap.cpp +24 -14
  272. data/vendor/faiss/faiss/invlists/DirectMap.h +4 -3
  273. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +157 -73
  274. data/vendor/faiss/faiss/invlists/InvertedLists.h +86 -23
  275. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +4 -4
  276. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +14 -14
  277. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  278. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +9 -19
  279. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +2 -2
  280. data/vendor/faiss/faiss/svs/IndexSVSFlat.h +2 -0
  281. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +350 -0
  282. data/vendor/faiss/faiss/svs/IndexSVSIVF.h +128 -0
  283. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.cpp +40 -0
  284. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.h +43 -0
  285. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +225 -0
  286. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.h +71 -0
  287. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +25 -1
  288. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +19 -2
  289. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +1 -1
  290. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +19 -2
  291. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +14 -0
  292. data/vendor/faiss/faiss/utils/Heap.cpp +56 -10
  293. data/vendor/faiss/faiss/utils/Heap.h +21 -0
  294. data/vendor/faiss/faiss/utils/NeuralNet.cpp +54 -40
  295. data/vendor/faiss/faiss/utils/NeuralNet.h +1 -1
  296. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +10 -4
  297. data/vendor/faiss/faiss/utils/distances.cpp +507 -559
  298. data/vendor/faiss/faiss/utils/distances.h +118 -1
  299. data/vendor/faiss/faiss/utils/distances_dispatch.h +250 -0
  300. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +8 -7
  301. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +33 -14
  302. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +12 -1
  303. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +16 -293
  304. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +57 -0
  305. data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +290 -0
  306. data/vendor/faiss/faiss/utils/distances_simd.cpp +72 -3681
  307. data/vendor/faiss/faiss/utils/extra_distances.cpp +60 -102
  308. data/vendor/faiss/faiss/utils/extra_distances.h +79 -7
  309. data/vendor/faiss/faiss/utils/hamming-inl.h +13 -11
  310. data/vendor/faiss/faiss/utils/hamming.cpp +66 -517
  311. data/vendor/faiss/faiss/utils/hamming.h +92 -2
  312. data/vendor/faiss/faiss/utils/hamming_distance/common.h +287 -10
  313. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +15 -0
  314. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +15 -0
  315. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx2.h +142 -0
  316. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +234 -0
  317. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-generic.h +368 -0
  318. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-neon.h +322 -0
  319. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-rvv.h +39 -0
  320. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer.h +146 -0
  321. data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +481 -0
  322. data/vendor/faiss/faiss/utils/hamming_distance/hamming_neon.cpp +15 -0
  323. data/vendor/faiss/faiss/utils/hamming_distance/hamming_rvv.cpp +15 -0
  324. data/vendor/faiss/faiss/utils/partitioning.cpp +66 -987
  325. data/vendor/faiss/faiss/utils/partitioning.h +31 -0
  326. data/vendor/faiss/faiss/utils/popcount.h +29 -0
  327. data/vendor/faiss/faiss/utils/pq_code_distance.h +251 -0
  328. data/vendor/faiss/faiss/utils/prefetch.h +2 -2
  329. data/vendor/faiss/faiss/utils/quantize_lut.cpp +30 -30
  330. data/vendor/faiss/faiss/utils/quantize_lut.h +1 -1
  331. data/vendor/faiss/faiss/utils/rabitq_simd.h +124 -343
  332. data/vendor/faiss/faiss/utils/random.cpp +6 -6
  333. data/vendor/faiss/faiss/utils/simd_impl/IVFFlatScanner-inl.h +51 -0
  334. data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +154 -0
  335. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +777 -0
  336. data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +306 -0
  337. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +1431 -0
  338. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +1095 -0
  339. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +189 -0
  340. data/vendor/faiss/faiss/utils/simd_impl/distances_simdlib256.h +195 -0
  341. data/vendor/faiss/faiss/utils/simd_impl/distances_sse-inl.h +392 -0
  342. data/vendor/faiss/faiss/utils/{distances_fused/simdlib_based.h → simd_impl/exhaustive_L2sqr_blas_cmax.h} +5 -10
  343. data/vendor/faiss/faiss/utils/simd_impl/hamming_impl.h +481 -0
  344. data/vendor/faiss/faiss/utils/simd_impl/partitioning_avx2.cpp +14 -0
  345. data/vendor/faiss/faiss/utils/simd_impl/partitioning_neon.cpp +14 -0
  346. data/vendor/faiss/faiss/utils/simd_impl/partitioning_simdlib256.h +1085 -0
  347. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +355 -0
  348. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +477 -0
  349. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +55 -0
  350. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +55 -0
  351. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +32 -0
  352. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +43 -0
  353. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +57 -0
  354. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +45 -0
  355. data/vendor/faiss/faiss/utils/simd_levels.cpp +334 -0
  356. data/vendor/faiss/faiss/utils/simd_levels.h +183 -0
  357. data/vendor/faiss/faiss/utils/sorting.cpp +48 -36
  358. data/vendor/faiss/faiss/utils/utils.cpp +21 -14
  359. data/vendor/faiss/faiss/utils/utils.h +3 -3
  360. metadata +156 -42
  361. data/vendor/faiss/faiss/impl/RaBitQStats.cpp +0 -29
  362. data/vendor/faiss/faiss/impl/RaBitQStats.h +0 -56
  363. data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +0 -81
  364. data/vendor/faiss/faiss/impl/code_distance/code_distance.h +0 -186
  365. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +0 -216
  366. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +0 -224
  367. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +0 -84
  368. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +0 -196
  369. data/vendor/faiss/faiss/utils/approx_topk/mode.h +0 -34
  370. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +0 -36
  371. data/vendor/faiss/faiss/utils/extra_distances-inl.h +0 -228
  372. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +0 -462
  373. data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +0 -490
  374. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -450
  375. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +0 -87
  376. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +0 -524
  377. data/vendor/faiss/faiss/utils/simdlib.h +0 -42
  378. data/vendor/faiss/faiss/utils/simdlib_avx512.h +0 -296
  379. /data/vendor/faiss/faiss/{cppcontrib/factory_tools.h → factory_tools.h} +0 -0
@@ -19,6 +19,7 @@
19
19
  #include <faiss/IndexFlat.h>
20
20
  #include <faiss/VectorTransform.h>
21
21
  #include <faiss/impl/FaissAssert.h>
22
+ #include <faiss/impl/simd_dispatch.h>
22
23
  #include <faiss/utils/distances.h>
23
24
 
24
25
  extern "C" {
@@ -47,8 +48,8 @@ namespace faiss {
47
48
  * PQ implementation
48
49
  *********************************************/
49
50
 
50
- ProductQuantizer::ProductQuantizer(size_t d, size_t M, size_t nbits)
51
- : Quantizer(d, 0), M(M), nbits(nbits), assign_index(nullptr) {
51
+ ProductQuantizer::ProductQuantizer(size_t d_in, size_t M_in, size_t nbits_in)
52
+ : Quantizer(d_in, 0), M(M_in), nbits(nbits_in), assign_index(nullptr) {
52
53
  set_derived_values();
53
54
  }
54
55
 
@@ -56,14 +57,15 @@ ProductQuantizer::ProductQuantizer() : ProductQuantizer(0, 1, 0) {}
56
57
 
57
58
  void ProductQuantizer::set_derived_values() {
58
59
  // quite a few derived values
60
+ FAISS_THROW_IF_NOT_MSG(M > 0, "M must be > 0");
59
61
  FAISS_THROW_IF_NOT_MSG(
60
62
  d % M == 0,
61
63
  "The dimension of the vector (d) should be a multiple of the number of subquantizers (M)");
62
64
  dsub = d / M;
63
- code_size = (nbits * M + 7) / 8;
64
65
  FAISS_THROW_IF_MSG(nbits > 24, "nbits larger than 24 is not practical.");
66
+ code_size = (nbits * M + 7) / 8;
65
67
  ksub = 1 << nbits;
66
- centroids.resize(d * ksub);
68
+ centroids.resize(mul_no_overflow(d, (size_t)ksub, "PQ centroids"));
67
69
  verbose = false;
68
70
  train_type = Train_default;
69
71
  }
@@ -137,8 +139,8 @@ void ProductQuantizer::train(size_t n, const float* x) {
137
139
  }
138
140
 
139
141
  std::unique_ptr<float[]> xslice(new float[n * dsub]);
140
- for (int m = 0; m < M; m++) {
141
- for (int j = 0; j < n; j++)
142
+ for (size_t m = 0; m < M; m++) {
143
+ for (size_t j = 0; j < n; j++)
142
144
  memcpy(xslice.get() + j * dsub,
143
145
  x + j * d + m * dsub,
144
146
  dsub * sizeof(float));
@@ -177,7 +179,7 @@ void ProductQuantizer::train(size_t n, const float* x) {
177
179
 
178
180
  if (verbose) {
179
181
  clus.verbose = true;
180
- printf("Training PQ slice %d/%zd\n", m, M);
182
+ printf("Training PQ slice %zd/%zd\n", m, M);
181
183
  }
182
184
  IndexFlatL2 index(dsub);
183
185
  clus.train(n, xslice.get(), assign_index ? *assign_index : index);
@@ -195,14 +197,16 @@ void ProductQuantizer::train(size_t n, const float* x) {
195
197
  IndexFlatL2 index(dsub);
196
198
 
197
199
  clus.train(n * M, x, assign_index ? *assign_index : index);
198
- for (int m = 0; m < M; m++) {
200
+ for (size_t m = 0; m < M; m++) {
199
201
  set_params(clus.centroids.data(), m);
200
202
  }
201
203
  }
202
204
  }
203
205
 
204
- template <class PQEncoder>
205
- void compute_code(const ProductQuantizer& pq, const float* x, uint8_t* code) {
206
+ namespace {
207
+
208
+ template <class PQEncoder, SIMDLevel SL>
209
+ void compute_1_code(const ProductQuantizer& pq, const float* x, uint8_t* code) {
206
210
  std::vector<float> distances(pq.ksub);
207
211
 
208
212
  // It seems to be meaningless to allocate std::vector<float> distances.
@@ -248,7 +252,7 @@ void compute_code(const ProductQuantizer& pq, const float* x, uint8_t* code) {
248
252
  uint64_t idxm = 0;
249
253
  if (pq.transposed_centroids.empty()) {
250
254
  // the regular version
251
- idxm = fvec_L2sqr_ny_nearest(
255
+ idxm = fvec_L2sqr_ny_nearest<SL>(
252
256
  distances.data(),
253
257
  xsub,
254
258
  pq.get_centroids(m, 0),
@@ -256,7 +260,7 @@ void compute_code(const ProductQuantizer& pq, const float* x, uint8_t* code) {
256
260
  pq.ksub);
257
261
  } else {
258
262
  // transposed centroids are available, use'em
259
- idxm = fvec_L2sqr_ny_nearest_y_transposed(
263
+ idxm = fvec_L2sqr_ny_nearest_y_transposed<SL>(
260
264
  distances.data(),
261
265
  xsub,
262
266
  pq.transposed_centroids.data() + m * pq.ksub,
@@ -270,20 +274,24 @@ void compute_code(const ProductQuantizer& pq, const float* x, uint8_t* code) {
270
274
  }
271
275
  }
272
276
 
277
+ } // namespace
278
+
273
279
  void ProductQuantizer::compute_code(const float* x, uint8_t* code) const {
274
- switch (nbits) {
275
- case 8:
276
- faiss::compute_code<PQEncoder8>(*this, x, code);
277
- break;
280
+ with_simd_level([&]<SIMDLevel SL>() {
281
+ switch (nbits) {
282
+ case 8:
283
+ compute_1_code<PQEncoder8, SL>(*this, x, code);
284
+ break;
278
285
 
279
- case 16:
280
- faiss::compute_code<PQEncoder16>(*this, x, code);
281
- break;
286
+ case 16:
287
+ compute_1_code<PQEncoder16, SL>(*this, x, code);
288
+ break;
282
289
 
283
- default:
284
- faiss::compute_code<PQEncoderGeneric>(*this, x, code);
285
- break;
286
- }
290
+ default:
291
+ compute_1_code<PQEncoderGeneric, SL>(*this, x, code);
292
+ break;
293
+ }
294
+ }); // with_simd_level
287
295
  }
288
296
 
289
297
  template <class PQDecoder>
@@ -314,8 +322,9 @@ void ProductQuantizer::decode(const uint8_t* code, float* x) const {
314
322
  }
315
323
 
316
324
  void ProductQuantizer::decode(const uint8_t* code, float* x, size_t n) const {
325
+ int64_t n_signed = n;
317
326
  #pragma omp parallel for if (n > 100)
318
- for (int64_t i = 0; i < n; i++) {
327
+ for (int64_t i = 0; i < n_signed; i++) {
319
328
  this->decode(code + code_size * i, x + d * i);
320
329
  }
321
330
  }
@@ -345,7 +354,8 @@ void ProductQuantizer::compute_codes_with_assign_index(
345
354
  const float* x,
346
355
  uint8_t* codes,
347
356
  size_t n) {
348
- FAISS_THROW_IF_NOT(assign_index && assign_index->d == dsub);
357
+ FAISS_THROW_IF_NOT(
358
+ assign_index && static_cast<size_t>(assign_index->d) == dsub);
349
359
 
350
360
  for (size_t m = 0; m < M; m++) {
351
361
  assign_index->reset();
@@ -407,10 +417,11 @@ void ProductQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
407
417
  return;
408
418
  }
409
419
 
420
+ int64_t n_signed = n;
410
421
  if (dsub < 16) { // simple direct computation
411
422
 
412
423
  #pragma omp parallel for
413
- for (int64_t i = 0; i < n; i++)
424
+ for (int64_t i = 0; i < n_signed; i++)
414
425
  compute_code(x + i * d, codes + i * code_size);
415
426
 
416
427
  } else { // worthwhile to use BLAS
@@ -418,7 +429,7 @@ void ProductQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
418
429
  compute_distance_tables(n, x, dis_tables.get());
419
430
 
420
431
  #pragma omp parallel for
421
- for (int64_t i = 0; i < n; i++) {
432
+ for (int64_t i = 0; i < n_signed; i++) {
422
433
  uint8_t* code = codes + i * code_size;
423
434
  const float* tab = dis_tables.get() + i * ksub * M;
424
435
  compute_code_from_distance_table(tab, code);
@@ -428,51 +439,54 @@ void ProductQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
428
439
 
429
440
  void ProductQuantizer::compute_distance_table(const float* x, float* dis_table)
430
441
  const {
431
- if (transposed_centroids.empty()) {
432
- // use regular version
433
- for (size_t m = 0; m < M; m++) {
434
- fvec_L2sqr_ny(
435
- dis_table + m * ksub,
436
- x + m * dsub,
437
- get_centroids(m, 0),
438
- dsub,
439
- ksub);
442
+ with_simd_level([&]<SIMDLevel SL>() {
443
+ if (transposed_centroids.empty()) {
444
+ // use regular version
445
+ for (size_t m = 0; m < M; m++) {
446
+ fvec_L2sqr_ny<SL>(
447
+ dis_table + m * ksub,
448
+ x + m * dsub,
449
+ get_centroids(m, 0),
450
+ dsub,
451
+ ksub);
452
+ }
453
+ } else {
454
+ // transposed centroids are available, use'em
455
+ for (size_t m = 0; m < M; m++) {
456
+ fvec_L2sqr_ny_transposed<SL>(
457
+ dis_table + m * ksub,
458
+ x + m * dsub,
459
+ transposed_centroids.data() + m * ksub,
460
+ centroids_sq_lengths.data() + m * ksub,
461
+ dsub,
462
+ M * ksub,
463
+ ksub);
464
+ }
440
465
  }
441
- } else {
442
- // transposed centroids are available, use'em
466
+ });
467
+ }
468
+
469
+ void ProductQuantizer::compute_inner_prod_table(
470
+ const float* x,
471
+ float* dis_table) const {
472
+ with_simd_level([&]<SIMDLevel SL>() {
443
473
  for (size_t m = 0; m < M; m++) {
444
- fvec_L2sqr_ny_transposed(
474
+ fvec_inner_products_ny<SL>(
445
475
  dis_table + m * ksub,
446
476
  x + m * dsub,
447
- transposed_centroids.data() + m * ksub,
448
- centroids_sq_lengths.data() + m * ksub,
477
+ get_centroids(m, 0),
449
478
  dsub,
450
- M * ksub,
451
479
  ksub);
452
480
  }
453
- }
454
- }
455
-
456
- void ProductQuantizer::compute_inner_prod_table(
457
- const float* x,
458
- float* dis_table) const {
459
- size_t m;
460
-
461
- for (m = 0; m < M; m++) {
462
- fvec_inner_products_ny(
463
- dis_table + m * ksub,
464
- x + m * dsub,
465
- get_centroids(m, 0),
466
- dsub,
467
- ksub);
468
- }
481
+ });
469
482
  }
470
483
 
471
484
  void ProductQuantizer::compute_distance_tables(
472
485
  size_t nx,
473
486
  const float* x,
474
487
  float* dis_tables) const {
475
- #if defined(__AVX2__) || defined(__aarch64__)
488
+ int64_t nx_signed = nx;
489
+ #if defined(COMPILE_SIMD_AVX2) || defined(COMPILE_SIMD_ARM_NEON)
476
490
  if (dsub == 2 && nbits < 8) { // interesting for a narrow range of settings
477
491
  compute_PQ_dis_tables_dsub2(
478
492
  d, ksub, centroids.data(), nx, x, false, dis_tables);
@@ -481,13 +495,13 @@ void ProductQuantizer::compute_distance_tables(
481
495
  if (dsub < 16) {
482
496
 
483
497
  #pragma omp parallel for if (nx > 1)
484
- for (int64_t i = 0; i < nx; i++) {
498
+ for (int64_t i = 0; i < nx_signed; i++) {
485
499
  compute_distance_table(x + i * d, dis_tables + i * ksub * M);
486
500
  }
487
501
 
488
502
  } else { // use BLAS
489
503
 
490
- for (int m = 0; m < M; m++) {
504
+ for (size_t m = 0; m < M; m++) {
491
505
  pairwise_L2sqr(
492
506
  dsub,
493
507
  nx,
@@ -506,7 +520,8 @@ void ProductQuantizer::compute_inner_prod_tables(
506
520
  size_t nx,
507
521
  const float* x,
508
522
  float* dis_tables) const {
509
- #if defined(__AVX2__) || defined(__aarch64__)
523
+ int64_t nx_signed = nx;
524
+ #if defined(COMPILE_SIMD_AVX2) || defined(COMPILE_SIMD_ARM_NEON)
510
525
  if (dsub == 2 && nbits < 8) {
511
526
  compute_PQ_dis_tables_dsub2(
512
527
  d, ksub, centroids.data(), nx, x, true, dis_tables);
@@ -515,14 +530,14 @@ void ProductQuantizer::compute_inner_prod_tables(
515
530
  if (dsub < 16) {
516
531
 
517
532
  #pragma omp parallel for if (nx > 1)
518
- for (int64_t i = 0; i < nx; i++) {
533
+ for (int64_t i = 0; i < nx_signed; i++) {
519
534
  compute_inner_prod_table(x + i * d, dis_tables + i * ksub * M);
520
535
  }
521
536
 
522
537
  } else { // use BLAS
523
538
 
524
539
  // compute distance tables
525
- for (int m = 0; m < M; m++) {
540
+ for (size_t m = 0; m < M; m++) {
526
541
  FINTEGER ldc = ksub * M, nxi = nx, ksubi = ksub, dsubi = dsub,
527
542
  di = d;
528
543
  float one = 1.0, zero = 0;
@@ -566,7 +581,7 @@ void pq_estimators_from_tables_Mmul4(
566
581
  float dis = 0;
567
582
  const float* dt = dis_table;
568
583
 
569
- for (size_t m = 0; m < M; m += 4) {
584
+ for (int m = 0; m < M; m += 4) {
570
585
  float dism = 0;
571
586
  dism = dt[*codes++];
572
587
  dt += ksub;
@@ -638,7 +653,7 @@ void pq_estimators_from_tables(
638
653
  for (size_t j = 0; j < ncodes; j++) {
639
654
  float dis = 0;
640
655
  const float* __restrict dt = dis_table;
641
- for (int m = 0; m < M; m++) {
656
+ for (size_t m = 0; m < M; m++) {
642
657
  dis += dt[*codes++];
643
658
  dt += ksub;
644
659
  }
@@ -686,10 +701,11 @@ void pq_knn_search_with_tables(
686
701
  HeapArray<C>* res,
687
702
  bool init_finalize_heap) {
688
703
  size_t k = res->k, nx = res->nh;
704
+ int64_t nx_signed = nx;
689
705
  size_t ksub = pq.ksub, M = pq.M;
690
706
 
691
707
  #pragma omp parallel for if (nx > 1)
692
- for (int64_t i = 0; i < nx; i++) {
708
+ for (int64_t i = 0; i < nx_signed; i++) {
693
709
  /* query preparation for asymmetric search: compute look-up tables */
694
710
  const float* dis_table = dis_tables + i * ksub * M;
695
711
 
@@ -785,22 +801,24 @@ void ProductQuantizer::compute_sdc_table() {
785
801
  sdc_table.resize(M * ksub * ksub);
786
802
 
787
803
  if (dsub < 4) {
804
+ with_simd_level([&]<SIMDLevel SL>() {
788
805
  #pragma omp parallel for
789
- for (int mk = 0; mk < M * ksub; mk++) {
790
- // allow omp to schedule in a more fine-grained way
791
- // `collapse` is not supported in OpenMP 2.x
792
- int m = mk / ksub;
793
- int k = mk % ksub;
794
- const float* cents = centroids.data() + m * ksub * dsub;
795
- const float* centi = cents + k * dsub;
796
- float* dis_tab = sdc_table.data() + m * ksub * ksub;
797
- fvec_L2sqr_ny(dis_tab + k * ksub, centi, cents, dsub, ksub);
798
- }
806
+ for (int64_t mk = 0; mk < static_cast<int64_t>(M * ksub); mk++) {
807
+ // allow omp to schedule in a more fine-grained way
808
+ // `collapse` is not supported in OpenMP 2.x
809
+ int m = mk / ksub;
810
+ int k = mk % ksub;
811
+ const float* cents = centroids.data() + m * ksub * dsub;
812
+ const float* centi = cents + k * dsub;
813
+ float* dis_tab = sdc_table.data() + m * ksub * ksub;
814
+ fvec_L2sqr_ny<SL>(dis_tab + k * ksub, centi, cents, dsub, ksub);
815
+ }
816
+ });
799
817
  } else {
800
818
  // NOTE: it would disable the omp loop in pairwise_L2sqr
801
819
  // but still accelerate especially when M >= 4
802
820
  #pragma omp parallel for
803
- for (int m = 0; m < M; m++) {
821
+ for (int64_t m = 0; m < static_cast<int64_t>(M); m++) {
804
822
  const float* cents = centroids.data() + m * ksub * dsub;
805
823
  float* dis_tab = sdc_table.data() + m * ksub * ksub;
806
824
  pairwise_L2sqr(
@@ -819,9 +837,10 @@ void ProductQuantizer::search_sdc(
819
837
  FAISS_THROW_IF_NOT(sdc_table.size() == M * ksub * ksub);
820
838
  FAISS_THROW_IF_NOT(nbits == 8);
821
839
  size_t k = res->k;
840
+ int64_t nq_signed = nq;
822
841
 
823
842
  #pragma omp parallel for
824
- for (int64_t i = 0; i < nq; i++) {
843
+ for (int64_t i = 0; i < nq_signed; i++) {
825
844
  /* Compute distances and keep smallest values */
826
845
  idx_t* heap_ids = res->ids + i * k;
827
846
  float* heap_dis = res->val + i * k;
@@ -834,7 +853,7 @@ void ProductQuantizer::search_sdc(
834
853
  for (size_t j = 0; j < nb; j++) {
835
854
  float dis = 0;
836
855
  const float* tab = sdc_table.data();
837
- for (int m = 0; m < M; m++) {
856
+ for (size_t m = 0; m < M; m++) {
838
857
  dis += tab[bcode[m] + qcode[m] * ksub];
839
858
  tab += ksub * ksub;
840
859
  }
@@ -16,8 +16,8 @@ struct Quantizer {
16
16
  size_t d; ///< size of the input vectors
17
17
  size_t code_size; ///< bytes per indexed vector
18
18
 
19
- explicit Quantizer(size_t d = 0, size_t code_size = 0)
20
- : d(d), code_size(code_size) {}
19
+ explicit Quantizer(size_t d_in = 0, size_t code_size_in = 0)
20
+ : d(d_in), code_size(code_size_in) {}
21
21
 
22
22
  /** Train the quantizer
23
23
  *
@@ -8,9 +8,12 @@
8
8
  #include <faiss/impl/RaBitQUtils.h>
9
9
 
10
10
  #include <faiss/impl/FaissAssert.h>
11
+ #include <faiss/impl/simd_dispatch.h>
11
12
  #include <faiss/utils/distances.h>
13
+ #include <faiss/utils/rabitq_simd.h>
12
14
  #include <algorithm>
13
15
  #include <cmath>
16
+ #include <cstring>
14
17
  #include <limits>
15
18
 
16
19
  namespace faiss {
@@ -151,6 +154,7 @@ QueryFactorsData compute_query_factors(
151
154
  std::vector<uint8_t>& rotated_qq) {
152
155
  FAISS_THROW_IF_NOT(qb <= 8);
153
156
  FAISS_THROW_IF_NOT(qb > 0);
157
+ FAISS_THROW_IF_NOT(d > 0);
154
158
 
155
159
  QueryFactorsData query_factors;
156
160
 
@@ -163,38 +167,42 @@ QueryFactorsData compute_query_factors(
163
167
  query_factors.g_error = std::sqrt(query_factors.qr_to_c_L2sqr);
164
168
 
165
169
  // Rotate the query (subtract centroid)
170
+ // Save aliasing state before resize(), which may reallocate the buffer.
171
+ const bool query_aliased = (query == rotated_q.data());
172
+ FAISS_THROW_IF_NOT_MSG(
173
+ !query_aliased || centroid == nullptr,
174
+ "query aliasing is only supported in the IVF residual path "
175
+ "(centroid == nullptr)");
166
176
  rotated_q.resize(d);
167
- for (size_t i = 0; i < d; i++) {
168
- if (i < rotated_q.size()) {
169
- rotated_q[i] =
170
- query[i] - ((centroid == nullptr) ? 0.0f : centroid[i]);
177
+ if (centroid == nullptr) {
178
+ // Caller may pass query == rotated_q.data() (IVF residual path);
179
+ // memcpy with overlapping src/dst is UB, so skip the copy in that case.
180
+ if (!query_aliased) {
181
+ memcpy(rotated_q.data(), query, d * sizeof(float));
182
+ }
183
+ } else {
184
+ for (size_t i = 0; i < d; i++) {
185
+ rotated_q[i] = query[i] - centroid[i];
171
186
  }
172
187
  }
173
188
 
174
- const float inv_d_sqrt =
175
- (d == 0) ? 1.0f : (1.0f / std::sqrt(static_cast<float>(d)));
189
+ const float inv_d_sqrt = 1.0f / std::sqrt(static_cast<float>(d));
176
190
 
177
191
  // Compute quantization range
178
192
  float v_min = std::numeric_limits<float>::max();
179
193
  float v_max = std::numeric_limits<float>::lowest();
180
194
 
195
+ const float* rq = rotated_q.data();
181
196
  if (centered) {
182
197
  float z_max = Z_MAX_BY_QB[qb - 1];
183
198
  float v_radius = z_max * std::sqrt(query_factors.qr_to_c_L2sqr / d);
184
199
  v_min = -v_radius;
185
200
  v_max = v_radius;
186
201
  } else {
187
- // Only compute min/max if we have dimensions to process
188
- if (d > 0 && !rotated_q.empty()) {
189
- for (size_t i = 0; i < d; i++) {
190
- const float v_q = rotated_q[i];
191
- v_min = std::min(v_min, v_q);
192
- v_max = std::max(v_max, v_q);
193
- }
194
- } else {
195
- // For empty dimensions, use default range
196
- v_min = 0.0f;
197
- v_max = 1.0f;
202
+ for (size_t i = 0; i < d; i++) {
203
+ const float v_q = rq[i];
204
+ v_min = std::min(v_min, v_q);
205
+ v_max = std::max(v_max, v_q);
198
206
  }
199
207
  }
200
208
 
@@ -207,25 +215,18 @@ QueryFactorsData compute_query_factors(
207
215
  size_t sum_qq = 0;
208
216
  int64_t sum2_signed_odd_int = 0;
209
217
 
210
- // Process arrays - throw error if they are unexpectedly empty
211
- if (d > 0 && !rotated_q.empty() && !rotated_qq.empty()) {
212
- for (size_t i = 0; i < d; i++) {
213
- const float v_q = rotated_q[i];
214
- // Non-randomized scalar quantization
215
- const uint8_t v_qq = std::clamp<float>(
216
- std::round((v_q - v_min) * inv_delta), 0, max_code);
217
- rotated_qq[i] = v_qq;
218
- sum_qq += v_qq;
219
-
220
- if (centered) {
221
- int64_t signed_odd_int = int64_t(v_qq) * 2 - max_code;
222
- sum2_signed_odd_int += signed_odd_int * signed_odd_int;
223
- }
218
+ uint8_t* rqq = rotated_qq.data();
219
+ for (size_t i = 0; i < d; i++) {
220
+ const float v_q = rq[i];
221
+ const uint8_t v_qq = std::clamp<float>(
222
+ std::round((v_q - v_min) * inv_delta), 0, max_code);
223
+ rqq[i] = v_qq;
224
+ sum_qq += v_qq;
225
+
226
+ if (centered) {
227
+ int64_t signed_odd_int = int64_t(v_qq) * 2 - max_code;
228
+ sum2_signed_odd_int += signed_odd_int * signed_odd_int;
224
229
  }
225
- } else {
226
- FAISS_THROW_MSG(
227
- "Arrays unexpectedly empty when d=" + std::to_string(d) +
228
- "or d is incorrectly set");
229
230
  }
230
231
 
231
232
  // Compute query factors
@@ -240,10 +241,18 @@ QueryFactorsData compute_query_factors(
240
241
  query_factors.int_dot_scale = 1.0f;
241
242
  }
242
243
 
243
- // Compute query norm for inner product metric
244
+ // Compute query norm for inner product metric.
245
+ // When centroid is nullptr (IVF residual path), qr_to_c_L2sqr already
246
+ // holds fvec_norm_L2sqr(query, d) from line 164, so reuse it.
244
247
  query_factors.qr_norm_L2sqr = 0.0f;
248
+ query_factors.q_dot_c = 0.0f;
245
249
  if (metric_type == MetricType::METRIC_INNER_PRODUCT) {
246
- query_factors.qr_norm_L2sqr = fvec_norm_L2sqr(query, d);
250
+ query_factors.qr_norm_L2sqr = (centroid == nullptr)
251
+ ? query_factors.qr_to_c_L2sqr
252
+ : fvec_norm_L2sqr(query, d);
253
+ if (centroid != nullptr) {
254
+ query_factors.q_dot_c = fvec_inner_product(query, centroid, d);
255
+ }
247
256
  }
248
257
 
249
258
  return query_factors;
@@ -290,5 +299,94 @@ void set_bit_fastscan(uint8_t* code, size_t bit_index) {
290
299
  }
291
300
  }
292
301
 
302
+ size_t compute_per_vector_storage_size(size_t nb_bits, size_t d) {
303
+ const size_t ex_bits = nb_bits - 1;
304
+ if (ex_bits == 0) {
305
+ return sizeof(SignBitFactors);
306
+ } else {
307
+ return sizeof(SignBitFactorsWithError) + sizeof(ExtraBitsFactors) +
308
+ (d * ex_bits + 7) / 8;
309
+ }
310
+ }
311
+
312
+ // Non-template wrapper with dynamic dispatch (one dispatch per call).
313
+ // The hot path in RaBitQuantizer dispatches once at distance computer
314
+ // construction, so per-vector dispatch only affects this utility path.
315
+ float compute_full_multibit_distance(
316
+ const uint8_t* sign_bits,
317
+ const uint8_t* ex_code,
318
+ const ExtraBitsFactors& ex_fac,
319
+ const float* rotated_q,
320
+ float qr_base,
321
+ size_t d,
322
+ size_t ex_bits,
323
+ MetricType metric_type) {
324
+ return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_A0>(
325
+ [&]<SIMDLevel SL>() {
326
+ return compute_full_multibit_distance<SL>(
327
+ sign_bits,
328
+ ex_code,
329
+ ex_fac,
330
+ rotated_q,
331
+ qr_base,
332
+ d,
333
+ ex_bits,
334
+ metric_type);
335
+ });
336
+ }
337
+
338
+ void populate_block_aux_from_flat_storage(
339
+ const std::vector<uint8_t>& flat_storage,
340
+ AlignedTable<uint8_t>& codes,
341
+ size_t num_vectors,
342
+ size_t bbs,
343
+ size_t M2,
344
+ size_t old_block_stride,
345
+ size_t new_block_stride,
346
+ size_t storage_size,
347
+ const int64_t* id_map) {
348
+ if (flat_storage.empty() || num_vectors == 0) {
349
+ return;
350
+ }
351
+
352
+ const size_t packed_block_size = ((M2 + 1) / 2) * bbs;
353
+ const size_t n_blocks = (num_vectors + bbs - 1) / bbs;
354
+
355
+ if (old_block_stride < new_block_stride) {
356
+ AlignedTable<uint8_t> old_data;
357
+ old_data.resize(codes.size());
358
+ memcpy(old_data.data(), codes.data(), codes.size());
359
+
360
+ codes.resize(n_blocks * new_block_stride);
361
+ memset(codes.data(), 0, n_blocks * new_block_stride);
362
+ for (size_t b = 0; b < n_blocks; b++) {
363
+ memcpy(codes.data() + b * new_block_stride,
364
+ old_data.data() + b * old_block_stride,
365
+ packed_block_size);
366
+ }
367
+ }
368
+
369
+ for (size_t offset = 0; offset < num_vectors; offset++) {
370
+ const int64_t global_id =
371
+ id_map ? id_map[offset] : static_cast<int64_t>(offset);
372
+ FAISS_THROW_IF_NOT_MSG(
373
+ global_id >= 0 &&
374
+ static_cast<size_t>(global_id) * storage_size +
375
+ storage_size <=
376
+ flat_storage.size(),
377
+ "global_id out of bounds for flat_storage during migration");
378
+
379
+ const uint8_t* src = flat_storage.data() + global_id * storage_size;
380
+ uint8_t* dst = get_block_aux_ptr(
381
+ codes.data(),
382
+ offset,
383
+ bbs,
384
+ packed_block_size,
385
+ new_block_stride,
386
+ storage_size);
387
+ memcpy(dst, src, storage_size);
388
+ }
389
+ }
390
+
293
391
  } // namespace rabitq_utils
294
392
  } // namespace faiss