26 #ifndef FAISS_hamming_h
27 #define FAISS_hamming_h
37 typedef int32_t hamdis_t;
41 inline int popcount64(uint64_t x) {
42 return __builtin_popcountl(x);
60 void bitvec_print (
const uint8_t * b,
size_t d);
77 void fvec2bitvec (
const float * x, uint8_t * b,
size_t d);
89 int_maxheap_array_t * ha,
97 void hammings_knn_core (
98 int_maxheap_array_t * ha,
107 void hamming_count_thres (
118 size_t match_hamming_thres (
129 void crosshamming_count_thres (
139 const uint64_t * bs1,
140 const uint64_t * bs2,
159 assert (code_size == 4);
163 inline int hamming (
const uint8_t *b)
const {
164 return popcount64 (*(uint32_t *)b ^ a0);
173 assert (code_size == 8);
177 inline int hamming (
const uint8_t *b)
const {
178 return popcount64 (*(uint64_t *)b ^ a0);
187 assert (code_size == 16);
188 const uint64_t *a = (uint64_t *)a8;
189 a0 = a[0]; a1 = a[1];
192 inline int hamming (
const uint8_t *b8)
const {
193 const uint64_t *b = (uint64_t *)b8;
194 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1);
206 assert (code_size == 20);
207 const uint64_t *a = (uint64_t *)a8;
208 a0 = a[0]; a1 = a[1]; a2 = a[2];
211 inline int hamming (
const uint8_t *b8)
const {
212 const uint64_t *b = (uint64_t *)b8;
213 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
214 popcount64 (*(uint32_t*)(b + 2) ^ a2);
219 uint64_t a0, a1, a2, a3;
222 assert (code_size == 32);
223 const uint64_t *a = (uint64_t *)a8;
224 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
227 inline int hamming (
const uint8_t *b8)
const {
228 const uint64_t *b = (uint64_t *)b8;
229 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
230 popcount64 (b[2] ^ a2) + popcount64 (b[3] ^ a3);
236 uint64_t a0, a1, a2, a3, a4, a5, a6, a7;
239 assert (code_size == 64);
240 const uint64_t *a = (uint64_t *)a8;
241 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
242 a4 = a[4]; a5 = a[5]; a6 = a[6]; a7 = a[7];
245 inline int hamming (
const uint8_t *b8)
const {
246 const uint64_t *b = (uint64_t *)b8;
247 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
248 popcount64 (b[2] ^ a2) + popcount64 (b[3] ^ a3) +
249 popcount64 (b[4] ^ a4) + popcount64 (b[5] ^ a5) +
250 popcount64 (b[6] ^ a6) + popcount64 (b[7] ^ a7);
260 assert (code_size % 8 == 0);
265 int hamming (
const uint8_t *b8)
const {
266 const uint64_t *b = (uint64_t *)b8;
268 for (
int i = 0; i < n; i++)
269 accu += popcount64 (a[i] ^ b[i]);
281 assert (code_size % 4 == 0);
285 int hamming (
const uint8_t *b8)
const {
286 const uint32_t *b = (uint32_t *)b8;
288 for (
int i = 0; i < n; i++)
289 accu += popcount64 (a[i] ^ b[i]);
300 template<
int CODE_SIZE>
306 #define SPECIALIZED_HC(CODE_SIZE) \
307 template<> struct HammingComputer<CODE_SIZE>: \
308 HammingComputer ## CODE_SIZE { \
309 HammingComputer (const uint8_t *a): \
310 HammingComputer ## CODE_SIZE(a, CODE_SIZE) {} \
320 #undef SPECIALIZED_HC
329 inline int generalized_hamming_64 (uint64_t a) {
333 a &= 0x0101010101010101UL;
334 return popcount64 (a);
342 assert (code_size == 8);
346 inline int hamming (
const uint8_t *b)
const {
347 return generalized_hamming_64 (*(uint64_t *)b ^ a0);
356 assert (code_size == 16);
357 const uint64_t *a = (uint64_t *)a8;
358 a0 = a[0]; a1 = a[1];
361 inline int hamming (
const uint8_t *b8)
const {
362 const uint64_t *b = (uint64_t *)b8;
363 return generalized_hamming_64 (b[0] ^ a0) +
364 generalized_hamming_64 (b[1] ^ a1);
370 uint64_t a0, a1, a2, a3;
373 assert (code_size == 32);
374 const uint64_t *a = (uint64_t *)a8;
375 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
378 inline int hamming (
const uint8_t *b8)
const {
379 const uint64_t *b = (uint64_t *)b8;
380 return generalized_hamming_64 (b[0] ^ a0) +
381 generalized_hamming_64 (b[1] ^ a1) +
382 generalized_hamming_64 (b[2] ^ a2) +
383 generalized_hamming_64 (b[3] ^ a3);
393 assert (code_size % 8 == 0);
398 int hamming (
const uint8_t *b8)
const {
399 const uint64_t *b = (uint64_t *)b8;
401 for (
int i = 0; i < n; i++)
402 accu += generalized_hamming_64 (a[i] ^ b[i]);
void generalized_hammings_knn(int_maxheap_array_t *ha, const uint8_t *a, const uint8_t *b, size_t nb, size_t code_size, int ordered)
void hammings_knn(int_maxheap_array_t *ha, const uint8_t *a, const uint8_t *b, size_t nb, size_t ncodes, int order)