#include "btorsimbv.h"
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include "util/btor2mem.h"
#define BTOR2_MASK_REM_BITS(bv) \
((((BTORSIM_BV_TYPE) 1 << (BTORSIM_BV_TYPE_BW - 1)) - 1) \
>> (BTORSIM_BV_TYPE_BW - 1 - (bv->width % BTORSIM_BV_TYPE_BW)))
#ifndef NDEBUG
static bool
rem_bits_zero_dbg (BtorSimBitVector *bv)
{
return (bv->width % BTORSIM_BV_TYPE_BW == 0
|| (bv->bits[0] >> (bv->width % BTORSIM_BV_TYPE_BW) == 0));
}
static bool
check_bits_sll_dbg (const BtorSimBitVector *bv,
const BtorSimBitVector *res,
uint32_t shift)
{
assert (bv);
assert (res);
assert (bv->width == res->width);
uint32_t i;
if (shift >= bv->width)
{
for (i = 0; i < bv->width; i++) assert (btorsim_bv_get_bit (bv, i) == 0);
}
else
{
for (i = 0; shift + i < bv->width; i++)
assert (btorsim_bv_get_bit (bv, i)
== btorsim_bv_get_bit (res, shift + i));
}
return true;
}
#endif
static void
set_rem_bits_to_zero (BtorSimBitVector *bv)
{
if (bv->width != BTORSIM_BV_TYPE_BW * bv->len)
bv->bits[0] &= BTOR2_MASK_REM_BITS (bv);
}
BtorSimBitVector *
btorsim_bv_new (uint32_t bw)
{
assert (bw > 0);
uint32_t i;
BtorSimBitVector *res;
i = bw / BTORSIM_BV_TYPE_BW;
if (bw % BTORSIM_BV_TYPE_BW > 0) i += 1;
assert (i > 0);
res =
btorsim_malloc (sizeof (BtorSimBitVector) + sizeof (BTORSIM_BV_TYPE) * i);
memset (res->bits, 0, i * sizeof *(res->bits));
res->len = i;
assert (res->len);
res->width = bw;
return res;
}
BtorSimBitVector *
btorsim_bv_new_random_bit_range (BtorSimRNG *rng,
uint32_t bw,
uint32_t up,
uint32_t lo)
{
assert (rng);
assert (bw > 0);
assert (lo <= up);
uint32_t i;
BtorSimBitVector *res;
res = btorsim_bv_new (bw);
for (i = 1; i < res->len; i++)
res->bits[i] = (BTORSIM_BV_TYPE) btorsim_rng_rand (rng);
res->bits[0] = (BTORSIM_BV_TYPE) btorsim_rng_pick_rand (
rng, 0, ((~0) >> (BTORSIM_BV_TYPE_BW - bw % BTORSIM_BV_TYPE_BW)) - 1);
for (i = 0; i < lo; i++) btorsim_bv_set_bit (res, i, 0);
for (i = up + 1; i < res->width; i++) btorsim_bv_set_bit (res, i, 0);
set_rem_bits_to_zero (res);
return res;
}
BtorSimBitVector *
btorsim_bv_new_random (BtorSimRNG *rng, uint32_t bw)
{
return btorsim_bv_new_random_bit_range (rng, bw, bw - 1, 0);
}
void
btorsim_bv_free (BtorSimBitVector *bv)
{
assert (bv);
BTOR2_DELETE (bv);
}
BtorSimBitVector *
btorsim_bv_char_to_bv (const char *assignment)
{
assert (assignment);
assert (strlen (assignment) > 0);
return btorsim_bv_const (assignment, strlen (assignment));
}
BtorSimBitVector *
btorsim_bv_uint64_to_bv (uint64_t value, uint32_t bw)
{
assert (bw > 0);
BtorSimBitVector *res;
res = btorsim_bv_new (bw);
assert (res->len > 0);
res->bits[res->len - 1] = (BTORSIM_BV_TYPE) value;
if (res->width > 32)
res->bits[res->len - 2] = (BTORSIM_BV_TYPE) (value >> BTORSIM_BV_TYPE_BW);
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_int64_to_bv (int64_t value, uint32_t bw)
{
assert (bw > 0);
BtorSimBitVector *res, *tmp;
res = btorsim_bv_new (bw);
assert (res->len > 0);
if (value < 0 && bw > 64)
{
tmp = btorsim_bv_not (res);
free (res);
res = tmp;
}
res->bits[res->len - 1] = (BTORSIM_BV_TYPE) value;
if (res->width > 32)
res->bits[res->len - 2] = (BTORSIM_BV_TYPE) (value >> BTORSIM_BV_TYPE_BW);
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_const (const char *str, uint32_t bw)
{
assert (strlen (str) <= bw);
uint32_t i, j, bit;
BtorSimBitVector *res;
res = btorsim_bv_new (bw);
for (i = 0; i < bw; i++)
{
j = bw - 1 - i;
assert (str[j] == '0' || str[j] == '1');
bit = str[j] == '0' ? 0 : 1;
btorsim_bv_set_bit (res, i, bit);
}
return res;
}
#ifndef NDEBUG
static int32_t
is_bin_str (const char *c)
{
const char *p;
char ch;
assert (c != NULL);
for (p = c; (ch = *p); p++)
if (ch != '0' && ch != '1') return 0;
return 1;
}
#endif
static const char *
strip_zeroes (const char *a)
{
assert (a);
while (*a == '0') a++;
return a;
}
static char *
mult_unbounded_bin_str (const char *a, const char *b)
{
assert (a);
assert (b);
assert (is_bin_str (a));
assert (is_bin_str (b));
char *res, *r, c, x, y, s, m;
uint32_t alen, blen, rlen, i;
const char *p;
a = strip_zeroes (a);
if (!*a) return btorsim_strdup ("");
if (a[0] == '1' && !a[1]) return btorsim_strdup (b);
b = strip_zeroes (b);
if (!*b) return btorsim_strdup ("");
if (b[0] == '1' && !b[1]) return btorsim_strdup (a);
alen = strlen (a);
blen = strlen (b);
rlen = alen + blen;
BTOR2_NEWN (res, rlen + 1);
res[rlen] = 0;
for (r = res; r < res + blen; r++) *r = '0';
for (p = a; p < a + alen; p++) *r++ = *p;
assert (r == res + rlen);
for (i = 0; i < alen; i++)
{
m = res[rlen - 1];
c = '0';
if (m == '1')
{
p = b + blen;
r = res + blen;
while (res < r && b < p)
{
assert (b < p);
x = *--p;
y = *--r;
s = x ^ y ^ c;
c = (x & y) | (x & c) | (y & c);
*r = s;
}
}
memmove (res + 1, res, rlen - 1);
res[0] = c;
}
return res;
}
static char *
add_unbounded_bin_str (const char *a, const char *b)
{
assert (a);
assert (b);
assert (is_bin_str (a));
assert (is_bin_str (b));
char *res, *r, c, x, y, s, *tmp;
uint32_t alen, blen, rlen;
const char *p, *q;
a = strip_zeroes (a);
b = strip_zeroes (b);
if (!*a) return btorsim_strdup (b);
if (!*b) return btorsim_strdup (a);
alen = strlen (a);
blen = strlen (b);
rlen = (alen < blen) ? blen : alen;
rlen++;
BTOR2_NEWN (res, rlen + 1);
p = a + alen;
q = b + blen;
c = '0';
r = res + rlen;
*r = 0;
while (res < r)
{
x = (a < p) ? *--p : '0';
y = (b < q) ? *--q : '0';
s = x ^ y ^ c;
c = (x & y) | (x & c) | (y & c);
*--r = s;
}
p = strip_zeroes (res);
if ((p != res))
{
tmp = btorsim_strdup (p);
if (!tmp)
{
free (res);
return 0;
}
free (res);
res = tmp;
}
return res;
}
static const char *digit2const_table[10] = {
"",
"1",
"10",
"11",
"100",
"101",
"110",
"111",
"1000",
"1001",
};
static const char *
digit2const (char ch)
{
assert ('0' <= ch);
assert (ch <= '9');
return digit2const_table[ch - '0'];
}
static char *
dec_to_bin_str (const char *str, uint32_t len)
{
assert (str);
const char *end, *p;
char *res, *tmp;
res = btorsim_strdup ("");
if (!res) return 0;
end = str + len;
for (p = str; p < end; p++)
{
tmp = mult_unbounded_bin_str (res, "1010");
if (!tmp)
{
free (res);
return 0;
}
free (res);
res = tmp;
tmp = add_unbounded_bin_str (res, digit2const (*p));
if (!tmp)
{
free (res);
return 0;
}
free (res);
res = tmp;
}
assert (strip_zeroes (res) == res);
if (strlen (res)) return res;
free (res);
return btorsim_strdup ("0");
}
#ifndef NDEBUG
static int32_t
check_constd (const char *str, uint32_t width)
{
assert (str);
assert (width);
int32_t is_neg, is_min_val = 0, res;
char *bits;
size_t size_bits, len;
is_neg = (str[0] == '-');
len = is_neg ? strlen (str) - 1 : strlen (str);
bits = dec_to_bin_str (is_neg ? str + 1 : str, len);
size_bits = strlen (bits);
if (is_neg)
{
is_min_val = (bits[0] == '1');
for (size_t i = 1; is_min_val && i < size_bits; i++)
is_min_val = (bits[i] == '0');
}
res = ((is_neg && !is_min_val) || size_bits <= width)
&& (!is_neg || is_min_val || size_bits + 1 <= width);
free (bits);
return res;
}
#endif
BtorSimBitVector *
btorsim_bv_constd (const char *str, uint32_t bw)
{
assert (check_constd (str, bw));
bool is_neg, is_min_val;
;
BtorSimBitVector *res, *tmp;
char *bits;
uint32_t size_bits, len;
is_min_val = false;
is_neg = (str[0] == '-');
len = is_neg ? strlen (str) - 1 : strlen (str);
bits = dec_to_bin_str (is_neg ? str + 1 : str, len);
size_bits = strlen (bits);
if (is_neg)
{
is_min_val = (bits[0] == '1');
for (size_t i = 1; is_min_val && i < size_bits; i++)
is_min_val = (bits[i] == '0');
}
assert (((is_neg && !is_min_val) || size_bits <= bw)
&& (!is_neg || is_min_val || size_bits + 1 <= bw));
res = btorsim_bv_char_to_bv (bits);
free (bits);
assert (res->width == size_bits);
if (size_bits < bw)
{
tmp = btorsim_bv_uext (res, bw - size_bits);
free (res);
res = tmp;
}
if (is_neg)
{
tmp = btorsim_bv_neg (res);
free (res);
res = tmp;
}
return res;
}
#ifndef NDEBUG
static int32_t
check_consth (const char *consth, uint32_t width)
{
char c;
size_t i, len, req_width;
len = strlen (consth);
req_width = len * 4;
for (i = 0; i < len; i++)
{
c = consth[i];
assert (isxdigit (c));
if (c >= 'A' && c <= 'F') c = tolower (c);
if (c == '0')
{
req_width -= 4;
continue;
}
c = (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 0xa;
assert (c > 0 && c <= 15);
if (c >> 1 == 0)
req_width -= 3;
else if (c >> 2 == 0)
req_width -= 2;
else if (c >> 3 == 0)
req_width -= 1;
break;
}
if (req_width <= width) return 1;
return 0;
}
#endif
static char *
hex_to_bin_str (const char *str)
{
assert (str);
const char *p, *end;
char *tmp, *res, *q;
uint32_t len, blen;
len = strlen (str);
blen = 4 * len;
BTOR2_NEWN (tmp, blen + 1);
q = tmp;
end = str + len;
for (p = str; p < end; p++) switch (*p)
{
case '0':
*q++ = '0';
*q++ = '0';
*q++ = '0';
*q++ = '0';
break;
case '1':
*q++ = '0';
*q++ = '0';
*q++ = '0';
*q++ = '1';
break;
case '2':
*q++ = '0';
*q++ = '0';
*q++ = '1';
*q++ = '0';
break;
case '3':
*q++ = '0';
*q++ = '0';
*q++ = '1';
*q++ = '1';
break;
case '4':
*q++ = '0';
*q++ = '1';
*q++ = '0';
*q++ = '0';
break;
case '5':
*q++ = '0';
*q++ = '1';
*q++ = '0';
*q++ = '1';
break;
case '6':
*q++ = '0';
*q++ = '1';
*q++ = '1';
*q++ = '0';
break;
case '7':
*q++ = '0';
*q++ = '1';
*q++ = '1';
*q++ = '1';
break;
case '8':
*q++ = '1';
*q++ = '0';
*q++ = '0';
*q++ = '0';
break;
case '9':
*q++ = '1';
*q++ = '0';
*q++ = '0';
*q++ = '1';
break;
case 'A':
case 'a':
*q++ = '1';
*q++ = '0';
*q++ = '1';
*q++ = '0';
break;
case 'B':
case 'b':
*q++ = '1';
*q++ = '0';
*q++ = '1';
*q++ = '1';
break;
case 'C':
case 'c':
*q++ = '1';
*q++ = '1';
*q++ = '0';
*q++ = '0';
break;
case 'D':
case 'd':
*q++ = '1';
*q++ = '1';
*q++ = '0';
*q++ = '1';
break;
case 'E':
case 'e':
*q++ = '1';
*q++ = '1';
*q++ = '1';
*q++ = '0';
break;
case 'F':
case 'f':
default:
assert (*p == 'f' || *p == 'F');
*q++ = '1';
*q++ = '1';
*q++ = '1';
*q++ = '1';
break;
}
assert (tmp + blen == q);
*q++ = 0;
res = btorsim_strdup (strip_zeroes (tmp));
free (tmp);
if (strlen (res)) return res;
free (res);
return btorsim_strdup ("0");
}
BtorSimBitVector *
btorsim_bv_consth (const char *str, uint32_t bw)
{
assert (check_consth (str, bw));
BtorSimBitVector *res, *tmp;
char *bits;
uint32_t size_bits;
bits = hex_to_bin_str (str);
size_bits = strlen (bits);
assert (size_bits <= bw);
res = btorsim_bv_char_to_bv (bits);
free (bits);
assert (res->width == size_bits);
if (size_bits < bw)
{
tmp = btorsim_bv_uext (res, bw - size_bits);
free (res);
res = tmp;
}
return res;
}
BtorSimBitVector *
btorsim_bv_copy (const BtorSimBitVector *bv)
{
assert (bv);
BtorSimBitVector *res;
res = btorsim_bv_new (bv->width);
assert (res->width == bv->width);
assert (res->len == bv->len);
memcpy (res->bits, bv->bits, sizeof (*(bv->bits)) * bv->len);
assert (btorsim_bv_compare (res, (BtorSimBitVector *) bv) == 0);
return res;
}
size_t
btorsim_bv_size (const BtorSimBitVector *bv)
{
assert (bv);
return sizeof (BtorSimBitVector) + bv->len * sizeof (BTORSIM_BV_TYPE);
}
int32_t
btorsim_bv_compare (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
uint32_t i;
if (a->width != b->width) return -1;
for (i = 0; i < a->len && a->bits[i] == b->bits[i]; i++)
;
if (i == a->len) return 0;
if (a->bits[i] > b->bits[i]) return 1;
assert (a->bits[i] < b->bits[i]);
return -1;
}
static uint32_t hash_primes[] = {333444569u, 76891121u, 456790003u};
#define NPRIMES ((uint32_t) (sizeof hash_primes / sizeof *hash_primes))
uint32_t
btorsim_bv_hash (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t res = 0, i, j = 0, x, p0, p1;
res = bv->width * hash_primes[j++];
for (i = 0, j = 0; i < bv->len; i++)
{
p0 = hash_primes[j++];
if (j == NPRIMES) j = 0;
p1 = hash_primes[j++];
if (j == NPRIMES) j = 0;
x = bv->bits[i] ^ res;
x = ((x >> 16) ^ x) * p0;
x = ((x >> 16) ^ x) * p1;
res = ((x >> 16) ^ x);
}
return res;
}
void
btorsim_bv_print_without_new_line (const BtorSimBitVector *bv)
{
assert (bv);
int64_t i;
for (i = bv->width - 1; i >= 0; i--)
printf ("%d", btorsim_bv_get_bit (bv, i));
}
void
btorsim_bv_print (const BtorSimBitVector *bv)
{
btorsim_bv_print_without_new_line (bv);
printf ("\n");
}
void
btorsim_bv_print_all (const BtorSimBitVector *bv)
{
assert (bv);
int64_t i;
for (i = BTORSIM_BV_TYPE_BW * bv->len - 1; i >= 0; i--)
{
if ((uint32_t) i == (BTORSIM_BV_TYPE_BW * bv->len + 1 - bv->width))
printf ("|");
if (i > 0
&& (BTORSIM_BV_TYPE_BW * bv->len - 1 - i) % BTORSIM_BV_TYPE_BW == 0)
printf (".");
printf ("%d", btorsim_bv_get_bit (bv, i));
}
printf ("\n");
}
char *
btorsim_bv_to_char (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i, bw, bit;
char *res;
bw = bv->width;
BTOR2_NEWN (res, bw + 1);
for (i = 0; i < bw; i++)
{
bit = btorsim_bv_get_bit (bv, i);
res[bw - 1 - i] = bit ? '1' : '0';
}
res[bw] = '\0';
return res;
}
char *
btorsim_bv_to_hex_char (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t len, i, j, k, tmp;
char *res, ch;
len = (bv->width + 3) / 4;
BTOR2_CNEWN (res, len + 1);
for (i = 0, j = len - 1; i < bv->width;)
{
tmp = btorsim_bv_get_bit (bv, i++);
for (k = 1; i < bv->width && k <= 3; i++, k++)
tmp |= btorsim_bv_get_bit (bv, i) << k;
ch = tmp < 10 ? '0' + tmp : 'a' + (tmp - 10);
res[j--] = ch;
}
return res;
}
static uint32_t
get_first_one_bit_idx (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i;
for (i = bv->width - 1; i < UINT_MAX; i--)
{
if (btorsim_bv_get_bit (bv, i)) break;
if (i == 0) return UINT_MAX;
}
return i;
}
char *
btorsim_bv_to_dec_char (const BtorSimBitVector *bv)
{
assert (bv);
BtorSimBitVector *tmp, *div, *rem, *ten;
uint32_t i;
char *res, ch, *p, *q;
BtorCharStack stack;
if (btorsim_bv_is_zero (bv))
{
BTOR2_CNEWN (res, 2);
res[0] = '0';
return res;
}
BTOR2_INIT_STACK (stack);
if (bv->width < 4)
{
ten = btorsim_bv_uint64_to_bv (10, 4);
tmp = btorsim_bv_uext ((BtorSimBitVector *) bv, 4 - bv->width);
}
else
{
ten = btorsim_bv_uint64_to_bv (10, bv->width);
tmp = btorsim_bv_copy (bv);
}
while (!btorsim_bv_is_zero (tmp))
{
div = btorsim_bv_udiv (tmp, ten);
rem = btorsim_bv_urem (tmp, ten);
ch = 0;
for (i = get_first_one_bit_idx (rem); i < UINT_MAX; i--)
{
ch <<= 1;
if (btorsim_bv_get_bit (rem, i)) ch += 1;
}
assert (ch < 10);
ch += '0';
BTOR2_PUSH_STACK (stack, ch);
free (rem);
free (tmp);
tmp = div;
}
free (tmp);
free (ten);
if (BTOR2_EMPTY_STACK (stack)) BTOR2_PUSH_STACK (stack, '0');
BTOR2_NEWN (res, BTOR2_COUNT_STACK (stack) + 1);
q = res;
p = stack.top;
while (p > stack.start) *q++ = *--p;
assert (res + BTOR2_COUNT_STACK (stack) == q);
*q = 0;
assert ((uint32_t) BTOR2_COUNT_STACK (stack) == strlen (res));
BTOR2_RELEASE_STACK (stack);
return res;
}
uint64_t
btorsim_bv_to_uint64 (const BtorSimBitVector *bv)
{
assert (bv);
assert (bv->width <= sizeof (uint64_t) * 8);
assert (bv->len <= 2);
uint32_t i;
uint64_t res;
res = 0;
for (i = 0; i < bv->len; i++)
res |= ((uint64_t) bv->bits[i]) << (BTORSIM_BV_TYPE_BW * (bv->len - 1 - i));
return res;
}
uint32_t
btorsim_bv_get_bit (const BtorSimBitVector *bv, uint32_t pos)
{
assert (bv);
uint32_t i, j;
i = pos / BTORSIM_BV_TYPE_BW;
j = pos % BTORSIM_BV_TYPE_BW;
return (bv->bits[bv->len - 1 - i] >> j) & 1;
}
void
btorsim_bv_set_bit (BtorSimBitVector *bv, uint32_t pos, uint32_t bit)
{
assert (bv);
assert (bv->len > 0);
assert (bit == 0 || bit == 1);
assert (pos < bv->width);
uint32_t i, j;
i = pos / BTORSIM_BV_TYPE_BW;
j = pos % BTORSIM_BV_TYPE_BW;
assert (i < bv->len);
if (bit)
bv->bits[bv->len - 1 - i] |= (1u << j);
else
bv->bits[bv->len - 1 - i] &= ~(1u << j);
}
void
btorsim_bv_flip_bit (BtorSimBitVector *bv, uint32_t pos)
{
assert (bv);
assert (bv->len > 0);
assert (pos < bv->width);
btorsim_bv_set_bit (bv, pos, btorsim_bv_get_bit (bv, pos) ? 0 : 1);
}
bool
btorsim_bv_is_true (const BtorSimBitVector *bv)
{
assert (bv);
if (bv->width != 1) return 0;
return btorsim_bv_get_bit (bv, 0);
}
bool
btorsim_bv_is_false (const BtorSimBitVector *bv)
{
assert (bv);
if (bv->width != 1) return 0;
return !btorsim_bv_get_bit (bv, 0);
}
bool
btorsim_bv_is_zero (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i;
for (i = 0; i < bv->len; i++)
if (bv->bits[i] != 0) return false;
return true;
}
bool
btorsim_bv_is_ones (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i, n;
for (i = bv->len - 1; i >= 1; i--)
if (bv->bits[i] != UINT_MAX) return false;
if (bv->width == BTORSIM_BV_TYPE_BW)
return bv->bits[0] == UINT_MAX;
else
{
n = BTORSIM_BV_TYPE_BW - bv->width % BTORSIM_BV_TYPE_BW;
assert (n > 0);
if (bv->bits[0] != UINT_MAX >> n) return false;
}
return true;
}
bool
btorsim_bv_is_one (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i;
if (bv->bits[bv->len - 1] != 1) return false;
for (i = 0; i < bv->len - 1; i++)
if (bv->bits[i] != 0) return false;
return true;
}
int64_t
btorsim_bv_power_of_two (const BtorSimBitVector *bv)
{
assert (bv);
int64_t i, j;
uint32_t bit;
bool iszero;
for (i = 0, j = 0, iszero = true; i < bv->width; i++)
{
bit = btorsim_bv_get_bit (bv, i);
if (!bit) continue;
if (bit && !iszero) return -1;
assert (bit && iszero);
j = i;
iszero = false;
}
return j;
}
int32_t
btorsim_bv_small_positive_int (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i;
for (i = 0; i < bv->len - 1; i++)
if (bv->bits[i] != 0) return -1;
if (((int32_t) bv->bits[bv->len - 1]) < 0) return -1;
return bv->bits[bv->len - 1];
}
uint32_t
btorsim_bv_get_num_trailing_zeros (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i, res;
for (i = 0, res = 0; i < bv->width; i++)
{
if (btorsim_bv_get_bit (bv, i)) break;
res += 1;
}
return res;
}
uint32_t
btorsim_bv_get_num_leading_zeros (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i, res;
for (i = bv->width - 1, res = 0; i < UINT_MAX; i--)
{
if (btorsim_bv_get_bit (bv, i)) break;
res += 1;
}
return res;
}
uint32_t
btorsim_bv_get_num_leading_ones (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i, res;
for (i = bv->width - 1, res = 0; i < UINT_MAX; i--)
{
if (!btorsim_bv_get_bit (bv, i)) break;
res += 1;
}
return res;
}
BtorSimBitVector *
btorsim_bv_one (uint32_t bw)
{
assert (bw);
BtorSimBitVector *res = btorsim_bv_new (bw);
btorsim_bv_set_bit (res, 0, 1);
return res;
}
BtorSimBitVector *
btorsim_bv_ones (uint32_t bw)
{
assert (bw);
BtorSimBitVector *res, *tmp;
tmp = btorsim_bv_new (bw);
res = btorsim_bv_not (tmp);
free (tmp);
return res;
}
BtorSimBitVector *
btorsim_bv_neg (const BtorSimBitVector *bv)
{
assert (bv);
BtorSimBitVector *not_bv, *one, *neg_b;
not_bv = btorsim_bv_not (bv);
one = btorsim_bv_one (bv->width);
neg_b = btorsim_bv_add (not_bv, one);
free (not_bv);
free (one);
return neg_b;
}
BtorSimBitVector *
btorsim_bv_not (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i;
BtorSimBitVector *res;
res = btorsim_bv_new (bv->width);
for (i = 0; i < bv->len; i++) res->bits[i] = ~bv->bits[i];
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_inc (const BtorSimBitVector *bv)
{
assert (bv);
BtorSimBitVector *res, *one;
one = btorsim_bv_one (bv->width);
res = btorsim_bv_add (bv, one);
free (one);
return res;
}
BtorSimBitVector *
btorsim_bv_dec (const BtorSimBitVector *bv)
{
assert (bv);
BtorSimBitVector *res, *one, *negone;
one = btorsim_bv_one (bv->width);
negone = btorsim_bv_neg (one);
res = btorsim_bv_add (bv, negone);
free (one);
free (negone);
return res;
}
BtorSimBitVector *
btorsim_bv_redand (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i;
uint32_t bit;
uint32_t mask0;
BtorSimBitVector *res;
res = btorsim_bv_new (1);
assert (rem_bits_zero_dbg (res));
if (bv->width == BTORSIM_BV_TYPE_BW * bv->len)
mask0 = ~(BTORSIM_BV_TYPE) 0;
else
mask0 = BTOR2_MASK_REM_BITS (bv);
bit = (bv->bits[0] == mask0);
for (i = 1; bit && i < bv->len; i++)
if (bv->bits[i] != ~(BTORSIM_BV_TYPE) 0) bit = 0;
btorsim_bv_set_bit (res, 0, bit);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_redor (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i;
uint32_t bit;
BtorSimBitVector *res;
res = btorsim_bv_new (1);
assert (rem_bits_zero_dbg (res));
bit = 0;
for (i = 0; !bit && i < bv->len; i++)
if (bv->bits[i]) bit = 1;
btorsim_bv_set_bit (res, 0, bit);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_redxor (const BtorSimBitVector *bv)
{
assert (bv);
uint32_t i;
uint32_t bit;
BtorSimBitVector *res;
res = btorsim_bv_new (1);
assert (rem_bits_zero_dbg (res));
bit = btorsim_bv_get_bit (bv, 0);
for (i = 1; i < bv->width; i++)
{
bit = bit ^ btorsim_bv_get_bit (bv, i);
}
btorsim_bv_set_bit (res, 0, bit);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_add (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
int64_t i;
uint64_t x, y, sum;
BtorSimBitVector *res;
BTORSIM_BV_TYPE carry;
if (a->width <= 64)
{
x = btorsim_bv_to_uint64 (a);
y = btorsim_bv_to_uint64 (b);
res = btorsim_bv_uint64_to_bv (x + y, a->width);
}
else
{
res = btorsim_bv_new (a->width);
carry = 0;
for (i = a->len - 1; i >= 0; i--)
{
sum = (uint64_t) a->bits[i] + b->bits[i] + carry;
res->bits[i] = (BTORSIM_BV_TYPE) sum;
carry = (BTORSIM_BV_TYPE) (sum >> 32);
}
}
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_sub (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
BtorSimBitVector *negb, *res;
negb = btorsim_bv_neg (b);
res = btorsim_bv_add (a, negb);
free (negb);
return res;
}
BtorSimBitVector *
btorsim_bv_and (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i;
BtorSimBitVector *res;
res = btorsim_bv_new (a->width);
for (i = 0; i < a->len; i++) res->bits[i] = a->bits[i] & b->bits[i];
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_implies (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i;
BtorSimBitVector *res;
res = btorsim_bv_new (a->width);
for (i = 0; i < a->len; i++) res->bits[i] = ~a->bits[i] | b->bits[i];
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_or (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i;
BtorSimBitVector *res;
res = btorsim_bv_new (a->width);
for (i = 0; i < a->len; i++) res->bits[i] = a->bits[i] | b->bits[i];
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_nand (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i;
BtorSimBitVector *res;
res = btorsim_bv_new (a->width);
for (i = 0; i < a->len; i++) res->bits[i] = ~(a->bits[i] & b->bits[i]);
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_nor (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i;
BtorSimBitVector *res;
res = btorsim_bv_new (a->width);
for (i = 0; i < a->len; i++) res->bits[i] = ~(a->bits[i] | b->bits[i]);
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_xnor (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i;
BtorSimBitVector *res;
res = btorsim_bv_new (a->width);
for (i = 0; i < a->len; i++) res->bits[i] = a->bits[i] ^ ~b->bits[i];
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_xor (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i;
BtorSimBitVector *res;
res = btorsim_bv_new (a->width);
for (i = 0; i < a->len; i++) res->bits[i] = a->bits[i] ^ b->bits[i];
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_eq (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i, bit;
BtorSimBitVector *res;
res = btorsim_bv_new (1);
bit = 1;
for (i = 0; i < a->len; i++)
{
if (a->bits[i] != b->bits[i])
{
bit = 0;
break;
}
}
btorsim_bv_set_bit (res, 0, bit);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_neq (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i, bit;
BtorSimBitVector *res;
res = btorsim_bv_new (1);
bit = 1;
for (i = 0; i < a->len; i++)
{
if (a->bits[i] != b->bits[i])
{
bit = 0;
break;
}
}
btorsim_bv_set_bit (res, 0, !bit);
assert (rem_bits_zero_dbg (res));
return res;
}
static uint32_t
find_diff_index (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
uint32_t i = 0;
for (i = 0; i < a->len && a->bits[i] == b->bits[i]; i++)
;
return i;
}
BtorSimBitVector *
btorsim_bv_ult (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i, bit;
BtorSimBitVector *res;
res = btorsim_bv_new (1);
bit = 1;
i = find_diff_index (a, b);
if (i == a->len || a->bits[i] >= b->bits[i]) bit = 0;
btorsim_bv_set_bit (res, 0, bit);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_ulte (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i, bit;
BtorSimBitVector *res;
res = btorsim_bv_new (1);
bit = 1;
i = find_diff_index (a, b);
if (i < a->len && a->bits[i] > b->bits[i]) bit = 0;
btorsim_bv_set_bit (res, 0, bit);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_slt (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i, bit, sign_a, sign_b;
BtorSimBitVector *res;
res = btorsim_bv_new (1);
bit = 1;
sign_a = btorsim_bv_get_bit (a, a->width - 1);
sign_b = btorsim_bv_get_bit (b, b->width - 1);
if (sign_a == sign_b)
{
i = find_diff_index (a, b);
if (i == a->len || a->bits[i] >= b->bits[i]) bit = 0;
}
else
{
bit = sign_a && !sign_b;
}
btorsim_bv_set_bit (res, 0, bit);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_slte (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i, bit, sign_a, sign_b;
BtorSimBitVector *res;
res = btorsim_bv_new (1);
bit = 1;
sign_a = btorsim_bv_get_bit (a, a->width - 1);
sign_b = btorsim_bv_get_bit (b, b->width - 1);
if (sign_a == sign_b)
{
i = find_diff_index (a, b);
if (i < a->len && a->bits[i] > b->bits[i]) bit = 0;
}
else
{
bit = sign_a && !sign_b;
}
btorsim_bv_set_bit (res, 0, bit);
assert (rem_bits_zero_dbg (res));
return res;
}
static BtorSimBitVector *
sll_bv (const BtorSimBitVector *a, uint32_t shift)
{
assert (a);
uint32_t skip, i, j, k;
BtorSimBitVector *res;
BTORSIM_BV_TYPE v;
res = btorsim_bv_new (a->width);
if (shift >= a->width) return res;
k = shift % BTORSIM_BV_TYPE_BW;
skip = shift / BTORSIM_BV_TYPE_BW;
v = 0;
for (i = a->len - 1, j = res->len - 1 - skip;; i--, j--)
{
v = (k == 0) ? a->bits[i] : v | (a->bits[i] << k);
res->bits[j] = v;
v = (k == 0) ? a->bits[i] : a->bits[i] >> (BTORSIM_BV_TYPE_BW - k);
if (i == 0 || j == 0) break;
}
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
assert (check_bits_sll_dbg (a, res, shift));
return res;
}
BtorSimBitVector *
btorsim_bv_sll (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint64_t shift;
BtorSimBitVector *res;
if (b->width <= 64)
shift = btorsim_bv_to_uint64 (b);
else
{
if (btorsim_bv_get_num_leading_zeros (b) < (b->width - 64))
return btorsim_bv_new (a->width);
BtorSimBitVector *lower = btorsim_bv_slice (b, 63, 0);
shift = btorsim_bv_to_uint64 (lower);
btorsim_bv_free (lower);
}
res = sll_bv (a, shift);
return res;
}
BtorSimBitVector *
btorsim_bv_srl (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t skip, i, j, k;
uint64_t shift;
BtorSimBitVector *res;
BTORSIM_BV_TYPE v;
res = btorsim_bv_new (a->width);
if (b->width <= 64)
shift = btorsim_bv_to_uint64 (b);
else
{
if (btorsim_bv_get_num_leading_zeros (b) < (b->width - 64)) return res;
BtorSimBitVector *lower = btorsim_bv_slice (b, 63, 0);
shift = btorsim_bv_to_uint64 (lower);
btorsim_bv_free (lower);
}
if (shift >= a->width) return res;
k = shift % BTORSIM_BV_TYPE_BW;
skip = shift / BTORSIM_BV_TYPE_BW;
v = 0;
for (i = 0, j = skip; i < a->len && j < a->len; i++, j++)
{
v = (k == 0) ? a->bits[i] : v | (a->bits[i] >> k);
res->bits[j] = v;
v = (k == 0) ? a->bits[i] : a->bits[i] << (BTORSIM_BV_TYPE_BW - k);
}
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_sra (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
BtorSimBitVector *res, *sign_a, *srl1, *srl2, *not_a;
sign_a = btorsim_bv_slice (a, a->width - 1, a->width - 1);
srl1 = btorsim_bv_srl (a, b);
not_a = btorsim_bv_not (a);
srl2 = btorsim_bv_srl (not_a, b);
res = btorsim_bv_is_true (sign_a) ? btorsim_bv_not (srl2)
: btorsim_bv_copy (srl1);
btorsim_bv_free (sign_a);
btorsim_bv_free (srl1);
btorsim_bv_free (srl2);
btorsim_bv_free (not_a);
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_rol (const BtorSimBitVector *a, const BtorSimBitVector *b) {
BtorSimBitVector *width = btorsim_bv_uint64_to_bv(a->width, a->width);
BtorSimBitVector *rem = btorsim_bv_urem(b, width);
BtorSimBitVector *rev = btorsim_bv_sub(width, rem);
BtorSimBitVector *sll_part = btorsim_bv_sll(a, rem);
BtorSimBitVector *srl_part = btorsim_bv_srl(a, rev);
BtorSimBitVector *res = btorsim_bv_or(sll_part, srl_part);
btorsim_bv_free(width);
btorsim_bv_free(rev);
btorsim_bv_free(sll_part);
btorsim_bv_free(srl_part);
return res;
}
BtorSimBitVector *
btorsim_bv_ror (const BtorSimBitVector *a, const BtorSimBitVector *b) {
BtorSimBitVector *width = btorsim_bv_uint64_to_bv(a->width, a->width);
BtorSimBitVector *rem = btorsim_bv_urem(b, width);
BtorSimBitVector *rev = btorsim_bv_sub(width, rem);
BtorSimBitVector *srl_part = btorsim_bv_srl(a, rem);
BtorSimBitVector *sll_part = btorsim_bv_sll(a, rev);
BtorSimBitVector *res = btorsim_bv_or(srl_part, sll_part);
btorsim_bv_free(width);
btorsim_bv_free(rev);
btorsim_bv_free(srl_part);
btorsim_bv_free(sll_part);
return res;
}
BtorSimBitVector *
btorsim_bv_mul (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
uint32_t i;
uint64_t x, y;
BtorSimBitVector *res, *and, *shift, *add;
if (a->width <= 64)
{
x = btorsim_bv_to_uint64 (a);
y = btorsim_bv_to_uint64 (b);
res = btorsim_bv_uint64_to_bv (x * y, a->width);
}
else
{
res = btorsim_bv_new (a->width);
for (i = 0; i < a->width; i++)
{
if (btorsim_bv_get_bit (b, i))
and = btorsim_bv_copy (a);
else
and = btorsim_bv_new (a->width);
shift = sll_bv (and, i);
add = btorsim_bv_add (res, shift);
free (and);
free (shift);
free (res);
res = add;
}
}
assert (rem_bits_zero_dbg (res));
return res;
}
static void
udiv_urem_bv (const BtorSimBitVector *a,
const BtorSimBitVector *b,
BtorSimBitVector **q,
BtorSimBitVector **r)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
int64_t i;
bool is_true;
uint64_t x, y, z;
BtorSimBitVector *neg_b, *quot, *rem, *ult, *eq, *tmp;
if (a->width <= 64)
{
x = btorsim_bv_to_uint64 (a);
y = btorsim_bv_to_uint64 (b);
if (y == 0)
{
y = x;
x = UINT64_MAX;
}
else
{
z = x / y;
y = x % y;
x = z;
}
quot = btorsim_bv_uint64_to_bv (x, a->width);
rem = btorsim_bv_uint64_to_bv (y, a->width);
}
else
{
neg_b = btorsim_bv_neg (b);
quot = btorsim_bv_new (a->width);
rem = btorsim_bv_new (a->width);
for (i = a->width - 1; i >= 0; i--)
{
tmp = sll_bv (rem, 1);
free (rem);
rem = tmp;
btorsim_bv_set_bit (rem, 0, btorsim_bv_get_bit (a, i));
ult = btorsim_bv_ult (b, rem);
is_true = btorsim_bv_is_true (ult);
free (ult);
if (is_true) goto UDIV_UREM_SUBTRACT;
eq = btorsim_bv_eq (b, rem);
is_true = btorsim_bv_is_true (eq);
free (eq);
if (is_true)
{
UDIV_UREM_SUBTRACT:
tmp = btorsim_bv_add (rem, neg_b);
free (rem);
rem = tmp;
btorsim_bv_set_bit (quot, i, 1);
}
}
free (neg_b);
}
if (q)
*q = quot;
else
free (quot);
if (r)
*r = rem;
else
free (rem);
}
BtorSimBitVector *
btorsim_bv_udiv (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
BtorSimBitVector *res = 0;
udiv_urem_bv (a, b, &res, 0);
assert (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_sdiv (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
BtorSimBitVector *res = 0, *not_a, *not_a_and_b, *sign_a, *sign_b, *xor;
BtorSimBitVector *neg_a, *neg_b, *cond_a, *cond_b, *udiv, *neg_udiv;
if (a->width == 1)
{
not_a = btorsim_bv_not (a);
not_a_and_b = btorsim_bv_and (not_a, b);
res = btorsim_bv_not (not_a_and_b);
btorsim_bv_free (not_a);
btorsim_bv_free (not_a_and_b);
}
else
{
sign_a = btorsim_bv_slice (a, a->width - 1, a->width - 1);
sign_b = btorsim_bv_slice (b, b->width - 1, b->width - 1);
xor = btorsim_bv_xor (sign_a, sign_b);
neg_a = btorsim_bv_neg (a);
neg_b = btorsim_bv_neg (b);
cond_a = btorsim_bv_is_true (sign_a) ? btorsim_bv_copy (neg_a)
: btorsim_bv_copy (a);
cond_b = btorsim_bv_is_true (sign_b) ? btorsim_bv_copy (neg_b)
: btorsim_bv_copy (b);
udiv = btorsim_bv_udiv (cond_a, cond_b);
neg_udiv = btorsim_bv_neg (udiv);
res = btorsim_bv_is_true (xor) ? btorsim_bv_copy (neg_udiv)
: btorsim_bv_copy (udiv);
btorsim_bv_free (sign_a);
btorsim_bv_free (sign_b);
btorsim_bv_free (xor);
btorsim_bv_free (neg_a);
btorsim_bv_free (neg_b);
btorsim_bv_free (cond_a);
btorsim_bv_free (cond_b);
btorsim_bv_free (udiv);
btorsim_bv_free (neg_udiv);
}
assert (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_urem (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
BtorSimBitVector *res = 0;
udiv_urem_bv (a, b, 0, &res);
assert (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_srem (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
BtorSimBitVector *res = 0, *not_b, *sign_a, *sign_b, *neg_a, *neg_b;
BtorSimBitVector *cond_a, *cond_b, *urem, *neg_urem;
if (a->width == 1)
{
not_b = btorsim_bv_not (b);
res = btorsim_bv_and (a, not_b);
btorsim_bv_free (not_b);
}
else
{
sign_a = btorsim_bv_slice (a, a->width - 1, a->width - 1);
sign_b = btorsim_bv_slice (b, b->width - 1, b->width - 1);
neg_a = btorsim_bv_neg (a);
neg_b = btorsim_bv_neg (b);
cond_a = btorsim_bv_is_true (sign_a) ? btorsim_bv_copy (neg_a)
: btorsim_bv_copy (a);
cond_b = btorsim_bv_is_true (sign_b) ? btorsim_bv_copy (neg_b)
: btorsim_bv_copy (b);
urem = btorsim_bv_urem (cond_a, cond_b);
neg_urem = btorsim_bv_neg (urem);
res = btorsim_bv_is_true (sign_a) ? btorsim_bv_copy (neg_urem)
: btorsim_bv_copy (urem);
btorsim_bv_free (sign_a);
btorsim_bv_free (sign_b);
btorsim_bv_free (neg_a);
btorsim_bv_free (neg_b);
btorsim_bv_free (cond_a);
btorsim_bv_free (cond_b);
btorsim_bv_free (urem);
btorsim_bv_free (neg_urem);
}
assert (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_smod (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
BtorSimBitVector *res = 0, *not_b, *sign_a, *sign_b, *neg_a, *neg_b, *add;
BtorSimBitVector *cond_a, *cond_b, *urem, *neg_urem;
bool a_positive, b_positive;
if (a->width == 1)
{
not_b = btorsim_bv_not (b);
res = btorsim_bv_and (a, not_b);
btorsim_bv_free (not_b);
}
else
{
sign_a = btorsim_bv_slice (a, a->width - 1, a->width - 1);
sign_b = btorsim_bv_slice (b, b->width - 1, b->width - 1);
a_positive = !btorsim_bv_is_true (sign_a);
b_positive = !btorsim_bv_is_true (sign_b);
neg_a = btorsim_bv_neg (a);
neg_b = btorsim_bv_neg (b);
cond_a = a_positive ? btorsim_bv_copy (a)
: btorsim_bv_copy (neg_a);
cond_b = b_positive ? btorsim_bv_copy (b)
: btorsim_bv_copy (neg_b);
urem = btorsim_bv_urem (cond_a, cond_b);
add = btorsim_bv_is_zero(urem) ? btorsim_bv_zero(b->width)
: btorsim_bv_copy(b);
neg_urem = btorsim_bv_neg (urem);
res = a_positive && b_positive ? btorsim_bv_copy(urem)
: !a_positive && b_positive ? btorsim_bv_add(neg_urem, add)
: a_positive && !b_positive ? btorsim_bv_add(urem, add)
: btorsim_bv_copy(neg_urem);
btorsim_bv_free (sign_a);
btorsim_bv_free (sign_b);
btorsim_bv_free (neg_a);
btorsim_bv_free (neg_b);
btorsim_bv_free (cond_a);
btorsim_bv_free (cond_b);
btorsim_bv_free (urem);
btorsim_bv_free (add);
btorsim_bv_free (neg_urem);
}
assert (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_concat (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
int64_t i, j, k;
BTORSIM_BV_TYPE v;
BtorSimBitVector *res;
res = btorsim_bv_new (a->width + b->width);
j = res->len - 1;
for (i = b->len - 1; i >= 0; i--) res->bits[j--] = b->bits[i];
k = b->width % BTORSIM_BV_TYPE_BW;
if (k == 0)
{
assert (j >= 0);
for (i = a->len - 1; i >= 0; i--) res->bits[j--] = a->bits[i];
}
else
{
j += 1;
assert (res->bits[j] >> k == 0);
v = res->bits[j];
for (i = a->len - 1; i >= 0; i--)
{
v = v | (a->bits[i] << k);
assert (j >= 0);
res->bits[j--] = v;
v = a->bits[i] >> (BTORSIM_BV_TYPE_BW - k);
}
assert (j <= 0);
if (j == 0) res->bits[j] = v;
}
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_slice (const BtorSimBitVector *bv, uint32_t upper, uint32_t lower)
{
assert (bv);
uint32_t i, j;
BtorSimBitVector *res;
res = btorsim_bv_new (upper - lower + 1);
for (i = lower, j = 0; i <= upper; i++)
btorsim_bv_set_bit (res, j++, btorsim_bv_get_bit (bv, i));
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_sext (const BtorSimBitVector *bv, uint32_t len)
{
assert (bv);
assert (len > 0);
uint32_t msb;
BtorSimBitVector *res, *tmp;
msb = btorsim_bv_get_bit (bv, bv->width - 1);
tmp = msb ? btorsim_bv_ones (len) : btorsim_bv_zero (len);
res = btorsim_bv_concat (tmp, bv);
btorsim_bv_free (tmp);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_uext (const BtorSimBitVector *bv, uint32_t len)
{
assert (bv);
assert (len > 0);
BtorSimBitVector *res;
res = btorsim_bv_new (bv->width + len);
memcpy (
res->bits + res->len - bv->len, bv->bits, sizeof (*(bv->bits)) * bv->len);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_ite (const BtorSimBitVector *c,
const BtorSimBitVector *t,
const BtorSimBitVector *e)
{
assert (c);
assert (c->len == 1);
assert (t);
assert (t->len > 0);
assert (e);
assert (t->len == e->len);
assert (t->width == e->width);
BtorSimBitVector *res;
BTORSIM_BV_TYPE cc, nn;
uint32_t i;
cc = btorsim_bv_get_bit (c, 0) ? (~(BTORSIM_BV_TYPE) 0) : 0;
nn = ~cc;
res = btorsim_bv_new (t->width);
for (i = 0; i < t->len; i++)
res->bits[i] = (cc & t->bits[i]) | (nn & e->bits[i]);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_flipped_bit (const BtorSimBitVector *bv, uint32_t pos)
{
assert (bv);
assert (bv->len > 0);
assert (pos < bv->width);
BtorSimBitVector *res;
res = btorsim_bv_copy (bv);
btorsim_bv_set_bit (res, pos, btorsim_bv_get_bit (res, pos) ? 0 : 1);
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
BtorSimBitVector *
btorsim_bv_flipped_bit_range (const BtorSimBitVector *bv,
uint32_t upper,
uint32_t lower)
{
assert (lower <= upper);
assert (upper < bv->width);
uint32_t i;
BtorSimBitVector *res;
res = btorsim_bv_copy (bv);
for (i = lower; i <= upper; i++)
btorsim_bv_set_bit (res, i, btorsim_bv_get_bit (res, i) ? 0 : 1);
set_rem_bits_to_zero (res);
assert (rem_bits_zero_dbg (res));
return res;
}
bool
btorsim_bv_is_umulo (const BtorSimBitVector *a, const BtorSimBitVector *b)
{
assert (a);
assert (b);
assert (a->len == b->len);
assert (a->width == b->width);
bool res;
BtorSimBitVector *aext, *bext, *mul, *o;
res = false;
if (a->width > 1)
{
aext = btorsim_bv_uext (a, a->width);
bext = btorsim_bv_uext (b, b->width);
mul = btorsim_bv_mul (aext, bext);
o = btorsim_bv_slice (mul, mul->width - 1, a->width);
if (!btorsim_bv_is_zero (o)) res = true;
free (aext);
free (bext);
free (mul);
free (o);
}
return res;
}