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
@@ -13,40 +13,34 @@
13
13
 
14
14
  #include <faiss/impl/CodePacker.h>
15
15
  #include <faiss/impl/FaissAssert.h>
16
- #include <faiss/impl/FastScanDistancePostProcessing.h>
17
16
  #include <faiss/impl/IDSelector.h>
18
- #include <faiss/impl/LookupTableScaler.h>
19
17
  #include <faiss/impl/RaBitQUtils.h>
20
- #include <faiss/impl/pq4_fast_scan.h>
21
- #include <faiss/impl/simd_result_handlers.h>
18
+ #include <faiss/impl/fast_scan/FastScanDistancePostProcessing.h>
19
+ #include <faiss/impl/fast_scan/fast_scan.h>
20
+ #include <faiss/impl/fast_scan/simd_result_handlers.h>
22
21
  #include <faiss/utils/hamming.h>
23
- #include <faiss/utils/utils.h>
24
-
25
- #include <faiss/impl/pq4_fast_scan.h>
26
- #include <faiss/impl/simd_result_handlers.h>
27
22
  #include <faiss/utils/quantize_lut.h>
23
+ #include <faiss/utils/utils.h>
28
24
 
29
25
  namespace faiss {
30
26
 
31
- using namespace simd_result_handlers;
32
-
33
27
  inline size_t roundup(size_t a, size_t b) {
34
28
  return (a + b - 1) / b * b;
35
29
  }
36
30
 
37
31
  void IndexFastScan::init_fastscan(
38
- int d,
32
+ int d_,
39
33
  size_t M_init,
40
34
  size_t nbits_init,
41
35
  MetricType metric,
42
- int bbs) {
36
+ int bbs_) {
43
37
  FAISS_THROW_IF_NOT(nbits_init == 4);
44
- FAISS_THROW_IF_NOT(bbs % 32 == 0);
45
- this->d = d;
38
+ FAISS_THROW_IF_NOT(bbs_ % 32 == 0);
39
+ this->d = d_;
46
40
  this->M = M_init;
47
41
  this->nbits = nbits_init;
48
42
  this->metric_type = metric;
49
- this->bbs = bbs;
43
+ this->bbs = bbs_;
50
44
  ksub = (1 << nbits_init);
51
45
 
52
46
  code_size = (M_init * nbits_init + 7) / 8;
@@ -84,7 +78,8 @@ void IndexFastScan::add(idx_t n, const float* x) {
84
78
  compute_codes(tmp_codes.get(), n, x);
85
79
 
86
80
  ntotal2 = roundup(ntotal + n, bbs);
87
- size_t new_size = ntotal2 * M2 / 2; // assume nbits = 4
81
+ size_t n_blocks = ntotal2 / bbs;
82
+ size_t new_size = n_blocks * get_block_stride();
88
83
  size_t old_size = codes.size();
89
84
  if (new_size > old_size) {
90
85
  codes.resize(new_size);
@@ -92,7 +87,15 @@ void IndexFastScan::add(idx_t n, const float* x) {
92
87
  }
93
88
 
94
89
  pq4_pack_codes_range(
95
- tmp_codes.get(), M, ntotal, ntotal + n, bbs, M2, codes.get());
90
+ tmp_codes.get(),
91
+ M,
92
+ ntotal,
93
+ ntotal + n,
94
+ bbs,
95
+ M2,
96
+ codes.get(),
97
+ 0,
98
+ get_block_stride());
96
99
 
97
100
  ntotal += n;
98
101
  }
@@ -101,17 +104,25 @@ CodePacker* IndexFastScan::get_CodePacker() const {
101
104
  return new CodePackerPQ4(M, bbs);
102
105
  }
103
106
 
107
+ size_t IndexFastScan::get_block_stride() const {
108
+ std::unique_ptr<CodePacker> packer(get_CodePacker());
109
+ FAISS_THROW_IF_NOT_MSG(
110
+ packer->nvec == static_cast<size_t>(bbs),
111
+ "CodePacker must pack bbs vectors per block for fast-scan");
112
+ return packer->block_size;
113
+ }
114
+
104
115
  size_t IndexFastScan::remove_ids(const IDSelector& sel) {
105
116
  idx_t j = 0;
106
117
  std::vector<uint8_t> buffer(code_size);
107
- CodePackerPQ4 packer(M, bbs);
118
+ std::unique_ptr<CodePacker> packer(get_CodePacker());
108
119
  for (idx_t i = 0; i < ntotal; i++) {
109
120
  if (sel.is_member(i)) {
110
121
  // should be removed
111
122
  } else {
112
123
  if (i > j) {
113
- packer.unpack_1(codes.data(), i, buffer.data());
114
- packer.pack_1(buffer.data(), j, codes.data());
124
+ packer->unpack_1(codes.data(), i, buffer.data());
125
+ packer->pack_1(buffer.data(), j, codes.data());
115
126
  }
116
127
  j++;
117
128
  }
@@ -120,8 +131,7 @@ size_t IndexFastScan::remove_ids(const IDSelector& sel) {
120
131
  if (nremove > 0) {
121
132
  ntotal = j;
122
133
  ntotal2 = roundup(ntotal, bbs);
123
- size_t new_size = ntotal2 * M2 / 2;
124
- codes.resize(new_size);
134
+ codes.resize(ntotal2 / bbs * get_block_stride());
125
135
  }
126
136
  return nremove;
127
137
  }
@@ -139,17 +149,18 @@ void IndexFastScan::check_compatible_for_merge(const Index& otherIndex) const {
139
149
  "can only merge indexes of the same type");
140
150
  }
141
151
 
142
- void IndexFastScan::merge_from(Index& otherIndex, idx_t add_id) {
152
+ void IndexFastScan::merge_from(Index& otherIndex, idx_t /*add_id*/) {
143
153
  check_compatible_for_merge(otherIndex);
144
154
  IndexFastScan* other = static_cast<IndexFastScan*>(&otherIndex);
145
155
  ntotal2 = roundup(ntotal + other->ntotal, bbs);
146
- codes.resize(ntotal2 * M2 / 2);
156
+ codes.resize(ntotal2 / bbs * get_block_stride());
147
157
  std::vector<uint8_t> buffer(code_size);
148
- CodePackerPQ4 packer(M, bbs);
158
+ std::unique_ptr<CodePacker> packer(get_CodePacker());
159
+ std::unique_ptr<CodePacker> other_packer(other->get_CodePacker());
149
160
 
150
- for (int i = 0; i < other->ntotal; i++) {
151
- packer.unpack_1(other->codes.data(), i, buffer.data());
152
- packer.pack_1(buffer.data(), ntotal + i, codes.data());
161
+ for (idx_t i = 0; i < other->ntotal; i++) {
162
+ other_packer->unpack_1(other->codes.data(), i, buffer.data());
163
+ packer->pack_1(buffer.data(), ntotal + i, codes.data());
153
164
  }
154
165
  ntotal += other->ntotal;
155
166
  other->reset();
@@ -173,18 +184,18 @@ void estimators_from_tables_generic(
173
184
  BitstringReader bsr(codes + j * index.code_size, index.code_size);
174
185
  accu_t dis = 0;
175
186
  const dis_t* dt = dis_table;
176
- int nscale = context.norm_scaler ? context.norm_scaler->nscale : 0;
187
+ int nscale = context.pq2x4_scale ? 2 : 0;
177
188
 
178
189
  for (size_t m = 0; m < index.M - nscale; m++) {
179
- uint64_t c = bsr.read(index.nbits);
190
+ uint64_t c = bsr.read(static_cast<int>(index.nbits));
180
191
  dis += dt[c];
181
192
  dt += index.ksub;
182
193
  }
183
194
 
184
- if (nscale && context.norm_scaler) {
195
+ if (nscale) {
185
196
  for (size_t m = 0; m < nscale; m++) {
186
- uint64_t c = bsr.read(index.nbits);
187
- dis += context.norm_scaler->scale_one(dt[c]);
197
+ uint64_t c = bsr.read(static_cast<int>(index.nbits));
198
+ dis += dt[c] * context.pq2x4_scale;
188
199
  dt += index.ksub;
189
200
  }
190
201
  }
@@ -198,43 +209,18 @@ void estimators_from_tables_generic(
198
209
 
199
210
  } // anonymous namespace
200
211
 
201
- // Default implementation of make_knn_handler with centralized fallback logic
202
- SIMDResultHandlerToFloat* IndexFastScan::make_knn_handler(
212
+ std::unique_ptr<FastScanCodeScanner> IndexFastScan::make_knn_scanner(
203
213
  bool is_max,
204
- int impl,
205
214
  idx_t n,
206
215
  idx_t k,
207
- size_t ntotal,
216
+ size_t ntotal_,
208
217
  float* distances,
209
218
  idx_t* labels,
210
219
  const IDSelector* sel,
220
+ int impl,
211
221
  const FastScanDistancePostProcessing&) const {
212
- // Create default handlers based on k and impl
213
- if (is_max) {
214
- using HeapHC = HeapHandler<CMax<uint16_t, int>, false>;
215
- using ReservoirHC = ReservoirHandler<CMax<uint16_t, int>, false>;
216
- using SingleResultHC = SingleResultHandler<CMax<uint16_t, int>, false>;
217
-
218
- if (k == 1) {
219
- return new SingleResultHC(n, ntotal, distances, labels, sel);
220
- } else if (impl % 2 == 0) {
221
- return new HeapHC(n, ntotal, k, distances, labels, sel);
222
- } else {
223
- return new ReservoirHC(n, ntotal, k, 2 * k, distances, labels, sel);
224
- }
225
- } else {
226
- using HeapHC = HeapHandler<CMin<uint16_t, int>, false>;
227
- using ReservoirHC = ReservoirHandler<CMin<uint16_t, int>, false>;
228
- using SingleResultHC = SingleResultHandler<CMin<uint16_t, int>, false>;
229
-
230
- if (k == 1) {
231
- return new SingleResultHC(n, ntotal, distances, labels, sel);
232
- } else if (impl % 2 == 0) {
233
- return new HeapHC(n, ntotal, k, distances, labels, sel);
234
- } else {
235
- return new ReservoirHC(n, ntotal, k, 2 * k, distances, labels, sel);
236
- }
237
- }
222
+ return make_fast_scan_knn_scanner(
223
+ is_max, impl, n, ntotal_, k, distances, labels, sel);
238
224
  }
239
225
 
240
226
  using namespace quantize_lut;
@@ -249,7 +235,7 @@ void IndexFastScan::compute_quantized_LUT(
249
235
  std::unique_ptr<float[]> dis_tables(new float[n * dim12]);
250
236
  compute_float_LUT(dis_tables.get(), n, x, context);
251
237
 
252
- for (uint64_t i = 0; i < n; i++) {
238
+ for (idx_t i = 0; i < n; i++) {
253
239
  round_uint8_per_column(
254
240
  dis_tables.get() + i * dim12,
255
241
  M,
@@ -258,11 +244,11 @@ void IndexFastScan::compute_quantized_LUT(
258
244
  &normalizers[2 * i + 1]);
259
245
  }
260
246
 
261
- for (uint64_t i = 0; i < n; i++) {
247
+ for (idx_t i = 0; i < n; i++) {
262
248
  const float* t_in = dis_tables.get() + i * dim12;
263
249
  uint8_t* t_out = lut + i * M2 * ksub;
264
250
 
265
- for (int j = 0; j < dim12; j++) {
251
+ for (size_t j = 0; j < dim12; j++) {
266
252
  t_out[j] = int(t_in[j]);
267
253
  }
268
254
  memset(t_out + dim12, 0, (M2 - M) * ksub);
@@ -406,7 +392,7 @@ void IndexFastScan::search_implem_234(
406
392
  if (implem == 2) {
407
393
  // default float
408
394
  } else if (implem == 3 || implem == 4) {
409
- for (uint64_t i = 0; i < n; i++) {
395
+ for (idx_t i = 0; i < n; i++) {
410
396
  round_uint8_per_column(
411
397
  dis_tables.get() + i * dim12,
412
398
  M,
@@ -439,7 +425,7 @@ void IndexFastScan::search_implem_234(
439
425
  float a = normalizers[2 * i];
440
426
  float b = normalizers[2 * i + 1];
441
427
 
442
- for (int j = 0; j < k; j++) {
428
+ for (idx_t j = 0; j < k; j++) {
443
429
  heap_dis[j] = heap_dis[j] / a + b;
444
430
  }
445
431
  }
@@ -455,7 +441,6 @@ void IndexFastScan::search_implem_12(
455
441
  idx_t* labels,
456
442
  int impl,
457
443
  const FastScanDistancePostProcessing& context) const {
458
- using RH = ResultHandlerCompare<C, false>;
459
444
  FAISS_THROW_IF_NOT(bbs == 32);
460
445
 
461
446
  // handle qbs2 blocking by recursive call
@@ -496,45 +481,37 @@ void IndexFastScan::search_implem_12(
496
481
  // block sizes are encoded in qbs, 4 bits at a time
497
482
 
498
483
  // caution: we override an object field
499
- int qbs = this->qbs;
484
+ int qbs_ = this->qbs;
500
485
 
501
- if (n != pq4_qbs_to_nq(qbs)) {
502
- qbs = pq4_preferred_qbs(n);
486
+ if (n != pq4_qbs_to_nq(qbs_)) {
487
+ qbs_ = pq4_preferred_qbs(static_cast<int>(n));
503
488
  }
504
489
 
505
- int LUT_nq =
506
- pq4_pack_LUT_qbs(qbs, M2, quantized_dis_tables.get(), LUT.get());
490
+ int LUT_nq = pq4_pack_LUT_qbs(
491
+ qbs_, static_cast<int>(M2), quantized_dis_tables.get(), LUT.get());
507
492
  FAISS_THROW_IF_NOT(LUT_nq == n);
508
493
 
509
- std::unique_ptr<RH> handler(
510
- static_cast<RH*>(make_knn_handler(
511
- C::is_max,
512
- impl,
513
- n,
514
- k,
515
- ntotal,
516
- distances,
517
- labels,
518
- nullptr,
519
- context)));
520
-
521
- handler->disable = bool(skip & 2);
522
- handler->normalizers = normalizers.get();
494
+ auto scanner = make_knn_scanner(
495
+ C::is_max, n, k, ntotal, distances, labels, nullptr, impl, context);
496
+ auto* rh = scanner->handler();
497
+ rh->normalizers = normalizers.get();
498
+ // Note: skip & 2 previously set handler->disable (run kernel,
499
+ // discard results). Through the scanner path, skip & 2 now skips
500
+ // the kernel entirely (same as skip & 4), since disable is not
501
+ // accessible through the SIMDResultHandlerToFloat* interface.
502
+ if (!(skip & (2 | 4))) {
503
+ scanner->accumulate_loop_qbs(
504
+ qbs_,
523
505
 
524
- if (skip & 4) {
525
- // pass
526
- } else {
527
- pq4_accumulate_loop_qbs(
528
- qbs,
529
506
  ntotal2,
530
- M2,
507
+ static_cast<int>(M2),
531
508
  codes.get(),
532
509
  LUT.get(),
533
- *handler.get(),
534
- context.norm_scaler);
510
+ context.pq2x4_scale,
511
+ get_block_stride());
535
512
  }
536
513
  if (!(skip & 8)) {
537
- handler->end();
514
+ rh->end();
538
515
  }
539
516
  }
540
517
 
@@ -549,10 +526,16 @@ void IndexFastScan::search_implem_14(
549
526
  idx_t* labels,
550
527
  int impl,
551
528
  const FastScanDistancePostProcessing& context) const {
552
- using RH = ResultHandlerCompare<C, false>;
553
529
  FAISS_THROW_IF_NOT(bbs % 32 == 0);
554
530
 
555
- int qbs2 = qbs == 0 ? 4 : qbs;
531
+ // The accumulate loop dispatch table only instantiates certain
532
+ // (nq, BB) pairs where BB = bbs/32. Cap the query batch size to
533
+ // the maximum nq instantiated for the current BB so the caller
534
+ // doesn't have to know about internal template constraints.
535
+ // BB=1 → nq up to 4, BB=2 → nq up to 2, BB>=3 → nq=1
536
+ int BB = bbs / 32;
537
+ int max_qbs = BB <= 1 ? 4 : BB == 2 ? 2 : 1;
538
+ int qbs2 = std::min(qbs == 0 ? 4 : qbs, max_qbs);
556
539
 
557
540
  // handle qbs2 blocking by recursive call
558
541
  if (n > qbs2) {
@@ -587,37 +570,33 @@ void IndexFastScan::search_implem_14(
587
570
  }
588
571
 
589
572
  AlignedTable<uint8_t> LUT(n * dim12);
590
- pq4_pack_LUT(n, M2, quantized_dis_tables.get(), LUT.get());
591
-
592
- std::unique_ptr<RH> handler(
593
- static_cast<RH*>(make_knn_handler(
594
- C::is_max,
595
- impl,
596
- n,
597
- k,
598
- ntotal,
599
- distances,
600
- labels,
601
- nullptr,
602
- context)));
603
- handler->disable = bool(skip & 2);
604
- handler->normalizers = normalizers.get();
605
-
606
- if (skip & 4) {
607
- // pass
608
- } else {
609
- pq4_accumulate_loop(
610
- n,
573
+ pq4_pack_LUT(
574
+ static_cast<int>(n),
575
+ static_cast<int>(M2),
576
+ quantized_dis_tables.get(),
577
+ LUT.get());
578
+
579
+ auto scanner = make_knn_scanner(
580
+ C::is_max, n, k, ntotal, distances, labels, nullptr, impl, context);
581
+ auto* rh = scanner->handler();
582
+ rh->normalizers = normalizers.get();
583
+ // Note: skip & 2 previously set handler->disable (run kernel,
584
+ // discard results). Through the scanner path, skip & 2 now skips
585
+ // the kernel entirely (same as skip & 4), since disable is not
586
+ // accessible through the SIMDResultHandlerToFloat* interface.
587
+ if (!(skip & (2 | 4))) {
588
+ scanner->accumulate_loop(
589
+ static_cast<int>(n),
611
590
  ntotal2,
612
591
  bbs,
613
- M2,
592
+ static_cast<int>(M2),
614
593
  codes.get(),
615
594
  LUT.get(),
616
- *handler.get(),
617
- context.norm_scaler);
595
+ context.pq2x4_scale,
596
+ get_block_stride());
618
597
  }
619
598
  if (!(skip & 8)) {
620
- handler->end();
599
+ rh->end();
621
600
  }
622
601
  }
623
602
 
@@ -639,11 +618,8 @@ template void IndexFastScan::search_dispatch_implem<false>(
639
618
 
640
619
  void IndexFastScan::reconstruct(idx_t key, float* recons) const {
641
620
  std::vector<uint8_t> code(code_size, 0);
642
- BitstringWriter bsw(code.data(), code_size);
643
- for (size_t m = 0; m < M; m++) {
644
- uint8_t c = pq4_get_packed_element(codes.data(), bbs, M2, key, m);
645
- bsw.write(c, nbits);
646
- }
621
+ std::unique_ptr<CodePacker> packer(get_CodePacker());
622
+ packer->unpack_1(codes.data(), key, code.data());
647
623
  sa_decode(1, code.data(), recons);
648
624
  }
649
625
 
@@ -7,16 +7,17 @@
7
7
 
8
8
  #pragma once
9
9
 
10
+ #include <memory>
11
+
10
12
  #include <faiss/Index.h>
11
- #include <faiss/impl/FastScanDistancePostProcessing.h>
13
+ #include <faiss/impl/fast_scan/FastScanDistancePostProcessing.h>
14
+ #include <faiss/impl/fast_scan/fast_scan.h>
12
15
  #include <faiss/utils/AlignedTable.h>
13
16
 
14
17
  namespace faiss {
15
18
 
16
19
  struct CodePacker;
17
- struct NormTableScaler;
18
20
  struct IDSelector;
19
- struct SIMDResultHandlerToFloat;
20
21
 
21
22
  /** Fast scan version of IndexPQ and IndexAQ. Works for 4-bit PQ and AQ for now.
22
23
  *
@@ -43,8 +44,8 @@ struct IndexFastScan : Index {
43
44
 
44
45
  // vector quantizer
45
46
  size_t M;
46
- size_t nbits;
47
- size_t ksub;
47
+ size_t nbits = 0;
48
+ size_t ksub = 0;
48
49
  size_t code_size;
49
50
 
50
51
  // packed version of the codes
@@ -122,33 +123,22 @@ struct IndexFastScan : Index {
122
123
  const float* x,
123
124
  const FastScanDistancePostProcessing& context) const = 0;
124
125
 
125
- /** Create a KNN handler for this index type
126
- *
127
- * This method can be overridden by derived classes to provide
128
- * specialized handlers (e.g., RaBitQHeapHandler for RaBitQ indexes).
129
- * Base implementation creates standard handlers based on k and impl.
126
+ /** Create a SIMD-dispatched scanner for knn search.
130
127
  *
131
- * @param is_max whether to use CMax comparator (true) or CMin (false)
132
- * @param impl implementation number
133
- * @param n number of queries
134
- * @param k number of neighbors to find
135
- * @param ntotal total number of vectors in database
136
- * @param distances output distances array
137
- * @param labels output labels array
138
- * @param sel optional ID selector
139
- * @param context processing context for distance post-processing
140
- * @return pointer to created handler (never returns nullptr)
128
+ * Returns a FastScanCodeScanner that bundles handler + accumulation
129
+ * kernel behind the SIMD dispatch boundary.
130
+ * The scanner's accumulate methods dispatch to the optimal SIMD level.
141
131
  */
142
- virtual SIMDResultHandlerToFloat* make_knn_handler(
132
+ virtual std::unique_ptr<FastScanCodeScanner> make_knn_scanner(
143
133
  bool is_max,
144
- int impl,
145
134
  idx_t n,
146
135
  idx_t k,
147
136
  size_t ntotal,
148
137
  float* distances,
149
138
  idx_t* labels,
150
139
  const IDSelector* sel,
151
- const FastScanDistancePostProcessing& context) const;
140
+ int impl = 0,
141
+ const FastScanDistancePostProcessing& context = {}) const;
152
142
 
153
143
  // called by search function
154
144
  void compute_quantized_LUT(
@@ -214,7 +204,16 @@ struct IndexFastScan : Index {
214
204
  *
215
205
  * @return pointer to the code packer
216
206
  */
217
- CodePacker* get_CodePacker() const;
207
+ virtual CodePacker* get_CodePacker() const;
208
+
209
+ /** Get stride in bytes between consecutive SIMD blocks.
210
+ *
211
+ * Derived from get_CodePacker()->block_size so that there is a
212
+ * single source of truth for the block layout.
213
+ *
214
+ * @return stride in bytes
215
+ */
216
+ size_t get_block_stride() const;
218
217
 
219
218
  /** Merge another index into this one
220
219
  *
@@ -237,6 +236,18 @@ struct IndexFastScan : Index {
237
236
  void sa_encode(idx_t n, const float* x, uint8_t* bytes) const override {
238
237
  compute_codes(bytes, n, x);
239
238
  }
239
+
240
+ /** Get the size of the code portion packed by pq4_pack_codes.
241
+ *
242
+ * Returns the number of bytes per vector that are interleaved into
243
+ * SIMD blocks by pq4_pack_codes, excluding any embedded metadata
244
+ * (e.g., RaBitQ factors). The meaning of these bytes depends on the
245
+ * quantizer: for PQ/AQ they are 4-bit sub-quantizer nibbles, for
246
+ * RaBitQ they are 1-bit-per-dimension sign bits packed into nibbles.
247
+ *
248
+ * Must be implemented by all derived classes.
249
+ */
250
+ virtual size_t fast_scan_code_size() const = 0;
240
251
  };
241
252
 
242
253
  struct FastScanStats {