faiss 0.3.0 → 0.3.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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/ext/faiss/extconf.rb +9 -2
  6. data/ext/faiss/index.cpp +1 -1
  7. data/ext/faiss/index_binary.cpp +2 -2
  8. data/ext/faiss/product_quantizer.cpp +1 -1
  9. data/lib/faiss/version.rb +1 -1
  10. data/vendor/faiss/faiss/AutoTune.cpp +7 -7
  11. data/vendor/faiss/faiss/AutoTune.h +1 -2
  12. data/vendor/faiss/faiss/Clustering.cpp +39 -22
  13. data/vendor/faiss/faiss/Clustering.h +40 -21
  14. data/vendor/faiss/faiss/IVFlib.cpp +26 -12
  15. data/vendor/faiss/faiss/Index.cpp +1 -1
  16. data/vendor/faiss/faiss/Index.h +40 -10
  17. data/vendor/faiss/faiss/Index2Layer.cpp +7 -7
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +176 -166
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +15 -15
  20. data/vendor/faiss/faiss/IndexBinary.cpp +9 -4
  21. data/vendor/faiss/faiss/IndexBinary.h +8 -19
  22. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +2 -1
  23. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +24 -31
  24. data/vendor/faiss/faiss/IndexBinaryHNSW.h +1 -1
  25. data/vendor/faiss/faiss/IndexBinaryHash.cpp +25 -50
  26. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +107 -188
  27. data/vendor/faiss/faiss/IndexFastScan.cpp +95 -146
  28. data/vendor/faiss/faiss/IndexFastScan.h +9 -8
  29. data/vendor/faiss/faiss/IndexFlat.cpp +206 -10
  30. data/vendor/faiss/faiss/IndexFlat.h +20 -1
  31. data/vendor/faiss/faiss/IndexFlatCodes.cpp +170 -5
  32. data/vendor/faiss/faiss/IndexFlatCodes.h +23 -4
  33. data/vendor/faiss/faiss/IndexHNSW.cpp +231 -382
  34. data/vendor/faiss/faiss/IndexHNSW.h +62 -49
  35. data/vendor/faiss/faiss/IndexIDMap.cpp +69 -28
  36. data/vendor/faiss/faiss/IndexIDMap.h +24 -2
  37. data/vendor/faiss/faiss/IndexIVF.cpp +162 -56
  38. data/vendor/faiss/faiss/IndexIVF.h +46 -6
  39. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +33 -26
  40. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +6 -2
  41. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +19 -46
  42. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +4 -3
  43. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +502 -401
  44. data/vendor/faiss/faiss/IndexIVFFastScan.h +63 -26
  45. data/vendor/faiss/faiss/IndexIVFFlat.cpp +15 -5
  46. data/vendor/faiss/faiss/IndexIVFFlat.h +3 -2
  47. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +172 -0
  48. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.h +56 -0
  49. data/vendor/faiss/faiss/IndexIVFPQ.cpp +79 -125
  50. data/vendor/faiss/faiss/IndexIVFPQ.h +6 -7
  51. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +39 -52
  52. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +4 -3
  53. data/vendor/faiss/faiss/IndexIVFPQR.cpp +45 -29
  54. data/vendor/faiss/faiss/IndexIVFPQR.h +5 -2
  55. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +25 -27
  56. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +6 -6
  57. data/vendor/faiss/faiss/IndexLSH.cpp +14 -16
  58. data/vendor/faiss/faiss/IndexLattice.cpp +1 -19
  59. data/vendor/faiss/faiss/IndexLattice.h +3 -22
  60. data/vendor/faiss/faiss/IndexNNDescent.cpp +3 -33
  61. data/vendor/faiss/faiss/IndexNNDescent.h +1 -1
  62. data/vendor/faiss/faiss/IndexNSG.cpp +11 -27
  63. data/vendor/faiss/faiss/IndexNSG.h +11 -11
  64. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +56 -0
  65. data/vendor/faiss/faiss/IndexNeuralNetCodec.h +49 -0
  66. data/vendor/faiss/faiss/IndexPQ.cpp +72 -88
  67. data/vendor/faiss/faiss/IndexPQ.h +1 -4
  68. data/vendor/faiss/faiss/IndexPQFastScan.cpp +1 -1
  69. data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -31
  70. data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
  71. data/vendor/faiss/faiss/IndexRefine.cpp +54 -24
  72. data/vendor/faiss/faiss/IndexRefine.h +7 -0
  73. data/vendor/faiss/faiss/IndexReplicas.cpp +23 -26
  74. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +25 -17
  75. data/vendor/faiss/faiss/IndexScalarQuantizer.h +6 -4
  76. data/vendor/faiss/faiss/IndexShards.cpp +21 -29
  77. data/vendor/faiss/faiss/IndexShardsIVF.cpp +1 -2
  78. data/vendor/faiss/faiss/MatrixStats.cpp +17 -32
  79. data/vendor/faiss/faiss/MatrixStats.h +21 -9
  80. data/vendor/faiss/faiss/MetaIndexes.cpp +35 -35
  81. data/vendor/faiss/faiss/MetricType.h +7 -2
  82. data/vendor/faiss/faiss/VectorTransform.cpp +13 -26
  83. data/vendor/faiss/faiss/VectorTransform.h +7 -7
  84. data/vendor/faiss/faiss/clone_index.cpp +15 -10
  85. data/vendor/faiss/faiss/clone_index.h +3 -0
  86. data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +95 -17
  87. data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +152 -0
  88. data/vendor/faiss/faiss/cppcontrib/factory_tools.h +24 -0
  89. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +83 -30
  90. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +123 -8
  91. data/vendor/faiss/faiss/gpu/GpuCloner.h +22 -0
  92. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +13 -0
  93. data/vendor/faiss/faiss/gpu/GpuDistance.h +46 -38
  94. data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -1
  95. data/vendor/faiss/faiss/gpu/GpuIndex.h +30 -12
  96. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +282 -0
  97. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +4 -4
  98. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +14 -9
  99. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +20 -3
  100. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +22 -11
  101. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +1 -3
  102. data/vendor/faiss/faiss/gpu/GpuResources.cpp +24 -3
  103. data/vendor/faiss/faiss/gpu/GpuResources.h +39 -11
  104. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +142 -17
  105. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +57 -3
  106. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +26 -21
  107. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +7 -1
  108. data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +8 -5
  109. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +25 -0
  110. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +129 -9
  111. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +332 -40
  112. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +299 -208
  113. data/vendor/faiss/faiss/gpu/test/TestGpuMemoryException.cpp +1 -0
  114. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +1 -1
  115. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +6 -0
  116. data/vendor/faiss/faiss/gpu/utils/RaftUtils.h +75 -0
  117. data/vendor/faiss/faiss/gpu/utils/Timer.cpp +4 -1
  118. data/vendor/faiss/faiss/gpu/utils/Timer.h +1 -1
  119. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +3 -1
  120. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +5 -5
  121. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +26 -1
  122. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +10 -3
  123. data/vendor/faiss/faiss/impl/DistanceComputer.h +70 -1
  124. data/vendor/faiss/faiss/impl/FaissAssert.h +4 -2
  125. data/vendor/faiss/faiss/impl/FaissException.h +13 -34
  126. data/vendor/faiss/faiss/impl/HNSW.cpp +605 -186
  127. data/vendor/faiss/faiss/impl/HNSW.h +52 -30
  128. data/vendor/faiss/faiss/impl/IDSelector.h +4 -4
  129. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +11 -9
  130. data/vendor/faiss/faiss/impl/LookupTableScaler.h +34 -0
  131. data/vendor/faiss/faiss/impl/NNDescent.cpp +42 -27
  132. data/vendor/faiss/faiss/impl/NSG.cpp +0 -29
  133. data/vendor/faiss/faiss/impl/NSG.h +1 -1
  134. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +14 -12
  135. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +1 -1
  136. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +25 -22
  137. data/vendor/faiss/faiss/impl/ProductQuantizer.h +6 -2
  138. data/vendor/faiss/faiss/impl/Quantizer.h +1 -1
  139. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +27 -1015
  140. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +5 -63
  141. data/vendor/faiss/faiss/impl/ResultHandler.h +347 -172
  142. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +1104 -147
  143. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +3 -8
  144. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +285 -42
  145. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx512.h +248 -0
  146. data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +21 -14
  147. data/vendor/faiss/faiss/impl/code_distance/code_distance.h +22 -12
  148. data/vendor/faiss/faiss/impl/index_read.cpp +74 -34
  149. data/vendor/faiss/faiss/impl/index_read_utils.h +37 -0
  150. data/vendor/faiss/faiss/impl/index_write.cpp +88 -51
  151. data/vendor/faiss/faiss/impl/io.cpp +23 -15
  152. data/vendor/faiss/faiss/impl/io.h +4 -4
  153. data/vendor/faiss/faiss/impl/io_macros.h +6 -0
  154. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -1
  155. data/vendor/faiss/faiss/impl/platform_macros.h +40 -1
  156. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +14 -0
  157. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +7 -6
  158. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +52 -38
  159. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +487 -49
  160. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +960 -0
  161. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +176 -0
  162. data/vendor/faiss/faiss/impl/simd_result_handlers.h +481 -225
  163. data/vendor/faiss/faiss/index_factory.cpp +41 -20
  164. data/vendor/faiss/faiss/index_io.h +12 -5
  165. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +28 -8
  166. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +3 -0
  167. data/vendor/faiss/faiss/invlists/DirectMap.cpp +10 -2
  168. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +73 -17
  169. data/vendor/faiss/faiss/invlists/InvertedLists.h +26 -8
  170. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +24 -9
  171. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +2 -1
  172. data/vendor/faiss/faiss/python/python_callbacks.cpp +4 -4
  173. data/vendor/faiss/faiss/utils/Heap.cpp +3 -1
  174. data/vendor/faiss/faiss/utils/Heap.h +105 -0
  175. data/vendor/faiss/faiss/utils/NeuralNet.cpp +342 -0
  176. data/vendor/faiss/faiss/utils/NeuralNet.h +147 -0
  177. data/vendor/faiss/faiss/utils/WorkerThread.h +1 -0
  178. data/vendor/faiss/faiss/utils/bf16.h +36 -0
  179. data/vendor/faiss/faiss/utils/distances.cpp +147 -123
  180. data/vendor/faiss/faiss/utils/distances.h +86 -9
  181. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +5 -5
  182. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +2 -2
  183. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +2 -2
  184. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +1 -1
  185. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +5 -5
  186. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.h +1 -1
  187. data/vendor/faiss/faiss/utils/distances_simd.cpp +1589 -243
  188. data/vendor/faiss/faiss/utils/extra_distances-inl.h +70 -0
  189. data/vendor/faiss/faiss/utils/extra_distances.cpp +85 -137
  190. data/vendor/faiss/faiss/utils/extra_distances.h +3 -2
  191. data/vendor/faiss/faiss/utils/fp16-arm.h +29 -0
  192. data/vendor/faiss/faiss/utils/fp16.h +2 -0
  193. data/vendor/faiss/faiss/utils/hamming.cpp +163 -111
  194. data/vendor/faiss/faiss/utils/hamming.h +58 -0
  195. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +16 -89
  196. data/vendor/faiss/faiss/utils/hamming_distance/common.h +1 -0
  197. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +19 -88
  198. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +58 -0
  199. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +14 -104
  200. data/vendor/faiss/faiss/utils/partitioning.cpp +3 -4
  201. data/vendor/faiss/faiss/utils/prefetch.h +77 -0
  202. data/vendor/faiss/faiss/utils/quantize_lut.cpp +0 -14
  203. data/vendor/faiss/faiss/utils/random.cpp +43 -0
  204. data/vendor/faiss/faiss/utils/random.h +25 -0
  205. data/vendor/faiss/faiss/utils/simdlib.h +10 -1
  206. data/vendor/faiss/faiss/utils/simdlib_avx2.h +0 -6
  207. data/vendor/faiss/faiss/utils/simdlib_avx512.h +296 -0
  208. data/vendor/faiss/faiss/utils/simdlib_neon.h +77 -79
  209. data/vendor/faiss/faiss/utils/simdlib_ppc64.h +1084 -0
  210. data/vendor/faiss/faiss/utils/sorting.cpp +140 -5
  211. data/vendor/faiss/faiss/utils/sorting.h +27 -0
  212. data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +176 -0
  213. data/vendor/faiss/faiss/utils/utils.cpp +120 -7
  214. data/vendor/faiss/faiss/utils/utils.h +60 -20
  215. metadata +23 -4
  216. data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +0 -102
@@ -5,8 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- // -*- c++ -*-
9
-
8
+ #include <faiss/impl/index_read_utils.h>
10
9
  #include <faiss/index_io.h>
11
10
 
12
11
  #include <faiss/impl/io_macros.h>
@@ -33,6 +32,7 @@
33
32
  #include <faiss/IndexIVFAdditiveQuantizer.h>
34
33
  #include <faiss/IndexIVFAdditiveQuantizerFastScan.h>
35
34
  #include <faiss/IndexIVFFlat.h>
35
+ #include <faiss/IndexIVFIndependentQuantizer.h>
36
36
  #include <faiss/IndexIVFPQ.h>
37
37
  #include <faiss/IndexIVFPQFastScan.h>
38
38
  #include <faiss/IndexIVFPQR.h>
@@ -62,7 +62,7 @@ namespace faiss {
62
62
  * Read
63
63
  **************************************************************/
64
64
 
65
- static void read_index_header(Index* idx, IOReader* f) {
65
+ void read_index_header(Index* idx, IOReader* f) {
66
66
  READ1(idx->d);
67
67
  READ1(idx->ntotal);
68
68
  idx_t dummy;
@@ -231,7 +231,7 @@ InvertedLists* read_InvertedLists(IOReader* f, int io_flags) {
231
231
  }
232
232
  }
233
233
 
234
- static void read_InvertedLists(IndexIVF* ivf, IOReader* f, int io_flags) {
234
+ void read_InvertedLists(IndexIVF* ivf, IOReader* f, int io_flags) {
235
235
  InvertedLists* ils = read_InvertedLists(f, io_flags);
236
236
  if (ils) {
237
237
  FAISS_THROW_IF_NOT(ils->nlist == ivf->nlist);
@@ -243,7 +243,7 @@ static void read_InvertedLists(IndexIVF* ivf, IOReader* f, int io_flags) {
243
243
  ivf->own_invlists = true;
244
244
  }
245
245
 
246
- static void read_ProductQuantizer(ProductQuantizer* pq, IOReader* f) {
246
+ void read_ProductQuantizer(ProductQuantizer* pq, IOReader* f) {
247
247
  READ1(pq->d);
248
248
  READ1(pq->M);
249
249
  READ1(pq->nbits);
@@ -291,11 +291,17 @@ static void read_AdditiveQuantizer(AdditiveQuantizer* aq, IOReader* f) {
291
291
  aq->set_derived_values();
292
292
  }
293
293
 
294
- static void read_ResidualQuantizer(ResidualQuantizer* rq, IOReader* f) {
294
+ static void read_ResidualQuantizer(
295
+ ResidualQuantizer* rq,
296
+ IOReader* f,
297
+ int io_flags) {
295
298
  read_AdditiveQuantizer(rq, f);
296
299
  READ1(rq->train_type);
297
300
  READ1(rq->max_beam_size);
298
- if (!(rq->train_type & ResidualQuantizer::Skip_codebook_tables)) {
301
+ if ((rq->train_type & ResidualQuantizer::Skip_codebook_tables) ||
302
+ (io_flags & IO_FLAG_SKIP_PRECOMPUTE_TABLE)) {
303
+ // don't precompute the tables
304
+ } else {
299
305
  rq->compute_codebook_tables();
300
306
  }
301
307
  }
@@ -324,12 +330,13 @@ static void read_ProductAdditiveQuantizer(
324
330
 
325
331
  static void read_ProductResidualQuantizer(
326
332
  ProductResidualQuantizer* prq,
327
- IOReader* f) {
333
+ IOReader* f,
334
+ int io_flags) {
328
335
  read_ProductAdditiveQuantizer(prq, f);
329
336
 
330
337
  for (size_t i = 0; i < prq->nsplits; i++) {
331
338
  auto rq = new ResidualQuantizer();
332
- read_ResidualQuantizer(rq, f);
339
+ read_ResidualQuantizer(rq, f, io_flags);
333
340
  prq->quantizers.push_back(rq);
334
341
  }
335
342
  }
@@ -346,7 +353,7 @@ static void read_ProductLocalSearchQuantizer(
346
353
  }
347
354
  }
348
355
 
349
- static void read_ScalarQuantizer(ScalarQuantizer* ivsc, IOReader* f) {
356
+ void read_ScalarQuantizer(ScalarQuantizer* ivsc, IOReader* f) {
350
357
  READ1(ivsc->qtype);
351
358
  READ1(ivsc->rangestat);
352
359
  READ1(ivsc->rangestat_arg);
@@ -367,7 +374,10 @@ static void read_HNSW(HNSW* hnsw, IOReader* f) {
367
374
  READ1(hnsw->max_level);
368
375
  READ1(hnsw->efConstruction);
369
376
  READ1(hnsw->efSearch);
370
- READ1(hnsw->upper_beam);
377
+
378
+ // // deprecated field
379
+ // READ1(hnsw->upper_beam);
380
+ READ1_DUMMY(int)
371
381
  }
372
382
 
373
383
  static void read_NSG(NSG* nsg, IOReader* f) {
@@ -390,15 +400,12 @@ static void read_NSG(NSG* nsg, IOReader* f) {
390
400
  graph = std::make_shared<nsg::Graph<int>>(N, R);
391
401
  std::fill_n(graph->data, N * R, EMPTY_ID);
392
402
 
393
- int size = 0;
394
-
395
403
  for (int i = 0; i < N; i++) {
396
404
  for (int j = 0; j < R + 1; j++) {
397
405
  int id;
398
406
  READ1(id);
399
407
  if (id != EMPTY_ID) {
400
408
  graph->at(i, j) = id;
401
- size += 1;
402
409
  } else {
403
410
  break;
404
411
  }
@@ -428,14 +435,14 @@ ProductQuantizer* read_ProductQuantizer(const char* fname) {
428
435
 
429
436
  ProductQuantizer* read_ProductQuantizer(IOReader* reader) {
430
437
  ProductQuantizer* pq = new ProductQuantizer();
431
- ScopeDeleter1<ProductQuantizer> del(pq);
438
+ std::unique_ptr<ProductQuantizer> del(pq);
432
439
 
433
440
  read_ProductQuantizer(pq, reader);
434
441
  del.release();
435
442
  return pq;
436
443
  }
437
444
 
438
- static void read_direct_map(DirectMap* dm, IOReader* f) {
445
+ void read_direct_map(DirectMap* dm, IOReader* f) {
439
446
  char maintain_direct_map;
440
447
  READ1(maintain_direct_map);
441
448
  dm->type = (DirectMap::Type)maintain_direct_map;
@@ -451,10 +458,10 @@ static void read_direct_map(DirectMap* dm, IOReader* f) {
451
458
  }
452
459
  }
453
460
 
454
- static void read_ivf_header(
461
+ void read_ivf_header(
455
462
  IndexIVF* ivf,
456
463
  IOReader* f,
457
- std::vector<std::vector<idx_t>>* ids = nullptr) {
464
+ std::vector<std::vector<idx_t>>* ids) {
458
465
  read_index_header(ivf, f);
459
466
  READ1(ivf->nlist);
460
467
  READ1(ivf->nprobe);
@@ -469,7 +476,7 @@ static void read_ivf_header(
469
476
  }
470
477
 
471
478
  // used for legacy formats
472
- static ArrayInvertedLists* set_array_invlist(
479
+ ArrayInvertedLists* set_array_invlist(
473
480
  IndexIVF* ivf,
474
481
  std::vector<std::vector<idx_t>>& ids) {
475
482
  ArrayInvertedLists* ail =
@@ -526,7 +533,11 @@ Index* read_index(IOReader* f, int io_flags) {
526
533
  Index* idx = nullptr;
527
534
  uint32_t h;
528
535
  READ1(h);
529
- if (h == fourcc("IxFI") || h == fourcc("IxF2") || h == fourcc("IxFl")) {
536
+ if (h == fourcc("null")) {
537
+ // denotes a missing index, useful for some cases
538
+ return nullptr;
539
+ } else if (
540
+ h == fourcc("IxFI") || h == fourcc("IxF2") || h == fourcc("IxFl")) {
530
541
  IndexFlat* idxf;
531
542
  if (h == fourcc("IxFI")) {
532
543
  idxf = new IndexFlatIP();
@@ -587,7 +598,7 @@ Index* read_index(IOReader* f, int io_flags) {
587
598
  READ1(idxp->encode_signs);
588
599
  READ1(idxp->polysemous_ht);
589
600
  }
590
- // Old versoins of PQ all had metric_type set to INNER_PRODUCT
601
+ // Old versions of PQ all had metric_type set to INNER_PRODUCT
591
602
  // when they were in fact using L2. Therefore, we force metric type
592
603
  // to L2 when the old format is detected
593
604
  if (h == fourcc("IxPQ") || h == fourcc("IxPo")) {
@@ -600,7 +611,7 @@ Index* read_index(IOReader* f, int io_flags) {
600
611
  if (h == fourcc("IxRQ")) {
601
612
  read_ResidualQuantizer_old(&idxr->rq, f);
602
613
  } else {
603
- read_ResidualQuantizer(&idxr->rq, f);
614
+ read_ResidualQuantizer(&idxr->rq, f, io_flags);
604
615
  }
605
616
  READ1(idxr->code_size);
606
617
  READVECTOR(idxr->codes);
@@ -615,7 +626,7 @@ Index* read_index(IOReader* f, int io_flags) {
615
626
  } else if (h == fourcc("IxPR")) {
616
627
  auto idxpr = new IndexProductResidualQuantizer();
617
628
  read_index_header(idxpr, f);
618
- read_ProductResidualQuantizer(&idxpr->prq, f);
629
+ read_ProductResidualQuantizer(&idxpr->prq, f, io_flags);
619
630
  READ1(idxpr->code_size);
620
631
  READVECTOR(idxpr->codes);
621
632
  idx = idxpr;
@@ -629,8 +640,13 @@ Index* read_index(IOReader* f, int io_flags) {
629
640
  } else if (h == fourcc("ImRQ")) {
630
641
  ResidualCoarseQuantizer* idxr = new ResidualCoarseQuantizer();
631
642
  read_index_header(idxr, f);
632
- read_ResidualQuantizer(&idxr->rq, f);
643
+ read_ResidualQuantizer(&idxr->rq, f, io_flags);
633
644
  READ1(idxr->beam_factor);
645
+ if (io_flags & IO_FLAG_SKIP_PRECOMPUTE_TABLE) {
646
+ // then we force the beam factor to -1
647
+ // which skips the table precomputation.
648
+ idxr->beam_factor = -1;
649
+ }
634
650
  idxr->set_beam_factor(idxr->beam_factor);
635
651
  idx = idxr;
636
652
  } else if (
@@ -655,13 +671,14 @@ Index* read_index(IOReader* f, int io_flags) {
655
671
  if (is_LSQ) {
656
672
  read_LocalSearchQuantizer((LocalSearchQuantizer*)idxaqfs->aq, f);
657
673
  } else if (is_RQ) {
658
- read_ResidualQuantizer((ResidualQuantizer*)idxaqfs->aq, f);
674
+ read_ResidualQuantizer(
675
+ (ResidualQuantizer*)idxaqfs->aq, f, io_flags);
659
676
  } else if (is_PLSQ) {
660
677
  read_ProductLocalSearchQuantizer(
661
678
  (ProductLocalSearchQuantizer*)idxaqfs->aq, f);
662
679
  } else {
663
680
  read_ProductResidualQuantizer(
664
- (ProductResidualQuantizer*)idxaqfs->aq, f);
681
+ (ProductResidualQuantizer*)idxaqfs->aq, f, io_flags);
665
682
  }
666
683
 
667
684
  READ1(idxaqfs->implem);
@@ -703,13 +720,13 @@ Index* read_index(IOReader* f, int io_flags) {
703
720
  if (is_LSQ) {
704
721
  read_LocalSearchQuantizer((LocalSearchQuantizer*)ivaqfs->aq, f);
705
722
  } else if (is_RQ) {
706
- read_ResidualQuantizer((ResidualQuantizer*)ivaqfs->aq, f);
723
+ read_ResidualQuantizer((ResidualQuantizer*)ivaqfs->aq, f, io_flags);
707
724
  } else if (is_PLSQ) {
708
725
  read_ProductLocalSearchQuantizer(
709
726
  (ProductLocalSearchQuantizer*)ivaqfs->aq, f);
710
727
  } else {
711
728
  read_ProductResidualQuantizer(
712
- (ProductResidualQuantizer*)ivaqfs->aq, f);
729
+ (ProductResidualQuantizer*)ivaqfs->aq, f, io_flags);
713
730
  }
714
731
 
715
732
  READ1(ivaqfs->by_residual);
@@ -831,13 +848,13 @@ Index* read_index(IOReader* f, int io_flags) {
831
848
  if (is_LSQ) {
832
849
  read_LocalSearchQuantizer((LocalSearchQuantizer*)iva->aq, f);
833
850
  } else if (is_RQ) {
834
- read_ResidualQuantizer((ResidualQuantizer*)iva->aq, f);
851
+ read_ResidualQuantizer((ResidualQuantizer*)iva->aq, f, io_flags);
835
852
  } else if (is_PLSQ) {
836
853
  read_ProductLocalSearchQuantizer(
837
854
  (ProductLocalSearchQuantizer*)iva->aq, f);
838
855
  } else {
839
856
  read_ProductResidualQuantizer(
840
- (ProductResidualQuantizer*)iva->aq, f);
857
+ (ProductResidualQuantizer*)iva->aq, f, io_flags);
841
858
  }
842
859
  READ1(iva->by_residual);
843
860
  READ1(iva->use_precomputed_table);
@@ -860,7 +877,22 @@ Index* read_index(IOReader* f, int io_flags) {
860
877
  h == fourcc("IvPQ") || h == fourcc("IvQR") || h == fourcc("IwPQ") ||
861
878
  h == fourcc("IwQR")) {
862
879
  idx = read_ivfpq(f, h, io_flags);
863
-
880
+ } else if (h == fourcc("IwIQ")) {
881
+ auto* indep = new IndexIVFIndependentQuantizer();
882
+ indep->own_fields = true;
883
+ read_index_header(indep, f);
884
+ indep->quantizer = read_index(f, io_flags);
885
+ bool has_vt;
886
+ READ1(has_vt);
887
+ if (has_vt) {
888
+ indep->vt = read_VectorTransform(f);
889
+ }
890
+ indep->index_ivf = dynamic_cast<IndexIVF*>(read_index(f, io_flags));
891
+ FAISS_THROW_IF_NOT(indep->index_ivf);
892
+ if (auto index_ivfpq = dynamic_cast<IndexIVFPQ*>(indep->index_ivf)) {
893
+ READ1(index_ivfpq->use_precomputed_table);
894
+ }
895
+ idx = indep;
864
896
  } else if (h == fourcc("IxPT")) {
865
897
  IndexPreTransform* ixpt = new IndexPreTransform();
866
898
  ixpt->own_fields = true;
@@ -922,7 +954,7 @@ Index* read_index(IOReader* f, int io_flags) {
922
954
  idx = idxp;
923
955
  } else if (
924
956
  h == fourcc("IHNf") || h == fourcc("IHNp") || h == fourcc("IHNs") ||
925
- h == fourcc("IHN2")) {
957
+ h == fourcc("IHN2") || h == fourcc("IHNc")) {
926
958
  IndexHNSW* idxhnsw = nullptr;
927
959
  if (h == fourcc("IHNf"))
928
960
  idxhnsw = new IndexHNSWFlat();
@@ -932,11 +964,19 @@ Index* read_index(IOReader* f, int io_flags) {
932
964
  idxhnsw = new IndexHNSWSQ();
933
965
  if (h == fourcc("IHN2"))
934
966
  idxhnsw = new IndexHNSW2Level();
967
+ if (h == fourcc("IHNc"))
968
+ idxhnsw = new IndexHNSWCagra();
935
969
  read_index_header(idxhnsw, f);
970
+ if (h == fourcc("IHNc")) {
971
+ READ1(idxhnsw->keep_max_size_level0);
972
+ auto idx_hnsw_cagra = dynamic_cast<IndexHNSWCagra*>(idxhnsw);
973
+ READ1(idx_hnsw_cagra->base_level_only);
974
+ READ1(idx_hnsw_cagra->num_base_level_search_entrypoints);
975
+ }
936
976
  read_HNSW(&idxhnsw->hnsw, f);
937
977
  idxhnsw->storage = read_index(f, io_flags);
938
- idxhnsw->own_fields = true;
939
- if (h == fourcc("IHNp")) {
978
+ idxhnsw->own_fields = idxhnsw->storage != nullptr;
979
+ if (h == fourcc("IHNp") && !(io_flags & IO_FLAG_PQ_SKIP_SDC_TABLE)) {
940
980
  dynamic_cast<IndexPQ*>(idxhnsw->storage)->pq.compute_sdc_table();
941
981
  }
942
982
  idx = idxhnsw;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ // Utils for index_read
9
+
10
+ #ifndef FAISS_INDEX_READ_UTILS_H
11
+ #define FAISS_INDEX_READ_UTILS_H
12
+
13
+ #include <faiss/IndexIVF.h>
14
+ #include <faiss/impl/io.h>
15
+
16
+ #pragma once
17
+
18
+ namespace faiss {
19
+ struct ProductQuantizer;
20
+ struct ScalarQuantizer;
21
+
22
+ void read_index_header(Index* idx, IOReader* f);
23
+ void read_direct_map(DirectMap* dm, IOReader* f);
24
+ void read_ivf_header(
25
+ IndexIVF* ivf,
26
+ IOReader* f,
27
+ std::vector<std::vector<idx_t>>* ids = nullptr);
28
+ void read_InvertedLists(IndexIVF* ivf, IOReader* f, int io_flags);
29
+ ArrayInvertedLists* set_array_invlist(
30
+ IndexIVF* ivf,
31
+ std::vector<std::vector<idx_t>>& ids);
32
+ void read_ProductQuantizer(ProductQuantizer* pq, IOReader* f);
33
+ void read_ScalarQuantizer(ScalarQuantizer* ivsc, IOReader* f);
34
+
35
+ } // namespace faiss
36
+
37
+ #endif
@@ -5,8 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- // -*- c++ -*-
9
-
10
8
  #include <faiss/index_io.h>
11
9
 
12
10
  #include <faiss/impl/io.h>
@@ -34,6 +32,7 @@
34
32
  #include <faiss/IndexIVFAdditiveQuantizer.h>
35
33
  #include <faiss/IndexIVFAdditiveQuantizerFastScan.h>
36
34
  #include <faiss/IndexIVFFlat.h>
35
+ #include <faiss/IndexIVFIndependentQuantizer.h>
37
36
  #include <faiss/IndexIVFPQ.h>
38
37
  #include <faiss/IndexIVFPQFastScan.h>
39
38
  #include <faiss/IndexIVFPQR.h>
@@ -313,7 +312,11 @@ static void write_HNSW(const HNSW* hnsw, IOWriter* f) {
313
312
  WRITE1(hnsw->max_level);
314
313
  WRITE1(hnsw->efConstruction);
315
314
  WRITE1(hnsw->efSearch);
316
- WRITE1(hnsw->upper_beam);
315
+
316
+ // // deprecated field
317
+ // WRITE1(hnsw->upper_beam);
318
+ constexpr int tmp_upper_beam = 1;
319
+ WRITE1(tmp_upper_beam);
317
320
  }
318
321
 
319
322
  static void write_NSG(const NSG* nsg, IOWriter* f) {
@@ -337,13 +340,11 @@ static void write_NSG(const NSG* nsg, IOWriter* f) {
337
340
  FAISS_THROW_IF_NOT(K == nsg->R);
338
341
  FAISS_THROW_IF_NOT(true == graph->own_fields);
339
342
 
340
- int size = 0;
341
343
  for (int i = 0; i < N; i++) {
342
344
  for (int j = 0; j < K; j++) {
343
345
  int id = graph->at(i, j);
344
346
  if (id != EMPTY_ID) {
345
347
  WRITE1(id);
346
- size += 1;
347
348
  } else {
348
349
  break;
349
350
  }
@@ -385,12 +386,18 @@ static void write_ivf_header(const IndexIVF* ivf, IOWriter* f) {
385
386
  write_index_header(ivf, f);
386
387
  WRITE1(ivf->nlist);
387
388
  WRITE1(ivf->nprobe);
389
+ // subclasses write by_residual (some of them support only one setting of
390
+ // by_residual).
388
391
  write_index(ivf->quantizer, f);
389
392
  write_direct_map(&ivf->direct_map, f);
390
393
  }
391
394
 
392
- void write_index(const Index* idx, IOWriter* f) {
393
- if (const IndexFlat* idxf = dynamic_cast<const IndexFlat*>(idx)) {
395
+ void write_index(const Index* idx, IOWriter* f, int io_flags) {
396
+ if (idx == nullptr) {
397
+ // eg. for a storage component of HNSW that is set to nullptr
398
+ uint32_t h = fourcc("null");
399
+ WRITE1(h);
400
+ } else if (const IndexFlat* idxf = dynamic_cast<const IndexFlat*>(idx)) {
394
401
  uint32_t h =
395
402
  fourcc(idxf->metric_type == METRIC_INNER_PRODUCT ? "IxFI"
396
403
  : idxf->metric_type == METRIC_L2 ? "IxF2"
@@ -430,13 +437,14 @@ void write_index(const Index* idx, IOWriter* f) {
430
437
  WRITE1(idxr->code_size);
431
438
  WRITEVECTOR(idxr->codes);
432
439
  } else if (
433
- auto* idxr = dynamic_cast<const IndexLocalSearchQuantizer*>(idx)) {
440
+ auto* idxr_2 =
441
+ dynamic_cast<const IndexLocalSearchQuantizer*>(idx)) {
434
442
  uint32_t h = fourcc("IxLS");
435
443
  WRITE1(h);
436
444
  write_index_header(idx, f);
437
- write_LocalSearchQuantizer(&idxr->lsq, f);
438
- WRITE1(idxr->code_size);
439
- WRITEVECTOR(idxr->codes);
445
+ write_LocalSearchQuantizer(&idxr_2->lsq, f);
446
+ WRITE1(idxr_2->code_size);
447
+ WRITEVECTOR(idxr_2->codes);
440
448
  } else if (
441
449
  const IndexProductResidualQuantizer* idxpr =
442
450
  dynamic_cast<const IndexProductResidualQuantizer*>(idx)) {
@@ -569,26 +577,26 @@ void write_index(const Index* idx, IOWriter* f) {
569
577
 
570
578
  write_InvertedLists(ivaqfs->invlists, f);
571
579
  } else if (
572
- const ResidualCoarseQuantizer* idxr =
580
+ const ResidualCoarseQuantizer* idxr_2 =
573
581
  dynamic_cast<const ResidualCoarseQuantizer*>(idx)) {
574
582
  uint32_t h = fourcc("ImRQ");
575
583
  WRITE1(h);
576
584
  write_index_header(idx, f);
577
- write_ResidualQuantizer(&idxr->rq, f);
578
- WRITE1(idxr->beam_factor);
585
+ write_ResidualQuantizer(&idxr_2->rq, f);
586
+ WRITE1(idxr_2->beam_factor);
579
587
  } else if (
580
- const Index2Layer* idxp = dynamic_cast<const Index2Layer*>(idx)) {
588
+ const Index2Layer* idxp_2 = dynamic_cast<const Index2Layer*>(idx)) {
581
589
  uint32_t h = fourcc("Ix2L");
582
590
  WRITE1(h);
583
591
  write_index_header(idx, f);
584
- write_index(idxp->q1.quantizer, f);
585
- WRITE1(idxp->q1.nlist);
586
- WRITE1(idxp->q1.quantizer_trains_alone);
587
- write_ProductQuantizer(&idxp->pq, f);
588
- WRITE1(idxp->code_size_1);
589
- WRITE1(idxp->code_size_2);
590
- WRITE1(idxp->code_size);
591
- WRITEVECTOR(idxp->codes);
592
+ write_index(idxp_2->q1.quantizer, f);
593
+ WRITE1(idxp_2->q1.nlist);
594
+ WRITE1(idxp_2->q1.quantizer_trains_alone);
595
+ write_ProductQuantizer(&idxp_2->pq, f);
596
+ WRITE1(idxp_2->code_size_1);
597
+ WRITE1(idxp_2->code_size_2);
598
+ WRITE1(idxp_2->code_size);
599
+ WRITEVECTOR(idxp_2->codes);
592
600
  } else if (
593
601
  const IndexScalarQuantizer* idxs =
594
602
  dynamic_cast<const IndexScalarQuantizer*>(idx)) {
@@ -598,15 +606,16 @@ void write_index(const Index* idx, IOWriter* f) {
598
606
  write_ScalarQuantizer(&idxs->sq, f);
599
607
  WRITEVECTOR(idxs->codes);
600
608
  } else if (
601
- const IndexLattice* idxl = dynamic_cast<const IndexLattice*>(idx)) {
609
+ const IndexLattice* idxl_2 =
610
+ dynamic_cast<const IndexLattice*>(idx)) {
602
611
  uint32_t h = fourcc("IxLa");
603
612
  WRITE1(h);
604
- WRITE1(idxl->d);
605
- WRITE1(idxl->nsq);
606
- WRITE1(idxl->scale_nbit);
607
- WRITE1(idxl->zn_sphere_codec.r2);
613
+ WRITE1(idxl_2->d);
614
+ WRITE1(idxl_2->nsq);
615
+ WRITE1(idxl_2->scale_nbit);
616
+ WRITE1(idxl_2->zn_sphere_codec.r2);
608
617
  write_index_header(idx, f);
609
- WRITEVECTOR(idxl->trained);
618
+ WRITEVECTOR(idxl_2->trained);
610
619
  } else if (
611
620
  const IndexIVFFlatDedup* ivfl =
612
621
  dynamic_cast<const IndexIVFFlatDedup*>(idx)) {
@@ -625,11 +634,12 @@ void write_index(const Index* idx, IOWriter* f) {
625
634
  }
626
635
  write_InvertedLists(ivfl->invlists, f);
627
636
  } else if (
628
- const IndexIVFFlat* ivfl = dynamic_cast<const IndexIVFFlat*>(idx)) {
637
+ const IndexIVFFlat* ivfl_2 =
638
+ dynamic_cast<const IndexIVFFlat*>(idx)) {
629
639
  uint32_t h = fourcc("IwFl");
630
640
  WRITE1(h);
631
- write_ivf_header(ivfl, f);
632
- write_InvertedLists(ivfl->invlists, f);
641
+ write_ivf_header(ivfl_2, f);
642
+ write_InvertedLists(ivfl_2->invlists, f);
633
643
  } else if (
634
644
  const IndexIVFScalarQuantizer* ivsc =
635
645
  dynamic_cast<const IndexIVFScalarQuantizer*>(idx)) {
@@ -700,7 +710,22 @@ void write_index(const Index* idx, IOWriter* f) {
700
710
  WRITEVECTOR(ivfpqr->refine_codes);
701
711
  WRITE1(ivfpqr->k_factor);
702
712
  }
703
-
713
+ } else if (
714
+ auto* indep =
715
+ dynamic_cast<const IndexIVFIndependentQuantizer*>(idx)) {
716
+ uint32_t h = fourcc("IwIQ");
717
+ WRITE1(h);
718
+ write_index_header(indep, f);
719
+ write_index(indep->quantizer, f);
720
+ bool has_vt = indep->vt != nullptr;
721
+ WRITE1(has_vt);
722
+ if (has_vt) {
723
+ write_VectorTransform(indep->vt, f);
724
+ }
725
+ write_index(indep->index_ivf, f);
726
+ if (auto index_ivfpq = dynamic_cast<IndexIVFPQ*>(indep->index_ivf)) {
727
+ WRITE1(index_ivfpq->use_precomputed_table);
728
+ }
704
729
  } else if (
705
730
  const IndexPreTransform* ixpt =
706
731
  dynamic_cast<const IndexPreTransform*>(idx)) {
@@ -741,12 +766,24 @@ void write_index(const Index* idx, IOWriter* f) {
741
766
  : dynamic_cast<const IndexHNSWPQ*>(idx) ? fourcc("IHNp")
742
767
  : dynamic_cast<const IndexHNSWSQ*>(idx) ? fourcc("IHNs")
743
768
  : dynamic_cast<const IndexHNSW2Level*>(idx) ? fourcc("IHN2")
769
+ : dynamic_cast<const IndexHNSWCagra*>(idx) ? fourcc("IHNc")
744
770
  : 0;
745
771
  FAISS_THROW_IF_NOT(h != 0);
746
772
  WRITE1(h);
747
773
  write_index_header(idxhnsw, f);
774
+ if (h == fourcc("IHNc")) {
775
+ WRITE1(idxhnsw->keep_max_size_level0);
776
+ auto idx_hnsw_cagra = dynamic_cast<const IndexHNSWCagra*>(idxhnsw);
777
+ WRITE1(idx_hnsw_cagra->base_level_only);
778
+ WRITE1(idx_hnsw_cagra->num_base_level_search_entrypoints);
779
+ }
748
780
  write_HNSW(&idxhnsw->hnsw, f);
749
- write_index(idxhnsw->storage, f);
781
+ if (io_flags & IO_FLAG_SKIP_STORAGE) {
782
+ uint32_t n4 = fourcc("null");
783
+ WRITE1(n4);
784
+ } else {
785
+ write_index(idxhnsw->storage, f);
786
+ }
750
787
  } else if (const IndexNSG* idxnsg = dynamic_cast<const IndexNSG*>(idx)) {
751
788
  uint32_t h = dynamic_cast<const IndexNSGFlat*>(idx) ? fourcc("INSf")
752
789
  : dynamic_cast<const IndexNSGPQ*>(idx) ? fourcc("INSp")
@@ -788,19 +825,19 @@ void write_index(const Index* idx, IOWriter* f) {
788
825
  WRITE1(idxpqfs->M2);
789
826
  WRITEVECTOR(idxpqfs->codes);
790
827
  } else if (
791
- const IndexIVFPQFastScan* ivpq =
828
+ const IndexIVFPQFastScan* ivpq_2 =
792
829
  dynamic_cast<const IndexIVFPQFastScan*>(idx)) {
793
830
  uint32_t h = fourcc("IwPf");
794
831
  WRITE1(h);
795
- write_ivf_header(ivpq, f);
796
- WRITE1(ivpq->by_residual);
797
- WRITE1(ivpq->code_size);
798
- WRITE1(ivpq->bbs);
799
- WRITE1(ivpq->M2);
800
- WRITE1(ivpq->implem);
801
- WRITE1(ivpq->qbs2);
802
- write_ProductQuantizer(&ivpq->pq, f);
803
- write_InvertedLists(ivpq->invlists, f);
832
+ write_ivf_header(ivpq_2, f);
833
+ WRITE1(ivpq_2->by_residual);
834
+ WRITE1(ivpq_2->code_size);
835
+ WRITE1(ivpq_2->bbs);
836
+ WRITE1(ivpq_2->M2);
837
+ WRITE1(ivpq_2->implem);
838
+ WRITE1(ivpq_2->qbs2);
839
+ write_ProductQuantizer(&ivpq_2->pq, f);
840
+ write_InvertedLists(ivpq_2->invlists, f);
804
841
  } else if (
805
842
  const IndexRowwiseMinMax* imm =
806
843
  dynamic_cast<const IndexRowwiseMinMax*>(idx)) {
@@ -810,26 +847,26 @@ void write_index(const Index* idx, IOWriter* f) {
810
847
  write_index_header(imm, f);
811
848
  write_index(imm->index, f);
812
849
  } else if (
813
- const IndexRowwiseMinMaxFP16* imm =
850
+ const IndexRowwiseMinMaxFP16* imm_2 =
814
851
  dynamic_cast<const IndexRowwiseMinMaxFP16*>(idx)) {
815
852
  // IndexRowwiseMinmaxHalf
816
853
  uint32_t h = fourcc("IRMh");
817
854
  WRITE1(h);
818
- write_index_header(imm, f);
819
- write_index(imm->index, f);
855
+ write_index_header(imm_2, f);
856
+ write_index(imm_2->index, f);
820
857
  } else {
821
858
  FAISS_THROW_MSG("don't know how to serialize this type of index");
822
859
  }
823
860
  }
824
861
 
825
- void write_index(const Index* idx, FILE* f) {
862
+ void write_index(const Index* idx, FILE* f, int io_flags) {
826
863
  FileIOWriter writer(f);
827
- write_index(idx, &writer);
864
+ write_index(idx, &writer, io_flags);
828
865
  }
829
866
 
830
- void write_index(const Index* idx, const char* fname) {
867
+ void write_index(const Index* idx, const char* fname, int io_flags) {
831
868
  FileIOWriter writer(fname);
832
- write_index(idx, &writer);
869
+ write_index(idx, &writer, io_flags);
833
870
  }
834
871
 
835
872
  void write_VectorTransform(const VectorTransform* vt, const char* fname) {