char * btor_decimal_to_const_n (BtorMemMgr * mem, const char *str, int len) { const char *end, *p; char *res, *tmp; assert (mem != NULL); assert (str != NULL); assert (len >= 0); res = btor_strdup (mem, ""); end = str + len; for (p = str; p < end; p++) { tmp = btor_mult_unbounded_const (mem, res, "1010"); /* *10 */ btor_delete_const (mem, res); res = tmp; tmp = btor_add_unbounded_const (mem, res, digit2const (*p)); btor_delete_const (mem, res); res = tmp; } assert (strip_zeroes (res) == res); return res; }
static char * mul_const (BtorMemMgr * mm, const char *a, const char *b) { char *result, *and, *add, *shift; int i, j, len; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const_3vl (a)); assert (is_valid_const_3vl (b)); len = (int) strlen (a); result = btor_int_to_const (mm, 0, len); for (i = len - 1; i >= 0; i--) { BTOR_NEWN (mm, and, len + 1); for (j = 0; j < len; j++) and[j] = BTOR_AND_CONST_3VL (a[j], b[i]); and[len] = '\0'; shift = btor_sll_n_bits_const (mm, and, len - 1 - i); add = add_const (mm, result, shift); btor_delete_const (mm, result); btor_delete_const (mm, and); btor_delete_const (mm, shift); result = add; } return result; }
char * btor_const_to_decimal (BtorMemMgr * mem, const char *c) { char *res, *q, *tmp, *rem, ch; BtorCharStack stack; const char *p; int len; BTOR_INIT_STACK (stack); assert (mem != NULL); assert (c != NULL); assert (is_valid_const (c)); res = btor_copy_const (mem, c); while (*res) { tmp = btor_udiv_unbounded_const (mem, res, "1010", &rem); /* / 10 */ assert ((int) strlen (rem) <= 4); ch = 0; for (p = strip_zeroes (rem); *p; p++) { ch <<= 1; if (*p == '1') ch++; } assert (ch < 10); ch += '0'; BTOR_PUSH_STACK (mem, stack, ch); btor_delete_const (mem, rem); btor_delete_const (mem, res); res = tmp; } btor_delete_const (mem, res); if (BTOR_EMPTY_STACK (stack)) BTOR_PUSH_STACK (mem, stack, '0'); len = BTOR_COUNT_STACK (stack); BTOR_NEWN (mem, res, len + 1); q = res; p = stack.top; while (p > stack.start) *q++ = *--p; assert (res + len == q); *q = 0; assert (len == (int) strlen (res)); BTOR_RELEASE_STACK (mem, stack); return res; }
static char * srl_const (BtorMemMgr * mm, const char *a, const char *b) { char *result, *temp; int i, len; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert ((int) strlen (a) > 1); assert (btor_is_power_of_2_util ((int) strlen (a))); assert (btor_log_2_util ((int) strlen (a)) == (int) strlen (b)); assert (is_valid_const_3vl (a)); assert (is_valid_const (b)); len = (int) strlen (b); if (b[len - 1] == '1') result = btor_srl_n_bits_const (mm, a, 1); else result = btor_copy_const (mm, a); for (i = len - 2; i >= 0; i--) { temp = result; if (b[i] == '1') result = btor_srl_n_bits_const (mm, temp, btor_pow_2_util (len - i - 1)); else result = btor_copy_const (mm, temp); btor_delete_const (mm, temp); } return result; }
static BtorNode * parse_consth (BtorBTORParser * parser, int len) { char * tmp, * extended; BtorNode *res; int ch, clen; if (parse_space (parser)) return 0; assert (BTOR_EMPTY_STACK (parser->constant)); while (!isspace (ch = btor_nextch_btor (parser)) && ch != EOF && ch != ';') { if (!isxdigit (ch)) { (void) btor_perr_btor (parser, "expected hexidecimal digit"); return 0; } BTOR_PUSH_STACK (parser->mem, parser->constant, ch); } btor_savech_btor (parser, ch); clen = BTOR_COUNT_STACK (parser->constant); BTOR_PUSH_STACK (parser->mem, parser->constant, 0); BTOR_RESET_STACK (parser->constant); tmp = btor_hex_to_const_n (parser->mem, parser->constant.start, clen); clen = (int) strlen (tmp); if (clen > len) { (void) btor_perr_btor (parser, "hexadecimal constant '%s' exceeds bit width %d", parser->constant.start, len); btor_freestr (parser->mem, tmp); return 0; } if (clen < len) { extended = btor_uext_const (parser->mem, tmp, len - clen); btor_delete_const (parser->mem, tmp); tmp = extended; } assert (len == (int) strlen (tmp)); res = btor_const_exp (parser->btor, tmp); btor_freestr (parser->mem, tmp); assert (btor_get_exp_len (parser->btor, res) == len); return res; }
char * btor_add_unbounded_const (BtorMemMgr * mm, const char *a, const char *b) { char *res, *r, c, x, y, s, *tmp; int alen, blen, rlen; const char *p, *q; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (is_valid_const (a)); assert (is_valid_const (b)); a = strip_zeroes (a); b = strip_zeroes (b); if (!*a) return btor_strdup (mm, b); if (!*b) return btor_strdup (mm, a); alen = (int) strlen (a); blen = (int) strlen (b); rlen = (alen < blen) ? blen : alen; rlen++; BTOR_NEWN (mm, 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 = btor_copy_const (mm, p); btor_delete_const (mm, res); res = tmp; } return res; }
char * btor_neg_const (BtorMemMgr * mm, const char *a) { char *result, *not_a, *one; int len; assert (mm != NULL); assert (a != NULL); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); len = (int) strlen (a); not_a = btor_not_const (mm, a); one = btor_int_to_const (mm, 1, len); result = btor_add_const (mm, not_a, one); btor_delete_const (mm, not_a); btor_delete_const (mm, one); return result; }
char * btor_urem_const (BtorMemMgr * mm, const char *a, const char *b) { char *quotient, *remainder; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); udiv_urem_const (mm, a, b, "ient, &remainder); btor_delete_const (mm, quotient); return remainder; }
char * btor_urem_const_3vl (BtorMemMgr * mm, const char *a, const char *b) { int i, len, skip_a, skip_b; char *quotient, *remainder; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const_3vl (a)); assert (is_valid_const_3vl (b)); udiv_urem_const (mm, a, b, "ient, &remainder); btor_delete_const (mm, quotient); /* optimization: b != 0 => a urem b <= a /\ a urem b <= b, * this optimization is necessary, as the urem circuit * does not propagate the known bits well */ skip_a = 0; skip_b = 0; if (is_unequal_zero_3vl(mm, b) == '1') { len = (int) strlen (a); for (i = 0; i < len; i++) { if (!skip_a && a[i] == '0') remainder[i] = '0'; else if (!skip_b) skip_a = 1; else break; if (!skip_b && b[i] == '0') remainder[i] = '0'; else if (!skip_a) skip_b = 1; else break; } } return remainder; }
char * btor_srl_const_3vl (BtorMemMgr * mm, const char *a, const char *b) { int min_shifts, max_shifts, len, found, i, j; char *result, *temp, cur; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert ((int) strlen (a) > 1); assert (btor_is_power_of_2_util ((int) strlen (a))); assert (btor_log_2_util ((int) strlen (a)) == (int) strlen (b)); assert (is_valid_const_3vl (a)); assert (is_valid_const_3vl (b)); if (is_valid_const (b)) result = srl_const (mm, a, b); else { len = (int) strlen (a); temp = btor_x_const_3vl (mm, len); compute_min_max_num_shifts (mm, b, &min_shifts, &max_shifts); result = btor_srl_n_bits_const (mm, temp, min_shifts); for (i = len - 1; i >= 0; i--) { cur = a[i]; if (cur != 'x') { found = 0; for (j = i - 1; j >= 0; j--) { if (a[j] == cur) found++; else break; } if (found >= max_shifts) result[i] = cur; } } btor_delete_const (mm, temp); } return result; }
char * btor_sub_const (BtorMemMgr * mm, const char *a, const char *b) { char *result, *neg_b; int len; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); len = (int) strlen (a); neg_b = btor_neg_const (mm, b); result = btor_add_const (mm, a, neg_b); btor_delete_const (mm, neg_b); return result; }
char * btor_udiv_const_3vl (BtorMemMgr * mm, const char *a, const char *b) { #if 0 int i, len; #endif char *quotient, *remainder; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const_3vl (a)); assert (is_valid_const_3vl (b)); udiv_urem_const (mm, a, b, "ient, &remainder); btor_delete_const (mm, remainder); /* it seems like this optimization is not necessary here, * as the division circuit propagates the known bits * quite well */ #if 0 /* optimization: b != 0 => a udiv b <= a */ if (is_unequal_zero_3vl(mm, b) == '1') { len = (int) strlen (a); for (i = 0; i < len; i++) { if (a[i] == '0') quotient[i] = '0'; else break; } } #endif return quotient; }
static BtorNode * parse_constd (BtorBTORParser * parser, int len) { char ch, *tmp, * extended; BtorNode *res; int clen; if (parse_space (parser)) return 0; assert (BTOR_EMPTY_STACK (parser->constant)); ch = btor_nextch_btor (parser); if (!isdigit (ch)) { (void) btor_perr_btor (parser, "expected digit"); return 0; } BTOR_PUSH_STACK (parser->mem, parser->constant, ch); if (ch == '0') { ch = btor_nextch_btor (parser); if (isdigit (ch)) { (void) btor_perr_btor (parser, "digit after '0'"); return 0; } tmp = btor_strdup (parser->mem, ""); } else { while (isdigit (ch = btor_nextch_btor (parser))) BTOR_PUSH_STACK (parser->mem, parser->constant, ch); clen = BTOR_COUNT_STACK (parser->constant); tmp = btor_decimal_to_const_n (parser->mem, parser->constant.start, clen); } BTOR_PUSH_STACK (parser->mem, parser->constant, 0); BTOR_RESET_STACK (parser->constant); btor_savech_btor (parser, ch); clen = (int) strlen (tmp); if (clen > len) { (void) btor_perr_btor (parser, "decimal constant '%s' exceeds bit width %d", parser->constant.start, len); btor_freestr (parser->mem, tmp); return 0; } if (clen < len) { extended = btor_uext_const (parser->mem, tmp, len - clen); btor_delete_const (parser->mem, tmp); tmp = extended; } assert (len == (int) strlen (tmp)); res = btor_const_exp (parser->btor, tmp); btor_delete_const (parser->mem, tmp); assert (btor_get_exp_len (parser->btor, res) == len); return res; }
char * btor_inverse_const (BtorMemMgr * mm, const char *c) { char *a, *b, *y, *ly, *r, *q, *yq, *res, *ty; int len = strlen (c); assert (mm != NULL); assert (c != NULL); assert (len > 0); assert (c[len - 1] == '1'); /* odd */ assert (is_valid_const (c)); BTOR_NEWN (mm, a, len + 2); a[0] = '1'; memset (a + 1, '0', len); a[len + 1] = 0; BTOR_NEWN (mm, b, len + 2); b[0] = '0'; memcpy (b + 1, c, len); b[len + 1] = 0; y = btor_unsigned_to_const (mm, 1, len + 1); ly = btor_unsigned_to_const (mm, 0, len + 1); while (!btor_is_zero_const (b)) { udiv_urem_const (mm, a, b, &q, &r); btor_delete_const (mm, a); a = b; b = r; ty = y; yq = btor_mul_const (mm, y, q); btor_delete_const (mm, q); y = btor_sub_const (mm, ly, yq); btor_delete_const (mm, yq); btor_delete_const (mm, ly); ly = ty; } res = btor_slice_const (mm, ly, len - 1, 0); #ifndef NDEBUG assert (strlen (res) == strlen (c)); ty = btor_mul_const (mm, c, res); assert (btor_is_one_const (ty)); btor_delete_const (mm, ty); #endif btor_delete_const (mm, ly); btor_delete_const (mm, y); btor_delete_const (mm, b); btor_delete_const (mm, a); return res; }
char * btor_udiv_unbounded_const (BtorMemMgr * mem, const char *dividend, const char *divisor, char **rem_ptr) { char *quotient, *rest, *extended_divisor, *tmp; int delta, plen, qlen; const char *p, *q; assert (mem != NULL); assert (dividend != NULL); assert (divisor != NULL); assert (is_valid_const (dividend)); assert (is_valid_const (divisor)); dividend = strip_zeroes (dividend); divisor = strip_zeroes (divisor); for (p = dividend; *p && *p == '0'; p++) ; for (q = divisor; *q && *q == '0'; q++) ; assert (*q); /* in any case even if 'dividend == 0' */ if (!*p || btor_cmp_const (p, q) < 0) { if (rem_ptr) *rem_ptr = btor_strdup (mem, p); /* copy divident */ return btor_strdup (mem, ""); } plen = (int) strlen (p); qlen = (int) strlen (q); delta = plen - qlen; assert (delta >= 0); BTOR_NEWN (mem, extended_divisor, plen + 1); memset (extended_divisor, '0', delta); strcpy (extended_divisor + delta, divisor); udiv_urem_const (mem, dividend, extended_divisor, "ient, &rest); btor_delete_const (mem, extended_divisor); tmp = btor_strdup (mem, strip_zeroes (quotient)); btor_delete_const (mem, quotient); quotient = tmp; tmp = btor_strdup (mem, strip_zeroes (rest)); btor_delete_const (mem, rest); rest = tmp; assert (btor_cmp_const (rest, divisor) < 0); #ifndef NDEBUG { char *tmp1 = btor_mult_unbounded_const (mem, quotient, divisor); char *tmp2 = btor_add_unbounded_const (mem, tmp1, rest); assert (!btor_cmp_const (dividend, tmp2)); btor_freestr (mem, tmp1); btor_freestr (mem, tmp2); } #endif if (rem_ptr) *rem_ptr = rest; else btor_delete_const (mem, rest); return quotient; }