Update copyright
[dyninst.git] / dataflowAPI / rose / integerOps.h
1 #ifndef ROSE_INTEGEROPS_H
2 #define ROSE_INTEGEROPS_H
3
4 #include <limits>
5 #include <boost/static_assert.hpp>
6
7 namespace IntegerOpsPrivate {
8
9   template <typename T>
10   struct NumBits {
11     BOOST_STATIC_ASSERT (std::numeric_limits<T>::radix == 2);
12     BOOST_STATIC_ASSERT (std::numeric_limits<T>::is_integer);
13     static const size_t value = std::numeric_limits<T>::digits;
14   };
15
16   template <typename T, size_t Count, bool TooBig> struct SHL1Helper;
17   template <typename T, size_t Count>
18   struct SHL1Helper<T, Count, true> {
19     static const T value = 0;
20   };
21   template <typename T, size_t Count>
22   struct SHL1Helper<T, Count, false> {
23     static const T value = T(1) << Count;
24   };
25
26 }
27
28 namespace IntegerOps {
29
30 // 1 << x, handling the case where x is >= the number of bits in T
31 template <typename T, size_t Count>
32 struct SHL1: public IntegerOpsPrivate::SHL1Helper<T, Count, (Count >= IntegerOpsPrivate::NumBits<T>::value)> {};
33
34 // 1 << x, handling the case where x is >= the number of bits in T
35 template <typename T>
36 inline T shl1(size_t count) {
37   return (count >= IntegerOpsPrivate::NumBits<T>::value) ? T(0) : (T(1) << count);
38 }
39
40 // Set rightmost (from LSB) count bits of result, clear others
41 template <typename T, size_t Count>
42 struct GenMask {
43   static const T value = SHL1<T, Count>::value - T(1);
44 };
45
46 template <typename T>
47 inline T genMask(size_t count) {
48   return shl1<T>(count) - 1;
49 }
50
51 template <size_t NBits, typename T>
52 inline bool signBit(T value) {
53   return (value & SHL1<T, NBits - 1>::value) != T(0);
54 }
55
56 template <size_t FromBits, size_t ToBits, typename T>
57 inline T signExtend(T value) {
58   return value | (signBit<FromBits>(value) ? (GenMask<T, ToBits>::value ^ GenMask<T, FromBits>::value) : T(0));
59 }
60
61 template <size_t NBits, typename T>
62 inline T shiftLeft(T value, size_t count) {
63   return (value * shl1<T>(count)) & GenMask<T, NBits>::value;
64 };
65
66 template <size_t NBits, typename T>
67 inline T shiftRightLogical(T value, size_t count) {
68   return (count >= NBits) ? T(0) : (value >> count);
69 }
70
71 template <size_t NBits, typename T>
72 inline T shiftRightArithmetic(T value, size_t count) {
73   if (count >= NBits) {
74     return signBit<NBits>(value) ? GenMask<T, NBits>::value : T(0);
75   } else {
76     return shiftRightLogical<NBits>(value, count) |
77            (signBit<NBits>(value) ? (GenMask<T, NBits>::value ^ genMask<T>(NBits - count)) : T(0));
78   }
79 }
80
81 template <size_t NBits, typename T>
82 inline T rotateLeft(T value, size_t count) {
83   count %= NBits;
84   return ((value << count) | (value >> (NBits - count))) & GenMask<T, NBits>::value;
85 }
86
87 template <size_t NBits, typename T>
88 inline T rotateRight(T value, size_t count) {
89   count %= NBits;
90   return ((value >> count) | (value << (NBits - count))) & GenMask<T, NBits>::value;
91 }
92
93 template <typename T>
94 inline T log2(T a) {
95   T n = T(1);
96   T i = 0;
97   while (n != 0 && n < a) {n <<= 1; ++i;}
98   return i;
99 }
100
101 } // namespace IntegerOps
102
103 #endif // ROSE_INTEGEROPS_H