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
@@ -50,7 +50,8 @@ int WriterStreambuf::overflow(int ch) {
50
50
  return wrote == 1 ? ch : traits_type::eof();
51
51
  }
52
52
 
53
- ReaderStreambuf::ReaderStreambuf(IOReader* rr) : r(rr), single_char_buffer(0) {
53
+ ReaderStreambuf::ReaderStreambuf(IOReader* rr, size_t limit)
54
+ : r(rr), single_char_buffer(0), per_read_byte_limit(limit) {
54
55
  // Initialize with empty get area
55
56
  setg(nullptr, nullptr, nullptr);
56
57
  }
@@ -77,9 +78,17 @@ std::streamsize ReaderStreambuf::xsgetn(char* s, std::streamsize n) {
77
78
  if (n <= 0) {
78
79
  return 0;
79
80
  }
81
+ size_t nbytes = n;
80
82
 
81
- size_t got = (*r)(s, 1, n);
82
- return static_cast<std::streamsize>(got);
83
+ // Per-read byte limit: reject individual reads that exceed the limit,
84
+ // matching READVECTOR semantics where each vector allocation is
85
+ // independently checked against deserialization_vector_byte_limit.
86
+ if (per_read_byte_limit > 0 && nbytes >= per_read_byte_limit) {
87
+ return 0;
88
+ }
89
+
90
+ size_t got = (*r)(s, 1, nbytes);
91
+ return got;
83
92
  }
84
93
 
85
94
  } // namespace svs_io
@@ -53,9 +53,15 @@ struct WriterStreambuf : std::streambuf {
53
53
  // without intermediate buffering.
54
54
  struct ReaderStreambuf : std::streambuf {
55
55
  IOReader* r;
56
- char single_char_buffer; // Single-byte buffer for underflow() operations
56
+ char single_char_buffer; // Single-byte buffer for underflow() operations
57
+ size_t per_read_byte_limit; // Max bytes per individual read (0 = unlimited)
57
58
 
58
- explicit ReaderStreambuf(IOReader* rr);
59
+ /// Construct with an optional per-read byte limit matching READVECTOR
60
+ /// semantics. Each individual xsgetn call that meets or exceeds the
61
+ /// limit returns 0, matching how READVECTOR rejects individual vectors
62
+ /// whose allocation would exceed deserialization_vector_byte_limit.
63
+ /// A limit of 0 means unlimited.
64
+ explicit ReaderStreambuf(IOReader* rr, size_t limit = 0);
59
65
  ~ReaderStreambuf() override;
60
66
 
61
67
  protected:
@@ -45,7 +45,6 @@
45
45
  #include <faiss/IndexRefine.h>
46
46
  #include <faiss/IndexRowwiseMinMax.h>
47
47
  #include <faiss/IndexScalarQuantizer.h>
48
- #include <faiss/MetaIndexes.h>
49
48
  #include <faiss/VectorTransform.h>
50
49
 
51
50
  #include <faiss/IndexBinaryFlat.h>
@@ -55,6 +54,9 @@
55
54
 
56
55
  #ifdef FAISS_ENABLE_SVS
57
56
  #include <faiss/svs/IndexSVSFlat.h>
57
+ #include <faiss/svs/IndexSVSIVF.h>
58
+ #include <faiss/svs/IndexSVSIVFLVQ.h>
59
+ #include <faiss/svs/IndexSVSIVFLeanVec.h>
58
60
  #include <faiss/svs/IndexSVSVamana.h>
59
61
  #include <faiss/svs/IndexSVSVamanaLVQ.h>
60
62
  #include <faiss/svs/IndexSVSVamanaLeanVec.h>
@@ -91,10 +93,10 @@ void find_matching_parentheses(
91
93
  int begin = 0) {
92
94
  int st = 0;
93
95
  i0 = i1 = 0;
94
- for (int i = begin; i < s.length(); i++) {
96
+ for (size_t i = begin; i < s.length(); i++) {
95
97
  if (s[i] == '(') {
96
98
  if (st == 0) {
97
- i0 = i;
99
+ i0 = static_cast<int>(i);
98
100
  }
99
101
  st++;
100
102
  }
@@ -102,7 +104,7 @@ void find_matching_parentheses(
102
104
  if (s[i] == ')') {
103
105
  st--;
104
106
  if (st == 0) {
105
- i1 = i;
107
+ i1 = static_cast<int>(i);
106
108
  return;
107
109
  }
108
110
  if (st < 0) {
@@ -128,6 +130,11 @@ char get_trains_alone(const Index* coarse_quantizer) {
128
130
  if (dynamic_cast<const IndexHNSWFlat*>(coarse_quantizer)) {
129
131
  return 2;
130
132
  }
133
+ #ifdef FAISS_ENABLE_SVS
134
+ if (dynamic_cast<const IndexSVSVamana*>(coarse_quantizer)) {
135
+ return 2;
136
+ }
137
+ #endif
131
138
  return 2; // for complicated indexes, we assume they can't be used as a
132
139
  // kmeans index
133
140
  }
@@ -155,9 +162,15 @@ std::map<std::string, ScalarQuantizer::QuantizerType> sq_types = {
155
162
  {"SQbf16", ScalarQuantizer::QT_bf16},
156
163
  {"SQ8_direct_signed", ScalarQuantizer::QT_8bit_direct_signed},
157
164
  {"SQ8_direct", ScalarQuantizer::QT_8bit_direct},
165
+ {"SQ0", ScalarQuantizer::QT_0bit},
166
+ {"SQtqmse1", ScalarQuantizer::QT_1bit_tqmse},
167
+ {"SQtqmse2", ScalarQuantizer::QT_2bit_tqmse},
168
+ {"SQtqmse3", ScalarQuantizer::QT_3bit_tqmse},
169
+ {"SQtqmse4", ScalarQuantizer::QT_4bit_tqmse},
170
+ {"SQtqmse8", ScalarQuantizer::QT_8bit_tqmse},
158
171
  };
159
172
  const std::string sq_pattern =
160
- "(SQ4|SQ8|SQ6|SQfp16|SQbf16|SQ8_direct_signed|SQ8_direct)";
173
+ "(SQ0|SQ4|SQ8|SQ6|SQfp16|SQbf16|SQ8_direct_signed|SQ8_direct|SQtqmse1|SQtqmse2|SQtqmse3|SQtqmse4|SQtqmse8)";
161
174
 
162
175
  std::map<std::string, AdditiveQuantizer::Search_type_t> aq_search_type = {
163
176
  {"_Nfloat", AdditiveQuantizer::ST_norm_float},
@@ -183,7 +196,7 @@ AdditiveQuantizer::Search_type_t aq_parse_search_type(
183
196
  return metric == METRIC_L2 ? AdditiveQuantizer::ST_decompress
184
197
  : AdditiveQuantizer::ST_LUT_nonorm;
185
198
  }
186
- int pos = stok.rfind('_');
199
+ size_t pos = stok.rfind('_');
187
200
  return aq_search_type[stok.substr(pos)];
188
201
  }
189
202
 
@@ -206,7 +219,7 @@ std::vector<size_t> aq_parse_nbits(std::string stok) {
206
219
 
207
220
  VectorTransform* parse_VectorTransform(const std::string& description, int d) {
208
221
  std::smatch sm;
209
- auto match = [&sm, description](std::string pattern) {
222
+ auto match = [&sm, description](const std::string& pattern) {
210
223
  return re_match(description, pattern, sm);
211
224
  };
212
225
  if (match("PCA(W?)(R?)([0-9]+)")) {
@@ -264,7 +277,7 @@ Index* parse_coarse_quantizer(
264
277
  size_t& nlist,
265
278
  bool& use_2layer) {
266
279
  std::smatch sm;
267
- auto match = [&sm, description](std::string pattern) {
280
+ auto match = [&sm, description](const std::string& pattern) {
268
281
  return re_match(description, pattern, sm);
269
282
  };
270
283
  use_2layer = false;
@@ -291,10 +304,34 @@ Index* parse_coarse_quantizer(
291
304
  int R = std::stoi(sm[2]);
292
305
  return new IndexNSGFlat(d, R, mt);
293
306
  }
307
+ #ifdef FAISS_ENABLE_SVS
308
+ if (match("IVF([0-9]+[kM]?)_SVSVamana([0-9]*)(_.+)?")) {
309
+ nlist = parse_nlist(sm[1].str());
310
+ int degree = sm[2].length() > 0 ? std::stoi(sm[2]) : 32;
311
+ SVSStorageKind storage = SVSStorageKind::SVS_FP32;
312
+ if (sm[3].matched) {
313
+ std::string s = sm[3].str().substr(1);
314
+ if (s == "SQI8") {
315
+ storage = SVSStorageKind::SVS_SQI8;
316
+ } else if (s == "FP16") {
317
+ storage = SVSStorageKind::SVS_FP16;
318
+ } else if (s == "FP32") {
319
+ storage = SVSStorageKind::SVS_FP32;
320
+ } else {
321
+ FAISS_THROW_FMT(
322
+ "unsupported SVSVamana coarse quantizer storage: %s",
323
+ s.c_str());
324
+ }
325
+ }
326
+ return new IndexSVSVamana(d, degree, mt, storage);
327
+ }
328
+ #endif
294
329
  if (match("IVF([0-9]+[kM]?)\\(Index([0-9])\\)")) {
295
330
  nlist = parse_nlist(sm[1].str());
296
331
  int no = std::stoi(sm[2].str());
297
- FAISS_ASSERT(no >= 0 && no < parenthesis_indexes.size());
332
+ FAISS_ASSERT(
333
+ no >= 0 &&
334
+ static_cast<size_t>(no) < parenthesis_indexes.size());
298
335
  return parenthesis_indexes[no].release();
299
336
  }
300
337
 
@@ -340,9 +377,11 @@ IndexIVF* parse_IndexIVF(
340
377
  if (match("FlatDedup")) {
341
378
  return new IndexIVFFlatDedup(get_q(), d, nlist, mt, own_il);
342
379
  }
343
- if (match("FlatPanorama([0-9]+)?")) {
380
+ if (match("FlatPanorama([0-9]+)?(_([0-9]+))?")) {
344
381
  int nlevels = mres_to_int(sm[1], 8); // default to 8 levels
345
- return new IndexIVFFlatPanorama(get_q(), d, nlist, nlevels, mt, own_il);
382
+ int bs = mres_to_int(sm[3], 128);
383
+ return new IndexIVFFlatPanorama(
384
+ get_q(), d, nlist, nlevels, mt, own_il, bs);
346
385
  }
347
386
  if (match(sq_pattern)) {
348
387
  return new IndexIVFScalarQuantizer(
@@ -588,6 +627,9 @@ SVSStorageKind parse_lvq(const std::string& lvq_string) {
588
627
  if (lvq_string == "LVQ4x8") {
589
628
  return SVSStorageKind::SVS_LVQ4x8;
590
629
  }
630
+ if (lvq_string == "LVQ8x0") {
631
+ return SVSStorageKind::SVS_LVQ8x0;
632
+ }
591
633
  FAISS_ASSERT(false && "not supported SVS LVQ level");
592
634
  }
593
635
 
@@ -619,28 +661,43 @@ Index* parse_svs_datatype(
619
661
  if (index_type == "Flat") {
620
662
  return new IndexSVSFlat(d, mt);
621
663
  }
622
- FAISS_ASSERT(false && "Unspported SVS index type");
664
+ if (index_type == "IVF") {
665
+ return new IndexSVSIVF(d, std::stoul(arg_string), mt);
666
+ }
667
+ FAISS_ASSERT(false && "Unsupported SVS index type");
623
668
  }
624
669
  if (re_match(datatype_string, "FP16", sm)) {
625
670
  if (index_type == "Vamana") {
626
671
  return new IndexSVSVamana(
627
672
  d, std::stoul(arg_string), mt, SVSStorageKind::SVS_FP16);
628
673
  }
629
- FAISS_ASSERT(false && "Unspported SVS index type for Float16");
674
+ if (index_type == "IVF") {
675
+ return new IndexSVSIVF(
676
+ d, std::stoul(arg_string), mt, SVSStorageKind::SVS_FP16);
677
+ }
678
+ FAISS_ASSERT(false && "Unsupported SVS index type for Float16");
630
679
  }
631
680
  if (re_match(datatype_string, "SQI8", sm)) {
632
681
  if (index_type == "Vamana") {
633
682
  return new IndexSVSVamana(
634
683
  d, std::stoul(arg_string), mt, SVSStorageKind::SVS_SQI8);
635
684
  }
636
- FAISS_ASSERT(false && "Unspported SVS index type for SQI8");
685
+ if (index_type == "IVF") {
686
+ return new IndexSVSIVF(
687
+ d, std::stoul(arg_string), mt, SVSStorageKind::SVS_SQI8);
688
+ }
689
+ FAISS_ASSERT(false && "Unsupported SVS index type for SQI8");
637
690
  }
638
691
  if (re_match(datatype_string, "(LVQ[0-9]+x[0-9]+)", sm)) {
639
692
  if (index_type == "Vamana") {
640
693
  return new IndexSVSVamanaLVQ(
641
694
  d, std::stoul(arg_string), mt, parse_lvq(sm[0].str()));
642
695
  }
643
- FAISS_ASSERT(false && "Unspported SVS index type for LVQ");
696
+ if (index_type == "IVF") {
697
+ return new IndexSVSIVFLVQ(
698
+ d, std::stoul(arg_string), mt, parse_lvq(sm[0].str()));
699
+ }
700
+ FAISS_ASSERT(false && "Unsupported SVS index type for LVQ");
644
701
  }
645
702
  if (re_match(datatype_string, "(LeanVec[0-9]+x[0-9]+)(_[0-9]+)?", sm)) {
646
703
  std::string leanvec_d_string =
@@ -655,7 +712,15 @@ Index* parse_svs_datatype(
655
712
  leanvec_d,
656
713
  parse_leanvec(sm[1].str()));
657
714
  }
658
- FAISS_ASSERT(false && "Unspported SVS index type for LeanVec");
715
+ if (index_type == "IVF") {
716
+ return new IndexSVSIVFLeanVec(
717
+ d,
718
+ std::stoul(arg_string),
719
+ mt,
720
+ leanvec_d,
721
+ parse_leanvec(sm[1].str()));
722
+ }
723
+ FAISS_ASSERT(false && "Unsupported SVS index type for LeanVec");
659
724
  }
660
725
  return nullptr;
661
726
  }
@@ -675,7 +740,10 @@ Index* parse_IndexSVS(const std::string& code_string, int d, MetricType mt) {
675
740
  "Vamana", degree_string, datatype_string, d, mt);
676
741
  }
677
742
  if (re_match(code_string, "IVF([0-9]+)(,.+)?", sm)) {
678
- FAISS_ASSERT(false && "Unspported SVS index type");
743
+ std::string nlist_string = sm[1].str();
744
+ std::string datatype_string =
745
+ sm[2].length() > 0 ? sm[2].str().substr(1) : "";
746
+ return parse_svs_datatype("IVF", nlist_string, datatype_string, d, mt);
679
747
  }
680
748
  return nullptr;
681
749
  }
@@ -964,7 +1032,7 @@ std::unique_ptr<Index> index_factory_sub(
964
1032
  int i0, i1;
965
1033
  find_matching_parentheses(description, i0, i1, begin);
966
1034
  std::string sub_description = description.substr(i0 + 1, i1 - i0 - 1);
967
- int no = parenthesis_indexes.size();
1035
+ size_t no = parenthesis_indexes.size();
968
1036
  parenthesis_indexes.push_back(
969
1037
  index_factory_sub(d, sub_description, metric));
970
1038
  description = description.substr(0, i0 + 1) + "Index" +
@@ -13,6 +13,8 @@
13
13
  #include <cstdio>
14
14
  #include <memory>
15
15
 
16
+ #include <faiss/impl/platform_macros.h>
17
+
16
18
  /** I/O functions can read/write to a filename, a file handle or to an
17
19
  * object that abstracts the medium.
18
20
  *
@@ -68,6 +70,8 @@ const int IO_FLAG_MMAP = IO_FLAG_SKIP_IVF_DATA | 0x646f0000;
68
70
  // after OnDiskInvertedLists get properly updated.
69
71
  const int IO_FLAG_MMAP_IFC = 1 << 9;
70
72
 
73
+ FAISS_API extern bool index_read_warn_on_null_invlists;
74
+
71
75
  Index* read_index(const char* fname, int io_flags = 0);
72
76
  Index* read_index(FILE* f, int io_flags = 0);
73
77
  Index* read_index(IOReader* reader, int io_flags = 0);
@@ -113,6 +117,26 @@ std::unique_ptr<InvertedLists> read_InvertedLists_up(
113
117
  IOReader* reader,
114
118
  int io_flags = 0);
115
119
 
120
+ // Returns the current deserialization loop limit.
121
+ // When nonzero, deserialization rejects loop-driving fields (nlist,
122
+ // nsplits, VT chain length, nhash, etc.) that exceed this value.
123
+ // Default: 0 (no limit).
124
+ size_t get_deserialization_loop_limit();
125
+
126
+ // Sets the deserialization loop limit.
127
+ // NOT thread-safe: set before any concurrent deserialization calls
128
+ // and do not modify while deserialization is in progress on other threads.
129
+ void set_deserialization_loop_limit(size_t value);
130
+
131
+ // Returns the maximum number of bytes that a single READVECTOR call
132
+ // may allocate. Default: 1 TB (1 << 40).
133
+ size_t get_deserialization_vector_byte_limit();
134
+
135
+ // Sets the per-vector byte limit for deserialization.
136
+ // NOT thread-safe: set before any concurrent deserialization calls
137
+ // and do not modify while deserialization is in progress on other threads.
138
+ void set_deserialization_vector_byte_limit(size_t value);
139
+
116
140
  } // namespace faiss
117
141
 
118
142
  #endif
@@ -5,6 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ #include <faiss/index_io.h>
8
9
  #include <faiss/invlists/BlockInvertedLists.h>
9
10
 
10
11
  #include <memory>
@@ -19,23 +20,25 @@
19
20
  namespace faiss {
20
21
 
21
22
  BlockInvertedLists::BlockInvertedLists(
22
- size_t nlist,
23
- size_t n_per_block,
24
- size_t block_size)
25
- : InvertedLists(nlist, InvertedLists::INVALID_CODE_SIZE),
26
- n_per_block(n_per_block),
27
- block_size(block_size) {
28
- ids.resize(nlist);
29
- codes.resize(nlist);
23
+ size_t nlist_in,
24
+ size_t n_per_block_in,
25
+ size_t block_size_in)
26
+ : InvertedLists(nlist_in, InvertedLists::INVALID_CODE_SIZE),
27
+ n_per_block(n_per_block_in),
28
+ block_size(block_size_in) {
29
+ ids.resize(nlist_in);
30
+ codes.resize(nlist_in);
30
31
  }
31
32
 
32
- BlockInvertedLists::BlockInvertedLists(size_t nlist, const CodePacker* packer)
33
- : InvertedLists(nlist, InvertedLists::INVALID_CODE_SIZE),
34
- n_per_block(packer->nvec),
35
- block_size(packer->block_size),
36
- packer(packer) {
37
- ids.resize(nlist);
38
- codes.resize(nlist);
33
+ BlockInvertedLists::BlockInvertedLists(
34
+ size_t nlist_in,
35
+ const CodePacker* packer_in)
36
+ : InvertedLists(nlist_in, InvertedLists::INVALID_CODE_SIZE),
37
+ n_per_block(packer_in->nvec),
38
+ block_size(packer_in->block_size),
39
+ packer(packer_in) {
40
+ ids.resize(nlist_in);
41
+ codes.resize(nlist_in);
39
42
  }
40
43
 
41
44
  BlockInvertedLists::BlockInvertedLists()
@@ -84,7 +87,7 @@ const uint8_t* BlockInvertedLists::get_codes(size_t list_no) const {
84
87
  size_t BlockInvertedLists::remove_ids(const IDSelector& sel) {
85
88
  idx_t nremove = 0;
86
89
  #pragma omp parallel for reduction(+ : nremove)
87
- for (idx_t i = 0; i < nlist; i++) {
90
+ for (idx_t i = 0; i < static_cast<idx_t>(nlist); i++) {
88
91
  std::vector<uint8_t> buffer(packer->code_size);
89
92
  idx_t l = ids[i].size(), j = 0;
90
93
  while (j < l) {
@@ -165,16 +168,63 @@ InvertedLists* BlockInvertedListsIOHook::read(IOReader* f, int /* io_flags */)
165
168
  const {
166
169
  auto il = std::make_unique<BlockInvertedLists>();
167
170
  READ1(il->nlist);
171
+ {
172
+ auto limit_ = get_deserialization_loop_limit();
173
+ if (limit_ > 0) {
174
+ FAISS_THROW_IF_NOT_FMT(
175
+ static_cast<size_t>(il->nlist) <= limit_,
176
+ "BlockInvertedLists nlist=%zd exceeds "
177
+ "deserialization_loop_limit of %zd",
178
+ static_cast<size_t>(il->nlist),
179
+ limit_);
180
+ }
181
+ }
168
182
  READ1(il->code_size);
169
183
  READ1(il->n_per_block);
170
184
  READ1(il->block_size);
171
185
 
186
+ {
187
+ auto limit = get_deserialization_loop_limit();
188
+ if (limit > 0) {
189
+ FAISS_THROW_IF_NOT_FMT(
190
+ il->nlist <= limit,
191
+ "BlockInvertedLists nlist=%zd exceeds "
192
+ "deserialization_loop_limit of %zd",
193
+ il->nlist,
194
+ limit);
195
+ }
196
+ }
197
+
198
+ FAISS_THROW_IF_NOT_FMT(
199
+ il->n_per_block > 0,
200
+ "invalid BlockInvertedLists n_per_block %zd (must be > 0)",
201
+ il->n_per_block);
202
+ FAISS_THROW_IF_NOT_FMT(
203
+ il->block_size > 0,
204
+ "invalid BlockInvertedLists block_size %zd (must be > 0)",
205
+ il->block_size);
206
+
172
207
  il->ids.resize(il->nlist);
173
208
  il->codes.resize(il->nlist);
174
209
 
175
210
  for (size_t i = 0; i < il->nlist; i++) {
176
211
  READVECTOR(il->ids[i]);
177
212
  READVECTOR(il->codes[i]);
213
+ size_t n_ids = il->ids[i].size();
214
+ size_t n_block = (n_ids + il->n_per_block - 1) / il->n_per_block;
215
+ size_t expected_codes_size = mul_no_overflow(
216
+ n_block, il->block_size, "BlockInvertedLists codes");
217
+ FAISS_THROW_IF_NOT_FMT(
218
+ il->codes[i].size() == expected_codes_size,
219
+ "BlockInvertedLists list %zd: codes size %zd does not "
220
+ "match expected %zd (ids=%zd, n_per_block=%zd, "
221
+ "block_size=%zd)",
222
+ i,
223
+ il->codes[i].size(),
224
+ expected_codes_size,
225
+ n_ids,
226
+ il->n_per_block,
227
+ il->block_size);
178
228
  }
179
229
 
180
230
  return il.release();
@@ -50,14 +50,15 @@ void DirectMap::set_type(
50
50
  InvertedLists::ScopedIds idlist(invlists, key);
51
51
 
52
52
  if (new_type == Array) {
53
- for (long ofs = 0; ofs < list_size; ofs++) {
53
+ for (size_t ofs = 0; ofs < list_size; ofs++) {
54
54
  FAISS_THROW_IF_NOT_MSG(
55
- 0 <= idlist[ofs] && idlist[ofs] < ntotal,
55
+ 0 <= idlist[ofs] &&
56
+ static_cast<size_t>(idlist[ofs]) < ntotal,
56
57
  "direct map supported only for sequential ids");
57
58
  array[idlist[ofs]] = lo_build(key, ofs);
58
59
  }
59
60
  } else if (new_type == Hashtable) {
60
- for (long ofs = 0; ofs < list_size; ofs++) {
61
+ for (size_t ofs = 0; ofs < list_size; ofs++) {
61
62
  hashtable[idlist[ofs]] = lo_build(key, ofs);
62
63
  }
63
64
  }
@@ -71,7 +72,9 @@ void DirectMap::clear() {
71
72
 
72
73
  idx_t DirectMap::get(idx_t key) const {
73
74
  if (type == Array) {
74
- FAISS_THROW_IF_NOT_MSG(key >= 0 && key < array.size(), "invalid key");
75
+ FAISS_THROW_IF_NOT_MSG(
76
+ key >= 0 && static_cast<size_t>(key) < array.size(),
77
+ "invalid key");
75
78
  idx_t lo = array[key];
76
79
  FAISS_THROW_IF_NOT_MSG(lo >= 0, "-1 entry in direct_map");
77
80
  return lo;
@@ -111,8 +114,14 @@ void DirectMap::check_can_add(const idx_t* ids) {
111
114
 
112
115
  /********************* DirectMapAdd implementation */
113
116
 
114
- DirectMapAdd::DirectMapAdd(DirectMap& direct_map, size_t n, const idx_t* xids)
115
- : direct_map(direct_map), type(direct_map.type), n(n), xids(xids) {
117
+ DirectMapAdd::DirectMapAdd(
118
+ DirectMap& direct_map_in,
119
+ size_t n_in,
120
+ const idx_t* xids_in)
121
+ : direct_map(direct_map_in),
122
+ type(direct_map_in.type),
123
+ n(n_in),
124
+ xids(xids_in) {
116
125
  if (type == DirectMap::Array) {
117
126
  FAISS_THROW_IF_NOT(xids == nullptr);
118
127
  ntotal = direct_map.array.size();
@@ -133,7 +142,7 @@ void DirectMapAdd::add(size_t i, idx_t list_no, size_t ofs) {
133
142
 
134
143
  DirectMapAdd::~DirectMapAdd() {
135
144
  if (type == DirectMap::Hashtable) {
136
- for (int i = 0; i < n; i++) {
145
+ for (size_t i = 0; i < n; i++) {
137
146
  idx_t id = xids ? xids[i] : ntotal + i;
138
147
  direct_map.hashtable[id] = all_ofs[i];
139
148
  }
@@ -158,7 +167,7 @@ size_t DirectMap::remove_ids(const IDSelector& sel, InvertedLists* invlists) {
158
167
  }
159
168
  // exhaustive scan of IVF
160
169
  #pragma omp parallel for
161
- for (idx_t i = 0; i < nlist; i++) {
170
+ for (idx_t i = 0; i < static_cast<idx_t>(nlist); i++) {
162
171
  idx_t l0 = invlists->list_size(i), l = l0, j = 0;
163
172
  ScopedIds idsi(invlists, i);
164
173
  while (j < l) {
@@ -177,7 +186,7 @@ size_t DirectMap::remove_ids(const IDSelector& sel, InvertedLists* invlists) {
177
186
  }
178
187
  // this will not run well in parallel on ondisk because of
179
188
  // possible shrinks
180
- for (idx_t i = 0; i < nlist; i++) {
189
+ for (idx_t i = 0; i < static_cast<idx_t>(nlist); i++) {
181
190
  if (toremove[i] > 0) {
182
191
  nremove += toremove[i];
183
192
  invlists->resize(i, invlists->list_size(i) - toremove[i]);
@@ -192,13 +201,13 @@ size_t DirectMap::remove_ids(const IDSelector& sel, InvertedLists* invlists) {
192
201
  FAISS_THROW_IF_NOT_MSG(
193
202
  sela, "remove with hashtable works only with IDSelectorArray");
194
203
 
195
- for (idx_t i = 0; i < sela->n; i++) {
204
+ for (idx_t i = 0; i < static_cast<idx_t>(sela->n); i++) {
196
205
  idx_t id = sela->ids[i];
197
206
  auto res = hashtable.find(id);
198
207
  if (res != hashtable.end()) {
199
208
  size_t list_no = lo_listno(res->second);
200
209
  size_t offset = lo_offset(res->second);
201
- idx_t last = invlists->list_size(list_no) - 1;
210
+ size_t last = invlists->list_size(list_no) - 1;
202
211
  hashtable.erase(res);
203
212
  if (offset < last) {
204
213
  idx_t last_id = invlists->get_single_id(list_no, last);
@@ -231,16 +240,17 @@ void DirectMap::update_codes(
231
240
 
232
241
  size_t code_size = invlists->code_size;
233
242
 
234
- for (size_t i = 0; i < n; i++) {
243
+ for (int i = 0; i < n; i++) {
235
244
  idx_t id = ids[i];
236
245
  FAISS_THROW_IF_NOT_MSG(
237
- 0 <= id && id < array.size(), "id to update out of range");
246
+ 0 <= id && static_cast<size_t>(id) < array.size(),
247
+ "id to update out of range");
238
248
  { // remove old one
239
249
  idx_t dm = array[id];
240
250
  int64_t ofs = lo_offset(dm);
241
251
  int64_t il = lo_listno(dm);
242
252
  size_t l = invlists->list_size(il);
243
- if (ofs != l - 1) { // move l - 1 to ofs
253
+ if (static_cast<size_t>(ofs) != l - 1) { // move l - 1 to ofs
244
254
  int64_t id2 = invlists->get_single_id(il, l - 1);
245
255
  array[id2] = lo_build(il, ofs);
246
256
  invlists->update_entry(
@@ -37,9 +37,10 @@ inline uint64_t lo_offset(uint64_t lo) {
37
37
  */
38
38
  struct DirectMap {
39
39
  enum Type {
40
- NoMap = 0, // default
41
- Array = 1, // sequential ids (only for add, no add_with_ids)
42
- Hashtable = 2 // arbitrary ids
40
+ NoMap, // default
41
+ Array, // sequential ids (only for add, no add_with_ids)
42
+ Hashtable, // arbitrary ids
43
+ DMT_count
43
44
  };
44
45
  Type type;
45
46