-
Notifications
You must be signed in to change notification settings - Fork 0
/
vec128b.h
159 lines (141 loc) · 3.5 KB
/
vec128b.h
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#ifndef VEC128B_H
#define VEC128B_H
#include <stdbool.h>
#define WORD_BITS (sizeof(unsigned int) * 8)
#define VEC128B_WORDS (128 / WORD_BITS)
typedef struct {
unsigned int word[VEC128B_WORDS];
} vec128b;
static inline
void vec128b_and(vec128b *a, const vec128b *b) {
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
FOREACH(i, a->word) {
a->word[i] &= b->word[i];
}
}
static inline
void vec128b_and_not(vec128b *a, const vec128b *b) {
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
FOREACH(i, a->word) {
a->word[i] &= ~b->word[i];
}
}
static inline
void vec128b_or(vec128b *a, const vec128b *b) {
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
FOREACH(i, a->word) {
a->word[i] |= b->word[i];
}
}
static inline
void vec128b_xor(vec128b *a, const vec128b *b) {
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
FOREACH(i, a->word) {
a->word[i] ^= b->word[i];
}
}
static inline
void vec128b_not(vec128b *a) {
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
FOREACH(i, a->word) {
a->word[i] = ~a->word[i];
}
}
static inline
void vec128b_set_bit(vec128b *a, int b) {
a->word[b / WORD_BITS] |= 1u << (b % WORD_BITS);
}
static inline
void vec128b_clear_bit(vec128b *a, int b) {
a->word[b / WORD_BITS] &= ~(1u << (b % WORD_BITS));
}
static inline
void vec128b_set_bit_val(vec128b *s, int k, bool v) {
if(v) {
vec128b_set_bit(s, k);
} else {
vec128b_clear_bit(s, k);
}
}
static inline
bool vec128b_eq(const vec128b *a, const vec128b *b) {
bool res = true;
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
FOREACH(i, a->word) {
res &= a->word[i] == b->word[i];
}
return res;
}
static inline
bool vec128b_zero(const vec128b *a) {
bool res = true;
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
FOREACH(i, a->word) {
res &= !a->word[i];
}
return res;
}
static inline
void vec128b_shiftl(vec128b *a, int b) {
const int word_shiftl = b / WORD_BITS;
const int bit_shiftl = b - word_shiftl * WORD_BITS;
const int bit_shiftr = WORD_BITS - bit_shiftl;
if(bit_shiftl) {
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
COUNTDOWN(i, LENGTH(a->word)) {
int j = i - word_shiftl;
a->word[i] =
(j >= 0 ? a->word[j] << bit_shiftl : 0) |
(j-1 >= 0 ? a->word[j-1] >> bit_shiftr : 0);
}
} else {
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
COUNTDOWN(i, LENGTH(a->word)) {
int j = i - word_shiftl;
a->word[i] = j >= 0 ? a->word[j] : 0;
}
}
}
static inline
void vec128b_shiftr(vec128b *a, int b) {
const int word_shiftr = b / WORD_BITS;
const int bit_shiftr = b - word_shiftr * WORD_BITS;
const int bit_shiftl = WORD_BITS - bit_shiftr;
if(bit_shiftr) {
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
COUNTUP(i, LENGTH(a->word)) {
int j = i + word_shiftr;
a->word[i] =
(j+1 < LENGTH(a->word) ? a->word[j+1] << bit_shiftl : 0) |
(j < LENGTH(a->word) ? a->word[j] >> bit_shiftr : 0);
}
} else {
#pragma GCC unroll (16 / sizeof(unsigned int))
#pragma unroll
COUNTUP(i, LENGTH(a->word)) {
int j = i + word_shiftr;
a->word[i] = j < LENGTH(a->word) ? a->word[j] : 0;
}
}
}
static inline
void vec128b_set_zero(vec128b *a) {
memset(a, 0, sizeof(vec128b));
}
static inline
bool vec128b_bit_is_set(const vec128b *a, int b) {
const int n = b / WORD_BITS;
const int bit = b - n * WORD_BITS;
return !!(a->word[n] & (1u << bit));
}
#endif