4 #include <Sawyer/Assert.h>
5 #include <Sawyer/Optional.h>
16 template<
typename Un
signed>
17 inline size_t nBits(Unsigned x = Unsigned(0)) {
18 return 8*
sizeof(Unsigned);
22 template<
typename Un
signed>
23 inline Unsigned
all(
bool b =
true) {
24 return Unsigned(0) - Unsigned(b ? 1 : 0);
27 template<
typename Un
signed>
inline Unsigned
lowMask(
size_t n);
32 template<
typename Un
signed>
33 inline Unsigned
allLsb(Unsigned src,
size_t w,
bool b =
true) {
34 ASSERT_require(w <=
nBits(src));
36 return src | lowMask<Unsigned>(w);
38 return src & ~lowMask<Unsigned>(w);
47 template<
typename Un
signed>
49 return n >= nBits<Unsigned>() ? all<Unsigned>(
true) : (Unsigned(1) << n) - Unsigned(1);
56 template<
typename Un
signed>
58 return n >= nBits<Unsigned>() ? all<Unsigned>(
true) : lowMask<Unsigned>(n) << (nBits<Unsigned>() - n);
65 template<
typename Un
signed>
66 inline Unsigned
select(Unsigned cond, Unsigned a, Unsigned b) {
67 return (a & cond) | (b & ~cond);
75 template<
typename Un
signed>
76 inline Unsigned
shiftLeft(Unsigned src,
size_t n,
bool b =
false) {
77 if (n >=
nBits(src)) {
78 return all<Unsigned>(b);
80 return Unsigned(src << n) | (all<Unsigned>(b) & lowMask<Unsigned>(n));
90 template<
typename Un
signed>
91 inline Unsigned
shiftLeftLsb(Unsigned src,
size_t w,
size_t n,
bool b =
false) {
92 ASSERT_require(w <=
nBits(src));
105 template<
typename Un
signed>
106 inline Unsigned
shiftRight(Unsigned src,
size_t n,
bool b =
false) {
107 if (n >=
nBits(src)) {
108 return all<Unsigned>(b);
110 return Unsigned(src >> n) | (all<Unsigned>(b) & highMask<Unsigned>(n));
119 template<
typename Un
signed>
120 inline Unsigned
shiftRightLsb(Unsigned src,
size_t w,
size_t n,
bool b =
false) {
121 ASSERT_require(w <=
nBits(src));
125 return select(lowMask<Unsigned>(w),
shiftRight(src & lowMask<Unsigned>(w), n, b), src);
133 template<
typename Un
signed>
135 return i < nBits<Unsigned>() ?
shiftLeft(Unsigned(1), i) : Unsigned(0);
141 template<
typename Un
signed>
143 ASSERT_require(w <=
nBits(src));
144 return select(lowMask<Unsigned>(w), position<Unsigned>(i), src);
152 template<
typename Un
signed>
153 inline Unsigned
mask(
size_t least,
size_t greatest) {
154 ASSERT_require(greatest < nBits<Unsigned>());
155 ASSERT_require(greatest >= least);
156 return shiftLeft(lowMask<Unsigned>(greatest - least + 1), least);
162 template<
typename Un
signed>
163 inline Unsigned
maskLsb(Unsigned src,
size_t w,
size_t least,
size_t greatest) {
164 ASSERT_require(w <=
nBits(src));
165 return select(lowMask<Unsigned>(w), mask<Unsigned>(least, greatest), src);
171 template<
typename Un
signed>
172 inline bool bit(Unsigned src,
size_t i) {
173 return i < nBits(src) ? (src & position<Unsigned>(i)) != 0 :
false;
180 template<
typename Un
signed>
181 inline bool bitLsb(Unsigned src,
size_t w,
size_t i) {
182 return i < w ? (src & position<Unsigned>(i)) != 0 :
false;
188 template<
typename Un
signed>
189 inline bool msb(Unsigned src) {
196 template<
typename Un
signed>
197 inline bool msbLsb(Unsigned src,
size_t w) {
198 ASSERT_require(w <=
nBits(src));
199 return w > 0 ?
bit(src, w-1) :
false;
208 template<
typename Un
signed>
220 template<
typename Un
signed>
229 template<
typename Un
signed>
230 inline Unsigned
bits(Unsigned src,
size_t least,
size_t greatest) {
231 return shiftRight(src & mask<Unsigned>(least, greatest), least);
238 template<
typename Un
signed>
239 inline Unsigned
bitsLsb(Unsigned src,
size_t w,
size_t least,
size_t greatest) {
240 return shiftRight(src & mask<Unsigned>(least, greatest) & lowMask<Unsigned>(w), least);
248 template<
typename Un
signedTarget,
typename Un
signedSource>
249 inline UnsignedTarget
convert(UnsignedSource x,
bool b =
false) {
250 if (
nBits(x) < nBits<UnsignedTarget>()) {
252 return UnsignedTarget(x) | (all<UnsignedTarget>(b) & ~lowMask<UnsignedTarget>(
nBits(x)));
255 return UnsignedTarget(x & lowMask<UnsignedSource>(nBits<UnsignedTarget>()));
263 template<
typename Un
signedTarget,
typename Un
signedSource>
265 return convert<UnsignedTarget>(x,
msb(x));
271 template<
typename Un
signed>
273 if (n <
nBits(src)) {
275 src |= mask<Unsigned>(n,
nBits(src)-1);
277 src &= ~mask<Unsigned>(n,
nBits(src)-1);
287 template<
typename Un
signed>
289 ASSERT_require(n > 0);
290 ASSERT_require(m >= n);
291 ASSERT_require(m <=
nBits(src));
295 Unsigned newBitsMask = mask<Unsigned>(n, m-1);
297 return src | newBitsMask;
299 return src & ~newBitsMask;
309 template<
typename Un
signed>
319 template<
typename Un
signed>
321 ASSERT_require(w <=
nBits(src));
323 return select(lowMask<Unsigned>(w),
333 template<
typename Un
signed>
343 template<
typename Un
signed>
345 ASSERT_require(w <=
nBits(src));
347 return select(lowMask<Unsigned>(w),
358 template<
typename Un
signed>
360 ASSERT_require(n != 0);
361 if (n >=
nBits(src)) {
364 size_t ngroups = (
nBits(src) + 1) / n;
366 for (
size_t i = 0; i < ngroups; ++i)
367 retval |=
shiftLeft(src & lowMask<Unsigned>(n), i*n);
377 template<
typename Un
signed>
379 ASSERT_require(w <=
nBits(src));
386 template<
typename Un
signed>
389 for (
size_t i =
nBits(src); i > 0; --i) {
397 template<
typename Un
signed>
398 inline size_t nSet(Unsigned src) {
Unsigned bits(Unsigned src, size_t least, size_t greatest)
Extract part of a value.
Unsigned position(size_t i)
Generate a single-bit mask.
Unsigned signExtendLsb(Unsigned src, size_t n, size_t m)
Sign extend part of value without affecting other bits.
bool msbLsb(Unsigned src, size_t w)
Most significant bit within lsb region.
Unsigned shiftLeft(Unsigned src, size_t n, bool b=false)
Left shift a value.
UnsignedTarget convert(UnsignedSource x, bool b=false)
Extend or truncate a value.
bool bitLsb(Unsigned src, size_t w, size_t i)
Extract a single bit.
Sawyer::Optional< size_t > highestSetBit(Unsigned src)
Index of the highest set bit.
Unsigned mask(size_t least, size_t greatest)
Generate a mask.
Unsigned rotateRightLsb(Unsigned src, size_t w, size_t n)
Rotate low-order bits right without affecting others.
Unsigned rotateLeft(Unsigned src, size_t n)
Rotate bits left.
Unsigned replicateLsb(Unsigned src, size_t w, size_t n)
Replicate low-order bits to fill region without affecting other bits.
Unsigned shiftRightSigned(Unsigned src, size_t n)
Right shift replicating MSB.
Unsigned replicate(Unsigned src, size_t n)
Replicate low-order bits to fill return value.
Unsigned signExtend(Unsigned src, size_t n)
Sign extend part of a value to the full width of the src type.
Unsigned highMask(size_t n)
Generate a value with high order bits set.
bool msb(Unsigned src)
Most significant bit.
bool bit(Unsigned src, size_t i)
Extract a single bit.
Unsigned shiftLeftLsb(Unsigned src, size_t w, size_t n, bool b=false)
Left shift part of a value without affecting the rest.
Unsigned bitsLsb(Unsigned src, size_t w, size_t least, size_t greatest)
Extract part of a value limited by width.
Unsigned shiftRightLsb(Unsigned src, size_t w, size_t n, bool b=false)
Right shift part of a value without affecting the rest.
size_t nBits(Unsigned x=Unsigned(0))
Number of bits in a type or value.
Unsigned allLsb(Unsigned src, size_t w, bool b=true)
Set or clear the low-order bits.
Unsigned positionLsb(Unsigned src, size_t w, size_t i)
Generate a single-bit mask without affecting the high-order bits.
Main namespace for the ROSE library.
Unsigned lowMask(size_t n)
Generate a value with low order bits set.
Unsigned maskLsb(Unsigned src, size_t w, size_t least, size_t greatest)
Generate a mask without affecting other bits.
UnsignedTarget convertSigned(UnsignedSource x)
Sign extend or truncate a value.
Unsigned rotateRight(Unsigned src, size_t n)
Rotate bits right.
Unsigned all(bool b=true)
Generate a value with all bits set or cleared.
Unsigned shiftRight(Unsigned src, size_t n, bool b=false)
Right shift a value.
Unsigned rotateLeftLsb(Unsigned src, size_t w, size_t n)
Rotate low-order bits left without affecting others.
Unsigned select(Unsigned cond, Unsigned a, Unsigned b)
Combine two values based on a bit mask.