void btor_dump_const_value_smt (Btor * btor, const char * bits, int base, FILE * file) { assert (btor); assert (bits); assert (base == BTOR_OUTPUT_BASE_BIN || base == BTOR_OUTPUT_BASE_DEC || base == BTOR_OUTPUT_BASE_HEX); char *val; const char *fmt; /* SMT-LIB v1.2 only supports decimal output */ if (base == BTOR_OUTPUT_BASE_DEC) { val = btor_const_to_decimal (btor->mm, bits); fmt = "(_ bv%s %d)"; fprintf (file, fmt, val, strlen (bits)); btor_freestr (btor->mm, val); } else if (base == BTOR_OUTPUT_BASE_HEX && strlen (bits) % 4 == 0) { val = btor_const_to_hex (btor->mm, bits); fprintf (file, "#x%s", val); btor_freestr (btor->mm, val); } else { fprintf (file, "#b%s", bits); } }
static void delete_smt_dump_context (BtorSMTDumpContext * sdc) { BtorHashTableIterator it; btor_delete_ptr_hash_table (sdc->dump); btor_delete_ptr_hash_table (sdc->dumped); btor_delete_ptr_hash_table (sdc->boolean); btor_delete_ptr_hash_table (sdc->stores); btor_delete_ptr_hash_table (sdc->idtab); btor_init_node_hash_table_iterator (&it, sdc->roots); while (btor_has_next_node_hash_table_iterator (&it)) btor_release_exp (sdc->btor, btor_next_node_hash_table_iterator (&it)); btor_delete_ptr_hash_table (sdc->roots); btor_init_hash_table_iterator (&it, sdc->const_cache); while (btor_has_next_hash_table_iterator (&it)) { assert (it.bucket->data.asStr); btor_freestr (sdc->btor->mm, it.bucket->data.asStr); btor_freestr (sdc->btor->mm, (char *) btor_next_hash_table_iterator (&it)); } btor_delete_ptr_hash_table (sdc->const_cache); BTOR_DELETE (sdc->btor->mm, sdc); }
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; }
static void btor_delete_btor_parser (BtorBTORParser * parser) { BtorNode *e; int i; for (i = 0; i < BTOR_COUNT_STACK (parser->exps); i++) if ((e = parser->exps.start[i])) btor_release_exp (parser->btor, parser->exps.start[i]); BTOR_RELEASE_STACK (parser->mem, parser->exps); BTOR_RELEASE_STACK (parser->mem, parser->info); BTOR_RELEASE_STACK (parser->mem, parser->inputs); BTOR_RELEASE_STACK (parser->mem, parser->outputs); BTOR_RELEASE_STACK (parser->mem, parser->regs); BTOR_RELEASE_STACK (parser->mem, parser->nexts); BTOR_RELEASE_STACK (parser->mem, parser->op); BTOR_RELEASE_STACK (parser->mem, parser->constant); BTOR_RELEASE_STACK (parser->mem, parser->symbol); BTOR_DELETEN (parser->mem, parser->parsers, SIZE_PARSERS); BTOR_DELETEN (parser->mem, parser->ops, SIZE_PARSERS); btor_freestr (parser->mem, parser->error); BTOR_DELETE (parser->mem, parser); }
void btor_delete_const (BtorMemMgr * mm, char *c) { assert (mm != NULL); assert (c != NULL); assert (is_valid_const_3vl (c)); btor_freestr (mm, c); }
static void recursively_dump_exp_smt (BtorSMTDumpContext * sdc, BtorNode * exp, int expect_bv, unsigned depth_limit) { assert (sdc); assert (exp); assert (btor_find_in_ptr_hash_table (sdc->dump, BTOR_REAL_ADDR_NODE (exp))); unsigned depth; int pad, i, is_bool, add_space, zero_extend, expect_bool; BtorBitVector *bitsbv; char *bits; const char *op, *fmt; BtorNode *arg, *real_exp; BtorArgsIterator it; BtorNodePtrStack dump, args; BtorIntStack expect_bv_stack, expect_bool_stack, depth_stack; BtorIntStack add_space_stack, zero_extend_stack; BtorPtrHashTable *visited; BtorMemMgr *mm; mm = sdc->btor->mm; visited = btor_new_ptr_hash_table (mm, 0, 0); BTOR_INIT_STACK (args); BTOR_INIT_STACK (dump); BTOR_INIT_STACK (expect_bv_stack); BTOR_INIT_STACK (expect_bool_stack); BTOR_INIT_STACK (add_space_stack); BTOR_INIT_STACK (zero_extend_stack); BTOR_INIT_STACK (depth_stack); PUSH_DUMP_NODE (exp, expect_bv, 0, 0, 0, 0); while (!BTOR_EMPTY_STACK (dump)) { assert (!BTOR_EMPTY_STACK (expect_bv_stack)); assert (!BTOR_EMPTY_STACK (expect_bool_stack)); assert (!BTOR_EMPTY_STACK (add_space_stack)); assert (!BTOR_EMPTY_STACK (zero_extend_stack)); assert (!BTOR_EMPTY_STACK (depth_stack)); depth = BTOR_POP_STACK (depth_stack); exp = BTOR_POP_STACK (dump); expect_bv = BTOR_POP_STACK (expect_bv_stack); expect_bool = BTOR_POP_STACK (expect_bool_stack); add_space = BTOR_POP_STACK (add_space_stack); zero_extend = BTOR_POP_STACK (zero_extend_stack); real_exp = BTOR_REAL_ADDR_NODE (exp); is_bool = is_boolean (sdc, real_exp); assert (!expect_bv || !expect_bool); assert (!expect_bool || !expect_bv); /* open s-expression */ if (!btor_find_in_ptr_hash_table (visited, real_exp)) { if (add_space) fputc (' ', sdc->file); /* wrap node with zero_extend */ if (zero_extend) { fmt = " ((_ zero_extend %d) "; fprintf (sdc->file, fmt, zero_extend); } /* always print constants */ if (BTOR_IS_BV_CONST_NODE (real_exp)) { if (exp == sdc->btor->true_exp && !expect_bv) fputs ("true", sdc->file); else if (exp == BTOR_INVERT_NODE (sdc->btor->true_exp) && !expect_bv) fputs ("false", sdc->file); else if (BTOR_IS_INVERTED_NODE (exp)) { bitsbv = btor_not_bv ( sdc->btor->mm, btor_const_get_bits (real_exp)); bits = btor_bv_to_char_bv (sdc->btor->mm, bitsbv); dump_const_value_aux_smt (sdc, bits); btor_free_bv (sdc->btor->mm, bitsbv); btor_freestr (sdc->btor->mm, bits); } else { bits = btor_bv_to_char_bv ( sdc->btor->mm, btor_const_get_bits (real_exp)); dump_const_value_aux_smt (sdc, bits); btor_freestr (sdc->btor->mm, bits); } /* close zero extend */ if (zero_extend) fputc (')', sdc->file); continue; } /* wrap non-bool node and make it bool */ if (expect_bool && !is_bool) { fputs ("(= ", sdc->file); dump_const_value_aux_smt (sdc, "1"); fputc (' ', sdc->file); } /* wrap node with bvnot/not */ if (BTOR_IS_INVERTED_NODE (exp)) fputs (expect_bv || !is_bool ? "(bvnot " : "(not ", sdc->file); /* wrap bool node and make it a bit vector expression */ if (is_bool && expect_bv) fputs ("(ite ", sdc->file); if (btor_find_in_ptr_hash_table (sdc->dumped, real_exp) || BTOR_IS_LAMBDA_NODE (real_exp) || BTOR_IS_UF_NODE (real_exp)) { #ifndef NDEBUG BtorPtrHashBucket *b; b = btor_find_in_ptr_hash_table (sdc->dump, real_exp); assert (b); /* functions and variables are declared separately */ assert (BTOR_IS_LAMBDA_NODE (real_exp) || BTOR_IS_UF_NODE (real_exp) || BTOR_IS_BV_VAR_NODE (real_exp) || BTOR_IS_PARAM_NODE (real_exp) || b->data.asInt > 1); #endif dump_smt_id (sdc, exp); goto CLOSE_WRAPPER; } if (depth_limit && depth >= depth_limit) { fprintf (sdc->file, "%s_%d", g_kind2smt[real_exp->kind], real_exp->id); goto CLOSE_WRAPPER; } PUSH_DUMP_NODE (exp, expect_bv, expect_bool, 0, zero_extend, depth); btor_insert_in_ptr_hash_table (visited, real_exp); op = ""; switch (real_exp->kind) { case BTOR_SLL_NODE: case BTOR_SRL_NODE: assert (!is_bool); op = real_exp->kind == BTOR_SRL_NODE ? "bvlshr" : "bvshl"; assert (btor_get_exp_width (sdc->btor, real_exp) > 1); pad = btor_get_exp_width (sdc->btor, real_exp) - btor_get_exp_width (sdc->btor, real_exp->e[1]); PUSH_DUMP_NODE (real_exp->e[1], 1, 0, 1, pad, depth + 1); PUSH_DUMP_NODE (real_exp->e[0], 1, 0, 1, 0, depth + 1); break; case BTOR_BCOND_NODE: op = "ite"; PUSH_DUMP_NODE (real_exp->e[2], !is_bool, 0, 1, 0, depth + 1); PUSH_DUMP_NODE (real_exp->e[1], !is_bool, 0, 1, 0, depth + 1); PUSH_DUMP_NODE (real_exp->e[0], 0, 1, 1, 0, depth + 1); break; case BTOR_APPLY_NODE: /* we need the arguments in reversed order */ btor_init_args_iterator (&it, real_exp->e[1]); while (btor_has_next_args_iterator (&it)) { arg = btor_next_args_iterator (&it); BTOR_PUSH_STACK (mm, args, arg); } while (!BTOR_EMPTY_STACK (args)) { arg = BTOR_POP_STACK (args); // TODO (ma): what about bool arguments/indices PUSH_DUMP_NODE (arg, 1, 0, 1, 0, depth + 1); } PUSH_DUMP_NODE (real_exp->e[0], 1, 0, 0, 0, depth + 1); break; #if 0 case BTOR_LAMBDA_NODE: extract_store (sdc, exp, &index, &value, &array); assert (index); assert (value); assert (array); fputs ("(store ", sdc->file); DUMP_EXP_SMT (array); fputc (' ', sdc->file); DUMP_EXP_SMT (index); fputc (' ', sdc->file); DUMP_EXP_SMT (value); fputc (')', sdc->file); break; #endif default: expect_bv = 1; switch (real_exp->kind) { case BTOR_FEQ_NODE: case BTOR_BEQ_NODE: op = "="; expect_bv = 1; break; case BTOR_ULT_NODE: op = "bvult"; expect_bv = 1; break; case BTOR_SLICE_NODE: assert (!is_bool); op = "(_ extract "; break; case BTOR_AND_NODE: op = is_bool ? "and" : "bvand"; expect_bv = !is_bool; break; case BTOR_ADD_NODE: assert (!is_bool); op = "bvadd"; break; case BTOR_MUL_NODE: assert (!is_bool); op = "bvmul"; break; case BTOR_UDIV_NODE: assert (!is_bool); op = "bvudiv"; break; case BTOR_UREM_NODE: assert (!is_bool); op = "bvurem"; break; case BTOR_CONCAT_NODE: assert (!is_bool); op = "concat"; break; default: assert (0); op = "unknown"; } if (BTOR_IS_AND_NODE (real_exp) && is_bool) { assert (BTOR_EMPTY_STACK (args)); get_children (sdc, exp, &args); for (i = 0; i < BTOR_COUNT_STACK (args); i++) { arg = BTOR_PEEK_STACK (args, i); PUSH_DUMP_NODE (arg, expect_bv, 0, 1, 0, depth + 1); } BTOR_RESET_STACK (args); } else for (i = real_exp->arity - 1; i >= 0; i--) PUSH_DUMP_NODE (real_exp->e[i], expect_bv, 0, 1, 0, depth + 1); } /* open s-expression */ assert (op); fprintf (sdc->file, "(%s", op); if (BTOR_IS_SLICE_NODE (real_exp)) { fmt = "%d %d)"; fprintf (sdc->file, fmt, btor_slice_get_upper (real_exp), btor_slice_get_lower (real_exp)); } } /* close s-expression */ else { if (!btor_find_in_ptr_hash_table (sdc->dumped, real_exp)) btor_insert_in_ptr_hash_table (sdc->dumped, real_exp); /* close s-expression */ if (real_exp->arity > 0) fputc (')', sdc->file); CLOSE_WRAPPER: /* close wrappers */ /* wrap boolean expressions in bit vector expression */ if (is_bool && expect_bv && !BTOR_IS_BV_CONST_NODE (real_exp)) { fputc (' ', sdc->file); dump_const_value_aux_smt (sdc, "1"); fputc (' ', sdc->file); dump_const_value_aux_smt (sdc, "0"); fputc (')', sdc->file); } /* close bvnot for non-constants */ if (BTOR_IS_INVERTED_NODE (exp) && !BTOR_IS_BV_CONST_NODE (real_exp)) fputc (')', sdc->file); /* close bool wrapper */ if (expect_bool && !is_boolean (sdc, real_exp)) fputc (')', sdc->file); /* close zero extend wrapper */ if (zero_extend) fputc (')', sdc->file); } } assert (BTOR_EMPTY_STACK (expect_bv_stack)); BTOR_RELEASE_STACK (mm, args); BTOR_RELEASE_STACK (mm, dump); BTOR_RELEASE_STACK (mm, expect_bv_stack); BTOR_RELEASE_STACK (mm, expect_bool_stack); BTOR_RELEASE_STACK (mm, add_space_stack); BTOR_RELEASE_STACK (mm, zero_extend_stack); BTOR_RELEASE_STACK (mm, depth_stack); btor_delete_ptr_hash_table (visited); }
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; }
int main (int argc, char ** argv) { int i, j, verbosity, close_input, close_output, binary, merge; const char * input_name, * output_name; FILE * input_file, * output_file, * file; BtorAIG * aig, * tmp, * merged, ** p; BtorPtrHashTable * back_annotation; const char * parse_error; BtorPtrHashBucket *b; BtorParseResult model; BtorAIGVecMgr * avmgr; BtorAIGPtrStack regs; BtorAIGPtrStack nexts; BtorAIGPtrStack aigs; BtorParser * parser; BtorAIGMgr * amgr; BtorMemMgr * mem; BtorAIGVec * av; Btor * btor; verbosity = 0; close_input = 0; close_output = 0; binary = 0; merge = 0; input_name = "<stdin>"; output_name = "<stdout>"; input_file = stdin; output_file = stdout; for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "-h")) { printf ("usage: synthebor [-h][-v][-m][<input>[<output>]]\n"); exit (0); } else if (!strcmp (argv[i], "-v")) verbosity++; else if (!strcmp (argv[i], "-m")) merge = 1; else if (argv[i][0] == '-') die (1, "invalid command line option '%s'", argv[i]); else if (close_output) die (1, "too many files"); else if (close_input) { if (!strcmp (argv[i], input_name)) die (1, "input and output are the same"); if (!(file = fopen (argv[i], "w"))) die (1, "can not write '%s'", argv[i]); output_file = file; output_name = argv[i]; close_output = 1; } else if (!(file = fopen (argv[i], "r"))) die (1, "can not read '%s'", argv[i]); else { input_file = file; input_name = argv[i]; close_input = 1; } } btor = btor_new_btor (); btor_set_verbosity_btor (btor, verbosity); btor_set_rewrite_level_btor (btor, 1); parser = btor_btor_parser_api ()->init (btor, verbosity); parse_error = btor_btor_parser_api()->parse (parser, input_file, input_name, &model); if (parse_error) die (0, parse_error); if (!model.noutputs) die (1, "no roots in '%s'", input_name); if (model.nregs && merge) die (1, "can not merge registers"); mem = btor->mm; avmgr = btor->avmgr; amgr = btor_get_aig_mgr_aigvec_mgr (avmgr); back_annotation = btor_new_ptr_hash_table (mem, 0, 0); BTOR_INIT_STACK (regs); BTOR_INIT_STACK (nexts); for (i = 0; i < model.nregs; i++) { if (btor_is_array_exp (btor, model.regs[i])) die (1, "can not synthesize memories (yet)"); av = btor_exp_to_aigvec (btor, model.regs[i], back_annotation); for (j = 0; j < av->len; j++) { aig = btor_copy_aig (amgr, av->aigs[j]); BTOR_PUSH_STACK (mem, regs, aig); } btor_release_delete_aigvec (avmgr, av); av = btor_exp_to_aigvec (btor, model.nexts[i], back_annotation); for (j = 0; j < av->len; j++) { aig = btor_copy_aig (amgr, av->aigs[j]); BTOR_PUSH_STACK (mem, nexts, aig); } btor_release_delete_aigvec (avmgr, av); } BTOR_INIT_STACK (aigs); merged = BTOR_AIG_TRUE; for (i = 0; i < model.noutputs; i++) { av = btor_exp_to_aigvec (btor, model.outputs[i], back_annotation); for (j = 0; j < av->len; j++) { aig = av->aigs[j]; if (merge) { tmp = btor_and_aig (amgr, merged, aig); btor_release_aig (amgr, merged); merged = tmp; } else { aig = btor_copy_aig (amgr, aig); BTOR_PUSH_STACK (mem, aigs, aig); } } btor_release_delete_aigvec (avmgr, av); } if (merge) BTOR_PUSH_STACK (mem, aigs, merged); #ifdef BTOR_HAVE_ISATTY if (close_output || !isatty (1)) binary = 1; #endif assert (BTOR_COUNT_STACK (regs) == BTOR_COUNT_STACK (nexts)); btor_dump_aiger (amgr, binary, output_file, BTOR_COUNT_STACK (aigs), aigs.start, BTOR_COUNT_STACK (regs), regs.start, nexts.start, back_annotation); for (p = aigs.start; p < aigs.top; p++) btor_release_aig (amgr, *p); BTOR_RELEASE_STACK (mem, aigs); for (p = regs.start; p < regs.top; p++) btor_release_aig (amgr, *p); BTOR_RELEASE_STACK (mem, regs); for (p = nexts.start; p < nexts.top; p++) btor_release_aig (amgr, *p); BTOR_RELEASE_STACK (mem, nexts); for (b = back_annotation->first; b; b = b->next) btor_freestr (mem, b->data.asStr); btor_delete_ptr_hash_table (back_annotation); btor_btor_parser_api()->reset (parser); btor_delete_btor (btor); if (close_input) fclose (input_file); if (close_output) fclose (output_file); return 0; }
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_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; }