faiss 0.5.3 → 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 (379) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/ext/faiss/ext.cpp +1 -1
  4. data/ext/faiss/extconf.rb +4 -4
  5. data/ext/faiss/index.cpp +63 -45
  6. data/ext/faiss/index_binary.cpp +37 -27
  7. data/ext/faiss/kmeans.cpp +9 -8
  8. data/ext/faiss/pca_matrix.cpp +9 -7
  9. data/ext/faiss/product_quantizer.cpp +13 -11
  10. data/ext/faiss/utils.cpp +4 -2
  11. data/ext/faiss/utils.h +4 -0
  12. data/lib/faiss/version.rb +1 -1
  13. data/lib/faiss.rb +1 -1
  14. data/vendor/faiss/faiss/AutoTune.cpp +214 -82
  15. data/vendor/faiss/faiss/AutoTune.h +14 -1
  16. data/vendor/faiss/faiss/Clustering.cpp +97 -249
  17. data/vendor/faiss/faiss/Clustering.h +18 -0
  18. data/vendor/faiss/faiss/IVFlib.cpp +67 -44
  19. data/vendor/faiss/faiss/Index.cpp +25 -12
  20. data/vendor/faiss/faiss/Index.h +26 -4
  21. data/vendor/faiss/faiss/Index2Layer.cpp +37 -53
  22. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +68 -61
  23. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +36 -34
  24. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +4 -1
  25. data/vendor/faiss/faiss/IndexBinary.cpp +6 -3
  26. data/vendor/faiss/faiss/IndexBinary.h +4 -4
  27. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +1 -1
  28. data/vendor/faiss/faiss/IndexBinaryFlat.h +1 -1
  29. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -4
  30. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +92 -95
  31. data/vendor/faiss/faiss/IndexBinaryHNSW.h +9 -3
  32. data/vendor/faiss/faiss/IndexBinaryHash.cpp +45 -236
  33. data/vendor/faiss/faiss/IndexBinaryHash.h +6 -6
  34. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +120 -414
  35. data/vendor/faiss/faiss/IndexFastScan.cpp +105 -129
  36. data/vendor/faiss/faiss/IndexFastScan.h +35 -24
  37. data/vendor/faiss/faiss/IndexFlat.cpp +216 -152
  38. data/vendor/faiss/faiss/IndexFlat.h +32 -14
  39. data/vendor/faiss/faiss/IndexFlatCodes.cpp +88 -41
  40. data/vendor/faiss/faiss/IndexFlatCodes.h +7 -1
  41. data/vendor/faiss/faiss/IndexHNSW.cpp +299 -187
  42. data/vendor/faiss/faiss/IndexHNSW.h +30 -14
  43. data/vendor/faiss/faiss/IndexIDMap.cpp +26 -22
  44. data/vendor/faiss/faiss/IndexIDMap.h +9 -7
  45. data/vendor/faiss/faiss/IndexIVF.cpp +535 -405
  46. data/vendor/faiss/faiss/IndexIVF.h +47 -16
  47. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +77 -74
  48. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +105 -99
  49. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +6 -3
  50. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +379 -249
  51. data/vendor/faiss/faiss/IndexIVFFastScan.h +65 -60
  52. data/vendor/faiss/faiss/IndexIVFFlat.cpp +41 -124
  53. data/vendor/faiss/faiss/IndexIVFFlat.h +32 -0
  54. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +89 -138
  55. data/vendor/faiss/faiss/IndexIVFFlatPanorama.h +3 -1
  56. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +18 -15
  57. data/vendor/faiss/faiss/IndexIVFPQ.cpp +77 -907
  58. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +184 -122
  59. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +3 -0
  60. data/vendor/faiss/faiss/IndexIVFPQR.cpp +23 -18
  61. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +59 -60
  62. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +4 -3
  63. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +564 -416
  64. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +269 -111
  65. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +41 -127
  66. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +1 -1
  67. data/vendor/faiss/faiss/IndexLSH.cpp +44 -25
  68. data/vendor/faiss/faiss/IndexLattice.cpp +41 -36
  69. data/vendor/faiss/faiss/IndexNNDescent.cpp +37 -21
  70. data/vendor/faiss/faiss/IndexNNDescent.h +2 -2
  71. data/vendor/faiss/faiss/IndexNSG.cpp +40 -23
  72. data/vendor/faiss/faiss/IndexNSG.h +0 -2
  73. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +32 -12
  74. data/vendor/faiss/faiss/IndexPQ.cpp +129 -213
  75. data/vendor/faiss/faiss/IndexPQ.h +3 -2
  76. data/vendor/faiss/faiss/IndexPQFastScan.cpp +20 -14
  77. data/vendor/faiss/faiss/IndexPQFastScan.h +3 -0
  78. data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -18
  79. data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
  80. data/vendor/faiss/faiss/IndexRaBitQ.cpp +31 -43
  81. data/vendor/faiss/faiss/IndexRaBitQ.h +4 -3
  82. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +135 -317
  83. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +192 -34
  84. data/vendor/faiss/faiss/IndexRefine.cpp +30 -55
  85. data/vendor/faiss/faiss/IndexRefine.h +4 -4
  86. data/vendor/faiss/faiss/IndexReplicas.cpp +6 -6
  87. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +15 -14
  88. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +1 -1
  89. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +82 -14
  90. data/vendor/faiss/faiss/IndexShards.cpp +13 -13
  91. data/vendor/faiss/faiss/IndexShardsIVF.cpp +21 -15
  92. data/vendor/faiss/faiss/MatrixStats.cpp +5 -4
  93. data/vendor/faiss/faiss/MetaIndexes.cpp +19 -17
  94. data/vendor/faiss/faiss/MetaIndexes.h +1 -1
  95. data/vendor/faiss/faiss/MetricType.h +29 -6
  96. data/vendor/faiss/faiss/SuperKMeans.cpp +656 -0
  97. data/vendor/faiss/faiss/SuperKMeans.h +97 -0
  98. data/vendor/faiss/faiss/VectorTransform.cpp +349 -141
  99. data/vendor/faiss/faiss/VectorTransform.h +39 -16
  100. data/vendor/faiss/faiss/build.cpp +23 -0
  101. data/vendor/faiss/faiss/build.h +15 -0
  102. data/vendor/faiss/faiss/clone_index.cpp +55 -51
  103. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +47 -47
  104. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +11 -0
  105. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +38 -38
  106. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +11 -0
  107. data/vendor/faiss/faiss/{cppcontrib/factory_tools.cpp → factory_tools.cpp} +6 -1
  108. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +1 -1
  109. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +6 -5
  110. data/vendor/faiss/faiss/gpu/GpuResources.h +1 -1
  111. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +9 -9
  112. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +4 -3
  113. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +46 -0
  114. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +56 -0
  115. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +78 -1
  116. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +72 -0
  117. data/vendor/faiss/faiss/gpu/test/TestUtils.h +23 -0
  118. data/vendor/faiss/faiss/gpu/utils/CuvsFilterConvert.h +1 -1
  119. data/vendor/faiss/faiss/gpu/utils/CuvsUtils.h +21 -10
  120. data/vendor/faiss/faiss/gpu_metal/GpuIndexFlat.h +22 -0
  121. data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +35 -0
  122. data/vendor/faiss/faiss/gpu_metal/MetalFlatKernels.h +40 -0
  123. data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +51 -0
  124. data/vendor/faiss/faiss/gpu_metal/MetalIndexFlat.h +65 -0
  125. data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +66 -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/impl/AdSampling.cpp +103 -0
  129. data/vendor/faiss/faiss/impl/AdSampling.h +35 -0
  130. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +64 -34
  131. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +1 -0
  132. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +10 -9
  133. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +3 -28
  134. data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +244 -0
  135. data/vendor/faiss/faiss/impl/ClusteringHelpers.h +94 -0
  136. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +367 -0
  137. data/vendor/faiss/faiss/impl/ClusteringInitialization.h +107 -0
  138. data/vendor/faiss/faiss/impl/CodePacker.cpp +7 -3
  139. data/vendor/faiss/faiss/impl/CodePacker.h +11 -3
  140. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +83 -0
  141. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.h +47 -0
  142. data/vendor/faiss/faiss/impl/DistanceComputer.h +8 -8
  143. data/vendor/faiss/faiss/impl/FaissAssert.h +64 -3
  144. data/vendor/faiss/faiss/impl/FaissException.h +50 -3
  145. data/vendor/faiss/faiss/impl/HNSW.cpp +117 -351
  146. data/vendor/faiss/faiss/impl/HNSW.h +21 -40
  147. data/vendor/faiss/faiss/impl/IDSelector.cpp +15 -11
  148. data/vendor/faiss/faiss/impl/IDSelector.h +8 -8
  149. data/vendor/faiss/faiss/impl/InvertedListScannerStats.h +26 -0
  150. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +114 -102
  151. data/vendor/faiss/faiss/impl/NNDescent.cpp +63 -26
  152. data/vendor/faiss/faiss/impl/NNDescent.h +6 -2
  153. data/vendor/faiss/faiss/impl/NSG.cpp +44 -26
  154. data/vendor/faiss/faiss/impl/NSG.h +20 -10
  155. data/vendor/faiss/faiss/impl/Panorama.cpp +76 -52
  156. data/vendor/faiss/faiss/impl/Panorama.h +265 -78
  157. data/vendor/faiss/faiss/impl/PdxLayout.cpp +93 -0
  158. data/vendor/faiss/faiss/impl/PdxLayout.h +41 -0
  159. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +62 -37
  160. data/vendor/faiss/faiss/impl/PolysemousTraining.h +3 -3
  161. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +35 -35
  162. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +21 -16
  163. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +99 -80
  164. data/vendor/faiss/faiss/impl/Quantizer.h +2 -2
  165. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +135 -37
  166. data/vendor/faiss/faiss/impl/RaBitQUtils.h +148 -21
  167. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +298 -301
  168. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +3 -10
  169. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +15 -41
  170. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.h +0 -4
  171. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +40 -32
  172. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
  173. data/vendor/faiss/faiss/impl/ResultHandler.h +218 -113
  174. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +119 -2362
  175. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +27 -3
  176. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +14 -11
  177. data/vendor/faiss/faiss/impl/VisitedTable.cpp +42 -0
  178. data/vendor/faiss/faiss/impl/VisitedTable.h +76 -0
  179. data/vendor/faiss/faiss/impl/approx_topk/approx_topk.h +276 -0
  180. data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +68 -0
  181. data/vendor/faiss/faiss/{utils → impl}/approx_topk/generic.h +15 -8
  182. data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +68 -0
  183. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab-inl.h +169 -0
  184. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab.h +117 -0
  185. data/vendor/faiss/faiss/impl/approx_topk/simdlib256-inl.h +146 -0
  186. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h +73 -0
  187. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +270 -0
  188. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +460 -0
  189. data/vendor/faiss/faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h +159 -0
  190. data/vendor/faiss/faiss/impl/binary_hamming/IndexPQ_impl.h +92 -0
  191. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +26 -0
  192. data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +26 -0
  193. data/vendor/faiss/faiss/impl/binary_hamming/dispatch.h +143 -0
  194. data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +26 -0
  195. data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +26 -0
  196. data/vendor/faiss/faiss/impl/expanded_scanners.h +163 -0
  197. data/vendor/faiss/faiss/impl/{FastScanDistancePostProcessing.h → fast_scan/FastScanDistancePostProcessing.h} +13 -6
  198. data/vendor/faiss/faiss/impl/{LookupTableScaler.h → fast_scan/LookupTableScaler.h} +16 -5
  199. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +237 -0
  200. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +185 -0
  201. data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +229 -0
  202. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +268 -0
  203. data/vendor/faiss/faiss/impl/{pq4_fast_scan.cpp → fast_scan/fast_scan.cpp} +176 -4
  204. data/vendor/faiss/faiss/impl/fast_scan/fast_scan.h +341 -0
  205. data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +36 -0
  206. data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +40 -0
  207. data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +120 -0
  208. data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +104 -0
  209. data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +213 -0
  210. data/vendor/faiss/faiss/impl/{pq4_fast_scan_search_qbs.cpp → fast_scan/kernels_simd512.h} +26 -348
  211. data/vendor/faiss/faiss/impl/fast_scan/rabitq_dispatching.h +90 -0
  212. data/vendor/faiss/faiss/impl/fast_scan/rabitq_result_handler.h +108 -0
  213. data/vendor/faiss/faiss/impl/{simd_result_handlers.h → fast_scan/simd_result_handlers.h} +290 -142
  214. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +54 -0
  215. data/vendor/faiss/faiss/impl/hnsw/LockVector.h +64 -0
  216. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +91 -0
  217. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -0
  218. data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +104 -0
  219. data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +111 -0
  220. data/vendor/faiss/faiss/impl/index_read.cpp +1950 -505
  221. data/vendor/faiss/faiss/impl/index_read_utils.h +1 -2
  222. data/vendor/faiss/faiss/impl/index_write.cpp +112 -21
  223. data/vendor/faiss/faiss/impl/io.cpp +6 -6
  224. data/vendor/faiss/faiss/impl/io_macros.h +33 -16
  225. data/vendor/faiss/faiss/impl/kmeans1d.cpp +10 -10
  226. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +81 -40
  227. data/vendor/faiss/faiss/impl/lattice_Zn.h +6 -6
  228. data/vendor/faiss/faiss/impl/mapped_io.cpp +15 -8
  229. data/vendor/faiss/faiss/impl/platform_macros.h +11 -4
  230. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +549 -0
  231. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +245 -0
  232. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.h +105 -0
  233. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +106 -0
  234. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +21 -0
  235. data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +21 -0
  236. data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +21 -0
  237. data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx2.h → pq_code_distance/pq_code_distance-avx2.h} +43 -220
  238. data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx512.h → pq_code_distance/pq_code_distance-avx512.h} +25 -112
  239. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +59 -0
  240. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +96 -0
  241. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +256 -0
  242. data/vendor/faiss/faiss/impl/{code_distance/code_distance-sve.h → pq_code_distance/pq_code_distance-sve.cpp} +57 -146
  243. data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +68 -0
  244. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +320 -483
  245. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
  246. data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +121 -0
  247. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +137 -0
  248. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +371 -0
  249. data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +190 -0
  250. data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +94 -0
  251. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +603 -0
  252. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +597 -0
  253. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +388 -0
  254. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +630 -0
  255. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +311 -0
  256. data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +387 -0
  257. data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +54 -0
  258. data/vendor/faiss/faiss/impl/simd_dispatch.h +173 -0
  259. data/vendor/faiss/faiss/impl/simdlib/simdlib.h +57 -0
  260. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_avx2.h +274 -171
  261. data/vendor/faiss/faiss/impl/simdlib/simdlib_avx512.h +414 -0
  262. data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +44 -0
  263. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_emulated.h +231 -166
  264. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_neon.h +275 -217
  265. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_ppc64.h +201 -160
  266. data/vendor/faiss/faiss/impl/svs_io.cpp +12 -3
  267. data/vendor/faiss/faiss/impl/svs_io.h +8 -2
  268. data/vendor/faiss/faiss/index_factory.cpp +115 -28
  269. data/vendor/faiss/faiss/index_io.h +53 -3
  270. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +73 -20
  271. data/vendor/faiss/faiss/invlists/DirectMap.cpp +24 -14
  272. data/vendor/faiss/faiss/invlists/DirectMap.h +4 -3
  273. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +157 -73
  274. data/vendor/faiss/faiss/invlists/InvertedLists.h +86 -23
  275. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +4 -4
  276. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +14 -14
  277. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  278. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +9 -19
  279. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +2 -2
  280. data/vendor/faiss/faiss/svs/IndexSVSFlat.h +2 -0
  281. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +350 -0
  282. data/vendor/faiss/faiss/svs/IndexSVSIVF.h +128 -0
  283. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.cpp +40 -0
  284. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.h +43 -0
  285. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +225 -0
  286. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.h +71 -0
  287. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +25 -1
  288. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +19 -2
  289. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +1 -1
  290. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +19 -2
  291. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +14 -0
  292. data/vendor/faiss/faiss/utils/Heap.cpp +56 -10
  293. data/vendor/faiss/faiss/utils/Heap.h +21 -0
  294. data/vendor/faiss/faiss/utils/NeuralNet.cpp +54 -40
  295. data/vendor/faiss/faiss/utils/NeuralNet.h +1 -1
  296. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +10 -4
  297. data/vendor/faiss/faiss/utils/distances.cpp +507 -559
  298. data/vendor/faiss/faiss/utils/distances.h +118 -1
  299. data/vendor/faiss/faiss/utils/distances_dispatch.h +250 -0
  300. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +8 -7
  301. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +33 -14
  302. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +12 -1
  303. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +16 -293
  304. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +57 -0
  305. data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +290 -0
  306. data/vendor/faiss/faiss/utils/distances_simd.cpp +72 -3681
  307. data/vendor/faiss/faiss/utils/extra_distances.cpp +60 -102
  308. data/vendor/faiss/faiss/utils/extra_distances.h +79 -7
  309. data/vendor/faiss/faiss/utils/hamming-inl.h +13 -11
  310. data/vendor/faiss/faiss/utils/hamming.cpp +66 -517
  311. data/vendor/faiss/faiss/utils/hamming.h +92 -2
  312. data/vendor/faiss/faiss/utils/hamming_distance/common.h +287 -10
  313. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +15 -0
  314. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +15 -0
  315. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx2.h +142 -0
  316. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +234 -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 -987
  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 +251 -0
  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 +124 -343
  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 +154 -0
  335. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +777 -0
  336. data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +306 -0
  337. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +1431 -0
  338. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +1095 -0
  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 +392 -0
  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 +1085 -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_neon.cpp +55 -0
  350. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +55 -0
  351. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +32 -0
  352. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +43 -0
  353. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +57 -0
  354. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +45 -0
  355. data/vendor/faiss/faiss/utils/simd_levels.cpp +334 -0
  356. data/vendor/faiss/faiss/utils/simd_levels.h +183 -0
  357. data/vendor/faiss/faiss/utils/sorting.cpp +48 -36
  358. data/vendor/faiss/faiss/utils/utils.cpp +21 -14
  359. data/vendor/faiss/faiss/utils/utils.h +3 -3
  360. metadata +156 -42
  361. data/vendor/faiss/faiss/impl/RaBitQStats.cpp +0 -29
  362. data/vendor/faiss/faiss/impl/RaBitQStats.h +0 -56
  363. data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +0 -81
  364. data/vendor/faiss/faiss/impl/code_distance/code_distance.h +0 -186
  365. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +0 -216
  366. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +0 -224
  367. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +0 -84
  368. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +0 -196
  369. data/vendor/faiss/faiss/utils/approx_topk/mode.h +0 -34
  370. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +0 -36
  371. data/vendor/faiss/faiss/utils/extra_distances-inl.h +0 -228
  372. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +0 -462
  373. data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +0 -490
  374. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -450
  375. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +0 -87
  376. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +0 -524
  377. data/vendor/faiss/faiss/utils/simdlib.h +0 -42
  378. data/vendor/faiss/faiss/utils/simdlib_avx512.h +0 -296
  379. /data/vendor/faiss/faiss/{cppcontrib/factory_tools.h → factory_tools.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]+)")) {
@@ -220,6 +233,9 @@ VectorTransform* parse_VectorTransform(const std::string& description, int d) {
220
233
  if (match("RR([0-9]+)?")) {
221
234
  return new RandomRotationMatrix(d, mres_to_int(sm[1], d));
222
235
  }
236
+ if (match("HR([0-9]+)?")) {
237
+ return new HadamardRotation(d, mres_to_int(sm[1], 12345));
238
+ }
223
239
  if (match("ITQ([0-9]+)?")) {
224
240
  return new ITQTransform(d, mres_to_int(sm[1], d), sm[1].length() > 0);
225
241
  }
@@ -261,7 +277,7 @@ Index* parse_coarse_quantizer(
261
277
  size_t& nlist,
262
278
  bool& use_2layer) {
263
279
  std::smatch sm;
264
- auto match = [&sm, description](std::string pattern) {
280
+ auto match = [&sm, description](const std::string& pattern) {
265
281
  return re_match(description, pattern, sm);
266
282
  };
267
283
  use_2layer = false;
@@ -288,10 +304,34 @@ Index* parse_coarse_quantizer(
288
304
  int R = std::stoi(sm[2]);
289
305
  return new IndexNSGFlat(d, R, mt);
290
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
291
329
  if (match("IVF([0-9]+[kM]?)\\(Index([0-9])\\)")) {
292
330
  nlist = parse_nlist(sm[1].str());
293
331
  int no = std::stoi(sm[2].str());
294
- FAISS_ASSERT(no >= 0 && no < parenthesis_indexes.size());
332
+ FAISS_ASSERT(
333
+ no >= 0 &&
334
+ static_cast<size_t>(no) < parenthesis_indexes.size());
295
335
  return parenthesis_indexes[no].release();
296
336
  }
297
337
 
@@ -337,9 +377,11 @@ IndexIVF* parse_IndexIVF(
337
377
  if (match("FlatDedup")) {
338
378
  return new IndexIVFFlatDedup(get_q(), d, nlist, mt, own_il);
339
379
  }
340
- if (match("FlatPanorama([0-9]+)?")) {
380
+ if (match("FlatPanorama([0-9]+)?(_([0-9]+))?")) {
341
381
  int nlevels = mres_to_int(sm[1], 8); // default to 8 levels
342
- 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);
343
385
  }
344
386
  if (match(sq_pattern)) {
345
387
  return new IndexIVFScalarQuantizer(
@@ -585,7 +627,10 @@ SVSStorageKind parse_lvq(const std::string& lvq_string) {
585
627
  if (lvq_string == "LVQ4x8") {
586
628
  return SVSStorageKind::SVS_LVQ4x8;
587
629
  }
588
- FAISS_ASSERT(!"not supported SVS LVQ level");
630
+ if (lvq_string == "LVQ8x0") {
631
+ return SVSStorageKind::SVS_LVQ8x0;
632
+ }
633
+ FAISS_ASSERT(false && "not supported SVS LVQ level");
589
634
  }
590
635
 
591
636
  SVSStorageKind parse_leanvec(const std::string& leanvec_string) {
@@ -598,7 +643,7 @@ SVSStorageKind parse_leanvec(const std::string& leanvec_string) {
598
643
  if (leanvec_string == "LeanVec8x8") {
599
644
  return SVSStorageKind::SVS_LeanVec8x8;
600
645
  }
601
- FAISS_ASSERT(!"not supported SVS Leanvec level");
646
+ FAISS_ASSERT(false && "not supported SVS Leanvec level");
602
647
  }
603
648
 
604
649
  Index* parse_svs_datatype(
@@ -610,43 +655,72 @@ Index* parse_svs_datatype(
610
655
  std::smatch sm;
611
656
 
612
657
  if (datatype_string.empty()) {
613
- if (index_type == "Vamana")
658
+ if (index_type == "Vamana") {
614
659
  return new IndexSVSVamana(d, std::stoul(arg_string), mt);
615
- if (index_type == "Flat")
660
+ }
661
+ if (index_type == "Flat") {
616
662
  return new IndexSVSFlat(d, mt);
617
- FAISS_ASSERT(!"Unspported SVS index type");
663
+ }
664
+ if (index_type == "IVF") {
665
+ return new IndexSVSIVF(d, std::stoul(arg_string), mt);
666
+ }
667
+ FAISS_ASSERT(false && "Unsupported SVS index type");
618
668
  }
619
669
  if (re_match(datatype_string, "FP16", sm)) {
620
- if (index_type == "Vamana")
670
+ if (index_type == "Vamana") {
621
671
  return new IndexSVSVamana(
622
672
  d, std::stoul(arg_string), mt, SVSStorageKind::SVS_FP16);
623
- FAISS_ASSERT(!"Unspported SVS index type for Float16");
673
+ }
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");
624
679
  }
625
680
  if (re_match(datatype_string, "SQI8", sm)) {
626
- if (index_type == "Vamana")
681
+ if (index_type == "Vamana") {
627
682
  return new IndexSVSVamana(
628
683
  d, std::stoul(arg_string), mt, SVSStorageKind::SVS_SQI8);
629
- FAISS_ASSERT(!"Unspported SVS index type for SQI8");
684
+ }
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");
630
690
  }
631
691
  if (re_match(datatype_string, "(LVQ[0-9]+x[0-9]+)", sm)) {
632
- if (index_type == "Vamana")
692
+ if (index_type == "Vamana") {
633
693
  return new IndexSVSVamanaLVQ(
634
694
  d, std::stoul(arg_string), mt, parse_lvq(sm[0].str()));
635
- FAISS_ASSERT(!"Unspported SVS index type for LVQ");
695
+ }
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");
636
701
  }
637
702
  if (re_match(datatype_string, "(LeanVec[0-9]+x[0-9]+)(_[0-9]+)?", sm)) {
638
703
  std::string leanvec_d_string =
639
704
  sm[2].length() > 0 ? sm[2].str().substr(1) : "0";
640
- int leanvec_d = std::stoul(leanvec_d_string);
705
+ int leanvec_d = static_cast<int>(std::stoul(leanvec_d_string));
641
706
 
642
- if (index_type == "Vamana")
707
+ if (index_type == "Vamana") {
643
708
  return new IndexSVSVamanaLeanVec(
644
709
  d,
645
710
  std::stoul(arg_string),
646
711
  mt,
647
712
  leanvec_d,
648
713
  parse_leanvec(sm[1].str()));
649
- FAISS_ASSERT(!"Unspported SVS index type for LeanVec");
714
+ }
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");
650
724
  }
651
725
  return nullptr;
652
726
  }
@@ -659,7 +733,6 @@ Index* parse_IndexSVS(const std::string& code_string, int d, MetricType mt) {
659
733
  return parse_svs_datatype("Flat", "", datatype_string, d, mt);
660
734
  }
661
735
  if (re_match(code_string, "Vamana([0-9]+)(,.+)?", sm)) {
662
- Index* index{nullptr};
663
736
  std::string degree_string = sm[1].str();
664
737
  std::string datatype_string =
665
738
  sm[2].length() > 0 ? sm[2].str().substr(1) : "";
@@ -667,7 +740,10 @@ Index* parse_IndexSVS(const std::string& code_string, int d, MetricType mt) {
667
740
  "Vamana", degree_string, datatype_string, d, mt);
668
741
  }
669
742
  if (re_match(code_string, "IVF([0-9]+)(,.+)?", sm)) {
670
- FAISS_ASSERT(!"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);
671
747
  }
672
748
  return nullptr;
673
749
  }
@@ -703,6 +779,17 @@ Index* parse_other_indexes(
703
779
  }
704
780
  }
705
781
 
782
+ // IndexFlatIPPanorama
783
+ if (match("FlatIPPanorama([0-9]+)(_[0-9]+)?")) {
784
+ FAISS_THROW_IF_NOT(metric == METRIC_INNER_PRODUCT);
785
+ int nlevels = std::stoi(sm[1].str());
786
+ if (sm[2].length() == 0) {
787
+ return new IndexFlatIPPanorama(d, nlevels);
788
+ }
789
+ int batch_size = std::stoi(sm[2].str().substr(1));
790
+ return new IndexFlatIPPanorama(d, nlevels, (size_t)batch_size);
791
+ }
792
+
706
793
  // IndexLSH
707
794
  if (match("LSH([0-9]*)(r?)(t?)")) {
708
795
  int nbits = sm[1].length() > 0 ? std::stoi(sm[1].str()) : d;
@@ -945,7 +1032,7 @@ std::unique_ptr<Index> index_factory_sub(
945
1032
  int i0, i1;
946
1033
  find_matching_parentheses(description, i0, i1, begin);
947
1034
  std::string sub_description = description.substr(i0 + 1, i1 - i0 - 1);
948
- int no = parenthesis_indexes.size();
1035
+ size_t no = parenthesis_indexes.size();
949
1036
  parenthesis_indexes.push_back(
950
1037
  index_factory_sub(d, sub_description, metric));
951
1038
  description = description.substr(0, i0 + 1) + "Index" +
@@ -11,13 +11,19 @@
11
11
  #define FAISS_INDEX_IO_H
12
12
 
13
13
  #include <cstdio>
14
+ #include <memory>
15
+
16
+ #include <faiss/impl/platform_macros.h>
14
17
 
15
18
  /** I/O functions can read/write to a filename, a file handle or to an
16
19
  * object that abstracts the medium.
17
20
  *
18
- * The read functions return objects that should be deallocated with
19
- * delete. All references within these objects are owned by the
20
- * object.
21
+ * The read functions come in two forms:
22
+ * - read_*_up() returns a std::unique_ptr that owns the result.
23
+ * - read_*() returns a raw pointer for backward compatibility.
24
+ * The caller is responsible for deleting the returned object.
25
+ *
26
+ * All references within these objects are owned by the object.
21
27
  */
22
28
 
23
29
  namespace faiss {
@@ -64,29 +70,73 @@ const int IO_FLAG_MMAP = IO_FLAG_SKIP_IVF_DATA | 0x646f0000;
64
70
  // after OnDiskInvertedLists get properly updated.
65
71
  const int IO_FLAG_MMAP_IFC = 1 << 9;
66
72
 
73
+ FAISS_API extern bool index_read_warn_on_null_invlists;
74
+
67
75
  Index* read_index(const char* fname, int io_flags = 0);
68
76
  Index* read_index(FILE* f, int io_flags = 0);
69
77
  Index* read_index(IOReader* reader, int io_flags = 0);
70
78
 
79
+ std::unique_ptr<Index> read_index_up(const char* fname, int io_flags = 0);
80
+ std::unique_ptr<Index> read_index_up(FILE* f, int io_flags = 0);
81
+ std::unique_ptr<Index> read_index_up(IOReader* reader, int io_flags = 0);
82
+
71
83
  IndexBinary* read_index_binary(const char* fname, int io_flags = 0);
72
84
  IndexBinary* read_index_binary(FILE* f, int io_flags = 0);
73
85
  IndexBinary* read_index_binary(IOReader* reader, int io_flags = 0);
74
86
 
87
+ std::unique_ptr<IndexBinary> read_index_binary_up(
88
+ const char* fname,
89
+ int io_flags = 0);
90
+ std::unique_ptr<IndexBinary> read_index_binary_up(FILE* f, int io_flags = 0);
91
+ std::unique_ptr<IndexBinary> read_index_binary_up(
92
+ IOReader* reader,
93
+ int io_flags = 0);
94
+
75
95
  void write_VectorTransform(const VectorTransform* vt, const char* fname);
76
96
  void write_VectorTransform(const VectorTransform* vt, IOWriter* f);
77
97
 
78
98
  VectorTransform* read_VectorTransform(const char* fname);
79
99
  VectorTransform* read_VectorTransform(IOReader* f);
80
100
 
101
+ std::unique_ptr<VectorTransform> read_VectorTransform_up(const char* fname);
102
+ std::unique_ptr<VectorTransform> read_VectorTransform_up(IOReader* f);
103
+
81
104
  ProductQuantizer* read_ProductQuantizer(const char* fname);
82
105
  ProductQuantizer* read_ProductQuantizer(IOReader* reader);
83
106
 
107
+ std::unique_ptr<ProductQuantizer> read_ProductQuantizer_up(const char* fname);
108
+ std::unique_ptr<ProductQuantizer> read_ProductQuantizer_up(IOReader* reader);
109
+
84
110
  void write_ProductQuantizer(const ProductQuantizer* pq, const char* fname);
85
111
  void write_ProductQuantizer(const ProductQuantizer* pq, IOWriter* f);
86
112
 
87
113
  void write_InvertedLists(const InvertedLists* ils, IOWriter* f);
88
114
  InvertedLists* read_InvertedLists(IOReader* reader, int io_flags = 0);
89
115
 
116
+ std::unique_ptr<InvertedLists> read_InvertedLists_up(
117
+ IOReader* reader,
118
+ int io_flags = 0);
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
+
90
140
  } // namespace faiss
91
141
 
92
142
  #endif
@@ -5,8 +5,11 @@
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
 
11
+ #include <memory>
12
+
10
13
  #include <faiss/impl/CodePacker.h>
11
14
  #include <faiss/impl/FaissAssert.h>
12
15
  #include <faiss/impl/IDSelector.h>
@@ -17,23 +20,25 @@
17
20
  namespace faiss {
18
21
 
19
22
  BlockInvertedLists::BlockInvertedLists(
20
- size_t nlist,
21
- size_t n_per_block,
22
- size_t block_size)
23
- : InvertedLists(nlist, InvertedLists::INVALID_CODE_SIZE),
24
- n_per_block(n_per_block),
25
- block_size(block_size) {
26
- ids.resize(nlist);
27
- 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);
28
31
  }
29
32
 
30
- BlockInvertedLists::BlockInvertedLists(size_t nlist, const CodePacker* packer)
31
- : InvertedLists(nlist, InvertedLists::INVALID_CODE_SIZE),
32
- n_per_block(packer->nvec),
33
- block_size(packer->block_size),
34
- packer(packer) {
35
- ids.resize(nlist);
36
- 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);
37
42
  }
38
43
 
39
44
  BlockInvertedLists::BlockInvertedLists()
@@ -81,8 +86,8 @@ const uint8_t* BlockInvertedLists::get_codes(size_t list_no) const {
81
86
 
82
87
  size_t BlockInvertedLists::remove_ids(const IDSelector& sel) {
83
88
  idx_t nremove = 0;
84
- #pragma omp parallel for
85
- for (idx_t i = 0; i < nlist; i++) {
89
+ #pragma omp parallel for reduction(+ : nremove)
90
+ for (idx_t i = 0; i < static_cast<idx_t>(nlist); i++) {
86
91
  std::vector<uint8_t> buffer(packer->code_size);
87
92
  idx_t l = ids[i].size(), j = 0;
88
93
  while (j < l) {
@@ -95,8 +100,9 @@ size_t BlockInvertedLists::remove_ids(const IDSelector& sel) {
95
100
  j++;
96
101
  }
97
102
  }
103
+ idx_t orig_size = ids[i].size();
98
104
  resize(i, l);
99
- nremove += ids[i].size() - l;
105
+ nremove += orig_size - l;
100
106
  }
101
107
 
102
108
  return nremove;
@@ -160,21 +166,68 @@ void BlockInvertedListsIOHook::write(const InvertedLists* ils_in, IOWriter* f)
160
166
 
161
167
  InvertedLists* BlockInvertedListsIOHook::read(IOReader* f, int /* io_flags */)
162
168
  const {
163
- BlockInvertedLists* il = new BlockInvertedLists();
169
+ auto il = std::make_unique<BlockInvertedLists>();
164
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
+ }
165
182
  READ1(il->code_size);
166
183
  READ1(il->n_per_block);
167
184
  READ1(il->block_size);
168
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
+
169
207
  il->ids.resize(il->nlist);
170
208
  il->codes.resize(il->nlist);
171
209
 
172
210
  for (size_t i = 0; i < il->nlist; i++) {
173
211
  READVECTOR(il->ids[i]);
174
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);
175
228
  }
176
229
 
177
- return il;
230
+ return il.release();
178
231
  }
179
232
 
180
233
  } // namespace faiss