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,35 @@ 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
+ // The representation is hex, i.e., four bits per letter,
293
+ // most significant nibble first.
294
+ const auto nibble_index = bit_index / 4 ;
295
+
296
+ if (nibble_index >= src.size ())
297
+ return false ;
298
+
299
+ const char nibble = src[src.size () - 1 - nibble_index];
300
+
301
+ DATA_INVARIANT (isxdigit (nibble), " bvrep is hexadecimal" );
302
+
303
+ const unsigned char nibble_value =
304
+ isdigit (nibble) ? nibble - ' 0'
305
+ : islower (nibble) ? nibble - ' a' + 10 : nibble - ' A' + 10 ;
306
+
307
+ return ((nibble_value >> (bit_index % 4 )) & 1 ) != 0 ;
308
+ }
309
+
310
+ // / turn a value 0...15 into '0'-'9', 'A'-'Z'
311
+ static char nibble2hex (unsigned char nibble)
312
+ {
313
+ PRECONDITION (nibble <= 0xf );
314
+
315
+ if (nibble >= 10 )
316
+ return ' A' + nibble - 10 ;
317
+ else
318
+ return ' 0' + nibble;
293
319
}
294
320
295
321
// / construct a bit-vector representation from a functor
@@ -299,12 +325,39 @@ bool get_bvrep_bit(
299
325
irep_idt
300
326
make_bvrep (const std::size_t width, const std::function<bool (std::size_t )> f)
301
327
{
302
- std::string result (width, ' ' );
328
+ std::string result;
329
+ result.reserve ((width + 3 ) / 4 );
330
+ unsigned char nibble = 0 ;
303
331
304
332
for (std::size_t i = 0 ; i < width; i++)
305
- result[width - 1 - i] = f (i) ? ' 1' : ' 0' ;
333
+ {
334
+ const auto bit_in_nibble = i % 4 ;
306
335
307
- return result;
336
+ nibble |= ((unsigned char )f (i)) << bit_in_nibble;
337
+
338
+ if (bit_in_nibble == 3 )
339
+ {
340
+ result += nibble2hex (nibble);
341
+ nibble = 0 ;
342
+ }
343
+ }
344
+
345
+ if (nibble != 0 )
346
+ result += nibble2hex (nibble);
347
+
348
+ // drop leading zeros
349
+ const std::size_t pos = result.find_last_not_of (' 0' );
350
+
351
+ if (pos == std::string::npos)
352
+ return ID_0;
353
+ else
354
+ {
355
+ result.resize (pos + 1 );
356
+
357
+ std::reverse (result.begin (), result.end ());
358
+
359
+ return result;
360
+ }
308
361
}
309
362
310
363
// / perform a binary bit-wise operation, given as a functor,
@@ -342,14 +395,50 @@ irep_idt bvrep_bitwise_op(
342
395
}
343
396
344
397
// / convert an integer to bit-vector representation with given width
398
+ // / This uses two's complement for negative numbers.
399
+ // / If the value is out of range, it is 'wrapped around'.
345
400
irep_idt integer2bvrep (const mp_integer &src, std::size_t width)
346
401
{
347
- return integer2binary (src, width);
402
+ const mp_integer p = power (2 , width);
403
+
404
+ if (src.is_negative ())
405
+ {
406
+ // do two's complement encoding of negative numbers
407
+ mp_integer tmp = src;
408
+ tmp.negate ();
409
+ tmp %= p;
410
+ if (tmp != 0 )
411
+ tmp = p - tmp;
412
+ return integer2string (tmp, 16 );
413
+ }
414
+ else
415
+ {
416
+ // we 'wrap around' if 'src' is too large
417
+ return integer2string (src % p, 16 );
418
+ }
348
419
}
349
420
350
421
// / convert a bit-vector representation (possibly signed) to integer
351
422
mp_integer bvrep2integer (const irep_idt &src, std::size_t width, bool is_signed)
352
423
{
353
- PRECONDITION (src.size () == width);
354
- return binary2integer (id2string (src), is_signed);
424
+ if (is_signed)
425
+ {
426
+ PRECONDITION (width >= 1 );
427
+ const auto tmp = string2integer (id2string (src), 16 );
428
+ const auto p = power (2 , width - 1 );
429
+ if (tmp >= p)
430
+ {
431
+ const auto result = tmp - 2 * p;
432
+ PRECONDITION (result >= -p);
433
+ return result;
434
+ }
435
+ else
436
+ return tmp;
437
+ }
438
+ else
439
+ {
440
+ const auto result = string2integer (id2string (src), 16 );
441
+ PRECONDITION (result < power (2 , width));
442
+ return result;
443
+ }
355
444
}
0 commit comments