25 #ifndef FAISS_hamming_h
26 #define FAISS_hamming_h
36 typedef int32_t hamdis_t;
41 extern size_t hamming_batch_size;
43 inline int popcount64(uint64_t x) {
44 return __builtin_popcountl(x);
62 void bitvec_print (
const uint8_t * b,
size_t d);
79 void fvec2bitvec (
const float * x, uint8_t * b,
size_t d);
92 int_maxheap_array_t * ha,
101 int_maxheap_array_t * ha,
132 void hamming_count_thres (
143 size_t match_hamming_thres (
154 void crosshamming_count_thres (
164 const uint64_t * bs1,
165 const uint64_t * bs2,
189 void set (
const uint8_t *a,
int code_size) {
190 assert (code_size == 4);
194 inline int hamming (
const uint8_t *b)
const {
195 return popcount64 (*(uint32_t *)b ^ a0);
209 void set (
const uint8_t *a,
int code_size) {
210 assert (code_size == 8);
214 inline int hamming (
const uint8_t *b)
const {
215 return popcount64 (*(uint64_t *)b ^ a0);
230 void set (
const uint8_t *a8,
int code_size) {
231 assert (code_size == 16);
232 const uint64_t *a = (uint64_t *)a8;
233 a0 = a[0]; a1 = a[1];
236 inline int hamming (
const uint8_t *b8)
const {
237 const uint64_t *b = (uint64_t *)b8;
238 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1);
255 void set (
const uint8_t *a8,
int code_size) {
256 assert (code_size == 20);
257 const uint64_t *a = (uint64_t *)a8;
258 a0 = a[0]; a1 = a[1]; a2 = a[2];
261 inline int hamming (
const uint8_t *b8)
const {
262 const uint64_t *b = (uint64_t *)b8;
263 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
264 popcount64 (*(uint32_t*)(b + 2) ^ a2);
269 uint64_t a0, a1, a2, a3;
277 void set (
const uint8_t *a8,
int code_size) {
278 assert (code_size == 32);
279 const uint64_t *a = (uint64_t *)a8;
280 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
283 inline int hamming (
const uint8_t *b8)
const {
284 const uint64_t *b = (uint64_t *)b8;
285 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
286 popcount64 (b[2] ^ a2) + popcount64 (b[3] ^ a3);
292 uint64_t a0, a1, a2, a3, a4, a5, a6, a7;
300 void set (
const uint8_t *a8,
int code_size) {
301 assert (code_size == 64);
302 const uint64_t *a = (uint64_t *)a8;
303 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
304 a4 = a[4]; a5 = a[5]; a6 = a[6]; a7 = a[7];
307 inline int hamming (
const uint8_t *b8)
const {
308 const uint64_t *b = (uint64_t *)b8;
309 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
310 popcount64 (b[2] ^ a2) + popcount64 (b[3] ^ a3) +
311 popcount64 (b[4] ^ a4) + popcount64 (b[5] ^ a5) +
312 popcount64 (b[6] ^ a6) + popcount64 (b[7] ^ a7);
328 void set (
const uint8_t *a8,
int code_size) {
333 int hamming (
const uint8_t *b8)
const {
335 for (
int i = 0; i < n; i++)
336 accu += popcount64 (a[i] ^ b8[i]);
353 void set (
const uint8_t *a8,
int code_size) {
354 assert (code_size % 8 == 0);
359 int hamming (
const uint8_t *b8)
const {
360 const uint64_t *b = (uint64_t *)b8;
362 for (
int i = 0; i < n; i++)
363 accu += popcount64 (a[i] ^ b[i]);
380 void set (
const uint8_t *a4,
int code_size) {
381 assert (code_size % 4 == 0);
386 int hamming (
const uint8_t *b8)
const {
387 const uint32_t *b = (uint32_t *)b8;
389 for (
int i = 0; i < n; i++)
390 accu += popcount64 (a[i] ^ b[i]);
401 template<
int CODE_SIZE>
407 #define SPECIALIZED_HC(CODE_SIZE) \
408 template<> struct HammingComputer<CODE_SIZE>: \
409 HammingComputer ## CODE_SIZE { \
410 HammingComputer (const uint8_t *a): \
411 HammingComputer ## CODE_SIZE(a, CODE_SIZE) {} \
421 #undef SPECIALIZED_HC
430 inline int generalized_hamming_64 (uint64_t a) {
434 a &= 0x0101010101010101UL;
435 return popcount64 (a);
443 assert (code_size == 8);
447 inline int hamming (
const uint8_t *b)
const {
448 return generalized_hamming_64 (*(uint64_t *)b ^ a0);
457 assert (code_size == 16);
458 const uint64_t *a = (uint64_t *)a8;
459 a0 = a[0]; a1 = a[1];
462 inline int hamming (
const uint8_t *b8)
const {
463 const uint64_t *b = (uint64_t *)b8;
464 return generalized_hamming_64 (b[0] ^ a0) +
465 generalized_hamming_64 (b[1] ^ a1);
471 uint64_t a0, a1, a2, a3;
474 assert (code_size == 32);
475 const uint64_t *a = (uint64_t *)a8;
476 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
479 inline int hamming (
const uint8_t *b8)
const {
480 const uint64_t *b = (uint64_t *)b8;
481 return generalized_hamming_64 (b[0] ^ a0) +
482 generalized_hamming_64 (b[1] ^ a1) +
483 generalized_hamming_64 (b[2] ^ a2) +
484 generalized_hamming_64 (b[3] ^ a3);
494 assert (code_size % 8 == 0);
499 int hamming (
const uint8_t *b8)
const {
500 const uint64_t *b = (uint64_t *)b8;
502 for (
int i = 0; i < n; i++)
503 accu += generalized_hamming_64 (a[i] ^ b[i]);
529 template<
class HammingComputer>
541 const uint8_t *x,
int d,
int k)
542 : counters(counters),
543 ids_per_dis(ids_per_dis),
550 void update_counter(
const uint8_t *y,
size_t j) {
551 int32_t dis = hc.hamming(y);
555 ids_per_dis[dis * k + counters[dis]++] = j;
557 while (count_lt == k && thres > 0) {
559 count_eq = counters[thres];
560 count_lt -= count_eq;
562 }
else if (count_eq < k) {
563 ids_per_dis[dis * k + count_eq++] = j;
564 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)