static void bdivmod(void) { struct number *a, *b, *rdiv, *rmod; BN_CTX *ctx; u_int scale; a = pop_number(); if (a == NULL) { return; } b = pop_number(); if (b == NULL) { push_number(a); return; } rdiv = new_number(); rmod = new_number(); rdiv->scale = bmachine.scale; rmod->scale = max(b->scale, a->scale + bmachine.scale); scale = max(a->scale, b->scale); if (BN_is_zero(a->number)) warnx("divide by zero"); else { normalize(a, scale); normalize(b, scale + bmachine.scale); ctx = BN_CTX_new(); bn_checkp(ctx); bn_check(BN_div(rdiv->number, rmod->number, b->number, a->number, ctx)); BN_CTX_free(ctx); } push_number(rdiv); push_number(rmod); free_number(a); free_number(b); }
struct number * readnumber(struct source *src, u_int base) { struct number *n; int ch; bool sign = false; bool dot = false; BN_ULONG v; u_int i; n = new_number(); bn_check(BN_zero(n->number)); while ((ch = (*src->vtable->readchar)(src)) != EOF) { if ('0' <= ch && ch <= '9') v = ch - '0'; else if ('A' <= ch && ch <= 'F') v = ch - 'A' + 10; else if (ch == '_') { sign = true; continue; } else if (ch == '.') { if (dot) break; dot = true; continue; } else { (*src->vtable->unreadchar)(src); break; } if (dot) n->scale++; bn_check(BN_mul_word(n->number, base)); #if 0 /* work around a bug in BN_add_word: 0 += 0 is buggy.... */ if (v > 0) #endif bn_check(BN_add_word(n->number, v)); } if (base != 10) { scale_number(n->number, n->scale); for (i = 0; i < n->scale; i++) (void)BN_div_word(n->number, base); } if (sign) negate(n); return n; }
static u_int count_digits(const struct number *n) { struct number *int_part, *fract_part; u_int i; if (BN_is_zero(n->number)) return n->scale ? n->scale : 1; int_part = new_number(); fract_part = new_number(); fract_part->scale = n->scale; split_number(n, int_part->number, fract_part->number); i = 0; while (!BN_is_zero(int_part->number)) { BN_div_word(int_part->number, 10); i++; } free_number(int_part); free_number(fract_part); return (i + n->scale); }
static void bsqrt(void) { struct number *n; struct number *r; BIGNUM *x, *y; u_int scale, onecount; BN_CTX *ctx; onecount = 0; n = pop_number(); if (n == NULL) { return; } if (BN_is_zero(n->number)) { r = new_number(); push_number(r); } else if (BN_is_negative(n->number)) warnx("square root of negative number"); else { scale = max(bmachine.scale, n->scale); normalize(n, 2*scale); x = BN_dup(n->number); bn_checkp(x); bn_check(BN_rshift(x, x, BN_num_bits(x)/2)); y = BN_new(); bn_checkp(y); ctx = BN_CTX_new(); bn_checkp(ctx); for (;;) { bn_checkp(BN_copy(y, x)); bn_check(BN_div(x, NULL, n->number, x, ctx)); bn_check(BN_add(x, x, y)); bn_check(BN_rshift1(x, x)); if (bsqrt_stop(x, y, &onecount)) break; } r = bmalloc(sizeof(*r)); r->scale = scale; r->number = y; BN_free(x); BN_CTX_free(ctx); push_number(r); } free_number(n); }
static void load(void) { int idx; struct value *v, copy; struct number *n; idx = readreg(); if (idx >= 0) { v = stack_tos(&bmachine.reg[idx]); if (v == NULL) { n = new_number(); bn_check(BN_zero(n->number)); push_number(n); } else push(stack_dup_value(v, ©)); } }
static void lesseq_numbers(void) { struct number *a, *b, *r; a = pop_number(); if (a == NULL) return; b = pop_number(); if (b == NULL) { push_number(a); return; } r = new_number(); bn_check(BN_set_word(r->number, compare_numbers(BCODE_NOT_GREATER, a, b) ? 1 : 0)); push_number(r); }
static void equal_numbers(void) { struct number *a, *b, *r; a = pop_number(); if (a == NULL) { return; } b = pop_number(); if (b == NULL) { push_number(a); return; } r = new_number(); bn_check(BN_set_word(r->number, compare_numbers(BCODE_EQUAL, a, b) ? 1 : 0)); push_number(r); }
static int cgc_assign_result(interp_t *interp, expr_t *expr) { char tmp[20]; if (expr->op == OP_FIELD || expr->op == OP_FIELD_VAR) { int num; if (expr->op == OP_FIELD) num = expr->e_cint.value; else { if (!get_number(interp, expr->e_var.name, &num)) return 0; } if (interp->result.type == VAR_NUMBER) { to_string_buf(interp->result.v_number.value, tmp); return cgc_set_field(interp, num, tmp); } else if (interp->result.type == VAR_STRING) { return cgc_set_field(interp, num, interp->result.v_string.value); } return 0; } else if (expr->op == OP_VAR) { var_t *var = NULL; if (interp->result.type == VAR_STRING) var = new_string(cgc_strdup(interp->result.v_string.value)); else var = new_number(interp->result.v_number.value); if (var == NULL) return 0; return cgc_dict_add(&interp->vars, expr->e_var.name, var); } else { return 0; } }
static void bmul(void) { struct number *a, *b, *r; a = pop_number(); if (a == NULL) return; b = pop_number(); if (b == NULL) { push_number(a); return; } r = new_number(); bmul_number(r, a, b, bmachine.scale); push_number(r); free_number(a); free_number(b); }
int main() { srand(time(NULL)); int num; char oper; do { do { num = rand() % 10000; } while ((num < 1000 || num > 9999) || (isPrime(num) == 'N')); printf("原始數字:%d\n", num); //printf("new_number: %d\n", new_number(num)); printf("密碼:%d\n", password(new_number(num))); printf("是否繼續產生密碼(輸入0程式結束):"); scanf(" %c", &oper); } while (oper != '0'); return 0; }
static void bmul(void) { struct number *a, *b; struct number *r; a = pop_number(); if (a == NULL) { return; } b = pop_number(); if (b == NULL) { push_number(a); return; } r = new_number(); bmul_number(r, a, b); push_number(r); free_number(a); free_number(b); }
static void bmod(void) { struct number *a, *b; struct number *r; u_int scale; BN_CTX *ctx; a = pop_number(); if (a == NULL) { return; } b = pop_number(); if (b == NULL) { push_number(a); return; } r = new_number(); scale = max(a->scale, b->scale); r->scale = max(b->scale, a->scale + bmachine.scale); if (BN_is_zero(a->number)) warnx("remainder by zero"); else { normalize(a, scale); normalize(b, scale + bmachine.scale); ctx = BN_CTX_new(); bn_checkp(ctx); bn_check(BN_mod(r->number, b->number, a->number, ctx)); BN_CTX_free(ctx); } push_number(r); free_number(a); free_number(b); }
static void push_scale(void) { struct number *n; struct value *value; u_int scale = 0; value = pop(); if (value != NULL) { switch (value->type) { case BCODE_NONE: return; case BCODE_NUMBER: scale = value->u.num->scale; break; case BCODE_STRING: break; } stack_free_value(value); n = new_number(); bn_check(BN_set_word(n->number, scale)); push_number(n); } }
void printnumber(FILE *f, const struct number *b, u_int base) { struct number *int_part, *fract_part; int digits; char buf[11]; size_t sz; int i; struct stack stack; char *p; charcount = 0; lastchar = -1; if (BN_is_zero(b->number)) putcharwrap(f, '0'); int_part = new_number(); fract_part = new_number(); fract_part->scale = b->scale; if (base <= 16) digits = 1; else { digits = snprintf(buf, sizeof(buf), "%u", base-1); } split_number(b, int_part->number, fract_part->number); i = 0; stack_init(&stack); while (!BN_is_zero(int_part->number)) { BN_ULONG rem = BN_div_word(int_part->number, base); stack_pushstring(&stack, get_digit(rem, digits, base)); i++; } sz = i; if (BN_cmp(b->number, &zero) < 0) putcharwrap(f, '-'); for (i = 0; i < sz; i++) { p = stack_popstring(&stack); if (base > 16) putcharwrap(f, ' '); printwrap(f, p); free(p); } stack_clear(&stack); if (b->scale > 0) { struct number *num_base; BIGNUM mult, stop; putcharwrap(f, '.'); num_base = new_number(); BN_set_word(num_base->number, base); BN_init(&mult); BN_one(&mult); BN_init(&stop); BN_one(&stop); scale_number(&stop, b->scale); i = 0; while (BN_cmp(&mult, &stop) < 0) { u_long rem; if (i && base > 16) putcharwrap(f, ' '); i = 1; bmul_number(fract_part, fract_part, num_base); split_number(fract_part, int_part->number, NULL); rem = BN_get_word(int_part->number); p = get_digit(rem, digits, base); int_part->scale = 0; normalize(int_part, fract_part->scale); BN_sub(fract_part->number, fract_part->number, int_part->number); printwrap(f, p); free(p); BN_mul_word(&mult, base); } free_number(num_base); BN_free(&mult); BN_free(&stop); } flushwrap(f); free_number(int_part); free_number(fract_part); }
static cell_t *chain_index(secd_t *secd, const cell_t *cell, cell_t *prev) { return new_cons(secd, new_number(secd, cell_index(secd, cell)), prev); }
cell_t *serialize_cell(secd_t *secd, cell_t *cell) { cell_t *opt = SECD_NIL; switch (cell_type(cell)) { case CELL_CONS: { cell_t *cdrc = chain_index(secd, get_cdr(cell), SECD_NIL); opt = chain_index(secd, get_car(cell), cdrc); } break; case CELL_PORT: opt = secd_pserialize(secd, cell); break; case CELL_SYM: opt = new_cons(secd, cell, SECD_NIL); break; case CELL_INT: case CELL_CHAR: opt = new_cons(secd, cell, SECD_NIL); break; case CELL_OP: { cell_t *namec = new_symbol(secd, opcode_table[ cell->as.op ].name); opt = new_cons(secd, namec, SECD_NIL); } break; case CELL_FUNC: opt = new_cons(secd, new_number(secd, (long)cell->as.ptr), SECD_NIL); break; case CELL_ARRMETA: { cell_t *typec = chain_sym(secd, (cell->as.mcons.cells ? "cell" : "byte"), SECD_NIL); cell_t *nextc = chain_index(secd, mcons_next(cell), typec); opt = chain_index(secd, mcons_prev(cell), nextc); } break; case CELL_FRAME: { cell_t *ioc = chain_index(secd, cell->as.frame.io, SECD_NIL); cell_t *nextc = chain_index(secd, cell->as.frame.cons.cdr, ioc); opt = chain_index(secd, cell->as.frame.cons.car, nextc); } break; case CELL_KONT: { cell_t *kctrl = chain_index(secd, cell->as.kont.ctrl, SECD_NIL); cell_t *kenv = chain_index(secd, cell->as.kont.env, kctrl); opt = chain_index(secd, cell->as.kont.stack, kenv); } break; case CELL_FREE: { cell_t *nextc = chain_index(secd, get_cdr(cell), SECD_NIL); opt = chain_index(secd, get_car(cell), nextc); } break; case CELL_REF: opt = chain_index(secd, cell->as.ref, SECD_NIL); break; case CELL_ERROR: opt = chain_string(secd, errmsg(cell), SECD_NIL); break; case CELL_UNDEF: opt = SECD_NIL; break; case CELL_ARRAY: opt = chain_index(secd, arr_val(cell, -1), SECD_NIL); break; case CELL_STR: case CELL_BYTES: opt = chain_index(secd, arr_meta((cell_t *)strmem(cell)), SECD_NIL); break; } opt = new_cons(secd, secd_type_sym(secd, cell), opt); cell_t *refc = new_cons(secd, new_number(secd, cell->nref), opt); return new_cons(secd, new_number(secd, cell - secd->begin), refc); }
static cell_t *read_token(secd_t *secd, secd_parser_t *p) { int tok; cell_t *inp = NULL; switch (tok = p->token) { case '(': ++p->nested; inp = read_list(secd, p); if (p->token != ')') goto error_exit; return inp; case TOK_NUM: return new_number(secd, p->numtok); case TOK_CHAR: return new_char(secd, p->numtok); case TOK_SYM: return new_symbol(secd, p->symtok); case TOK_STR: inp = new_string(secd, strmem(p->strtok)); drop_cell(secd, p->strtok); return inp; case TOK_EOF: return new_symbol(secd, EOF_OBJ); case TOK_QUOTE: case TOK_QQ: case TOK_UQ: case TOK_UQSPL: { const char *formname = special_form_for(tok); assert(formname, "No special form for token=%d\n", tok); inp = sexp_read(secd, p); assert_cell(inp, "sexp_read: reading subexpression failed"); return new_cons(secd, new_symbol(secd, formname), new_cons(secd, inp, SECD_NIL)); } case '#': switch (tok = lexnext(p)) { case '(': { cell_t *tmplist = read_list(secd, p); if (p->token != ')') { free_cell(secd, tmplist); goto error_exit; } inp = list_to_vector(secd, tmplist); free_cell(secd, tmplist); return inp; } case TOK_SYM: { if (p->symtok[0] == '.') { int op = secdop_by_name(p->symtok + 1); if (op < 0) goto error_exit; return new_op(secd, op); } if (str_eq(p->symtok, "u8")) { lexnext(p); inp = read_bytevector(p); if (p->token != ')') goto error_exit; return inp; } } } errorf("Unknown suffix for #\n"); } error_exit: if (inp) free_cell(secd, inp); errorf("read_token: failed\n"); return new_error(secd, SECD_NIL, "read_token: failed on token %1$d '%1$c'", p->token); }
static void bexp(void) { struct number *a, *p; struct number *r; bool neg; u_int rscale; p = pop_number(); if (p == NULL) return; a = pop_number(); if (a == NULL) { push_number(p); return; } if (p->scale != 0) { BIGNUM *i, *f; i = BN_new(); bn_checkp(i); f = BN_new(); bn_checkp(f); split_number(p, i, f); if (!BN_is_zero(f)) warnx("Runtime warning: non-zero fractional part in exponent"); BN_free(i); BN_free(f); } normalize(p, 0); neg = false; if (BN_is_negative(p->number)) { neg = true; negate(p); rscale = bmachine.scale; } else { /* Posix bc says min(a.scale * b, max(a.scale, scale) */ u_long b; u_int m; b = BN_get_word(p->number); m = max(a->scale, bmachine.scale); rscale = a->scale * (u_int)b; if (rscale > m || (a->scale > 0 && (b == ULONG_MAX || b > UINT_MAX))) rscale = m; } if (BN_is_zero(p->number)) { r = new_number(); bn_check(BN_one(r->number)); normalize(r, rscale); } else { u_int ascale, mscale; ascale = a->scale; while (!BN_is_bit_set(p->number, 0)) { ascale *= 2; bmul_number(a, a, a, ascale); bn_check(BN_rshift1(p->number, p->number)); } r = dup_number(a); bn_check(BN_rshift1(p->number, p->number)); mscale = ascale; while (!BN_is_zero(p->number)) { ascale *= 2; bmul_number(a, a, a, ascale); if (BN_is_bit_set(p->number, 0)) { mscale += ascale; bmul_number(r, r, a, mscale); } bn_check(BN_rshift1(p->number, p->number)); } if (neg) { BN_CTX *ctx; BIGNUM *one; one = BN_new(); bn_checkp(one); bn_check(BN_one(one)); ctx = BN_CTX_new(); bn_checkp(ctx); scale_number(one, r->scale + rscale); if (BN_is_zero(r->number)) warnx("divide by zero"); else bn_check(BN_div(r->number, NULL, one, r->number, ctx)); BN_free(one); BN_CTX_free(ctx); r->scale = rscale; } else normalize(r, rscale); } push_number(r); free_number(a); free_number(p); }
static void bexp(void) { struct number *a, *p; struct number *r; bool neg; u_int scale; p = pop_number(); if (p == NULL) { return; } a = pop_number(); if (a == NULL) { push_number(p); return; } if (p->scale != 0) warnx("Runtime warning: non-zero scale in exponent"); normalize(p, 0); neg = false; if (BN_cmp(p->number, &zero) < 0) { neg = true; negate(p); scale = bmachine.scale; } else { /* Posix bc says min(a.scale * b, max(a.scale, scale) */ u_long b; u_int m; b = BN_get_word(p->number); m = max(a->scale, bmachine.scale); scale = a->scale * (u_int)b; if (scale > m || (a->scale > 0 && (b == BN_MASK2 || b > UINT_MAX))) scale = m; } if (BN_is_zero(p->number)) { r = new_number(); bn_check(BN_one(r->number)); normalize(r, scale); } else { while (!BN_is_bit_set(p->number, 0)) { bmul_number(a, a, a); bn_check(BN_rshift1(p->number, p->number)); } r = dup_number(a); normalize(r, scale); bn_check(BN_rshift1(p->number, p->number)); while (!BN_is_zero(p->number)) { bmul_number(a, a, a); if (BN_is_bit_set(p->number, 0)) bmul_number(r, r, a); bn_check(BN_rshift1(p->number, p->number)); } if (neg) { BN_CTX *ctx; BIGNUM *one; one = BN_new(); bn_checkp(one); bn_check(BN_one(one)); ctx = BN_CTX_new(); bn_checkp(ctx); scale_number(one, r->scale + scale); normalize(r, scale); bn_check(BN_div(r->number, NULL, one, r->number, ctx)); BN_free(one); BN_CTX_free(ctx); } else normalize(r, scale); } push_number(r); free_number(a); free_number(p); }
// Parses any expression. struct ParseResult parse(const char *text) { struct ParseResult result; result.err_type = PARSE_SUCCESS; const char *s = text; s += skip_whitespace(s); size_t len; switch (*s) { case '\0': result.err_type = ERR_UNEXPECTED_EOI; break; case '(': s++; result = parse_pair(s); s += result.chars_read; break; case ')': result.err_type = ERR_UNEXPECTED_RPAREN; break; case '.': result.err_type = ERR_INVALID_DOT; break; case '#': len = skip_symbol(s + 1); if (len == 1 && s[1] == 't') { s += 2; result.expr = new_boolean(true); } else if (len == 1 && s[1] == 'f') { s += 2; result.expr = new_boolean(false); } else if (len > 2 && s[1] == '\\') { char c = parse_char_name(s + 2, len - 1); if (c == '\0') { s += 2; result.err_type = ERR_UNKNOWN_CHARACTER; } else { s += 1 + len; result.expr = new_character(c); } } else if (s[1] == '\\' && s[2] && !isspace(s[2])) { result.expr = new_character(s[2]); s += 3; } else { result.err_type = ERR_INVALID_LITERAL; } break; case '\'': s++; result = parse(s); s += result.chars_read; if (result.err_type == PARSE_SUCCESS) { result.expr = new_pair( new_stdmacro(F_QUOTE), new_pair(result.expr, new_null())); } break; case '`': s++; result = parse(s); s += result.chars_read; if (result.err_type == PARSE_SUCCESS) { result.expr = new_pair( new_stdmacro(F_QUASIQUOTE), new_pair(result.expr, new_null())); } break; case ',': s++; enum StandardMacro stdmacro = F_UNQUOTE; if (*s == '@') { s++; stdmacro = F_UNQUOTE_SPLICING; } result = parse(s); s += result.chars_read; if (result.err_type == PARSE_SUCCESS) { result.expr = new_pair( new_stdmacro(stdmacro), new_pair(result.expr, new_null())); } break; case '"': s++; len = skip_string(s); if (!(s[len-1] == '\\' && (len < 2 || s[len-2] == '\\')) && s[len] == '"') { result.expr = parse_string(s, len); } else { result.err_type = ERR_UNEXPECTED_EOI; } s += len; s++; break; default:; len = skip_symbol(s); assert(len > 0); Number number; if (parse_number(s, len, &number)) { result.expr = new_number(number); } else { InternId symbol_id = intern_string_n(s, len); result.expr = new_symbol(symbol_id); } s += len; break; } if (result.err_type == PARSE_SUCCESS) { s += skip_whitespace(s); assert(s > text); } result.chars_read = (size_t)(s - text); return result; }