Coverage Report

Created: 2025-10-14 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/contrib/faiss/faiss/IndexBinaryHash.cpp
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
// -*- c++ -*-
9
10
#include <faiss/IndexBinaryHash.h>
11
12
#include <cinttypes>
13
#include <cstdio>
14
#include <memory>
15
#include <unordered_set>
16
17
#include <faiss/utils/hamming.h>
18
#include <faiss/utils/utils.h>
19
20
#include <faiss/impl/AuxIndexStructures.h>
21
#include <faiss/impl/FaissAssert.h>
22
23
namespace faiss {
24
25
void IndexBinaryHash::InvertedList::add(
26
        idx_t id,
27
        size_t code_size,
28
0
        const uint8_t* code) {
29
0
    ids.push_back(id);
30
0
    vecs.insert(vecs.end(), code, code + code_size);
31
0
}
32
33
IndexBinaryHash::IndexBinaryHash(int d, int b)
34
0
        : IndexBinary(d), b(b), nflip(0) {
35
0
    is_trained = true;
36
0
}
37
38
0
IndexBinaryHash::IndexBinaryHash() : b(0), nflip(0) {
39
0
    is_trained = true;
40
0
}
41
42
0
void IndexBinaryHash::reset() {
43
0
    invlists.clear();
44
0
    ntotal = 0;
45
0
}
46
47
0
void IndexBinaryHash::add(idx_t n, const uint8_t* x) {
48
0
    add_with_ids(n, x, nullptr);
49
0
}
50
51
void IndexBinaryHash::add_with_ids(
52
        idx_t n,
53
        const uint8_t* x,
54
0
        const idx_t* xids) {
55
0
    uint64_t mask = ((uint64_t)1 << b) - 1;
56
    // simplistic add function. Cannot really be parallelized.
57
58
0
    for (idx_t i = 0; i < n; i++) {
59
0
        idx_t id = xids ? xids[i] : ntotal + i;
60
0
        const uint8_t* xi = x + i * code_size;
61
0
        idx_t hash = *((uint64_t*)xi) & mask;
62
0
        invlists[hash].add(id, code_size, xi);
63
0
    }
64
0
    ntotal += n;
65
0
}
66
67
namespace {
68
69
/** Enumerate all bit vectors of size nbit with up to maxflip 1s
70
 * test in P127257851 P127258235
71
 */
72
struct FlipEnumerator {
73
    int nbit, nflip, maxflip;
74
    uint64_t mask, x;
75
76
0
    FlipEnumerator(int nbit, int maxflip) : nbit(nbit), maxflip(maxflip) {
77
0
        nflip = 0;
78
0
        mask = 0;
79
0
        x = 0;
80
0
    }
81
82
0
    bool next() {
83
0
        if (x == mask) {
84
0
            if (nflip == maxflip) {
85
0
                return false;
86
0
            }
87
            // increase Hamming radius
88
0
            nflip++;
89
0
            mask = (((uint64_t)1 << nflip) - 1);
90
0
            x = mask << (nbit - nflip);
91
0
            return true;
92
0
        }
93
94
0
        int i = __builtin_ctzll(x);
95
96
0
        if (i > 0) {
97
0
            x ^= (uint64_t)3 << (i - 1);
98
0
        } else {
99
            // nb of LSB 1s
100
0
            int n1 = __builtin_ctzll(~x);
101
            // clear them
102
0
            x &= ((uint64_t)(-1) << n1);
103
0
            int n2 = __builtin_ctzll(x);
104
0
            x ^= (((uint64_t)1 << (n1 + 2)) - 1) << (n2 - n1 - 1);
105
0
        }
106
0
        return true;
107
0
    }
108
};
109
110
struct RangeSearchResults {
111
    int radius;
112
    RangeQueryResult& qres;
113
114
0
    inline void add(float dis, idx_t id) {
115
0
        if (dis < radius) {
116
0
            qres.add(dis, id);
117
0
        }
118
0
    }
119
};
120
121
struct KnnSearchResults {
122
    // heap params
123
    idx_t k;
124
    int32_t* heap_sim;
125
    idx_t* heap_ids;
126
127
    using C = CMax<int, idx_t>;
128
129
0
    inline void add(float dis, idx_t id) {
130
0
        if (dis < heap_sim[0]) {
131
0
            heap_replace_top<C>(k, heap_sim, heap_ids, dis, id);
132
0
        }
133
0
    }
134
};
135
136
template <class HammingComputer, class SearchResults>
137
void search_single_query_template(
138
        const IndexBinaryHash& index,
139
        const uint8_t* q,
140
        SearchResults& res,
141
        size_t& n0,
142
        size_t& nlist,
143
0
        size_t& ndis) {
144
0
    size_t code_size = index.code_size;
145
0
    uint64_t mask = ((uint64_t)1 << index.b) - 1;
146
0
    uint64_t qhash = *((uint64_t*)q) & mask;
147
0
    HammingComputer hc(q, code_size);
148
0
    FlipEnumerator fe(index.b, index.nflip);
149
150
    // loop over neighbors that are at most at nflip bits
151
0
    do {
152
0
        uint64_t hash = qhash ^ fe.x;
153
0
        auto it = index.invlists.find(hash);
154
155
0
        if (it == index.invlists.end()) {
156
0
            continue;
157
0
        }
158
159
0
        const IndexBinaryHash::InvertedList& il = it->second;
160
161
0
        size_t nv = il.ids.size();
162
163
0
        if (nv == 0) {
164
0
            n0++;
165
0
        } else {
166
0
            const uint8_t* codes = il.vecs.data();
167
0
            for (size_t i = 0; i < nv; i++) {
168
0
                int dis = hc.hamming(codes);
169
0
                res.add(dis, il.ids[i]);
170
0
                codes += code_size;
171
0
            }
172
0
            ndis += nv;
173
0
            nlist++;
174
0
        }
175
0
    } while (fe.next());
176
0
}
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_16HammingComputer4ENS0_18RangeSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_16HammingComputer8ENS0_18RangeSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_17HammingComputer16ENS0_18RangeSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_17HammingComputer20ENS0_18RangeSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_17HammingComputer32ENS0_18RangeSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_17HammingComputer64ENS0_18RangeSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_22HammingComputerDefaultENS0_18RangeSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_16HammingComputer4ENS0_16KnnSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_16HammingComputer8ENS0_16KnnSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_17HammingComputer16ENS0_16KnnSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_17HammingComputer20ENS0_16KnnSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_17HammingComputer32ENS0_16KnnSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_17HammingComputer64ENS0_16KnnSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_128search_single_query_templateINS_22HammingComputerDefaultENS0_16KnnSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT0_RmSB_SB_
177
178
struct Run_search_single_query {
179
    using T = void;
180
    template <class HammingComputer, class... Types>
181
0
    T f(Types... args) {
182
0
        search_single_query_template<HammingComputer>(args...);
183
0
    }
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_16HammingComputer4EJNS_15IndexBinaryHashEPKhNS0_18RangeSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_16HammingComputer8EJNS_15IndexBinaryHashEPKhNS0_18RangeSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_17HammingComputer16EJNS_15IndexBinaryHashEPKhNS0_18RangeSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_17HammingComputer20EJNS_15IndexBinaryHashEPKhNS0_18RangeSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_17HammingComputer32EJNS_15IndexBinaryHashEPKhNS0_18RangeSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_17HammingComputer64EJNS_15IndexBinaryHashEPKhNS0_18RangeSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_22HammingComputerDefaultEJNS_15IndexBinaryHashEPKhNS0_18RangeSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_16HammingComputer4EJNS_15IndexBinaryHashEPKhNS0_16KnnSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_16HammingComputer8EJNS_15IndexBinaryHashEPKhNS0_16KnnSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_17HammingComputer16EJNS_15IndexBinaryHashEPKhNS0_16KnnSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_17HammingComputer20EJNS_15IndexBinaryHashEPKhNS0_16KnnSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_17HammingComputer32EJNS_15IndexBinaryHashEPKhNS0_16KnnSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_17HammingComputer64EJNS_15IndexBinaryHashEPKhNS0_16KnnSearchResultsEmmmEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_123Run_search_single_query1fINS_22HammingComputerDefaultEJNS_15IndexBinaryHashEPKhNS0_16KnnSearchResultsEmmmEEEvDpT0_
184
};
185
186
template <class SearchResults>
187
void search_single_query(
188
        const IndexBinaryHash& index,
189
        const uint8_t* q,
190
        SearchResults& res,
191
        size_t& n0,
192
        size_t& nlist,
193
0
        size_t& ndis) {
194
0
    Run_search_single_query r;
195
0
    dispatch_HammingComputer(
196
0
            index.code_size, r, index, q, res, n0, nlist, ndis);
197
0
}
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_119search_single_queryINS0_18RangeSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT_RmSA_SA_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_119search_single_queryINS0_16KnnSearchResultsEEEvRKNS_15IndexBinaryHashEPKhRT_RmSA_SA_
198
199
} // anonymous namespace
200
201
void IndexBinaryHash::range_search(
202
        idx_t n,
203
        const uint8_t* x,
204
        int radius,
205
        RangeSearchResult* result,
206
0
        const SearchParameters* params) const {
207
0
    FAISS_THROW_IF_NOT_MSG(
208
0
            !params, "search params not supported for this index");
209
0
    size_t nlist = 0, ndis = 0, n0 = 0;
210
211
0
#pragma omp parallel if (n > 100) reduction(+ : ndis, n0, nlist)
212
0
    {
213
0
        RangeSearchPartialResult pres(result);
214
215
0
#pragma omp for
216
0
        for (idx_t i = 0; i < n; i++) { // loop queries
217
0
            RangeQueryResult& qres = pres.new_result(i);
218
0
            RangeSearchResults res = {radius, qres};
219
0
            const uint8_t* q = x + i * code_size;
220
221
0
            search_single_query(*this, q, res, n0, nlist, ndis);
222
0
        }
223
0
        pres.finalize();
224
0
    }
225
0
    indexBinaryHash_stats.nq += n;
226
0
    indexBinaryHash_stats.n0 += n0;
227
0
    indexBinaryHash_stats.nlist += nlist;
228
0
    indexBinaryHash_stats.ndis += ndis;
229
0
}
230
231
void IndexBinaryHash::search(
232
        idx_t n,
233
        const uint8_t* x,
234
        idx_t k,
235
        int32_t* distances,
236
        idx_t* labels,
237
0
        const SearchParameters* params) const {
238
0
    FAISS_THROW_IF_NOT_MSG(
239
0
            !params, "search params not supported for this index");
240
0
    FAISS_THROW_IF_NOT(k > 0);
241
242
0
    using HeapForL2 = CMax<int32_t, idx_t>;
243
0
    size_t nlist = 0, ndis = 0, n0 = 0;
244
245
0
#pragma omp parallel for if (n > 100) reduction(+ : nlist, ndis, n0)
246
0
    for (idx_t i = 0; i < n; i++) {
247
0
        int32_t* simi = distances + k * i;
248
0
        idx_t* idxi = labels + k * i;
249
250
0
        heap_heapify<HeapForL2>(k, simi, idxi);
251
0
        KnnSearchResults res = {k, simi, idxi};
252
0
        const uint8_t* q = x + i * code_size;
253
254
0
        search_single_query(*this, q, res, n0, nlist, ndis);
255
256
0
        heap_reorder<HeapForL2>(k, simi, idxi);
257
0
    }
258
0
    indexBinaryHash_stats.nq += n;
259
0
    indexBinaryHash_stats.n0 += n0;
260
0
    indexBinaryHash_stats.nlist += nlist;
261
0
    indexBinaryHash_stats.ndis += ndis;
262
0
}
263
264
0
size_t IndexBinaryHash::hashtable_size() const {
265
0
    return invlists.size();
266
0
}
267
268
0
void IndexBinaryHash::display() const {
269
0
    for (auto it = invlists.begin(); it != invlists.end(); ++it) {
270
0
        printf("%" PRId64 ": [", it->first);
271
0
        const std::vector<idx_t>& v = it->second.ids;
272
0
        for (auto x : v) {
273
0
            printf("%" PRId64 " ", x);
274
0
        }
275
0
        printf("]\n");
276
0
    }
277
0
}
278
279
8
void IndexBinaryHashStats::reset() {
280
8
    memset((void*)this, 0, sizeof(*this));
281
8
}
282
283
IndexBinaryHashStats indexBinaryHash_stats;
284
285
/*******************************************************
286
 * IndexBinaryMultiHash implementation
287
 ******************************************************/
288
289
IndexBinaryMultiHash::IndexBinaryMultiHash(int d, int nhash, int b)
290
0
        : IndexBinary(d),
291
0
          storage(new IndexBinaryFlat(d)),
292
0
          own_fields(true),
293
0
          maps(nhash),
294
0
          nhash(nhash),
295
0
          b(b),
296
0
          nflip(0) {
297
0
    FAISS_THROW_IF_NOT(nhash * b <= d);
298
0
}
299
300
IndexBinaryMultiHash::IndexBinaryMultiHash()
301
0
        : storage(nullptr), own_fields(true), nhash(0), b(0), nflip(0) {}
302
303
0
IndexBinaryMultiHash::~IndexBinaryMultiHash() {
304
0
    if (own_fields) {
305
0
        delete storage;
306
0
    }
307
0
}
308
309
0
void IndexBinaryMultiHash::reset() {
310
0
    storage->reset();
311
0
    ntotal = 0;
312
0
    for (auto map : maps) {
313
0
        map.clear();
314
0
    }
315
0
}
316
317
0
void IndexBinaryMultiHash::add(idx_t n, const uint8_t* x) {
318
0
    storage->add(n, x);
319
    // populate maps
320
0
    uint64_t mask = ((uint64_t)1 << b) - 1;
321
322
0
    for (idx_t i = 0; i < n; i++) {
323
0
        const uint8_t* xi = x + i * code_size;
324
0
        int ho = 0;
325
0
        for (int h = 0; h < nhash; h++) {
326
0
            uint64_t hash = *(uint64_t*)(xi + (ho >> 3)) >> (ho & 7);
327
0
            hash &= mask;
328
0
            maps[h][hash].push_back(i + ntotal);
329
0
            ho += b;
330
0
        }
331
0
    }
332
0
    ntotal += n;
333
0
}
334
335
namespace {
336
337
template <class HammingComputer, class SearchResults>
338
static void verify_shortlist(
339
        const IndexBinaryFlat* index,
340
        const uint8_t* q,
341
        const std::unordered_set<idx_t>& shortlist,
342
0
        SearchResults& res) {
343
0
    size_t code_size = index->code_size;
344
345
0
    HammingComputer hc(q, code_size);
346
0
    const uint8_t* codes = index->xb.data();
347
348
0
    for (auto i : shortlist) {
349
0
        int dis = hc.hamming(codes + i * code_size);
350
0
        res.add(dis, i);
351
0
    }
352
0
}
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_16HammingComputer4ENS0_18RangeSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_16HammingComputer8ENS0_18RangeSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_17HammingComputer16ENS0_18RangeSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_17HammingComputer20ENS0_18RangeSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_17HammingComputer32ENS0_18RangeSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_17HammingComputer64ENS0_18RangeSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_22HammingComputerDefaultENS0_18RangeSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_16HammingComputer4ENS0_16KnnSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_16HammingComputer8ENS0_16KnnSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_17HammingComputer16ENS0_16KnnSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_17HammingComputer20ENS0_16KnnSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_17HammingComputer32ENS0_16KnnSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_17HammingComputer64ENS0_16KnnSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_116verify_shortlistINS_22HammingComputerDefaultENS0_16KnnSearchResultsEEEvPKNS_15IndexBinaryFlatEPKhRKSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEERT0_
353
354
struct Run_verify_shortlist {
355
    using T = void;
356
    template <class HammingComputer, class... Types>
357
0
    void f(Types... args) {
358
0
        verify_shortlist<HammingComputer>(args...);
359
0
    }
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_16HammingComputer4EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_18RangeSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_16HammingComputer8EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_18RangeSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_17HammingComputer16EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_18RangeSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_17HammingComputer20EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_18RangeSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_17HammingComputer32EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_18RangeSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_17HammingComputer64EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_18RangeSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_22HammingComputerDefaultEJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_18RangeSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_16HammingComputer4EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_16KnnSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_16HammingComputer8EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_16KnnSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_17HammingComputer16EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_16KnnSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_17HammingComputer20EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_16KnnSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_17HammingComputer32EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_16KnnSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_17HammingComputer64EJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_16KnnSearchResultsEEEEvDpT0_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_120Run_verify_shortlist1fINS_22HammingComputerDefaultEJPNS_15IndexBinaryFlatEPKhSt13unordered_setIlSt4hashIlESt8equal_toIlESaIlEENS0_16KnnSearchResultsEEEEvDpT0_
360
};
361
362
template <class SearchResults>
363
void search_1_query_multihash(
364
        const IndexBinaryMultiHash& index,
365
        const uint8_t* xi,
366
        SearchResults& res,
367
        size_t& n0,
368
        size_t& nlist,
369
0
        size_t& ndis) {
370
0
    std::unordered_set<idx_t> shortlist;
371
0
    int b = index.b;
372
0
    uint64_t mask = ((uint64_t)1 << b) - 1;
373
374
0
    int ho = 0;
375
0
    for (int h = 0; h < index.nhash; h++) {
376
0
        uint64_t qhash = *(uint64_t*)(xi + (ho >> 3)) >> (ho & 7);
377
0
        qhash &= mask;
378
0
        const IndexBinaryMultiHash::Map& map = index.maps[h];
379
380
0
        FlipEnumerator fe(index.b, index.nflip);
381
        // loop over neighbors that are at most at nflip bits
382
0
        do {
383
0
            uint64_t hash = qhash ^ fe.x;
384
0
            auto it = map.find(hash);
385
386
0
            if (it != map.end()) {
387
0
                const std::vector<idx_t>& v = it->second;
388
0
                for (auto i : v) {
389
0
                    shortlist.insert(i);
390
0
                }
391
0
                nlist++;
392
0
            } else {
393
0
                n0++;
394
0
            }
395
0
        } while (fe.next());
396
397
0
        ho += b;
398
0
    }
399
0
    ndis += shortlist.size();
400
401
    // verify shortlist
402
0
    Run_verify_shortlist r;
403
0
    dispatch_HammingComputer(
404
0
            index.code_size, r, index.storage, xi, shortlist, res);
405
0
}
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_124search_1_query_multihashINS0_18RangeSearchResultsEEEvRKNS_20IndexBinaryMultiHashEPKhRT_RmSA_SA_
Unexecuted instantiation: IndexBinaryHash.cpp:_ZN5faiss12_GLOBAL__N_124search_1_query_multihashINS0_16KnnSearchResultsEEEvRKNS_20IndexBinaryMultiHashEPKhRT_RmSA_SA_
406
407
} // anonymous namespace
408
409
void IndexBinaryMultiHash::range_search(
410
        idx_t n,
411
        const uint8_t* x,
412
        int radius,
413
        RangeSearchResult* result,
414
0
        const SearchParameters* params) const {
415
0
    FAISS_THROW_IF_NOT_MSG(
416
0
            !params, "search params not supported for this index");
417
0
    size_t nlist = 0, ndis = 0, n0 = 0;
418
419
0
#pragma omp parallel if (n > 100) reduction(+ : ndis, n0, nlist)
420
0
    {
421
0
        RangeSearchPartialResult pres(result);
422
423
0
#pragma omp for
424
0
        for (idx_t i = 0; i < n; i++) { // loop queries
425
0
            RangeQueryResult& qres = pres.new_result(i);
426
0
            RangeSearchResults res = {radius, qres};
427
0
            const uint8_t* q = x + i * code_size;
428
429
0
            search_1_query_multihash(*this, q, res, n0, nlist, ndis);
430
0
        }
431
0
        pres.finalize();
432
0
    }
433
0
    indexBinaryHash_stats.nq += n;
434
0
    indexBinaryHash_stats.n0 += n0;
435
0
    indexBinaryHash_stats.nlist += nlist;
436
0
    indexBinaryHash_stats.ndis += ndis;
437
0
}
438
439
void IndexBinaryMultiHash::search(
440
        idx_t n,
441
        const uint8_t* x,
442
        idx_t k,
443
        int32_t* distances,
444
        idx_t* labels,
445
0
        const SearchParameters* params) const {
446
0
    FAISS_THROW_IF_NOT_MSG(
447
0
            !params, "search params not supported for this index");
448
0
    FAISS_THROW_IF_NOT(k > 0);
449
450
0
    using HeapForL2 = CMax<int32_t, idx_t>;
451
0
    size_t nlist = 0, ndis = 0, n0 = 0;
452
453
0
#pragma omp parallel for if (n > 100) reduction(+ : nlist, ndis, n0)
454
0
    for (idx_t i = 0; i < n; i++) {
455
0
        int32_t* simi = distances + k * i;
456
0
        idx_t* idxi = labels + k * i;
457
458
0
        heap_heapify<HeapForL2>(k, simi, idxi);
459
0
        KnnSearchResults res = {k, simi, idxi};
460
0
        const uint8_t* q = x + i * code_size;
461
462
0
        search_1_query_multihash(*this, q, res, n0, nlist, ndis);
463
464
0
        heap_reorder<HeapForL2>(k, simi, idxi);
465
0
    }
466
0
    indexBinaryHash_stats.nq += n;
467
0
    indexBinaryHash_stats.n0 += n0;
468
0
    indexBinaryHash_stats.nlist += nlist;
469
0
    indexBinaryHash_stats.ndis += ndis;
470
0
}
471
472
0
size_t IndexBinaryMultiHash::hashtable_size() const {
473
0
    size_t tot = 0;
474
0
    for (auto map : maps) {
475
0
        tot += map.size();
476
0
    }
477
478
0
    return tot;
479
0
}
480
481
} // namespace faiss