faiss 0.2.6 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/ext/faiss/extconf.rb +1 -1
  4. data/lib/faiss/version.rb +1 -1
  5. data/lib/faiss.rb +2 -2
  6. data/vendor/faiss/faiss/AutoTune.cpp +15 -4
  7. data/vendor/faiss/faiss/AutoTune.h +0 -1
  8. data/vendor/faiss/faiss/Clustering.cpp +1 -5
  9. data/vendor/faiss/faiss/Clustering.h +0 -2
  10. data/vendor/faiss/faiss/IVFlib.h +0 -2
  11. data/vendor/faiss/faiss/Index.h +1 -2
  12. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +17 -3
  13. data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +10 -1
  14. data/vendor/faiss/faiss/IndexBinary.h +0 -1
  15. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +2 -1
  16. data/vendor/faiss/faiss/IndexBinaryFlat.h +4 -0
  17. data/vendor/faiss/faiss/IndexBinaryHash.cpp +1 -3
  18. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +273 -48
  19. data/vendor/faiss/faiss/IndexBinaryIVF.h +18 -11
  20. data/vendor/faiss/faiss/IndexFastScan.cpp +13 -10
  21. data/vendor/faiss/faiss/IndexFastScan.h +5 -1
  22. data/vendor/faiss/faiss/IndexFlat.cpp +16 -3
  23. data/vendor/faiss/faiss/IndexFlat.h +1 -1
  24. data/vendor/faiss/faiss/IndexFlatCodes.cpp +5 -0
  25. data/vendor/faiss/faiss/IndexFlatCodes.h +7 -2
  26. data/vendor/faiss/faiss/IndexHNSW.cpp +3 -6
  27. data/vendor/faiss/faiss/IndexHNSW.h +0 -1
  28. data/vendor/faiss/faiss/IndexIDMap.cpp +4 -4
  29. data/vendor/faiss/faiss/IndexIDMap.h +0 -2
  30. data/vendor/faiss/faiss/IndexIVF.cpp +155 -129
  31. data/vendor/faiss/faiss/IndexIVF.h +121 -61
  32. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +2 -2
  33. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +12 -11
  34. data/vendor/faiss/faiss/IndexIVFFastScan.h +6 -1
  35. data/vendor/faiss/faiss/IndexIVFPQ.cpp +221 -165
  36. data/vendor/faiss/faiss/IndexIVFPQ.h +1 -0
  37. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +6 -1
  38. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +0 -2
  39. data/vendor/faiss/faiss/IndexNNDescent.cpp +1 -2
  40. data/vendor/faiss/faiss/IndexNNDescent.h +0 -1
  41. data/vendor/faiss/faiss/IndexNSG.cpp +1 -2
  42. data/vendor/faiss/faiss/IndexPQ.cpp +7 -9
  43. data/vendor/faiss/faiss/IndexRefine.cpp +1 -1
  44. data/vendor/faiss/faiss/IndexReplicas.cpp +3 -4
  45. data/vendor/faiss/faiss/IndexReplicas.h +0 -1
  46. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +8 -1
  47. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +7 -0
  48. data/vendor/faiss/faiss/IndexShards.cpp +26 -109
  49. data/vendor/faiss/faiss/IndexShards.h +2 -3
  50. data/vendor/faiss/faiss/IndexShardsIVF.cpp +246 -0
  51. data/vendor/faiss/faiss/IndexShardsIVF.h +42 -0
  52. data/vendor/faiss/faiss/MetaIndexes.cpp +86 -0
  53. data/vendor/faiss/faiss/MetaIndexes.h +29 -0
  54. data/vendor/faiss/faiss/MetricType.h +14 -0
  55. data/vendor/faiss/faiss/VectorTransform.cpp +8 -10
  56. data/vendor/faiss/faiss/VectorTransform.h +1 -3
  57. data/vendor/faiss/faiss/clone_index.cpp +232 -18
  58. data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +25 -3
  59. data/vendor/faiss/faiss/cppcontrib/detail/CoarseBitType.h +7 -0
  60. data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +78 -0
  61. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +20 -6
  62. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +7 -1
  63. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +21 -7
  64. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMax-inl.h +7 -0
  65. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMaxFP16-inl.h +7 -0
  66. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +10 -3
  67. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +7 -1
  68. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +11 -3
  69. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +25 -2
  70. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +76 -29
  71. data/vendor/faiss/faiss/gpu/GpuCloner.h +2 -2
  72. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +14 -13
  73. data/vendor/faiss/faiss/gpu/GpuDistance.h +18 -6
  74. data/vendor/faiss/faiss/gpu/GpuIndex.h +23 -21
  75. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +10 -10
  76. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -12
  77. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +29 -50
  78. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +3 -3
  79. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +8 -8
  80. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +4 -4
  81. data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +2 -5
  82. data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +9 -7
  83. data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +4 -4
  84. data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +2 -2
  85. data/vendor/faiss/faiss/gpu/perf/IndexWrapper.h +1 -1
  86. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +55 -6
  87. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +20 -6
  88. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +95 -25
  89. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +67 -16
  90. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +4 -4
  91. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +7 -7
  92. data/vendor/faiss/faiss/gpu/test/TestUtils.h +4 -4
  93. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +1 -1
  94. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +6 -0
  95. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +0 -7
  96. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +9 -9
  97. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +1 -1
  98. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +2 -7
  99. data/vendor/faiss/faiss/impl/CodePacker.cpp +67 -0
  100. data/vendor/faiss/faiss/impl/CodePacker.h +71 -0
  101. data/vendor/faiss/faiss/impl/DistanceComputer.h +0 -2
  102. data/vendor/faiss/faiss/impl/HNSW.cpp +3 -7
  103. data/vendor/faiss/faiss/impl/HNSW.h +6 -9
  104. data/vendor/faiss/faiss/impl/IDSelector.cpp +1 -1
  105. data/vendor/faiss/faiss/impl/IDSelector.h +39 -1
  106. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +62 -51
  107. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +11 -12
  108. data/vendor/faiss/faiss/impl/NNDescent.cpp +3 -9
  109. data/vendor/faiss/faiss/impl/NNDescent.h +10 -10
  110. data/vendor/faiss/faiss/impl/NSG.cpp +1 -6
  111. data/vendor/faiss/faiss/impl/NSG.h +4 -7
  112. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +1 -15
  113. data/vendor/faiss/faiss/impl/PolysemousTraining.h +11 -10
  114. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +0 -7
  115. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +25 -12
  116. data/vendor/faiss/faiss/impl/ProductQuantizer.h +2 -4
  117. data/vendor/faiss/faiss/impl/Quantizer.h +6 -3
  118. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +796 -174
  119. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +16 -8
  120. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +3 -5
  121. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +4 -4
  122. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +3 -3
  123. data/vendor/faiss/faiss/impl/ThreadedIndex.h +4 -4
  124. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +291 -0
  125. data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +74 -0
  126. data/vendor/faiss/faiss/impl/code_distance/code_distance.h +123 -0
  127. data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +102 -0
  128. data/vendor/faiss/faiss/impl/index_read.cpp +13 -10
  129. data/vendor/faiss/faiss/impl/index_write.cpp +3 -4
  130. data/vendor/faiss/faiss/impl/kmeans1d.cpp +0 -1
  131. data/vendor/faiss/faiss/impl/kmeans1d.h +3 -3
  132. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -1
  133. data/vendor/faiss/faiss/impl/platform_macros.h +61 -0
  134. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +48 -4
  135. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +18 -4
  136. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +2 -2
  137. data/vendor/faiss/faiss/index_factory.cpp +8 -10
  138. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +29 -12
  139. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +8 -2
  140. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
  141. data/vendor/faiss/faiss/invlists/DirectMap.h +2 -4
  142. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +118 -18
  143. data/vendor/faiss/faiss/invlists/InvertedLists.h +44 -4
  144. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +3 -3
  145. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  146. data/vendor/faiss/faiss/python/python_callbacks.cpp +1 -1
  147. data/vendor/faiss/faiss/python/python_callbacks.h +1 -1
  148. data/vendor/faiss/faiss/utils/AlignedTable.h +3 -1
  149. data/vendor/faiss/faiss/utils/Heap.cpp +139 -3
  150. data/vendor/faiss/faiss/utils/Heap.h +35 -1
  151. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +84 -0
  152. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +196 -0
  153. data/vendor/faiss/faiss/utils/approx_topk/generic.h +138 -0
  154. data/vendor/faiss/faiss/utils/approx_topk/mode.h +34 -0
  155. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +367 -0
  156. data/vendor/faiss/faiss/utils/distances.cpp +61 -7
  157. data/vendor/faiss/faiss/utils/distances.h +11 -0
  158. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +346 -0
  159. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +36 -0
  160. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +42 -0
  161. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +40 -0
  162. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +352 -0
  163. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.h +32 -0
  164. data/vendor/faiss/faiss/utils/distances_simd.cpp +515 -327
  165. data/vendor/faiss/faiss/utils/extra_distances-inl.h +17 -1
  166. data/vendor/faiss/faiss/utils/extra_distances.cpp +37 -8
  167. data/vendor/faiss/faiss/utils/extra_distances.h +2 -1
  168. data/vendor/faiss/faiss/utils/fp16-fp16c.h +7 -0
  169. data/vendor/faiss/faiss/utils/fp16-inl.h +7 -0
  170. data/vendor/faiss/faiss/utils/fp16.h +7 -0
  171. data/vendor/faiss/faiss/utils/hamming-inl.h +0 -456
  172. data/vendor/faiss/faiss/utils/hamming.cpp +104 -120
  173. data/vendor/faiss/faiss/utils/hamming.h +21 -10
  174. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +535 -0
  175. data/vendor/faiss/faiss/utils/hamming_distance/common.h +48 -0
  176. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +519 -0
  177. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +26 -0
  178. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +614 -0
  179. data/vendor/faiss/faiss/utils/partitioning.cpp +21 -25
  180. data/vendor/faiss/faiss/utils/simdlib_avx2.h +344 -3
  181. data/vendor/faiss/faiss/utils/simdlib_emulated.h +390 -0
  182. data/vendor/faiss/faiss/utils/simdlib_neon.h +655 -130
  183. data/vendor/faiss/faiss/utils/sorting.cpp +692 -0
  184. data/vendor/faiss/faiss/utils/sorting.h +71 -0
  185. data/vendor/faiss/faiss/utils/transpose/transpose-avx2-inl.h +165 -0
  186. data/vendor/faiss/faiss/utils/utils.cpp +4 -176
  187. data/vendor/faiss/faiss/utils/utils.h +2 -9
  188. metadata +29 -3
  189. data/vendor/faiss/faiss/gpu/GpuClonerOptions.cpp +0 -26
@@ -0,0 +1,519 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #ifndef HAMMING_GENERIC_INL_H
9
+ #define HAMMING_GENERIC_INL_H
10
+
11
+ // A general-purpose version of hamming distance computation.
12
+
13
+ #include <cassert>
14
+ #include <cstddef>
15
+ #include <cstdint>
16
+
17
+ #include <faiss/impl/platform_macros.h>
18
+
19
+ namespace faiss {
20
+
21
+ /* Elementary Hamming distance computation: unoptimized */
22
+ template <size_t nbits, typename T>
23
+ inline T hamming(const uint8_t* bs1, const uint8_t* bs2) {
24
+ const size_t nbytes = nbits / 8;
25
+ size_t i;
26
+ T h = 0;
27
+ for (i = 0; i < nbytes; i++) {
28
+ h += (T)hamdis_tab_ham_bytes[bs1[i] ^ bs2[i]];
29
+ }
30
+ return h;
31
+ }
32
+
33
+ /* Hamming distances for multiples of 64 bits */
34
+ template <size_t nbits>
35
+ inline hamdis_t hamming(const uint64_t* bs1, const uint64_t* bs2) {
36
+ const size_t nwords = nbits / 64;
37
+ size_t i;
38
+ hamdis_t h = 0;
39
+ for (i = 0; i < nwords; i++) {
40
+ h += popcount64(bs1[i] ^ bs2[i]);
41
+ }
42
+ return h;
43
+ }
44
+
45
+ /* specialized (optimized) functions */
46
+ template <>
47
+ inline hamdis_t hamming<64>(const uint64_t* pa, const uint64_t* pb) {
48
+ return popcount64(pa[0] ^ pb[0]);
49
+ }
50
+
51
+ template <>
52
+ inline hamdis_t hamming<128>(const uint64_t* pa, const uint64_t* pb) {
53
+ return popcount64(pa[0] ^ pb[0]) + popcount64(pa[1] ^ pb[1]);
54
+ }
55
+
56
+ template <>
57
+ inline hamdis_t hamming<256>(const uint64_t* pa, const uint64_t* pb) {
58
+ return popcount64(pa[0] ^ pb[0]) + popcount64(pa[1] ^ pb[1]) +
59
+ popcount64(pa[2] ^ pb[2]) + popcount64(pa[3] ^ pb[3]);
60
+ }
61
+
62
+ /* Hamming distances for multiple of 64 bits */
63
+ inline hamdis_t hamming(
64
+ const uint64_t* bs1,
65
+ const uint64_t* bs2,
66
+ size_t nwords) {
67
+ hamdis_t h = 0;
68
+ for (size_t i = 0; i < nwords; i++) {
69
+ h += popcount64(bs1[i] ^ bs2[i]);
70
+ }
71
+ return h;
72
+ }
73
+
74
+ /******************************************************************
75
+ * The HammingComputer series of classes compares a single code of
76
+ * size 4 to 32 to incoming codes. They are intended for use as a
77
+ * template class where it would be inefficient to switch on the code
78
+ * size in the inner loop. Hopefully the compiler will inline the
79
+ * hamming() functions and put the a0, a1, ... in registers.
80
+ ******************************************************************/
81
+
82
+ struct HammingComputer4 {
83
+ uint32_t a0;
84
+
85
+ HammingComputer4() {}
86
+
87
+ HammingComputer4(const uint8_t* a, int code_size) {
88
+ set(a, code_size);
89
+ }
90
+
91
+ void set(const uint8_t* a, int code_size) {
92
+ assert(code_size == 4);
93
+ a0 = *(uint32_t*)a;
94
+ }
95
+
96
+ inline int hamming(const uint8_t* b) const {
97
+ return popcount64(*(uint32_t*)b ^ a0);
98
+ }
99
+
100
+ inline static constexpr int get_code_size() {
101
+ return 4;
102
+ }
103
+ };
104
+
105
+ struct HammingComputer8 {
106
+ uint64_t a0;
107
+
108
+ HammingComputer8() {}
109
+
110
+ HammingComputer8(const uint8_t* a, int code_size) {
111
+ set(a, code_size);
112
+ }
113
+
114
+ void set(const uint8_t* a, int code_size) {
115
+ assert(code_size == 8);
116
+ a0 = *(uint64_t*)a;
117
+ }
118
+
119
+ inline int hamming(const uint8_t* b) const {
120
+ return popcount64(*(uint64_t*)b ^ a0);
121
+ }
122
+
123
+ inline static constexpr int get_code_size() {
124
+ return 8;
125
+ }
126
+ };
127
+
128
+ struct HammingComputer16 {
129
+ uint64_t a0, a1;
130
+
131
+ HammingComputer16() {}
132
+
133
+ HammingComputer16(const uint8_t* a8, int code_size) {
134
+ set(a8, code_size);
135
+ }
136
+
137
+ void set(const uint8_t* a8, int code_size) {
138
+ assert(code_size == 16);
139
+ const uint64_t* a = (uint64_t*)a8;
140
+ a0 = a[0];
141
+ a1 = a[1];
142
+ }
143
+
144
+ inline int hamming(const uint8_t* b8) const {
145
+ const uint64_t* b = (uint64_t*)b8;
146
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1);
147
+ }
148
+
149
+ inline static constexpr int get_code_size() {
150
+ return 16;
151
+ }
152
+ };
153
+
154
+ // when applied to an array, 1/2 of the 64-bit accesses are unaligned.
155
+ // This incurs a penalty of ~10% wrt. fully aligned accesses.
156
+ struct HammingComputer20 {
157
+ uint64_t a0, a1;
158
+ uint32_t a2;
159
+
160
+ HammingComputer20() {}
161
+
162
+ HammingComputer20(const uint8_t* a8, int code_size) {
163
+ set(a8, code_size);
164
+ }
165
+
166
+ void set(const uint8_t* a8, int code_size) {
167
+ assert(code_size == 20);
168
+ const uint64_t* a = (uint64_t*)a8;
169
+ a0 = a[0];
170
+ a1 = a[1];
171
+ a2 = a[2];
172
+ }
173
+
174
+ inline int hamming(const uint8_t* b8) const {
175
+ const uint64_t* b = (uint64_t*)b8;
176
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
177
+ popcount64(*(uint32_t*)(b + 2) ^ a2);
178
+ }
179
+
180
+ inline static constexpr int get_code_size() {
181
+ return 20;
182
+ }
183
+ };
184
+
185
+ struct HammingComputer32 {
186
+ uint64_t a0, a1, a2, a3;
187
+
188
+ HammingComputer32() {}
189
+
190
+ HammingComputer32(const uint8_t* a8, int code_size) {
191
+ set(a8, code_size);
192
+ }
193
+
194
+ void set(const uint8_t* a8, int code_size) {
195
+ assert(code_size == 32);
196
+ const uint64_t* a = (uint64_t*)a8;
197
+ a0 = a[0];
198
+ a1 = a[1];
199
+ a2 = a[2];
200
+ a3 = a[3];
201
+ }
202
+
203
+ inline int hamming(const uint8_t* b8) const {
204
+ const uint64_t* b = (uint64_t*)b8;
205
+ return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
206
+ popcount64(b[2] ^ a2) + popcount64(b[3] ^ a3);
207
+ }
208
+
209
+ inline static constexpr int get_code_size() {
210
+ return 32;
211
+ }
212
+ };
213
+
214
+ struct HammingComputer64 {
215
+ uint64_t a0, a1, a2, a3, a4, a5, a6, a7;
216
+
217
+ HammingComputer64() {}
218
+
219
+ HammingComputer64(const uint8_t* a8, int code_size) {
220
+ set(a8, code_size);
221
+ }
222
+
223
+ void set(const uint8_t* a8, int code_size) {
224
+ assert(code_size == 64);
225
+ const uint64_t* a = (uint64_t*)a8;
226
+ a0 = a[0];
227
+ a1 = a[1];
228
+ a2 = a[2];
229
+ a3 = a[3];
230
+ a4 = a[4];
231
+ a5 = a[5];
232
+ a6 = a[6];
233
+ a7 = a[7];
234
+ }
235
+
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) +
239
+ popcount64(b[2] ^ a2) + popcount64(b[3] ^ a3) +
240
+ popcount64(b[4] ^ a4) + popcount64(b[5] ^ a5) +
241
+ popcount64(b[6] ^ a6) + popcount64(b[7] ^ a7);
242
+ }
243
+
244
+ inline static constexpr int get_code_size() {
245
+ return 64;
246
+ }
247
+ };
248
+
249
+ struct HammingComputerDefault {
250
+ const uint8_t* a8;
251
+ int quotient8;
252
+ int remainder8;
253
+
254
+ HammingComputerDefault() {}
255
+
256
+ HammingComputerDefault(const uint8_t* a8, int code_size) {
257
+ set(a8, code_size);
258
+ }
259
+
260
+ void set(const uint8_t* a8, int code_size) {
261
+ this->a8 = a8;
262
+ quotient8 = code_size / 8;
263
+ remainder8 = code_size % 8;
264
+ }
265
+
266
+ int hamming(const uint8_t* b8) const {
267
+ int accu = 0;
268
+
269
+ const uint64_t* a64 = reinterpret_cast<const uint64_t*>(a8);
270
+ const uint64_t* b64 = reinterpret_cast<const uint64_t*>(b8);
271
+ int i = 0, len = quotient8;
272
+ switch (len & 7) {
273
+ default:
274
+ while (len > 7) {
275
+ len -= 8;
276
+ accu += popcount64(a64[i] ^ b64[i]);
277
+ i++;
278
+ case 7:
279
+ accu += popcount64(a64[i] ^ b64[i]);
280
+ i++;
281
+ case 6:
282
+ accu += popcount64(a64[i] ^ b64[i]);
283
+ i++;
284
+ case 5:
285
+ accu += popcount64(a64[i] ^ b64[i]);
286
+ i++;
287
+ case 4:
288
+ accu += popcount64(a64[i] ^ b64[i]);
289
+ i++;
290
+ case 3:
291
+ accu += popcount64(a64[i] ^ b64[i]);
292
+ i++;
293
+ case 2:
294
+ accu += popcount64(a64[i] ^ b64[i]);
295
+ i++;
296
+ case 1:
297
+ accu += popcount64(a64[i] ^ b64[i]);
298
+ i++;
299
+ }
300
+ }
301
+ if (remainder8) {
302
+ const uint8_t* a = a8 + 8 * quotient8;
303
+ const uint8_t* b = b8 + 8 * quotient8;
304
+ switch (remainder8) {
305
+ case 7:
306
+ accu += hamdis_tab_ham_bytes[a[6] ^ b[6]];
307
+ case 6:
308
+ accu += hamdis_tab_ham_bytes[a[5] ^ b[5]];
309
+ case 5:
310
+ accu += hamdis_tab_ham_bytes[a[4] ^ b[4]];
311
+ case 4:
312
+ accu += hamdis_tab_ham_bytes[a[3] ^ b[3]];
313
+ case 3:
314
+ accu += hamdis_tab_ham_bytes[a[2] ^ b[2]];
315
+ case 2:
316
+ accu += hamdis_tab_ham_bytes[a[1] ^ b[1]];
317
+ case 1:
318
+ accu += hamdis_tab_ham_bytes[a[0] ^ b[0]];
319
+ default:
320
+ break;
321
+ }
322
+ }
323
+
324
+ return accu;
325
+ }
326
+
327
+ inline int get_code_size() const {
328
+ return quotient8 * 8 + remainder8;
329
+ }
330
+ };
331
+
332
+ // more inefficient than HammingComputerDefault (obsolete)
333
+ struct HammingComputerM8 {
334
+ const uint64_t* a;
335
+ int n;
336
+
337
+ HammingComputerM8() {}
338
+
339
+ HammingComputerM8(const uint8_t* a8, int code_size) {
340
+ set(a8, code_size);
341
+ }
342
+
343
+ void set(const uint8_t* a8, int code_size) {
344
+ assert(code_size % 8 == 0);
345
+ a = (uint64_t*)a8;
346
+ n = code_size / 8;
347
+ }
348
+
349
+ int hamming(const uint8_t* b8) const {
350
+ const uint64_t* b = (uint64_t*)b8;
351
+ int accu = 0;
352
+ for (int i = 0; i < n; i++)
353
+ accu += popcount64(a[i] ^ b[i]);
354
+ return accu;
355
+ }
356
+
357
+ inline int get_code_size() const {
358
+ return n * 8;
359
+ }
360
+ };
361
+
362
+ // more inefficient than HammingComputerDefault (obsolete)
363
+ struct HammingComputerM4 {
364
+ const uint32_t* a;
365
+ int n;
366
+
367
+ HammingComputerM4() {}
368
+
369
+ HammingComputerM4(const uint8_t* a4, int code_size) {
370
+ set(a4, code_size);
371
+ }
372
+
373
+ void set(const uint8_t* a4, int code_size) {
374
+ assert(code_size % 4 == 0);
375
+ a = (uint32_t*)a4;
376
+ n = code_size / 4;
377
+ }
378
+
379
+ int hamming(const uint8_t* b8) const {
380
+ const uint32_t* b = (uint32_t*)b8;
381
+ int accu = 0;
382
+ for (int i = 0; i < n; i++)
383
+ accu += popcount64(a[i] ^ b[i]);
384
+ return accu;
385
+ }
386
+
387
+ inline int get_code_size() const {
388
+ return n * 4;
389
+ }
390
+ };
391
+
392
+ /***************************************************************************
393
+ * Equivalence with a template class when code size is known at compile time
394
+ **************************************************************************/
395
+
396
+ // default template
397
+ template <int CODE_SIZE>
398
+ struct HammingComputer : HammingComputerDefault {
399
+ HammingComputer(const uint8_t* a, int code_size)
400
+ : HammingComputerDefault(a, code_size) {}
401
+ };
402
+
403
+ #define SPECIALIZED_HC(CODE_SIZE) \
404
+ template <> \
405
+ struct HammingComputer<CODE_SIZE> : HammingComputer##CODE_SIZE { \
406
+ HammingComputer(const uint8_t* a) \
407
+ : HammingComputer##CODE_SIZE(a, CODE_SIZE) {} \
408
+ }
409
+
410
+ SPECIALIZED_HC(4);
411
+ SPECIALIZED_HC(8);
412
+ SPECIALIZED_HC(16);
413
+ SPECIALIZED_HC(20);
414
+ SPECIALIZED_HC(32);
415
+ SPECIALIZED_HC(64);
416
+
417
+ #undef SPECIALIZED_HC
418
+
419
+ /***************************************************************************
420
+ * generalized Hamming = number of bytes that are different between
421
+ * two codes.
422
+ ***************************************************************************/
423
+
424
+ inline int generalized_hamming_64(uint64_t a) {
425
+ a |= a >> 1;
426
+ a |= a >> 2;
427
+ a |= a >> 4;
428
+ a &= 0x0101010101010101UL;
429
+ return popcount64(a);
430
+ }
431
+
432
+ struct GenHammingComputer8 {
433
+ uint64_t a0;
434
+
435
+ GenHammingComputer8(const uint8_t* a, int code_size) {
436
+ assert(code_size == 8);
437
+ a0 = *(uint64_t*)a;
438
+ }
439
+
440
+ inline int hamming(const uint8_t* b) const {
441
+ return generalized_hamming_64(*(uint64_t*)b ^ a0);
442
+ }
443
+
444
+ inline static constexpr int get_code_size() {
445
+ return 8;
446
+ }
447
+ };
448
+
449
+ struct GenHammingComputer16 {
450
+ uint64_t a0, a1;
451
+ GenHammingComputer16(const uint8_t* a8, int code_size) {
452
+ assert(code_size == 16);
453
+ const uint64_t* a = (uint64_t*)a8;
454
+ a0 = a[0];
455
+ a1 = a[1];
456
+ }
457
+
458
+ inline int hamming(const uint8_t* b8) const {
459
+ const uint64_t* b = (uint64_t*)b8;
460
+ return generalized_hamming_64(b[0] ^ a0) +
461
+ generalized_hamming_64(b[1] ^ a1);
462
+ }
463
+
464
+ inline static constexpr int get_code_size() {
465
+ return 16;
466
+ }
467
+ };
468
+
469
+ struct GenHammingComputer32 {
470
+ uint64_t a0, a1, a2, a3;
471
+
472
+ GenHammingComputer32(const uint8_t* a8, int code_size) {
473
+ assert(code_size == 32);
474
+ const uint64_t* a = (uint64_t*)a8;
475
+ a0 = a[0];
476
+ a1 = a[1];
477
+ a2 = a[2];
478
+ a3 = a[3];
479
+ }
480
+
481
+ inline int hamming(const uint8_t* b8) const {
482
+ const uint64_t* b = (uint64_t*)b8;
483
+ return generalized_hamming_64(b[0] ^ a0) +
484
+ generalized_hamming_64(b[1] ^ a1) +
485
+ generalized_hamming_64(b[2] ^ a2) +
486
+ generalized_hamming_64(b[3] ^ a3);
487
+ }
488
+
489
+ inline static constexpr int get_code_size() {
490
+ return 32;
491
+ }
492
+ };
493
+
494
+ struct GenHammingComputerM8 {
495
+ const uint64_t* a;
496
+ int n;
497
+
498
+ GenHammingComputerM8(const uint8_t* a8, int code_size) {
499
+ assert(code_size % 8 == 0);
500
+ a = (uint64_t*)a8;
501
+ n = code_size / 8;
502
+ }
503
+
504
+ int hamming(const uint8_t* b8) const {
505
+ const uint64_t* b = (uint64_t*)b8;
506
+ int accu = 0;
507
+ for (int i = 0; i < n; i++)
508
+ accu += generalized_hamming_64(a[i] ^ b[i]);
509
+ return accu;
510
+ }
511
+
512
+ inline int get_code_size() const {
513
+ return n * 8;
514
+ }
515
+ };
516
+
517
+ } // namespace faiss
518
+
519
+ #endif
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ // This file contains low level inline facilities for computing
9
+ // Hamming distances, such as HammingComputerXX and GenHammingComputerXX.
10
+
11
+ #ifndef FAISS_hamming_inl_h
12
+ #define FAISS_hamming_inl_h
13
+
14
+ #include <faiss/utils/hamming_distance/common.h>
15
+
16
+ #ifdef __aarch64__
17
+ // ARM compilers may produce inoptimal code for Hamming distance somewhy.
18
+ #include <faiss/utils/hamming_distance/neon-inl.h>
19
+ #elif __AVX2__
20
+ // better versions for GenHammingComputer
21
+ #include <faiss/utils/hamming_distance/avx2-inl.h>
22
+ #else
23
+ #include <faiss/utils/hamming_distance/generic-inl.h>
24
+ #endif
25
+
26
+ #endif