faiss 0.6.0 → 0.6.2

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 (378) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -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 +88 -97
  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 +89 -417
  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 +374 -206
  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 +467 -364
  41. data/vendor/faiss/faiss/IndexIVF.h +33 -12
  42. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +79 -76
  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 +39 -69
  48. data/vendor/faiss/faiss/IndexIVFFlat.h +32 -0
  49. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +56 -33
  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 +73 -846
  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 +23 -20
  56. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +30 -52
  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 +38 -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 +150 -20
  84. data/vendor/faiss/faiss/IndexScalarQuantizer.h +10 -0
  85. data/vendor/faiss/faiss/IndexShards.cpp +10 -9
  86. data/vendor/faiss/faiss/IndexShardsIVF.cpp +21 -15
  87. data/vendor/faiss/faiss/MatrixStats.cpp +5 -4
  88. data/vendor/faiss/faiss/MetaIndexes.cpp +19 -17
  89. data/vendor/faiss/faiss/MetaIndexes.h +1 -1
  90. data/vendor/faiss/faiss/MetricType.h +14 -7
  91. data/vendor/faiss/faiss/SuperKMeans.cpp +656 -0
  92. data/vendor/faiss/faiss/SuperKMeans.h +97 -0
  93. data/vendor/faiss/faiss/VectorTransform.cpp +237 -149
  94. data/vendor/faiss/faiss/VectorTransform.h +16 -16
  95. data/vendor/faiss/faiss/build.cpp +23 -0
  96. data/vendor/faiss/faiss/build.h +15 -0
  97. data/vendor/faiss/faiss/clone_index.cpp +48 -47
  98. data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +1 -1
  99. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +47 -47
  100. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +11 -0
  101. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +902 -12
  102. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +38 -38
  103. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +11 -0
  104. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +702 -10
  105. data/vendor/faiss/faiss/factory_tools.cpp +9 -0
  106. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +6 -5
  107. data/vendor/faiss/faiss/gpu/GpuResources.h +3 -2
  108. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +15 -16
  109. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +5 -4
  110. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +46 -0
  111. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +56 -0
  112. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +78 -1
  113. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +72 -0
  114. data/vendor/faiss/faiss/gpu/test/TestUtils.h +23 -0
  115. data/vendor/faiss/faiss/gpu/utils/CuvsFilterConvert.h +1 -1
  116. data/vendor/faiss/faiss/gpu/utils/CuvsUtils.h +21 -10
  117. data/vendor/faiss/faiss/gpu_metal/GpuIndexFlat.h +22 -0
  118. data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +35 -0
  119. data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +87 -0
  120. data/vendor/faiss/faiss/gpu_metal/MetalFlatKernels.h +40 -0
  121. data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +58 -0
  122. data/vendor/faiss/faiss/gpu_metal/MetalIndexFlat.h +65 -0
  123. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +181 -0
  124. data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +111 -0
  125. data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +45 -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/gpu_metal/impl/MetalIVFFlat.h +193 -0
  129. data/vendor/faiss/faiss/impl/AdSampling.cpp +103 -0
  130. data/vendor/faiss/faiss/impl/AdSampling.h +35 -0
  131. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +29 -25
  132. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +1 -0
  133. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +10 -9
  134. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +3 -0
  135. data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +244 -0
  136. data/vendor/faiss/faiss/impl/ClusteringHelpers.h +94 -0
  137. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +16 -16
  138. data/vendor/faiss/faiss/impl/CodePacker.cpp +3 -3
  139. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +1 -1
  140. data/vendor/faiss/faiss/impl/DistanceComputer.h +8 -8
  141. data/vendor/faiss/faiss/impl/FaissAssert.h +6 -3
  142. data/vendor/faiss/faiss/impl/FaissException.h +50 -3
  143. data/vendor/faiss/faiss/impl/HNSW.cpp +639 -507
  144. data/vendor/faiss/faiss/impl/HNSW.h +61 -44
  145. data/vendor/faiss/faiss/impl/IDSelector.cpp +15 -11
  146. data/vendor/faiss/faiss/impl/IDSelector.h +8 -8
  147. data/vendor/faiss/faiss/impl/InvertedListScannerStats.h +26 -0
  148. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +82 -77
  149. data/vendor/faiss/faiss/impl/NNDescent.cpp +62 -25
  150. data/vendor/faiss/faiss/impl/NNDescent.h +6 -2
  151. data/vendor/faiss/faiss/impl/NSG.cpp +53 -32
  152. data/vendor/faiss/faiss/impl/NSG.h +4 -4
  153. data/vendor/faiss/faiss/impl/Panorama.cpp +23 -6
  154. data/vendor/faiss/faiss/impl/Panorama.h +269 -87
  155. data/vendor/faiss/faiss/impl/PdxLayout.cpp +93 -0
  156. data/vendor/faiss/faiss/impl/PdxLayout.h +41 -0
  157. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +46 -32
  158. data/vendor/faiss/faiss/impl/PolysemousTraining.h +3 -3
  159. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +35 -35
  160. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +21 -16
  161. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +55 -25
  162. data/vendor/faiss/faiss/impl/Quantizer.h +2 -2
  163. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +55 -49
  164. data/vendor/faiss/faiss/impl/RaBitQUtils.h +65 -0
  165. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +302 -283
  166. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +26 -23
  167. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
  168. data/vendor/faiss/faiss/impl/ResultHandler.h +100 -75
  169. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +318 -7
  170. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +77 -1
  171. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +14 -11
  172. data/vendor/faiss/faiss/impl/VisitedTable.cpp +10 -10
  173. data/vendor/faiss/faiss/impl/VisitedTable.h +70 -28
  174. data/vendor/faiss/faiss/impl/approx_topk/approx_topk.h +276 -0
  175. data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +68 -0
  176. data/vendor/faiss/faiss/{utils → impl}/approx_topk/generic.h +15 -8
  177. data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +68 -0
  178. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab-inl.h +169 -0
  179. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab.h +117 -0
  180. data/vendor/faiss/faiss/impl/approx_topk/simdlib256-inl.h +146 -0
  181. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h +73 -0
  182. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +270 -0
  183. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +460 -0
  184. data/vendor/faiss/faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h +159 -0
  185. data/vendor/faiss/faiss/impl/binary_hamming/IndexPQ_impl.h +92 -0
  186. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +26 -0
  187. data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +26 -0
  188. data/vendor/faiss/faiss/impl/binary_hamming/dispatch.h +143 -0
  189. data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +26 -0
  190. data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +26 -0
  191. data/vendor/faiss/faiss/impl/expanded_scanners.h +8 -3
  192. data/vendor/faiss/faiss/impl/{FastScanDistancePostProcessing.h → fast_scan/FastScanDistancePostProcessing.h} +13 -6
  193. data/vendor/faiss/faiss/impl/{LookupTableScaler.h → fast_scan/LookupTableScaler.h} +16 -5
  194. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +237 -0
  195. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +185 -0
  196. data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +229 -0
  197. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +270 -0
  198. data/vendor/faiss/faiss/impl/{pq4_fast_scan.cpp → fast_scan/fast_scan.cpp} +169 -2
  199. data/vendor/faiss/faiss/impl/fast_scan/fast_scan.h +341 -0
  200. data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +36 -0
  201. data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +40 -0
  202. data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +120 -0
  203. data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +104 -0
  204. data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +213 -0
  205. data/vendor/faiss/faiss/impl/{pq4_fast_scan_search_qbs.cpp → fast_scan/kernels_simd512.h} +26 -356
  206. data/vendor/faiss/faiss/impl/fast_scan/rabitq_dispatching.h +90 -0
  207. data/vendor/faiss/faiss/impl/fast_scan/rabitq_result_handler.h +108 -0
  208. data/vendor/faiss/faiss/impl/{simd_result_handlers.h → fast_scan/simd_result_handlers.h} +282 -134
  209. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +54 -0
  210. data/vendor/faiss/faiss/impl/hnsw/LockVector.h +64 -0
  211. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +83 -0
  212. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +113 -0
  213. data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +150 -0
  214. data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +142 -0
  215. data/vendor/faiss/faiss/impl/index_read.cpp +1227 -79
  216. data/vendor/faiss/faiss/impl/index_read_utils.h +1 -1
  217. data/vendor/faiss/faiss/impl/index_write.cpp +96 -13
  218. data/vendor/faiss/faiss/impl/io.cpp +6 -6
  219. data/vendor/faiss/faiss/impl/io_macros.h +58 -16
  220. data/vendor/faiss/faiss/impl/kmeans1d.cpp +10 -10
  221. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +37 -23
  222. data/vendor/faiss/faiss/impl/lattice_Zn.h +6 -6
  223. data/vendor/faiss/faiss/impl/mapped_io.cpp +6 -6
  224. data/vendor/faiss/faiss/impl/platform_macros.h +15 -4
  225. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +549 -0
  226. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +245 -0
  227. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.h +105 -0
  228. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +106 -0
  229. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +23 -0
  230. data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +23 -0
  231. data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +23 -0
  232. data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx2.cpp → pq_code_distance-avx2.h} +9 -13
  233. data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx512.cpp → pq_code_distance-avx512.h} +9 -57
  234. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +45 -107
  235. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +96 -0
  236. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +274 -5
  237. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +10 -7
  238. data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +105 -0
  239. data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +70 -0
  240. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +311 -477
  241. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
  242. data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +1 -1
  243. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +9 -2
  244. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +419 -19
  245. data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +27 -1
  246. data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +3 -3
  247. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +387 -2
  248. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +553 -0
  249. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +559 -0
  250. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +341 -2
  251. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +425 -3
  252. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +290 -2
  253. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +337 -0
  254. data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +192 -8
  255. data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +12 -0
  256. data/vendor/faiss/faiss/impl/simd_dispatch.h +157 -66
  257. data/vendor/faiss/faiss/impl/simdlib/simdlib.h +57 -0
  258. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_avx2.h +264 -172
  259. data/vendor/faiss/faiss/impl/simdlib/simdlib_avx512.h +414 -0
  260. data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +44 -0
  261. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_emulated.h +231 -166
  262. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_neon.h +270 -218
  263. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_ppc64.h +201 -160
  264. data/vendor/faiss/faiss/impl/svs_io.cpp +12 -3
  265. data/vendor/faiss/faiss/impl/svs_io.h +8 -2
  266. data/vendor/faiss/faiss/index_factory.cpp +90 -18
  267. data/vendor/faiss/faiss/index_io.h +40 -0
  268. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +66 -16
  269. data/vendor/faiss/faiss/invlists/DirectMap.cpp +28 -15
  270. data/vendor/faiss/faiss/invlists/DirectMap.h +4 -3
  271. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +170 -86
  272. data/vendor/faiss/faiss/invlists/InvertedLists.h +88 -25
  273. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +4 -4
  274. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +13 -13
  275. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  276. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +1 -1
  277. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +2 -2
  278. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +350 -0
  279. data/vendor/faiss/faiss/svs/IndexSVSIVF.h +128 -0
  280. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.cpp +40 -0
  281. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.h +43 -0
  282. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +225 -0
  283. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.h +71 -0
  284. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +142 -21
  285. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +33 -7
  286. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +3 -2
  287. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
  288. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +77 -27
  289. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +10 -4
  290. data/vendor/faiss/faiss/utils/Heap.cpp +10 -10
  291. data/vendor/faiss/faiss/utils/NeuralNet.cpp +47 -36
  292. data/vendor/faiss/faiss/utils/NeuralNet.h +1 -1
  293. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +10 -4
  294. data/vendor/faiss/faiss/utils/bf16.h +34 -0
  295. data/vendor/faiss/faiss/utils/distances.cpp +390 -560
  296. data/vendor/faiss/faiss/utils/distances.h +20 -1
  297. data/vendor/faiss/faiss/utils/distances_dispatch.h +117 -37
  298. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +8 -7
  299. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +33 -14
  300. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +12 -1
  301. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +16 -293
  302. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +57 -0
  303. data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +290 -0
  304. data/vendor/faiss/faiss/utils/distances_simd.cpp +5 -178
  305. data/vendor/faiss/faiss/utils/extra_distances.cpp +9 -8
  306. data/vendor/faiss/faiss/utils/extra_distances.h +32 -6
  307. data/vendor/faiss/faiss/utils/hamming-inl.h +13 -11
  308. data/vendor/faiss/faiss/utils/hamming.cpp +66 -517
  309. data/vendor/faiss/faiss/utils/hamming.h +92 -2
  310. data/vendor/faiss/faiss/utils/hamming_distance/common.h +287 -10
  311. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +16 -0
  312. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +15 -0
  313. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +15 -0
  314. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx2.h +142 -0
  315. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +210 -0
  316. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_spr.h +171 -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 -989
  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 +2 -2
  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 +57 -536
  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 +5 -1
  335. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +213 -4
  336. data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +163 -10
  337. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +250 -4
  338. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +7 -4
  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 +2 -1
  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 +1031 -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_avx512_spr.cpp +343 -0
  350. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +55 -0
  351. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +55 -0
  352. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +32 -0
  353. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +43 -0
  354. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +57 -0
  355. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +45 -0
  356. data/vendor/faiss/faiss/utils/simd_levels.cpp +29 -7
  357. data/vendor/faiss/faiss/utils/simd_levels.h +93 -1
  358. data/vendor/faiss/faiss/utils/sorting.cpp +48 -36
  359. data/vendor/faiss/faiss/utils/utils.cpp +5 -5
  360. data/vendor/faiss/faiss/utils/utils.h +3 -3
  361. metadata +129 -34
  362. data/vendor/faiss/faiss/impl/RaBitQStats.cpp +0 -29
  363. data/vendor/faiss/faiss/impl/RaBitQStats.h +0 -56
  364. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +0 -224
  365. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +0 -230
  366. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +0 -84
  367. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +0 -196
  368. data/vendor/faiss/faiss/utils/approx_topk/mode.h +0 -34
  369. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +0 -36
  370. data/vendor/faiss/faiss/utils/extra_distances-inl.h +0 -235
  371. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +0 -462
  372. data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +0 -490
  373. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -449
  374. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +0 -87
  375. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +0 -524
  376. data/vendor/faiss/faiss/utils/simdlib.h +0 -42
  377. data/vendor/faiss/faiss/utils/simdlib_avx512.h +0 -365
  378. /data/ext/faiss/{utils_rb.h → utils.h} +0 -0
@@ -13,12 +13,15 @@
13
13
  #include <cstdio>
14
14
  #include <cstring>
15
15
  #include <memory>
16
+ #include <type_traits>
16
17
 
17
18
  #include <algorithm>
18
19
 
19
20
  #include <faiss/IndexFlat.h>
20
21
  #include <faiss/VectorTransform.h>
21
22
  #include <faiss/impl/FaissAssert.h>
23
+ // NOLINTNEXTLINE(facebook-hte-InlineHeader)
24
+ #include <faiss/impl/pq_code_distance/pq_code_distance-inl.h>
22
25
  #include <faiss/impl/simd_dispatch.h>
23
26
  #include <faiss/utils/distances.h>
24
27
 
@@ -48,8 +51,8 @@ namespace faiss {
48
51
  * PQ implementation
49
52
  *********************************************/
50
53
 
51
- ProductQuantizer::ProductQuantizer(size_t d, size_t M, size_t nbits)
52
- : Quantizer(d, 0), M(M), nbits(nbits), assign_index(nullptr) {
54
+ ProductQuantizer::ProductQuantizer(size_t d_in, size_t M_in, size_t nbits_in)
55
+ : Quantizer(d_in, 0), M(M_in), nbits(nbits_in), assign_index(nullptr) {
53
56
  set_derived_values();
54
57
  }
55
58
 
@@ -139,8 +142,8 @@ void ProductQuantizer::train(size_t n, const float* x) {
139
142
  }
140
143
 
141
144
  std::unique_ptr<float[]> xslice(new float[n * dsub]);
142
- for (int m = 0; m < M; m++) {
143
- for (int j = 0; j < n; j++)
145
+ for (size_t m = 0; m < M; m++) {
146
+ for (size_t j = 0; j < n; j++)
144
147
  memcpy(xslice.get() + j * dsub,
145
148
  x + j * d + m * dsub,
146
149
  dsub * sizeof(float));
@@ -179,7 +182,7 @@ void ProductQuantizer::train(size_t n, const float* x) {
179
182
 
180
183
  if (verbose) {
181
184
  clus.verbose = true;
182
- printf("Training PQ slice %d/%zd\n", m, M);
185
+ printf("Training PQ slice %zd/%zd\n", m, M);
183
186
  }
184
187
  IndexFlatL2 index(dsub);
185
188
  clus.train(n, xslice.get(), assign_index ? *assign_index : index);
@@ -197,7 +200,7 @@ void ProductQuantizer::train(size_t n, const float* x) {
197
200
  IndexFlatL2 index(dsub);
198
201
 
199
202
  clus.train(n * M, x, assign_index ? *assign_index : index);
200
- for (int m = 0; m < M; m++) {
203
+ for (size_t m = 0; m < M; m++) {
201
204
  set_params(clus.centroids.data(), m);
202
205
  }
203
206
  }
@@ -322,8 +325,9 @@ void ProductQuantizer::decode(const uint8_t* code, float* x) const {
322
325
  }
323
326
 
324
327
  void ProductQuantizer::decode(const uint8_t* code, float* x, size_t n) const {
328
+ int64_t n_signed = n;
325
329
  #pragma omp parallel for if (n > 100)
326
- for (int64_t i = 0; i < n; i++) {
330
+ for (int64_t i = 0; i < n_signed; i++) {
327
331
  this->decode(code + code_size * i, x + d * i);
328
332
  }
329
333
  }
@@ -353,7 +357,8 @@ void ProductQuantizer::compute_codes_with_assign_index(
353
357
  const float* x,
354
358
  uint8_t* codes,
355
359
  size_t n) {
356
- FAISS_THROW_IF_NOT(assign_index && assign_index->d == dsub);
360
+ FAISS_THROW_IF_NOT(
361
+ assign_index && static_cast<size_t>(assign_index->d) == dsub);
357
362
 
358
363
  for (size_t m = 0; m < M; m++) {
359
364
  assign_index->reset();
@@ -415,10 +420,11 @@ void ProductQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
415
420
  return;
416
421
  }
417
422
 
423
+ int64_t n_signed = n;
418
424
  if (dsub < 16) { // simple direct computation
419
425
 
420
426
  #pragma omp parallel for
421
- for (int64_t i = 0; i < n; i++)
427
+ for (int64_t i = 0; i < n_signed; i++)
422
428
  compute_code(x + i * d, codes + i * code_size);
423
429
 
424
430
  } else { // worthwhile to use BLAS
@@ -426,7 +432,7 @@ void ProductQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
426
432
  compute_distance_tables(n, x, dis_tables.get());
427
433
 
428
434
  #pragma omp parallel for
429
- for (int64_t i = 0; i < n; i++) {
435
+ for (int64_t i = 0; i < n_signed; i++) {
430
436
  uint8_t* code = codes + i * code_size;
431
437
  const float* tab = dis_tables.get() + i * ksub * M;
432
438
  compute_code_from_distance_table(tab, code);
@@ -482,7 +488,8 @@ void ProductQuantizer::compute_distance_tables(
482
488
  size_t nx,
483
489
  const float* x,
484
490
  float* dis_tables) const {
485
- #if defined(__AVX2__) || defined(__aarch64__)
491
+ int64_t nx_signed = nx;
492
+ #if defined(COMPILE_SIMD_AVX2) || defined(COMPILE_SIMD_ARM_NEON)
486
493
  if (dsub == 2 && nbits < 8) { // interesting for a narrow range of settings
487
494
  compute_PQ_dis_tables_dsub2(
488
495
  d, ksub, centroids.data(), nx, x, false, dis_tables);
@@ -491,13 +498,13 @@ void ProductQuantizer::compute_distance_tables(
491
498
  if (dsub < 16) {
492
499
 
493
500
  #pragma omp parallel for if (nx > 1)
494
- for (int64_t i = 0; i < nx; i++) {
501
+ for (int64_t i = 0; i < nx_signed; i++) {
495
502
  compute_distance_table(x + i * d, dis_tables + i * ksub * M);
496
503
  }
497
504
 
498
505
  } else { // use BLAS
499
506
 
500
- for (int m = 0; m < M; m++) {
507
+ for (size_t m = 0; m < M; m++) {
501
508
  pairwise_L2sqr(
502
509
  dsub,
503
510
  nx,
@@ -516,7 +523,8 @@ void ProductQuantizer::compute_inner_prod_tables(
516
523
  size_t nx,
517
524
  const float* x,
518
525
  float* dis_tables) const {
519
- #if defined(__AVX2__) || defined(__aarch64__)
526
+ int64_t nx_signed = nx;
527
+ #if defined(COMPILE_SIMD_AVX2) || defined(COMPILE_SIMD_ARM_NEON)
520
528
  if (dsub == 2 && nbits < 8) {
521
529
  compute_PQ_dis_tables_dsub2(
522
530
  d, ksub, centroids.data(), nx, x, true, dis_tables);
@@ -525,14 +533,14 @@ void ProductQuantizer::compute_inner_prod_tables(
525
533
  if (dsub < 16) {
526
534
 
527
535
  #pragma omp parallel for if (nx > 1)
528
- for (int64_t i = 0; i < nx; i++) {
536
+ for (int64_t i = 0; i < nx_signed; i++) {
529
537
  compute_inner_prod_table(x + i * d, dis_tables + i * ksub * M);
530
538
  }
531
539
 
532
540
  } else { // use BLAS
533
541
 
534
542
  // compute distance tables
535
- for (int m = 0; m < M; m++) {
543
+ for (size_t m = 0; m < M; m++) {
536
544
  FINTEGER ldc = ksub * M, nxi = nx, ksubi = ksub, dsubi = dsub,
537
545
  di = d;
538
546
  float one = 1.0, zero = 0;
@@ -576,7 +584,7 @@ void pq_estimators_from_tables_Mmul4(
576
584
  float dis = 0;
577
585
  const float* dt = dis_table;
578
586
 
579
- for (size_t m = 0; m < M; m += 4) {
587
+ for (int m = 0; m < M; m += 4) {
580
588
  float dism = 0;
581
589
  dism = dt[*codes++];
582
590
  dt += ksub;
@@ -648,7 +656,7 @@ void pq_estimators_from_tables(
648
656
  for (size_t j = 0; j < ncodes; j++) {
649
657
  float dis = 0;
650
658
  const float* __restrict dt = dis_table;
651
- for (int m = 0; m < M; m++) {
659
+ for (size_t m = 0; m < M; m++) {
652
660
  dis += dt[*codes++];
653
661
  dt += ksub;
654
662
  }
@@ -696,10 +704,11 @@ void pq_knn_search_with_tables(
696
704
  HeapArray<C>* res,
697
705
  bool init_finalize_heap) {
698
706
  size_t k = res->k, nx = res->nh;
707
+ int64_t nx_signed = nx;
699
708
  size_t ksub = pq.ksub, M = pq.M;
700
709
 
701
710
  #pragma omp parallel for if (nx > 1)
702
- for (int64_t i = 0; i < nx; i++) {
711
+ for (int64_t i = 0; i < nx_signed; i++) {
703
712
  /* query preparation for asymmetric search: compute look-up tables */
704
713
  const float* dis_table = dis_tables + i * ksub * M;
705
714
 
@@ -713,8 +722,28 @@ void pq_knn_search_with_tables(
713
722
 
714
723
  switch (nbits) {
715
724
  case 8:
716
- pq_estimators_from_tables<uint8_t, C>(
717
- pq, codes, ncodes, dis_table, k, heap_dis, heap_ids);
725
+ if (ksub == 256) {
726
+ constexpr bool max_heap =
727
+ std::is_same_v<C, CMax<float, int64_t>>;
728
+ pq_code_distance::pq_scan_8bit(
729
+ M,
730
+ dis_table,
731
+ codes,
732
+ ncodes,
733
+ k,
734
+ heap_dis,
735
+ heap_ids,
736
+ max_heap);
737
+ } else {
738
+ pq_estimators_from_tables<uint8_t, C>(
739
+ pq,
740
+ codes,
741
+ ncodes,
742
+ dis_table,
743
+ k,
744
+ heap_dis,
745
+ heap_ids);
746
+ }
718
747
  break;
719
748
 
720
749
  case 16:
@@ -797,7 +826,7 @@ void ProductQuantizer::compute_sdc_table() {
797
826
  if (dsub < 4) {
798
827
  with_simd_level([&]<SIMDLevel SL>() {
799
828
  #pragma omp parallel for
800
- for (int mk = 0; mk < M * ksub; mk++) {
829
+ for (int64_t mk = 0; mk < static_cast<int64_t>(M * ksub); mk++) {
801
830
  // allow omp to schedule in a more fine-grained way
802
831
  // `collapse` is not supported in OpenMP 2.x
803
832
  int m = mk / ksub;
@@ -812,7 +841,7 @@ void ProductQuantizer::compute_sdc_table() {
812
841
  // NOTE: it would disable the omp loop in pairwise_L2sqr
813
842
  // but still accelerate especially when M >= 4
814
843
  #pragma omp parallel for
815
- for (int m = 0; m < M; m++) {
844
+ for (int64_t m = 0; m < static_cast<int64_t>(M); m++) {
816
845
  const float* cents = centroids.data() + m * ksub * dsub;
817
846
  float* dis_tab = sdc_table.data() + m * ksub * ksub;
818
847
  pairwise_L2sqr(
@@ -831,9 +860,10 @@ void ProductQuantizer::search_sdc(
831
860
  FAISS_THROW_IF_NOT(sdc_table.size() == M * ksub * ksub);
832
861
  FAISS_THROW_IF_NOT(nbits == 8);
833
862
  size_t k = res->k;
863
+ int64_t nq_signed = nq;
834
864
 
835
865
  #pragma omp parallel for
836
- for (int64_t i = 0; i < nq; i++) {
866
+ for (int64_t i = 0; i < nq_signed; i++) {
837
867
  /* Compute distances and keep smallest values */
838
868
  idx_t* heap_ids = res->ids + i * k;
839
869
  float* heap_dis = res->val + i * k;
@@ -846,7 +876,7 @@ void ProductQuantizer::search_sdc(
846
876
  for (size_t j = 0; j < nb; j++) {
847
877
  float dis = 0;
848
878
  const float* tab = sdc_table.data();
849
- for (int m = 0; m < M; m++) {
879
+ for (size_t m = 0; m < M; m++) {
850
880
  dis += tab[bcode[m] + qcode[m] * ksub];
851
881
  tab += ksub * ksub;
852
882
  }
@@ -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,6 +8,7 @@
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>
12
13
  #include <faiss/utils/rabitq_simd.h>
13
14
  #include <algorithm>
@@ -153,6 +154,7 @@ QueryFactorsData compute_query_factors(
153
154
  std::vector<uint8_t>& rotated_qq) {
154
155
  FAISS_THROW_IF_NOT(qb <= 8);
155
156
  FAISS_THROW_IF_NOT(qb > 0);
157
+ FAISS_THROW_IF_NOT(d > 0);
156
158
 
157
159
  QueryFactorsData query_factors;
158
160
 
@@ -165,38 +167,42 @@ QueryFactorsData compute_query_factors(
165
167
  query_factors.g_error = std::sqrt(query_factors.qr_to_c_L2sqr);
166
168
 
167
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)");
168
176
  rotated_q.resize(d);
169
- for (size_t i = 0; i < d; i++) {
170
- if (i < rotated_q.size()) {
171
- rotated_q[i] =
172
- 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];
173
186
  }
174
187
  }
175
188
 
176
- const float inv_d_sqrt =
177
- (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));
178
190
 
179
191
  // Compute quantization range
180
192
  float v_min = std::numeric_limits<float>::max();
181
193
  float v_max = std::numeric_limits<float>::lowest();
182
194
 
195
+ const float* rq = rotated_q.data();
183
196
  if (centered) {
184
197
  float z_max = Z_MAX_BY_QB[qb - 1];
185
198
  float v_radius = z_max * std::sqrt(query_factors.qr_to_c_L2sqr / d);
186
199
  v_min = -v_radius;
187
200
  v_max = v_radius;
188
201
  } else {
189
- // Only compute min/max if we have dimensions to process
190
- if (d > 0 && !rotated_q.empty()) {
191
- for (size_t i = 0; i < d; i++) {
192
- const float v_q = rotated_q[i];
193
- v_min = std::min(v_min, v_q);
194
- v_max = std::max(v_max, v_q);
195
- }
196
- } else {
197
- // For empty dimensions, use default range
198
- v_min = 0.0f;
199
- 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);
200
206
  }
201
207
  }
202
208
 
@@ -209,25 +215,18 @@ QueryFactorsData compute_query_factors(
209
215
  size_t sum_qq = 0;
210
216
  int64_t sum2_signed_odd_int = 0;
211
217
 
212
- // Process arrays - throw error if they are unexpectedly empty
213
- if (d > 0 && !rotated_q.empty() && !rotated_qq.empty()) {
214
- for (size_t i = 0; i < d; i++) {
215
- const float v_q = rotated_q[i];
216
- // Non-randomized scalar quantization
217
- const uint8_t v_qq = std::clamp<float>(
218
- std::round((v_q - v_min) * inv_delta), 0, max_code);
219
- rotated_qq[i] = v_qq;
220
- sum_qq += v_qq;
221
-
222
- if (centered) {
223
- int64_t signed_odd_int = int64_t(v_qq) * 2 - max_code;
224
- sum2_signed_odd_int += signed_odd_int * signed_odd_int;
225
- }
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;
226
229
  }
227
- } else {
228
- FAISS_THROW_MSG(
229
- "Arrays unexpectedly empty when d=" + std::to_string(d) +
230
- "or d is incorrectly set");
231
230
  }
232
231
 
233
232
  // Compute query factors
@@ -242,11 +241,15 @@ QueryFactorsData compute_query_factors(
242
241
  query_factors.int_dot_scale = 1.0f;
243
242
  }
244
243
 
245
- // 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.
246
247
  query_factors.qr_norm_L2sqr = 0.0f;
247
248
  query_factors.q_dot_c = 0.0f;
248
249
  if (metric_type == MetricType::METRIC_INNER_PRODUCT) {
249
- 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);
250
253
  if (centroid != nullptr) {
251
254
  query_factors.q_dot_c = fvec_inner_product(query, centroid, d);
252
255
  }
@@ -306,6 +309,9 @@ size_t compute_per_vector_storage_size(size_t nb_bits, size_t d) {
306
309
  }
307
310
  }
308
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.
309
315
  float compute_full_multibit_distance(
310
316
  const uint8_t* sign_bits,
311
317
  const uint8_t* ex_code,
@@ -315,18 +321,18 @@ float compute_full_multibit_distance(
315
321
  size_t d,
316
322
  size_t ex_bits,
317
323
  MetricType metric_type) {
318
- const float cb = -(static_cast<float>(1 << ex_bits) - 0.5f);
319
-
320
- float ex_ip = rabitq::multibit::compute_inner_product(
321
- sign_bits, ex_code, rotated_q, d, ex_bits, cb);
322
-
323
- float dist = qr_base + ex_fac.f_add_ex + ex_fac.f_rescale_ex * ex_ip;
324
-
325
- if (metric_type == MetricType::METRIC_L2) {
326
- dist = std::max(0.0f, dist);
327
- }
328
-
329
- return dist;
324
+ return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_A0_SPR>(
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
+ });
330
336
  }
331
337
 
332
338
  void populate_block_aux_from_flat_storage(
@@ -10,6 +10,9 @@
10
10
  #include <faiss/MetricType.h>
11
11
  #include <faiss/impl/platform_macros.h>
12
12
  #include <faiss/utils/AlignedTable.h>
13
+ #include <faiss/utils/rabitq_simd.h>
14
+ #include <faiss/utils/simd_levels.h>
15
+ #include <algorithm>
13
16
  #include <cstddef>
14
17
  #include <cstdint>
15
18
  #include <cstring>
@@ -337,6 +340,33 @@ float compute_full_multibit_distance(
337
340
  size_t ex_bits,
338
341
  MetricType metric_type);
339
342
 
343
+ // SIMDLevel-templatized version — avoids per-call dynamic dispatch.
344
+ // Inline so it can be used from templatized distance computers without
345
+ // needing explicit instantiations in per-SIMD TUs.
346
+ template <SIMDLevel SL>
347
+ inline float compute_full_multibit_distance(
348
+ const uint8_t* sign_bits,
349
+ const uint8_t* ex_code,
350
+ const ExtraBitsFactors& ex_fac,
351
+ const float* rotated_q,
352
+ float qr_base,
353
+ size_t d,
354
+ size_t ex_bits,
355
+ MetricType metric_type) {
356
+ const float cb = -(static_cast<float>(1 << ex_bits) - 0.5f);
357
+
358
+ float ex_ip = rabitq::multibit::compute_inner_product<SL>(
359
+ sign_bits, ex_code, rotated_q, d, ex_bits, cb);
360
+
361
+ float dist = qr_base + ex_fac.f_add_ex + ex_fac.f_rescale_ex * ex_ip;
362
+
363
+ if (metric_type == MetricType::METRIC_L2) {
364
+ dist = std::max(0.0f, dist);
365
+ }
366
+
367
+ return dist;
368
+ }
369
+
340
370
  /** Compute pointer to a vector's auxiliary data within block layout. */
341
371
  template <typename T>
342
372
  inline T* get_block_aux_ptr(
@@ -350,6 +380,41 @@ inline T* get_block_aux_ptr(
350
380
  (vec_pos % bbs) * storage_size;
351
381
  }
352
382
 
383
+ /// Extract sign bits from PQ4-interleaved block into flat byte packing.
384
+ /// Like CodePackerRaBitQ::unpack_1 but sign-bits-only and with the
385
+ /// vector's in-block address hoisted out of the per-SQ loop.
386
+ inline void unpack_sign_bits_from_packed(
387
+ const uint8_t* block,
388
+ size_t bbs,
389
+ size_t nsq,
390
+ size_t offset,
391
+ size_t block_stride,
392
+ uint8_t* sign_bits_out) {
393
+ block += (offset / bbs) * block_stride;
394
+ offset = offset % bbs;
395
+
396
+ const bool nibble_high = offset > 15;
397
+ const size_t vid = offset & 15;
398
+ const size_t in_group_addr =
399
+ (vid < 8) ? (vid << 1) : (((vid - 8) << 1) + 1);
400
+
401
+ const size_t num_pairs = nsq / 2;
402
+ for (size_t k = 0; k < num_pairs; k++) {
403
+ const size_t base = k * bbs;
404
+ const uint8_t raw_even = block[base + in_group_addr];
405
+ const uint8_t raw_odd = block[base + in_group_addr + 16];
406
+
407
+ const uint8_t nib0 = nibble_high ? (raw_even >> 4) : (raw_even & 0xF);
408
+ const uint8_t nib1 = nibble_high ? (raw_odd >> 4) : (raw_odd & 0xF);
409
+ sign_bits_out[k] = nib0 | (nib1 << 4);
410
+ }
411
+
412
+ if (nsq & 1) {
413
+ const uint8_t raw = block[num_pairs * bbs + in_group_addr];
414
+ sign_bits_out[num_pairs] = nibble_high ? (raw >> 4) : (raw & 0xF);
415
+ }
416
+ }
417
+
353
418
  /** Compute per-vector auxiliary storage size.
354
419
  *
355
420
  * @param nb_bits number of quantization bits (1 = sign-bit only)