ROSE 0.11.145.147
integerOps.h
1#ifndef ROSE_INTEGEROPS_H
2#define ROSE_INTEGEROPS_H
3
4#include <cassert>
5#include <limits>
6#include <boost/static_assert.hpp>
7#include <boost/optional.hpp>
8
9namespace IntegerOpsPrivate {
10
11 template <typename T>
12 struct NumBits {
13 BOOST_STATIC_ASSERT (std::numeric_limits<T>::radix == 2);
14 BOOST_STATIC_ASSERT (std::numeric_limits<T>::is_integer);
15 static const size_t value = std::numeric_limits<T>::digits;
16 };
17
18 template <typename T, size_t Count, bool TooBig> struct SHL1Helper;
19 template <typename T, size_t Count>
20 struct SHL1Helper<T, Count, true> {
21 static const T value = 0;
22 };
23 template <typename T, size_t Count>
24 struct SHL1Helper<T, Count, false> {
25 static const T value = T(1) << Count;
26 };
27
28}
29
35namespace IntegerOps {
36
38template <typename T, size_t n>
39struct SHL1: public IntegerOpsPrivate::SHL1Helper<T, n, (n >= IntegerOpsPrivate::NumBits<T>::value)> {};
40
42template <typename T>
43inline T shl1(size_t n) {
44 return (n >= IntegerOpsPrivate::NumBits<T>::value) ? T(0) : (T(1) << n);
45}
46
48template <typename T, size_t n>
49struct GenMask {
50 static const T value = SHL1<T, n>::value - T(1);
51};
52
54template <typename T>
55inline T genMask(size_t n) {
56 return shl1<T>(n) - 1;
57}
58
61template <typename T>
62inline T genMask(size_t lobit, size_t hibit)
63{
64 assert(hibit<8*sizeof(T));
65 assert(hibit>=lobit);
66 return genMask<T>(1+hibit-lobit) << lobit;
67}
68
71template <size_t NBits, typename T>
72inline bool signBit(T value) {
73 return (value & SHL1<T, NBits - 1>::value) != T(0);
74}
75
76template <typename T>
77inline bool signBit2(T value, size_t width=8*sizeof(T)) {
78 assert(width>0 && width<=8*sizeof(T));
79 T sign_mask = shl1<T>(width-1);
80 return 0 != (value & sign_mask);
81}
87template <size_t FromBits, size_t ToBits, typename T>
88inline T signExtend(T value) {
89 return value | (signBit<FromBits>(value) ? (GenMask<T, ToBits>::value ^ GenMask<T, FromBits>::value) : T(0));
90}
91
92template <typename T>
93inline T signExtend2(T value, size_t from_width, size_t to_width) {
94 assert(from_width<=8*sizeof(T));
95 assert(to_width<=8*sizeof(T));
96 return value | (signBit2(value, from_width) ? (genMask<T>(to_width) ^ genMask<T>(from_width)) : T(0));
97}
102template <size_t NBits, typename T>
103inline T shiftLeft(T value, size_t count) {
104 return (value * shl1<T>(count)) & GenMask<T, NBits>::value;
105}
106
107template <typename T>
108inline T shiftLeft2(T value, size_t count, size_t width=8*sizeof(T)) {
109 assert(width>0 && width<=8*sizeof(T));
110 return (value * shl1<T>(count)) & genMask<T>(width);
111}
116template <size_t NBits, typename T>
117inline T shiftRightLogical(T value, size_t count) {
118 return (count >= NBits) ? T(0) : (value >> count);
119}
120
121template <typename T>
122inline T shiftRightLogical2(T value, size_t count, size_t width=8*sizeof(T)) {
123 assert(width>0 && width<=8*sizeof(T));
124 return (count >= width) ? T(0) : (value >> count);
125}
130template <size_t NBits, typename T>
131inline T shiftRightArithmetic(T value, size_t count) {
132 if (count >= NBits) {
133 return signBit<NBits>(value) ? GenMask<T, NBits>::value : T(0);
134 } else {
135 return (shiftRightLogical<NBits>(value, count) |
136 (signBit<NBits>(value) ? (GenMask<T, NBits>::value ^ genMask<T>(NBits - count)) : T(0)));
137 }
138}
139
140template <typename T>
141inline T shiftRightArithmetic2(T value, size_t count, size_t width=8*sizeof(T)) {
142 if (count >= width) {
143 return signBit2(value, width) ? genMask<T>(width) : T(0);
144 } else {
145 return (shiftRightLogical2(value, count, width) |
146 (signBit2(value, width) ? (genMask<T>(width) ^ genMask<T>(width-count)) : T(0)));
147 }
148}
153template <size_t NBits, typename T>
154inline T rotateLeft(T value, size_t count) {
155 count %= NBits;
156 return ((value << count) | (value >> (NBits - count))) & GenMask<T, NBits>::value;
157}
158
159template <typename T>
160inline T rotateLeft2(T value, size_t count, size_t width=8*sizeof(T)) {
161 assert(width>0 && width<=8*sizeof(T));
162 count %= width;
163 return ((value << count) | (value >> (width-count))) & genMask<T>(width);
164}
169template <size_t NBits, typename T>
170inline T rotateRight(T value, size_t count) {
171 count %= NBits;
172 return ((value >> count) | (value << (NBits - count))) & GenMask<T, NBits>::value;
173}
174
175template <typename T>
176inline T rotateRight2(T value, size_t count, size_t width=8*sizeof(T)) {
177 assert(width>0 && width<=8*sizeof(T));
178 return ((value >> count) | (value << (width - count))) & genMask<T>(width);
179}
183template <typename T>
184inline bool isPowerOfTwo(T value)
185{
186 assert(sizeof(T) <= sizeof(uint64_t));
187 if (0 != (value & SHL1<T, 8*sizeof(T)-1>::value))
188 value = ~value + 1;
189 uint64_t uval = value;
190 while (uval) {
191 if (uval & 1)
192 return 1==uval;
193 uval >>= 1u;
194 }
195 return true; // treat zero as a power of two
196}
197
200template <typename T>
201inline T log2max(T value)
202{
203 assert(sizeof(T) <= sizeof(uint64_t));
204 uint64_t uval = value;
205 bool low_bits_set = false;
206 T retval = 0;
207 while (uval) {
208 if (1==uval)
209 return retval + (low_bits_set ? 1 : 0);
210 if (uval & 1)
211 low_bits_set = true;
212 ++retval;
213 uval >>= 1;
214 }
215 return retval;
216}
217
218
219template <typename T>
220inline T log2(T a) {
221 T n = T(1);
222 T i = 0;
223 while (n != 0 && n < a) {
224 n <<= 1;
225 ++i;
226 }
227 return i;
228}
229
234template<size_t lobit, size_t hibit, typename T>
235inline T shift_to(T value) {
236 assert(hibit<8*sizeof(T));
237 assert(hibit>=lobit);
238 assert(0==(value & ~GenMask<T, 1+hibit-lobit>::value));
239 return shiftLeft<8*sizeof(T)>(value & GenMask<T, 1+hibit-lobit>::value, lobit);
240}
241template<typename T>
242inline T shift_to2(size_t lobit, size_t hibit, T value)
243{
244 assert(hibit<8*sizeof(T));
245 assert(hibit>=lobit);
246 assert(0==(value & ~genMask<T>(1+hibit-lobit)));
247 return shiftLeft2<T>(value & genMask<T>(1+hibit-lobit), lobit);
248}
254template<size_t lobit, size_t hibit, typename T>
255inline T extract(T bits) {
256 assert(hibit<8*sizeof(T));
257 assert(hibit>=lobit);
258 return shiftRightLogical<8*sizeof(T)>(bits, lobit) & GenMask<T, 1+hibit-lobit>::value;
259}
260template<typename T>
261inline T extract2(size_t lobit, size_t hibit, T bits)
262{
263 assert(hibit<8*sizeof(T));
264 assert(hibit>=lobit);
265 return shiftRightLogical<8*sizeof(T)>(bits, lobit) & genMask<T>(1+hibit-lobit);
266}
271template<typename T>
272inline bool bitmask_subset(T m1, T m2)
273{
274 return 0 == (~m1 & m2); // m2 must not contain bits that are not in m1
275}
276
278template<typename T>
279inline size_t countSet(T val)
280{
281 size_t retval = 0;
282 for (size_t i=0; i<8*sizeof(T); ++i) {
283 if (0 != (val & shl1<T>(i)))
284 ++retval;
285 }
286 return retval;
287}
288
290template<typename T>
291inline size_t countClear(T val)
292{
293 size_t retval = 0;
294 for (size_t i=0; i<8*sizeof(T); ++i) {
295 if (0 == (val & shl1<T>(i)))
296 ++retval;
297 }
298 return retval;
299}
300
302template<typename T>
303inline boost::optional<size_t> msb_set(T val)
304{
305 if (val!=0) {
306 for (size_t bitno = 8*sizeof(T); bitno>0; --bitno) {
307 if (0 != (val & shl1<T>(bitno-1)))
308 return boost::optional<size_t>(bitno-1);
309 }
310 }
311 return boost::optional<size_t>();
312}
313
314} // namespace
315#endif // ROSE_INTEGEROPS_H
Bit-wise operations on integers.
Definition integerOps.h:35
T shiftRightArithmetic(T value, size_t count)
Shifts bits of value right by count bits with sign extension.
Definition integerOps.h:131
T extract(T bits)
Extract bits from a value.
Definition integerOps.h:255
T rotateLeft(T value, size_t count)
Rotate the bits of the value left by count bits.
Definition integerOps.h:154
T shiftRightLogical(T value, size_t count)
Shifts bits of value right by count bits without sign extension.
Definition integerOps.h:117
bool signBit(T value)
Returns true if the sign bit is set, false if clear.
Definition integerOps.h:72
T signExtend2(T value, size_t from_width, size_t to_width)
Sign extend value.
Definition integerOps.h:93
T shift_to(T value)
Create a shifted value.
Definition integerOps.h:235
bool signBit2(T value, size_t width=8 *sizeof(T))
Returns true if the sign bit is set, false if clear.
Definition integerOps.h:77
size_t countClear(T val)
Counts how many bits are clear (zero).
Definition integerOps.h:291
T rotateRight2(T value, size_t count, size_t width=8 *sizeof(T))
Rotate bits of the value right by count bits.
Definition integerOps.h:176
T rotateRight(T value, size_t count)
Rotate bits of the value right by count bits.
Definition integerOps.h:170
T signExtend(T value)
Sign extend value.
Definition integerOps.h:88
boost::optional< size_t > msb_set(T val)
Optionally returns the zero-origin position of the most significant set bit.
Definition integerOps.h:303
T shift_to2(size_t lobit, size_t hibit, T value)
Create a shifted value.
Definition integerOps.h:242
bool bitmask_subset(T m1, T m2)
Determines if one bitmask is a subset of another.
Definition integerOps.h:272
T rotateLeft2(T value, size_t count, size_t width=8 *sizeof(T))
Rotate the bits of the value left by count bits.
Definition integerOps.h:160
T extract2(size_t lobit, size_t hibit, T bits)
Extract bits from a value.
Definition integerOps.h:261
bool isPowerOfTwo(T value)
Returns true if the value is a power of two.
Definition integerOps.h:184
T log2max(T value)
Returns the base-2 logorithm of value.
Definition integerOps.h:201
T genMask(size_t n)
Bitmask with bits 0 through N-1 set.
Definition integerOps.h:55
size_t countSet(T val)
Counts how many bits are set (one).
Definition integerOps.h:279
T shiftLeft(T value, size_t count)
Shifts bits of value left by count bits.
Definition integerOps.h:103
T shiftLeft2(T value, size_t count, size_t width=8 *sizeof(T))
Shifts bits of value left by count bits.
Definition integerOps.h:108
T shiftRightArithmetic2(T value, size_t count, size_t width=8 *sizeof(T))
Shifts bits of value right by count bits with sign extension.
Definition integerOps.h:141
T shl1(size_t n)
Bitmask with bit n set.
Definition integerOps.h:43
T shiftRightLogical2(T value, size_t count, size_t width=8 *sizeof(T))
Shifts bits of value right by count bits without sign extension.
Definition integerOps.h:122
Bit mask constant with bits 0 through n-1 set.
Definition integerOps.h:49
Bitmask constant with bit n set.
Definition integerOps.h:39