faiss 0.6.3 → 0.6.4

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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/faiss/version.rb +1 -1
  4. data/vendor/faiss/faiss/Clustering.h +8 -0
  5. data/vendor/faiss/faiss/Index.h +1 -1
  6. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +23 -2
  7. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +12 -140
  8. data/vendor/faiss/faiss/IndexBinaryHNSW.h +0 -6
  9. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +6 -14
  10. data/vendor/faiss/faiss/IndexBinaryIVF.h +8 -1
  11. data/vendor/faiss/faiss/IndexFlat.cpp +8 -4
  12. data/vendor/faiss/faiss/IndexFlat.h +2 -2
  13. data/vendor/faiss/faiss/IndexHNSW.cpp +301 -91
  14. data/vendor/faiss/faiss/IndexHNSW.h +31 -7
  15. data/vendor/faiss/faiss/IndexIDMap.cpp +11 -6
  16. data/vendor/faiss/faiss/IndexIVF.cpp +19 -4
  17. data/vendor/faiss/faiss/IndexIVFPQ.cpp +9 -1
  18. data/vendor/faiss/faiss/IndexIVFPQ.h +11 -0
  19. data/vendor/faiss/faiss/IndexShards.cpp +3 -3
  20. data/vendor/faiss/faiss/IndexShardsIVF.cpp +4 -3
  21. data/vendor/faiss/faiss/SuperKMeans.cpp +31 -8
  22. data/vendor/faiss/faiss/SuperKMeans.h +3 -2
  23. data/vendor/faiss/faiss/VectorTransform.cpp +38 -0
  24. data/vendor/faiss/faiss/VectorTransform.h +3 -0
  25. data/vendor/faiss/faiss/clone_index.cpp +3 -0
  26. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +1 -5
  27. data/vendor/faiss/faiss/gpu/GpuDistance.h +2 -5
  28. data/vendor/faiss/faiss/gpu/GpuIndex.h +4 -5
  29. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +65 -42
  30. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +1 -1
  31. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +5 -2
  32. data/vendor/faiss/faiss/impl/HNSW.cpp +419 -115
  33. data/vendor/faiss/faiss/impl/HNSW.h +46 -7
  34. data/vendor/faiss/faiss/impl/IDSelector.h +44 -0
  35. data/vendor/faiss/faiss/impl/NNDescent.cpp +10 -3
  36. data/vendor/faiss/faiss/impl/Panorama.h +11 -2
  37. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +4 -4
  38. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +1 -1
  39. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +74 -8
  40. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +47 -4
  41. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +2 -2
  42. data/vendor/faiss/faiss/impl/ResultHandler.h +9 -3
  43. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +32 -30
  44. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +6 -10
  45. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +89 -13
  46. data/vendor/faiss/faiss/impl/expanded_scanners.h +5 -1
  47. data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +1 -0
  48. data/vendor/faiss/faiss/impl/index_read.cpp +130 -29
  49. data/vendor/faiss/faiss/impl/index_write.cpp +31 -26
  50. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +73 -39
  51. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +4 -4
  52. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +6 -1
  53. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +2 -2
  54. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +6 -2
  55. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +37 -17
  56. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +109 -10
  57. data/vendor/faiss/faiss/impl/simd_dispatch.h +40 -22
  58. data/vendor/faiss/faiss/index_factory.cpp +8 -1
  59. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +7 -4
  60. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +10 -4
  61. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +16 -4
  62. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +8 -1
  63. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +4 -2
  64. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
  65. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +9 -2
  66. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +2 -1
  67. data/vendor/faiss/faiss/utils/distances.cpp +20 -13
  68. data/vendor/faiss/faiss/utils/distances_dispatch.h +30 -24
  69. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +1 -1
  70. data/vendor/faiss/faiss/utils/hamming.cpp +15 -9
  71. data/vendor/faiss/faiss/utils/hamming.h +10 -1
  72. data/vendor/faiss/faiss/utils/hamming_distance/common.h +14 -3
  73. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_vpopcnt.cpp +24 -0
  74. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +1 -1
  75. data/vendor/faiss/faiss/utils/hamming_distance/{hamming_computer-avx512_spr.h → hamming_computer-avx512_vpopcnt.h} +85 -24
  76. data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +141 -0
  77. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +194 -30
  78. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +93 -55
  79. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +57 -40
  80. data/vendor/faiss/faiss/utils/simd_impl/{rabitq_avx512_spr.cpp → rabitq_avx512_vpopcnt.cpp} +21 -24
  81. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +2 -7
  82. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +6 -1
  83. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_sve.cpp +34 -0
  84. data/vendor/faiss/faiss/utils/simd_levels.cpp +172 -67
  85. data/vendor/faiss/faiss/utils/simd_levels.h +26 -15
  86. metadata +6 -5
  87. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ab0ef0079ca7056c6d303b95882757645a81bee9b4c13862f4337dbec1b105a
4
- data.tar.gz: d61339d723153ed333a6719001de98fa1742606334684b0f7db26f26ad001b09
3
+ metadata.gz: 6a22f4ad8f3c626f1d6571c4cefcb8292965e52eb3b0b77c354f39ed117570c5
4
+ data.tar.gz: b848af534bebc2ecfdfa5fe7eaa270b530d17d5fe5381aea350451aa03c22d9f
5
5
  SHA512:
6
- metadata.gz: 20ce33982905751c82f05241b94ca500b241ac15f18245e8e14dad29d2fe5f162c7d4fe4e5441e92f79e06eb9519538831fa2c857050e6b3ea8ad5d0b8e63366
7
- data.tar.gz: cfd073d25d3067488fdde88e06c5c68eeec6840ea57b9e6222129f4594279a27148b62361bcbd0dcc57727053acd35e4f202558adef03de648d0c8179f05ce07
6
+ metadata.gz: 4c5083b9733f589fc30c93f429ed4da74fbb4bbdbe2bde17787506cafb178e2715d114e04ed17bd21a1161a096df66a0c502ae6dc245455c1e221737e80a1f3e
7
+ data.tar.gz: 41eb8ce7434c4408fccf238893468e8c808b1961966a9fc495f960d27ff950d5d6a9cafff18a11e14287f5fedc77f83db9118c47c60e06fdc9f86d9987592c7c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.6.4 (2026-09-17)
2
+
3
+ - Updated Faiss to 1.15.1
4
+
1
5
  ## 0.6.3 (2026-08-03)
2
6
 
3
7
  - Updated Faiss to 1.15.0
data/lib/faiss/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Faiss
2
- VERSION = "0.6.3"
2
+ VERSION = "0.6.4"
3
3
  end
@@ -75,6 +75,14 @@ struct ClusteringParameters {
75
75
  /// so the training process stops only if an error
76
76
  /// is unchanged from the previous iteration.
77
77
  double early_stop_threshold = 0.0;
78
+
79
+ /// Whether to use the SuperKMeans (super fast k-means) variant instead of
80
+ /// the vanilla Clustering implementation. Only honored by callers that
81
+ /// explicitly support it (e.g. IVF level-1 quantizer training). Cannot be
82
+ /// combined with a user-provided clustering index: SuperKMeans assigns
83
+ /// with its own index, so callers that supply both get an exception rather
84
+ /// than a silent downgrade to vanilla Clustering.
85
+ bool use_super_kmeans = false;
78
86
  };
79
87
 
80
88
  struct ClusteringIterationStats {
@@ -17,7 +17,7 @@
17
17
 
18
18
  #define FAISS_VERSION_MAJOR 1
19
19
  #define FAISS_VERSION_MINOR 15
20
- #define FAISS_VERSION_PATCH 0
20
+ #define FAISS_VERSION_PATCH 1
21
21
 
22
22
  // Macro to combine the version components into a single string
23
23
  #ifndef FAISS_STRINGIFY
@@ -9,9 +9,11 @@
9
9
 
10
10
  #include <faiss/IndexBinaryFromFloat.h>
11
11
 
12
+ #include <faiss/MetricType.h>
12
13
  #include <faiss/impl/FaissAssert.h>
13
14
  #include <faiss/utils/utils.h>
14
15
  #include <algorithm>
16
+ #include <cmath>
15
17
  #include <memory>
16
18
 
17
19
  namespace faiss {
@@ -67,8 +69,27 @@ void IndexBinaryFromFloat::search(
67
69
  binary_to_real(bn * d, x + b * code_size, xf.get());
68
70
 
69
71
  index->search(bn, xf.get(), k, df.get(), labels + b * k);
70
- for (int i = 0; i < bn * k; ++i) {
71
- distances[b * k + i] = int32_t(std::round(df[i] / 4.0));
72
+ // binary_to_real maps bits to {-1, +1}, so the float distance relates
73
+ // to the Hamming distance differently for each metric. In all cases the
74
+ // mapping is monotonic, so the result order needs no adjustment.
75
+ switch (index->metric_type) {
76
+ case METRIC_INNER_PRODUCT:
77
+ for (int i = 0; i < bn * k; ++i) {
78
+ distances[b * k + i] =
79
+ int32_t(std::round((d - df[i]) / 2.0));
80
+ }
81
+ break;
82
+ case METRIC_L1:
83
+ for (int i = 0; i < bn * k; ++i) {
84
+ distances[b * k + i] = int32_t(std::round(df[i] / 2.0));
85
+ }
86
+ break;
87
+ case METRIC_L2:
88
+ default:
89
+ for (int i = 0; i < bn * k; ++i) {
90
+ distances[b * k + i] = int32_t(std::round(df[i] / 4.0));
91
+ }
92
+ break;
72
93
  }
73
94
  }
74
95
  }
@@ -7,7 +7,6 @@
7
7
 
8
8
  #include <faiss/IndexBinaryHNSW.h>
9
9
 
10
- #include <omp.h>
11
10
  #include <cassert>
12
11
  #include <cmath>
13
12
  #include <cstdio>
@@ -39,140 +38,6 @@
39
38
 
40
39
  namespace faiss {
41
40
 
42
- /**************************************************************
43
- * add / search blocks of descriptors
44
- **************************************************************/
45
-
46
- namespace {
47
-
48
- void hnsw_add_vertices(
49
- IndexBinaryHNSW& index_hnsw,
50
- size_t n0,
51
- size_t n,
52
- const uint8_t* x,
53
- bool verbose,
54
- bool preset_levels = false) {
55
- HNSW& hnsw = index_hnsw.hnsw;
56
- size_t ntotal = n0 + n;
57
- double t0 = getmillisecs();
58
- if (verbose) {
59
- printf("hnsw_add_vertices: adding %zd elements on top of %zd "
60
- "(preset_levels=%d)\n",
61
- n,
62
- n0,
63
- int(preset_levels));
64
- }
65
-
66
- int max_level = hnsw.prepare_level_tab(n, preset_levels);
67
-
68
- if (verbose) {
69
- printf(" max_level = %d\n", max_level);
70
- }
71
-
72
- auto& locks = index_hnsw.locks;
73
- locks.prepare(ntotal);
74
-
75
- // add vectors from highest to lowest level
76
- std::vector<int> hist;
77
- std::vector<int> order(n);
78
-
79
- { // make buckets with vectors of the same level
80
-
81
- // build histogram
82
- for (size_t i = 0; i < n; i++) {
83
- HNSW::storage_idx_t pt_id =
84
- static_cast<HNSW::storage_idx_t>(i + n0);
85
- int pt_level = hnsw.levels[pt_id] - 1;
86
- while (pt_level >= static_cast<int>(hist.size())) {
87
- hist.push_back(0);
88
- }
89
- hist[pt_level]++;
90
- }
91
-
92
- // accumulate
93
- std::vector<int> offsets(hist.size() + 1, 0);
94
- for (size_t i = 0; i < hist.size() - 1; i++) {
95
- offsets[i + 1] = offsets[i] + hist[i];
96
- }
97
-
98
- // bucket sort
99
- for (size_t i = 0; i < n; i++) {
100
- HNSW::storage_idx_t pt_id =
101
- static_cast<HNSW::storage_idx_t>(i + n0);
102
- int pt_level = hnsw.levels[pt_id] - 1;
103
- order[offsets[pt_level]++] = pt_id;
104
- }
105
- }
106
-
107
- { // perform add
108
- RandomGenerator rng2(789);
109
-
110
- size_t i1 = static_cast<int>(n);
111
-
112
- for (int pt_level = static_cast<int>(hist.size()) - 1;
113
- pt_level >= int(!index_hnsw.init_level0);
114
- pt_level--) {
115
- size_t i0 = i1 - hist[pt_level];
116
-
117
- if (verbose) {
118
- printf("Adding %zu elements at level %d\n", i1 - i0, pt_level);
119
- }
120
-
121
- // random permutation to get rid of dataset order bias
122
- for (size_t j = i0; j < i1; j++) {
123
- std::swap(
124
- order[j],
125
- order[j + rng2.rand_int(static_cast<int>(i1 - j))]);
126
- }
127
-
128
- #pragma omp parallel
129
- {
130
- std::unique_ptr<VisitedTable> vt = VisitedTable::create(ntotal);
131
-
132
- std::unique_ptr<DistanceComputer> dis(
133
- index_hnsw.get_distance_computer());
134
- bool do_display = verbose && omp_get_thread_num() == 0;
135
- size_t prev_display = 0;
136
-
137
- #pragma omp for schedule(dynamic)
138
- for (int64_t i = i0; i < i1; i++) {
139
- HNSW::storage_idx_t pt_id = order[i];
140
- dis->set_query(
141
- (float*)(x + (pt_id - n0) * index_hnsw.code_size));
142
-
143
- hnsw.add_with_locks(
144
- *dis,
145
- pt_level,
146
- pt_id,
147
- locks,
148
- *vt,
149
- index_hnsw.keep_max_size_level0 && (pt_level == 0));
150
-
151
- if (do_display && i - i0 > prev_display + 10000) {
152
- prev_display = i - i0;
153
- printf(" %zu / %zu\r", i - i0, i1 - i0);
154
- fflush(stdout);
155
- }
156
- }
157
- }
158
- i1 = i0;
159
- }
160
- if (index_hnsw.init_level0) {
161
- FAISS_ASSERT(i1 == 0);
162
- } else {
163
- FAISS_ASSERT((i1 - hist[0]) == 0);
164
- }
165
- }
166
- if (verbose) {
167
- printf("Done in %.3f ms\n", getmillisecs() - t0);
168
- }
169
- if (!index_hnsw.retain_locks) {
170
- locks.clear();
171
- }
172
- }
173
-
174
- } // anonymous namespace
175
-
176
41
  /**************************************************************
177
42
  * IndexBinaryHNSW implementation
178
43
  **************************************************************/
@@ -270,18 +135,25 @@ void IndexBinaryHNSW::add(idx_t n, const uint8_t* x) {
270
135
  storage->add(n, x);
271
136
  ntotal = storage->ntotal;
272
137
 
273
- hnsw_add_vertices(
274
- *this,
138
+ bool preset_levels = hnsw.levels.size() == static_cast<size_t>(ntotal);
139
+
140
+ hnsw_add_vertices_deterministic(
141
+ hnsw,
275
142
  n0,
276
143
  n,
277
- x,
144
+ d,
145
+ init_level0,
146
+ keep_max_size_level0,
147
+ preset_levels,
278
148
  verbose,
279
- hnsw.levels.size() == static_cast<size_t>(ntotal));
149
+ [this] { return get_distance_computer(); },
150
+ [this, x, n0](DistanceComputer& dc, HNSW::storage_idx_t pt_id) {
151
+ dc.set_query((const float*)(x + (pt_id - n0) * code_size));
152
+ });
280
153
  }
281
154
 
282
155
  void IndexBinaryHNSW::reset() {
283
156
  hnsw.reset();
284
- locks.clear();
285
157
  storage->reset();
286
158
  ntotal = 0;
287
159
  }
@@ -11,7 +11,6 @@
11
11
 
12
12
  #include <faiss/IndexBinaryFlat.h>
13
13
  #include <faiss/impl/HNSW.h>
14
- #include <faiss/impl/hnsw/LockVector.h>
15
14
  #include <faiss/utils/utils.h>
16
15
 
17
16
  namespace faiss {
@@ -41,11 +40,6 @@ struct IndexBinaryHNSW : IndexBinary {
41
40
  // used when GpuIndexBinaryCagra::copyFrom(IndexBinaryHNSW*) is called.
42
41
  bool keep_max_size_level0 = false;
43
42
 
44
- // Per-node locks for HNSW graph construction.
45
- LockVector locks;
46
- // locks are freed after each call to add() unless this flag is set.
47
- bool retain_locks = false;
48
-
49
43
  explicit IndexBinaryHNSW();
50
44
  explicit IndexBinaryHNSW(int d, int M = 32);
51
45
  explicit IndexBinaryHNSW(IndexBinary* storage, int M = 32);
@@ -192,7 +192,7 @@ void IndexBinaryIVF::reconstruct_n(idx_t i0, idx_t ni, uint8_t* recons) const {
192
192
  continue;
193
193
  }
194
194
 
195
- uint8_t* reconstructed = recons + (id - i0) * d;
195
+ uint8_t* reconstructed = recons + (id - i0) * code_size;
196
196
  reconstruct_from_offset(list_no, offset, reconstructed);
197
197
  }
198
198
  }
@@ -233,10 +233,10 @@ void IndexBinaryIVF::search_and_reconstruct(
233
233
  for (idx_t j = 0; j < k; ++j) {
234
234
  idx_t ij = i * k + j;
235
235
  idx_t key = labels[ij];
236
- uint8_t* reconstructed = recons + ij * d;
236
+ uint8_t* reconstructed = recons + ij * code_size;
237
237
  if (key < 0) {
238
238
  // Fill with NaNs
239
- memset(reconstructed, -1, sizeof(*reconstructed) * d);
239
+ memset(reconstructed, -1, code_size);
240
240
  } else {
241
241
  int list_no = key >> 32;
242
242
  int offset = key & 0xffffffff;
@@ -348,10 +348,6 @@ void IndexBinaryIVF::replace_invlists(InvertedLists* il, bool own) {
348
348
  own_invlists = own;
349
349
  }
350
350
 
351
- // IVFBinaryScannerL2, search_knn_hamming_count, BlockSearch,
352
- // BlockSearchVariableK, search_knn_hamming_per_invlist are now in
353
- // impl/binary_hamming/IndexBinaryIVF_impl.h (compiled per-ISA)
354
-
355
351
  namespace {
356
352
 
357
353
  void search_knn_hamming_heap(
@@ -461,13 +457,9 @@ void search_knn_hamming_heap(
461
457
 
462
458
  } // anonymous namespace
463
459
 
464
- // The remaining template code (search_knn_hamming_count,
465
- // search_knn_hamming_per_invlist, etc.) has been moved to
466
- // impl/binary_hamming/IndexBinaryIVF_impl.h
467
-
468
460
  BinaryInvertedListScanner* IndexBinaryIVF::get_InvertedListScanner(
469
461
  bool store_pairs) const {
470
- return with_simd_level([&]<SIMDLevel SL>() {
462
+ return with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
471
463
  return make_binary_ivf_scanner_fixSL<SL>(code_size, store_pairs);
472
464
  });
473
465
  }
@@ -483,7 +475,7 @@ void IndexBinaryIVF::search_preassigned(
483
475
  bool store_pairs,
484
476
  const IVFSearchParameters* params) const {
485
477
  if (per_invlist_search) {
486
- with_simd_level([&]<SIMDLevel SL>() {
478
+ with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
487
479
  search_knn_hamming_per_invlist_fixSL<SL>(
488
480
  code_size,
489
481
  this,
@@ -501,7 +493,7 @@ void IndexBinaryIVF::search_preassigned(
501
493
  search_knn_hamming_heap(
502
494
  this, n, x, k, cidx, cdis, dis, idx, store_pairs, params);
503
495
  } else {
504
- with_simd_level([&]<SIMDLevel SL>() {
496
+ with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
505
497
  search_knn_hamming_count_fixSL<SL>(
506
498
  code_size,
507
499
  store_pairs,
@@ -232,7 +232,14 @@ struct BinaryInvertedListScanner {
232
232
  virtual uint32_t distance_to_code(const uint8_t* code) const = 0;
233
233
 
234
234
  /** compute the distances to codes. (distances, labels) should be
235
- * organized as a min- or max-heap
235
+ * organized as a max-heap: the scan accepts a code whose distance is
236
+ * below distances[0] and replaces the top. A min-heap caller reads its
237
+ * neutral value as a huge unsigned bound and gets wrong results.
238
+
239
+ *
240
+ * The heap top is the only bound. To keep the k nearest codes inside a
241
+ * radius, seed every heap slot with that radius instead of the neutral
242
+ * value; an unfilled slot keeps its label of -1.
236
243
  *
237
244
  * @param n number of codes to scan
238
245
  * @param codes codes to scan (n * code_size)
@@ -270,9 +270,11 @@ struct FlatIPDis : FlatCodesDistanceComputer {
270
270
  FlatCodesDistanceComputer* IndexFlat::get_FlatCodesDistanceComputer() const {
271
271
  FlatCodesDistanceComputer* dc = nullptr;
272
272
  if (metric_type == METRIC_L2) {
273
- with_simd_level([&]<SIMDLevel SL>() { dc = new FlatL2Dis<SL>(*this); });
273
+ with_simd_level_with_sve(
274
+ [&]<SIMDLevel SL>() { dc = new FlatL2Dis<SL>(*this); });
274
275
  } else if (metric_type == METRIC_INNER_PRODUCT) {
275
- with_simd_level([&]<SIMDLevel SL>() { dc = new FlatIPDis<SL>(*this); });
276
+ with_simd_level_with_sve(
277
+ [&]<SIMDLevel SL>() { dc = new FlatIPDis<SL>(*this); });
276
278
  } else {
277
279
  dc = get_extra_distance_computer(d, metric_type, metric_arg, get_xb());
278
280
  }
@@ -404,7 +406,7 @@ FlatCodesDistanceComputer* IndexFlatL2::get_FlatCodesDistanceComputer() const {
404
406
  if (metric_type == METRIC_L2) {
405
407
  if (!cached_l2norms.empty()) {
406
408
  FlatCodesDistanceComputer* dc = nullptr;
407
- with_simd_level([&]<SIMDLevel SL>() {
409
+ with_simd_level_with_sve([&]<SIMDLevel SL>() {
408
410
  dc = new FlatL2WithNormsDis<SL>(*this);
409
411
  });
410
412
  return dc;
@@ -704,10 +706,12 @@ void IndexFlatPanorama::reset() {
704
706
  }
705
707
 
706
708
  void IndexFlatPanorama::reconstruct(idx_t key, float* recons) const {
709
+ FAISS_THROW_IF_NOT(key >= 0 && key < ntotal);
707
710
  pano.reconstruct(key, recons, codes.data());
708
711
  }
709
712
 
710
713
  void IndexFlatPanorama::reconstruct_n(idx_t i, idx_t n, float* recons) const {
714
+ FAISS_THROW_IF_NOT(i >= 0 && i <= ntotal && n >= 0 && n <= ntotal - i);
711
715
  Index::reconstruct_n(i, n, recons);
712
716
  }
713
717
 
@@ -784,7 +788,7 @@ void IndexFlatPanorama::search_subset(
784
788
  idx_t k,
785
789
  float* distances,
786
790
  idx_t* labels) const {
787
- with_simd_level([&]<SIMDLevel SL>() {
791
+ with_simd_level_with_sve([&]<SIMDLevel SL>() {
788
792
  with_metric_type(metric_type, [&]<MetricType M>() {
789
793
  constexpr bool is_sim = is_similarity_metric(M);
790
794
  using C = std::conditional_t<
@@ -176,7 +176,7 @@ struct IndexFlatL2Panorama : IndexFlatPanorama {
176
176
  explicit IndexFlatL2Panorama(
177
177
  idx_t d_in,
178
178
  size_t n_levels_in,
179
- size_t batch_size_in = 512)
179
+ size_t batch_size_in = Panorama::kDefaultBatchSize)
180
180
  : IndexFlatPanorama(d_in, METRIC_L2, n_levels_in, batch_size_in) {}
181
181
  };
182
182
 
@@ -189,7 +189,7 @@ struct IndexFlatIPPanorama : IndexFlatPanorama {
189
189
  explicit IndexFlatIPPanorama(
190
190
  idx_t d_in,
191
191
  size_t n_levels_in,
192
- size_t batch_size_in = 512)
192
+ size_t batch_size_in = Panorama::kDefaultBatchSize)
193
193
  : IndexFlatPanorama(
194
194
  d_in,
195
195
  METRIC_INNER_PRODUCT,