openMSX
uint128.hh
Go to the documentation of this file.
1 #ifndef UINT128_HH
2 #define UINT128_HH
3 
4 #include <cstdint>
5 
6 #if defined __x86_64 && !defined _MSC_VER
7 // On 64-bit CPUs gcc already provides a 128-bit type,
8 // use that type because it's most likely much more efficient.
9 // VC++ 2008 does not provide a 128-bit integer type
10 typedef __uint128_t uint128;
11 inline uint64_t toUint64(uint128 a) { return a; }
12 
13 #else // __x86_64 && !_MSC_VER
14 
21 class uint128
22 {
23 public:
24  uint128(const uint128& a) : lo(a.lo), hi(a.hi) {}
25  uint128(uint64_t a) : lo(a), hi(0) {}
26 
27  bool operator!() const
28  {
29  return !(hi || lo);
30  }
31 
33  {
34  return uint128(~lo, ~hi);
35  }
37  {
38  uint128 result = ~*this;
39  ++result;
40  return result;
41  }
42 
44  {
45  ++lo;
46  if (lo == 0) ++hi;
47  return *this;
48  }
50  {
51  if (lo == 0) --hi;
52  --lo;
53  return *this;
54  }
56  {
57  uint128 b = *this;
58  ++*this;
59  return b;
60  }
62  {
63  uint128 b = *this;
64  --*this;
65  return b;
66  }
67 
69  {
70  uint64_t old_lo = lo;
71  lo += b.lo;
72  hi += b.hi + (lo < old_lo);
73  return *this;
74  }
76  {
77  return *this += (-b);
78  }
79 
80  uint128& operator>>=(unsigned n)
81  {
82  n &= 0x7F;
83  if (n < 64) {
84  lo = (hi << (64 - n)) | (lo >> n);
85  hi >>= n;
86  } else {
87  lo = hi >> (n - 64);
88  hi = 0;
89  }
90  return *this;
91  }
92  uint128& operator<<=(unsigned n)
93  {
94  n &= 0x7F;
95  if (n < 64) {
96  hi = (hi << n) | (lo >> (64 - n));
97  lo <<= n;
98  } else {
99  hi = lo << (n - 64);
100  lo = 0;
101  }
102  return *this;
103  }
104 
106  {
107  hi |= b.hi;
108  lo |= b.lo;
109  return *this;
110  }
112  {
113  hi &= b.hi;
114  lo &= b.lo;
115  return *this;
116  }
118  {
119  hi ^= b.hi;
120  lo ^= b.lo;
121  return *this;
122  }
123 
125  {
126  uint128 dummy;
127  *this = div(b, dummy);
128  return *this;
129  }
131  {
132  div(b, *this);
133  return *this;
134  }
135 
136  uint128& operator*=(const uint128& b);
137 
138 private:
139  uint128() {}
140  uint128(uint64_t a, uint64_t b) : lo(a), hi(b) {}
141  uint128 div(const uint128& ds, uint128& remainder) const;
142  bool bit(unsigned n) const;
143  void setBit(unsigned n);
144 
145  uint64_t lo;
146  uint64_t hi;
147 
148  friend bool operator< (const uint128&, const uint128&);
149  friend bool operator==(const uint128&, const uint128&);
150  friend bool operator||(const uint128&, const uint128&);
151  friend bool operator&&(const uint128&, const uint128&);
152  friend uint64_t toUint64(const uint128&);
153 };
154 
155 
156 inline uint128 operator+(const uint128& a, const uint128& b)
157 {
158  return uint128(a) += b;
159 }
160 inline uint128 operator-(const uint128& a, const uint128& b)
161 {
162  return uint128(a) -= b;
163 }
164 inline uint128 operator*(const uint128& a, const uint128& b)
165 {
166  return uint128(a) *= b;
167 }
168 inline uint128 operator/(const uint128& a, const uint128& b)
169 {
170  return uint128(a) /= b;
171 }
172 inline uint128 operator%(const uint128& a, const uint128& b)
173 {
174  return uint128(a) %= b;
175 }
176 
177 inline uint128 operator>>(const uint128& a, unsigned n)
178 {
179  return uint128(a) >>= n;
180 }
181 inline uint128 operator<<(const uint128 & a, unsigned n)
182 {
183  return uint128(a) <<= n;
184 }
185 
186 inline uint128 operator&(const uint128& a, const uint128& b)
187 {
188  return uint128(a) &= b;
189 }
190 inline uint128 operator|(const uint128& a, const uint128& b)
191 {
192  return uint128(a) |= b;
193 }
194 inline uint128 operator^(const uint128& a, const uint128& b)
195 {
196  return uint128(a) ^= b;
197 }
198 
199 inline bool operator<(const uint128& a, const uint128& b)
200 {
201  return (a.hi == b.hi) ? (a.lo < b.lo) : (a.hi < b.hi);
202 }
203 inline bool operator>(const uint128& a, const uint128& b)
204 {
205  return b < a;
206 }
207 inline bool operator<=(const uint128& a, const uint128& b)
208 {
209  return !(b < a);
210 }
211 inline bool operator>=(const uint128& a, const uint128& b)
212 {
213  return !(a < b);
214 }
215 inline bool operator==(const uint128& a, const uint128& b)
216 {
217  return (a.hi == b.hi) && (a.lo == b.lo);
218 }
219 inline bool operator!=(const uint128& a, const uint128& b)
220 {
221  return !(a == b);
222 }
223 
224 inline bool operator&&(const uint128& a, const uint128& b)
225 {
226  return (a.hi || a.lo) && (b.hi || b.lo);
227 }
228 inline bool operator||(const uint128& a, const uint128& b)
229 {
230  return a.hi || a.lo || b.hi || b.lo;
231 }
232 
233 inline uint64_t toUint64(const uint128& a)
234 {
235  return a.lo;
236 }
237 
238 #endif // __x86_64 && !_MSC_VER
239 
240 #endif // UINT128_HH