faiss 0.1.7 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (219) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/README.md +7 -7
  4. data/ext/faiss/ext.cpp +1 -1
  5. data/ext/faiss/extconf.rb +8 -2
  6. data/ext/faiss/index.cpp +102 -69
  7. data/ext/faiss/index_binary.cpp +24 -30
  8. data/ext/faiss/kmeans.cpp +20 -16
  9. data/ext/faiss/numo.hpp +867 -0
  10. data/ext/faiss/pca_matrix.cpp +13 -14
  11. data/ext/faiss/product_quantizer.cpp +23 -24
  12. data/ext/faiss/utils.cpp +10 -37
  13. data/ext/faiss/utils.h +2 -13
  14. data/lib/faiss/version.rb +1 -1
  15. data/lib/faiss.rb +0 -5
  16. data/vendor/faiss/faiss/AutoTune.cpp +292 -291
  17. data/vendor/faiss/faiss/AutoTune.h +55 -56
  18. data/vendor/faiss/faiss/Clustering.cpp +334 -195
  19. data/vendor/faiss/faiss/Clustering.h +88 -35
  20. data/vendor/faiss/faiss/IVFlib.cpp +171 -195
  21. data/vendor/faiss/faiss/IVFlib.h +48 -51
  22. data/vendor/faiss/faiss/Index.cpp +85 -103
  23. data/vendor/faiss/faiss/Index.h +54 -48
  24. data/vendor/faiss/faiss/Index2Layer.cpp +139 -164
  25. data/vendor/faiss/faiss/Index2Layer.h +22 -22
  26. data/vendor/faiss/faiss/IndexBinary.cpp +45 -37
  27. data/vendor/faiss/faiss/IndexBinary.h +140 -132
  28. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +73 -53
  29. data/vendor/faiss/faiss/IndexBinaryFlat.h +29 -24
  30. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +46 -43
  31. data/vendor/faiss/faiss/IndexBinaryFromFloat.h +16 -15
  32. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +215 -232
  33. data/vendor/faiss/faiss/IndexBinaryHNSW.h +25 -24
  34. data/vendor/faiss/faiss/IndexBinaryHash.cpp +182 -177
  35. data/vendor/faiss/faiss/IndexBinaryHash.h +41 -34
  36. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +489 -461
  37. data/vendor/faiss/faiss/IndexBinaryIVF.h +97 -68
  38. data/vendor/faiss/faiss/IndexFlat.cpp +116 -147
  39. data/vendor/faiss/faiss/IndexFlat.h +35 -46
  40. data/vendor/faiss/faiss/IndexHNSW.cpp +372 -348
  41. data/vendor/faiss/faiss/IndexHNSW.h +57 -41
  42. data/vendor/faiss/faiss/IndexIVF.cpp +474 -454
  43. data/vendor/faiss/faiss/IndexIVF.h +146 -113
  44. data/vendor/faiss/faiss/IndexIVFFlat.cpp +248 -250
  45. data/vendor/faiss/faiss/IndexIVFFlat.h +48 -51
  46. data/vendor/faiss/faiss/IndexIVFPQ.cpp +457 -516
  47. data/vendor/faiss/faiss/IndexIVFPQ.h +74 -66
  48. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +406 -372
  49. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +82 -57
  50. data/vendor/faiss/faiss/IndexIVFPQR.cpp +104 -102
  51. data/vendor/faiss/faiss/IndexIVFPQR.h +33 -28
  52. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +125 -133
  53. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +19 -21
  54. data/vendor/faiss/faiss/IndexLSH.cpp +75 -96
  55. data/vendor/faiss/faiss/IndexLSH.h +21 -26
  56. data/vendor/faiss/faiss/IndexLattice.cpp +42 -56
  57. data/vendor/faiss/faiss/IndexLattice.h +11 -16
  58. data/vendor/faiss/faiss/IndexNNDescent.cpp +231 -0
  59. data/vendor/faiss/faiss/IndexNNDescent.h +72 -0
  60. data/vendor/faiss/faiss/IndexNSG.cpp +303 -0
  61. data/vendor/faiss/faiss/IndexNSG.h +85 -0
  62. data/vendor/faiss/faiss/IndexPQ.cpp +405 -464
  63. data/vendor/faiss/faiss/IndexPQ.h +64 -67
  64. data/vendor/faiss/faiss/IndexPQFastScan.cpp +143 -170
  65. data/vendor/faiss/faiss/IndexPQFastScan.h +46 -32
  66. data/vendor/faiss/faiss/IndexPreTransform.cpp +120 -150
  67. data/vendor/faiss/faiss/IndexPreTransform.h +33 -36
  68. data/vendor/faiss/faiss/IndexRefine.cpp +115 -131
  69. data/vendor/faiss/faiss/IndexRefine.h +22 -23
  70. data/vendor/faiss/faiss/IndexReplicas.cpp +147 -153
  71. data/vendor/faiss/faiss/IndexReplicas.h +62 -56
  72. data/vendor/faiss/faiss/IndexResidual.cpp +291 -0
  73. data/vendor/faiss/faiss/IndexResidual.h +152 -0
  74. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +120 -155
  75. data/vendor/faiss/faiss/IndexScalarQuantizer.h +41 -45
  76. data/vendor/faiss/faiss/IndexShards.cpp +256 -240
  77. data/vendor/faiss/faiss/IndexShards.h +85 -73
  78. data/vendor/faiss/faiss/MatrixStats.cpp +112 -97
  79. data/vendor/faiss/faiss/MatrixStats.h +7 -10
  80. data/vendor/faiss/faiss/MetaIndexes.cpp +135 -157
  81. data/vendor/faiss/faiss/MetaIndexes.h +40 -34
  82. data/vendor/faiss/faiss/MetricType.h +7 -7
  83. data/vendor/faiss/faiss/VectorTransform.cpp +652 -474
  84. data/vendor/faiss/faiss/VectorTransform.h +61 -89
  85. data/vendor/faiss/faiss/clone_index.cpp +77 -73
  86. data/vendor/faiss/faiss/clone_index.h +4 -9
  87. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +33 -38
  88. data/vendor/faiss/faiss/gpu/GpuAutoTune.h +11 -9
  89. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +197 -170
  90. data/vendor/faiss/faiss/gpu/GpuCloner.h +53 -35
  91. data/vendor/faiss/faiss/gpu/GpuClonerOptions.cpp +12 -14
  92. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +27 -25
  93. data/vendor/faiss/faiss/gpu/GpuDistance.h +116 -112
  94. data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -2
  95. data/vendor/faiss/faiss/gpu/GpuIndex.h +134 -137
  96. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +76 -73
  97. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +173 -162
  98. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +67 -64
  99. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +89 -86
  100. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +150 -141
  101. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +101 -103
  102. data/vendor/faiss/faiss/gpu/GpuIndicesOptions.h +17 -16
  103. data/vendor/faiss/faiss/gpu/GpuResources.cpp +116 -128
  104. data/vendor/faiss/faiss/gpu/GpuResources.h +182 -186
  105. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +433 -422
  106. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +131 -130
  107. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +468 -456
  108. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.h +25 -19
  109. data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +22 -20
  110. data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +9 -8
  111. data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +39 -44
  112. data/vendor/faiss/faiss/gpu/perf/IndexWrapper.h +16 -14
  113. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +77 -71
  114. data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +109 -88
  115. data/vendor/faiss/faiss/gpu/perf/WriteIndex.cpp +75 -64
  116. data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +230 -215
  117. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +80 -86
  118. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +284 -277
  119. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +416 -416
  120. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +611 -517
  121. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +166 -164
  122. data/vendor/faiss/faiss/gpu/test/TestGpuMemoryException.cpp +61 -53
  123. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +274 -238
  124. data/vendor/faiss/faiss/gpu/test/TestUtils.h +73 -57
  125. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +47 -50
  126. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +79 -72
  127. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +140 -146
  128. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.h +69 -71
  129. data/vendor/faiss/faiss/gpu/utils/StaticUtils.h +21 -16
  130. data/vendor/faiss/faiss/gpu/utils/Timer.cpp +25 -29
  131. data/vendor/faiss/faiss/gpu/utils/Timer.h +30 -29
  132. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +270 -0
  133. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +115 -0
  134. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +90 -120
  135. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +81 -65
  136. data/vendor/faiss/faiss/impl/FaissAssert.h +73 -58
  137. data/vendor/faiss/faiss/impl/FaissException.cpp +56 -48
  138. data/vendor/faiss/faiss/impl/FaissException.h +41 -29
  139. data/vendor/faiss/faiss/impl/HNSW.cpp +595 -611
  140. data/vendor/faiss/faiss/impl/HNSW.h +179 -200
  141. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +672 -0
  142. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +172 -0
  143. data/vendor/faiss/faiss/impl/NNDescent.cpp +487 -0
  144. data/vendor/faiss/faiss/impl/NNDescent.h +154 -0
  145. data/vendor/faiss/faiss/impl/NSG.cpp +682 -0
  146. data/vendor/faiss/faiss/impl/NSG.h +199 -0
  147. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +484 -454
  148. data/vendor/faiss/faiss/impl/PolysemousTraining.h +52 -55
  149. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +26 -47
  150. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +469 -459
  151. data/vendor/faiss/faiss/impl/ProductQuantizer.h +76 -87
  152. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +448 -0
  153. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +130 -0
  154. data/vendor/faiss/faiss/impl/ResultHandler.h +96 -132
  155. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +648 -701
  156. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +48 -46
  157. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +129 -131
  158. data/vendor/faiss/faiss/impl/ThreadedIndex.h +61 -55
  159. data/vendor/faiss/faiss/impl/index_read.cpp +547 -479
  160. data/vendor/faiss/faiss/impl/index_write.cpp +497 -407
  161. data/vendor/faiss/faiss/impl/io.cpp +75 -94
  162. data/vendor/faiss/faiss/impl/io.h +31 -41
  163. data/vendor/faiss/faiss/impl/io_macros.h +40 -29
  164. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +137 -186
  165. data/vendor/faiss/faiss/impl/lattice_Zn.h +40 -51
  166. data/vendor/faiss/faiss/impl/platform_macros.h +29 -8
  167. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +77 -124
  168. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +39 -48
  169. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +41 -52
  170. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +80 -117
  171. data/vendor/faiss/faiss/impl/simd_result_handlers.h +109 -137
  172. data/vendor/faiss/faiss/index_factory.cpp +269 -218
  173. data/vendor/faiss/faiss/index_factory.h +6 -7
  174. data/vendor/faiss/faiss/index_io.h +23 -26
  175. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +67 -75
  176. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +22 -24
  177. data/vendor/faiss/faiss/invlists/DirectMap.cpp +96 -112
  178. data/vendor/faiss/faiss/invlists/DirectMap.h +29 -33
  179. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +307 -364
  180. data/vendor/faiss/faiss/invlists/InvertedLists.h +151 -151
  181. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +29 -34
  182. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.h +17 -18
  183. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +257 -293
  184. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +50 -45
  185. data/vendor/faiss/faiss/python/python_callbacks.cpp +23 -26
  186. data/vendor/faiss/faiss/python/python_callbacks.h +9 -16
  187. data/vendor/faiss/faiss/utils/AlignedTable.h +79 -44
  188. data/vendor/faiss/faiss/utils/Heap.cpp +40 -48
  189. data/vendor/faiss/faiss/utils/Heap.h +186 -209
  190. data/vendor/faiss/faiss/utils/WorkerThread.cpp +67 -76
  191. data/vendor/faiss/faiss/utils/WorkerThread.h +32 -33
  192. data/vendor/faiss/faiss/utils/distances.cpp +301 -310
  193. data/vendor/faiss/faiss/utils/distances.h +133 -118
  194. data/vendor/faiss/faiss/utils/distances_simd.cpp +456 -516
  195. data/vendor/faiss/faiss/utils/extra_distances-inl.h +117 -0
  196. data/vendor/faiss/faiss/utils/extra_distances.cpp +113 -232
  197. data/vendor/faiss/faiss/utils/extra_distances.h +30 -29
  198. data/vendor/faiss/faiss/utils/hamming-inl.h +260 -209
  199. data/vendor/faiss/faiss/utils/hamming.cpp +375 -469
  200. data/vendor/faiss/faiss/utils/hamming.h +62 -85
  201. data/vendor/faiss/faiss/utils/ordered_key_value.h +16 -18
  202. data/vendor/faiss/faiss/utils/partitioning.cpp +393 -318
  203. data/vendor/faiss/faiss/utils/partitioning.h +26 -21
  204. data/vendor/faiss/faiss/utils/quantize_lut.cpp +78 -66
  205. data/vendor/faiss/faiss/utils/quantize_lut.h +22 -20
  206. data/vendor/faiss/faiss/utils/random.cpp +39 -63
  207. data/vendor/faiss/faiss/utils/random.h +13 -16
  208. data/vendor/faiss/faiss/utils/simdlib.h +4 -2
  209. data/vendor/faiss/faiss/utils/simdlib_avx2.h +88 -85
  210. data/vendor/faiss/faiss/utils/simdlib_emulated.h +226 -165
  211. data/vendor/faiss/faiss/utils/simdlib_neon.h +832 -0
  212. data/vendor/faiss/faiss/utils/utils.cpp +304 -287
  213. data/vendor/faiss/faiss/utils/utils.h +53 -48
  214. metadata +26 -12
  215. data/lib/faiss/index.rb +0 -20
  216. data/lib/faiss/index_binary.rb +0 -20
  217. data/lib/faiss/kmeans.rb +0 -15
  218. data/lib/faiss/pca_matrix.rb +0 -15
  219. data/lib/faiss/product_quantizer.rb +0 -22
@@ -7,15 +7,15 @@
7
7
 
8
8
  namespace faiss {
9
9
 
10
+ extern const uint8_t hamdis_tab_ham_bytes[256];
10
11
 
11
- inline BitstringWriter::BitstringWriter(uint8_t *code, size_t code_size):
12
- code (code), code_size (code_size), i(0)
13
- {
14
- memset (code, 0, code_size);
12
+ inline BitstringWriter::BitstringWriter(uint8_t* code, size_t code_size)
13
+ : code(code), code_size(code_size), i(0) {
14
+ memset(code, 0, code_size);
15
15
  }
16
16
 
17
17
  inline void BitstringWriter::write(uint64_t x, int nbit) {
18
- assert (code_size * 8 >= nbit + i);
18
+ assert(code_size * 8 >= nbit + i);
19
19
  // nb of available bits in i / 8
20
20
  int na = 8 - (i & 7);
21
21
 
@@ -35,13 +35,11 @@ inline void BitstringWriter::write(uint64_t x, int nbit) {
35
35
  }
36
36
  }
37
37
 
38
-
39
- inline BitstringReader::BitstringReader(const uint8_t *code, size_t code_size):
40
- code (code), code_size (code_size), i(0)
41
- {}
38
+ inline BitstringReader::BitstringReader(const uint8_t* code, size_t code_size)
39
+ : code(code), code_size(code_size), i(0) {}
42
40
 
43
41
  inline uint64_t BitstringReader::read(int nbit) {
44
- assert (code_size * 8 >= nbit + i);
42
+ assert(code_size * 8 >= nbit + i);
45
43
  // nb of available bits in i / 8
46
44
  int na = 8 - (i & 7);
47
45
  // get available bits in current byte
@@ -67,7 +65,6 @@ inline uint64_t BitstringReader::read(int nbit) {
67
65
  }
68
66
  }
69
67
 
70
-
71
68
  /******************************************************************
72
69
  * The HammingComputer series of classes compares a single code of
73
70
  * size 4 to 32 to incoming codes. They are intended for use as a
@@ -76,68 +73,64 @@ inline uint64_t BitstringReader::read(int nbit) {
76
73
  * hamming() functions and put the a0, a1, ... in registers.
77
74
  ******************************************************************/
78
75
 
79
-
80
76
  struct HammingComputer4 {
81
77
  uint32_t a0;
82
78
 
83
- HammingComputer4 () {}
79
+ HammingComputer4() {}
84
80
 
85
- HammingComputer4 (const uint8_t *a, int code_size) {
86
- set (a, code_size);
81
+ HammingComputer4(const uint8_t* a, int code_size) {
82
+ set(a, code_size);
87
83
  }
88
84
 
89
- void set (const uint8_t *a, int code_size) {
90
- assert (code_size == 4);
91
- a0 = *(uint32_t *)a;
85
+ void set(const uint8_t* a, int code_size) {
86
+ assert(code_size == 4);
87
+ a0 = *(uint32_t*)a;
92
88
  }
93
89
 
94
- inline int hamming (const uint8_t *b) const {
95
- return popcount64 (*(uint32_t *)b ^ a0);
90
+ inline int hamming(const uint8_t* b) const {
91
+ return popcount64(*(uint32_t*)b ^ a0);
96
92
  }
97
-
98
93
  };
99
94
 
100
95
  struct HammingComputer8 {
101
96
  uint64_t a0;
102
97
 
103
- HammingComputer8 () {}
98
+ HammingComputer8() {}
104
99
 
105
- HammingComputer8 (const uint8_t *a, int code_size) {
106
- set (a, code_size);
100
+ HammingComputer8(const uint8_t* a, int code_size) {
101
+ set(a, code_size);
107
102
  }
108
103
 
109
- void set (const uint8_t *a, int code_size) {
110
- assert (code_size == 8);
111
- a0 = *(uint64_t *)a;
104
+ void set(const uint8_t* a, int code_size) {
105
+ assert(code_size == 8);
106
+ a0 = *(uint64_t*)a;
112
107
  }
113
108
 
114
- inline int hamming (const uint8_t *b) const {
115
- return popcount64 (*(uint64_t *)b ^ a0);
109
+ inline int hamming(const uint8_t* b) const {
110
+ return popcount64(*(uint64_t*)b ^ a0);
116
111
  }
117
-
118
112
  };
119
113
 
120
-
121
114
  struct HammingComputer16 {
122
115
  uint64_t a0, a1;
123
116
 
124
- HammingComputer16 () {}
117
+ HammingComputer16() {}
125
118
 
126
- HammingComputer16 (const uint8_t *a8, int code_size) {
127
- set (a8, code_size);
119
+ HammingComputer16(const uint8_t* a8, int code_size) {
120
+ set(a8, code_size);
128
121
  }
129
122
 
130
- void set (const uint8_t *a8, int code_size) {
131
- assert (code_size == 16);
132
- const uint64_t *a = (uint64_t *)a8;
133
- a0 = a[0]; a1 = a[1];
123
+ void set(const uint8_t* a8, int code_size) {
124
+ assert(code_size == 16);
125
+ const uint64_t* a = (uint64_t*)a8;
126
+ a0 = a[0];
127
+ a1 = a[1];
134
128
  }
135
129
 
136
- inline int hamming (const uint8_t *b8) const {
137
- const uint64_t *b = (uint64_t *)b8;
138
- return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1);
130
+ inline int hamming(const uint8_t* b8) const {
131
+ const uint64_t* b = (uint64_t*)b8;
132
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1);
139
133
  }
140
-
141
134
  };
142
135
 
143
136
  // when applied to an array, 1/2 of the 64-bit accesses are unaligned.
@@ -146,150 +139,212 @@ struct HammingComputer20 {
146
139
  uint64_t a0, a1;
147
140
  uint32_t a2;
148
141
 
149
- HammingComputer20 () {}
142
+ HammingComputer20() {}
150
143
 
151
- HammingComputer20 (const uint8_t *a8, int code_size) {
152
- set (a8, code_size);
144
+ HammingComputer20(const uint8_t* a8, int code_size) {
145
+ set(a8, code_size);
153
146
  }
154
147
 
155
- void set (const uint8_t *a8, int code_size) {
156
- assert (code_size == 20);
157
- const uint64_t *a = (uint64_t *)a8;
158
- a0 = a[0]; a1 = a[1]; a2 = a[2];
148
+ void set(const uint8_t* a8, int code_size) {
149
+ assert(code_size == 20);
150
+ const uint64_t* a = (uint64_t*)a8;
151
+ a0 = a[0];
152
+ a1 = a[1];
153
+ a2 = a[2];
159
154
  }
160
155
 
161
- inline int hamming (const uint8_t *b8) const {
162
- const uint64_t *b = (uint64_t *)b8;
163
- return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
164
- popcount64 (*(uint32_t*)(b + 2) ^ a2);
156
+ inline int hamming(const uint8_t* b8) const {
157
+ const uint64_t* b = (uint64_t*)b8;
158
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
159
+ popcount64(*(uint32_t*)(b + 2) ^ a2);
165
160
  }
166
161
  };
167
162
 
168
163
  struct HammingComputer32 {
169
164
  uint64_t a0, a1, a2, a3;
170
165
 
171
- HammingComputer32 () {}
166
+ HammingComputer32() {}
172
167
 
173
- HammingComputer32 (const uint8_t *a8, int code_size) {
174
- set (a8, code_size);
168
+ HammingComputer32(const uint8_t* a8, int code_size) {
169
+ set(a8, code_size);
175
170
  }
176
171
 
177
- void set (const uint8_t *a8, int code_size) {
178
- assert (code_size == 32);
179
- const uint64_t *a = (uint64_t *)a8;
180
- a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
172
+ void set(const uint8_t* a8, int code_size) {
173
+ assert(code_size == 32);
174
+ const uint64_t* a = (uint64_t*)a8;
175
+ a0 = a[0];
176
+ a1 = a[1];
177
+ a2 = a[2];
178
+ a3 = a[3];
181
179
  }
182
180
 
183
- inline int hamming (const uint8_t *b8) const {
184
- const uint64_t *b = (uint64_t *)b8;
185
- return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
186
- popcount64 (b[2] ^ a2) + popcount64 (b[3] ^ a3);
181
+ inline int hamming(const uint8_t* b8) const {
182
+ const uint64_t* b = (uint64_t*)b8;
183
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
184
+ popcount64(b[2] ^ a2) + popcount64(b[3] ^ a3);
187
185
  }
188
-
189
186
  };
190
187
 
191
188
  struct HammingComputer64 {
192
189
  uint64_t a0, a1, a2, a3, a4, a5, a6, a7;
193
190
 
194
- HammingComputer64 () {}
191
+ HammingComputer64() {}
195
192
 
196
- HammingComputer64 (const uint8_t *a8, int code_size) {
197
- set (a8, code_size);
193
+ HammingComputer64(const uint8_t* a8, int code_size) {
194
+ set(a8, code_size);
198
195
  }
199
196
 
200
- void set (const uint8_t *a8, int code_size) {
201
- assert (code_size == 64);
202
- const uint64_t *a = (uint64_t *)a8;
203
- a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3];
204
- a4 = a[4]; a5 = a[5]; a6 = a[6]; a7 = a[7];
197
+ void set(const uint8_t* a8, int code_size) {
198
+ assert(code_size == 64);
199
+ const uint64_t* a = (uint64_t*)a8;
200
+ a0 = a[0];
201
+ a1 = a[1];
202
+ a2 = a[2];
203
+ a3 = a[3];
204
+ a4 = a[4];
205
+ a5 = a[5];
206
+ a6 = a[6];
207
+ a7 = a[7];
205
208
  }
206
209
 
207
- inline int hamming (const uint8_t *b8) const {
208
- const uint64_t *b = (uint64_t *)b8;
209
- return popcount64 (b[0] ^ a0) + popcount64 (b[1] ^ a1) +
210
- popcount64 (b[2] ^ a2) + popcount64 (b[3] ^ a3) +
211
- popcount64 (b[4] ^ a4) + popcount64 (b[5] ^ a5) +
212
- popcount64 (b[6] ^ a6) + popcount64 (b[7] ^ a7);
210
+ inline int hamming(const uint8_t* b8) const {
211
+ const uint64_t* b = (uint64_t*)b8;
212
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
213
+ popcount64(b[2] ^ a2) + popcount64(b[3] ^ a3) +
214
+ popcount64(b[4] ^ a4) + popcount64(b[5] ^ a5) +
215
+ popcount64(b[6] ^ a6) + popcount64(b[7] ^ a7);
213
216
  }
214
-
215
217
  };
216
218
 
217
- // very inefficient...
218
219
  struct HammingComputerDefault {
219
- const uint8_t *a;
220
- int n;
220
+ const uint8_t* a8;
221
+ int quotient8;
222
+ int remainder8;
221
223
 
222
- HammingComputerDefault () {}
224
+ HammingComputerDefault() {}
223
225
 
224
- HammingComputerDefault (const uint8_t *a8, int code_size) {
225
- set (a8, code_size);
226
+ HammingComputerDefault(const uint8_t* a8, int code_size) {
227
+ set(a8, code_size);
226
228
  }
227
229
 
228
- void set (const uint8_t *a8, int code_size) {
229
- a = a8;
230
- n = code_size;
230
+ void set(const uint8_t* a8, int code_size) {
231
+ this->a8 = a8;
232
+ quotient8 = code_size / 8;
233
+ remainder8 = code_size % 8;
231
234
  }
232
235
 
233
- int hamming (const uint8_t *b8) const {
236
+ int hamming(const uint8_t* b8) const {
234
237
  int accu = 0;
235
- for (int i = 0; i < n; i++)
236
- accu += popcount64 (a[i] ^ b8[i]);
238
+
239
+ const uint64_t* a64 = reinterpret_cast<const uint64_t*>(a8);
240
+ const uint64_t* b64 = reinterpret_cast<const uint64_t*>(b8);
241
+ int i = 0, len = quotient8;
242
+ switch (len & 7) {
243
+ default:
244
+ while (len > 7) {
245
+ len -= 8;
246
+ accu += popcount64(a64[i] ^ b64[i]);
247
+ i++;
248
+ case 7:
249
+ accu += popcount64(a64[i] ^ b64[i]);
250
+ i++;
251
+ case 6:
252
+ accu += popcount64(a64[i] ^ b64[i]);
253
+ i++;
254
+ case 5:
255
+ accu += popcount64(a64[i] ^ b64[i]);
256
+ i++;
257
+ case 4:
258
+ accu += popcount64(a64[i] ^ b64[i]);
259
+ i++;
260
+ case 3:
261
+ accu += popcount64(a64[i] ^ b64[i]);
262
+ i++;
263
+ case 2:
264
+ accu += popcount64(a64[i] ^ b64[i]);
265
+ i++;
266
+ case 1:
267
+ accu += popcount64(a64[i] ^ b64[i]);
268
+ i++;
269
+ }
270
+ }
271
+ if (remainder8) {
272
+ const uint8_t* a = a8 + 8 * quotient8;
273
+ const uint8_t* b = b8 + 8 * quotient8;
274
+ switch (remainder8) {
275
+ case 7:
276
+ accu += hamdis_tab_ham_bytes[a[6] ^ b[6]];
277
+ case 6:
278
+ accu += hamdis_tab_ham_bytes[a[5] ^ b[5]];
279
+ case 5:
280
+ accu += hamdis_tab_ham_bytes[a[4] ^ b[4]];
281
+ case 4:
282
+ accu += hamdis_tab_ham_bytes[a[3] ^ b[3]];
283
+ case 3:
284
+ accu += hamdis_tab_ham_bytes[a[2] ^ b[2]];
285
+ case 2:
286
+ accu += hamdis_tab_ham_bytes[a[1] ^ b[1]];
287
+ case 1:
288
+ accu += hamdis_tab_ham_bytes[a[0] ^ b[0]];
289
+ default:
290
+ break;
291
+ }
292
+ }
293
+
237
294
  return accu;
238
295
  }
239
-
240
296
  };
241
297
 
298
+ // more inefficient than HammingComputerDefault (obsolete)
242
299
  struct HammingComputerM8 {
243
- const uint64_t *a;
300
+ const uint64_t* a;
244
301
  int n;
245
302
 
246
- HammingComputerM8 () {}
303
+ HammingComputerM8() {}
247
304
 
248
- HammingComputerM8 (const uint8_t *a8, int code_size) {
249
- set (a8, code_size);
305
+ HammingComputerM8(const uint8_t* a8, int code_size) {
306
+ set(a8, code_size);
250
307
  }
251
308
 
252
- void set (const uint8_t *a8, int code_size) {
253
- assert (code_size % 8 == 0);
254
- a = (uint64_t *)a8;
309
+ void set(const uint8_t* a8, int code_size) {
310
+ assert(code_size % 8 == 0);
311
+ a = (uint64_t*)a8;
255
312
  n = code_size / 8;
256
313
  }
257
314
 
258
- int hamming (const uint8_t *b8) const {
259
- const uint64_t *b = (uint64_t *)b8;
315
+ int hamming(const uint8_t* b8) const {
316
+ const uint64_t* b = (uint64_t*)b8;
260
317
  int accu = 0;
261
318
  for (int i = 0; i < n; i++)
262
- accu += popcount64 (a[i] ^ b[i]);
319
+ accu += popcount64(a[i] ^ b[i]);
263
320
  return accu;
264
321
  }
265
-
266
322
  };
267
323
 
268
- // even more inefficient!
324
+ // more inefficient than HammingComputerDefault (obsolete)
269
325
  struct HammingComputerM4 {
270
- const uint32_t *a;
326
+ const uint32_t* a;
271
327
  int n;
272
328
 
273
- HammingComputerM4 () {}
329
+ HammingComputerM4() {}
274
330
 
275
- HammingComputerM4 (const uint8_t *a4, int code_size) {
276
- set (a4, code_size);
331
+ HammingComputerM4(const uint8_t* a4, int code_size) {
332
+ set(a4, code_size);
277
333
  }
278
334
 
279
- void set (const uint8_t *a4, int code_size) {
280
- assert (code_size % 4 == 0);
281
- a = (uint32_t *)a4;
335
+ void set(const uint8_t* a4, int code_size) {
336
+ assert(code_size % 4 == 0);
337
+ a = (uint32_t*)a4;
282
338
  n = code_size / 4;
283
339
  }
284
340
 
285
- int hamming (const uint8_t *b8) const {
286
- const uint32_t *b = (uint32_t *)b8;
341
+ int hamming(const uint8_t* b8) const {
342
+ const uint32_t* b = (uint32_t*)b8;
287
343
  int accu = 0;
288
344
  for (int i = 0; i < n; i++)
289
- accu += popcount64 (a[i] ^ b[i]);
345
+ accu += popcount64(a[i] ^ b[i]);
290
346
  return accu;
291
347
  }
292
-
293
348
  };
294
349
 
295
350
  /***************************************************************************
@@ -297,17 +352,17 @@ struct HammingComputerM4 {
297
352
  **************************************************************************/
298
353
 
299
354
  // default template
300
- template<int CODE_SIZE>
301
- struct HammingComputer: HammingComputerM8 {
302
- HammingComputer (const uint8_t *a, int code_size):
303
- HammingComputerM8(a, code_size) {}
355
+ template <int CODE_SIZE>
356
+ struct HammingComputer : HammingComputerDefault {
357
+ HammingComputer(const uint8_t* a, int code_size)
358
+ : HammingComputerDefault(a, code_size) {}
304
359
  };
305
360
 
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) {} \
361
+ #define SPECIALIZED_HC(CODE_SIZE) \
362
+ template <> \
363
+ struct HammingComputer<CODE_SIZE> : HammingComputer##CODE_SIZE { \
364
+ HammingComputer(const uint8_t* a) \
365
+ : HammingComputer##CODE_SIZE(a, CODE_SIZE) {} \
311
366
  }
312
367
 
313
368
  SPECIALIZED_HC(4);
@@ -319,105 +374,98 @@ SPECIALIZED_HC(64);
319
374
 
320
375
  #undef SPECIALIZED_HC
321
376
 
322
-
323
377
  /***************************************************************************
324
378
  * generalized Hamming = number of bytes that are different between
325
379
  * two codes.
326
380
  ***************************************************************************/
327
381
 
328
-
329
- inline int generalized_hamming_64 (uint64_t a) {
382
+ inline int generalized_hamming_64(uint64_t a) {
330
383
  a |= a >> 1;
331
384
  a |= a >> 2;
332
385
  a |= a >> 4;
333
386
  a &= 0x0101010101010101UL;
334
- return popcount64 (a);
387
+ return popcount64(a);
335
388
  }
336
389
 
337
-
338
390
  struct GenHammingComputer8 {
339
391
  uint64_t a0;
340
392
 
341
- GenHammingComputer8 (const uint8_t *a, int code_size) {
342
- assert (code_size == 8);
343
- a0 = *(uint64_t *)a;
393
+ GenHammingComputer8(const uint8_t* a, int code_size) {
394
+ assert(code_size == 8);
395
+ a0 = *(uint64_t*)a;
344
396
  }
345
397
 
346
- inline int hamming (const uint8_t *b) const {
347
- return generalized_hamming_64 (*(uint64_t *)b ^ a0);
398
+ inline int hamming(const uint8_t* b) const {
399
+ return generalized_hamming_64(*(uint64_t*)b ^ a0);
348
400
  }
349
-
350
401
  };
351
402
 
352
-
353
403
  struct GenHammingComputer16 {
354
404
  uint64_t a0, a1;
355
- GenHammingComputer16 (const uint8_t *a8, int code_size) {
356
- assert (code_size == 16);
357
- const uint64_t *a = (uint64_t *)a8;
358
- a0 = a[0]; a1 = a[1];
405
+ GenHammingComputer16(const uint8_t* a8, int code_size) {
406
+ assert(code_size == 16);
407
+ const uint64_t* a = (uint64_t*)a8;
408
+ a0 = a[0];
409
+ a1 = a[1];
359
410
  }
360
411
 
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);
412
+ inline int hamming(const uint8_t* b8) const {
413
+ const uint64_t* b = (uint64_t*)b8;
414
+ return generalized_hamming_64(b[0] ^ a0) +
415
+ generalized_hamming_64(b[1] ^ a1);
365
416
  }
366
-
367
417
  };
368
418
 
369
419
  struct GenHammingComputer32 {
370
420
  uint64_t a0, a1, a2, a3;
371
421
 
372
- GenHammingComputer32 (const uint8_t *a8, int code_size) {
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];
422
+ GenHammingComputer32(const uint8_t* a8, int code_size) {
423
+ assert(code_size == 32);
424
+ const uint64_t* a = (uint64_t*)a8;
425
+ a0 = a[0];
426
+ a1 = a[1];
427
+ a2 = a[2];
428
+ a3 = a[3];
376
429
  }
377
430
 
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);
431
+ inline int hamming(const uint8_t* b8) const {
432
+ const uint64_t* b = (uint64_t*)b8;
433
+ return generalized_hamming_64(b[0] ^ a0) +
434
+ generalized_hamming_64(b[1] ^ a1) +
435
+ generalized_hamming_64(b[2] ^ a2) +
436
+ generalized_hamming_64(b[3] ^ a3);
384
437
  }
385
-
386
438
  };
387
439
 
388
440
  struct GenHammingComputerM8 {
389
- const uint64_t *a;
441
+ const uint64_t* a;
390
442
  int n;
391
443
 
392
- GenHammingComputerM8 (const uint8_t *a8, int code_size) {
393
- assert (code_size % 8 == 0);
394
- a = (uint64_t *)a8;
444
+ GenHammingComputerM8(const uint8_t* a8, int code_size) {
445
+ assert(code_size % 8 == 0);
446
+ a = (uint64_t*)a8;
395
447
  n = code_size / 8;
396
448
  }
397
449
 
398
- int hamming (const uint8_t *b8) const {
399
- const uint64_t *b = (uint64_t *)b8;
450
+ int hamming(const uint8_t* b8) const {
451
+ const uint64_t* b = (uint64_t*)b8;
400
452
  int accu = 0;
401
453
  for (int i = 0; i < n; i++)
402
- accu += generalized_hamming_64 (a[i] ^ b[i]);
454
+ accu += generalized_hamming_64(a[i] ^ b[i]);
403
455
  return accu;
404
456
  }
405
-
406
457
  };
407
458
 
408
-
409
459
  /** generalized Hamming distances (= count number of code bytes that
410
460
  are the same) */
411
- void generalized_hammings_knn_hc (
412
- int_maxheap_array_t * ha,
413
- const uint8_t * a,
414
- const uint8_t * b,
461
+ void generalized_hammings_knn_hc(
462
+ int_maxheap_array_t* ha,
463
+ const uint8_t* a,
464
+ const uint8_t* b,
415
465
  size_t nb,
416
466
  size_t code_size,
417
467
  int ordered = true);
418
468
 
419
-
420
-
421
469
  /** This class maintains a list of best distances seen so far.
422
470
  *
423
471
  * Since the distances are in a limited range (0 to nbit), the
@@ -425,46 +473,49 @@ void generalized_hammings_knn_hc (
425
473
  * in only the n-first lists, such that the sum of sizes of the
426
474
  * n lists is below k.
427
475
  */
428
- template<class HammingComputer>
476
+ template <class HammingComputer>
429
477
  struct HCounterState {
430
- int *counters;
431
- int64_t *ids_per_dis;
432
-
433
- HammingComputer hc;
434
- int thres;
435
- int count_lt;
436
- int count_eq;
437
- int k;
438
-
439
- HCounterState(int *counters, int64_t *ids_per_dis,
440
- const uint8_t *x, int d, int k)
441
- : counters(counters),
442
- ids_per_dis(ids_per_dis),
443
- hc(x, d / 8),
444
- thres(d + 1),
445
- count_lt(0),
446
- count_eq(0),
447
- k(k) {}
448
-
449
- void update_counter(const uint8_t *y, size_t j) {
450
- int32_t dis = hc.hamming(y);
451
-
452
- if (dis <= thres) {
453
- if (dis < thres) {
454
- ids_per_dis[dis * k + counters[dis]++] = j;
455
- ++count_lt;
456
- while (count_lt == k && thres > 0) {
457
- --thres;
458
- count_eq = counters[thres];
459
- count_lt -= count_eq;
478
+ int* counters;
479
+ int64_t* ids_per_dis;
480
+
481
+ HammingComputer hc;
482
+ int thres;
483
+ int count_lt;
484
+ int count_eq;
485
+ int k;
486
+
487
+ HCounterState(
488
+ int* counters,
489
+ int64_t* ids_per_dis,
490
+ const uint8_t* x,
491
+ int d,
492
+ int k)
493
+ : counters(counters),
494
+ ids_per_dis(ids_per_dis),
495
+ hc(x, d / 8),
496
+ thres(d + 1),
497
+ count_lt(0),
498
+ count_eq(0),
499
+ k(k) {}
500
+
501
+ void update_counter(const uint8_t* y, size_t j) {
502
+ int32_t dis = hc.hamming(y);
503
+
504
+ if (dis <= thres) {
505
+ if (dis < thres) {
506
+ ids_per_dis[dis * k + counters[dis]++] = j;
507
+ ++count_lt;
508
+ while (count_lt == k && thres > 0) {
509
+ --thres;
510
+ count_eq = counters[thres];
511
+ count_lt -= count_eq;
512
+ }
513
+ } else if (count_eq < k) {
514
+ ids_per_dis[dis * k + count_eq++] = j;
515
+ counters[dis] = count_eq;
516
+ }
460
517
  }
461
- } else if (count_eq < k) {
462
- ids_per_dis[dis * k + count_eq++] = j;
463
- counters[dis] = count_eq;
464
- }
465
518
  }
466
- }
467
519
  };
468
520
 
469
-
470
521
  } // namespace faiss