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; }
static void dump_const_value_aux_smt (BtorSMTDumpContext * sdc, char * bits) { assert (sdc); assert (bits); int base; FILE *file; char *val; const char *fmt; BtorPtrHashBucket *b; base = sdc->btor->options.output_number_format.val; file = sdc->file; /* converting consts to decimal/hex is costly. we now always dump the value of * constants. in order to avoid computing the same value again we cache * the result of the first computation and print the cached value in * subsequent calls. */ if (base == BTOR_OUTPUT_BASE_DEC) { if ((b = btor_find_in_ptr_hash_table (sdc->const_cache, bits))) { val = b->data.asStr; assert (val); } else { val = btor_const_to_decimal (sdc->btor->mm, bits); btor_insert_in_ptr_hash_table (sdc->const_cache, btor_strdup (sdc->btor->mm, bits))->data.asStr = val; } fmt = "(_ bv%s %d)"; fprintf (file, fmt, val, strlen (bits)); } else if (base == BTOR_OUTPUT_BASE_HEX && strlen (bits) % 4 == 0) { if ((b = btor_find_in_ptr_hash_table (sdc->const_cache, bits))) { val = b->data.asStr; assert (val); } else { val = btor_const_to_hex (sdc->btor->mm, bits); btor_insert_in_ptr_hash_table (sdc->const_cache, btor_strdup (sdc->btor->mm, bits))->data.asStr = val; } fprintf (file, "#x%s", val); } else btor_dump_const_value_smt (sdc->btor, bits, base, file); }
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; }
char * btor_copy_const (BtorMemMgr * mm, const char *c) { assert (mm != NULL); assert (c != NULL); assert (is_valid_const_3vl (c)); return btor_strdup (mm, c); }
char * btor_const_to_hex (BtorMemMgr * mem, const char *c) { int clen, rlen, i, j, tmp; char *res, ch; assert (mem != NULL); assert (c != NULL); assert (is_valid_const (c)); clen = (int) strlen (c); rlen = (clen + 3) / 4; if (rlen) { BTOR_NEWN (mem, res, rlen + 1); i = clen - 1; j = rlen; res[j--] = 0; while (i >= 0) { tmp = (c[i--] == '1'); if (i >= 0) { tmp |= (c[i--] == '1') << 1; if (i >= 0) { tmp |= (c[i--] == '1') << 2; if (i >= 0) tmp |= (c[i--] == '1') << 3; } } if (tmp < 10) ch = '0' + tmp; else ch = 'a' + (tmp - 10); res[j--] = ch; } } else res = btor_strdup (mem, "0"); return res; }
static char * btor_srl_n_bits_const (BtorMemMgr * mm, const char *a, int n) { char *result; int len, i; assert (mm != NULL); assert (a != NULL); assert (is_valid_const_3vl (a)); assert (n >= 0); assert (n < (int) strlen (a)); len = (int) strlen (a); if (len == 0) return btor_strdup (mm, a); BTOR_NEWN (mm, result, len + 1); for (i = 0; i < n; i++) result[i] = '0'; for (i = n; i < len; i++) result[i] = a[i - n]; result[len] = '\0'; return result; }
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_sub_unbounded_const (BtorMemMgr * mem, const char *a, const char *b) { char *res, *tmp, *r, c, x, y, s; int alen, blen, rlen; const char *p, *q; assert (mem != NULL); assert (a != NULL); assert (b != NULL); assert (is_valid_const (a)); assert (is_valid_const (b)); assert (btor_cmp_const (b, a) <= 0); a = strip_zeroes (a); b = strip_zeroes (b); if (!*b) return btor_strdup (mem, a); alen = (int) strlen (a); blen = (int) strlen (b); assert (alen >= blen); rlen = alen; BTOR_NEWN (mem, res, rlen + 1); p = a + alen; q = b + blen; c = '0'; r = res + rlen; *r = 0; while (res < r) { assert (a < p); x = *--p; y = (b < q) ? *--q : '0'; s = x ^ y ^ c; c = ((1 ^ x) & c) | ((1 ^ x) & y) | (y & c); *--r = s; } assert (c == '0'); #ifndef NDEBUG { tmp = btor_add_unbounded_const (mem, res, b); assert (!btor_cmp_const (tmp, a)); btor_freestr (mem, tmp); } #endif tmp = btor_strdup (mem, strip_zeroes (res)); btor_freestr (mem, res); res = tmp; return res; }
char * btor_mult_unbounded_const (BtorMemMgr * mm, const char *a, const char *b) { char *res, *r, c, x, y, s, m; int alen, blen, rlen, i; const char *p; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (is_valid_const (a)); assert (is_valid_const (b)); a = strip_zeroes (a); if (!*a) return btor_strdup (mm, ""); if (a[0] == '1' && !a[1]) return btor_strdup (mm, b); b = strip_zeroes (b); if (!*b) return btor_strdup (mm, ""); if (b[0] == '1' && !b[1]) return btor_strdup (mm, a); alen = (int) strlen (a); blen = (int) strlen (b); rlen = alen + blen; BTOR_NEWN (mm, 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) { 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; }
char * btor_hex_to_const_n (BtorMemMgr * mem, const char *str, int hlen) { const char *p, *end; char *tmp, *res, *q; int len; assert (mem != NULL); assert (str != NULL); assert (hlen >= 0); len = 4 * hlen; BTOR_NEWN (mem, tmp, len + 1); q = tmp; end = str + hlen; 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 + len == q); *q++ = 0; res = btor_strdup (mem, strip_zeroes (tmp)); btor_freestr (mem, tmp); 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; }