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