faiss 0.5.0 → 0.5.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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +2 -0
  4. data/ext/faiss/index.cpp +16 -9
  5. data/ext/faiss/numo.hpp +31 -31
  6. data/lib/faiss/version.rb +1 -1
  7. data/vendor/faiss/faiss/IVFlib.cpp +25 -49
  8. data/vendor/faiss/faiss/Index.cpp +11 -0
  9. data/vendor/faiss/faiss/Index.h +24 -1
  10. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +1 -0
  11. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +5 -1
  12. data/vendor/faiss/faiss/IndexFastScan.cpp +1 -1
  13. data/vendor/faiss/faiss/IndexFastScan.h +3 -8
  14. data/vendor/faiss/faiss/IndexFlat.cpp +374 -4
  15. data/vendor/faiss/faiss/IndexFlat.h +80 -0
  16. data/vendor/faiss/faiss/IndexHNSW.cpp +90 -1
  17. data/vendor/faiss/faiss/IndexHNSW.h +57 -1
  18. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +34 -149
  19. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +86 -2
  20. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +3 -1
  21. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +293 -115
  22. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +52 -16
  23. data/vendor/faiss/faiss/IndexPQ.cpp +4 -1
  24. data/vendor/faiss/faiss/IndexPreTransform.cpp +14 -0
  25. data/vendor/faiss/faiss/IndexPreTransform.h +9 -0
  26. data/vendor/faiss/faiss/IndexRaBitQ.cpp +96 -16
  27. data/vendor/faiss/faiss/IndexRaBitQ.h +5 -1
  28. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +238 -93
  29. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +35 -9
  30. data/vendor/faiss/faiss/IndexRefine.cpp +49 -0
  31. data/vendor/faiss/faiss/IndexRefine.h +17 -0
  32. data/vendor/faiss/faiss/clone_index.cpp +2 -0
  33. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +3 -1
  34. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +1 -1
  35. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +1 -1
  36. data/vendor/faiss/faiss/impl/DistanceComputer.h +74 -3
  37. data/vendor/faiss/faiss/impl/HNSW.cpp +294 -15
  38. data/vendor/faiss/faiss/impl/HNSW.h +31 -2
  39. data/vendor/faiss/faiss/impl/IDSelector.h +3 -3
  40. data/vendor/faiss/faiss/impl/Panorama.cpp +193 -0
  41. data/vendor/faiss/faiss/impl/Panorama.h +204 -0
  42. data/vendor/faiss/faiss/impl/RaBitQStats.cpp +29 -0
  43. data/vendor/faiss/faiss/impl/RaBitQStats.h +56 -0
  44. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +54 -6
  45. data/vendor/faiss/faiss/impl/RaBitQUtils.h +183 -6
  46. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +269 -84
  47. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +71 -4
  48. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +362 -0
  49. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.h +112 -0
  50. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +6 -9
  51. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +1 -3
  52. data/vendor/faiss/faiss/impl/index_read.cpp +156 -12
  53. data/vendor/faiss/faiss/impl/index_write.cpp +142 -19
  54. data/vendor/faiss/faiss/impl/platform_macros.h +12 -0
  55. data/vendor/faiss/faiss/impl/svs_io.cpp +86 -0
  56. data/vendor/faiss/faiss/impl/svs_io.h +67 -0
  57. data/vendor/faiss/faiss/index_factory.cpp +182 -15
  58. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +1 -1
  59. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
  60. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +18 -109
  61. data/vendor/faiss/faiss/invlists/InvertedLists.h +2 -18
  62. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +1 -1
  63. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  64. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +261 -0
  65. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +117 -0
  66. data/vendor/faiss/faiss/svs/IndexSVSFlat.h +66 -0
  67. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +245 -0
  68. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +137 -0
  69. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +39 -0
  70. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +42 -0
  71. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +149 -0
  72. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +58 -0
  73. data/vendor/faiss/faiss/utils/distances.cpp +0 -3
  74. data/vendor/faiss/faiss/utils/utils.cpp +4 -0
  75. metadata +21 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f3306dbb81c9168dcd82435c99d3404ab8501ac9b948adb2db7238ab89c01003
4
- data.tar.gz: b14a120e9cc67baba96816b52cf34388aae79fa690fc511918543921b64380d5
3
+ metadata.gz: 8ab397b95262fa87d28a4f08098de35f487b44e6240682ec8e98c4efc823c4df
4
+ data.tar.gz: 719490d3f20bad4531f588e9469d3fa9ec2362cc18f800e913725ffb6b0aeca0
5
5
  SHA512:
6
- metadata.gz: b7af3f6540d283d886301137e5fed5dff32b0c0659e9c46d6c45808439e94a0a91f8c953d5897b480568169ec23cacc4224db523d6ab9b3737d7f0df1ce8190c
7
- data.tar.gz: fbe44473d9e3c61427aee597fed40264ba83a8184c0fe5280b6bf181d9bcc396583f033a69e8d3ec643ee0d41ef435dfeef4aa4441ade67703cbd8259326cb81
6
+ metadata.gz: 56e16fad10a1ba95c9727f2e356470e984ca29b44406cf125b1ab529c83fee2c9bf15efa564a543cda331489dbdc56c9c44f4eda4ad53178979370987b6fbf9e
7
+ data.tar.gz: 691e9a843eaac7e699dafc15d5505f6febf783ae6d474ee0409cb01d1b1f1575477db13cb7290a4d2cc639692503099fa7d4ff767d3c3034838d05ea0476521a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.5.2 (2026-01-02)
2
+
3
+ - Fixed error with Rice 4.8
4
+
5
+ ## 0.5.1 (2025-12-20)
6
+
7
+ - Updated Faiss to 1.13.2
8
+ - Added `reconstruct` method
9
+
1
10
  ## 0.5.0 (2025-11-12)
2
11
 
3
12
  - Updated Faiss to 1.13.0
data/README.md CHANGED
@@ -53,6 +53,8 @@ Search
53
53
  distances, ids = index.search(objects, 3)
54
54
  ```
55
55
 
56
+ > Use `index.freeze` to release the GVL for searches
57
+
56
58
  Save an index
57
59
 
58
60
  ```ruby
data/ext/faiss/index.cpp CHANGED
@@ -31,13 +31,9 @@ namespace Rice::detail {
31
31
 
32
32
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
33
33
 
34
- Convertible is_convertible(VALUE value) { return Convertible::Cast; }
34
+ double is_convertible(VALUE value) { return Convertible::Exact; }
35
35
 
36
36
  faiss::MetricType convert(VALUE x) {
37
- if (x == Qnil && this->arg_ && this->arg_->hasDefaultValue()) {
38
- return this->arg_->defaultValue<faiss::MetricType>();
39
- }
40
-
41
37
  auto s = Object(x).to_s().str();
42
38
  if (s == "inner_product") {
43
39
  return faiss::METRIC_INNER_PRODUCT;
@@ -64,7 +60,7 @@ namespace Rice::detail {
64
60
 
65
61
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
66
62
 
67
- Convertible is_convertible(VALUE value) { return Convertible::Cast; }
63
+ double is_convertible(VALUE value) { return Convertible::Exact; }
68
64
 
69
65
  faiss::ScalarQuantizer::QuantizerType convert(VALUE x) {
70
66
  auto s = Object(x).to_s().str();
@@ -169,6 +165,14 @@ void init_index(Rice::Module& m) {
169
165
  auto &self = *Rice::Data_Object<faiss::Index>{rb_self};
170
166
  faiss::ParameterSpace().set_index_parameter(&self, "nprobe", val);
171
167
  })
168
+ .define_method(
169
+ "reconstruct",
170
+ [](faiss::Index &self, int64_t key) {
171
+ auto d = static_cast<std::size_t>(self.d);
172
+ auto recons = numo::SFloat({d});
173
+ self.reconstruct(key, recons.write_ptr());
174
+ return recons;
175
+ })
172
176
  .define_method(
173
177
  "save",
174
178
  [](faiss::Index &self, Rice::String fname) {
@@ -187,10 +191,12 @@ void init_index(Rice::Module& m) {
187
191
  .define_constructor(Rice::Constructor<faiss::IndexFlatIP, int64_t>());
188
192
 
189
193
  Rice::define_class_under<faiss::IndexHNSWFlat, faiss::Index>(m, "IndexHNSWFlat")
190
- .define_constructor(Rice::Constructor<faiss::IndexHNSWFlat, int, int, faiss::MetricType>(), Rice::Arg("_d"), Rice::Arg("_M"), Rice::Arg("_metric") = faiss::METRIC_L2);
194
+ .define_constructor(Rice::Constructor<faiss::IndexHNSWFlat, int, int>())
195
+ .define_constructor(Rice::Constructor<faiss::IndexHNSWFlat, int, int, faiss::MetricType>());
191
196
 
192
197
  Rice::define_class_under<faiss::IndexIVFFlat, faiss::Index>(m, "IndexIVFFlat")
193
- .define_constructor(Rice::Constructor<faiss::IndexIVFFlat, faiss::Index*, size_t, size_t, faiss::MetricType>(), Rice::Arg("_quantizer"), Rice::Arg("_d"), Rice::Arg("_nlist"), Rice::Arg("_metric") = faiss::METRIC_L2);
198
+ .define_constructor(Rice::Constructor<faiss::IndexIVFFlat, faiss::Index*, size_t, size_t>())
199
+ .define_constructor(Rice::Constructor<faiss::IndexIVFFlat, faiss::Index*, size_t, size_t, faiss::MetricType>());
194
200
 
195
201
  Rice::define_class_under<faiss::IndexLSH, faiss::Index>(m, "IndexLSH")
196
202
  .define_constructor(Rice::Constructor<faiss::IndexLSH, int64_t, int>());
@@ -205,7 +211,8 @@ void init_index(Rice::Module& m) {
205
211
  .define_constructor(Rice::Constructor<faiss::IndexIVFScalarQuantizer, faiss::Index*, size_t, size_t, faiss::ScalarQuantizer::QuantizerType>());
206
212
 
207
213
  Rice::define_class_under<faiss::IndexIVFPQ, faiss::Index>(m, "IndexIVFPQ")
208
- .define_constructor(Rice::Constructor<faiss::IndexIVFPQ, faiss::Index*, size_t, size_t, size_t, size_t, faiss::MetricType>(), Rice::Arg("_quantizer"), Rice::Arg("_d"), Rice::Arg("_nlist"), Rice::Arg("_M"), Rice::Arg("_nbits_per_idx"), Rice::Arg("_metric") = faiss::METRIC_L2);
214
+ .define_constructor(Rice::Constructor<faiss::IndexIVFPQ, faiss::Index*, size_t, size_t, size_t, size_t>())
215
+ .define_constructor(Rice::Constructor<faiss::IndexIVFPQ, faiss::Index*, size_t, size_t, size_t, size_t, faiss::MetricType>());
209
216
 
210
217
  Rice::define_class_under<faiss::IndexIVFPQR, faiss::Index>(m, "IndexIVFPQR")
211
218
  .define_constructor(Rice::Constructor<faiss::IndexIVFPQR, faiss::Index*, size_t, size_t, size_t, size_t, size_t, size_t>());
data/ext/faiss/numo.hpp CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Numo.hpp v0.2.1
2
+ * Numo.hpp v0.3.0
3
3
  * https://github.com/ankane/numo.hpp
4
4
  * BSD-2-Clause License
5
5
  */
@@ -460,12 +460,12 @@ public:
460
460
 
461
461
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
462
462
 
463
- Convertible is_convertible(VALUE value) {
463
+ double is_convertible(VALUE value) {
464
464
  switch (rb_type(value)) {
465
465
  case RUBY_T_DATA:
466
466
  return Data_Type<numo::NArray>::is_descendant(value) ? Convertible::Exact : Convertible::None;
467
467
  case RUBY_T_ARRAY:
468
- return Convertible::Cast;
468
+ return Convertible::Exact;
469
469
  default:
470
470
  return Convertible::None;
471
471
  }
@@ -506,12 +506,12 @@ public:
506
506
 
507
507
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
508
508
 
509
- Convertible is_convertible(VALUE value) {
509
+ double is_convertible(VALUE value) {
510
510
  switch (rb_type(value)) {
511
511
  case RUBY_T_DATA:
512
512
  return Data_Type<numo::SFloat>::is_descendant(value) ? Convertible::Exact : Convertible::None;
513
513
  case RUBY_T_ARRAY:
514
- return Convertible::Cast;
514
+ return Convertible::Exact;
515
515
  default:
516
516
  return Convertible::None;
517
517
  }
@@ -552,12 +552,12 @@ public:
552
552
 
553
553
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
554
554
 
555
- Convertible is_convertible(VALUE value) {
555
+ double is_convertible(VALUE value) {
556
556
  switch (rb_type(value)) {
557
557
  case RUBY_T_DATA:
558
558
  return Data_Type<numo::DFloat>::is_descendant(value) ? Convertible::Exact : Convertible::None;
559
559
  case RUBY_T_ARRAY:
560
- return Convertible::Cast;
560
+ return Convertible::Exact;
561
561
  default:
562
562
  return Convertible::None;
563
563
  }
@@ -598,12 +598,12 @@ public:
598
598
 
599
599
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
600
600
 
601
- Convertible is_convertible(VALUE value) {
601
+ double is_convertible(VALUE value) {
602
602
  switch (rb_type(value)) {
603
603
  case RUBY_T_DATA:
604
604
  return Data_Type<numo::Int8>::is_descendant(value) ? Convertible::Exact : Convertible::None;
605
605
  case RUBY_T_ARRAY:
606
- return Convertible::Cast;
606
+ return Convertible::Exact;
607
607
  default:
608
608
  return Convertible::None;
609
609
  }
@@ -644,12 +644,12 @@ public:
644
644
 
645
645
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
646
646
 
647
- Convertible is_convertible(VALUE value) {
647
+ double is_convertible(VALUE value) {
648
648
  switch (rb_type(value)) {
649
649
  case RUBY_T_DATA:
650
650
  return Data_Type<numo::Int16>::is_descendant(value) ? Convertible::Exact : Convertible::None;
651
651
  case RUBY_T_ARRAY:
652
- return Convertible::Cast;
652
+ return Convertible::Exact;
653
653
  default:
654
654
  return Convertible::None;
655
655
  }
@@ -690,12 +690,12 @@ public:
690
690
 
691
691
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
692
692
 
693
- Convertible is_convertible(VALUE value) {
693
+ double is_convertible(VALUE value) {
694
694
  switch (rb_type(value)) {
695
695
  case RUBY_T_DATA:
696
696
  return Data_Type<numo::Int32>::is_descendant(value) ? Convertible::Exact : Convertible::None;
697
697
  case RUBY_T_ARRAY:
698
- return Convertible::Cast;
698
+ return Convertible::Exact;
699
699
  default:
700
700
  return Convertible::None;
701
701
  }
@@ -736,12 +736,12 @@ public:
736
736
 
737
737
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
738
738
 
739
- Convertible is_convertible(VALUE value) {
739
+ double is_convertible(VALUE value) {
740
740
  switch (rb_type(value)) {
741
741
  case RUBY_T_DATA:
742
742
  return Data_Type<numo::Int64>::is_descendant(value) ? Convertible::Exact : Convertible::None;
743
743
  case RUBY_T_ARRAY:
744
- return Convertible::Cast;
744
+ return Convertible::Exact;
745
745
  default:
746
746
  return Convertible::None;
747
747
  }
@@ -782,12 +782,12 @@ public:
782
782
 
783
783
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
784
784
 
785
- Convertible is_convertible(VALUE value) {
785
+ double is_convertible(VALUE value) {
786
786
  switch (rb_type(value)) {
787
787
  case RUBY_T_DATA:
788
788
  return Data_Type<numo::UInt8>::is_descendant(value) ? Convertible::Exact : Convertible::None;
789
789
  case RUBY_T_ARRAY:
790
- return Convertible::Cast;
790
+ return Convertible::Exact;
791
791
  default:
792
792
  return Convertible::None;
793
793
  }
@@ -828,12 +828,12 @@ public:
828
828
 
829
829
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
830
830
 
831
- Convertible is_convertible(VALUE value) {
831
+ double is_convertible(VALUE value) {
832
832
  switch (rb_type(value)) {
833
833
  case RUBY_T_DATA:
834
834
  return Data_Type<numo::UInt16>::is_descendant(value) ? Convertible::Exact : Convertible::None;
835
835
  case RUBY_T_ARRAY:
836
- return Convertible::Cast;
836
+ return Convertible::Exact;
837
837
  default:
838
838
  return Convertible::None;
839
839
  }
@@ -874,12 +874,12 @@ public:
874
874
 
875
875
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
876
876
 
877
- Convertible is_convertible(VALUE value) {
877
+ double is_convertible(VALUE value) {
878
878
  switch (rb_type(value)) {
879
879
  case RUBY_T_DATA:
880
880
  return Data_Type<numo::UInt32>::is_descendant(value) ? Convertible::Exact : Convertible::None;
881
881
  case RUBY_T_ARRAY:
882
- return Convertible::Cast;
882
+ return Convertible::Exact;
883
883
  default:
884
884
  return Convertible::None;
885
885
  }
@@ -920,12 +920,12 @@ public:
920
920
 
921
921
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
922
922
 
923
- Convertible is_convertible(VALUE value) {
923
+ double is_convertible(VALUE value) {
924
924
  switch (rb_type(value)) {
925
925
  case RUBY_T_DATA:
926
926
  return Data_Type<numo::UInt64>::is_descendant(value) ? Convertible::Exact : Convertible::None;
927
927
  case RUBY_T_ARRAY:
928
- return Convertible::Cast;
928
+ return Convertible::Exact;
929
929
  default:
930
930
  return Convertible::None;
931
931
  }
@@ -966,12 +966,12 @@ public:
966
966
 
967
967
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
968
968
 
969
- Convertible is_convertible(VALUE value) {
969
+ double is_convertible(VALUE value) {
970
970
  switch (rb_type(value)) {
971
971
  case RUBY_T_DATA:
972
972
  return Data_Type<numo::SComplex>::is_descendant(value) ? Convertible::Exact : Convertible::None;
973
973
  case RUBY_T_ARRAY:
974
- return Convertible::Cast;
974
+ return Convertible::Exact;
975
975
  default:
976
976
  return Convertible::None;
977
977
  }
@@ -1012,12 +1012,12 @@ public:
1012
1012
 
1013
1013
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
1014
1014
 
1015
- Convertible is_convertible(VALUE value) {
1015
+ double is_convertible(VALUE value) {
1016
1016
  switch (rb_type(value)) {
1017
1017
  case RUBY_T_DATA:
1018
1018
  return Data_Type<numo::DComplex>::is_descendant(value) ? Convertible::Exact : Convertible::None;
1019
1019
  case RUBY_T_ARRAY:
1020
- return Convertible::Cast;
1020
+ return Convertible::Exact;
1021
1021
  default:
1022
1022
  return Convertible::None;
1023
1023
  }
@@ -1058,12 +1058,12 @@ public:
1058
1058
 
1059
1059
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
1060
1060
 
1061
- Convertible is_convertible(VALUE value) {
1061
+ double is_convertible(VALUE value) {
1062
1062
  switch (rb_type(value)) {
1063
1063
  case RUBY_T_DATA:
1064
1064
  return Data_Type<numo::Bit>::is_descendant(value) ? Convertible::Exact : Convertible::None;
1065
1065
  case RUBY_T_ARRAY:
1066
- return Convertible::Cast;
1066
+ return Convertible::Exact;
1067
1067
  default:
1068
1068
  return Convertible::None;
1069
1069
  }
@@ -1104,12 +1104,12 @@ public:
1104
1104
 
1105
1105
  explicit From_Ruby(Arg* arg) : arg_(arg) { }
1106
1106
 
1107
- Convertible is_convertible(VALUE value) {
1107
+ double is_convertible(VALUE value) {
1108
1108
  switch (rb_type(value)) {
1109
1109
  case RUBY_T_DATA:
1110
1110
  return Data_Type<numo::RObject>::is_descendant(value) ? Convertible::Exact : Convertible::None;
1111
1111
  case RUBY_T_ARRAY:
1112
- return Convertible::Cast;
1112
+ return Convertible::Exact;
1113
1113
  default:
1114
1114
  return Convertible::None;
1115
1115
  }
data/lib/faiss/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Faiss
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.2"
3
3
  end
@@ -558,19 +558,6 @@ void handle_ivf(
558
558
  const std::string& filename_template,
559
559
  ShardingFunction* sharding_function,
560
560
  bool generate_ids) {
561
- std::vector<faiss::IndexIVF*> sharded_indexes(shard_count);
562
- auto clone = static_cast<faiss::IndexIVF*>(faiss::clone_index(index));
563
- clone->quantizer->reset();
564
- for (int64_t i = 0; i < shard_count; i++) {
565
- sharded_indexes[i] =
566
- static_cast<faiss::IndexIVF*>(faiss::clone_index(clone));
567
- if (generate_ids) {
568
- // Assume the quantizer does not natively support add_with_ids.
569
- sharded_indexes[i]->quantizer =
570
- new IndexIDMap2(sharded_indexes[i]->quantizer);
571
- }
572
- }
573
-
574
561
  // assign centroids to each sharded Index based on sharding_function, and
575
562
  // add them to the quantizer of each sharded index
576
563
  std::vector<std::vector<float>> sharded_centroids(shard_count);
@@ -588,27 +575,29 @@ void handle_ivf(
588
575
  &reconstructed[index->quantizer->d]);
589
576
  delete[] reconstructed;
590
577
  }
578
+
579
+ auto clone = static_cast<faiss::IndexIVF*>(faiss::clone_index(index));
580
+ clone->quantizer->reset();
591
581
  for (int64_t i = 0; i < shard_count; i++) {
582
+ auto sharded_index =
583
+ static_cast<faiss::IndexIVF*>(faiss::clone_index(clone));
592
584
  if (generate_ids) {
593
- sharded_indexes[i]->quantizer->add_with_ids(
585
+ // Assume the quantizer does not natively support add_with_ids.
586
+ sharded_index->quantizer =
587
+ new IndexIDMap2(sharded_index->quantizer);
588
+ sharded_index->quantizer->add_with_ids(
594
589
  sharded_centroids[i].size() / index->quantizer->d,
595
590
  sharded_centroids[i].data(),
596
591
  xids[i].data());
597
592
  } else {
598
- sharded_indexes[i]->quantizer->add(
593
+ sharded_index->quantizer->add(
599
594
  sharded_centroids[i].size() / index->quantizer->d,
600
595
  sharded_centroids[i].data());
601
596
  }
602
- }
603
-
604
- for (int64_t i = 0; i < shard_count; i++) {
605
597
  char fname[256];
606
598
  snprintf(fname, 256, filename_template.c_str(), i);
607
- faiss::write_index(sharded_indexes[i], fname);
608
- }
609
-
610
- for (int64_t i = 0; i < shard_count; i++) {
611
- delete sharded_indexes[i];
599
+ faiss::write_index(sharded_index, fname);
600
+ delete sharded_index;
612
601
  }
613
602
  }
614
603
 
@@ -618,22 +607,6 @@ void handle_binary_ivf(
618
607
  const std::string& filename_template,
619
608
  ShardingFunction* sharding_function,
620
609
  bool generate_ids) {
621
- std::vector<faiss::IndexBinaryIVF*> sharded_indexes(shard_count);
622
-
623
- auto clone = static_cast<faiss::IndexBinaryIVF*>(
624
- faiss::clone_binary_index(index));
625
- clone->quantizer->reset();
626
-
627
- for (int64_t i = 0; i < shard_count; i++) {
628
- sharded_indexes[i] = static_cast<faiss::IndexBinaryIVF*>(
629
- faiss::clone_binary_index(clone));
630
- if (generate_ids) {
631
- // Assume the quantizer does not natively support add_with_ids.
632
- sharded_indexes[i]->quantizer =
633
- new IndexBinaryIDMap2(sharded_indexes[i]->quantizer);
634
- }
635
- }
636
-
637
610
  // assign centroids to each sharded Index based on sharding_function, and
638
611
  // add them to the quantizer of each sharded index
639
612
  int64_t reconstruction_size = index->quantizer->d / 8;
@@ -652,27 +625,30 @@ void handle_binary_ivf(
652
625
  &reconstructed[reconstruction_size]);
653
626
  delete[] reconstructed;
654
627
  }
628
+
629
+ auto clone = static_cast<faiss::IndexBinaryIVF*>(
630
+ faiss::clone_binary_index(index));
631
+ clone->quantizer->reset();
655
632
  for (int64_t i = 0; i < shard_count; i++) {
633
+ auto sharded_index = static_cast<faiss::IndexBinaryIVF*>(
634
+ faiss::clone_binary_index(clone));
656
635
  if (generate_ids) {
657
- sharded_indexes[i]->quantizer->add_with_ids(
636
+ // Assume the quantizer does not natively support add_with_ids.
637
+ sharded_index->quantizer =
638
+ new IndexBinaryIDMap2(sharded_index->quantizer);
639
+ sharded_index->quantizer->add_with_ids(
658
640
  sharded_centroids[i].size() / reconstruction_size,
659
641
  sharded_centroids[i].data(),
660
642
  xids[i].data());
661
643
  } else {
662
- sharded_indexes[i]->quantizer->add(
644
+ sharded_index->quantizer->add(
663
645
  sharded_centroids[i].size() / reconstruction_size,
664
646
  sharded_centroids[i].data());
665
647
  }
666
- }
667
-
668
- for (int64_t i = 0; i < shard_count; i++) {
669
648
  char fname[256];
670
649
  snprintf(fname, 256, filename_template.c_str(), i);
671
- faiss::write_index_binary(sharded_indexes[i], fname);
672
- }
673
-
674
- for (int64_t i = 0; i < shard_count; i++) {
675
- delete sharded_indexes[i];
650
+ faiss::write_index_binary(sharded_index, fname);
651
+ delete sharded_index;
676
652
  }
677
653
  }
678
654
 
@@ -104,6 +104,17 @@ void Index::search_and_reconstruct(
104
104
  }
105
105
  }
106
106
 
107
+ void Index::search_subset(
108
+ idx_t n,
109
+ const float* x,
110
+ idx_t k_base,
111
+ const idx_t* base_labels,
112
+ idx_t k,
113
+ float* distances,
114
+ idx_t* labels) const {
115
+ FAISS_THROW_MSG("search_subset not implemented for this type of index");
116
+ }
117
+
107
118
  void Index::compute_residual(const float* x, float* residual, idx_t key) const {
108
119
  reconstruct(key, residual);
109
120
  for (size_t i = 0; i < d; i++) {
@@ -18,7 +18,7 @@
18
18
 
19
19
  #define FAISS_VERSION_MAJOR 1
20
20
  #define FAISS_VERSION_MINOR 13
21
- #define FAISS_VERSION_PATCH 0
21
+ #define FAISS_VERSION_PATCH 2
22
22
 
23
23
  // Macro to combine the version components into a single string
24
24
  #ifndef FAISS_STRINGIFY
@@ -304,6 +304,29 @@ struct Index {
304
304
  float* recons,
305
305
  const SearchParameters* params = nullptr) const;
306
306
 
307
+ /** Similar to search, but operates on a potentially different subset
308
+ * of the dataset for each query.
309
+ *
310
+ * The default implementation fails with an assertion, as it is
311
+ * not supported by all indexes.
312
+ *
313
+ * @param n number of vectors
314
+ * @param x input vectors, size n * d
315
+ * @param k_base number of vectors to search from
316
+ * @param base_labels ids of the vectors to search from
317
+ * @param k desired number of results per query
318
+ * @param distances output pairwise distances, size n*k
319
+ * @param labels output labels of the NNs, size n*k
320
+ */
321
+ virtual void search_subset(
322
+ idx_t n,
323
+ const float* x,
324
+ idx_t k_base,
325
+ const idx_t* base_labels,
326
+ idx_t k,
327
+ float* distances,
328
+ idx_t* labels) const;
329
+
307
330
  /** Computes a residual vector after indexing encoding.
308
331
  *
309
332
  * The residual vector is the difference between a vector and the
@@ -86,6 +86,7 @@ struct AQDistanceComputerLUT : FlatCodesDistanceComputer {
86
86
 
87
87
  float bias;
88
88
  void set_query(const float* x) final {
89
+ q = x;
89
90
  // this is quite sub-optimal for multiple queries
90
91
  aq.compute_LUT(1, x, LUT.data());
91
92
  if (is_IP) {
@@ -227,7 +227,11 @@ void IndexBinaryHNSW::search(
227
227
  for (idx_t i = 0; i < n; i++) {
228
228
  res.begin(i);
229
229
  dis->set_query((float*)(x + i * code_size));
230
- hnsw.search(*dis, res, vt);
230
+ // Given that IndexBinaryHNSW is not an IndexHNSW, we pass nullptr
231
+ // as the index parameter. This state does not get used in the
232
+ // search function, as it is merely there to to enable Panorama
233
+ // execution for IndexHNSWFlatPanorama.
234
+ hnsw.search(*dis, nullptr, res, vt);
231
235
  res.end();
232
236
  }
233
237
  }
@@ -199,7 +199,7 @@ void estimators_from_tables_generic(
199
199
  } // anonymous namespace
200
200
 
201
201
  // Default implementation of make_knn_handler with centralized fallback logic
202
- void* IndexFastScan::make_knn_handler(
202
+ SIMDResultHandlerToFloat* IndexFastScan::make_knn_handler(
203
203
  bool is_max,
204
204
  int impl,
205
205
  idx_t n,
@@ -15,13 +15,8 @@ namespace faiss {
15
15
 
16
16
  struct CodePacker;
17
17
  struct NormTableScaler;
18
-
19
- // Forward declarations for result handlers
20
- namespace simd_result_handlers {
21
- template <class C, bool with_id_map>
22
- struct ResultHandlerCompare;
23
- }
24
18
  struct IDSelector;
19
+ struct SIMDResultHandlerToFloat;
25
20
 
26
21
  /** Fast scan version of IndexPQ and IndexAQ. Works for 4-bit PQ and AQ for now.
27
22
  *
@@ -141,10 +136,10 @@ struct IndexFastScan : Index {
141
136
  * @param distances output distances array
142
137
  * @param labels output labels array
143
138
  * @param sel optional ID selector
144
- * @param query_offset query offset for batch processing
139
+ * @param context processing context for distance post-processing
145
140
  * @return pointer to created handler (never returns nullptr)
146
141
  */
147
- virtual void* make_knn_handler(
142
+ virtual SIMDResultHandlerToFloat* make_knn_handler(
148
143
  bool is_max,
149
144
  int impl,
150
145
  idx_t n,