faiss 0.2.3 → 0.2.5

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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +23 -21
  5. data/ext/faiss/extconf.rb +11 -0
  6. data/ext/faiss/index.cpp +4 -4
  7. data/ext/faiss/index_binary.cpp +6 -6
  8. data/ext/faiss/product_quantizer.cpp +4 -4
  9. data/lib/faiss/version.rb +1 -1
  10. data/vendor/faiss/faiss/AutoTune.cpp +13 -0
  11. data/vendor/faiss/faiss/Clustering.cpp +32 -0
  12. data/vendor/faiss/faiss/Clustering.h +14 -0
  13. data/vendor/faiss/faiss/IVFlib.cpp +101 -2
  14. data/vendor/faiss/faiss/IVFlib.h +26 -2
  15. data/vendor/faiss/faiss/Index.cpp +36 -3
  16. data/vendor/faiss/faiss/Index.h +43 -6
  17. data/vendor/faiss/faiss/Index2Layer.cpp +24 -93
  18. data/vendor/faiss/faiss/Index2Layer.h +8 -17
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +610 -0
  20. data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +253 -0
  21. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +299 -0
  22. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +199 -0
  23. data/vendor/faiss/faiss/IndexBinary.cpp +20 -4
  24. data/vendor/faiss/faiss/IndexBinary.h +18 -3
  25. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +9 -2
  26. data/vendor/faiss/faiss/IndexBinaryFlat.h +4 -2
  27. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -1
  28. data/vendor/faiss/faiss/IndexBinaryFromFloat.h +2 -1
  29. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +5 -1
  30. data/vendor/faiss/faiss/IndexBinaryHNSW.h +2 -1
  31. data/vendor/faiss/faiss/IndexBinaryHash.cpp +17 -4
  32. data/vendor/faiss/faiss/IndexBinaryHash.h +8 -4
  33. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +28 -13
  34. data/vendor/faiss/faiss/IndexBinaryIVF.h +10 -7
  35. data/vendor/faiss/faiss/IndexFastScan.cpp +626 -0
  36. data/vendor/faiss/faiss/IndexFastScan.h +145 -0
  37. data/vendor/faiss/faiss/IndexFlat.cpp +52 -69
  38. data/vendor/faiss/faiss/IndexFlat.h +16 -19
  39. data/vendor/faiss/faiss/IndexFlatCodes.cpp +101 -0
  40. data/vendor/faiss/faiss/IndexFlatCodes.h +59 -0
  41. data/vendor/faiss/faiss/IndexHNSW.cpp +66 -138
  42. data/vendor/faiss/faiss/IndexHNSW.h +4 -2
  43. data/vendor/faiss/faiss/IndexIDMap.cpp +247 -0
  44. data/vendor/faiss/faiss/IndexIDMap.h +107 -0
  45. data/vendor/faiss/faiss/IndexIVF.cpp +200 -40
  46. data/vendor/faiss/faiss/IndexIVF.h +59 -22
  47. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +393 -0
  48. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +183 -0
  49. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +590 -0
  50. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +171 -0
  51. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +1290 -0
  52. data/vendor/faiss/faiss/IndexIVFFastScan.h +213 -0
  53. data/vendor/faiss/faiss/IndexIVFFlat.cpp +43 -26
  54. data/vendor/faiss/faiss/IndexIVFFlat.h +4 -2
  55. data/vendor/faiss/faiss/IndexIVFPQ.cpp +238 -53
  56. data/vendor/faiss/faiss/IndexIVFPQ.h +6 -2
  57. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +23 -852
  58. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +7 -112
  59. data/vendor/faiss/faiss/IndexIVFPQR.cpp +3 -3
  60. data/vendor/faiss/faiss/IndexIVFPQR.h +1 -1
  61. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +63 -40
  62. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +23 -7
  63. data/vendor/faiss/faiss/IndexLSH.cpp +8 -32
  64. data/vendor/faiss/faiss/IndexLSH.h +4 -16
  65. data/vendor/faiss/faiss/IndexLattice.cpp +7 -1
  66. data/vendor/faiss/faiss/IndexLattice.h +3 -1
  67. data/vendor/faiss/faiss/IndexNNDescent.cpp +4 -5
  68. data/vendor/faiss/faiss/IndexNNDescent.h +2 -1
  69. data/vendor/faiss/faiss/IndexNSG.cpp +37 -5
  70. data/vendor/faiss/faiss/IndexNSG.h +25 -1
  71. data/vendor/faiss/faiss/IndexPQ.cpp +108 -120
  72. data/vendor/faiss/faiss/IndexPQ.h +21 -22
  73. data/vendor/faiss/faiss/IndexPQFastScan.cpp +15 -450
  74. data/vendor/faiss/faiss/IndexPQFastScan.h +15 -78
  75. data/vendor/faiss/faiss/IndexPreTransform.cpp +47 -8
  76. data/vendor/faiss/faiss/IndexPreTransform.h +15 -3
  77. data/vendor/faiss/faiss/IndexRefine.cpp +36 -4
  78. data/vendor/faiss/faiss/IndexRefine.h +14 -2
  79. data/vendor/faiss/faiss/IndexReplicas.cpp +4 -2
  80. data/vendor/faiss/faiss/IndexReplicas.h +2 -1
  81. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +438 -0
  82. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +92 -0
  83. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +28 -43
  84. data/vendor/faiss/faiss/IndexScalarQuantizer.h +8 -23
  85. data/vendor/faiss/faiss/IndexShards.cpp +4 -1
  86. data/vendor/faiss/faiss/IndexShards.h +2 -1
  87. data/vendor/faiss/faiss/MetaIndexes.cpp +5 -178
  88. data/vendor/faiss/faiss/MetaIndexes.h +3 -81
  89. data/vendor/faiss/faiss/VectorTransform.cpp +45 -1
  90. data/vendor/faiss/faiss/VectorTransform.h +25 -4
  91. data/vendor/faiss/faiss/clone_index.cpp +26 -3
  92. data/vendor/faiss/faiss/clone_index.h +3 -0
  93. data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +300 -0
  94. data/vendor/faiss/faiss/cppcontrib/detail/CoarseBitType.h +24 -0
  95. data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +195 -0
  96. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +2058 -0
  97. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +408 -0
  98. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +2147 -0
  99. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMax-inl.h +460 -0
  100. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMaxFP16-inl.h +465 -0
  101. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +1618 -0
  102. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +251 -0
  103. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +1452 -0
  104. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +1 -0
  105. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +2 -6
  106. data/vendor/faiss/faiss/gpu/GpuIcmEncoder.h +60 -0
  107. data/vendor/faiss/faiss/gpu/GpuIndex.h +28 -4
  108. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +2 -1
  109. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +10 -8
  110. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +75 -14
  111. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +19 -32
  112. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +22 -31
  113. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +22 -28
  114. data/vendor/faiss/faiss/gpu/GpuResources.cpp +14 -0
  115. data/vendor/faiss/faiss/gpu/GpuResources.h +16 -3
  116. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +3 -3
  117. data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +32 -0
  118. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +1 -0
  119. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +311 -75
  120. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +10 -0
  121. data/vendor/faiss/faiss/gpu/test/TestUtils.h +3 -0
  122. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +2 -2
  123. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +5 -4
  124. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +331 -29
  125. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +110 -19
  126. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +0 -54
  127. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +0 -76
  128. data/vendor/faiss/faiss/impl/DistanceComputer.h +64 -0
  129. data/vendor/faiss/faiss/impl/HNSW.cpp +133 -32
  130. data/vendor/faiss/faiss/impl/HNSW.h +19 -16
  131. data/vendor/faiss/faiss/impl/IDSelector.cpp +125 -0
  132. data/vendor/faiss/faiss/impl/IDSelector.h +135 -0
  133. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +378 -217
  134. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +106 -29
  135. data/vendor/faiss/faiss/impl/LookupTableScaler.h +77 -0
  136. data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -0
  137. data/vendor/faiss/faiss/impl/NSG.cpp +1 -4
  138. data/vendor/faiss/faiss/impl/NSG.h +1 -1
  139. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +383 -0
  140. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +154 -0
  141. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +225 -145
  142. data/vendor/faiss/faiss/impl/ProductQuantizer.h +29 -10
  143. data/vendor/faiss/faiss/impl/Quantizer.h +43 -0
  144. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +521 -55
  145. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +94 -16
  146. data/vendor/faiss/faiss/impl/ResultHandler.h +96 -0
  147. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +108 -191
  148. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +18 -18
  149. data/vendor/faiss/faiss/impl/index_read.cpp +338 -24
  150. data/vendor/faiss/faiss/impl/index_write.cpp +300 -18
  151. data/vendor/faiss/faiss/impl/io.cpp +1 -1
  152. data/vendor/faiss/faiss/impl/io_macros.h +20 -0
  153. data/vendor/faiss/faiss/impl/kmeans1d.cpp +303 -0
  154. data/vendor/faiss/faiss/impl/kmeans1d.h +48 -0
  155. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +56 -16
  156. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +25 -8
  157. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +66 -25
  158. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +75 -27
  159. data/vendor/faiss/faiss/index_factory.cpp +772 -412
  160. data/vendor/faiss/faiss/index_factory.h +3 -0
  161. data/vendor/faiss/faiss/index_io.h +5 -0
  162. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -0
  163. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +4 -1
  164. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +2 -1
  165. data/vendor/faiss/faiss/python/python_callbacks.cpp +27 -0
  166. data/vendor/faiss/faiss/python/python_callbacks.h +15 -0
  167. data/vendor/faiss/faiss/utils/Heap.h +31 -15
  168. data/vendor/faiss/faiss/utils/distances.cpp +384 -58
  169. data/vendor/faiss/faiss/utils/distances.h +149 -18
  170. data/vendor/faiss/faiss/utils/distances_simd.cpp +776 -6
  171. data/vendor/faiss/faiss/utils/extra_distances.cpp +12 -7
  172. data/vendor/faiss/faiss/utils/extra_distances.h +3 -1
  173. data/vendor/faiss/faiss/utils/fp16-fp16c.h +21 -0
  174. data/vendor/faiss/faiss/utils/fp16-inl.h +101 -0
  175. data/vendor/faiss/faiss/utils/fp16.h +11 -0
  176. data/vendor/faiss/faiss/utils/hamming-inl.h +54 -0
  177. data/vendor/faiss/faiss/utils/hamming.cpp +0 -48
  178. data/vendor/faiss/faiss/utils/ordered_key_value.h +10 -0
  179. data/vendor/faiss/faiss/utils/quantize_lut.cpp +62 -0
  180. data/vendor/faiss/faiss/utils/quantize_lut.h +20 -0
  181. data/vendor/faiss/faiss/utils/random.cpp +53 -0
  182. data/vendor/faiss/faiss/utils/random.h +5 -0
  183. data/vendor/faiss/faiss/utils/simdlib_avx2.h +4 -0
  184. data/vendor/faiss/faiss/utils/simdlib_emulated.h +6 -1
  185. data/vendor/faiss/faiss/utils/simdlib_neon.h +7 -2
  186. data/vendor/faiss/faiss/utils/utils.h +1 -1
  187. metadata +46 -5
  188. data/vendor/faiss/faiss/IndexResidual.cpp +0 -291
  189. data/vendor/faiss/faiss/IndexResidual.h +0 -152
@@ -19,6 +19,9 @@ Index* index_factory(
19
19
  const char* description,
20
20
  MetricType metric = METRIC_L2);
21
21
 
22
+ /// set to > 0 to get more logs from index_factory
23
+ FAISS_API extern int index_factory_verbose;
24
+
22
25
  IndexBinary* index_binary_factory(int d, const char* description);
23
26
 
24
27
  } // namespace faiss
@@ -50,6 +50,8 @@ const int IO_FLAG_READ_ONLY = 2;
50
50
  const int IO_FLAG_ONDISK_SAME_DIR = 4;
51
51
  // don't load IVF data to RAM, only list sizes
52
52
  const int IO_FLAG_SKIP_IVF_DATA = 8;
53
+ // don't initialize precomputed table after loading
54
+ const int IO_FLAG_SKIP_PRECOMPUTE_TABLE = 16;
53
55
  // try to memmap data (useful to load an ArrayInvertedLists as an
54
56
  // OnDiskInvertedLists)
55
57
  const int IO_FLAG_MMAP = IO_FLAG_SKIP_IVF_DATA | 0x646f0000;
@@ -63,7 +65,10 @@ IndexBinary* read_index_binary(FILE* f, int io_flags = 0);
63
65
  IndexBinary* read_index_binary(IOReader* reader, int io_flags = 0);
64
66
 
65
67
  void write_VectorTransform(const VectorTransform* vt, const char* fname);
68
+ void write_VectorTransform(const VectorTransform* vt, IOWriter* f);
69
+
66
70
  VectorTransform* read_VectorTransform(const char* fname);
71
+ VectorTransform* read_VectorTransform(IOReader* f);
67
72
 
68
73
  ProductQuantizer* read_ProductQuantizer(const char* fname);
69
74
  ProductQuantizer* read_ProductQuantizer(IOReader* reader);
@@ -14,6 +14,7 @@
14
14
 
15
15
  #include <faiss/impl/AuxIndexStructures.h>
16
16
  #include <faiss/impl/FaissAssert.h>
17
+ #include <faiss/impl/IDSelector.h>
17
18
 
18
19
  namespace faiss {
19
20
 
@@ -28,7 +28,10 @@ InvertedLists::~InvertedLists() {}
28
28
  InvertedLists::idx_t InvertedLists::get_single_id(size_t list_no, size_t offset)
29
29
  const {
30
30
  assert(offset < list_size(list_no));
31
- return get_ids(list_no)[offset];
31
+ const idx_t* ids = get_ids(list_no);
32
+ idx_t id = ids[offset];
33
+ release_ids(list_no, ids);
34
+ return id;
32
35
  }
33
36
 
34
37
  void InvertedLists::release_codes(size_t, const uint8_t*) const {}
@@ -278,13 +278,14 @@ void OnDiskInvertedLists::do_mmap() {
278
278
  uint8_t* ptro =
279
279
  (uint8_t*)mmap(nullptr, totsize, prot, MAP_SHARED, fileno(f), 0);
280
280
 
281
+ fclose(f);
282
+
281
283
  FAISS_THROW_IF_NOT_FMT(
282
284
  ptro != MAP_FAILED,
283
285
  "could not mmap %s: %s",
284
286
  filename.c_str(),
285
287
  strerror(errno));
286
288
  ptr = ptro;
287
- fclose(f);
288
289
  }
289
290
 
290
291
  void OnDiskInvertedLists::update_totsize(size_t new_size) {
@@ -107,3 +107,30 @@ PyCallbackIOReader::~PyCallbackIOReader() {
107
107
  PyThreadLock gil;
108
108
  Py_DECREF(callback);
109
109
  }
110
+
111
+ /***********************************************************
112
+ * Callbacks for IDSelector
113
+ ***********************************************************/
114
+
115
+ PyCallbackIDSelector::PyCallbackIDSelector(PyObject* callback)
116
+ : callback(callback) {
117
+ PyThreadLock gil;
118
+ Py_INCREF(callback);
119
+ }
120
+
121
+ bool PyCallbackIDSelector::is_member(idx_t id) const {
122
+ FAISS_THROW_IF_NOT((id >> 32) == 0);
123
+ PyThreadLock gil;
124
+ PyObject* result = PyObject_CallFunction(callback, "(n)", int(id));
125
+ if (result == NULL) {
126
+ FAISS_THROW_MSG("propagate py error");
127
+ }
128
+ bool b = PyObject_IsTrue(result);
129
+ Py_DECREF(result);
130
+ return b;
131
+ }
132
+
133
+ PyCallbackIDSelector::~PyCallbackIDSelector() {
134
+ PyThreadLock gil;
135
+ Py_DECREF(callback);
136
+ }
@@ -7,6 +7,7 @@
7
7
 
8
8
  #pragma once
9
9
 
10
+ #include <faiss/impl/IDSelector.h>
10
11
  #include <faiss/impl/io.h>
11
12
  #include <faiss/invlists/InvertedLists.h>
12
13
  #include "Python.h"
@@ -43,3 +44,17 @@ struct PyCallbackIOReader : faiss::IOReader {
43
44
 
44
45
  ~PyCallbackIOReader() override;
45
46
  };
47
+
48
+ /***********************************************************
49
+ * Callbacks for IDSelector
50
+ ***********************************************************/
51
+
52
+ struct PyCallbackIDSelector : faiss::IDSelector {
53
+ PyObject* callback;
54
+
55
+ explicit PyCallbackIDSelector(PyObject* callback);
56
+
57
+ bool is_member(idx_t id) const override;
58
+
59
+ ~PyCallbackIDSelector() override;
60
+ };
@@ -47,21 +47,25 @@ inline void heap_pop(size_t k, typename C::T* bh_val, typename C::TI* bh_ids) {
47
47
  bh_val--; /* Use 1-based indexing for easier node->child translation */
48
48
  bh_ids--;
49
49
  typename C::T val = bh_val[k];
50
+ typename C::TI id = bh_ids[k];
50
51
  size_t i = 1, i1, i2;
51
52
  while (1) {
52
53
  i1 = i << 1;
53
54
  i2 = i1 + 1;
54
55
  if (i1 > k)
55
56
  break;
56
- if (i2 == k + 1 || C::cmp(bh_val[i1], bh_val[i2])) {
57
- if (C::cmp(val, bh_val[i1]))
57
+ if ((i2 == k + 1) ||
58
+ C::cmp2(bh_val[i1], bh_val[i2], bh_ids[i1], bh_ids[i2])) {
59
+ if (C::cmp2(val, bh_val[i1], id, bh_ids[i1])) {
58
60
  break;
61
+ }
59
62
  bh_val[i] = bh_val[i1];
60
63
  bh_ids[i] = bh_ids[i1];
61
64
  i = i1;
62
65
  } else {
63
- if (C::cmp(val, bh_val[i2]))
66
+ if (C::cmp2(val, bh_val[i2], id, bh_ids[i2])) {
64
67
  break;
68
+ }
65
69
  bh_val[i] = bh_val[i2];
66
70
  bh_ids[i] = bh_ids[i2];
67
71
  i = i2;
@@ -80,24 +84,28 @@ inline void heap_push(
80
84
  typename C::T* bh_val,
81
85
  typename C::TI* bh_ids,
82
86
  typename C::T val,
83
- typename C::TI ids) {
87
+ typename C::TI id) {
84
88
  bh_val--; /* Use 1-based indexing for easier node->child translation */
85
89
  bh_ids--;
86
90
  size_t i = k, i_father;
87
91
  while (i > 1) {
88
92
  i_father = i >> 1;
89
- if (!C::cmp(val, bh_val[i_father])) /* the heap structure is ok */
93
+ if (!C::cmp2(val, bh_val[i_father], id, bh_ids[i_father])) {
94
+ /* the heap structure is ok */
90
95
  break;
96
+ }
91
97
  bh_val[i] = bh_val[i_father];
92
98
  bh_ids[i] = bh_ids[i_father];
93
99
  i = i_father;
94
100
  }
95
101
  bh_val[i] = val;
96
- bh_ids[i] = ids;
102
+ bh_ids[i] = id;
97
103
  }
98
104
 
99
- /** Replace the top element from the heap defined by bh_val[0..k-1] and
100
- * bh_ids[0..k-1].
105
+ /**
106
+ * Replaces the top element from the heap defined by bh_val[0..k-1] and
107
+ * bh_ids[0..k-1], and for identical bh_val[] values also sorts by bh_ids[]
108
+ * values.
101
109
  */
102
110
  template <class C>
103
111
  inline void heap_replace_top(
@@ -105,31 +113,39 @@ inline void heap_replace_top(
105
113
  typename C::T* bh_val,
106
114
  typename C::TI* bh_ids,
107
115
  typename C::T val,
108
- typename C::TI ids) {
116
+ typename C::TI id) {
109
117
  bh_val--; /* Use 1-based indexing for easier node->child translation */
110
118
  bh_ids--;
111
119
  size_t i = 1, i1, i2;
112
120
  while (1) {
113
121
  i1 = i << 1;
114
122
  i2 = i1 + 1;
115
- if (i1 > k)
123
+ if (i1 > k) {
116
124
  break;
117
- if (i2 == k + 1 || C::cmp(bh_val[i1], bh_val[i2])) {
118
- if (C::cmp(val, bh_val[i1]))
125
+ }
126
+
127
+ // Note that C::cmp2() is a bool function answering
128
+ // `(a1 > b1) || ((a1 == b1) && (a2 > b2))` for max
129
+ // heap and same with the `<` sign for min heap.
130
+ if ((i2 == k + 1) ||
131
+ C::cmp2(bh_val[i1], bh_val[i2], bh_ids[i1], bh_ids[i2])) {
132
+ if (C::cmp2(val, bh_val[i1], id, bh_ids[i1])) {
119
133
  break;
134
+ }
120
135
  bh_val[i] = bh_val[i1];
121
136
  bh_ids[i] = bh_ids[i1];
122
137
  i = i1;
123
138
  } else {
124
- if (C::cmp(val, bh_val[i2]))
139
+ if (C::cmp2(val, bh_val[i2], id, bh_ids[i2])) {
125
140
  break;
141
+ }
126
142
  bh_val[i] = bh_val[i2];
127
143
  bh_ids[i] = bh_ids[i2];
128
144
  i = i2;
129
145
  }
130
146
  }
131
147
  bh_val[i] = val;
132
- bh_ids[i] = ids;
148
+ bh_ids[i] = id;
133
149
  }
134
150
 
135
151
  /* Partial instanciation for heaps with TI = int64_t */
@@ -294,7 +310,7 @@ inline void maxheap_addn(
294
310
  * Heap finalization (reorder elements)
295
311
  *******************************************************************/
296
312
 
297
- /* This function maps a binary heap into an sorted structure.
313
+ /* This function maps a binary heap into a sorted structure.
298
314
  It returns the number */
299
315
  template <typename C>
300
316
  inline size_t heap_reorder(