PandA-2024.02
APInt.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2020-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
44 #include "APInt.hpp"
45 
46 #include "exceptions.hpp"
47 
48 using namespace boost::multiprecision;
49 
50 using bw_t = APInt::bw_t;
51 
52 #pragma GCC diagnostic push
53 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
54 APInt::APInt() : _data(57)
55 {
56 }
57 #pragma GCC diagnostic pop
58 
59 bool operator<(const APInt& lhs, const APInt& rhs)
60 {
61  return lhs._data < rhs._data;
62 }
63 
64 bool operator>(const APInt& lhs, const APInt& rhs)
65 {
66  return lhs._data > rhs._data;
67 }
68 
69 bool operator<=(const APInt& lhs, const APInt& rhs)
70 {
71  return lhs._data <= rhs._data;
72 }
73 
74 bool operator>=(const APInt& lhs, const APInt& rhs)
75 {
76  return lhs._data >= rhs._data;
77 }
78 
79 bool operator==(const APInt& lhs, const APInt& rhs)
80 {
81  return lhs._data == rhs._data;
82 }
83 
84 bool operator!=(const APInt& lhs, const APInt& rhs)
85 {
86  return lhs._data != rhs._data;
87 }
88 
89 APInt::operator bool() const
90 {
91  return _data != 0;
92 }
93 
94 /*
95  * Binary operators
96  */
97 APInt operator+(const APInt& lhs, const APInt& rhs)
98 {
99  return APInt(lhs) += rhs;
100 }
101 
102 APInt operator-(const APInt& lhs, const APInt& rhs)
103 {
104  return APInt(lhs) -= rhs;
105 }
106 
107 APInt operator*(const APInt& lhs, const APInt& rhs)
108 {
109  return APInt(lhs) *= rhs;
110 }
111 
112 APInt operator/(const APInt& lhs, const APInt& rhs)
113 {
114  return APInt(lhs) /= rhs;
115 }
116 
117 APInt operator%(const APInt& lhs, const APInt& rhs)
118 {
119  return APInt(lhs) %= rhs;
120 }
121 
122 APInt operator&(const APInt& lhs, const APInt& rhs)
123 {
124  return APInt(lhs) &= rhs;
125 }
126 
127 APInt operator|(const APInt& lhs, const APInt& rhs)
128 {
129  return APInt(lhs) |= rhs;
130 }
131 
132 APInt operator^(const APInt& lhs, const APInt& rhs)
133 {
134  return APInt(lhs) ^= rhs;
135 }
136 
137 APInt operator<<(const APInt& lhs, const APInt& rhs)
138 {
139  return APInt(lhs) <<= rhs;
140 }
141 
142 APInt operator>>(const APInt& lhs, const APInt& rhs)
143 {
144  return APInt(lhs) >>= rhs;
145 }
146 
148 {
149  _data += rhs._data;
150  return *this;
151 }
152 
154 {
155  _data -= rhs._data;
156  return *this;
157 }
158 
160 {
161  _data *= rhs._data;
162  return *this;
163 }
164 
166 {
167  _data /= rhs._data;
168  return *this;
169 }
170 
172 {
173  _data %= rhs._data;
174  return *this;
175 }
176 
177 APInt& APInt::operator&=(const APInt& rhs)
178 {
179  _data &= rhs._data;
180  return *this;
181 }
182 
184 {
185  _data |= rhs._data;
186  return *this;
187 }
188 
190 {
191  _data ^= rhs._data;
192  return *this;
193 }
194 
196 {
197  _data <<= static_cast<bw_t>(rhs._data);
198  return *this;
199 }
200 
202 {
203  _data >>= static_cast<bw_t>(rhs._data);
204  return *this;
205 }
206 
207 /*
208  * Unary operators
209  */
211 {
212  APInt abs;
214  return abs;
215 }
216 
218 {
219  APInt neg;
220  neg._data = -_data;
221  return neg;
222 }
223 
225 {
226  APInt _not;
227  _not._data = ~_data;
228  return _not;
229 }
230 
232 {
233  APInt t = *this;
234  ++_data;
235  return t;
236 }
237 
239 {
240  APInt t = *this;
241  --_data;
242  return t;
243 }
244 
246 {
247  return operator+=(1LL);
248 }
249 
251 {
252  return operator-=(1LL);
253 }
254 
256 {
257  _data |= 0x1_apint << i;
258 }
259 
261 {
262  _data &= ~(0x1_apint << i);
263 }
264 
265 bool APInt::bit_tst(bw_t i) const
266 {
267  return ((_data >> i) & 1) != 0;
268 }
269 
270 bool APInt::sign() const
271 {
272  return _data < 0;
273 }
274 
275 #ifdef __clang__
276 #pragma clang diagnostic push
277 #pragma clang diagnostic ignored "-Wconversion"
278 #pragma clang diagnostic ignored "-Wsign-conversion"
279 #else
280 #pragma GCC diagnostic push
281 #pragma GCC diagnostic ignored "-Wconversion"
282 #pragma GCC diagnostic ignored "-Wsign-conversion"
283 #endif
284 
286 {
287  THROW_ASSERT(bw, "Minimum bitwidth of 1 is required");
288  const number mask = (0x1_apint << bw) - 1;
289  _data &= mask;
290  if(sign && bit_tst(bw - 1U))
291  {
292  _data += (-0x1_apint << bw);
293  }
294  return *this;
295 }
296 
298 {
299  THROW_ASSERT(bw, "Minimum bitwidth of 1 is required");
300  const number mask = (0x1_apint << bw) - 1;
301  APInt val(_data & mask);
302  if(sign && val.bit_tst(bw - 1U))
303  {
304  val += (-0x1_apint << bw);
305  }
306  return APInt(val);
307 }
308 
310 {
311  bw_t i = 0;
312  for(; i < bw; ++i)
313  {
314  if(bit_tst(i))
315  {
316  break;
317  }
318  }
319  return i;
320 }
321 
323 {
324  bw_t i = 0;
325  for(; i < bw; ++i)
326  {
327  if(!bit_tst(i))
328  {
329  break;
330  }
331  }
332  return i;
333 }
334 
336 {
337  if(_data < 0)
338  {
339  return 0;
340  }
341  if(_data == 0)
342  {
343  return bw;
344  }
345  THROW_ASSERT(_data.backend().size() > 0, "unexpected condition");
346  const auto limbs = _data.backend().limbs();
347  auto nchunks = bw / backend::limb_bits + ((bw % backend::limb_bits) ? 1 : 0);
348  THROW_ASSERT(_data.backend().size() <= nchunks, "unexpected condition");
349  bw_t lzc = 0;
350  bw_t offset = 0;
351  if(_data.backend().size() < nchunks)
352  {
353  lzc += bw - _data.backend().size() * backend::limb_bits;
354  }
355  else
356  {
357  offset += (bw % backend::limb_bits) ? backend::limb_bits - (bw % backend::limb_bits) : 0;
358  }
359  for(int i = _data.backend().size() - 1; i >= 0; --i)
360  {
361  const auto& val = limbs[i];
362  if(val != 0)
363  {
364  if(backend::limb_bits == 64)
365  {
366  return lzc + __builtin_clzll(val) - offset;
367  }
368  else if(backend::limb_bits == 32)
369  {
370  return lzc + __builtin_clz(val) - offset;
371  }
372  else
373  {
374  THROW_ERROR("backend::limb_bits size not supported");
375  }
376  }
377  lzc += backend::limb_bits;
378  }
379  return lzc;
380 }
381 
383 {
384  bw_t i = bw;
385  for(; i > 0; --i)
386  {
387  if(!bit_tst(i - 1U))
388  {
389  break;
390  }
391  }
392  return bw - i;
393 }
394 
396 {
397  if(_data.backend().isneg())
398  {
399  if(!sign)
400  {
401  return std::numeric_limits<number>::digits;
402  }
403  return std::numeric_limits<number>::digits + 1 -
404  APInt(-_data - 1).leadingZeros(std::numeric_limits<number>::digits);
405  }
406  else if(_data.is_zero())
407  {
408  return 1U;
409  }
410  return std::numeric_limits<number>::digits - leadingZeros(std::numeric_limits<number>::digits) + sign;
411 }
412 
413 #ifdef __clang__
414 #pragma clang diagnostic pop
415 #else
416 #pragma GCC diagnostic pop
417 #endif
418 
420 {
421  return (APInt(1) << bw) - 1;
422 }
423 
425 {
426  return APInt(0);
427 }
428 
430 {
431  return (APInt(1) << (bw - 1)) - APInt(1);
432 }
433 
435 {
436  return -(APInt(1) << (bw - 1));
437 }
438 
439 std::ostream& operator<<(std::ostream& str, const APInt& v)
440 {
441  str << v._data;
442  return str;
443 }
444 
445 std::istream& operator>>(std::istream& str, APInt& v)
446 {
447  str >> v._data;
448  return str;
449 }
APInt & extOrTrunc(bw_t bw, bool sign)
Definition: APInt.cpp:285
static APInt getSignedMinValue(bw_t bw)
Definition: APInt.cpp:434
APInt & operator--()
Definition: APInt.cpp:250
APInt & operator|=(const APInt &rhs)
Definition: APInt.cpp:183
bool bit_tst(bw_t i) const
Definition: APInt.cpp:265
friend bool operator>=(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:74
exceptions managed by PandA
APInt & operator*=(const APInt &rhs)
Definition: APInt.cpp:159
Range::bw_t bw_t
Definition: Range.cpp:69
static APInt getSignedMaxValue(bw_t bw)
Definition: APInt.cpp:429
bw_t leadingOnes(bw_t bw) const
Definition: APInt.cpp:382
APInt & operator++()
Definition: APInt.cpp:245
friend APInt operator*(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:107
APInt & operator<<=(const APInt &rhs)
Definition: APInt.cpp:195
friend APInt operator/(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:112
#define abs(x)
Definition: main.c:3
bw_t trailingZeros(bw_t bw) const
Definition: APInt.cpp:309
APInt & operator-=(const APInt &rhs)
Definition: APInt.cpp:153
bool
Definition: bellmanford.c:29
bw_t minBitwidth(bool sign) const
Definition: APInt.cpp:395
APInt & operator &=(const APInt &rhs)
friend APInt operator>>(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:142
APInt & operator+=(const APInt &rhs)
Definition: APInt.cpp:147
friend bool operator==(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:79
APInt operator~() const
Definition: APInt.cpp:224
void bit_set(bw_t i)
Definition: APInt.cpp:255
friend bool operator!=(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:84
friend bool operator<=(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:69
static APInt getMaxValue(bw_t bw)
Definition: APInt.cpp:419
APInt & operator%=(const APInt &rhs)
Definition: APInt.cpp:171
boost::multiprecision::number< backend > number
Definition: APInt.hpp:58
unsigned offset[NUM_VERTICES+1]
Definition: graph.h:3
friend bool operator<(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:59
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
uint16_t bw_t
Definition: APInt.hpp:59
friend APInt operator &(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:122
bw_t leadingZeros(bw_t bw) const
Definition: APInt.cpp:335
APInt & operator/=(const APInt &rhs)
Definition: APInt.cpp:165
Definition: APInt.hpp:53
bool sign() const
Definition: APInt.cpp:270
bw_t trailingOnes(bw_t bw) const
Definition: APInt.cpp:322
void bit_clr(bw_t i)
Definition: APInt.cpp:260
friend APInt operator<<(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:137
APInt operator-() const
Definition: APInt.cpp:217
APInt abs() const
Definition: APInt.cpp:210
static APInt getMinValue(bw_t bw)
Definition: APInt.cpp:424
char str[25]
Definition: fixedptc.c:8
APInt & operator^=(const APInt &rhs)
Definition: APInt.cpp:189
friend APInt operator|(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:127
APInt()
Definition: APInt.cpp:54
APInt & operator>>=(const APInt &rhs)
Definition: APInt.cpp:201
friend APInt operator^(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:132
friend APInt operator+(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:97
number _data
Definition: APInt.hpp:62
friend APInt operator%(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:117
friend bool operator>(const APInt &lhs, const APInt &rhs)
Definition: APInt.cpp:64
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:56 for PandA-2024.02 by doxygen 1.8.13