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
@@ -0,0 +1,368 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #ifndef HAMMING_COMPUTER_GENERIC_H
9
+ #define HAMMING_COMPUTER_GENERIC_H
10
+
11
+ // Scalar (NONE) HammingComputer specializations and hamming_popcount_tail
12
+ // utility. No ISA-specific intrinsics. Per-ISA files (hamming_computer-avx2.h,
13
+ // etc.) include this file and inherit or override the NONE specializations.
14
+
15
+ #include <faiss/utils/hamming_distance/hamming_computer.h>
16
+
17
+ namespace faiss {
18
+
19
+ /* Duff's device + byte remainder tail for HammingComputerDefault.
20
+ * Processes uint64 words starting at index i_start using popcount,
21
+ * then handles any remaining bytes via lookup table. */
22
+ inline int hamming_popcount_tail(
23
+ const uint64_t* a64,
24
+ const uint64_t* b64,
25
+ int i_start,
26
+ int quotient8,
27
+ const uint8_t* a8,
28
+ const uint8_t* b8,
29
+ int remainder8) {
30
+ int accu = 0;
31
+ int i = i_start;
32
+ int len = quotient8 - i_start;
33
+ switch (len & 7) {
34
+ default:
35
+ while (len > 7) {
36
+ len -= 8;
37
+ accu += popcount64(a64[i] ^ b64[i]);
38
+ i++;
39
+ [[fallthrough]];
40
+ case 7:
41
+ accu += popcount64(a64[i] ^ b64[i]);
42
+ i++;
43
+ [[fallthrough]];
44
+ case 6:
45
+ accu += popcount64(a64[i] ^ b64[i]);
46
+ i++;
47
+ [[fallthrough]];
48
+ case 5:
49
+ accu += popcount64(a64[i] ^ b64[i]);
50
+ i++;
51
+ [[fallthrough]];
52
+ case 4:
53
+ accu += popcount64(a64[i] ^ b64[i]);
54
+ i++;
55
+ [[fallthrough]];
56
+ case 3:
57
+ accu += popcount64(a64[i] ^ b64[i]);
58
+ i++;
59
+ [[fallthrough]];
60
+ case 2:
61
+ accu += popcount64(a64[i] ^ b64[i]);
62
+ i++;
63
+ [[fallthrough]];
64
+ case 1:
65
+ accu += popcount64(a64[i] ^ b64[i]);
66
+ i++;
67
+ }
68
+ }
69
+ if (remainder8) {
70
+ const uint8_t* a = a8 + 8 * quotient8;
71
+ const uint8_t* b = b8 + 8 * quotient8;
72
+ if (remainder8 >= 4) {
73
+ accu += popcount32(*(uint32_t*)a ^ *(uint32_t*)b);
74
+ a += 4;
75
+ b += 4;
76
+ remainder8 -= 4;
77
+ }
78
+ if (remainder8 >= 2) {
79
+ accu += popcount32(*(uint16_t*)a ^ *(uint16_t*)b);
80
+ a += 2;
81
+ b += 2;
82
+ remainder8 -= 2;
83
+ }
84
+ if (remainder8 >= 1) {
85
+ accu += popcount32(*a ^ *b);
86
+ remainder8 -= 2;
87
+ }
88
+ }
89
+ return accu;
90
+ }
91
+
92
+ /***************************************************************************
93
+ * HammingComputer NONE specializations — scalar bodies.
94
+ * Per-ISA backend files (hamming_computer-avx512.h, hamming_computer-neon.h,
95
+ * etc.) provide their own specializations; those without custom code
96
+ * inherit from NONE.
97
+ ***************************************************************************/
98
+
99
+ template <>
100
+ struct HammingComputer16_tpl<SIMDLevel::NONE> {
101
+ uint64_t a0, a1;
102
+
103
+ HammingComputer16_tpl() {}
104
+
105
+ HammingComputer16_tpl(const uint8_t* a8, int code_size) {
106
+ set(a8, code_size);
107
+ }
108
+
109
+ void set(const uint8_t* a8, FAISS_MAYBE_UNUSED int code_size) {
110
+ assert(code_size == 16);
111
+ const uint64_t* a = reinterpret_cast<const uint64_t*>(a8);
112
+ a0 = a[0];
113
+ a1 = a[1];
114
+ }
115
+
116
+ inline int hamming(const uint8_t* b8) const {
117
+ const uint64_t* b = reinterpret_cast<const uint64_t*>(b8);
118
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1);
119
+ }
120
+
121
+ inline static constexpr int get_code_size() {
122
+ return 16;
123
+ }
124
+ };
125
+
126
+ // when applied to an array, 1/2 of the 64-bit accesses are unaligned.
127
+ // This incurs a penalty of ~10% wrt. fully aligned accesses.
128
+ template <>
129
+ struct HammingComputer20_tpl<SIMDLevel::NONE> {
130
+ uint64_t a0, a1;
131
+ uint32_t a2;
132
+
133
+ HammingComputer20_tpl() {}
134
+
135
+ HammingComputer20_tpl(const uint8_t* a8, int code_size) {
136
+ set(a8, code_size);
137
+ }
138
+
139
+ void set(const uint8_t* a8, FAISS_MAYBE_UNUSED int code_size) {
140
+ assert(code_size == 20);
141
+ const uint64_t* a = reinterpret_cast<const uint64_t*>(a8);
142
+ const uint32_t* a32 = reinterpret_cast<const uint32_t*>(a8);
143
+ a0 = a[0];
144
+ a1 = a[1];
145
+ // can't read a[2] since it is uint64_t, not uint32_t
146
+ // results in AddressSanitizer failure reading past end of array
147
+ a2 = a32[4];
148
+ }
149
+
150
+ inline int hamming(const uint8_t* b8) const {
151
+ const uint64_t* b = reinterpret_cast<const uint64_t*>(b8);
152
+ const uint32_t* b32_tail = reinterpret_cast<const uint32_t*>(b + 2);
153
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
154
+ popcount64(*b32_tail ^ a2);
155
+ }
156
+
157
+ inline static constexpr int get_code_size() {
158
+ return 20;
159
+ }
160
+ };
161
+
162
+ template <>
163
+ struct HammingComputer32_tpl<SIMDLevel::NONE> {
164
+ uint64_t a0, a1, a2, a3;
165
+
166
+ HammingComputer32_tpl() {}
167
+
168
+ HammingComputer32_tpl(const uint8_t* a8, int code_size) {
169
+ set(a8, code_size);
170
+ }
171
+
172
+ void set(const uint8_t* a8, FAISS_MAYBE_UNUSED int code_size) {
173
+ assert(code_size == 32);
174
+ const uint64_t* a = reinterpret_cast<const uint64_t*>(a8);
175
+ a0 = a[0];
176
+ a1 = a[1];
177
+ a2 = a[2];
178
+ a3 = a[3];
179
+ }
180
+
181
+ inline int hamming(const uint8_t* b8) const {
182
+ const uint64_t* b = reinterpret_cast<const uint64_t*>(b8);
183
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
184
+ popcount64(b[2] ^ a2) + popcount64(b[3] ^ a3);
185
+ }
186
+
187
+ inline static constexpr int get_code_size() {
188
+ return 32;
189
+ }
190
+ };
191
+
192
+ template <>
193
+ struct GenHammingComputer8_tpl<SIMDLevel::NONE> {
194
+ uint64_t a0;
195
+
196
+ GenHammingComputer8_tpl(
197
+ const uint8_t* a,
198
+ FAISS_MAYBE_UNUSED int code_size) {
199
+ assert(code_size == 8);
200
+ const uint64_t* a64 = reinterpret_cast<const uint64_t*>(a);
201
+ a0 = *a64;
202
+ }
203
+
204
+ inline int hamming(const uint8_t* b) const {
205
+ const uint64_t* b64 = reinterpret_cast<const uint64_t*>(b);
206
+ return generalized_hamming_64(*b64 ^ a0);
207
+ }
208
+
209
+ inline static constexpr int get_code_size() {
210
+ return 8;
211
+ }
212
+ };
213
+
214
+ /***************************************************************************
215
+ * Scalar HammingComputer64 and HammingComputerDefault NONE specializations.
216
+ * AVX512 and NEON override via per-ISA specializations.
217
+ ***************************************************************************/
218
+
219
+ template <>
220
+ struct HammingComputer64_tpl<SIMDLevel::NONE> {
221
+ uint64_t a0, a1, a2, a3, a4, a5, a6, a7;
222
+
223
+ HammingComputer64_tpl() {}
224
+
225
+ HammingComputer64_tpl(const uint8_t* a8, int code_size) {
226
+ set(a8, code_size);
227
+ }
228
+
229
+ void set(const uint8_t* a8, FAISS_MAYBE_UNUSED int code_size) {
230
+ assert(code_size == 64);
231
+ const uint64_t* a = reinterpret_cast<const uint64_t*>(a8);
232
+ a0 = a[0];
233
+ a1 = a[1];
234
+ a2 = a[2];
235
+ a3 = a[3];
236
+ a4 = a[4];
237
+ a5 = a[5];
238
+ a6 = a[6];
239
+ a7 = a[7];
240
+ }
241
+
242
+ inline int hamming(const uint8_t* b8) const {
243
+ const uint64_t* b = reinterpret_cast<const uint64_t*>(b8);
244
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
245
+ popcount64(b[2] ^ a2) + popcount64(b[3] ^ a3) +
246
+ popcount64(b[4] ^ a4) + popcount64(b[5] ^ a5) +
247
+ popcount64(b[6] ^ a6) + popcount64(b[7] ^ a7);
248
+ }
249
+
250
+ inline static constexpr int get_code_size() {
251
+ return 64;
252
+ }
253
+ };
254
+
255
+ template <>
256
+ struct HammingComputerDefault_tpl<SIMDLevel::NONE> {
257
+ const uint8_t* a8;
258
+ int quotient8;
259
+ int remainder8;
260
+
261
+ HammingComputerDefault_tpl() {}
262
+
263
+ HammingComputerDefault_tpl(const uint8_t* a8_in, int code_size) {
264
+ set(a8_in, code_size);
265
+ }
266
+
267
+ void set(const uint8_t* a8_in, int code_size) {
268
+ this->a8 = a8_in;
269
+ quotient8 = code_size / 8;
270
+ remainder8 = code_size % 8;
271
+ }
272
+
273
+ int hamming(const uint8_t* b8) const {
274
+ const uint64_t* a64 = reinterpret_cast<const uint64_t*>(a8);
275
+ const uint64_t* b64 = reinterpret_cast<const uint64_t*>(b8);
276
+ return hamming_popcount_tail(
277
+ a64, b64, 0, quotient8, a8, b8, remainder8);
278
+ }
279
+
280
+ inline int get_code_size() const {
281
+ return quotient8 * 8 + remainder8;
282
+ }
283
+ };
284
+
285
+ /***************************************************************************
286
+ * Generalized HammingComputer NONE specializations (scalar bodies).
287
+ * AVX2/AVX512/NEON override via per-ISA specializations.
288
+ ***************************************************************************/
289
+
290
+ template <>
291
+ struct GenHammingComputer16_tpl<SIMDLevel::NONE> {
292
+ uint64_t a0, a1;
293
+
294
+ GenHammingComputer16_tpl(
295
+ const uint8_t* a8,
296
+ FAISS_MAYBE_UNUSED int code_size) {
297
+ assert(code_size == 16);
298
+ const uint64_t* a = reinterpret_cast<const uint64_t*>(a8);
299
+ a0 = a[0];
300
+ a1 = a[1];
301
+ }
302
+
303
+ inline int hamming(const uint8_t* b8) const {
304
+ const uint64_t* b = reinterpret_cast<const uint64_t*>(b8);
305
+ return generalized_hamming_64(b[0] ^ a0) +
306
+ generalized_hamming_64(b[1] ^ a1);
307
+ }
308
+
309
+ inline static constexpr int get_code_size() {
310
+ return 16;
311
+ }
312
+ };
313
+
314
+ template <>
315
+ struct GenHammingComputer32_tpl<SIMDLevel::NONE> {
316
+ uint64_t a0, a1, a2, a3;
317
+
318
+ GenHammingComputer32_tpl(
319
+ const uint8_t* a8,
320
+ FAISS_MAYBE_UNUSED int code_size) {
321
+ assert(code_size == 32);
322
+ const uint64_t* a = reinterpret_cast<const uint64_t*>(a8);
323
+ a0 = a[0];
324
+ a1 = a[1];
325
+ a2 = a[2];
326
+ a3 = a[3];
327
+ }
328
+
329
+ inline int hamming(const uint8_t* b8) const {
330
+ const uint64_t* b = reinterpret_cast<const uint64_t*>(b8);
331
+ return generalized_hamming_64(b[0] ^ a0) +
332
+ generalized_hamming_64(b[1] ^ a1) +
333
+ generalized_hamming_64(b[2] ^ a2) +
334
+ generalized_hamming_64(b[3] ^ a3);
335
+ }
336
+
337
+ inline static constexpr int get_code_size() {
338
+ return 32;
339
+ }
340
+ };
341
+
342
+ template <>
343
+ struct GenHammingComputerM8_tpl<SIMDLevel::NONE> {
344
+ const uint64_t* a;
345
+ int n;
346
+
347
+ GenHammingComputerM8_tpl(const uint8_t* a8, int code_size) {
348
+ assert(code_size % 8 == 0);
349
+ a = reinterpret_cast<const uint64_t*>(a8);
350
+ n = code_size / 8;
351
+ }
352
+
353
+ int hamming(const uint8_t* b8) const {
354
+ const uint64_t* b = reinterpret_cast<const uint64_t*>(b8);
355
+ int accu = 0;
356
+ for (int i = 0; i < n; i++)
357
+ accu += generalized_hamming_64(a[i] ^ b[i]);
358
+ return accu;
359
+ }
360
+
361
+ inline int get_code_size() const {
362
+ return n * 8;
363
+ }
364
+ };
365
+
366
+ } // namespace faiss
367
+
368
+ #endif
@@ -0,0 +1,322 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #ifndef HAMMING_COMPUTER_NEON_H
9
+ #define HAMMING_COMPUTER_NEON_H
10
+
11
+ // NEON-optimized HammingComputer and GenHammingComputer specializations.
12
+ // The hamming<nbits>() free functions live in common.h.
13
+ //
14
+ // Universal code (HammingComputer4, HammingComputer8, generalized_hamming_64,
15
+ // hamming_popcount_tail) comes from hamming_computer.h /
16
+ // hamming_computer-generic.h. SIMDLevel::ARM_NEON specializations for the
17
+ // ISA-varying HammingComputer and GenHammingComputer structs live in this file.
18
+
19
+ #ifdef __aarch64__
20
+
21
+ #include <arm_neon.h>
22
+
23
+ #include <cassert>
24
+ #include <cstddef>
25
+ #include <cstdint>
26
+
27
+ #include <faiss/impl/platform_macros.h>
28
+
29
+ #include <faiss/utils/hamming_distance/hamming_computer-generic.h>
30
+
31
+ namespace faiss {
32
+
33
+ /******************************************************************
34
+ * NEON-optimized HammingComputer<SIMDLevel::ARM_NEON> specializations.
35
+ * Sizes 4 and 8 use the scalar versions from hamming_computer.h.
36
+ ******************************************************************/
37
+
38
+ template <>
39
+ struct HammingComputer16_tpl<SIMDLevel::ARM_NEON> {
40
+ uint8x16_t a0;
41
+
42
+ HammingComputer16_tpl() {}
43
+
44
+ HammingComputer16_tpl(const uint8_t* a8, int code_size) {
45
+ set(a8, code_size);
46
+ }
47
+
48
+ void set(const uint8_t* a8, FAISS_MAYBE_UNUSED int code_size) {
49
+ assert(code_size == 16);
50
+ a0 = vld1q_u8(a8);
51
+ }
52
+
53
+ inline int hamming(const uint8_t* b8) const {
54
+ uint8x16_t b0 = vld1q_u8(b8);
55
+
56
+ uint8x16_t or0 = veorq_u8(a0, b0);
57
+ uint8x16_t c0 = vcntq_u8(or0);
58
+ auto dis = vaddvq_u8(c0);
59
+ return dis;
60
+ }
61
+
62
+ inline static constexpr int get_code_size() {
63
+ return 16;
64
+ }
65
+ };
66
+
67
+ // when applied to an array, 1/2 of the 64-bit accesses are unaligned.
68
+ // This incurs a penalty of ~10% wrt. fully aligned accesses.
69
+ template <>
70
+ struct HammingComputer20_tpl<SIMDLevel::ARM_NEON> {
71
+ uint8x16_t a0;
72
+ uint32_t a2;
73
+
74
+ HammingComputer20_tpl() {}
75
+
76
+ HammingComputer20_tpl(const uint8_t* a8, int code_size) {
77
+ set(a8, code_size);
78
+ }
79
+
80
+ void set(const uint8_t* a8, FAISS_MAYBE_UNUSED int code_size) {
81
+ assert(code_size == 20);
82
+
83
+ a0 = vld1q_u8(a8);
84
+
85
+ const uint32_t* a = (uint32_t*)a8;
86
+ a2 = a[4];
87
+ }
88
+
89
+ inline int hamming(const uint8_t* b8) const {
90
+ uint8x16_t b0 = vld1q_u8(b8);
91
+
92
+ uint8x16_t or0 = veorq_u8(a0, b0);
93
+ uint8x16_t c0 = vcntq_u8(or0);
94
+ auto dis = vaddvq_u8(c0);
95
+
96
+ const uint32_t* b = (uint32_t*)b8;
97
+ return dis + popcount64(b[4] ^ a2);
98
+ }
99
+
100
+ inline static constexpr int get_code_size() {
101
+ return 20;
102
+ }
103
+ };
104
+
105
+ template <>
106
+ struct HammingComputer32_tpl<SIMDLevel::ARM_NEON> {
107
+ uint8x16_t a0;
108
+ uint8x16_t a1;
109
+
110
+ HammingComputer32_tpl() {}
111
+
112
+ HammingComputer32_tpl(const uint8_t* a8, int code_size) {
113
+ set(a8, code_size);
114
+ }
115
+
116
+ void set(const uint8_t* a8, FAISS_MAYBE_UNUSED int code_size) {
117
+ assert(code_size == 32);
118
+ a0 = vld1q_u8(a8);
119
+ a1 = vld1q_u8(a8 + 16);
120
+ }
121
+
122
+ inline int hamming(const uint8_t* b8) const {
123
+ uint8x16_t b0 = vld1q_u8(b8);
124
+ uint8x16_t b1 = vld1q_u8(b8 + 16);
125
+
126
+ uint8x16_t or0 = veorq_u8(a0, b0);
127
+ uint8x16_t or1 = veorq_u8(a1, b1);
128
+ uint8x16_t c0 = vcntq_u8(or0);
129
+ uint8x16_t c1 = vcntq_u8(or1);
130
+ uint8x16_t ca = vpaddq_u8(c0, c1);
131
+ auto dis = vaddvq_u8(ca);
132
+ return dis;
133
+ }
134
+
135
+ inline static constexpr int get_code_size() {
136
+ return 32;
137
+ }
138
+ };
139
+
140
+ template <>
141
+ struct HammingComputer64_tpl<SIMDLevel::ARM_NEON> {
142
+ HammingComputer32_tpl<SIMDLevel::ARM_NEON> hc0, hc1;
143
+
144
+ HammingComputer64_tpl() {}
145
+
146
+ HammingComputer64_tpl(const uint8_t* a8, int code_size) {
147
+ set(a8, code_size);
148
+ }
149
+
150
+ void set(const uint8_t* a8, FAISS_MAYBE_UNUSED int code_size) {
151
+ assert(code_size == 64);
152
+ hc0.set(a8, 32);
153
+ hc1.set(a8 + 32, 32);
154
+ }
155
+
156
+ inline int hamming(const uint8_t* b8) const {
157
+ return hc0.hamming(b8) + hc1.hamming(b8 + 32);
158
+ }
159
+
160
+ inline static constexpr int get_code_size() {
161
+ return 64;
162
+ }
163
+ };
164
+
165
+ template <>
166
+ struct HammingComputerDefault_tpl<SIMDLevel::ARM_NEON> {
167
+ const uint8_t* a8;
168
+ int quotient8;
169
+ int remainder8;
170
+
171
+ HammingComputerDefault_tpl() {}
172
+
173
+ HammingComputerDefault_tpl(const uint8_t* a8_in, int code_size) {
174
+ set(a8_in, code_size);
175
+ }
176
+
177
+ void set(const uint8_t* a8_in, int code_size) {
178
+ this->a8 = a8_in;
179
+ quotient8 = code_size / 8;
180
+ remainder8 = code_size % 8;
181
+ }
182
+
183
+ int hamming(const uint8_t* b8) const {
184
+ int accu = 0;
185
+
186
+ const uint64_t* a64 = reinterpret_cast<const uint64_t*>(a8);
187
+ const uint64_t* b64 = reinterpret_cast<const uint64_t*>(b8);
188
+ int i = 0;
189
+
190
+ int len256 = (quotient8 / 4) * 4;
191
+ for (; i < len256; i += 4) {
192
+ accu += ::faiss::hamming<256>(a64 + i, b64 + i);
193
+ }
194
+
195
+ accu += hamming_popcount_tail(
196
+ a64, b64, i, quotient8, a8, b8, remainder8);
197
+ return accu;
198
+ }
199
+
200
+ inline int get_code_size() const {
201
+ return quotient8 * 8 + remainder8;
202
+ }
203
+ };
204
+
205
+ /***************************************************************************
206
+ * NEON-optimized generalized Hamming computer specializations.
207
+ ***************************************************************************/
208
+
209
+ template <>
210
+ struct GenHammingComputer8_tpl<SIMDLevel::ARM_NEON> {
211
+ uint8x8_t a0;
212
+
213
+ GenHammingComputer8_tpl(
214
+ const uint8_t* a8,
215
+ FAISS_MAYBE_UNUSED int code_size) {
216
+ assert(code_size == 8);
217
+ a0 = vld1_u8(a8);
218
+ }
219
+
220
+ inline int hamming(const uint8_t* b8) const {
221
+ uint8x8_t b0 = vld1_u8(b8);
222
+ uint8x8_t reg = vceq_u8(a0, b0);
223
+ uint8x8_t c0 = vcnt_u8(reg);
224
+ return 8 - vaddv_u8(c0) / 8;
225
+ }
226
+
227
+ inline static constexpr int get_code_size() {
228
+ return 8;
229
+ }
230
+ };
231
+
232
+ template <>
233
+ struct GenHammingComputer16_tpl<SIMDLevel::ARM_NEON> {
234
+ uint8x16_t a0;
235
+
236
+ GenHammingComputer16_tpl(
237
+ const uint8_t* a8,
238
+ FAISS_MAYBE_UNUSED int code_size) {
239
+ assert(code_size == 16);
240
+ a0 = vld1q_u8(a8);
241
+ }
242
+
243
+ inline int hamming(const uint8_t* b8) const {
244
+ uint8x16_t b0 = vld1q_u8(b8);
245
+ uint8x16_t reg = vceqq_u8(a0, b0);
246
+ uint8x16_t c0 = vcntq_u8(reg);
247
+ return 16 - vaddvq_u8(c0) / 8;
248
+ }
249
+
250
+ inline static constexpr int get_code_size() {
251
+ return 16;
252
+ }
253
+ };
254
+
255
+ template <>
256
+ struct GenHammingComputer32_tpl<SIMDLevel::ARM_NEON> {
257
+ GenHammingComputer16_tpl<SIMDLevel::ARM_NEON> a0, a1;
258
+
259
+ GenHammingComputer32_tpl(
260
+ const uint8_t* a8,
261
+ FAISS_MAYBE_UNUSED int code_size)
262
+ : a0(a8, 16), a1(a8 + 16, 16) {
263
+ assert(code_size == 32);
264
+ }
265
+
266
+ inline int hamming(const uint8_t* b8) const {
267
+ return a0.hamming(b8) + a1.hamming(b8 + 16);
268
+ }
269
+
270
+ inline static constexpr int get_code_size() {
271
+ return 32;
272
+ }
273
+ };
274
+
275
+ template <>
276
+ struct GenHammingComputerM8_tpl<SIMDLevel::ARM_NEON> {
277
+ const uint64_t* a;
278
+ int n;
279
+
280
+ GenHammingComputerM8_tpl(const uint8_t* a8, int code_size) {
281
+ assert(code_size % 8 == 0);
282
+ a = (uint64_t*)a8;
283
+ n = code_size / 8;
284
+ }
285
+
286
+ int hamming(const uint8_t* b8) const {
287
+ const uint64_t* b = (uint64_t*)b8;
288
+ int accu = 0;
289
+
290
+ int n2 = (n / 2) * 2;
291
+ int i = 0;
292
+ for (; i < n2; i += 2) {
293
+ uint8x16_t a0 = vld1q_u8((const uint8_t*)(a + i));
294
+ uint8x16_t b0 = vld1q_u8((const uint8_t*)(b + i));
295
+ uint8x16_t reg = vceqq_u8(a0, b0);
296
+ uint8x16_t c0 = vcntq_u8(reg);
297
+ auto dis = 16 - vaddvq_u8(c0) / 8;
298
+ accu += dis;
299
+ }
300
+
301
+ for (; i < n; i++) {
302
+ uint8x8_t a0 = vld1_u8((const uint8_t*)(a + i));
303
+ uint8x8_t b0 = vld1_u8((const uint8_t*)(b + i));
304
+ uint8x8_t reg = vceq_u8(a0, b0);
305
+ uint8x8_t c0 = vcnt_u8(reg);
306
+ auto dis = 8 - vaddv_u8(c0) / 8;
307
+ accu += dis;
308
+ }
309
+
310
+ return accu;
311
+ }
312
+
313
+ inline int get_code_size() {
314
+ return n * 8;
315
+ }
316
+ };
317
+
318
+ } // namespace faiss
319
+
320
+ #endif
321
+
322
+ #endif