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,37 @@ 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
+ if (pos != std::string::npos)
351
+ result.resize (pos + 1 );
352
+
353
+ std::reverse (result.begin (), result.end ());
354
+
355
+ if (result.empty ())
356
+ return ID_0;
357
+ else
358
+ return result;
308
359
}
309
360
310
361
// / perform a binary bit-wise operation, given as a functor,
@@ -342,14 +393,50 @@ irep_idt bvrep_bitwise_op(
342
393
}
343
394
344
395
// / convert an integer to bit-vector representation with given width
396
+ // / This uses two's complement for negative numbers.
397
+ // / If the value is out of range, it is 'wrapped around'.
345
398
irep_idt integer2bvrep (const mp_integer &src, std::size_t width)
346
399
{
347
- return integer2binary (src, width);
400
+ const mp_integer p = power (2 , width);
401
+
402
+ if (src.is_negative ())
403
+ {
404
+ // do two's complement encoding of negative numbers
405
+ mp_integer tmp = src;
406
+ tmp.negate ();
407
+ tmp %= p;
408
+ if (tmp != 0 )
409
+ tmp = p - tmp;
410
+ return integer2string (tmp, 16 );
411
+ }
412
+ else
413
+ {
414
+ // we 'wrap around' if 'src' is too large
415
+ return integer2string (src % p, 16 );
416
+ }
348
417
}
349
418
350
419
// / convert a bit-vector representation (possibly signed) to integer
351
420
mp_integer bvrep2integer (const irep_idt &src, std::size_t width, bool is_signed)
352
421
{
353
- PRECONDITION (src.size () == width);
354
- return binary2integer (id2string (src), is_signed);
422
+ if (is_signed)
423
+ {
424
+ PRECONDITION (width >= 1 );
425
+ const auto tmp = string2integer (id2string (src), 16 );
426
+ const auto p = power (2 , width - 1 );
427
+ if (tmp >= p)
428
+ {
429
+ const auto result = tmp - 2 * p;
430
+ PRECONDITION (result >= -p);
431
+ return result;
432
+ }
433
+ else
434
+ return tmp;
435
+ }
436
+ else
437
+ {
438
+ const auto result = string2integer (id2string (src), 16 );
439
+ PRECONDITION (result < power (2 , width));
440
+ return result;
441
+ }
355
442
}
0 commit comments