1414#include " std_types.h"
1515#include " std_expr.h"
1616
17+ #include < algorithm>
18+
1719bool to_integer (const exprt &expr, mp_integer &int_value)
1820{
1921 if (!expr.is_constant ())
@@ -285,11 +287,38 @@ bool get_bvrep_bit(
285287 std::size_t width,
286288 std::size_t bit_index)
287289{
288- // The representation is binary, using '0'/'1',
289- // most significant bit first.
290290 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;
293322}
294323
295324// / construct a bit-vector representation from a functor
@@ -299,12 +328,39 @@ bool get_bvrep_bit(
299328irep_idt
300329make_bvrep (const std::size_t width, const std::function<bool (std::size_t )> f)
301330{
302- std::string result (width, ' ' );
331+ std::string result;
332+ result.reserve ((width + 3 ) / 4 );
333+ unsigned char nibble = 0 ;
303334
304335 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 ;
306338
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+ }
308364}
309365
310366// / perform a binary bit-wise operation, given as a functor,
@@ -342,14 +398,50 @@ irep_idt bvrep_bitwise_op(
342398}
343399
344400// / 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'.
345403irep_idt integer2bvrep (const mp_integer &src, std::size_t width)
346404{
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+ }
348422}
349423
350424// / convert a bit-vector representation (possibly signed) to integer
351425mp_integer bvrep2integer (const irep_idt &src, std::size_t width, bool is_signed)
352426{
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+ }
355447}
0 commit comments