27 #ifndef FAISS_hamming_h
28 #define FAISS_hamming_h
38 typedef int32_t hamdis_t;
42 inline int popcount64(uint64_t x) {
43 return __builtin_popcountl(x);
61 void bitvec_print (
const uint8_t * b,
size_t d);
78 void fvec2bitvec (
const float * x, uint8_t * b,
size_t d);
90 int_maxheap_array_t * ha,
98 void hammings_knn_core (
99 int_maxheap_array_t * ha,
108 void hamming_count_thres (
119 size_t match_hamming_thres (
130 void crosshamming_count_thres (
140 const uint64_t * bs1,
141 const uint64_t * bs2,
160 assert (code_size == 4);
164 inline int hamming (
const uint8_t *b)
const {
165 return popcount64 (*(uint32_t *)b ^ a0);
174 assert (code_size == 8);
178 inline int hamming (
const uint8_t *b)
const {
179 return popcount64 (*(uint64_t *)b ^ a0);
188 assert (code_size == 16);
189 const uint64_t *a = (uint64_t *)a8;
190 a0 = a[0]; a1 = a[1];
193 inline int hamming (
const uint8_t *b8)
const {
194 const uint64_t *b = (uint64_t *)b8;
195 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1);
207 assert (code_size == 20);
208 const uint64_t *a = (uint64_t *)a8;
209 a0 = a[0]; a1 = a[1]; a2 = a[2];
212 inline int hamming (
const uint8_t *b8)
const {
213 const uint64_t *b = (uint64_t *)b8;
214 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
215 popcount64 (*(uint32_t*)(b + 2) ^ a2);
220 uint64_t a0, a1, a2, a3;
223 assert (code_size == 32);
224 const uint64_t *a = (uint64_t *)a8;
225 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
228 inline int hamming (
const uint8_t *b8)
const {
229 const uint64_t *b = (uint64_t *)b8;
230 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
231 popcount64 (b[2] ^ a2) + popcount64 (b[3] ^ a3);
237 uint64_t a0, a1, a2, a3, a4, a5, a6, a7;
240 assert (code_size == 64);
241 const uint64_t *a = (uint64_t *)a8;
242 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
243 a4 = a[4]; a5 = a[5]; a6 = a[6]; a7 = a[7];
246 inline int hamming (
const uint8_t *b8)
const {
247 const uint64_t *b = (uint64_t *)b8;
248 return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
249 popcount64 (b[2] ^ a2) + popcount64 (b[3] ^ a3) +
250 popcount64 (b[4] ^ a4) + popcount64 (b[5] ^ a5) +
251 popcount64 (b[6] ^ a6) + popcount64 (b[7] ^ a7);
261 assert (code_size % 8 == 0);
266 int hamming (
const uint8_t *b8)
const {
267 const uint64_t *b = (uint64_t *)b8;
269 for (
int i = 0; i < n; i++)
270 accu += popcount64 (a[i] ^ b[i]);
282 assert (code_size % 4 == 0);
286 int hamming (
const uint8_t *b8)
const {
287 const uint32_t *b = (uint32_t *)b8;
289 for (
int i = 0; i < n; i++)
290 accu += popcount64 (a[i] ^ b[i]);
301 template<
int CODE_SIZE>
307 #define SPECIALIZED_HC(CODE_SIZE) \
308 template<> struct HammingComputer<CODE_SIZE>: \
309 HammingComputer ## CODE_SIZE { \
310 HammingComputer (const uint8_t *a): \
311 HammingComputer ## CODE_SIZE(a, CODE_SIZE) {} \
321 #undef SPECIALIZED_HC
330 inline int generalized_hamming_64 (uint64_t a) {
334 a &= 0x0101010101010101UL;
335 return popcount64 (a);
343 assert (code_size == 8);
347 inline int hamming (
const uint8_t *b)
const {
348 return generalized_hamming_64 (*(uint64_t *)b ^ a0);
357 assert (code_size == 16);
358 const uint64_t *a = (uint64_t *)a8;
359 a0 = a[0]; a1 = a[1];
362 inline int hamming (
const uint8_t *b8)
const {
363 const uint64_t *b = (uint64_t *)b8;
364 return generalized_hamming_64 (b[0] ^ a0) +
365 generalized_hamming_64 (b[1] ^ a1);
371 uint64_t a0, a1, a2, a3;
374 assert (code_size == 32);
375 const uint64_t *a = (uint64_t *)a8;
376 a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
379 inline int hamming (
const uint8_t *b8)
const {
380 const uint64_t *b = (uint64_t *)b8;
381 return generalized_hamming_64 (b[0] ^ a0) +
382 generalized_hamming_64 (b[1] ^ a1) +
383 generalized_hamming_64 (b[2] ^ a2) +
384 generalized_hamming_64 (b[3] ^ a3);
394 assert (code_size % 8 == 0);
399 int hamming (
const uint8_t *b8)
const {
400 const uint64_t *b = (uint64_t *)b8;
402 for (
int i = 0; i < n; i++)
403 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)