faiss 0.3.4 → 0.4.0

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/lib/faiss/version.rb +1 -1
  4. data/vendor/faiss/faiss/AutoTune.cpp +11 -8
  5. data/vendor/faiss/faiss/Clustering.cpp +0 -16
  6. data/vendor/faiss/faiss/IVFlib.cpp +213 -0
  7. data/vendor/faiss/faiss/IVFlib.h +42 -0
  8. data/vendor/faiss/faiss/Index.h +1 -1
  9. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +9 -7
  10. data/vendor/faiss/faiss/IndexBinaryFlat.h +2 -1
  11. data/vendor/faiss/faiss/IndexFlatCodes.cpp +1 -1
  12. data/vendor/faiss/faiss/IndexFlatCodes.h +4 -2
  13. data/vendor/faiss/faiss/IndexHNSW.cpp +13 -20
  14. data/vendor/faiss/faiss/IndexHNSW.h +1 -1
  15. data/vendor/faiss/faiss/IndexIVF.cpp +20 -3
  16. data/vendor/faiss/faiss/IndexIVF.h +5 -2
  17. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +2 -1
  18. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +2 -1
  19. data/vendor/faiss/faiss/IndexIVFFlat.cpp +2 -1
  20. data/vendor/faiss/faiss/IndexIVFFlat.h +2 -1
  21. data/vendor/faiss/faiss/IndexIVFPQ.cpp +2 -1
  22. data/vendor/faiss/faiss/IndexIVFPQ.h +2 -1
  23. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +277 -0
  24. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +70 -0
  25. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +2 -1
  26. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +2 -1
  27. data/vendor/faiss/faiss/IndexRaBitQ.cpp +148 -0
  28. data/vendor/faiss/faiss/IndexRaBitQ.h +65 -0
  29. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +2 -1
  30. data/vendor/faiss/faiss/IndexScalarQuantizer.h +2 -1
  31. data/vendor/faiss/faiss/clone_index.cpp +38 -3
  32. data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +19 -0
  33. data/vendor/faiss/faiss/cppcontrib/factory_tools.h +4 -11
  34. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +2 -1
  35. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +13 -3
  36. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +1 -1
  37. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +1 -1
  38. data/vendor/faiss/faiss/gpu/test/TestGpuIcmEncoder.cpp +112 -0
  39. data/vendor/faiss/faiss/impl/HNSW.cpp +35 -13
  40. data/vendor/faiss/faiss/impl/HNSW.h +5 -4
  41. data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -1
  42. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +519 -0
  43. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +78 -0
  44. data/vendor/faiss/faiss/impl/ResultHandler.h +2 -2
  45. data/vendor/faiss/faiss/impl/code_distance/code_distance-sve.h +3 -4
  46. data/vendor/faiss/faiss/impl/index_read.cpp +220 -25
  47. data/vendor/faiss/faiss/impl/index_write.cpp +29 -0
  48. data/vendor/faiss/faiss/impl/io.h +2 -2
  49. data/vendor/faiss/faiss/impl/io_macros.h +2 -0
  50. data/vendor/faiss/faiss/impl/mapped_io.cpp +313 -0
  51. data/vendor/faiss/faiss/impl/mapped_io.h +51 -0
  52. data/vendor/faiss/faiss/impl/maybe_owned_vector.h +316 -0
  53. data/vendor/faiss/faiss/impl/platform_macros.h +7 -3
  54. data/vendor/faiss/faiss/impl/simd_result_handlers.h +1 -1
  55. data/vendor/faiss/faiss/impl/zerocopy_io.cpp +67 -0
  56. data/vendor/faiss/faiss/impl/zerocopy_io.h +32 -0
  57. data/vendor/faiss/faiss/index_factory.cpp +16 -5
  58. data/vendor/faiss/faiss/index_io.h +4 -0
  59. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +3 -3
  60. data/vendor/faiss/faiss/invlists/InvertedLists.h +5 -3
  61. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +3 -3
  62. data/vendor/faiss/faiss/python/python_callbacks.cpp +24 -0
  63. data/vendor/faiss/faiss/python/python_callbacks.h +22 -0
  64. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +30 -12
  65. data/vendor/faiss/faiss/utils/hamming.cpp +45 -21
  66. data/vendor/faiss/faiss/utils/hamming.h +7 -3
  67. data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +1 -1
  68. data/vendor/faiss/faiss/utils/utils.cpp +4 -4
  69. data/vendor/faiss/faiss/utils/utils.h +3 -3
  70. metadata +16 -4
@@ -12,6 +12,7 @@
12
12
 
13
13
  #include <cstdio>
14
14
  #include <cstdlib>
15
+ #include <optional>
15
16
 
16
17
  #include <faiss/impl/FaissAssert.h>
17
18
  #include <faiss/impl/io.h>
@@ -33,6 +34,7 @@
33
34
  #include <faiss/IndexIVFPQ.h>
34
35
  #include <faiss/IndexIVFPQFastScan.h>
35
36
  #include <faiss/IndexIVFPQR.h>
37
+ #include <faiss/IndexIVFRaBitQ.h>
36
38
  #include <faiss/IndexIVFSpectralHash.h>
37
39
  #include <faiss/IndexLSH.h>
38
40
  #include <faiss/IndexLattice.h>
@@ -41,6 +43,7 @@
41
43
  #include <faiss/IndexPQ.h>
42
44
  #include <faiss/IndexPQFastScan.h>
43
45
  #include <faiss/IndexPreTransform.h>
46
+ #include <faiss/IndexRaBitQ.h>
44
47
  #include <faiss/IndexRefine.h>
45
48
  #include <faiss/IndexRowwiseMinMax.h>
46
49
  #include <faiss/IndexScalarQuantizer.h>
@@ -53,8 +56,141 @@
53
56
  #include <faiss/IndexBinaryHash.h>
54
57
  #include <faiss/IndexBinaryIVF.h>
55
58
 
59
+ // mmap-ing and viewing facilities
60
+ #include <faiss/impl/maybe_owned_vector.h>
61
+
62
+ #include <faiss/impl/mapped_io.h>
63
+ #include <faiss/impl/zerocopy_io.h>
64
+
56
65
  namespace faiss {
57
66
 
67
+ /*************************************************************
68
+ * Mmap-ing and viewing facilities
69
+ **************************************************************/
70
+
71
+ // This is a baseline functionality for reading mmapped and zerocopied vector.
72
+ // * if `beforeknown_size` is defined, then a size of the vector won't be read.
73
+ // * if `size_multiplier` is defined, then a size will be multiplied by it.
74
+ // * returns true is the case was handled; ownerwise, false
75
+ template <typename VectorT>
76
+ bool read_vector_base(
77
+ VectorT& target,
78
+ IOReader* f,
79
+ const std::optional<size_t> beforeknown_size,
80
+ const std::optional<size_t> size_multiplier) {
81
+ // check if the use case is right
82
+ if constexpr (is_maybe_owned_vector_v<VectorT>) {
83
+ // is it a mmap-enabled reader?
84
+ MappedFileIOReader* mf = dynamic_cast<MappedFileIOReader*>(f);
85
+ if (mf != nullptr) {
86
+ // read the size or use a known one
87
+ size_t size = 0;
88
+ if (beforeknown_size.has_value()) {
89
+ size = beforeknown_size.value();
90
+ } else {
91
+ READANDCHECK(&size, 1);
92
+ }
93
+
94
+ // perform the size multiplication
95
+ size *= size_multiplier.value_or(1);
96
+
97
+ // ok, mmap and check
98
+ char* address = nullptr;
99
+ const size_t nread = mf->mmap(
100
+ (void**)&address,
101
+ sizeof(typename VectorT::value_type),
102
+ size);
103
+
104
+ FAISS_THROW_IF_NOT_FMT(
105
+ nread == (size),
106
+ "read error in %s: %zd != %zd (%s)",
107
+ f->name.c_str(),
108
+ nread,
109
+ size,
110
+ strerror(errno));
111
+
112
+ VectorT mmapped_view =
113
+ VectorT::create_view(address, nread, mf->mmap_owner);
114
+ target = std::move(mmapped_view);
115
+
116
+ return true;
117
+ }
118
+
119
+ // is it a zero-copy reader?
120
+ ZeroCopyIOReader* zr = dynamic_cast<ZeroCopyIOReader*>(f);
121
+ if (zr != nullptr) {
122
+ // read the size or use a known one
123
+ size_t size = 0;
124
+ if (beforeknown_size.has_value()) {
125
+ size = beforeknown_size.value();
126
+ } else {
127
+ READANDCHECK(&size, 1);
128
+ }
129
+
130
+ // perform the size multiplication
131
+ size *= size_multiplier.value_or(1);
132
+
133
+ // create a view
134
+ char* address = nullptr;
135
+ size_t nread = zr->get_data_view(
136
+ (void**)&address,
137
+ sizeof(typename VectorT::value_type),
138
+ size);
139
+
140
+ FAISS_THROW_IF_NOT_FMT(
141
+ nread == (size),
142
+ "read error in %s: %zd != %zd (%s)",
143
+ f->name.c_str(),
144
+ nread,
145
+ size_t(size),
146
+ strerror(errno));
147
+
148
+ VectorT view = VectorT::create_view(address, nread, nullptr);
149
+ target = std::move(view);
150
+
151
+ return true;
152
+ }
153
+ }
154
+
155
+ return false;
156
+ }
157
+
158
+ // a replacement for READANDCHECK for reading data into std::vector
159
+ template <typename VectorT>
160
+ void read_vector_with_known_size(VectorT& target, IOReader* f, size_t size) {
161
+ // size is known beforehand, no size multiplication
162
+ if (read_vector_base<VectorT>(target, f, size, std::nullopt)) {
163
+ return;
164
+ }
165
+
166
+ // the default case
167
+ READANDCHECK(target.data(), size);
168
+ }
169
+
170
+ // a replacement for READVECTOR
171
+ template <typename VectorT>
172
+ void read_vector(VectorT& target, IOReader* f) {
173
+ // size is not known beforehand, no size multiplication
174
+ if (read_vector_base<VectorT>(target, f, std::nullopt, std::nullopt)) {
175
+ return;
176
+ }
177
+
178
+ // the default case
179
+ READVECTOR(target);
180
+ }
181
+
182
+ // a replacement for READXBVECTOR
183
+ template <typename VectorT>
184
+ void read_xb_vector(VectorT& target, IOReader* f) {
185
+ // size is not known beforehand, nultiply the size 4x
186
+ if (read_vector_base<VectorT>(target, f, std::nullopt, 4)) {
187
+ return;
188
+ }
189
+
190
+ // the default case
191
+ READXBVECTOR(target);
192
+ }
193
+
58
194
  /*************************************************************
59
195
  * Read
60
196
  **************************************************************/
@@ -205,8 +341,9 @@ InvertedLists* read_InvertedLists(IOReader* f, int io_flags) {
205
341
  for (size_t i = 0; i < ails->nlist; i++) {
206
342
  size_t n = ails->ids[i].size();
207
343
  if (n > 0) {
208
- READANDCHECK(ails->codes[i].data(), n * ails->code_size);
209
- READANDCHECK(ails->ids[i].data(), n);
344
+ read_vector_with_known_size(
345
+ ails->codes[i], f, n * ails->code_size);
346
+ read_vector_with_known_size(ails->ids[i], f, n);
210
347
  }
211
348
  }
212
349
  return ails;
@@ -275,7 +412,7 @@ static void read_AdditiveQuantizer(AdditiveQuantizer* aq, IOReader* f) {
275
412
  aq->search_type == AdditiveQuantizer::ST_norm_cqint4 ||
276
413
  aq->search_type == AdditiveQuantizer::ST_norm_lsq2x4 ||
277
414
  aq->search_type == AdditiveQuantizer::ST_norm_rq2x4) {
278
- READXBVECTOR(aq->qnorm.codes);
415
+ read_xb_vector(aq->qnorm.codes, f);
279
416
  aq->qnorm.ntotal = aq->qnorm.codes.size() / 4;
280
417
  aq->qnorm.update_permutation();
281
418
  }
@@ -365,7 +502,7 @@ static void read_HNSW(HNSW* hnsw, IOReader* f) {
365
502
  READVECTOR(hnsw->cum_nneighbor_per_level);
366
503
  READVECTOR(hnsw->levels);
367
504
  READVECTOR(hnsw->offsets);
368
- READVECTOR(hnsw->neighbors);
505
+ read_vector(hnsw->neighbors, f);
369
506
 
370
507
  READ1(hnsw->entry_point);
371
508
  READ1(hnsw->max_level);
@@ -439,6 +576,13 @@ ProductQuantizer* read_ProductQuantizer(IOReader* reader) {
439
576
  return pq;
440
577
  }
441
578
 
579
+ static void read_RaBitQuantizer(RaBitQuantizer* rabitq, IOReader* f) {
580
+ // don't care about rabitq->centroid
581
+ READ1(rabitq->d);
582
+ READ1(rabitq->code_size);
583
+ READ1(rabitq->metric_type);
584
+ }
585
+
442
586
  void read_direct_map(DirectMap* dm, IOReader* f) {
443
587
  char maintain_direct_map;
444
588
  READ1(maintain_direct_map);
@@ -478,7 +622,12 @@ ArrayInvertedLists* set_array_invlist(
478
622
  std::vector<std::vector<idx_t>>& ids) {
479
623
  ArrayInvertedLists* ail =
480
624
  new ArrayInvertedLists(ivf->nlist, ivf->code_size);
481
- std::swap(ail->ids, ids);
625
+
626
+ ail->ids.resize(ids.size());
627
+ for (size_t i = 0; i < ids.size(); i++) {
628
+ ail->ids[i] = MaybeOwnedVector<idx_t>(std::move(ids[i]));
629
+ }
630
+
482
631
  ivf->invlists = ail;
483
632
  ivf->own_invlists = true;
484
633
  return ail;
@@ -545,7 +694,7 @@ Index* read_index(IOReader* f, int io_flags) {
545
694
  }
546
695
  read_index_header(idxf, f);
547
696
  idxf->code_size = idxf->d * sizeof(float);
548
- READXBVECTOR(idxf->codes);
697
+ read_xb_vector(idxf->codes, f);
549
698
  FAISS_THROW_IF_NOT(
550
699
  idxf->codes.size() == idxf->ntotal * idxf->code_size);
551
700
  // leak!
@@ -576,7 +725,7 @@ Index* read_index(IOReader* f, int io_flags) {
576
725
  idxl->rrot = *rrot;
577
726
  delete rrot;
578
727
  }
579
- READVECTOR(idxl->codes);
728
+ read_vector(idxl->codes, f);
580
729
  FAISS_THROW_IF_NOT(
581
730
  idxl->rrot.d_in == idxl->d && idxl->rrot.d_out == idxl->nbits);
582
731
  FAISS_THROW_IF_NOT(
@@ -589,7 +738,7 @@ Index* read_index(IOReader* f, int io_flags) {
589
738
  read_index_header(idxp, f);
590
739
  read_ProductQuantizer(&idxp->pq, f);
591
740
  idxp->code_size = idxp->pq.code_size;
592
- READVECTOR(idxp->codes);
741
+ read_vector(idxp->codes, f);
593
742
  if (h == fourcc("IxPo") || h == fourcc("IxPq")) {
594
743
  READ1(idxp->search_type);
595
744
  READ1(idxp->encode_signs);
@@ -611,28 +760,28 @@ Index* read_index(IOReader* f, int io_flags) {
611
760
  read_ResidualQuantizer(&idxr->rq, f, io_flags);
612
761
  }
613
762
  READ1(idxr->code_size);
614
- READVECTOR(idxr->codes);
763
+ read_vector(idxr->codes, f);
615
764
  idx = idxr;
616
765
  } else if (h == fourcc("IxLS")) {
617
766
  auto idxr = new IndexLocalSearchQuantizer();
618
767
  read_index_header(idxr, f);
619
768
  read_LocalSearchQuantizer(&idxr->lsq, f);
620
769
  READ1(idxr->code_size);
621
- READVECTOR(idxr->codes);
770
+ read_vector(idxr->codes, f);
622
771
  idx = idxr;
623
772
  } else if (h == fourcc("IxPR")) {
624
773
  auto idxpr = new IndexProductResidualQuantizer();
625
774
  read_index_header(idxpr, f);
626
775
  read_ProductResidualQuantizer(&idxpr->prq, f, io_flags);
627
776
  READ1(idxpr->code_size);
628
- READVECTOR(idxpr->codes);
777
+ read_vector(idxpr->codes, f);
629
778
  idx = idxpr;
630
779
  } else if (h == fourcc("IxPL")) {
631
780
  auto idxpl = new IndexProductLocalSearchQuantizer();
632
781
  read_index_header(idxpl, f);
633
782
  read_ProductLocalSearchQuantizer(&idxpl->plsq, f);
634
783
  READ1(idxpl->code_size);
635
- READVECTOR(idxpl->codes);
784
+ read_vector(idxpl->codes, f);
636
785
  idx = idxpl;
637
786
  } else if (h == fourcc("ImRQ")) {
638
787
  ResidualCoarseQuantizer* idxr = new ResidualCoarseQuantizer();
@@ -789,7 +938,7 @@ Index* read_index(IOReader* f, int io_flags) {
789
938
  IndexScalarQuantizer* idxs = new IndexScalarQuantizer();
790
939
  read_index_header(idxs, f);
791
940
  read_ScalarQuantizer(&idxs->sq, f);
792
- READVECTOR(idxs->codes);
941
+ read_vector(idxs->codes, f);
793
942
  idxs->code_size = idxs->sq.code_size;
794
943
  idx = idxs;
795
944
  } else if (h == fourcc("IxLa")) {
@@ -947,7 +1096,7 @@ Index* read_index(IOReader* f, int io_flags) {
947
1096
  READ1(idxp->code_size_1);
948
1097
  READ1(idxp->code_size_2);
949
1098
  READ1(idxp->code_size);
950
- READVECTOR(idxp->codes);
1099
+ read_vector(idxp->codes, f);
951
1100
  idx = idxp;
952
1101
  } else if (
953
1102
  h == fourcc("IHNf") || h == fourcc("IHNp") || h == fourcc("IHNs") ||
@@ -1060,6 +1209,24 @@ Index* read_index(IOReader* f, int io_flags) {
1060
1209
  imm->own_fields = true;
1061
1210
 
1062
1211
  idx = imm;
1212
+ } else if (h == fourcc("Ixrq")) {
1213
+ IndexRaBitQ* idxq = new IndexRaBitQ();
1214
+ read_index_header(idxq, f);
1215
+ read_RaBitQuantizer(&idxq->rabitq, f);
1216
+ READVECTOR(idxq->codes);
1217
+ READVECTOR(idxq->center);
1218
+ READ1(idxq->qb);
1219
+ idxq->code_size = idxq->rabitq.code_size;
1220
+ idx = idxq;
1221
+ } else if (h == fourcc("Iwrq")) {
1222
+ IndexIVFRaBitQ* ivrq = new IndexIVFRaBitQ();
1223
+ read_ivf_header(ivrq, f);
1224
+ read_RaBitQuantizer(&ivrq->rabitq, f);
1225
+ READ1(ivrq->code_size);
1226
+ READ1(ivrq->by_residual);
1227
+ READ1(ivrq->qb);
1228
+ read_InvertedLists(ivrq, f, io_flags);
1229
+ idx = ivrq;
1063
1230
  } else {
1064
1231
  FAISS_THROW_FMT(
1065
1232
  "Index type 0x%08x (\"%s\") not recognized",
@@ -1071,14 +1238,28 @@ Index* read_index(IOReader* f, int io_flags) {
1071
1238
  }
1072
1239
 
1073
1240
  Index* read_index(FILE* f, int io_flags) {
1074
- FileIOReader reader(f);
1075
- return read_index(&reader, io_flags);
1241
+ if ((io_flags & IO_FLAG_MMAP_IFC) == IO_FLAG_MMAP_IFC) {
1242
+ // enable mmap-supporting IOReader
1243
+ auto owner = std::make_shared<MmappedFileMappingOwner>(f);
1244
+ MappedFileIOReader reader(owner);
1245
+ return read_index(&reader, io_flags);
1246
+ } else {
1247
+ FileIOReader reader(f);
1248
+ return read_index(&reader, io_flags);
1249
+ }
1076
1250
  }
1077
1251
 
1078
1252
  Index* read_index(const char* fname, int io_flags) {
1079
- FileIOReader reader(fname);
1080
- Index* idx = read_index(&reader, io_flags);
1081
- return idx;
1253
+ if ((io_flags & IO_FLAG_MMAP_IFC) == IO_FLAG_MMAP_IFC) {
1254
+ // enable mmap-supporting IOReader
1255
+ auto owner = std::make_shared<MmappedFileMappingOwner>(fname);
1256
+ MappedFileIOReader reader(owner);
1257
+ return read_index(&reader, io_flags);
1258
+ } else {
1259
+ FileIOReader reader(fname);
1260
+ Index* idx = read_index(&reader, io_flags);
1261
+ return idx;
1262
+ }
1082
1263
  }
1083
1264
 
1084
1265
  VectorTransform* read_VectorTransform(const char* fname) {
@@ -1181,7 +1362,7 @@ IndexBinary* read_index_binary(IOReader* f, int io_flags) {
1181
1362
  if (h == fourcc("IBxF")) {
1182
1363
  IndexBinaryFlat* idxf = new IndexBinaryFlat();
1183
1364
  read_index_binary_header(idxf, f);
1184
- READVECTOR(idxf->xb);
1365
+ read_vector(idxf->xb, f);
1185
1366
  FAISS_THROW_IF_NOT(idxf->xb.size() == idxf->ntotal * idxf->code_size);
1186
1367
  // leak!
1187
1368
  idx = idxf;
@@ -1249,14 +1430,28 @@ IndexBinary* read_index_binary(IOReader* f, int io_flags) {
1249
1430
  }
1250
1431
 
1251
1432
  IndexBinary* read_index_binary(FILE* f, int io_flags) {
1252
- FileIOReader reader(f);
1253
- return read_index_binary(&reader, io_flags);
1433
+ if ((io_flags & IO_FLAG_MMAP_IFC) == IO_FLAG_MMAP_IFC) {
1434
+ // enable mmap-supporting IOReader
1435
+ auto owner = std::make_shared<MmappedFileMappingOwner>(f);
1436
+ MappedFileIOReader reader(owner);
1437
+ return read_index_binary(&reader, io_flags);
1438
+ } else {
1439
+ FileIOReader reader(f);
1440
+ return read_index_binary(&reader, io_flags);
1441
+ }
1254
1442
  }
1255
1443
 
1256
1444
  IndexBinary* read_index_binary(const char* fname, int io_flags) {
1257
- FileIOReader reader(fname);
1258
- IndexBinary* idx = read_index_binary(&reader, io_flags);
1259
- return idx;
1445
+ if ((io_flags & IO_FLAG_MMAP_IFC) == IO_FLAG_MMAP_IFC) {
1446
+ // enable mmap-supporting IOReader
1447
+ auto owner = std::make_shared<MmappedFileMappingOwner>(fname);
1448
+ MappedFileIOReader reader(owner);
1449
+ return read_index_binary(&reader, io_flags);
1450
+ } else {
1451
+ FileIOReader reader(fname);
1452
+ IndexBinary* idx = read_index_binary(&reader, io_flags);
1453
+ return idx;
1454
+ }
1260
1455
  }
1261
1456
 
1262
1457
  } // namespace faiss
@@ -32,6 +32,7 @@
32
32
  #include <faiss/IndexIVFPQ.h>
33
33
  #include <faiss/IndexIVFPQFastScan.h>
34
34
  #include <faiss/IndexIVFPQR.h>
35
+ #include <faiss/IndexIVFRaBitQ.h>
35
36
  #include <faiss/IndexIVFSpectralHash.h>
36
37
  #include <faiss/IndexLSH.h>
37
38
  #include <faiss/IndexLattice.h>
@@ -40,6 +41,7 @@
40
41
  #include <faiss/IndexPQ.h>
41
42
  #include <faiss/IndexPQFastScan.h>
42
43
  #include <faiss/IndexPreTransform.h>
44
+ #include <faiss/IndexRaBitQ.h>
43
45
  #include <faiss/IndexRefine.h>
44
46
  #include <faiss/IndexRowwiseMinMax.h>
45
47
  #include <faiss/IndexScalarQuantizer.h>
@@ -364,6 +366,13 @@ static void write_NNDescent(const NNDescent* nnd, IOWriter* f) {
364
366
  WRITEVECTOR(nnd->final_graph);
365
367
  }
366
368
 
369
+ static void write_RaBitQuantizer(const RaBitQuantizer* rabitq, IOWriter* f) {
370
+ // don't care about rabitq->centroid
371
+ WRITE1(rabitq->d);
372
+ WRITE1(rabitq->code_size);
373
+ WRITE1(rabitq->metric_type);
374
+ }
375
+
367
376
  static void write_direct_map(const DirectMap* dm, IOWriter* f) {
368
377
  char maintain_direct_map =
369
378
  (char)dm->type; // for backwards compatibility with bool
@@ -850,6 +859,26 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
850
859
  WRITE1(h);
851
860
  write_index_header(imm_2, f);
852
861
  write_index(imm_2->index, f);
862
+ } else if (
863
+ const IndexRaBitQ* idxq = dynamic_cast<const IndexRaBitQ*>(idx)) {
864
+ uint32_t h = fourcc("Ixrq");
865
+ WRITE1(h);
866
+ write_index_header(idx, f);
867
+ write_RaBitQuantizer(&idxq->rabitq, f);
868
+ WRITEVECTOR(idxq->codes);
869
+ WRITEVECTOR(idxq->center);
870
+ WRITE1(idxq->qb);
871
+ } else if (
872
+ const IndexIVFRaBitQ* ivrq =
873
+ dynamic_cast<const IndexIVFRaBitQ*>(idx)) {
874
+ uint32_t h = fourcc("Iwrq");
875
+ WRITE1(h);
876
+ write_ivf_header(ivrq, f);
877
+ write_RaBitQuantizer(&ivrq->rabitq, f);
878
+ WRITE1(ivrq->code_size);
879
+ WRITE1(ivrq->by_residual);
880
+ WRITE1(ivrq->qb);
881
+ write_InvertedLists(ivrq->invlists, f);
853
882
  } else {
854
883
  FAISS_THROW_MSG("don't know how to serialize this type of index");
855
884
  }
@@ -16,12 +16,12 @@
16
16
 
17
17
  #pragma once
18
18
 
19
+ #include <cstddef>
20
+ #include <cstdint>
19
21
  #include <cstdio>
20
22
  #include <string>
21
23
  #include <vector>
22
24
 
23
- #include <faiss/Index.h>
24
-
25
25
  namespace faiss {
26
26
 
27
27
  struct IOReader {
@@ -7,6 +7,8 @@
7
7
 
8
8
  #pragma once
9
9
 
10
+ #include <faiss/impl/maybe_owned_vector.h>
11
+
10
12
  /*************************************************************
11
13
  * I/O macros
12
14
  *