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
@@ -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,19 @@ 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},
171
+ {"SQtq2", ScalarQuantizer::QT_2bit_tq},
172
+ {"SQtq3", ScalarQuantizer::QT_3bit_tq},
173
+ {"SQtq4", ScalarQuantizer::QT_4bit_tq},
174
+ {"SQtq5", ScalarQuantizer::QT_5bit_tq},
158
175
  };
159
176
  const std::string sq_pattern =
160
- "(SQ4|SQ8|SQ6|SQfp16|SQbf16|SQ8_direct_signed|SQ8_direct)";
177
+ "(SQ0|SQ4|SQ8|SQ6|SQfp16|SQbf16|SQ8_direct_signed|SQ8_direct|SQtqmse1|SQtqmse2|SQtqmse3|SQtqmse4|SQtqmse8|SQtq2|SQtq3|SQtq4|SQtq5)";
161
178
 
162
179
  std::map<std::string, AdditiveQuantizer::Search_type_t> aq_search_type = {
163
180
  {"_Nfloat", AdditiveQuantizer::ST_norm_float},
@@ -183,7 +200,7 @@ AdditiveQuantizer::Search_type_t aq_parse_search_type(
183
200
  return metric == METRIC_L2 ? AdditiveQuantizer::ST_decompress
184
201
  : AdditiveQuantizer::ST_LUT_nonorm;
185
202
  }
186
- int pos = stok.rfind('_');
203
+ size_t pos = stok.rfind('_');
187
204
  return aq_search_type[stok.substr(pos)];
188
205
  }
189
206
 
@@ -206,7 +223,7 @@ std::vector<size_t> aq_parse_nbits(std::string stok) {
206
223
 
207
224
  VectorTransform* parse_VectorTransform(const std::string& description, int d) {
208
225
  std::smatch sm;
209
- auto match = [&sm, description](std::string pattern) {
226
+ auto match = [&sm, description](const std::string& pattern) {
210
227
  return re_match(description, pattern, sm);
211
228
  };
212
229
  if (match("PCA(W?)(R?)([0-9]+)")) {
@@ -264,7 +281,7 @@ Index* parse_coarse_quantizer(
264
281
  size_t& nlist,
265
282
  bool& use_2layer) {
266
283
  std::smatch sm;
267
- auto match = [&sm, description](std::string pattern) {
284
+ auto match = [&sm, description](const std::string& pattern) {
268
285
  return re_match(description, pattern, sm);
269
286
  };
270
287
  use_2layer = false;
@@ -291,10 +308,34 @@ Index* parse_coarse_quantizer(
291
308
  int R = std::stoi(sm[2]);
292
309
  return new IndexNSGFlat(d, R, mt);
293
310
  }
311
+ #ifdef FAISS_ENABLE_SVS
312
+ if (match("IVF([0-9]+[kM]?)_SVSVamana([0-9]*)(_.+)?")) {
313
+ nlist = parse_nlist(sm[1].str());
314
+ int degree = sm[2].length() > 0 ? std::stoi(sm[2]) : 32;
315
+ SVSStorageKind storage = SVSStorageKind::SVS_FP32;
316
+ if (sm[3].matched) {
317
+ std::string s = sm[3].str().substr(1);
318
+ if (s == "SQI8") {
319
+ storage = SVSStorageKind::SVS_SQI8;
320
+ } else if (s == "FP16") {
321
+ storage = SVSStorageKind::SVS_FP16;
322
+ } else if (s == "FP32") {
323
+ storage = SVSStorageKind::SVS_FP32;
324
+ } else {
325
+ FAISS_THROW_FMT(
326
+ "unsupported SVSVamana coarse quantizer storage: %s",
327
+ s.c_str());
328
+ }
329
+ }
330
+ return new IndexSVSVamana(d, degree, mt, storage);
331
+ }
332
+ #endif
294
333
  if (match("IVF([0-9]+[kM]?)\\(Index([0-9])\\)")) {
295
334
  nlist = parse_nlist(sm[1].str());
296
335
  int no = std::stoi(sm[2].str());
297
- FAISS_ASSERT(no >= 0 && no < parenthesis_indexes.size());
336
+ FAISS_ASSERT(
337
+ no >= 0 &&
338
+ static_cast<size_t>(no) < parenthesis_indexes.size());
298
339
  return parenthesis_indexes[no].release();
299
340
  }
300
341
 
@@ -340,9 +381,11 @@ IndexIVF* parse_IndexIVF(
340
381
  if (match("FlatDedup")) {
341
382
  return new IndexIVFFlatDedup(get_q(), d, nlist, mt, own_il);
342
383
  }
343
- if (match("FlatPanorama([0-9]+)?")) {
384
+ if (match("FlatPanorama([0-9]+)?(_([0-9]+))?")) {
344
385
  int nlevels = mres_to_int(sm[1], 8); // default to 8 levels
345
- return new IndexIVFFlatPanorama(get_q(), d, nlist, nlevels, mt, own_il);
386
+ int bs = mres_to_int(sm[3], 128);
387
+ return new IndexIVFFlatPanorama(
388
+ get_q(), d, nlist, nlevels, mt, own_il, bs);
346
389
  }
347
390
  if (match(sq_pattern)) {
348
391
  return new IndexIVFScalarQuantizer(
@@ -588,6 +631,9 @@ SVSStorageKind parse_lvq(const std::string& lvq_string) {
588
631
  if (lvq_string == "LVQ4x8") {
589
632
  return SVSStorageKind::SVS_LVQ4x8;
590
633
  }
634
+ if (lvq_string == "LVQ8x0") {
635
+ return SVSStorageKind::SVS_LVQ8x0;
636
+ }
591
637
  FAISS_ASSERT(false && "not supported SVS LVQ level");
592
638
  }
593
639
 
@@ -619,28 +665,43 @@ Index* parse_svs_datatype(
619
665
  if (index_type == "Flat") {
620
666
  return new IndexSVSFlat(d, mt);
621
667
  }
622
- FAISS_ASSERT(false && "Unspported SVS index type");
668
+ if (index_type == "IVF") {
669
+ return new IndexSVSIVF(d, std::stoul(arg_string), mt);
670
+ }
671
+ FAISS_ASSERT(false && "Unsupported SVS index type");
623
672
  }
624
673
  if (re_match(datatype_string, "FP16", sm)) {
625
674
  if (index_type == "Vamana") {
626
675
  return new IndexSVSVamana(
627
676
  d, std::stoul(arg_string), mt, SVSStorageKind::SVS_FP16);
628
677
  }
629
- FAISS_ASSERT(false && "Unspported SVS index type for Float16");
678
+ if (index_type == "IVF") {
679
+ return new IndexSVSIVF(
680
+ d, std::stoul(arg_string), mt, SVSStorageKind::SVS_FP16);
681
+ }
682
+ FAISS_ASSERT(false && "Unsupported SVS index type for Float16");
630
683
  }
631
684
  if (re_match(datatype_string, "SQI8", sm)) {
632
685
  if (index_type == "Vamana") {
633
686
  return new IndexSVSVamana(
634
687
  d, std::stoul(arg_string), mt, SVSStorageKind::SVS_SQI8);
635
688
  }
636
- FAISS_ASSERT(false && "Unspported SVS index type for SQI8");
689
+ if (index_type == "IVF") {
690
+ return new IndexSVSIVF(
691
+ d, std::stoul(arg_string), mt, SVSStorageKind::SVS_SQI8);
692
+ }
693
+ FAISS_ASSERT(false && "Unsupported SVS index type for SQI8");
637
694
  }
638
695
  if (re_match(datatype_string, "(LVQ[0-9]+x[0-9]+)", sm)) {
639
696
  if (index_type == "Vamana") {
640
697
  return new IndexSVSVamanaLVQ(
641
698
  d, std::stoul(arg_string), mt, parse_lvq(sm[0].str()));
642
699
  }
643
- FAISS_ASSERT(false && "Unspported SVS index type for LVQ");
700
+ if (index_type == "IVF") {
701
+ return new IndexSVSIVFLVQ(
702
+ d, std::stoul(arg_string), mt, parse_lvq(sm[0].str()));
703
+ }
704
+ FAISS_ASSERT(false && "Unsupported SVS index type for LVQ");
644
705
  }
645
706
  if (re_match(datatype_string, "(LeanVec[0-9]+x[0-9]+)(_[0-9]+)?", sm)) {
646
707
  std::string leanvec_d_string =
@@ -655,7 +716,15 @@ Index* parse_svs_datatype(
655
716
  leanvec_d,
656
717
  parse_leanvec(sm[1].str()));
657
718
  }
658
- FAISS_ASSERT(false && "Unspported SVS index type for LeanVec");
719
+ if (index_type == "IVF") {
720
+ return new IndexSVSIVFLeanVec(
721
+ d,
722
+ std::stoul(arg_string),
723
+ mt,
724
+ leanvec_d,
725
+ parse_leanvec(sm[1].str()));
726
+ }
727
+ FAISS_ASSERT(false && "Unsupported SVS index type for LeanVec");
659
728
  }
660
729
  return nullptr;
661
730
  }
@@ -675,7 +744,10 @@ Index* parse_IndexSVS(const std::string& code_string, int d, MetricType mt) {
675
744
  "Vamana", degree_string, datatype_string, d, mt);
676
745
  }
677
746
  if (re_match(code_string, "IVF([0-9]+)(,.+)?", sm)) {
678
- FAISS_ASSERT(false && "Unspported SVS index type");
747
+ std::string nlist_string = sm[1].str();
748
+ std::string datatype_string =
749
+ sm[2].length() > 0 ? sm[2].str().substr(1) : "";
750
+ return parse_svs_datatype("IVF", nlist_string, datatype_string, d, mt);
679
751
  }
680
752
  return nullptr;
681
753
  }
@@ -964,7 +1036,7 @@ std::unique_ptr<Index> index_factory_sub(
964
1036
  int i0, i1;
965
1037
  find_matching_parentheses(description, i0, i1, begin);
966
1038
  std::string sub_description = description.substr(i0 + 1, i1 - i0 - 1);
967
- int no = parenthesis_indexes.size();
1039
+ size_t no = parenthesis_indexes.size();
968
1040
  parenthesis_indexes.push_back(
969
1041
  index_factory_sub(d, sub_description, metric));
970
1042
  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,42 @@ 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
+
140
+ // Returns the current IndexLattice r2 limit for deserialization.
141
+ // When nonzero, deserialization rejects IndexLattice payloads whose
142
+ // r2 (squared lattice radius) exceeds this value. The
143
+ // ZnSphereCodecRec constructor that runs at IndexLattice deserialize
144
+ // time builds a decode cache whose population cost scales
145
+ // polynomially in r2 and dim, and can exceed real-world workload time
146
+ // budgets even for r2 values that do not trip the existing
147
+ // decode-cache memory cap.
148
+ // Default: 0 (no limit).
149
+ size_t get_deserialization_lattice_r2_limit();
150
+
151
+ // Sets the IndexLattice r2 deserialization limit.
152
+ // NOT thread-safe: set before any concurrent deserialization calls
153
+ // and do not modify while deserialization is in progress on other threads.
154
+ void set_deserialization_lattice_r2_limit(size_t value);
155
+
116
156
  } // namespace faiss
117
157
 
118
158
  #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,20 +240,24 @@ 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(
247
- il, ofs, id2, invlists->get_single_code(il, l - 1));
257
+ il,
258
+ ofs,
259
+ id2,
260
+ InvertedLists::ScopedCodes(invlists, il, l - 1).get());
248
261
  }
249
262
  invlists->resize(il, l - 1);
250
263
  }
@@ -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