CBMC
Loading...
Searching...
No Matches
arith_tools.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include "arith_tools.h"
10
11#include "c_types.h"
12#include "expr_util.h"
13#include "fixedbv.h"
14#include "ieee_float.h"
15#include "invariant.h"
16#include "mathematical_types.h"
17#include "std_expr.h"
18
19#include <algorithm>
20
22{
23 const irep_idt &value=expr.get_value();
24 const typet &type=expr.type();
25 const irep_idt &type_id=type.id();
26
28 {
29 if(expr.is_null_pointer())
30 {
31 int_value=0;
32 return false;
33 }
34 }
35 else if(type_id == ID_integer || type_id == ID_natural || type_id == ID_range)
36 {
38 return false;
39 }
40 else if(type_id==ID_unsignedbv)
41 {
42 const auto width = to_unsignedbv_type(type).get_width();
43 int_value = bvrep2integer(value, width, false);
44 return false;
45 }
46 else if(type_id==ID_signedbv)
47 {
48 const auto width = to_signedbv_type(type).get_width();
49 int_value = bvrep2integer(value, width, true);
50 return false;
51 }
52 else if(type_id==ID_c_bool)
53 {
54 const auto width = to_c_bool_type(type).get_width();
55 int_value = bvrep2integer(value, width, false);
56 return false;
57 }
58 else if(type_id==ID_c_enum)
59 {
60 const typet &underlying_type = to_c_enum_type(type).underlying_type();
61 if(underlying_type.id() == ID_signedbv)
62 {
63 const auto width = to_signedbv_type(underlying_type).get_width();
64 int_value = bvrep2integer(value, width, true);
65 return false;
66 }
67 else if(underlying_type.id() == ID_unsignedbv)
68 {
69 const auto width = to_unsignedbv_type(underlying_type).get_width();
70 int_value = bvrep2integer(value, width, false);
71 return false;
72 }
73 }
74 else if(type_id==ID_c_bit_field)
75 {
76 const auto &c_bit_field_type = to_c_bit_field_type(type);
77 const auto width = c_bit_field_type.get_width();
78 const typet &underlying_type = c_bit_field_type.underlying_type();
79
80 if(underlying_type.id() == ID_signedbv)
81 {
82 int_value = bvrep2integer(value, width, true);
83 return false;
84 }
85 else if(underlying_type.id() == ID_unsignedbv)
86 {
87 int_value = bvrep2integer(value, width, false);
88 return false;
89 }
90 else if(underlying_type.id() == ID_c_bool)
91 {
92 int_value = bvrep2integer(value, width, false);
93 return false;
94 }
95 }
96
97 return true;
98}
99
101 const mp_integer &int_value,
102 const typet &type)
103{
104 const irep_idt &type_id=type.id();
105
107 {
109 }
110 else if(type_id==ID_natural)
111 {
114 }
115 else if(type_id == ID_range)
116 {
117 auto &range_type = to_integer_range_type(type);
121 }
122 else if(type_id==ID_unsignedbv)
123 {
124 std::size_t width=to_unsignedbv_type(type).get_width();
125 return constant_exprt(integer2bvrep(int_value, width), type);
126 }
127 else if(type_id==ID_bv)
128 {
129 std::size_t width=to_bv_type(type).get_width();
130 return constant_exprt(integer2bvrep(int_value, width), type);
131 }
132 else if(type_id==ID_signedbv)
133 {
134 std::size_t width=to_signedbv_type(type).get_width();
135 return constant_exprt(integer2bvrep(int_value, width), type);
136 }
137 else if(type_id==ID_c_enum)
138 {
139 const std::size_t width =
140 to_bitvector_type(to_c_enum_type(type).underlying_type()).get_width();
141 return constant_exprt(integer2bvrep(int_value, width), type);
142 }
143 else if(type_id==ID_c_bool)
144 {
145 std::size_t width=to_c_bool_type(type).get_width();
146 return constant_exprt(integer2bvrep(int_value, width), type);
147 }
148 else if(type_id==ID_bool)
149 {
150 PRECONDITION(int_value == 0 || int_value == 1);
151 if(int_value == 0)
152 return false_exprt();
153 else
154 return true_exprt();
155 }
156 else if(type_id==ID_pointer)
157 {
160 }
161 else if(type_id==ID_c_bit_field)
162 {
163 std::size_t width=to_c_bit_field_type(type).get_width();
164 return constant_exprt(integer2bvrep(int_value, width), type);
165 }
166 else if(type_id==ID_fixedbv)
167 {
170 fixedbv.from_integer(int_value);
171 return fixedbv.to_expr();
172 }
173 else if(type_id==ID_floatbv)
174 {
177 // always rounds to zero
178 ieee_float.from_integer(int_value);
179 return ieee_float.to_expr();
180 }
181 else if(type_id == ID_rational)
182 {
184 }
185 else
186 PRECONDITION(false);
187}
188
190std::size_t address_bits(const mp_integer &size)
191{
192 // in theory an arbitrary-precision integer could be as large as
193 // numeric_limits<std::size_t>::max() * CHAR_BIT (but then we would only be
194 // able to store 2^CHAR_BIT many of those; the implementation of mp_integer as
195 // BigInt is much more restricted as its size is stored as an unsigned int
196 std::size_t result = 1;
197
198 for(mp_integer x = 2; x < size; ++result, x *= 2) {}
199
200 INVARIANT(power(2, result) >= size, "address_bits(size) >= log2(size)");
201
202 return result;
203}
204
206{
208
209 for(x = 1; n > x; x *= 2)
210 {
211 }
212
213 return x == n;
214}
215
220 const mp_integer &exponent)
221{
222 PRECONDITION(exponent >= 0);
223
224 /* There are a number of special cases which are:
225 * A. very common
226 * B. handled more efficiently
227 */
228 if(base.is_long() && exponent.is_long())
229 {
230 switch(base.to_long())
231 {
232 case 2:
233 {
234 mp_integer result;
235 result.setPower2(numeric_cast_v<unsigned>(exponent));
236 return result;
237 }
238 case 1: return 1;
239 case 0: return 0;
240 default:
241 {
242 }
243 }
244 }
245
246 if(exponent==0)
247 return 1;
248
249 if(base<0)
250 {
251 mp_integer result = power(-base, exponent);
252 if(exponent.is_odd())
253 return -result;
254 else
255 return result;
256 }
257
258 mp_integer result=base;
259 mp_integer count=exponent-1;
260
261 while(count!=0)
262 {
263 result*=base;
264 --count;
265 }
266
267 return result;
268}
269
271{
272 if(b<a)
273 a=b;
274}
275
277{
278 if(b>a)
279 a=b;
280}
281
287 const irep_idt &src,
288 std::size_t width,
289 std::size_t bit_index)
290{
291 PRECONDITION(bit_index < width);
292
293 // The representation is hex, i.e., four bits per letter,
294 // most significant nibble first, using uppercase letters.
295 // No lowercase, no leading zeros (other than for 'zero'),
296 // to ensure canonicity.
297 const auto nibble_index = bit_index / 4;
298
299 if(nibble_index >= src.size())
300 return false;
301
302 const char nibble = src[src.size() - 1 - nibble_index];
303
305 isdigit(nibble) || (nibble >= 'A' && nibble <= 'F'),
306 "bvrep is hexadecimal, upper-case");
307
308 const unsigned char nibble_value =
309 isdigit(nibble) ? nibble - '0' : nibble - 'A' + 10;
310
311 return ((nibble_value >> (bit_index % 4)) & 1) != 0;
312}
313
315static char nibble2hex(unsigned char nibble)
316{
317 PRECONDITION(nibble <= 0xf);
318
319 if(nibble >= 10)
320 return 'A' + nibble - 10;
321 else
322 return '0' + nibble;
323}
324
330make_bvrep(const std::size_t width, const std::function<bool(std::size_t)> f)
331{
332 std::string result;
333 result.reserve((width + 3) / 4);
334 unsigned char nibble = 0;
335
336 for(std::size_t i = 0; i < width; i++)
337 {
338 const auto bit_in_nibble = i % 4;
339
340 nibble |= ((unsigned char)f(i)) << bit_in_nibble;
341
342 if(bit_in_nibble == 3)
343 {
344 result += nibble2hex(nibble);
345 nibble = 0;
346 }
347 }
348
349 if(nibble != 0)
350 result += nibble2hex(nibble);
351
352 // drop leading zeros
353 const std::size_t pos = result.find_last_not_of('0');
354
355 if(pos == std::string::npos)
356 return ID_0;
357 else
358 {
359 result.resize(pos + 1);
360
361 std::reverse(result.begin(), result.end());
362
363 return result;
364 }
365}
366
375 const irep_idt &a,
376 const irep_idt &b,
377 const std::size_t width,
378 const std::function<bool(bool, bool)> f)
379{
380 return make_bvrep(width, [&a, &b, &width, f](std::size_t i) {
381 return f(get_bvrep_bit(a, width, i), get_bvrep_bit(b, width, i));
382 });
383}
384
392 const irep_idt &a,
393 const std::size_t width,
394 const std::function<bool(bool)> f)
395{
396 return make_bvrep(width, [&a, &width, f](std::size_t i) {
397 return f(get_bvrep_bit(a, width, i));
398 });
399}
400
404irep_idt integer2bvrep(const mp_integer &src, std::size_t width)
405{
406 const mp_integer p = power(2, width);
407
408 if(src.is_negative())
409 {
410 // do two's complement encoding of negative numbers
411 mp_integer tmp = src;
412 tmp.negate();
413 tmp %= p;
414 if(tmp != 0)
415 tmp = p - tmp;
416 return integer2string(tmp, 16);
417 }
418 else
419 {
420 // we 'wrap around' if 'src' is too large
421 return integer2string(src % p, 16);
422 }
423}
424
426mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
427{
428 if(is_signed)
429 {
430 PRECONDITION(width >= 1);
431 const auto tmp = string2integer(id2string(src), 16);
432 const auto p = power(2, width - 1);
433 if(tmp >= p)
434 {
435 const auto result = tmp - 2 * p;
436 PRECONDITION(result >= -p);
437 return result;
438 }
439 else
440 return tmp;
441 }
442 else
443 {
444 const auto result = string2integer(id2string(src), 16);
445 PRECONDITION(result < power(2, width));
446 return result;
447 }
448}
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
irep_idt make_bvrep(const std::size_t width, const std::function< bool(std::size_t)> f)
construct a bit-vector representation from a functor
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
std::size_t address_bits(const mp_integer &size)
ceil(log2(size))
void mp_max(mp_integer &a, const mp_integer &b)
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
static char nibble2hex(unsigned char nibble)
turn a value 0...15 into '0'-'9', 'A'-'Z'
bool get_bvrep_bit(const irep_idt &src, std::size_t width, std::size_t bit_index)
Get a bit with given index from bit-vector representation.
bool is_power_of_two(const mp_integer &n)
irep_idt bvrep_bitwise_op(const irep_idt &a, const irep_idt &b, const std::size_t width, const std::function< bool(bool, bool)> f)
perform a binary bit-wise operation, given as a functor, on a bit-vector representation
irep_idt integer2bvrep(const mp_integer &src, std::size_t width)
convert an integer to bit-vector representation with given width This uses two's complement for negat...
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
void mp_min(mp_integer &a, const mp_integer &b)
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition c_types.h:80
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition c_types.h:335
const c_bool_typet & to_c_bool_type(const typet &type)
Cast a typet to a c_bool_typet.
Definition c_types.h:128
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
A constant literal expression.
Definition std_expr.h:3007
const irep_idt & get_value() const
Definition std_expr.h:3015
bool is_null_pointer() const
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition std_expr.cpp:170
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
size_t size() const
Definition dstring.h:121
typet & type()
Return the type of the expression.
Definition expr.h:85
The Boolean constant false.
Definition std_expr.h:3135
An IEEE 754 value plus a rounding mode, enabling operations with rounding on values.
Definition ieee_float.h:338
const irep_idt & id() const
Definition irep.h:388
The null pointer constant.
The Boolean constant true.
Definition std_expr.h:3126
The type of an expression, extends irept.
Definition type.h:29
int isdigit(int c)
Definition ctype.c:24
Deprecated expression utility functions.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
literalt pos(literalt a)
Definition literal.h:194
Mathematical types.
const integer_range_typet & to_integer_range_type(const typet &type)
Cast a typet to a integer_range_typet.
const mp_integer string2integer(const std::string &n, unsigned base)
Definition mp_arith.cpp:54
const std::string integer2string(const mp_integer &n, unsigned base)
Definition mp_arith.cpp:103
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
BigInt mp_integer
Definition smt_terms.h:17
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
API to expression classes.
bool is_signed(const typet &t)
Convenience function – is the type signed?
Definition util.cpp:45