Skip to content

Commit 3f832e7

Browse files
author
Daniel Kroening
committed
base 256 bitvector representation
Simultaneously leading zeros are dropped. This reduces the memory consumption of bit-vectors by 8x or more.
1 parent 8cd3a87 commit 3f832e7

File tree

4 files changed

+92
-20
lines changed

4 files changed

+92
-20
lines changed

regression/invariants/invariant-irep-diagnostic/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ invariant-with-irep-diagnostics
55
^SIGNAL=0$
66
--- begin invariant violation report ---
77
Invariant check failed
8-
value: 00000000000000000000000000001000
9-
value: 00000000000000000000000000001101
8+
value: 8
9+
value: [dD]

src/solvers/flattening/boolbv_constant.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,6 @@ bvt boolbvt::convert_constant(const constant_exprt &expr)
8181
{
8282
const auto &value = expr.get_value();
8383

84-
if(value.size() != width)
85-
{
86-
error().source_location=expr.find_source_location();
87-
error() << "wrong value length in constant: "
88-
<< expr.pretty() << eom;
89-
throw 0;
90-
}
91-
9284
for(std::size_t i=0; i<width; i++)
9385
{
9486
const bool bit = get_bvrep_bit(value, width, i);

src/util/arith_tools.cpp

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Author: Daniel Kroening, [email protected]
1414
#include "std_types.h"
1515
#include "std_expr.h"
1616

17+
#include <algorithm>
18+
1719
bool to_integer(const exprt &expr, mp_integer &int_value)
1820
{
1921
if(!expr.is_constant())
@@ -285,11 +287,16 @@ 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+
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;
293300
}
294301

295302
/// construct a bit-vector representation from a functor
@@ -299,10 +306,31 @@ bool get_bvrep_bit(
299306
irep_idt
300307
make_bvrep(const std::size_t width, const std::function<bool(std::size_t)> f)
301308
{
302-
std::string result(width, ' ');
309+
std::string result;
310+
result.reserve(width / 8 + 1);
311+
unsigned byte = 0;
303312

304313
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());
306334

307335
return result;
308336
}
@@ -341,15 +369,66 @@ irep_idt bvrep_bitwise_op(
341369
});
342370
}
343371

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+
344385
/// 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'.
345388
irep_idt integer2bvrep(const mp_integer &src, std::size_t width)
346389
{
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+
}
348407
}
349408

350409
/// convert a bit-vector representation (possibly signed) to integer
351410
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
352411
{
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+
}
355434
}

src/util/expr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ bool exprt::is_zero() const
198198
type_id == ID_unsignedbv || type_id == ID_signedbv ||
199199
type_id == ID_c_bool || type_id == ID_c_bit_field)
200200
{
201-
return constant.value_is_zero_string();
201+
// zero is the empty string
202+
return constant.get_value().empty();
202203
}
203204
else if(type_id==ID_fixedbv)
204205
{

0 commit comments

Comments
 (0)