1#ifndef ROSE_INTEGEROPS_H
2#define ROSE_INTEGEROPS_H
6#include <boost/static_assert.hpp>
7#include <boost/optional.hpp>
9namespace IntegerOpsPrivate {
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;
18 template <
typename T,
size_t Count,
bool TooBig>
struct SHL1Helper;
19 template <
typename T,
size_t Count>
21 static const T value = 0;
23 template <
typename T,
size_t Count>
25 static const T value = T(1) << Count;
38template <
typename T,
size_t n>
48template <
typename T,
size_t n>
56 return shl1<T>(n) - 1;
62inline T
genMask(
size_t lobit,
size_t hibit)
64 assert(hibit<8*
sizeof(T));
66 return genMask<T>(1+hibit-lobit) << lobit;
71template <
size_t NBits,
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);
87template <
size_t FromBits,
size_t ToBits,
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));
102template <
size_t NBits,
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);
116template <
size_t NBits,
typename T>
118 return (count >= NBits) ? T(0) : (value >> count);
123 assert(width>0 && width<=8*
sizeof(T));
124 return (count >= width) ? T(0) : (value >> count);
130template <
size_t NBits,
typename T>
132 if (count >= NBits) {
135 return (shiftRightLogical<NBits>(value, count) |
142 if (count >= width) {
143 return signBit2(value, width) ? genMask<T>(width) : T(0);
146 (
signBit2(value, width) ? (genMask<T>(width) ^ genMask<T>(width-count)) : T(0)));
153template <
size_t NBits,
typename T>
160inline T
rotateLeft2(T value,
size_t count,
size_t width=8*
sizeof(T)) {
161 assert(width>0 && width<=8*
sizeof(T));
163 return ((value << count) | (value >> (width-count))) & genMask<T>(width);
169template <
size_t NBits,
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);
186 assert(
sizeof(T) <=
sizeof(uint64_t));
187 if (0 != (value &
SHL1<T, 8*
sizeof(T)-1>::value))
189 uint64_t uval = value;
203 assert(
sizeof(T) <=
sizeof(uint64_t));
204 uint64_t uval = value;
205 bool low_bits_set =
false;
209 return retval + (low_bits_set ? 1 : 0);
223 while (n != 0 && n < a) {
234template<
size_t lobit,
size_t hibit,
typename T>
236 assert(hibit<8*
sizeof(T));
237 assert(hibit>=lobit);
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);
254template<
size_t lobit,
size_t hibit,
typename T>
256 assert(hibit<8*
sizeof(T));
257 assert(hibit>=lobit);
258 return shiftRightLogical<8*sizeof(T)>(bits, lobit) &
GenMask<T, 1+hibit-lobit>::value;
261inline T
extract2(
size_t lobit,
size_t hibit, T bits)
263 assert(hibit<8*
sizeof(T));
264 assert(hibit>=lobit);
265 return shiftRightLogical<8*sizeof(T)>(bits, lobit) & genMask<T>(1+hibit-lobit);
274 return 0 == (~m1 & m2);
282 for (
size_t i=0; i<8*
sizeof(T); ++i) {
283 if (0 != (val & shl1<T>(i)))
294 for (
size_t i=0; i<8*
sizeof(T); ++i) {
295 if (0 == (val & shl1<T>(i)))
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);
311 return boost::optional<size_t>();
Bit-wise operations on integers.
T shiftRightArithmetic(T value, size_t count)
Shifts bits of value right by count bits with sign extension.
T extract(T bits)
Extract bits from a value.
T rotateLeft(T value, size_t count)
Rotate the bits of the value left by count bits.
T shiftRightLogical(T value, size_t count)
Shifts bits of value right by count bits without sign extension.
bool signBit(T value)
Returns true if the sign bit is set, false if clear.
T signExtend2(T value, size_t from_width, size_t to_width)
Sign extend value.
T shift_to(T value)
Create a shifted value.
bool signBit2(T value, size_t width=8 *sizeof(T))
Returns true if the sign bit is set, false if clear.
size_t countClear(T val)
Counts how many bits are clear (zero).
T rotateRight2(T value, size_t count, size_t width=8 *sizeof(T))
Rotate bits of the value right by count bits.
T rotateRight(T value, size_t count)
Rotate bits of the value right by count bits.
T signExtend(T value)
Sign extend value.
boost::optional< size_t > msb_set(T val)
Optionally returns the zero-origin position of the most significant set bit.
T shift_to2(size_t lobit, size_t hibit, T value)
Create a shifted value.
bool bitmask_subset(T m1, T m2)
Determines if one bitmask is a subset of another.
T rotateLeft2(T value, size_t count, size_t width=8 *sizeof(T))
Rotate the bits of the value left by count bits.
T extract2(size_t lobit, size_t hibit, T bits)
Extract bits from a value.
bool isPowerOfTwo(T value)
Returns true if the value is a power of two.
T log2max(T value)
Returns the base-2 logorithm of value.
T genMask(size_t n)
Bitmask with bits 0 through N-1 set.
size_t countSet(T val)
Counts how many bits are set (one).
T shiftLeft(T value, size_t count)
Shifts bits of value left by count bits.
T shiftLeft2(T value, size_t count, size_t width=8 *sizeof(T))
Shifts bits of value left by count bits.
T shiftRightArithmetic2(T value, size_t count, size_t width=8 *sizeof(T))
Shifts bits of value right by count bits with sign extension.
T shl1(size_t n)
Bitmask with bit n set.
T shiftRightLogical2(T value, size_t count, size_t width=8 *sizeof(T))
Shifts bits of value right by count bits without sign extension.
Bit mask constant with bits 0 through n-1 set.
Bitmask constant with bit n set.