-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconciseutil.h
176 lines (153 loc) · 4.49 KB
/
conciseutil.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#ifndef CONCISEUTIL_H
#define CONCISEUTIL_H
#include <cstdint>
/**
* The highest representable integer.
*/
constexpr static uint32_t MAX_ALLOWED_INTEGER =
31 * (UINT32_C(1) << 25) + 30; // 1040187422
/**
* Maximum number of representable bits within a literal
*/
constexpr static uint32_t MAX_LITERAL_LENGTH = UINT32_C(31);
/**
* Literal that represents all bits set to 1 (and MSB = 1)
*/
constexpr static uint32_t ALL_ONES_LITERAL = UINT32_C(0xFFFFFFFF);
/**
* Literal that represents all bits set to 0 (and MSB = 1)
*/
constexpr static uint32_t ALL_ZEROS_LITERAL = UINT32_C(0x80000000);
/**
* All bits set to 1 and MSB = 0
*/
constexpr static uint32_t ALL_ONES_WITHOUT_MSB = UINT32_C(0x7FFFFFFF);
/**
* Sequence bit
*/
constexpr static uint32_t SEQUENCE_BIT = UINT32_C(0x40000000);
/**
* Calculates the modulus division by 31 in a faster way than using n % 31
*/
inline uint32_t maxLiteralLengthModulus(uint32_t n) {
return n % 31;
// following code is a bad idea. Compilers can compiler n % 31 to something
// faster.
/**
uint32_t m = (n & UINT32_C(0xC1F07C1F)) + ((n >> 5) & UINT32_C(0xC1F07C1F));
m = (m >> 15) + (m & UINT32_C(0x00007FFF));
if (m <= 31)
return m == 31 ? 0 : m;
m = (m >> 5) + (m & UINT32_C(0x0000001F));
if (m <= 31)
return m == 31 ? 0 : m;
m = (m >> 5) + (m & UINT32_C(0x0000001F));
if (m <= 31)
return m == 31 ? 0 : m;
m = (m >> 5) + (m & UINT32_C(0x0000001F));
if (m <= 31)
return m == 31 ? 0 : m;
m = (m >> 5) + (m & UINT32_C(0x0000001F));
if (m <= 31)
return m == 31 ? 0 : m;
m = (m >> 5) + (m & UINT32_C(0x0000001F));
return m == 31 ? 0 : m;
**/
}
/**
* Calculates the multiplication by 31 in a faster way than using n * 31
*/
inline uint32_t maxLiteralLengthMultiplication(uint32_t n) {
return (n << 5) - n; // a good compiler should do this on its own
}
/**
* Calculates the division by 31
*/
inline uint32_t maxLiteralLengthDivision(uint32_t n) { return n / 31; }
/**
* Checks whether a word is a literal one
*/
inline bool isLiteral(uint32_t word) {
// "word" must be 1*
// NOTE: this is faster than "return (word & 0x80000000) == 0x80000000"
return (word & UINT32_C(0x80000000)) != 0;
}
/**
* Checks whether a word contains a sequence of 1's
*/
inline bool isOneSequence(uint32_t word) {
// "word" must be 01*
return (word & UINT32_C(0xC0000000)) == SEQUENCE_BIT;
}
/**
* Checks whether a word contains a sequence of 0's
*/
inline bool isZeroSequence(uint32_t word) {
// "word" must be 00*
return (word & UINT32_C(0xC0000000)) == 0;
}
/**
* Checks whether a word contains a sequence of 0's with no set bit, or 1's
* with no unset bit.
*/
inline bool isSequenceWithNoBits(uint32_t word) {
// "word" must be 0?00000*
return (word & UINT32_C(0xBE000000)) == UINT32_C(0x00000000);
}
/**
* Gets the number of blocks of 1's or 0's stored in a sequence word
*/
template <bool wah_mode>
inline uint32_t getSequenceCount(uint32_t word) {
// get the 25 LSB bits
return word & (wah_mode? UINT32_C(0x3FFFFFFF) : UINT32_C(0x01FFFFFF));
}
/**
* Clears the (un)set bit in a sequence
*/
inline uint32_t getSequenceWithNoBits(uint32_t word) {
// clear 29 to 25 LSB bits
return (word & UINT32_C(0xC1FFFFFF));
}
/**
* Returns true when the given 31-bit literal string (namely,
* with MSB set) contains only one set bit
*/
inline bool containsOnlyOneBit(uint32_t literal) {
return (literal & (literal - 1)) == 0;
}
/**
* Gets the position of the flipped bit within a sequence word. If the
* sequence has no set/unset bit, returns -1.
*/
inline int getFlippedBit(uint32_t word) {
// get bits from 30 to 26
// NOTE: "-1" is required since 00000 represents no bits and 00001 the LSB bit
// set
return ((word >> 25) & UINT32_C(0x0000001F)) - 1;
}
inline uint32_t concise_xor(uint32_t literal1, uint32_t literal2) {
return ALL_ZEROS_LITERAL | (literal1 ^ literal2);
}
inline uint32_t concise_andnot(uint32_t literal1, uint32_t literal2) {
return ALL_ZEROS_LITERAL | (literal1 & (~literal2));
}
inline uint32_t concise_and(uint32_t literal1, uint32_t literal2) {
return ALL_ZEROS_LITERAL | (literal1 & literal2);
}
/**
* Gets the bits contained within the literal word
*/
inline uint32_t getLiteralBits(uint32_t word) {
return ALL_ONES_WITHOUT_MSB & word;
}
/**
* Gets the number of set bits within the literal word
*/
inline int getLiteralBitCount(uint32_t word) {
return __builtin_popcount(getLiteralBits(word));
}
inline bool isLiteralZero(uint32_t word) {
return getLiteralBits(word) == 0;
}
#endif