-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathbtree.cc
55 lines (47 loc) · 1.16 KB
/
btree.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "binsearch.hh"
#include <x86intrin.h>
typedef __m256i reg;
const int B = 16;
const int INF = std::numeric_limits<int>::max();
int n;
int nblocks;
int *_a;
int (*btree)[B];
int go(int k, int i) { return k * (B + 1) + i + 1; }
void build(int k = 0) {
static int t = 0;
if (k < nblocks) {
for (int i = 0; i < B; i++) {
build(go(k, i));
btree[k][i] = (t < n ? _a[t++] : INF);
}
build(go(k, B));
}
}
void prepare(int *a, int _n) {
n = _n;
nblocks = (n + B - 1) / B;
_a = a;
btree = (int(*)[16]) std::aligned_alloc(64, 64 * nblocks);
build();
}
int cmp(reg x_vec, int* y_ptr) {
reg y_vec = _mm256_load_si256((reg*) y_ptr);
reg mask = _mm256_cmpgt_epi32(x_vec, y_vec);
return _mm256_movemask_ps((__m256) mask);
}
int lower_bound(int x) {
int k = 0, res = INF;
reg x_vec = _mm256_set1_epi32(x);
while (k < nblocks) {
int mask = ~(
cmp(x_vec, &btree[k][0]) +
(cmp(x_vec, &btree[k][8]) << 8)
);
int i = __builtin_ffs(mask) - 1;
if (i < B)
res = btree[k][i];
k = go(k, i);
}
return res;
}