14
14
#include " std_types.h"
15
15
#include " std_expr.h"
16
16
17
+ #include < algorithm>
18
+
17
19
bool to_integer (const exprt &expr, mp_integer &int_value)
18
20
{
19
21
if (!expr.is_constant ())
@@ -285,11 +287,16 @@ bool get_bvrep_bit(
285
287
std::size_t width,
286
288
std::size_t bit_index)
287
289
{
288
- // The representation is binary, using '0'/'1',
289
- // most significant bit first.
290
290
PRECONDITION (bit_index < width);
291
- PRECONDITION (src.size () == width);
292
- return src[src.size () - 1 - bit_index] == ' 1' ;
291
+
292
+ const auto byte_index = bit_index >> 3 ;
293
+
294
+ if (byte_index >= src.size ())
295
+ return false ;
296
+
297
+ unsigned char byte = src[src.size () - 1 - byte_index];
298
+
299
+ return ((byte >> (bit_index & 7 )) & 1 ) != 0 ;
293
300
}
294
301
295
302
// / construct a bit-vector representation from a functor
@@ -299,10 +306,31 @@ bool get_bvrep_bit(
299
306
irep_idt
300
307
make_bvrep (const std::size_t width, const std::function<bool (std::size_t )> f)
301
308
{
302
- std::string result (width, ' ' );
309
+ std::string result;
310
+ result.reserve (width / 8 + 1 );
311
+ unsigned byte = 0 ;
303
312
304
313
for (std::size_t i = 0 ; i < width; i++)
305
- result[width - 1 - i] = f (i) ? ' 1' : ' 0' ;
314
+ {
315
+ const auto bit_in_byte = i % 8 ;
316
+
317
+ byte |= ((unsigned )f (i)) << bit_in_byte;
318
+
319
+ if (bit_in_byte == 7 )
320
+ {
321
+ result += (char )byte;
322
+ byte = 0 ;
323
+ }
324
+ }
325
+
326
+ if (byte != 0 )
327
+ result += (char )byte;
328
+
329
+ // drop leading zeros
330
+ while (!result.empty () && result.back () == 0 )
331
+ result.resize (result.size () - 1 );
332
+
333
+ std::reverse (result.begin (), result.end ());
306
334
307
335
return result;
308
336
}
@@ -341,15 +369,66 @@ irep_idt bvrep_bitwise_op(
341
369
});
342
370
}
343
371
372
+ std::string dump_integer (mp_integer src)
373
+ {
374
+ std::size_t d = src.digits (256 ) + 1 ;
375
+ unsigned char *buf = new unsigned char [d], *p = buf;
376
+ src.dump (buf, d);
377
+ while (d > 0 && *p == 0 )
378
+ {
379
+ d--;
380
+ p++;
381
+ }
382
+ return std::string ((char *)p, d);
383
+ }
384
+
344
385
// / convert an integer to bit-vector representation with given width
386
+ // / This uses two's complement for negative numbers.
387
+ // / If the value is out of range, it is 'wrapped around'.
345
388
irep_idt integer2bvrep (const mp_integer &src, std::size_t width)
346
389
{
347
- return integer2binary (src, width);
390
+ const mp_integer p = power (2 , width);
391
+
392
+ if (src.is_negative ())
393
+ {
394
+ // do two's complement encoding of negative numbers
395
+ mp_integer tmp = src;
396
+ tmp.negate ();
397
+ tmp %= p;
398
+ if (tmp != 0 )
399
+ tmp = p - tmp;
400
+ return dump_integer (tmp);
401
+ }
402
+ else
403
+ {
404
+ // we 'wrap around' if 'src' is too large
405
+ return dump_integer (src % p);
406
+ }
348
407
}
349
408
350
409
// / convert a bit-vector representation (possibly signed) to integer
351
410
mp_integer bvrep2integer (const irep_idt &src, std::size_t width, bool is_signed)
352
411
{
353
- PRECONDITION (src.size () == width);
354
- return binary2integer (id2string (src), is_signed);
412
+ if (is_signed)
413
+ {
414
+ PRECONDITION (width >= 1 );
415
+ mp_integer tmp;
416
+ tmp.load ((const unsigned char *)src.data (), src.size ());
417
+ const auto p = power (2 , width - 1 );
418
+ if (tmp >= p)
419
+ {
420
+ const auto result = tmp - 2 * p;
421
+ PRECONDITION (result >= -p);
422
+ return result;
423
+ }
424
+ else
425
+ return tmp;
426
+ }
427
+ else
428
+ {
429
+ mp_integer result;
430
+ result.load ((const unsigned char *)src.data (), src.size ());
431
+ PRECONDITION (result < power (2 , width));
432
+ return result;
433
+ }
355
434
}
0 commit comments