Coverage Report

Created: 2025-09-29 18:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/contrib/faiss/faiss/utils/Heap.h
Line
Count
Source
1
/*
2
 * Copyright (c) Meta Platforms, Inc. and 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
/*
9
 * C++ support for heaps. The set of functions is tailored for efficient
10
 * similarity search.
11
 *
12
 * There is no specific object for a heap, and the functions that operate on a
13
 * single heap are inlined, because heaps are often small. More complex
14
 * functions are implemented in Heaps.cpp
15
 *
16
 * All heap functions rely on a C template class that define the type of the
17
 * keys and values and their ordering (increasing with CMax and decreasing with
18
 * Cmin). The C types are defined in ordered_key_value.h
19
 */
20
21
#ifndef FAISS_Heap_h
22
#define FAISS_Heap_h
23
24
#include <climits>
25
#include <cmath>
26
#include <cstring>
27
28
#include <stdint.h>
29
#include <cassert>
30
#include <cstdio>
31
32
#include <limits>
33
#include <utility>
34
35
#include <faiss/utils/ordered_key_value.h>
36
37
namespace faiss {
38
39
/*******************************************************************
40
 * Basic heap ops: push and pop
41
 *******************************************************************/
42
43
/** Pops the top element from the heap defined by bh_val[0..k-1] and
44
 * bh_ids[0..k-1].  on output the element at k-1 is undefined.
45
 */
46
template <class C>
47
6.25k
inline void heap_pop(size_t k, typename C::T* bh_val, typename C::TI* bh_ids) {
48
6.25k
    bh_val--; /* Use 1-based indexing for easier node->child translation */
49
6.25k
    bh_ids--;
50
6.25k
    typename C::T val = bh_val[k];
51
6.25k
    typename C::TI id = bh_ids[k];
52
6.25k
    size_t i = 1, i1, i2;
53
38.4k
    while (1) {
54
38.4k
        i1 = i << 1;
55
38.4k
        i2 = i1 + 1;
56
38.4k
        if (i1 > k)
57
5.32k
            break;
58
33.1k
        if ((i2 == k + 1) ||
59
33.1k
            C::cmp2(bh_val[i1], bh_val[i2], bh_ids[i1], bh_ids[i2])) {
60
19.0k
            if (C::cmp2(val, bh_val[i1], id, bh_ids[i1])) {
61
468
                break;
62
468
            }
63
18.5k
            bh_val[i] = bh_val[i1];
64
18.5k
            bh_ids[i] = bh_ids[i1];
65
18.5k
            i = i1;
66
18.5k
        } else {
67
14.0k
            if (C::cmp2(val, bh_val[i2], id, bh_ids[i2])) {
68
466
                break;
69
466
            }
70
13.5k
            bh_val[i] = bh_val[i2];
71
13.5k
            bh_ids[i] = bh_ids[i2];
72
13.5k
            i = i2;
73
13.5k
        }
74
33.1k
    }
75
6.25k
    bh_val[i] = bh_val[k];
76
6.25k
    bh_ids[i] = bh_ids[k];
77
6.25k
}
Unexecuted instantiation: _ZN5faiss8heap_popINS_4CMinIflEEEEvmPNT_1TEPNS3_2TIE
_ZN5faiss8heap_popINS_4CMaxIflEEEEvmPNT_1TEPNS3_2TIE
Line
Count
Source
47
3.97k
inline void heap_pop(size_t k, typename C::T* bh_val, typename C::TI* bh_ids) {
48
3.97k
    bh_val--; /* Use 1-based indexing for easier node->child translation */
49
3.97k
    bh_ids--;
50
3.97k
    typename C::T val = bh_val[k];
51
3.97k
    typename C::TI id = bh_ids[k];
52
3.97k
    size_t i = 1, i1, i2;
53
27.8k
    while (1) {
54
27.8k
        i1 = i << 1;
55
27.8k
        i2 = i1 + 1;
56
27.8k
        if (i1 > k)
57
3.46k
            break;
58
24.3k
        if ((i2 == k + 1) ||
59
24.3k
            C::cmp2(bh_val[i1], bh_val[i2], bh_ids[i1], bh_ids[i2])) {
60
13.0k
            if (C::cmp2(val, bh_val[i1], id, bh_ids[i1])) {
61
267
                break;
62
267
            }
63
12.7k
            bh_val[i] = bh_val[i1];
64
12.7k
            bh_ids[i] = bh_ids[i1];
65
12.7k
            i = i1;
66
12.7k
        } else {
67
11.2k
            if (C::cmp2(val, bh_val[i2], id, bh_ids[i2])) {
68
244
                break;
69
244
            }
70
11.0k
            bh_val[i] = bh_val[i2];
71
11.0k
            bh_ids[i] = bh_ids[i2];
72
11.0k
            i = i2;
73
11.0k
        }
74
24.3k
    }
75
3.97k
    bh_val[i] = bh_val[k];
76
3.97k
    bh_ids[i] = bh_ids[k];
77
3.97k
}
_ZN5faiss8heap_popINS_4CMaxIfiEEEEvmPNT_1TEPNS3_2TIE
Line
Count
Source
47
2.28k
inline void heap_pop(size_t k, typename C::T* bh_val, typename C::TI* bh_ids) {
48
2.28k
    bh_val--; /* Use 1-based indexing for easier node->child translation */
49
2.28k
    bh_ids--;
50
2.28k
    typename C::T val = bh_val[k];
51
2.28k
    typename C::TI id = bh_ids[k];
52
2.28k
    size_t i = 1, i1, i2;
53
10.6k
    while (1) {
54
10.6k
        i1 = i << 1;
55
10.6k
        i2 = i1 + 1;
56
10.6k
        if (i1 > k)
57
1.85k
            break;
58
8.77k
        if ((i2 == k + 1) ||
59
8.77k
            C::cmp2(bh_val[i1], bh_val[i2], bh_ids[i1], bh_ids[i2])) {
60
5.99k
            if (C::cmp2(val, bh_val[i1], id, bh_ids[i1])) {
61
201
                break;
62
201
            }
63
5.79k
            bh_val[i] = bh_val[i1];
64
5.79k
            bh_ids[i] = bh_ids[i1];
65
5.79k
            i = i1;
66
5.79k
        } else {
67
2.77k
            if (C::cmp2(val, bh_val[i2], id, bh_ids[i2])) {
68
222
                break;
69
222
            }
70
2.55k
            bh_val[i] = bh_val[i2];
71
2.55k
            bh_ids[i] = bh_ids[i2];
72
2.55k
            i = i2;
73
2.55k
        }
74
8.77k
    }
75
2.28k
    bh_val[i] = bh_val[k];
76
2.28k
    bh_ids[i] = bh_ids[k];
77
2.28k
}
Unexecuted instantiation: _ZN5faiss8heap_popINS_4CMaxItiEEEEvmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss8heap_popINS_4CMinItiEEEEvmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss8heap_popINS_4CMaxItlEEEEvmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss8heap_popINS_4CMinItlEEEEvmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss8heap_popINS_4CMaxIilEEEEvmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss8heap_popINS_4CMinIilEEEEvmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss8heap_popINS_4CMinIfiEEEEvmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss8heap_popINS_4CMinIiiEEEEvmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss8heap_popINS_4CMaxIiiEEEEvmPNT_1TEPNS3_2TIE
78
79
/** Pushes the element (val, ids) into the heap bh_val[0..k-2] and
80
 * bh_ids[0..k-2].  on output the element at k-1 is defined.
81
 */
82
template <class C>
83
inline void heap_push(
84
        size_t k,
85
        typename C::T* bh_val,
86
        typename C::TI* bh_ids,
87
        typename C::T val,
88
7.26k
        typename C::TI id) {
89
7.26k
    bh_val--; /* Use 1-based indexing for easier node->child translation */
90
7.26k
    bh_ids--;
91
7.26k
    size_t i = k, i_father;
92
15.1k
    while (i > 1) {
93
14.6k
        i_father = i >> 1;
94
14.6k
        if (!C::cmp2(val, bh_val[i_father], id, bh_ids[i_father])) {
95
            /* the heap structure is ok */
96
6.77k
            break;
97
6.77k
        }
98
7.85k
        bh_val[i] = bh_val[i_father];
99
7.85k
        bh_ids[i] = bh_ids[i_father];
100
7.85k
        i = i_father;
101
7.85k
    }
102
7.26k
    bh_val[i] = val;
103
7.26k
    bh_ids[i] = id;
104
7.26k
}
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMinIflEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMaxIflEEEEvmPNT_1TEPNS3_2TIES4_S6_
_ZN5faiss9heap_pushINS_4CMaxIfiEEEEvmPNT_1TEPNS3_2TIES4_S6_
Line
Count
Source
88
7.26k
        typename C::TI id) {
89
7.26k
    bh_val--; /* Use 1-based indexing for easier node->child translation */
90
7.26k
    bh_ids--;
91
7.26k
    size_t i = k, i_father;
92
15.1k
    while (i > 1) {
93
14.6k
        i_father = i >> 1;
94
14.6k
        if (!C::cmp2(val, bh_val[i_father], id, bh_ids[i_father])) {
95
            /* the heap structure is ok */
96
6.77k
            break;
97
6.77k
        }
98
7.85k
        bh_val[i] = bh_val[i_father];
99
7.85k
        bh_ids[i] = bh_ids[i_father];
100
7.85k
        i = i_father;
101
7.85k
    }
102
7.26k
    bh_val[i] = val;
103
7.26k
    bh_ids[i] = id;
104
7.26k
}
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMaxItiEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMinItiEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMaxItlEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMinItlEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMaxIilEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMinIilEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMinIfiEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMinIiiEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss9heap_pushINS_4CMaxIiiEEEEvmPNT_1TEPNS3_2TIES4_S6_
105
106
/**
107
 * Replaces the top element from the heap defined by bh_val[0..k-1] and
108
 * bh_ids[0..k-1], and for identical bh_val[] values also sorts by bh_ids[]
109
 * values.
110
 */
111
template <class C>
112
inline void heap_replace_top(
113
        size_t k,
114
        typename C::T* bh_val,
115
        typename C::TI* bh_ids,
116
        typename C::T val,
117
3.75k
        typename C::TI id) {
118
3.75k
    bh_val--; /* Use 1-based indexing for easier node->child translation */
119
3.75k
    bh_ids--;
120
3.75k
    size_t i = 1, i1, i2;
121
28.4k
    while (1) {
122
28.4k
        i1 = i << 1;
123
28.4k
        i2 = i1 + 1;
124
28.4k
        if (i1 > k) {
125
2.87k
            break;
126
2.87k
        }
127
128
        // Note that C::cmp2() is a bool function answering
129
        // `(a1 > b1) || ((a1 == b1) && (a2 > b2))` for max
130
        // heap and same with the `<` sign for min heap.
131
25.5k
        if ((i2 == k + 1) ||
132
25.5k
            C::cmp2(bh_val[i1], bh_val[i2], bh_ids[i1], bh_ids[i2])) {
133
12.9k
            if (C::cmp2(val, bh_val[i1], id, bh_ids[i1])) {
134
479
                break;
135
479
            }
136
12.5k
            bh_val[i] = bh_val[i1];
137
12.5k
            bh_ids[i] = bh_ids[i1];
138
12.5k
            i = i1;
139
12.6k
        } else {
140
12.6k
            if (C::cmp2(val, bh_val[i2], id, bh_ids[i2])) {
141
409
                break;
142
409
            }
143
12.2k
            bh_val[i] = bh_val[i2];
144
12.2k
            bh_ids[i] = bh_ids[i2];
145
12.2k
            i = i2;
146
12.2k
        }
147
25.5k
    }
148
3.75k
    bh_val[i] = val;
149
3.75k
    bh_ids[i] = id;
150
3.75k
}
Unexecuted instantiation: _ZN5faiss16heap_replace_topINS_4CMinIflEEEEvmPNT_1TEPNS3_2TIES4_S6_
_ZN5faiss16heap_replace_topINS_4CMaxIflEEEEvmPNT_1TEPNS3_2TIES4_S6_
Line
Count
Source
117
3.75k
        typename C::TI id) {
118
3.75k
    bh_val--; /* Use 1-based indexing for easier node->child translation */
119
3.75k
    bh_ids--;
120
3.75k
    size_t i = 1, i1, i2;
121
28.4k
    while (1) {
122
28.4k
        i1 = i << 1;
123
28.4k
        i2 = i1 + 1;
124
28.4k
        if (i1 > k) {
125
2.87k
            break;
126
2.87k
        }
127
128
        // Note that C::cmp2() is a bool function answering
129
        // `(a1 > b1) || ((a1 == b1) && (a2 > b2))` for max
130
        // heap and same with the `<` sign for min heap.
131
25.5k
        if ((i2 == k + 1) ||
132
25.5k
            C::cmp2(bh_val[i1], bh_val[i2], bh_ids[i1], bh_ids[i2])) {
133
12.9k
            if (C::cmp2(val, bh_val[i1], id, bh_ids[i1])) {
134
479
                break;
135
479
            }
136
12.5k
            bh_val[i] = bh_val[i1];
137
12.5k
            bh_ids[i] = bh_ids[i1];
138
12.5k
            i = i1;
139
12.6k
        } else {
140
12.6k
            if (C::cmp2(val, bh_val[i2], id, bh_ids[i2])) {
141
409
                break;
142
409
            }
143
12.2k
            bh_val[i] = bh_val[i2];
144
12.2k
            bh_ids[i] = bh_ids[i2];
145
12.2k
            i = i2;
146
12.2k
        }
147
25.5k
    }
148
3.75k
    bh_val[i] = val;
149
3.75k
    bh_ids[i] = id;
150
3.75k
}
Unexecuted instantiation: _ZN5faiss16heap_replace_topINS_4CMaxIfiEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss16heap_replace_topINS_4CMaxItiEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss16heap_replace_topINS_4CMinItiEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss16heap_replace_topINS_4CMaxItlEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss16heap_replace_topINS_4CMinItlEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss16heap_replace_topINS_4CMaxIilEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss16heap_replace_topINS_4CMinIfiEEEEvmPNT_1TEPNS3_2TIES4_S6_
Unexecuted instantiation: _ZN5faiss16heap_replace_topINS_4CMinIilEEEEvmPNT_1TEPNS3_2TIES4_S6_
151
152
/* Partial instanciation for heaps with TI = int64_t */
153
154
template <typename T>
155
inline void minheap_pop(size_t k, T* bh_val, int64_t* bh_ids) {
156
    heap_pop<CMin<T, int64_t>>(k, bh_val, bh_ids);
157
}
158
159
template <typename T>
160
inline void minheap_push(
161
        size_t k,
162
        T* bh_val,
163
        int64_t* bh_ids,
164
        T val,
165
        int64_t ids) {
166
    heap_push<CMin<T, int64_t>>(k, bh_val, bh_ids, val, ids);
167
}
168
169
template <typename T>
170
inline void minheap_replace_top(
171
        size_t k,
172
        T* bh_val,
173
        int64_t* bh_ids,
174
        T val,
175
0
        int64_t ids) {
176
0
    heap_replace_top<CMin<T, int64_t>>(k, bh_val, bh_ids, val, ids);
177
0
}
178
179
template <typename T>
180
inline void maxheap_pop(size_t k, T* bh_val, int64_t* bh_ids) {
181
    heap_pop<CMax<T, int64_t>>(k, bh_val, bh_ids);
182
}
183
184
template <typename T>
185
inline void maxheap_push(
186
        size_t k,
187
        T* bh_val,
188
        int64_t* bh_ids,
189
        T val,
190
0
        int64_t ids) {
191
0
    heap_push<CMax<T, int64_t>>(k, bh_val, bh_ids, val, ids);
192
0
}
193
194
template <typename T>
195
inline void maxheap_replace_top(
196
        size_t k,
197
        T* bh_val,
198
        int64_t* bh_ids,
199
        T val,
200
0
        int64_t ids) {
201
0
    heap_replace_top<CMax<T, int64_t>>(k, bh_val, bh_ids, val, ids);
202
0
}
Unexecuted instantiation: _ZN5faiss19maxheap_replace_topIfEEvmPT_PlS1_l
Unexecuted instantiation: _ZN5faiss19maxheap_replace_topIiEEvmPT_PlS1_l
203
204
/*******************************************************************
205
 * Basic heap<std:pair<>> ops: push and pop
206
 *******************************************************************/
207
208
// This section contains a heap implementation that works with
209
//   std::pair<Priority, Value> elements.
210
211
/** Pops the top element from the heap defined by bh_val[0..k-1] and
212
 * bh_ids[0..k-1].  on output the element at k-1 is undefined.
213
 */
214
template <class C>
215
inline void heap_pop(size_t k, std::pair<typename C::T, typename C::TI>* bh) {
216
    bh--; /* Use 1-based indexing for easier node->child translation */
217
    typename C::T val = bh[k].first;
218
    typename C::TI id = bh[k].second;
219
    size_t i = 1, i1, i2;
220
    while (1) {
221
        i1 = i << 1;
222
        i2 = i1 + 1;
223
        if (i1 > k)
224
            break;
225
        if ((i2 == k + 1) ||
226
            C::cmp2(bh[i1].first, bh[i2].first, bh[i1].second, bh[i2].second)) {
227
            if (C::cmp2(val, bh[i1].first, id, bh[i1].second)) {
228
                break;
229
            }
230
            bh[i] = bh[i1];
231
            i = i1;
232
        } else {
233
            if (C::cmp2(val, bh[i2].first, id, bh[i2].second)) {
234
                break;
235
            }
236
            bh[i] = bh[i2];
237
            i = i2;
238
        }
239
    }
240
    bh[i] = bh[k];
241
}
242
243
/** Pushes the element (val, ids) into the heap bh_val[0..k-2] and
244
 * bh_ids[0..k-2].  on output the element at k-1 is defined.
245
 */
246
template <class C>
247
inline void heap_push(
248
        size_t k,
249
        std::pair<typename C::T, typename C::TI>* bh,
250
        typename C::T val,
251
        typename C::TI id) {
252
    bh--; /* Use 1-based indexing for easier node->child translation */
253
    size_t i = k, i_father;
254
    while (i > 1) {
255
        i_father = i >> 1;
256
        auto bh_v = bh[i_father];
257
        if (!C::cmp2(val, bh_v.first, id, bh_v.second)) {
258
            /* the heap structure is ok */
259
            break;
260
        }
261
        bh[i] = bh_v;
262
        i = i_father;
263
    }
264
    bh[i] = std::make_pair(val, id);
265
}
266
267
/**
268
 * Replaces the top element from the heap defined by bh_val[0..k-1] and
269
 * bh_ids[0..k-1], and for identical bh_val[] values also sorts by bh_ids[]
270
 * values.
271
 */
272
template <class C>
273
inline void heap_replace_top(
274
        size_t k,
275
        std::pair<typename C::T, typename C::TI>* bh,
276
        typename C::T val,
277
        typename C::TI id) {
278
    bh--; /* Use 1-based indexing for easier node->child translation */
279
    size_t i = 1, i1, i2;
280
    while (1) {
281
        i1 = i << 1;
282
        i2 = i1 + 1;
283
        if (i1 > k) {
284
            break;
285
        }
286
287
        // Note that C::cmp2() is a bool function answering
288
        // `(a1 > b1) || ((a1 == b1) && (a2 > b2))` for max
289
        // heap and same with the `<` sign for min heap.
290
        if ((i2 == k + 1) ||
291
            C::cmp2(bh[i1].first, bh[i2].first, bh[i1].second, bh[i2].second)) {
292
            if (C::cmp2(val, bh[i1].first, id, bh[i1].second)) {
293
                break;
294
            }
295
            bh[i] = bh[i1];
296
            i = i1;
297
        } else {
298
            if (C::cmp2(val, bh[i2].first, id, bh[i2].second)) {
299
                break;
300
            }
301
            bh[i] = bh[i2];
302
            i = i2;
303
        }
304
    }
305
    bh[i] = std::make_pair(val, id);
306
}
307
308
/*******************************************************************
309
 * Heap initialization
310
 *******************************************************************/
311
312
/* Initialization phase for the heap (with unconditionnal pushes).
313
 * Store k0 elements in a heap containing up to k values. Note that
314
 * (bh_val, bh_ids) can be the same as (x, ids) */
315
template <class C>
316
inline void heap_heapify(
317
        size_t k,
318
        typename C::T* bh_val,
319
        typename C::TI* bh_ids,
320
        const typename C::T* x = nullptr,
321
        const typename C::TI* ids = nullptr,
322
37
        size_t k0 = 0) {
323
37
    if (k0 > 0)
324
37
        assert(x);
325
326
37
    if (ids) {
327
0
        for (size_t i = 0; i < k0; i++)
328
0
            heap_push<C>(i + 1, bh_val, bh_ids, x[i], ids[i]);
329
37
    } else {
330
37
        for (size_t i = 0; i < k0; i++)
331
0
            heap_push<C>(i + 1, bh_val, bh_ids, x[i], i);
332
37
    }
333
334
4.01k
    for (size_t i = k0; i < k; i++) {
335
3.97k
        bh_val[i] = C::neutral();
336
3.97k
        bh_ids[i] = -1;
337
3.97k
    }
338
37
}
Unexecuted instantiation: _ZN5faiss12heap_heapifyINS_4CMinIflEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
_ZN5faiss12heap_heapifyINS_4CMaxIflEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
Line
Count
Source
322
37
        size_t k0 = 0) {
323
37
    if (k0 > 0)
324
37
        assert(x);
325
326
37
    if (ids) {
327
0
        for (size_t i = 0; i < k0; i++)
328
0
            heap_push<C>(i + 1, bh_val, bh_ids, x[i], ids[i]);
329
37
    } else {
330
37
        for (size_t i = 0; i < k0; i++)
331
0
            heap_push<C>(i + 1, bh_val, bh_ids, x[i], i);
332
37
    }
333
334
4.01k
    for (size_t i = k0; i < k; i++) {
335
3.97k
        bh_val[i] = C::neutral();
336
3.97k
        bh_ids[i] = -1;
337
3.97k
    }
338
37
}
Unexecuted instantiation: _ZN5faiss12heap_heapifyINS_4CMaxItiEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
Unexecuted instantiation: _ZN5faiss12heap_heapifyINS_4CMinItiEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
Unexecuted instantiation: _ZN5faiss12heap_heapifyINS_4CMaxItlEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
Unexecuted instantiation: _ZN5faiss12heap_heapifyINS_4CMinItlEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
Unexecuted instantiation: _ZN5faiss12heap_heapifyINS_4CMaxIilEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
Unexecuted instantiation: _ZN5faiss12heap_heapifyINS_4CMinIilEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
Unexecuted instantiation: _ZN5faiss12heap_heapifyINS_4CMinIfiEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
Unexecuted instantiation: _ZN5faiss12heap_heapifyINS_4CMaxIfiEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
339
340
template <typename T>
341
inline void minheap_heapify(
342
        size_t k,
343
        T* bh_val,
344
        int64_t* bh_ids,
345
        const T* x = nullptr,
346
        const int64_t* ids = nullptr,
347
0
        size_t k0 = 0) {
348
0
    heap_heapify<CMin<T, int64_t>>(k, bh_val, bh_ids, x, ids, k0);
349
0
}
350
351
template <typename T>
352
inline void maxheap_heapify(
353
        size_t k,
354
        T* bh_val,
355
        int64_t* bh_ids,
356
        const T* x = nullptr,
357
        const int64_t* ids = nullptr,
358
0
        size_t k0 = 0) {
359
0
    heap_heapify<CMax<T, int64_t>>(k, bh_val, bh_ids, x, ids, k0);
360
0
}
361
362
/*******************************************************************
363
 * Add n elements to the heap
364
 *******************************************************************/
365
366
/* Add some elements to the heap  */
367
template <class C>
368
inline void heap_addn(
369
        size_t k,
370
        typename C::T* bh_val,
371
        typename C::TI* bh_ids,
372
        const typename C::T* x,
373
        const typename C::TI* ids,
374
0
        size_t n) {
375
0
    size_t i;
376
0
    if (ids)
377
0
        for (i = 0; i < n; i++) {
378
0
            if (C::cmp(bh_val[0], x[i])) {
379
0
                heap_replace_top<C>(k, bh_val, bh_ids, x[i], ids[i]);
380
0
            }
381
0
        }
382
0
    else
383
0
        for (i = 0; i < n; i++) {
384
0
            if (C::cmp(bh_val[0], x[i])) {
385
0
                heap_replace_top<C>(k, bh_val, bh_ids, x[i], i);
386
0
            }
387
0
        }
388
0
}
Unexecuted instantiation: _ZN5faiss9heap_addnINS_4CMinIflEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
Unexecuted instantiation: _ZN5faiss9heap_addnINS_4CMaxIflEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
Unexecuted instantiation: _ZN5faiss9heap_addnINS_4CMaxIfiEEEEvmPNT_1TEPNS3_2TIEPKS4_PKS6_m
389
390
/* Partial instanciation for heaps with TI = int64_t */
391
392
template <typename T>
393
inline void minheap_addn(
394
        size_t k,
395
        T* bh_val,
396
        int64_t* bh_ids,
397
        const T* x,
398
        const int64_t* ids,
399
0
        size_t n) {
400
0
    heap_addn<CMin<T, int64_t>>(k, bh_val, bh_ids, x, ids, n);
401
0
}
402
403
template <typename T>
404
inline void maxheap_addn(
405
        size_t k,
406
        T* bh_val,
407
        int64_t* bh_ids,
408
        const T* x,
409
        const int64_t* ids,
410
        size_t n) {
411
    heap_addn<CMax<T, int64_t>>(k, bh_val, bh_ids, x, ids, n);
412
}
413
414
/*******************************************************************
415
 * Heap finalization (reorder elements)
416
 *******************************************************************/
417
418
/* This function maps a binary heap into a sorted structure.
419
   It returns the number  */
420
template <typename C>
421
inline size_t heap_reorder(
422
        size_t k,
423
        typename C::T* bh_val,
424
37
        typename C::TI* bh_ids) {
425
37
    size_t i, ii;
426
427
4.01k
    for (i = 0, ii = 0; i < k; i++) {
428
        /* top element should be put at the end of the list */
429
3.97k
        typename C::T val = bh_val[0];
430
3.97k
        typename C::TI id = bh_ids[0];
431
432
        /* boundary case: we will over-ride this value if not a true element */
433
3.97k
        heap_pop<C>(k - i, bh_val, bh_ids);
434
3.97k
        bh_val[k - ii - 1] = val;
435
3.97k
        bh_ids[k - ii - 1] = id;
436
3.97k
        if (id != -1)
437
3.30k
            ii++;
438
3.97k
    }
439
    /* Count the number of elements which are effectively returned */
440
37
    size_t nel = ii;
441
442
37
    memmove(bh_val, bh_val + k - ii, ii * sizeof(*bh_val));
443
37
    memmove(bh_ids, bh_ids + k - ii, ii * sizeof(*bh_ids));
444
445
712
    for (; ii < k; ii++) {
446
675
        bh_val[ii] = C::neutral();
447
675
        bh_ids[ii] = -1;
448
675
    }
449
37
    return nel;
450
37
}
Unexecuted instantiation: _ZN5faiss12heap_reorderINS_4CMinIflEEEEmmPNT_1TEPNS3_2TIE
_ZN5faiss12heap_reorderINS_4CMaxIflEEEEmmPNT_1TEPNS3_2TIE
Line
Count
Source
424
37
        typename C::TI* bh_ids) {
425
37
    size_t i, ii;
426
427
4.01k
    for (i = 0, ii = 0; i < k; i++) {
428
        /* top element should be put at the end of the list */
429
3.97k
        typename C::T val = bh_val[0];
430
3.97k
        typename C::TI id = bh_ids[0];
431
432
        /* boundary case: we will over-ride this value if not a true element */
433
3.97k
        heap_pop<C>(k - i, bh_val, bh_ids);
434
3.97k
        bh_val[k - ii - 1] = val;
435
3.97k
        bh_ids[k - ii - 1] = id;
436
3.97k
        if (id != -1)
437
3.30k
            ii++;
438
3.97k
    }
439
    /* Count the number of elements which are effectively returned */
440
37
    size_t nel = ii;
441
442
37
    memmove(bh_val, bh_val + k - ii, ii * sizeof(*bh_val));
443
37
    memmove(bh_ids, bh_ids + k - ii, ii * sizeof(*bh_ids));
444
445
712
    for (; ii < k; ii++) {
446
675
        bh_val[ii] = C::neutral();
447
675
        bh_ids[ii] = -1;
448
675
    }
449
37
    return nel;
450
37
}
Unexecuted instantiation: _ZN5faiss12heap_reorderINS_4CMaxItiEEEEmmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss12heap_reorderINS_4CMinItiEEEEmmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss12heap_reorderINS_4CMaxItlEEEEmmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss12heap_reorderINS_4CMinItlEEEEmmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss12heap_reorderINS_4CMaxIilEEEEmmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss12heap_reorderINS_4CMinIilEEEEmmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss12heap_reorderINS_4CMaxIfiEEEEmmPNT_1TEPNS3_2TIE
Unexecuted instantiation: _ZN5faiss12heap_reorderINS_4CMinIfiEEEEmmPNT_1TEPNS3_2TIE
451
452
template <typename T>
453
0
inline size_t minheap_reorder(size_t k, T* bh_val, int64_t* bh_ids) {
454
0
    return heap_reorder<CMin<T, int64_t>>(k, bh_val, bh_ids);
455
0
}
456
457
template <typename T>
458
0
inline size_t maxheap_reorder(size_t k, T* bh_val, int64_t* bh_ids) {
459
0
    return heap_reorder<CMax<T, int64_t>>(k, bh_val, bh_ids);
460
0
}
461
462
/*******************************************************************
463
 * Operations on heap arrays
464
 *******************************************************************/
465
466
/** a template structure for a set of [min|max]-heaps it is tailored
467
 * so that the actual data of the heaps can just live in compact
468
 * arrays.
469
 */
470
template <typename C>
471
struct HeapArray {
472
    typedef typename C::TI TI;
473
    typedef typename C::T T;
474
475
    size_t nh; ///< number of heaps
476
    size_t k;  ///< allocated size per heap
477
    TI* ids;   ///< identifiers (size nh * k)
478
    T* val;    ///< values (distances or similarities), size nh * k
479
480
    /// Return the list of values for a heap
481
0
    T* get_val(size_t key) {
482
0
        return val + key * k;
483
0
    }
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMinIflEEE7get_valEm
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMaxIflEEE7get_valEm
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMinIfiEEE7get_valEm
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMaxIfiEEE7get_valEm
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMinIilEEE7get_valEm
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMaxIilEEE7get_valEm
484
485
    /// Correspponding identifiers
486
0
    TI* get_ids(size_t key) {
487
0
        return ids + key * k;
488
0
    }
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMinIflEEE7get_idsEm
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMaxIflEEE7get_idsEm
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMinIfiEEE7get_idsEm
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMaxIfiEEE7get_idsEm
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMinIilEEE7get_idsEm
Unexecuted instantiation: _ZN5faiss9HeapArrayINS_4CMaxIilEEE7get_idsEm
489
490
    /// prepare all the heaps before adding
491
    void heapify();
492
493
    /** add nj elements to heaps i0:i0+ni, with sequential ids
494
     *
495
     * @param nj    nb of elements to add to each heap
496
     * @param vin   elements to add, size ni * nj
497
     * @param j0    add this to the ids that are added
498
     * @param i0    first heap to update
499
     * @param ni    nb of elements to update (-1 = use nh)
500
     */
501
    void addn(
502
            size_t nj,
503
            const T* vin,
504
            TI j0 = 0,
505
            size_t i0 = 0,
506
            int64_t ni = -1);
507
508
    /** same as addn
509
     *
510
     * @param id_in     ids of the elements to add, size ni * nj
511
     * @param id_stride stride for id_in
512
     */
513
    void addn_with_ids(
514
            size_t nj,
515
            const T* vin,
516
            const TI* id_in = nullptr,
517
            int64_t id_stride = 0,
518
            size_t i0 = 0,
519
            int64_t ni = -1);
520
521
    /** same as addn_with_ids, but for just a subset of queries
522
     *
523
     * @param nsubset  number of query entries to update
524
     * @param subset   indexes of queries to update, in 0..nh-1, size nsubset
525
     */
526
    void addn_query_subset_with_ids(
527
            size_t nsubset,
528
            const TI* subset,
529
            size_t nj,
530
            const T* vin,
531
            const TI* id_in = nullptr,
532
            int64_t id_stride = 0);
533
534
    /// reorder all the heaps
535
    void reorder();
536
537
    /** this is not really a heap function. It just finds the per-line
538
     *   extrema of each line of array D
539
     * @param vals_out    extreme value of each line (size nh, or NULL)
540
     * @param idx_out     index of extreme value (size nh or NULL)
541
     */
542
    void per_line_extrema(T* vals_out, TI* idx_out) const;
543
};
544
545
/* Define useful heaps */
546
typedef HeapArray<CMin<float, int64_t>> float_minheap_array_t;
547
typedef HeapArray<CMin<int, int64_t>> int_minheap_array_t;
548
549
typedef HeapArray<CMax<float, int64_t>> float_maxheap_array_t;
550
typedef HeapArray<CMax<int, int64_t>> int_maxheap_array_t;
551
552
// The heap templates are instantiated explicitly in Heap.cpp
553
554
/*********************************************************************
555
 * Indirect heaps: instead of having
556
 *
557
 *          node i = (bh_ids[i], bh_val[i]),
558
 *
559
 * in indirect heaps,
560
 *
561
 *          node i = (bh_ids[i], bh_val[bh_ids[i]]),
562
 *
563
 *********************************************************************/
564
565
template <class C>
566
inline void indirect_heap_pop(
567
        size_t k,
568
        const typename C::T* bh_val,
569
0
        typename C::TI* bh_ids) {
570
0
    bh_ids--; /* Use 1-based indexing for easier node->child translation */
571
0
    typename C::T val = bh_val[bh_ids[k]];
572
0
    size_t i = 1;
573
0
    while (1) {
574
0
        size_t i1 = i << 1;
575
0
        size_t i2 = i1 + 1;
576
0
        if (i1 > k)
577
0
            break;
578
0
        typename C::TI id1 = bh_ids[i1], id2 = bh_ids[i2];
579
0
        if (i2 == k + 1 || C::cmp(bh_val[id1], bh_val[id2])) {
580
0
            if (C::cmp(val, bh_val[id1]))
581
0
                break;
582
0
            bh_ids[i] = id1;
583
0
            i = i1;
584
0
        } else {
585
0
            if (C::cmp(val, bh_val[id2]))
586
0
                break;
587
0
            bh_ids[i] = id2;
588
0
            i = i2;
589
0
        }
590
0
    }
591
0
    bh_ids[i] = bh_ids[k];
592
0
}
593
594
template <class C>
595
inline void indirect_heap_push(
596
        size_t k,
597
        const typename C::T* bh_val,
598
        typename C::TI* bh_ids,
599
0
        typename C::TI id) {
600
0
    bh_ids--; /* Use 1-based indexing for easier node->child translation */
601
0
    typename C::T val = bh_val[id];
602
0
    size_t i = k;
603
0
    while (i > 1) {
604
0
        size_t i_father = i >> 1;
605
0
        if (!C::cmp(val, bh_val[bh_ids[i_father]]))
606
0
            break;
607
0
        bh_ids[i] = bh_ids[i_father];
608
0
        i = i_father;
609
0
    }
610
0
    bh_ids[i] = id;
611
0
}
612
613
/** Merge result tables from several shards. The per-shard results are assumed
614
 * to be sorted. Note that the C comparator is reversed w.r.t. the usual top-k
615
 * element heap because we want the best (ie. lowest for L2) result to be on
616
 * top, not the worst. Also, it needs to hold an index of a shard id (ie.
617
 * usually int32 is more than enough).
618
 *
619
 * @param all_distances  size (nshard, n, k)
620
 * @param all_labels     size (nshard, n, k)
621
 * @param distances      output distances, size (n, k)
622
 * @param labels         output labels, size (n, k)
623
 */
624
template <class idx_t, class C>
625
void merge_knn_results(
626
        size_t n,
627
        size_t k,
628
        typename C::TI nshard,
629
        const typename C::T* all_distances,
630
        const idx_t* all_labels,
631
        typename C::T* distances,
632
        idx_t* labels);
633
634
} // namespace faiss
635
636
#endif /* FAISS_Heap_h */