26 #ifndef FAISS_hamming_h
27 #define FAISS_hamming_h
37 typedef int32_t hamdis_t;
42 extern size_t hamming_batch_size;
44 inline int popcount64(uint64_t x) {
45 return __builtin_popcountl(x);
63 void bitvec_print (
const uint8_t * b,
size_t d);
80 void fvec2bitvec (
const float * x, uint8_t * b,
size_t d);
93 int_maxheap_array_t * ha,
102 int_maxheap_array_t * ha,
133 void hamming_count_thres (
144 size_t match_hamming_thres (
155 void crosshamming_count_thres (
165 const uint64_t * bs1,
166 const uint64_t * bs2,
190 void set (
const uint8_t *a,
int code_size) {
191 assert (code_size == 4);
195 inline int hamming (
const uint8_t *b)
const {
196 return popcount64 (*(uint32_t *)b ^ a0);
210 void set (
const uint8_t *a,
int code_size) {
211 assert (code_size == 8);
215 inline int hamming (
const uint8_t *b)
const {
216 return popcount64 (*(uint64_t *)b ^ a0);
231 void set (
const uint8_t *a8,
int code_size) {
232 assert (code_size == 16);
233 const uint64_t *a = (uint64_t *)a8;
234 a0 = a[0]; a1 = a[1];
237 inline int hamming (
const uint8_t *b8)
const {
238 const uint64_t *b = (uint64_t *)b8;
239 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1);
256 void set (
const uint8_t *a8,
int code_size) {
257 assert (code_size == 20);
258 const uint64_t *a = (uint64_t *)a8;
259 a0 = a[0]; a1 = a[1]; a2 = a[2];
262 inline int hamming (
const uint8_t *b8)
const {
263 const uint64_t *b = (uint64_t *)b8;
264 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
265 popcount64 (*(uint32_t*)(b + 2) ^ a2);
270 uint64_t a0, a1, a2, a3;
278 void set (
const uint8_t *a8,
int code_size) {
279 assert (code_size == 32);
280 const uint64_t *a = (uint64_t *)a8;
281 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
284 inline int hamming (
const uint8_t *b8)
const {
285 const uint64_t *b = (uint64_t *)b8;
286 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
287 popcount64 (b[2] ^ a2) + popcount64 (b[3] ^ a3);
293 uint64_t a0, a1, a2, a3, a4, a5, a6, a7;
301 void set (
const uint8_t *a8,
int code_size) {
302 assert (code_size == 64);
303 const uint64_t *a = (uint64_t *)a8;
304 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
305 a4 = a[4]; a5 = a[5]; a6 = a[6]; a7 = a[7];
308 inline int hamming (
const uint8_t *b8)
const {
309 const uint64_t *b = (uint64_t *)b8;
310 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
311 popcount64 (b[2] ^ a2) + popcount64 (b[3] ^ a3) +
312 popcount64 (b[4] ^ a4) + popcount64 (b[5] ^ a5) +
313 popcount64 (b[6] ^ a6) + popcount64 (b[7] ^ a7);
329 void set (
const uint8_t *a8,
int code_size) {
334 int hamming (
const uint8_t *b8)
const {
336 for (
int i = 0; i < n; i++)
337 accu += popcount64 (a[i] ^ b8[i]);
354 void set (
const uint8_t *a8,
int code_size) {
355 assert (code_size % 8 == 0);
360 int hamming (
const uint8_t *b8)
const {
361 const uint64_t *b = (uint64_t *)b8;
363 for (
int i = 0; i < n; i++)
364 accu += popcount64 (a[i] ^ b[i]);
381 void set (
const uint8_t *a4,
int code_size) {
382 assert (code_size % 4 == 0);
387 int hamming (
const uint8_t *b8)
const {
388 const uint32_t *b = (uint32_t *)b8;
390 for (
int i = 0; i < n; i++)
391 accu += popcount64 (a[i] ^ b[i]);
402 template<
int CODE_SIZE>
408 #define SPECIALIZED_HC(CODE_SIZE) \
409 template<> struct HammingComputer<CODE_SIZE>: \
410 HammingComputer ## CODE_SIZE { \
411 HammingComputer (const uint8_t *a): \
412 HammingComputer ## CODE_SIZE(a, CODE_SIZE) {} \
422 #undef SPECIALIZED_HC
431 inline int generalized_hamming_64 (uint64_t a) {
435 a &= 0x0101010101010101UL;
436 return popcount64 (a);
444 assert (code_size == 8);
448 inline int hamming (
const uint8_t *b)
const {
449 return generalized_hamming_64 (*(uint64_t *)b ^ a0);
458 assert (code_size == 16);
459 const uint64_t *a = (uint64_t *)a8;
460 a0 = a[0]; a1 = a[1];
463 inline int hamming (
const uint8_t *b8)
const {
464 const uint64_t *b = (uint64_t *)b8;
465 return generalized_hamming_64 (b[0] ^ a0) +
466 generalized_hamming_64 (b[1] ^ a1);
472 uint64_t a0, a1, a2, a3;
475 assert (code_size == 32);
476 const uint64_t *a = (uint64_t *)a8;
477 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
480 inline int hamming (
const uint8_t *b8)
const {
481 const uint64_t *b = (uint64_t *)b8;
482 return generalized_hamming_64 (b[0] ^ a0) +
483 generalized_hamming_64 (b[1] ^ a1) +
484 generalized_hamming_64 (b[2] ^ a2) +
485 generalized_hamming_64 (b[3] ^ a3);
495 assert (code_size % 8 == 0);
500 int hamming (
const uint8_t *b8)
const {
501 const uint64_t *b = (uint64_t *)b8;
503 for (
int i = 0; i < n; i++)
504 accu += generalized_hamming_64 (a[i] ^ b[i]);
530 template<
class HammingComputer>
542 const uint8_t *x,
int d,
int k)
543 : counters(counters),
544 ids_per_dis(ids_per_dis),
551 void update_counter(
const uint8_t *y,
size_t j) {
552 int32_t dis = hc.hamming(y);
556 ids_per_dis[dis * k + counters[dis]++] = j;
558 while (count_lt == k && thres > 0) {
560 count_eq = counters[thres];
561 count_lt -= count_eq;
563 }
else if (count_eq < k) {
564 ids_per_dis[dis * k + count_eq++] = j;
565 counters[dis] = count_eq;
void hammings_knn_hc(int_maxheap_array_t *ha, const uint8_t *a, const uint8_t *b, size_t nb, size_t ncodes, int order)
void hammings_knn_mc(const uint8_t *a, const uint8_t *b, size_t na, size_t nb, size_t k, size_t ncodes, int32_t *distances, long *labels)
void generalized_hammings_knn_hc(int_maxheap_array_t *ha, const uint8_t *a, const uint8_t *b, size_t nb, size_t code_size, int ordered)