faiss 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/LICENSE.txt +18 -18
- data/README.md +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/Clustering.cpp +318 -53
- data/vendor/faiss/Clustering.h +39 -11
- data/vendor/faiss/DirectMap.cpp +267 -0
- data/vendor/faiss/DirectMap.h +120 -0
- data/vendor/faiss/IVFlib.cpp +24 -4
- data/vendor/faiss/IVFlib.h +4 -0
- data/vendor/faiss/Index.h +5 -24
- data/vendor/faiss/Index2Layer.cpp +0 -1
- data/vendor/faiss/IndexBinary.h +7 -3
- data/vendor/faiss/IndexBinaryFlat.cpp +5 -0
- data/vendor/faiss/IndexBinaryFlat.h +3 -0
- data/vendor/faiss/IndexBinaryHash.cpp +492 -0
- data/vendor/faiss/IndexBinaryHash.h +116 -0
- data/vendor/faiss/IndexBinaryIVF.cpp +160 -107
- data/vendor/faiss/IndexBinaryIVF.h +14 -4
- data/vendor/faiss/IndexFlat.h +2 -1
- data/vendor/faiss/IndexHNSW.cpp +68 -16
- data/vendor/faiss/IndexHNSW.h +3 -3
- data/vendor/faiss/IndexIVF.cpp +72 -76
- data/vendor/faiss/IndexIVF.h +24 -5
- data/vendor/faiss/IndexIVFFlat.cpp +19 -54
- data/vendor/faiss/IndexIVFFlat.h +1 -11
- data/vendor/faiss/IndexIVFPQ.cpp +49 -26
- data/vendor/faiss/IndexIVFPQ.h +9 -10
- data/vendor/faiss/IndexIVFPQR.cpp +2 -2
- data/vendor/faiss/IndexIVFSpectralHash.cpp +2 -2
- data/vendor/faiss/IndexLSH.h +4 -1
- data/vendor/faiss/IndexPreTransform.cpp +0 -1
- data/vendor/faiss/IndexScalarQuantizer.cpp +8 -1
- data/vendor/faiss/InvertedLists.cpp +0 -2
- data/vendor/faiss/MetaIndexes.cpp +0 -1
- data/vendor/faiss/MetricType.h +36 -0
- data/vendor/faiss/c_api/Clustering_c.cpp +13 -7
- data/vendor/faiss/c_api/Clustering_c.h +11 -5
- data/vendor/faiss/c_api/IndexIVF_c.cpp +7 -0
- data/vendor/faiss/c_api/IndexIVF_c.h +7 -0
- data/vendor/faiss/c_api/IndexPreTransform_c.cpp +21 -0
- data/vendor/faiss/c_api/IndexPreTransform_c.h +32 -0
- data/vendor/faiss/demos/demo_weighted_kmeans.cpp +185 -0
- data/vendor/faiss/gpu/GpuCloner.cpp +4 -0
- data/vendor/faiss/gpu/GpuClonerOptions.cpp +1 -1
- data/vendor/faiss/gpu/GpuDistance.h +93 -0
- data/vendor/faiss/gpu/GpuIndex.h +7 -0
- data/vendor/faiss/gpu/GpuIndexFlat.h +0 -10
- data/vendor/faiss/gpu/GpuIndexIVF.h +1 -0
- data/vendor/faiss/gpu/StandardGpuResources.cpp +8 -0
- data/vendor/faiss/gpu/test/TestGpuIndexFlat.cpp +49 -27
- data/vendor/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +110 -2
- data/vendor/faiss/gpu/utils/DeviceUtils.h +6 -0
- data/vendor/faiss/impl/AuxIndexStructures.cpp +17 -0
- data/vendor/faiss/impl/AuxIndexStructures.h +14 -3
- data/vendor/faiss/impl/HNSW.cpp +0 -1
- data/vendor/faiss/impl/PolysemousTraining.h +5 -5
- data/vendor/faiss/impl/ProductQuantizer-inl.h +138 -0
- data/vendor/faiss/impl/ProductQuantizer.cpp +1 -113
- data/vendor/faiss/impl/ProductQuantizer.h +42 -47
- data/vendor/faiss/impl/index_read.cpp +103 -7
- data/vendor/faiss/impl/index_write.cpp +101 -5
- data/vendor/faiss/impl/io.cpp +111 -1
- data/vendor/faiss/impl/io.h +38 -0
- data/vendor/faiss/index_factory.cpp +0 -1
- data/vendor/faiss/tests/test_merge.cpp +0 -1
- data/vendor/faiss/tests/test_pq_encoding.cpp +6 -6
- data/vendor/faiss/tutorial/cpp/5-Multiple-GPUs.cpp +1 -0
- data/vendor/faiss/utils/distances.cpp +4 -5
- data/vendor/faiss/utils/distances_simd.cpp +0 -1
- data/vendor/faiss/utils/hamming.cpp +85 -3
- data/vendor/faiss/utils/hamming.h +20 -0
- data/vendor/faiss/utils/utils.cpp +0 -96
- data/vendor/faiss/utils/utils.h +0 -15
- metadata +11 -3
- data/lib/faiss/ext.bundle +0 -0
@@ -64,6 +64,12 @@ bool getFullUnifiedMemSupport(int device);
|
|
64
64
|
/// Equivalent to getFullUnifiedMemSupport(getCurrentDevice())
|
65
65
|
bool getFullUnifiedMemSupportCurrentDevice();
|
66
66
|
|
67
|
+
/// Does the given device support tensor core operations?
|
68
|
+
bool getTensorCoreSupport(int device);
|
69
|
+
|
70
|
+
/// Equivalent to getTensorCoreSupport(getCurrentDevice())
|
71
|
+
bool getTensorCoreSupportCurrentDevice();
|
72
|
+
|
67
73
|
/// Returns the maximum k-selection value supported based on the CUDA SDK that
|
68
74
|
/// we were compiled with. .cu files can use DeviceDefs.cuh, but this is for
|
69
75
|
/// non-CUDA files
|
@@ -228,6 +228,23 @@ bool IDSelectorRange::is_member (idx_t id) const
|
|
228
228
|
return id >= imin && id < imax;
|
229
229
|
}
|
230
230
|
|
231
|
+
/***********************************************************************
|
232
|
+
* IDSelectorArray
|
233
|
+
***********************************************************************/
|
234
|
+
|
235
|
+
IDSelectorArray::IDSelectorArray (size_t n, const idx_t *ids):
|
236
|
+
n (n), ids(ids)
|
237
|
+
{
|
238
|
+
}
|
239
|
+
|
240
|
+
bool IDSelectorArray::is_member (idx_t id) const
|
241
|
+
{
|
242
|
+
for (idx_t i = 0; i < n; i++) {
|
243
|
+
if (ids[i] == id) return true;
|
244
|
+
}
|
245
|
+
return false;
|
246
|
+
}
|
247
|
+
|
231
248
|
|
232
249
|
/***********************************************************************
|
233
250
|
* IDSelectorBatch
|
@@ -51,9 +51,7 @@ struct RangeSearchResult {
|
|
51
51
|
};
|
52
52
|
|
53
53
|
|
54
|
-
/**
|
55
|
-
|
56
|
-
Encapsulates a set of ids to remove. */
|
54
|
+
/** Encapsulates a set of ids to remove. */
|
57
55
|
struct IDSelector {
|
58
56
|
typedef Index::idx_t idx_t;
|
59
57
|
virtual bool is_member (idx_t id) const = 0;
|
@@ -71,6 +69,19 @@ struct IDSelectorRange: IDSelector {
|
|
71
69
|
~IDSelectorRange() override {}
|
72
70
|
};
|
73
71
|
|
72
|
+
/** simple list of elements to remove
|
73
|
+
*
|
74
|
+
* this is inefficient in most cases, except for IndexIVF with
|
75
|
+
* maintain_direct_map
|
76
|
+
*/
|
77
|
+
struct IDSelectorArray: IDSelector {
|
78
|
+
size_t n;
|
79
|
+
const idx_t *ids;
|
80
|
+
|
81
|
+
IDSelectorArray (size_t n, const idx_t *ids);
|
82
|
+
bool is_member(idx_t id) const override;
|
83
|
+
~IDSelectorArray() override {}
|
84
|
+
};
|
74
85
|
|
75
86
|
/** Remove ids from a set. Repetitions of ids in the indices set
|
76
87
|
* passed to the constructor does not hurt performance. The hash
|
data/vendor/faiss/impl/HNSW.cpp
CHANGED
@@ -123,15 +123,15 @@ struct PolysemousTraining: SimulatedAnnealingParameters {
|
|
123
123
|
enum Optimization_type_t {
|
124
124
|
OT_None,
|
125
125
|
OT_ReproduceDistances_affine, ///< default
|
126
|
-
OT_Ranking_weighted_diff
|
126
|
+
OT_Ranking_weighted_diff ///< same as _2, but use rank of y+ - rank of y-
|
127
127
|
};
|
128
128
|
Optimization_type_t optimization_type;
|
129
129
|
|
130
|
-
|
131
|
-
|
132
|
-
|
130
|
+
/** use 1/4 of the training points for the optimization, with
|
131
|
+
* max. ntrain_permutation. If ntrain_permutation == 0: train on
|
132
|
+
* centroids */
|
133
133
|
int ntrain_permutation;
|
134
|
-
double dis_weight_factor;
|
134
|
+
double dis_weight_factor; ///< decay of exp that weights distance loss
|
135
135
|
|
136
136
|
// filename pattern for the logging of iterations
|
137
137
|
std::string log_pattern;
|
@@ -0,0 +1,138 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) Facebook, Inc. and its 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
|
+
namespace faiss {
|
9
|
+
|
10
|
+
inline
|
11
|
+
PQEncoderGeneric::PQEncoderGeneric(uint8_t *code, int nbits,
|
12
|
+
uint8_t offset)
|
13
|
+
: code(code), offset(offset), nbits(nbits), reg(0)
|
14
|
+
{
|
15
|
+
assert(nbits <= 64);
|
16
|
+
if (offset > 0) {
|
17
|
+
reg = (*code & ((1 << offset) - 1));
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
inline
|
22
|
+
void PQEncoderGeneric::encode(uint64_t x)
|
23
|
+
{
|
24
|
+
reg |= (uint8_t)(x << offset);
|
25
|
+
x >>= (8 - offset);
|
26
|
+
if (offset + nbits >= 8) {
|
27
|
+
*code++ = reg;
|
28
|
+
|
29
|
+
for (int i = 0; i < (nbits - (8 - offset)) / 8; ++i) {
|
30
|
+
*code++ = (uint8_t)x;
|
31
|
+
x >>= 8;
|
32
|
+
}
|
33
|
+
|
34
|
+
offset += nbits;
|
35
|
+
offset &= 7;
|
36
|
+
reg = (uint8_t)x;
|
37
|
+
} else {
|
38
|
+
offset += nbits;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
inline
|
43
|
+
PQEncoderGeneric::~PQEncoderGeneric()
|
44
|
+
{
|
45
|
+
if (offset > 0) {
|
46
|
+
*code = reg;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
|
51
|
+
inline
|
52
|
+
PQEncoder8::PQEncoder8(uint8_t *code, int nbits)
|
53
|
+
: code(code) {
|
54
|
+
assert(8 == nbits);
|
55
|
+
}
|
56
|
+
|
57
|
+
inline
|
58
|
+
void PQEncoder8::encode(uint64_t x) {
|
59
|
+
*code++ = (uint8_t)x;
|
60
|
+
}
|
61
|
+
|
62
|
+
inline
|
63
|
+
PQEncoder16::PQEncoder16(uint8_t *code, int nbits)
|
64
|
+
: code((uint16_t *)code) {
|
65
|
+
assert(16 == nbits);
|
66
|
+
}
|
67
|
+
|
68
|
+
inline
|
69
|
+
void PQEncoder16::encode(uint64_t x) {
|
70
|
+
*code++ = (uint16_t)x;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
inline
|
75
|
+
PQDecoderGeneric::PQDecoderGeneric(const uint8_t *code,
|
76
|
+
int nbits)
|
77
|
+
: code(code),
|
78
|
+
offset(0),
|
79
|
+
nbits(nbits),
|
80
|
+
mask((1ull << nbits) - 1),
|
81
|
+
reg(0) {
|
82
|
+
assert(nbits <= 64);
|
83
|
+
}
|
84
|
+
|
85
|
+
inline
|
86
|
+
uint64_t PQDecoderGeneric::decode() {
|
87
|
+
if (offset == 0) {
|
88
|
+
reg = *code;
|
89
|
+
}
|
90
|
+
uint64_t c = (reg >> offset);
|
91
|
+
|
92
|
+
if (offset + nbits >= 8) {
|
93
|
+
uint64_t e = 8 - offset;
|
94
|
+
++code;
|
95
|
+
for (int i = 0; i < (nbits - (8 - offset)) / 8; ++i) {
|
96
|
+
c |= ((uint64_t)(*code++) << e);
|
97
|
+
e += 8;
|
98
|
+
}
|
99
|
+
|
100
|
+
offset += nbits;
|
101
|
+
offset &= 7;
|
102
|
+
if (offset > 0) {
|
103
|
+
reg = *code;
|
104
|
+
c |= ((uint64_t)reg << e);
|
105
|
+
}
|
106
|
+
} else {
|
107
|
+
offset += nbits;
|
108
|
+
}
|
109
|
+
|
110
|
+
return c & mask;
|
111
|
+
}
|
112
|
+
|
113
|
+
|
114
|
+
inline
|
115
|
+
PQDecoder8::PQDecoder8(const uint8_t *code, int nbits)
|
116
|
+
: code(code) {
|
117
|
+
assert(8 == nbits);
|
118
|
+
}
|
119
|
+
|
120
|
+
inline
|
121
|
+
uint64_t PQDecoder8::decode() {
|
122
|
+
return (uint64_t)(*code++);
|
123
|
+
}
|
124
|
+
|
125
|
+
|
126
|
+
inline
|
127
|
+
PQDecoder16::PQDecoder16(const uint8_t *code, int nbits)
|
128
|
+
: code((uint16_t *)code) {
|
129
|
+
assert(16 == nbits);
|
130
|
+
}
|
131
|
+
|
132
|
+
inline
|
133
|
+
uint64_t PQDecoder16::decode() {
|
134
|
+
return (uint64_t)(*code++);
|
135
|
+
}
|
136
|
+
|
137
|
+
|
138
|
+
} // namespace faiss
|
@@ -151,7 +151,7 @@ static inline void pq_estimators_from_tables_generic(const ProductQuantizer& pq,
|
|
151
151
|
const size_t M = pq.M;
|
152
152
|
const size_t ksub = pq.ksub;
|
153
153
|
for (size_t j = 0; j < ncodes; ++j) {
|
154
|
-
|
154
|
+
PQDecoderGeneric decoder(
|
155
155
|
codes + j * pq.code_size, nbits
|
156
156
|
);
|
157
157
|
float dis = 0;
|
@@ -760,117 +760,5 @@ void ProductQuantizer::search_sdc (const uint8_t * qcodes,
|
|
760
760
|
}
|
761
761
|
|
762
762
|
|
763
|
-
ProductQuantizer::PQEncoderGeneric::PQEncoderGeneric(uint8_t *code, int nbits,
|
764
|
-
uint8_t offset)
|
765
|
-
: code(code), offset(offset), nbits(nbits), reg(0) {
|
766
|
-
assert(nbits <= 64);
|
767
|
-
if (offset > 0) {
|
768
|
-
reg = (*code & ((1 << offset) - 1));
|
769
|
-
}
|
770
|
-
}
|
771
|
-
|
772
|
-
void ProductQuantizer::PQEncoderGeneric::encode(uint64_t x) {
|
773
|
-
reg |= (uint8_t)(x << offset);
|
774
|
-
x >>= (8 - offset);
|
775
|
-
if (offset + nbits >= 8) {
|
776
|
-
*code++ = reg;
|
777
|
-
|
778
|
-
for (int i = 0; i < (nbits - (8 - offset)) / 8; ++i) {
|
779
|
-
*code++ = (uint8_t)x;
|
780
|
-
x >>= 8;
|
781
|
-
}
|
782
|
-
|
783
|
-
offset += nbits;
|
784
|
-
offset &= 7;
|
785
|
-
reg = (uint8_t)x;
|
786
|
-
} else {
|
787
|
-
offset += nbits;
|
788
|
-
}
|
789
|
-
}
|
790
|
-
|
791
|
-
ProductQuantizer::PQEncoderGeneric::~PQEncoderGeneric() {
|
792
|
-
if (offset > 0) {
|
793
|
-
*code = reg;
|
794
|
-
}
|
795
|
-
}
|
796
|
-
|
797
|
-
|
798
|
-
ProductQuantizer::PQEncoder8::PQEncoder8(uint8_t *code, int nbits)
|
799
|
-
: code(code) {
|
800
|
-
assert(8 == nbits);
|
801
|
-
}
|
802
|
-
|
803
|
-
void ProductQuantizer::PQEncoder8::encode(uint64_t x) {
|
804
|
-
*code++ = (uint8_t)x;
|
805
|
-
}
|
806
|
-
|
807
|
-
|
808
|
-
ProductQuantizer::PQEncoder16::PQEncoder16(uint8_t *code, int nbits)
|
809
|
-
: code((uint16_t *)code) {
|
810
|
-
assert(16 == nbits);
|
811
|
-
}
|
812
|
-
|
813
|
-
void ProductQuantizer::PQEncoder16::encode(uint64_t x) {
|
814
|
-
*code++ = (uint16_t)x;
|
815
|
-
}
|
816
|
-
|
817
|
-
|
818
|
-
ProductQuantizer::PQDecoderGeneric::PQDecoderGeneric(const uint8_t *code,
|
819
|
-
int nbits)
|
820
|
-
: code(code),
|
821
|
-
offset(0),
|
822
|
-
nbits(nbits),
|
823
|
-
mask((1ull << nbits) - 1),
|
824
|
-
reg(0) {
|
825
|
-
assert(nbits <= 64);
|
826
|
-
}
|
827
|
-
|
828
|
-
uint64_t ProductQuantizer::PQDecoderGeneric::decode() {
|
829
|
-
if (offset == 0) {
|
830
|
-
reg = *code;
|
831
|
-
}
|
832
|
-
uint64_t c = (reg >> offset);
|
833
|
-
|
834
|
-
if (offset + nbits >= 8) {
|
835
|
-
uint64_t e = 8 - offset;
|
836
|
-
++code;
|
837
|
-
for (int i = 0; i < (nbits - (8 - offset)) / 8; ++i) {
|
838
|
-
c |= ((uint64_t)(*code++) << e);
|
839
|
-
e += 8;
|
840
|
-
}
|
841
|
-
|
842
|
-
offset += nbits;
|
843
|
-
offset &= 7;
|
844
|
-
if (offset > 0) {
|
845
|
-
reg = *code;
|
846
|
-
c |= ((uint64_t)reg << e);
|
847
|
-
}
|
848
|
-
} else {
|
849
|
-
offset += nbits;
|
850
|
-
}
|
851
|
-
|
852
|
-
return c & mask;
|
853
|
-
}
|
854
|
-
|
855
|
-
|
856
|
-
ProductQuantizer::PQDecoder8::PQDecoder8(const uint8_t *code, int nbits)
|
857
|
-
: code(code) {
|
858
|
-
assert(8 == nbits);
|
859
|
-
}
|
860
|
-
|
861
|
-
uint64_t ProductQuantizer::PQDecoder8::decode() {
|
862
|
-
return (uint64_t)(*code++);
|
863
|
-
}
|
864
|
-
|
865
|
-
|
866
|
-
ProductQuantizer::PQDecoder16::PQDecoder16(const uint8_t *code, int nbits)
|
867
|
-
: code((uint16_t *)code) {
|
868
|
-
assert(16 == nbits);
|
869
|
-
}
|
870
|
-
|
871
|
-
uint64_t ProductQuantizer::PQDecoder16::decode() {
|
872
|
-
return (uint64_t)(*code++);
|
873
|
-
}
|
874
|
-
|
875
763
|
|
876
764
|
} // namespace faiss
|
@@ -173,70 +173,65 @@ struct ProductQuantizer {
|
|
173
173
|
float_maxheap_array_t * res,
|
174
174
|
bool init_finalize_heap = true) const;
|
175
175
|
|
176
|
-
|
177
|
-
uint8_t *code; ///< code for this vector
|
178
|
-
uint8_t offset;
|
179
|
-
const int nbits; ///< number of bits per subquantizer index
|
180
|
-
|
181
|
-
uint8_t reg;
|
182
|
-
|
183
|
-
PQEncoderGeneric(uint8_t *code, int nbits, uint8_t offset = 0);
|
184
|
-
|
185
|
-
void encode(uint64_t x);
|
186
|
-
|
187
|
-
~PQEncoderGeneric();
|
188
|
-
};
|
189
|
-
|
190
|
-
|
191
|
-
struct PQEncoder8 {
|
192
|
-
uint8_t *code;
|
193
|
-
|
194
|
-
PQEncoder8(uint8_t *code, int nbits);
|
195
|
-
|
196
|
-
void encode(uint64_t x);
|
197
|
-
};
|
198
|
-
|
199
|
-
struct PQEncoder16 {
|
200
|
-
uint16_t *code;
|
176
|
+
};
|
201
177
|
|
202
|
-
PQEncoder16(uint8_t *code, int nbits);
|
203
178
|
|
204
|
-
|
205
|
-
|
179
|
+
/*************************************************
|
180
|
+
* Objects to encode / decode strings of bits
|
181
|
+
*************************************************/
|
206
182
|
|
183
|
+
struct PQEncoderGeneric {
|
184
|
+
uint8_t *code; ///< code for this vector
|
185
|
+
uint8_t offset;
|
186
|
+
const int nbits; ///< number of bits per subquantizer index
|
207
187
|
|
208
|
-
|
209
|
-
const uint8_t *code;
|
210
|
-
uint8_t offset;
|
211
|
-
const int nbits;
|
212
|
-
const uint64_t mask;
|
213
|
-
uint8_t reg;
|
188
|
+
uint8_t reg;
|
214
189
|
|
215
|
-
|
190
|
+
PQEncoderGeneric(uint8_t *code, int nbits, uint8_t offset = 0);
|
216
191
|
|
217
|
-
|
218
|
-
};
|
192
|
+
void encode(uint64_t x);
|
219
193
|
|
220
|
-
|
221
|
-
|
194
|
+
~PQEncoderGeneric();
|
195
|
+
};
|
222
196
|
|
223
|
-
PQDecoder8(const uint8_t *code, int nbits);
|
224
197
|
|
225
|
-
|
226
|
-
|
198
|
+
struct PQEncoder8 {
|
199
|
+
uint8_t *code;
|
200
|
+
PQEncoder8(uint8_t *code, int nbits);
|
201
|
+
void encode(uint64_t x);
|
202
|
+
};
|
227
203
|
|
228
|
-
|
229
|
-
|
204
|
+
struct PQEncoder16 {
|
205
|
+
uint16_t *code;
|
206
|
+
PQEncoder16(uint8_t *code, int nbits);
|
207
|
+
void encode(uint64_t x);
|
208
|
+
};
|
230
209
|
|
231
|
-
PQDecoder16(const uint8_t *code, int nbits);
|
232
210
|
|
233
|
-
|
234
|
-
|
211
|
+
struct PQDecoderGeneric {
|
212
|
+
const uint8_t *code;
|
213
|
+
uint8_t offset;
|
214
|
+
const int nbits;
|
215
|
+
const uint64_t mask;
|
216
|
+
uint8_t reg;
|
217
|
+
PQDecoderGeneric(const uint8_t *code, int nbits);
|
218
|
+
uint64_t decode();
|
219
|
+
};
|
235
220
|
|
221
|
+
struct PQDecoder8 {
|
222
|
+
const uint8_t *code;
|
223
|
+
PQDecoder8(const uint8_t *code, int nbits);
|
224
|
+
uint64_t decode();
|
236
225
|
};
|
237
226
|
|
227
|
+
struct PQDecoder16 {
|
228
|
+
const uint16_t *code;
|
229
|
+
PQDecoder16(const uint8_t *code, int nbits);
|
230
|
+
uint64_t decode();
|
231
|
+
};
|
238
232
|
|
239
233
|
} // namespace faiss
|
240
234
|
|
235
|
+
#include <faiss/impl/ProductQuantizer-inl.h>
|
241
236
|
|
242
237
|
#endif
|