faiss 0.6.0 → 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 (361) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/ext/faiss/extconf.rb +2 -1
  4. data/ext/faiss/{index_rb.cpp → index.cpp} +1 -1
  5. data/ext/faiss/index_binary.cpp +1 -1
  6. data/ext/faiss/kmeans.cpp +1 -1
  7. data/ext/faiss/pca_matrix.cpp +1 -1
  8. data/ext/faiss/product_quantizer.cpp +1 -1
  9. data/ext/faiss/{utils_rb.cpp → utils.cpp} +1 -1
  10. data/lib/faiss/version.rb +1 -1
  11. data/vendor/faiss/faiss/AutoTune.cpp +93 -80
  12. data/vendor/faiss/faiss/Clustering.cpp +39 -240
  13. data/vendor/faiss/faiss/Clustering.h +6 -0
  14. data/vendor/faiss/faiss/IVFlib.cpp +41 -21
  15. data/vendor/faiss/faiss/Index.cpp +6 -5
  16. data/vendor/faiss/faiss/Index.h +5 -5
  17. data/vendor/faiss/faiss/Index2Layer.cpp +37 -53
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +49 -37
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +36 -34
  20. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +4 -1
  21. data/vendor/faiss/faiss/IndexBinary.cpp +5 -3
  22. data/vendor/faiss/faiss/IndexBinary.h +4 -4
  23. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +1 -1
  24. data/vendor/faiss/faiss/IndexBinaryFlat.h +1 -1
  25. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -4
  26. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +84 -92
  27. data/vendor/faiss/faiss/IndexBinaryHNSW.h +9 -3
  28. data/vendor/faiss/faiss/IndexBinaryHash.cpp +45 -236
  29. data/vendor/faiss/faiss/IndexBinaryHash.h +6 -6
  30. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +87 -415
  31. data/vendor/faiss/faiss/IndexFastScan.cpp +72 -109
  32. data/vendor/faiss/faiss/IndexFastScan.h +25 -23
  33. data/vendor/faiss/faiss/IndexFlat.cpp +27 -20
  34. data/vendor/faiss/faiss/IndexFlat.h +21 -18
  35. data/vendor/faiss/faiss/IndexFlatCodes.cpp +42 -19
  36. data/vendor/faiss/faiss/IndexHNSW.cpp +283 -145
  37. data/vendor/faiss/faiss/IndexHNSW.h +16 -2
  38. data/vendor/faiss/faiss/IndexIDMap.cpp +25 -21
  39. data/vendor/faiss/faiss/IndexIDMap.h +9 -7
  40. data/vendor/faiss/faiss/IndexIVF.cpp +465 -362
  41. data/vendor/faiss/faiss/IndexIVF.h +33 -12
  42. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +77 -74
  43. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +96 -93
  44. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +4 -1
  45. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +357 -238
  46. data/vendor/faiss/faiss/IndexIVFFastScan.h +42 -41
  47. data/vendor/faiss/faiss/IndexIVFFlat.cpp +36 -68
  48. data/vendor/faiss/faiss/IndexIVFFlat.h +32 -0
  49. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +53 -30
  50. data/vendor/faiss/faiss/IndexIVFFlatPanorama.h +3 -1
  51. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +18 -15
  52. data/vendor/faiss/faiss/IndexIVFPQ.cpp +71 -843
  53. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +151 -121
  54. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +3 -0
  55. data/vendor/faiss/faiss/IndexIVFPQR.cpp +21 -17
  56. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +26 -39
  57. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +2 -1
  58. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +475 -476
  59. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +248 -93
  60. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +41 -127
  61. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +1 -1
  62. data/vendor/faiss/faiss/IndexLSH.cpp +36 -19
  63. data/vendor/faiss/faiss/IndexLattice.cpp +13 -13
  64. data/vendor/faiss/faiss/IndexNNDescent.cpp +36 -21
  65. data/vendor/faiss/faiss/IndexNNDescent.h +2 -2
  66. data/vendor/faiss/faiss/IndexNSG.cpp +39 -23
  67. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +31 -11
  68. data/vendor/faiss/faiss/IndexPQ.cpp +128 -221
  69. data/vendor/faiss/faiss/IndexPQ.h +3 -2
  70. data/vendor/faiss/faiss/IndexPQFastScan.cpp +20 -14
  71. data/vendor/faiss/faiss/IndexPQFastScan.h +3 -0
  72. data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -18
  73. data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
  74. data/vendor/faiss/faiss/IndexRaBitQ.cpp +11 -36
  75. data/vendor/faiss/faiss/IndexRaBitQ.h +2 -1
  76. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +41 -277
  77. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +183 -27
  78. data/vendor/faiss/faiss/IndexRefine.cpp +30 -25
  79. data/vendor/faiss/faiss/IndexRefine.h +4 -4
  80. data/vendor/faiss/faiss/IndexReplicas.cpp +6 -6
  81. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +15 -14
  82. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +1 -1
  83. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +82 -14
  84. data/vendor/faiss/faiss/IndexShards.cpp +10 -9
  85. data/vendor/faiss/faiss/IndexShardsIVF.cpp +21 -15
  86. data/vendor/faiss/faiss/MatrixStats.cpp +5 -4
  87. data/vendor/faiss/faiss/MetaIndexes.cpp +19 -17
  88. data/vendor/faiss/faiss/MetaIndexes.h +1 -1
  89. data/vendor/faiss/faiss/MetricType.h +14 -7
  90. data/vendor/faiss/faiss/SuperKMeans.cpp +656 -0
  91. data/vendor/faiss/faiss/SuperKMeans.h +97 -0
  92. data/vendor/faiss/faiss/VectorTransform.cpp +237 -149
  93. data/vendor/faiss/faiss/VectorTransform.h +16 -16
  94. data/vendor/faiss/faiss/build.cpp +23 -0
  95. data/vendor/faiss/faiss/build.h +15 -0
  96. data/vendor/faiss/faiss/clone_index.cpp +48 -47
  97. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +47 -47
  98. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +11 -0
  99. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +38 -38
  100. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +11 -0
  101. data/vendor/faiss/faiss/factory_tools.cpp +5 -0
  102. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +6 -5
  103. data/vendor/faiss/faiss/gpu/GpuResources.h +1 -1
  104. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +9 -9
  105. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +4 -3
  106. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +46 -0
  107. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +56 -0
  108. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +78 -1
  109. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +72 -0
  110. data/vendor/faiss/faiss/gpu/test/TestUtils.h +23 -0
  111. data/vendor/faiss/faiss/gpu/utils/CuvsFilterConvert.h +1 -1
  112. data/vendor/faiss/faiss/gpu/utils/CuvsUtils.h +21 -10
  113. data/vendor/faiss/faiss/gpu_metal/GpuIndexFlat.h +22 -0
  114. data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +35 -0
  115. data/vendor/faiss/faiss/gpu_metal/MetalFlatKernels.h +40 -0
  116. data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +51 -0
  117. data/vendor/faiss/faiss/gpu_metal/MetalIndexFlat.h +65 -0
  118. data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +66 -0
  119. data/vendor/faiss/faiss/gpu_metal/MetalResources.h +79 -0
  120. data/vendor/faiss/faiss/gpu_metal/StandardMetalResources.h +35 -0
  121. data/vendor/faiss/faiss/impl/AdSampling.cpp +103 -0
  122. data/vendor/faiss/faiss/impl/AdSampling.h +35 -0
  123. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +29 -25
  124. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +1 -0
  125. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +10 -9
  126. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +3 -0
  127. data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +244 -0
  128. data/vendor/faiss/faiss/impl/ClusteringHelpers.h +94 -0
  129. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +16 -16
  130. data/vendor/faiss/faiss/impl/CodePacker.cpp +3 -3
  131. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +1 -1
  132. data/vendor/faiss/faiss/impl/DistanceComputer.h +8 -8
  133. data/vendor/faiss/faiss/impl/FaissAssert.h +6 -3
  134. data/vendor/faiss/faiss/impl/FaissException.h +50 -3
  135. data/vendor/faiss/faiss/impl/HNSW.cpp +92 -317
  136. data/vendor/faiss/faiss/impl/HNSW.h +13 -34
  137. data/vendor/faiss/faiss/impl/IDSelector.cpp +15 -11
  138. data/vendor/faiss/faiss/impl/IDSelector.h +8 -8
  139. data/vendor/faiss/faiss/impl/InvertedListScannerStats.h +26 -0
  140. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +82 -77
  141. data/vendor/faiss/faiss/impl/NNDescent.cpp +62 -25
  142. data/vendor/faiss/faiss/impl/NNDescent.h +6 -2
  143. data/vendor/faiss/faiss/impl/NSG.cpp +38 -21
  144. data/vendor/faiss/faiss/impl/NSG.h +4 -4
  145. data/vendor/faiss/faiss/impl/Panorama.cpp +23 -6
  146. data/vendor/faiss/faiss/impl/Panorama.h +258 -87
  147. data/vendor/faiss/faiss/impl/PdxLayout.cpp +93 -0
  148. data/vendor/faiss/faiss/impl/PdxLayout.h +41 -0
  149. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +46 -32
  150. data/vendor/faiss/faiss/impl/PolysemousTraining.h +3 -3
  151. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +35 -35
  152. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +21 -16
  153. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +30 -23
  154. data/vendor/faiss/faiss/impl/Quantizer.h +2 -2
  155. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +55 -49
  156. data/vendor/faiss/faiss/impl/RaBitQUtils.h +65 -0
  157. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +296 -283
  158. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +26 -23
  159. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
  160. data/vendor/faiss/faiss/impl/ResultHandler.h +99 -75
  161. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +52 -4
  162. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +27 -1
  163. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +14 -11
  164. data/vendor/faiss/faiss/impl/VisitedTable.h +7 -0
  165. data/vendor/faiss/faiss/impl/approx_topk/approx_topk.h +276 -0
  166. data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +68 -0
  167. data/vendor/faiss/faiss/{utils → impl}/approx_topk/generic.h +15 -8
  168. data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +68 -0
  169. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab-inl.h +169 -0
  170. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab.h +117 -0
  171. data/vendor/faiss/faiss/impl/approx_topk/simdlib256-inl.h +146 -0
  172. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h +73 -0
  173. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +270 -0
  174. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +460 -0
  175. data/vendor/faiss/faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h +159 -0
  176. data/vendor/faiss/faiss/impl/binary_hamming/IndexPQ_impl.h +92 -0
  177. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +26 -0
  178. data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +26 -0
  179. data/vendor/faiss/faiss/impl/binary_hamming/dispatch.h +143 -0
  180. data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +26 -0
  181. data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +26 -0
  182. data/vendor/faiss/faiss/impl/expanded_scanners.h +8 -3
  183. data/vendor/faiss/faiss/impl/{FastScanDistancePostProcessing.h → fast_scan/FastScanDistancePostProcessing.h} +13 -6
  184. data/vendor/faiss/faiss/impl/{LookupTableScaler.h → fast_scan/LookupTableScaler.h} +16 -5
  185. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +237 -0
  186. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +185 -0
  187. data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +229 -0
  188. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +268 -0
  189. data/vendor/faiss/faiss/impl/{pq4_fast_scan.cpp → fast_scan/fast_scan.cpp} +169 -2
  190. data/vendor/faiss/faiss/impl/fast_scan/fast_scan.h +341 -0
  191. data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +36 -0
  192. data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +40 -0
  193. data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +120 -0
  194. data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +104 -0
  195. data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +213 -0
  196. data/vendor/faiss/faiss/impl/{pq4_fast_scan_search_qbs.cpp → fast_scan/kernels_simd512.h} +26 -356
  197. data/vendor/faiss/faiss/impl/fast_scan/rabitq_dispatching.h +90 -0
  198. data/vendor/faiss/faiss/impl/fast_scan/rabitq_result_handler.h +108 -0
  199. data/vendor/faiss/faiss/impl/{simd_result_handlers.h → fast_scan/simd_result_handlers.h} +282 -134
  200. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +54 -0
  201. data/vendor/faiss/faiss/impl/hnsw/LockVector.h +64 -0
  202. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +91 -0
  203. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -0
  204. data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +104 -0
  205. data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +111 -0
  206. data/vendor/faiss/faiss/impl/index_read.cpp +1132 -45
  207. data/vendor/faiss/faiss/impl/index_read_utils.h +1 -1
  208. data/vendor/faiss/faiss/impl/index_write.cpp +95 -13
  209. data/vendor/faiss/faiss/impl/io.cpp +6 -6
  210. data/vendor/faiss/faiss/impl/io_macros.h +33 -16
  211. data/vendor/faiss/faiss/impl/kmeans1d.cpp +10 -10
  212. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +37 -23
  213. data/vendor/faiss/faiss/impl/lattice_Zn.h +6 -6
  214. data/vendor/faiss/faiss/impl/mapped_io.cpp +6 -6
  215. data/vendor/faiss/faiss/impl/platform_macros.h +11 -4
  216. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +549 -0
  217. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +245 -0
  218. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.h +105 -0
  219. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +106 -0
  220. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +21 -0
  221. data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +21 -0
  222. data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +21 -0
  223. data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx2.cpp → pq_code_distance-avx2.h} +9 -13
  224. data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx512.cpp → pq_code_distance-avx512.h} +9 -57
  225. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +29 -111
  226. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +96 -0
  227. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +238 -5
  228. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +5 -7
  229. data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +68 -0
  230. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +311 -477
  231. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
  232. data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +1 -1
  233. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +3 -2
  234. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +102 -11
  235. data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +27 -1
  236. data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +3 -3
  237. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +148 -0
  238. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +167 -0
  239. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +59 -0
  240. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +163 -0
  241. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +311 -0
  242. data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +192 -8
  243. data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +12 -0
  244. data/vendor/faiss/faiss/impl/simd_dispatch.h +100 -66
  245. data/vendor/faiss/faiss/impl/simdlib/simdlib.h +57 -0
  246. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_avx2.h +264 -172
  247. data/vendor/faiss/faiss/impl/simdlib/simdlib_avx512.h +414 -0
  248. data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +44 -0
  249. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_emulated.h +231 -166
  250. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_neon.h +270 -218
  251. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_ppc64.h +201 -160
  252. data/vendor/faiss/faiss/impl/svs_io.cpp +12 -3
  253. data/vendor/faiss/faiss/impl/svs_io.h +8 -2
  254. data/vendor/faiss/faiss/index_factory.cpp +86 -18
  255. data/vendor/faiss/faiss/index_io.h +24 -0
  256. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +66 -16
  257. data/vendor/faiss/faiss/invlists/DirectMap.cpp +24 -14
  258. data/vendor/faiss/faiss/invlists/DirectMap.h +4 -3
  259. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +157 -73
  260. data/vendor/faiss/faiss/invlists/InvertedLists.h +86 -23
  261. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +4 -4
  262. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +13 -13
  263. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  264. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +1 -1
  265. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +2 -2
  266. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +350 -0
  267. data/vendor/faiss/faiss/svs/IndexSVSIVF.h +128 -0
  268. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.cpp +40 -0
  269. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.h +43 -0
  270. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +225 -0
  271. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.h +71 -0
  272. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +25 -1
  273. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +18 -2
  274. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +1 -1
  275. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +12 -3
  276. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +7 -2
  277. data/vendor/faiss/faiss/utils/Heap.cpp +10 -10
  278. data/vendor/faiss/faiss/utils/NeuralNet.cpp +47 -36
  279. data/vendor/faiss/faiss/utils/NeuralNet.h +1 -1
  280. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +10 -4
  281. data/vendor/faiss/faiss/utils/distances.cpp +390 -560
  282. data/vendor/faiss/faiss/utils/distances.h +20 -1
  283. data/vendor/faiss/faiss/utils/distances_dispatch.h +117 -37
  284. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +8 -7
  285. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +33 -14
  286. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +12 -1
  287. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +16 -293
  288. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +57 -0
  289. data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +290 -0
  290. data/vendor/faiss/faiss/utils/distances_simd.cpp +5 -177
  291. data/vendor/faiss/faiss/utils/extra_distances.cpp +9 -8
  292. data/vendor/faiss/faiss/utils/extra_distances.h +32 -6
  293. data/vendor/faiss/faiss/utils/hamming-inl.h +13 -11
  294. data/vendor/faiss/faiss/utils/hamming.cpp +66 -517
  295. data/vendor/faiss/faiss/utils/hamming.h +92 -2
  296. data/vendor/faiss/faiss/utils/hamming_distance/common.h +287 -10
  297. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +15 -0
  298. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +15 -0
  299. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx2.h +142 -0
  300. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +234 -0
  301. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-generic.h +368 -0
  302. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-neon.h +322 -0
  303. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-rvv.h +39 -0
  304. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer.h +146 -0
  305. data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +481 -0
  306. data/vendor/faiss/faiss/utils/hamming_distance/hamming_neon.cpp +15 -0
  307. data/vendor/faiss/faiss/utils/hamming_distance/hamming_rvv.cpp +15 -0
  308. data/vendor/faiss/faiss/utils/partitioning.cpp +66 -987
  309. data/vendor/faiss/faiss/utils/partitioning.h +31 -0
  310. data/vendor/faiss/faiss/utils/popcount.h +29 -0
  311. data/vendor/faiss/faiss/utils/pq_code_distance.h +2 -2
  312. data/vendor/faiss/faiss/utils/prefetch.h +2 -2
  313. data/vendor/faiss/faiss/utils/quantize_lut.cpp +30 -30
  314. data/vendor/faiss/faiss/utils/quantize_lut.h +1 -1
  315. data/vendor/faiss/faiss/utils/rabitq_simd.h +57 -536
  316. data/vendor/faiss/faiss/utils/random.cpp +6 -6
  317. data/vendor/faiss/faiss/utils/simd_impl/IVFFlatScanner-inl.h +51 -0
  318. data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +5 -1
  319. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +213 -4
  320. data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +163 -10
  321. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +250 -4
  322. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +7 -4
  323. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +189 -0
  324. data/vendor/faiss/faiss/utils/simd_impl/distances_simdlib256.h +195 -0
  325. data/vendor/faiss/faiss/utils/simd_impl/distances_sse-inl.h +2 -1
  326. data/vendor/faiss/faiss/utils/{distances_fused/simdlib_based.h → simd_impl/exhaustive_L2sqr_blas_cmax.h} +5 -10
  327. data/vendor/faiss/faiss/utils/simd_impl/hamming_impl.h +481 -0
  328. data/vendor/faiss/faiss/utils/simd_impl/partitioning_avx2.cpp +14 -0
  329. data/vendor/faiss/faiss/utils/simd_impl/partitioning_neon.cpp +14 -0
  330. data/vendor/faiss/faiss/utils/simd_impl/partitioning_simdlib256.h +1085 -0
  331. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +355 -0
  332. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +477 -0
  333. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +55 -0
  334. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +55 -0
  335. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +32 -0
  336. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +43 -0
  337. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +57 -0
  338. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +45 -0
  339. data/vendor/faiss/faiss/utils/simd_levels.cpp +17 -5
  340. data/vendor/faiss/faiss/utils/simd_levels.h +93 -1
  341. data/vendor/faiss/faiss/utils/sorting.cpp +48 -36
  342. data/vendor/faiss/faiss/utils/utils.cpp +5 -5
  343. data/vendor/faiss/faiss/utils/utils.h +3 -3
  344. metadata +119 -34
  345. data/vendor/faiss/faiss/impl/RaBitQStats.cpp +0 -29
  346. data/vendor/faiss/faiss/impl/RaBitQStats.h +0 -56
  347. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +0 -224
  348. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +0 -230
  349. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +0 -84
  350. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +0 -196
  351. data/vendor/faiss/faiss/utils/approx_topk/mode.h +0 -34
  352. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +0 -36
  353. data/vendor/faiss/faiss/utils/extra_distances-inl.h +0 -235
  354. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +0 -462
  355. data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +0 -490
  356. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -449
  357. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +0 -87
  358. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +0 -524
  359. data/vendor/faiss/faiss/utils/simdlib.h +0 -42
  360. data/vendor/faiss/faiss/utils/simdlib_avx512.h +0 -365
  361. /data/ext/faiss/{utils_rb.h → utils.h} +0 -0
@@ -13,10 +13,9 @@
13
13
  #include <faiss/IndexIVFFastScan.h>
14
14
  #include <faiss/IndexIVFRaBitQ.h>
15
15
  #include <faiss/IndexRaBitQFastScan.h>
16
- #include <faiss/impl/RaBitQStats.h>
17
16
  #include <faiss/impl/RaBitQUtils.h>
18
17
  #include <faiss/impl/RaBitQuantizer.h>
19
- #include <faiss/impl/simd_result_handlers.h>
18
+ #include <faiss/impl/fast_scan/rabitq_result_handler.h>
20
19
  #include <faiss/utils/AlignedTable.h>
21
20
  #include <faiss/utils/Heap.h>
22
21
 
@@ -83,6 +82,10 @@ struct IndexIVFRaBitQFastScan : IndexIVFFastScan {
83
82
  uint8_t* codes,
84
83
  bool include_listnos = false) const override;
85
84
 
85
+ /// Packed code size: (d + 7) / 8 bytes (1-bit-per-dimension sign bits,
86
+ /// excluding factors)
87
+ size_t fast_scan_code_size() const override;
88
+
86
89
  protected:
87
90
  /// Return code_size as stride to skip embedded factor data during packing
88
91
  size_t code_packing_stride() const override;
@@ -108,15 +111,29 @@ struct IndexIVFRaBitQFastScan : IndexIVFFastScan {
108
111
  /// Compute per-vector auxiliary storage size based on nb_bits
109
112
  size_t compute_per_vector_storage_size() const;
110
113
 
111
- private:
112
- /// Compute query factors and lookup table for a residual vector
113
- /// (similar to IndexRaBitQFastScan::compute_float_LUT)
114
+ /// Override: compute and quantize LUT per-query to avoid O(n*nprobe*M*16)
115
+ /// float table allocation.
116
+ void compute_LUT_uint8(
117
+ size_t n,
118
+ const float* x,
119
+ const CoarseQuantized& cq,
120
+ AlignedTable<uint8_t>& dis_tables,
121
+ AlignedTable<uint16_t>& biases,
122
+ float* normalizers,
123
+ const FastScanDistancePostProcessing& context) const override;
124
+
125
+ /// Compute residual, query factors, and float LUT in two passes over d.
114
126
  void compute_residual_LUT(
115
- const float* residual,
127
+ const float* query,
128
+ idx_t centroid_id,
116
129
  QueryFactorsData& query_factors,
117
130
  float* lut_out,
118
- const float* original_query = nullptr) const;
131
+ uint8_t qb_param,
132
+ bool centered_param,
133
+ std::vector<float>& rotated_q,
134
+ std::vector<float>& centroid_buf) const;
119
135
 
136
+ private:
120
137
  /// Decode FastScan code to RaBitQ residual vector with explicit
121
138
  /// dp_multiplier
122
139
  void decode_fastscan_to_residual(
@@ -148,17 +165,16 @@ struct IndexIVFRaBitQFastScan : IndexIVFFastScan {
148
165
  const IVFSearchParameters* params = nullptr,
149
166
  IndexIVFStats* stats = nullptr) const override;
150
167
 
151
- /// Override to create RaBitQ-specific handlers
152
- SIMDResultHandlerToFloat* make_knn_handler(
168
+ /// RaBitQ scanner via rabitq_ivf_make_knn_scanner
169
+ std::unique_ptr<FastScanCodeScanner> make_knn_scanner(
153
170
  bool is_max,
154
- int /* impl */,
155
171
  idx_t n,
156
172
  idx_t k,
157
173
  float* distances,
158
174
  idx_t* labels,
159
175
  const IDSelector* sel,
160
- const FastScanDistancePostProcessing& context,
161
- const float* normalizers = nullptr) const override;
176
+ int impl = 0,
177
+ const FastScanDistancePostProcessing& context = {}) const override;
162
178
 
163
179
  /// Get an InvertedListScanner for single-query scanning.
164
180
  /// This provides compatibility with the standard IVF search interface
@@ -167,89 +183,228 @@ struct IndexIVFRaBitQFastScan : IndexIVFFastScan {
167
183
  const IDSelector* sel = nullptr,
168
184
  const IVFSearchParameters* params = nullptr) const override;
169
185
 
170
- /** SIMD result handler for IndexIVFRaBitQFastScan that applies
171
- * RaBitQ-specific distance corrections during batch processing.
172
- *
173
- * This handler processes batches of 32 distance computations from SIMD
174
- * kernels, applies RaBitQ distance formula adjustments (factors and
175
- * normalizers), and immediately updates result heaps. This eliminates the
176
- * need for post-processing and provides significant performance benefits.
177
- *
178
- * Key optimizations:
179
- * - Direct heap integration with no intermediate result storage
180
- * - Batch-level computation of normalizers and query factors
181
- * - Specialized handling for both centered and non-centered quantization
182
- * modes
183
- * - Efficient inner product metric corrections
184
- * - Uses runtime boolean for multi-bit mode
185
- *
186
- * @tparam C Comparator type (CMin/CMax) for heap operations
187
- */
186
+ /// RaBitQ-specific result handler (defined in impl/fast_scan/)
188
187
  template <class C>
189
- struct IVFRaBitQHeapHandler
190
- : simd_result_handlers::ResultHandlerCompare<C, true> {
191
- const IndexIVFRaBitQFastScan* index;
192
- float* heap_distances; // [nq * k]
193
- int64_t* heap_labels; // [nq * k]
194
- const size_t nq, k;
195
- size_t current_list_no = 0;
196
- const uint8_t* list_codes_ptr = nullptr; // raw block data for list
197
- std::vector<int>
198
- probe_indices; // probe index for each query in current batch
199
- const FastScanDistancePostProcessing*
200
- context; // Processing context with query factors
201
- const bool is_multibit; // Whether to use multi-bit two-stage search
202
- size_t nup = 0; // Number of heap updates
203
-
204
- // Cached block-layout constants (invariant for handler lifetime)
205
- const size_t storage_size;
206
- const size_t packed_block_size;
207
- const size_t full_block_size;
208
- std::unique_ptr<CodePacker> packer; // cached for unpack in hot path
209
-
210
- // Use float-based comparator for heap operations
211
- using Cfloat = typename std::conditional<
212
- C::is_max,
213
- CMax<float, int64_t>,
214
- CMin<float, int64_t>>::type;
215
-
216
- IVFRaBitQHeapHandler(
217
- const IndexIVFRaBitQFastScan* idx,
218
- size_t nq_val,
219
- size_t k_val,
220
- float* distances,
221
- int64_t* labels,
222
- const FastScanDistancePostProcessing* ctx = nullptr,
223
- bool multibit = false);
224
-
225
- void handle(size_t q, size_t b, simd16uint16 d0, simd16uint16 d1)
226
- override;
227
-
228
- /// Override base class virtual method to receive context information
229
- void set_list_context(size_t list_no, const std::vector<int>& probe_map)
230
- override;
231
-
232
- void begin(const float* norms) override;
233
-
234
- void end() override;
235
-
236
- size_t num_updates() override {
237
- return nup;
188
+ using IVFRaBitQHeapHandler = simd_result_handlers::IVFRaBitQHeapHandler<C>;
189
+ };
190
+
191
+ /*********************************************************
192
+ * IVFRaBitQHeapHandler method bodies — defined here (after
193
+ * IndexIVFRaBitQFastScan is complete) to break the circular
194
+ * dependency between rabitq_result_handler.h and this header.
195
+ *********************************************************/
196
+
197
+ namespace simd_result_handlers {
198
+
199
+ template <class C, SIMDLevel SL>
200
+ IVFRaBitQHeapHandler<C, SL>::IVFRaBitQHeapHandler(
201
+ const IndexIVFRaBitQFastScan* idx,
202
+ size_t nq_val,
203
+ size_t k_val,
204
+ float* distances,
205
+ int64_t* labels,
206
+ const IDSelector* sel,
207
+ const FastScanDistancePostProcessing* ctx,
208
+ bool multibit)
209
+ : ResultHandlerCompare<C, true, SL>(nq_val, 0, sel),
210
+ index(idx),
211
+ heap_distances(distances),
212
+ heap_labels(labels),
213
+ nq(nq_val),
214
+ k(k_val),
215
+ context(ctx),
216
+ is_multibit(multibit),
217
+ storage_size(idx->compute_per_vector_storage_size()),
218
+ packed_block_size(((idx->M2 + 1) / 2) * idx->bbs),
219
+ full_block_size(idx->get_block_stride()),
220
+ unpack_buf((idx->d + 7) / 8) {
221
+ current_list_no = 0;
222
+ probe_indices.clear();
223
+ for (int64_t q = 0; q < static_cast<int64_t>(nq); q++) {
224
+ heap_heapify<Cfloat>(k, heap_distances + q * k, heap_labels + q * k);
225
+ }
226
+ }
227
+
228
+ template <class C, SIMDLevel SL>
229
+ void IVFRaBitQHeapHandler<C, SL>::handle(
230
+ size_t q,
231
+ size_t b,
232
+ simd16uint16 d0,
233
+ simd16uint16 d1) {
234
+ size_t local_q = q;
235
+ this->adjust_with_origin(q, d0, d1);
236
+
237
+ ALIGNED(32) uint16_t d32tab[32];
238
+ d0.store(d32tab);
239
+ d1.store(d32tab + 16);
240
+
241
+ float* const heap_dis = heap_distances + q * k;
242
+ int64_t* const heap_ids = heap_labels + q * k;
243
+
244
+ FAISS_THROW_IF_NOT_FMT(
245
+ !probe_indices.empty() && local_q < probe_indices.size(),
246
+ "set_list_context() must be called before handle() - probe_indices size: %zu, local_q: %zu, global_q: %zu",
247
+ probe_indices.size(),
248
+ local_q,
249
+ q);
250
+
251
+ if (!context || !context->query_factors) {
252
+ FAISS_THROW_MSG(
253
+ "Query factors not available: FastScanDistancePostProcessing with query_factors required");
254
+ }
255
+
256
+ const size_t probe_rank = probe_indices[local_q];
257
+ const size_t storage_idx = q * cached_nprobe + probe_rank;
258
+ const auto& query_factors = context->query_factors[storage_idx];
259
+
260
+ const float one_a =
261
+ this->normalizers ? (1.0f / this->normalizers[2 * q]) : 1.0f;
262
+ const float bias = this->normalizers ? this->normalizers[2 * q + 1] : 0.0f;
263
+
264
+ const uint64_t idx_base = this->j0 + b * 32;
265
+ if (idx_base >= this->ntotal) {
266
+ return;
267
+ }
268
+ const size_t max_positions = std::min<size_t>(32, this->ntotal - idx_base);
269
+
270
+ // Hoist aux pointer base out of loop: all 32 elements in this block share
271
+ // the same block base. Only the per-element offset (j * storage_size)
272
+ // varies.
273
+ const uint8_t* aux_base = this->list_codes_ptr +
274
+ (idx_base / index->bbs) * full_block_size + packed_block_size;
275
+
276
+ // Cache index fields used in the inner loop.
277
+ // Use overridden qb/centered from context if provided, else index defaults.
278
+ const bool centered = context->qb > 0 ? context->centered : index->centered;
279
+ const size_t qb = context->qb > 0 ? context->qb : index->qb;
280
+ const size_t d = index->d;
281
+
282
+ for (size_t j = 0; j < max_positions; j++) {
283
+ const int64_t result_id = this->adjust_id(b, j);
284
+ if (result_id < 0) {
285
+ continue;
286
+ }
287
+ if (this->sel != nullptr && !this->sel->is_member(result_id)) {
288
+ continue;
238
289
  }
239
290
 
240
- private:
241
- /// Compute full multi-bit distance for a candidate vector (multi-bit
242
- /// only)
243
- /// @param db_idx Global database vector index
244
- /// @param local_q Batch-local query index (for probe_indices access)
245
- /// @param global_q Global query index (for storage indexing)
246
- /// @param local_offset Offset within the current inverted list
247
- float compute_full_multibit_distance(
248
- size_t /*db_idx*/,
249
- size_t local_q,
250
- size_t global_q,
251
- size_t local_offset) const;
252
- };
253
- };
291
+ this->scan_cnt++;
292
+
293
+ const float normalized_distance = d32tab[j] * one_a + bias;
294
+ const uint8_t* base_ptr = aux_base + j * storage_size;
295
+
296
+ if (is_multibit) {
297
+ const SignBitFactorsWithError& full_factors =
298
+ *reinterpret_cast<const SignBitFactorsWithError*>(base_ptr);
299
+
300
+ float dist_1bit = rabitq_utils::compute_1bit_adjusted_distance(
301
+ normalized_distance,
302
+ full_factors,
303
+ query_factors,
304
+ centered,
305
+ qb,
306
+ d);
307
+
308
+ bool should_refine = rabitq_utils::should_refine_candidate(
309
+ dist_1bit,
310
+ full_factors.f_error,
311
+ query_factors.g_error,
312
+ heap_dis[0],
313
+ is_similarity);
314
+ if (should_refine) {
315
+ size_t local_offset = idx_base + j;
316
+ float dist_full = compute_full_multibit_distance(
317
+ local_q, q, local_offset, base_ptr);
318
+ if (Cfloat::cmp(heap_dis[0], dist_full)) {
319
+ heap_replace_top<Cfloat>(
320
+ k, heap_dis, heap_ids, dist_full, result_id);
321
+ nup++;
322
+ }
323
+ }
324
+ } else {
325
+ const auto& db_factors =
326
+ *reinterpret_cast<const SignBitFactors*>(base_ptr);
327
+ float adjusted_distance =
328
+ rabitq_utils::compute_1bit_adjusted_distance(
329
+ normalized_distance,
330
+ db_factors,
331
+ query_factors,
332
+ centered,
333
+ qb,
334
+ d);
335
+ if (Cfloat::cmp(heap_dis[0], adjusted_distance)) {
336
+ heap_replace_top<Cfloat>(
337
+ k, heap_dis, heap_ids, adjusted_distance, result_id);
338
+ nup++;
339
+ }
340
+ }
341
+ }
342
+ }
343
+
344
+ template <class C, SIMDLevel SL>
345
+ void IVFRaBitQHeapHandler<C, SL>::set_list_context(
346
+ size_t list_no,
347
+ const std::vector<int>& probe_map) {
348
+ current_list_no = list_no;
349
+ probe_indices = probe_map;
350
+ cached_nprobe =
351
+ context && context->nprobe > 0 ? context->nprobe : index->nprobe;
352
+ is_similarity = index->metric_type == MetricType::METRIC_INNER_PRODUCT;
353
+ if (index->invlists) {
354
+ this->list_codes_ptr = index->invlists->get_codes(list_no);
355
+ }
356
+ }
357
+
358
+ template <class C, SIMDLevel SL>
359
+ void IVFRaBitQHeapHandler<C, SL>::begin(const float* norms) {
360
+ this->normalizers = norms;
361
+ }
362
+
363
+ template <class C, SIMDLevel SL>
364
+ void IVFRaBitQHeapHandler<C, SL>::end() {
365
+ #pragma omp parallel for
366
+ for (int64_t q = 0; q < static_cast<int64_t>(nq); q++) {
367
+ heap_reorder<Cfloat>(k, heap_distances + q * k, heap_labels + q * k);
368
+ }
369
+ }
370
+
371
+ template <class C, SIMDLevel SL>
372
+ float IVFRaBitQHeapHandler<C, SL>::compute_full_multibit_distance(
373
+ size_t local_q,
374
+ size_t global_q,
375
+ size_t local_offset,
376
+ const uint8_t* aux_ptr) {
377
+ const size_t ex_bits = index->rabitq.nb_bits - 1;
378
+ const size_t dim = index->d;
379
+
380
+ const size_t ex_code_size = (dim * ex_bits + 7) / 8;
381
+ const uint8_t* ex_code = aux_ptr + sizeof(SignBitFactorsWithError);
382
+ const ExtraBitsFactors& ex_fac = *reinterpret_cast<const ExtraBitsFactors*>(
383
+ aux_ptr + sizeof(SignBitFactorsWithError) + ex_code_size);
384
+
385
+ const size_t probe_rank = probe_indices[local_q];
386
+ const size_t storage_idx_val = global_q * cached_nprobe + probe_rank;
387
+ const auto& query_factors = context->query_factors[storage_idx_val];
388
+
389
+ rabitq_utils::unpack_sign_bits_from_packed(
390
+ this->list_codes_ptr,
391
+ index->bbs,
392
+ index->M2,
393
+ local_offset,
394
+ full_block_size,
395
+ unpack_buf.data());
396
+
397
+ return rabitq_utils::compute_full_multibit_distance(
398
+ unpack_buf.data(),
399
+ ex_code,
400
+ ex_fac,
401
+ query_factors.rotated_q.data(),
402
+ is_similarity ? query_factors.q_dot_c : query_factors.qr_to_c_L2sqr,
403
+ dim,
404
+ ex_bits,
405
+ index->metric_type);
406
+ }
407
+
408
+ } // namespace simd_result_handlers
254
409
 
255
410
  } // namespace faiss
@@ -10,6 +10,7 @@
10
10
  #include <faiss/IndexIVFSpectralHash.h>
11
11
 
12
12
  #include <algorithm>
13
+ #include <cmath>
13
14
  #include <cstdint>
14
15
  #include <memory>
15
16
 
@@ -20,27 +21,39 @@
20
21
  #include <faiss/impl/FaissAssert.h>
21
22
  #include <faiss/utils/hamming.h>
22
23
 
24
+ #include <faiss/impl/simd_dispatch.h>
25
+
26
+ // Scalar (NONE) fallback for dynamic dispatch
27
+ #define THE_SIMD_LEVEL SIMDLevel::NONE
28
+ // NOLINTNEXTLINE(facebook-hte-InlineHeader)
29
+ // NOLINTNEXTLINE(facebook-hte-InlineHeader)
30
+ #include <faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h>
31
+ #include <faiss/utils/hamming_distance/hamming_computer-generic.h>
32
+ #undef THE_SIMD_LEVEL
33
+
23
34
  namespace faiss {
24
35
 
25
36
  IndexIVFSpectralHash::IndexIVFSpectralHash(
26
- Index* quantizer,
27
- size_t d,
28
- size_t nlist,
29
- int nbit,
30
- float period,
31
- bool own_invlists)
37
+ Index* quantizer_in,
38
+ size_t d_in,
39
+ size_t nlist_in,
40
+ int nbit_in,
41
+ float period_in,
42
+ bool own_invlists_in)
32
43
  : IndexIVF(
33
- quantizer,
34
- d,
35
- nlist,
36
- (nbit + 7) / 8,
44
+ quantizer_in,
45
+ d_in,
46
+ nlist_in,
47
+ (nbit_in + 7) / 8,
37
48
  METRIC_L2,
38
- own_invlists),
39
- nbit(nbit),
40
- period(period) {
41
- RandomRotationMatrix* rr = new RandomRotationMatrix(d, nbit);
49
+ own_invlists_in),
50
+ nbit(nbit_in),
51
+ period(period_in) {
52
+ auto rr = std::make_unique<RandomRotationMatrix>(
53
+ static_cast<int>(d_in), nbit_in);
42
54
  rr->init(1234);
43
- vt = rr;
55
+ vt = rr.release();
56
+ own_fields = true;
44
57
  is_trained = false;
45
58
  by_residual = false;
46
59
  }
@@ -71,7 +84,7 @@ float median(size_t n, float* x) {
71
84
  void IndexIVFSpectralHash::train_encoder(
72
85
  idx_t n,
73
86
  const float* x,
74
- const idx_t* assign) {
87
+ const idx_t* /*assign*/) {
75
88
  if (!vt->is_trained) {
76
89
  vt->train(n, x);
77
90
  }
@@ -102,13 +115,13 @@ void IndexIVFSpectralHash::train_encoder(
102
115
  quantizer->assign(n, x, idx.get());
103
116
 
104
117
  std::vector<size_t> sizes(nlist + 1);
105
- for (size_t i = 0; i < n; i++) {
118
+ for (idx_t i = 0; i < n; i++) {
106
119
  FAISS_THROW_IF_NOT(idx[i] >= 0);
107
120
  sizes[idx[i]]++;
108
121
  }
109
122
 
110
123
  size_t ofs = 0;
111
- for (int j = 0; j < nlist; j++) {
124
+ for (size_t j = 0; j < nlist; j++) {
112
125
  size_t o0 = ofs;
113
126
  ofs += sizes[j];
114
127
  sizes[j] = o0;
@@ -120,9 +133,9 @@ void IndexIVFSpectralHash::train_encoder(
120
133
  // transpose + reorder
121
134
  std::unique_ptr<float[]> xo(new float[n * nbit]);
122
135
 
123
- for (size_t i = 0; i < n; i++) {
136
+ for (idx_t i = 0; i < n; i++) {
124
137
  size_t idest = sizes[idx[i]]++;
125
- for (size_t j = 0; j < nbit; j++) {
138
+ for (size_t j = 0; j < static_cast<size_t>(nbit); j++) {
126
139
  xo[idest + n * j] = xt[i * nbit + j];
127
140
  }
128
141
  }
@@ -130,7 +143,7 @@ void IndexIVFSpectralHash::train_encoder(
130
143
  trained.resize(n * nbit);
131
144
  // compute medians
132
145
  #pragma omp for
133
- for (int i = 0; i < nlist; i++) {
146
+ for (idx_t i = 0; i < static_cast<idx_t>(nlist); i++) {
134
147
  size_t i0 = i == 0 ? 0 : sizes[i - 1];
135
148
  size_t i1 = sizes[i];
136
149
  for (int j = 0; j < nbit; j++) {
@@ -157,7 +170,7 @@ void binarize_with_freq(
157
170
  memset(codes, 0, (nbit + 7) / 8);
158
171
  for (size_t i = 0; i < nbit; i++) {
159
172
  float xf = (x[i] - c[i]);
160
- int64_t xi = int64_t(floor(xf * freq));
173
+ int64_t xi = int64_t(std::floor(xf * freq));
161
174
  int64_t bit = xi & 1;
162
175
  codes[i >> 3] |= bit << (i & 7);
163
176
  }
@@ -205,114 +218,15 @@ void IndexIVFSpectralHash::encode_vectors(
205
218
  }
206
219
  }
207
220
 
208
- namespace {
209
-
210
- template <class HammingComputer>
211
- struct IVFScanner : InvertedListScanner {
212
- // copied from index structure
213
- const IndexIVFSpectralHash* index;
214
- size_t nbit;
215
-
216
- float period, freq;
217
- std::vector<float> q;
218
- std::vector<float> zero;
219
- std::vector<uint8_t> qcode;
220
- HammingComputer hc;
221
-
222
- IVFScanner(const IndexIVFSpectralHash* index, bool store_pairs)
223
- : index(index),
224
- nbit(index->nbit),
225
- period(index->period),
226
- freq(2.0 / index->period),
227
- q(nbit),
228
- zero(nbit),
229
- qcode(index->code_size),
230
- hc(qcode.data(), index->code_size) {
231
- this->store_pairs = store_pairs;
232
- this->code_size = index->code_size;
233
- this->keep_max = is_similarity_metric(index->metric_type);
234
- }
235
-
236
- void set_query(const float* query) override {
237
- FAISS_THROW_IF_NOT(query);
238
- FAISS_THROW_IF_NOT(q.size() == nbit);
239
- index->vt->apply_noalloc(1, query, q.data());
240
-
241
- if (index->threshold_type == IndexIVFSpectralHash::Thresh_global) {
242
- binarize_with_freq(nbit, freq, q.data(), zero.data(), qcode.data());
243
- hc.set(qcode.data(), code_size);
244
- }
245
- }
246
-
247
- void set_list(idx_t list_no, float /*coarse_dis*/) override {
248
- this->list_no = list_no;
249
- if (index->threshold_type != IndexIVFSpectralHash::Thresh_global) {
250
- const float* c = index->trained.data() + list_no * nbit;
251
- binarize_with_freq(nbit, freq, q.data(), c, qcode.data());
252
- hc.set(qcode.data(), code_size);
253
- }
254
- }
255
-
256
- float distance_to_code(const uint8_t* code) const final {
257
- return hc.hamming(code);
258
- }
259
-
260
- size_t scan_codes(
261
- size_t list_size,
262
- const uint8_t* codes,
263
- const idx_t* ids,
264
- float* simi,
265
- idx_t* idxi,
266
- size_t k) const override {
267
- size_t nup = 0;
268
- for (size_t j = 0; j < list_size; j++) {
269
- float dis = hc.hamming(codes);
270
-
271
- if (dis < simi[0]) {
272
- int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
273
- maxheap_replace_top(k, simi, idxi, dis, id);
274
- nup++;
275
- }
276
- codes += code_size;
277
- }
278
- return nup;
279
- }
280
-
281
- void scan_codes_range(
282
- size_t list_size,
283
- const uint8_t* codes,
284
- const idx_t* ids,
285
- float radius,
286
- RangeQueryResult& res) const override {
287
- for (size_t j = 0; j < list_size; j++) {
288
- float dis = hc.hamming(codes);
289
- if (dis < radius) {
290
- int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
291
- res.add(dis, id);
292
- }
293
- codes += code_size;
294
- }
295
- }
296
- };
297
-
298
- struct BuildScanner {
299
- using T = InvertedListScanner*;
300
-
301
- template <class HammingComputer>
302
- static T f(const IndexIVFSpectralHash* index, bool store_pairs) {
303
- return new IVFScanner<HammingComputer>(index, store_pairs);
304
- }
305
- };
306
-
307
- } // anonymous namespace
308
-
309
221
  InvertedListScanner* IndexIVFSpectralHash::get_InvertedListScanner(
310
222
  bool store_pairs,
311
223
  const IDSelector* sel,
312
224
  const IVFSearchParameters*) const {
313
225
  FAISS_THROW_IF_NOT(!sel);
314
- BuildScanner bs;
315
- return dispatch_HammingComputer(code_size, bs, this, store_pairs);
226
+ return with_simd_level([&]<SIMDLevel SL>() {
227
+ return make_spectral_hash_scanner_fixSL<SL>(
228
+ code_size, this, store_pairs);
229
+ });
316
230
  }
317
231
 
318
232
  void IndexIVFSpectralHash::replace_vt(VectorTransform* vt_in, bool own) {
@@ -323,8 +237,8 @@ void IndexIVFSpectralHash::replace_vt(VectorTransform* vt_in, bool own) {
323
237
  }
324
238
  vt = vt_in;
325
239
  threshold_type = Thresh_global;
326
- is_trained = quantizer->is_trained && quantizer->ntotal == nlist &&
327
- vt->is_trained;
240
+ is_trained = quantizer->is_trained &&
241
+ quantizer->ntotal == static_cast<idx_t>(nlist) && vt->is_trained;
328
242
  own_fields = own;
329
243
  }
330
244
 
@@ -32,7 +32,7 @@ struct IndexIVFSpectralHash : IndexIVF {
32
32
  /// transformation from d to nbit dim
33
33
  VectorTransform* vt = nullptr;
34
34
  /// own the vt
35
- bool own_fields = true;
35
+ bool own_fields = false;
36
36
 
37
37
  /// nb of bits of the binary signature
38
38
  int nbit = 0;