66
77#include " hashutil.h"
88
9- #include < array>
10- #include < type_traits>
119#if defined(__BMI2__)
1210#include < immintrin.h>
1311#endif
1412
15-
16-
17-
1813using namespace std ;
1914using namespace hashing ;
2015
2116namespace counting_bloomfilter {
2217
18+ inline int bitCount64 (uint64_t x) {
19+ return __builtin_popcountll (x);
20+ }
21+
22+ inline int select64 (uint64_t x, int n) {
23+ #if defined(__BMI2__)
24+ // with this, "add" is around 310 ns/key at 10000000 keys
25+ // from http://bitmagic.io/rank-select.html
26+ // https://github.com/Forceflow/libmorton/issues/6
27+ // This is a rather unusual usage of the bit deposit operation,
28+ // as we use the x as the mask, and we use n as the value.
29+ // We deposit (move) the bits of x = 1 << n to the locations
30+ // defined by x.
31+ uint64_t d = _pdep_u64 (1ULL << n, x);
32+ // and now we count the trailing zeroes, to find out
33+ // where the '1' was deposited
34+ return __builtin_ctzl (d);
35+ // return _tzcnt_u64(d);
36+ #else
37+ // slow implementation
38+ // with this, "add" is around 680 ns/key at 10000000 keys
39+ for (int i = 0 ; i < 64 ; i++) {
40+ if ((x & 1 ) == 1 ) {
41+ if (n-- == 0 ) {
42+ return i;
43+ }
44+ }
45+ x >>= 1 ;
46+ }
47+ return -1 ;
48+ #endif
49+ }
50+
51+ inline int numberOfLeadingZeros64 (uint64_t x) {
52+ // If x is 0, the result is undefined.
53+ return x == 0 ? 64 : __builtin_clzl (x);
54+ }
55+
2356enum Status {
2457 Ok = 0 ,
2558 NotFound = 1 ,
@@ -66,7 +99,7 @@ Status CountingBloomFilter<ItemType, bits_per_item, branchless, HashFamily, k>::
6699 uint32_t b = (uint32_t )hash;
67100 for (int i = 0 ; i < k; i++) {
68101 uint index = reduce (a, this ->arrayLength );
69- data[index] += 1L << ((a << 2 ) & 63 );
102+ data[index] += 1ULL << ((a << 2 ) & 63 );
70103 a += b;
71104 }
72105 return Ok;
@@ -147,34 +180,6 @@ Status SuccinctCountingBloomFilter<ItemType, bits_per_item, branchless, HashFami
147180 return Ok;
148181}
149182
150- inline int numberOfLeadingZeros64 (uint64_t x) {
151- // If x is 0, the result is undefined.
152- return x == 0 ? 64 : __builtin_clzl (x);
153- }
154-
155- inline int bitCount64 (uint64_t x) {
156- return __builtin_popcountll (x);
157- }
158-
159-
160- inline int selectInLong64 (uint64_t x, int n) {
161- // from http://bitmagic.io/rank-select.html
162- // https://github.com/Forceflow/libmorton/issues/6
163- uint64_t d = _pdep_u64 (1L << n, x);
164- return _tzcnt_u64 (d);
165- /*
166- for(int i = 0; i < 64; i++) {
167- if ((x & 1) == 1) {
168- if (n-- == 0) {
169- return i;
170- }
171- }
172- x >>= 1;
173- }
174- return -1;
175- */
176- }
177-
178183template <typename ItemType, size_t bits_per_item, bool branchless,
179184 typename HashFamily, int k>
180185void SuccinctCountingBloomFilter<ItemType, bits_per_item, branchless, HashFamily, k>::
@@ -191,8 +196,8 @@ void SuccinctCountingBloomFilter<ItemType, bits_per_item, branchless, HashFamily
191196 // allocate overflow
192197 index = nextFreeOverflow;
193198 if (index >= overflowLength) {
194- ::std::cout << " WARNING : overflow too small\n " ;
195- data[group] |= 1L << bit;
199+ ::std::cout << " ERROR : overflow too small\n " ;
200+ data[group] |= 1ULL << bit;
196201 return ;
197202 }
198203 nextFreeOverflow = (size_t ) overflow[index];
@@ -203,29 +208,29 @@ void SuccinctCountingBloomFilter<ItemType, bits_per_item, branchless, HashFamily
203208 // convert to a pointer
204209 for (int i = 0 ; i < 64 ; i++) {
205210 int n = ReadCount (group, i);
206- overflow[index + i / 16 ] += n * (1L << (i * 4 ));
211+ overflow[index + i / 16 ] += n * (1ULL << (i * 4 ));
207212 }
208213 uint64_t count = 64 ;
209214 c = 0x8000000000000000L | (count << 32 ) | index;
210215 counts[group] = c;
211216 } else {
212217 // already
213218 index = (size_t ) (c & 0x0fffffff );
214- c += 1L << 32 ;
219+ c += 1ULL << 32 ;
215220 counts[group] = c;
216221 }
217- overflow[index + bit / 16 ] += (1L << (bit * 4 ));
218- data[group] |= 1L << bit;
222+ overflow[index + bit / 16 ] += (1ULL << (bit * 4 ));
223+ data[group] |= 1ULL << bit;
219224 return ;
220225 }
221- data[group] |= 1L << bit;
226+ data[group] |= 1ULL << bit;
222227 int bitsBefore = bitCount64 (m & (0xffffffffffffffffL >> (63 - bit)));
223- int before = selectInLong64 ((c << 1 ) | 1 , bitsBefore);
228+ int before = select64 ((c << 1 ) | 1 , bitsBefore);
224229 int insertAt = before - d;
225- uint64_t mask = (1L << insertAt) - 1 ;
230+ uint64_t mask = (1ULL << insertAt) - 1 ;
226231 uint64_t left = c & ~mask;
227232 uint64_t right = c & mask;
228- c = (left << 1 ) | ((1L ^ d) << insertAt) | right;
233+ c = (left << 1 ) | ((1ULL ^ d) << insertAt) | right;
229234 counts[group] = c;
230235}
231236
@@ -246,8 +251,8 @@ int SuccinctCountingBloomFilter<ItemType, bits_per_item, branchless, HashFamily,
246251 return (int ) (n & 15 );
247252 }
248253 int bitsBefore = bitCount64 (m & (0xffffffffffffffffL >> (63 - bit)));
249- int bitPos = selectInLong64 (c, bitsBefore - 1 );
250- uint64_t y = ((c << (63 - bitPos)) << 1 ) | (1L << (63 - bitPos));
254+ int bitPos = select64 (c, bitsBefore - 1 );
255+ uint64_t y = ((c << (63 - bitPos)) << 1 ) | (1ULL << (63 - bitPos));
251256 return numberOfLeadingZeros64 (y) + 1 ;
252257}
253258
0 commit comments