int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) { mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp; int err; if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { return err; } /* initialize, (u1,u2,u3) = (1,0,a) */ mp_set(&u1, 1); if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; } /* initialize, (v1,v2,v3) = (0,1,b) */ mp_set(&v2, 1); if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; } /* loop while v3 != 0 */ while (mp_iszero(&v3) == MP_NO) { /* q = u3/v3 */ if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; } /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; } if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; } if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; } if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; } if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; } if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; } /* (u1,u2,u3) = (v1,v2,v3) */ if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; } /* (v1,v2,v3) = (t1,t2,t3) */ if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; } } /* make sure U3 >= 0 */ if (u3.sign == MP_NEG) { mp_neg(&u1, &u1); mp_neg(&u2, &u2); mp_neg(&u3, &u3); } /* copy result out */ if (U1 != NULL) { mp_exch(U1, &u1); } if (U2 != NULL) { mp_exch(U2, &u2); } if (U3 != NULL) { mp_exch(U3, &u3); } err = MP_OKAY; _ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); return err; }
/* Used with boxing. Gets an integer value, for representations that can * hold one. */ static INTVAL get_int(PARROT_INTERP, STable *st, void *data) { INTVAL ret; mp_int *i = &((P6bigintBody *)data)->i; if (MP_LT == mp_cmp_d(i, 0)) { mp_neg(i, i); ret = mp_get_long(i); mp_neg(i, i); return -ret; } else { return mp_get_long(i); } }
static void two_complement_bitop(mp_int *a, mp_int *b, mp_int *c, int (*mp_bitop)(mp_int *, mp_int *, mp_int *)) { mp_int d; if (SIGN(a) ^ SIGN(b)) { /* exactly one of them is negative, so need to perform * some magic. tommath stores a sign bit, but Perl 6 expects * 2's complement */ mp_init(&d); if (MP_NEG == SIGN(a)) { grow_and_negate(a, USED(b), &d); mp_bitop(&d, b, c); } else { grow_and_negate(b, USED(a), &d); mp_bitop(a, &d, c); } if (DIGIT(c, USED(c) - 1) & ((mp_digit)1<<(mp_digit)(DIGIT_BIT - 1))) { grow_and_negate(c, c->used, &d); mp_copy(&d, c); mp_neg(c, c); } mp_clear(&d); } else { mp_bitop(a, b, c); } }
/* Used with boxing. Sets an integer value, for representations that can hold * one. */ static void set_int(PARROT_INTERP, STable *st, void *data, INTVAL value) { mp_int *i = &((P6bigintBody *)data)->i; if (value >= 0) { mp_set_long(i, value); } else { mp_set_long(i, -value); mp_neg(i, i); } }
extern void TclBNInitBignumFromWideInt( mp_int *a, /* Bignum to initialize */ Tcl_WideInt v) /* Initial value */ { if (v < (Tcl_WideInt)0) { TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)(-v)); mp_neg(a, a); } else { TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)v); } }
/* Converts a possibly-signed digit string into a large binary number. Returns assumed radix, derived from suffix 'h','o',b','.' */ int str2reg(unitptr reg, string digitstr) { unit temp[MAX_UNIT_PRECISION], base[MAX_UNIT_PRECISION]; int c, i; boolean minus = FALSE; short radix; /* base 2-16 */ mp_init(reg, 0); i = string_length(digitstr); if (i == 0) return (10); /* empty string, assume radix 10 */ c = digitstr[i - 1]; /* get last char in string */ switch (c) { /* classify radix select suffix character */ case '.': radix = 10; break; case 'H': case 'h': radix = 16; break; case 'O': case 'o': radix = 8; break; case 'B': /* caution! 'b' is a hex digit! */ case 'b': radix = 2; break; default: radix = 10; break; } mp_init(base, radix); if ((minus = (*digitstr == '-')) != 0) digitstr++; while ((c = *digitstr++) != 0) { if (c == ',') continue; /* allow commas in number */ c = ctox(c); if ((c < 0) || (c >= radix)) break; /* scan terminated by any non-digit */ mp_mult(temp, reg, base); mp_move(reg, temp); mp_init(temp, c); mp_add(reg, temp); } if (minus) mp_neg(reg); return (radix); } /* str2reg */
/* b = ~a */ int mp_com(mp_int * a, mp_int * b) { int res; // -x == ~x + 1 (2's complement), hence ~x == -x - 1 if ((res = mp_neg(a, b)) != MP_OKAY) { return res; } if ((res = mp_sub_d(b, 1, b)) != MP_OKAY) { return res; } return MP_OKAY; }
static void from_num(MVMnum64 d, mp_int *a) { MVMnum64 d_digit = pow(2, DIGIT_BIT); MVMnum64 da = fabs(d); MVMnum64 upper; MVMnum64 lower; MVMnum64 lowest; MVMnum64 rest; int digits = 0; mp_zero(a); while (da > d_digit * d_digit * d_digit) {; da /= d_digit; digits++; } mp_grow(a, digits + 3); /* populate the top 3 digits */ upper = da / (d_digit*d_digit); rest = fmod(da, d_digit*d_digit); lower = rest / d_digit; lowest = fmod(rest,d_digit ); if (upper >= 1) { mp_set_long(a, (unsigned long) upper); mp_mul_2d(a, DIGIT_BIT , a); DIGIT(a, 0) = (mp_digit) lower; mp_mul_2d(a, DIGIT_BIT , a); } else { if (lower >= 1) { mp_set_long(a, (unsigned long) lower); mp_mul_2d(a, DIGIT_BIT , a); a->used = 2; } else { a->used = 1; } } DIGIT(a, 0) = (mp_digit) lowest; /* shift the rest */ mp_mul_2d(a, DIGIT_BIT * digits, a); if (d < 0) mp_neg(a, a); mp_clamp(a); mp_shrink(a); }
/* Stores an int64 in a bigint result body, either as a 32-bit smallint if it * is in range, or a big integer if not. */ static void store_int64_result(MVMP6bigintBody *body, MVMint64 result) { if (MVM_IS_32BIT_INT(result)) { body->u.smallint.flag = MVM_BIGINT_32_FLAG; body->u.smallint.value = (MVMint32)result; } else { mp_int *i = MVM_malloc(sizeof(mp_int)); mp_init(i); if (result >= 0) { MVM_bigint_mp_set_uint64(i, (MVMuint64)result); } else { MVM_bigint_mp_set_uint64(i, (MVMuint64)-result); mp_neg(i, i); } body->u.bigint = i; } }
static void two_complement_bitop(mp_int *a, mp_int *b, mp_int *c, int (*mp_bitop)(mp_int *, mp_int *, mp_int *)) { mp_int d; mp_int e; mp_int *f; mp_int *g; f = a; g = b; if (MP_NEG == SIGN(a)) { mp_init(&d); grow_and_negate(a, USED(b), &d); f = &d; } if (MP_NEG == SIGN(b)) { mp_init(&e); grow_and_negate(b, USED(a), &e); g = &e; } /* f and g now guaranteed to each point to positive bigints containing * a 2s compliment representation of the values in a and b. If either * a or b was negative, the representation is one tomath "digit" longer * than it need be and sign extended. */ mp_bitop(f, g, c); if (f == &d) mp_clear(&d); if (g == &e) mp_clear(&e); /* Use the fact that tomath clamps to detect results that should be * signed. If we created extra tomath "digits" and they resulted in * sign bits of 0, they have been clamped away. If the resulting sign * bits were 1, they remain, and c will have more digits than either of * original operands. Note this only works because we do not * support NOR/NAND/NXOR, and so two zero sign bits can never create 1s. */ if (USED(c) > MAX(USED(a),USED(b))) { int i; for (i = 0; i < USED(c); i++) { DIGIT(c, i) = (~DIGIT(c, i)) & MP_MASK; } mp_add_d(c, 1, c); mp_neg(c, c); } }
/* Forces a bigint, even if we only have a smallint. Takes a parameter that * indicates where to allocate a temporary mp_int if needed. */ static mp_int * force_bigint(const MVMP6bigintBody *body, mp_int **tmp) { if (MVM_BIGINT_IS_BIG(body)) { return body->u.bigint; } else { MVMint32 value = body->u.smallint.value; mp_int *i = MVM_malloc(sizeof(mp_int)); mp_init(i); if (value >= 0) { mp_set_long(i, value); } else { mp_set_long(i, -value); mp_neg(i, i); } while (*tmp) tmp++; *tmp = i; return i; } }
int pb_sub(pb_poly *a, pb_poly *b, pb_poly *c) { int neg, err, x, y, z, characteristic; pb_poly *tmp; /* grow c to be the max size */ y = MAX(a->used, b->used); if (c->alloc < y) { if ((err = pb_grow(c, y)) != MP_OKAY) { return err; } } /* do we need to concern char */ characteristic = mp_iszero(&(c->characteristic)); /* sub the terms */ z = MIN(a->used, b->used); for (x = 0; x < z; x++) { if ((err = mp_sub(&(a->terms[x]), &(b->terms[x]), &(c->terms[x]))) != MP_OKAY) { return err; } if (characteristic == MP_NO) { if ((err = mp_mod(&(c->terms[x]), &(c->characteristic), &(c->terms[x]))) != MP_OKAY) { return err; } } } /* excess digits? */ if (y != z) { if (a->used == y) { tmp = a; neg = 0; } else { tmp = b; neg = 1; } for (x = z; x < y; x++) { if (characteristic == MP_NO) { if ((err = mp_mod(&(tmp->terms[x]), &(c->characteristic), &(c->terms[x]))) != MP_OKAY) { return err; } if (neg) { if ((err = mp_sub(&(c->characteristic), &(c->terms[x]), &(c->terms[x]))) != MP_OKAY) { return err; } } } else { if (neg) { if ((err = mp_neg(&(tmp->terms[x]), &(c->terms[x]))) != MP_OKAY) { return err; } } else { if ((err = mp_copy(&(tmp->terms[x]), &(c->terms[x]))) != MP_OKAY) { return err; } } } } } /* zero excess */ for (x = y; x < c->used; x++) { mp_zero(&(c->terms[x])); } c->used = y; pb_clamp(c); return MP_OKAY; }
int main(void) { unsigned rr; int cnt, ix; #if LTM_DEMO_TEST_VS_MTEST unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n; char* ret; #else unsigned long s, t; unsigned long long q, r; mp_digit mp; int i, n, err, should; #endif if (mp_init_multi(&a, &b, &c, &d, &e, &f, NULL)!= MP_OKAY) return EXIT_FAILURE; atexit(_cleanup); #if defined(LTM_DEMO_REAL_RAND) if (!fd_urandom) { fd_urandom = fopen("/dev/urandom", "r"); if (!fd_urandom) { #if !defined(_WIN32) fprintf(stderr, "\ncould not open /dev/urandom\n"); #endif } } #endif srand(LTM_DEMO_RAND_SEED); #ifdef MP_8BIT printf("Digit size 8 Bit \n"); #endif #ifdef MP_16BIT printf("Digit size 16 Bit \n"); #endif #ifdef MP_32BIT printf("Digit size 32 Bit \n"); #endif #ifdef MP_64BIT printf("Digit size 64 Bit \n"); #endif printf("Size of mp_digit: %u\n", (unsigned int)sizeof(mp_digit)); printf("Size of mp_word: %u\n", (unsigned int)sizeof(mp_word)); printf("DIGIT_BIT: %d\n", DIGIT_BIT); printf("MP_PREC: %d\n", MP_PREC); #if LTM_DEMO_TEST_VS_MTEST == 0 // trivial stuff // a: 0->5 mp_set_int(&a, 5); // a: 5-> b: -5 mp_neg(&a, &b); if (mp_cmp(&a, &b) != MP_GT) { return EXIT_FAILURE; } if (mp_cmp(&b, &a) != MP_LT) { return EXIT_FAILURE; } // a: 5-> a: -5 mp_neg(&a, &a); if (mp_cmp(&b, &a) != MP_EQ) { return EXIT_FAILURE; } // a: -5-> b: 5 mp_abs(&a, &b); if (mp_isneg(&b) != MP_NO) { return EXIT_FAILURE; } // a: -5-> b: -4 mp_add_d(&a, 1, &b); if (mp_isneg(&b) != MP_YES) { return EXIT_FAILURE; } if (mp_get_int(&b) != 4) { return EXIT_FAILURE; } // a: -5-> b: 1 mp_add_d(&a, 6, &b); if (mp_get_int(&b) != 1) { return EXIT_FAILURE; } // a: -5-> a: 1 mp_add_d(&a, 6, &a); if (mp_get_int(&a) != 1) { return EXIT_FAILURE; } mp_zero(&a); // a: 0-> a: 6 mp_add_d(&a, 6, &a); if (mp_get_int(&a) != 6) { return EXIT_FAILURE; } mp_set_int(&a, 0); mp_set_int(&b, 1); if ((err = mp_jacobi(&a, &b, &i)) != MP_OKAY) { printf("Failed executing mp_jacobi(0 | 1) %s.\n", mp_error_to_string(err)); return EXIT_FAILURE; } if (i != 1) { printf("Failed trivial mp_jacobi(0 | 1) %d != 1\n", i); return EXIT_FAILURE; } for (cnt = 0; cnt < (int)(sizeof(jacobi)/sizeof(jacobi[0])); ++cnt) { mp_set_int(&b, jacobi[cnt].n); /* only test positive values of a */ for (n = -5; n <= 10; ++n) { mp_set_int(&a, abs(n)); should = MP_OKAY; if (n < 0) { mp_neg(&a, &a); /* Until #44 is fixed the negative a's must fail */ should = MP_VAL; } if ((err = mp_jacobi(&a, &b, &i)) != should) { printf("Failed executing mp_jacobi(%d | %lu) %s.\n", n, jacobi[cnt].n, mp_error_to_string(err)); return EXIT_FAILURE; } if (err == MP_OKAY && i != jacobi[cnt].c[n + 5]) { printf("Failed trivial mp_jacobi(%d | %lu) %d != %d\n", n, jacobi[cnt].n, i, jacobi[cnt].c[n + 5]); return EXIT_FAILURE; } } } // test mp_get_int printf("\n\nTesting: mp_get_int"); for (i = 0; i < 1000; ++i) { t = ((unsigned long) rand () * rand () + 1) & 0xFFFFFFFF; mp_set_int (&a, t); if (t != mp_get_int (&a)) { printf ("\nmp_get_int() bad result!"); return EXIT_FAILURE; } } mp_set_int(&a, 0); if (mp_get_int(&a) != 0) { printf("\nmp_get_int() bad result!"); return EXIT_FAILURE; } mp_set_int(&a, 0xffffffff); if (mp_get_int(&a) != 0xffffffff) { printf("\nmp_get_int() bad result!"); return EXIT_FAILURE; } printf("\n\nTesting: mp_get_long\n"); for (i = 0; i < (int)(sizeof(unsigned long)*CHAR_BIT) - 1; ++i) { t = (1ULL << (i+1)) - 1; if (!t) t = -1; printf(" t = 0x%lx i = %d\r", t, i); do { if (mp_set_long(&a, t) != MP_OKAY) { printf("\nmp_set_long() error!"); return EXIT_FAILURE; } s = mp_get_long(&a); if (s != t) { printf("\nmp_get_long() bad result! 0x%lx != 0x%lx", s, t); return EXIT_FAILURE; } t <<= 1; } while(t); } printf("\n\nTesting: mp_get_long_long\n"); for (i = 0; i < (int)(sizeof(unsigned long long)*CHAR_BIT) - 1; ++i) { r = (1ULL << (i+1)) - 1; if (!r) r = -1; printf(" r = 0x%llx i = %d\r", r, i); do { if (mp_set_long_long(&a, r) != MP_OKAY) { printf("\nmp_set_long_long() error!"); return EXIT_FAILURE; } q = mp_get_long_long(&a); if (q != r) { printf("\nmp_get_long_long() bad result! 0x%llx != 0x%llx", q, r); return EXIT_FAILURE; } r <<= 1; } while(r); } // test mp_sqrt printf("\n\nTesting: mp_sqrt\n"); for (i = 0; i < 1000; ++i) { printf ("%6d\r", i); fflush (stdout); n = (rand () & 15) + 1; mp_rand (&a, n); if (mp_sqrt (&a, &b) != MP_OKAY) { printf ("\nmp_sqrt() error!"); return EXIT_FAILURE; } mp_n_root_ex (&a, 2, &c, 0); mp_n_root_ex (&a, 2, &d, 1); if (mp_cmp_mag (&c, &d) != MP_EQ) { printf ("\nmp_n_root_ex() bad result!"); return EXIT_FAILURE; } if (mp_cmp_mag (&b, &c) != MP_EQ) { printf ("mp_sqrt() bad result!\n"); return EXIT_FAILURE; } } printf("\n\nTesting: mp_is_square\n"); for (i = 0; i < 1000; ++i) { printf ("%6d\r", i); fflush (stdout); /* test mp_is_square false negatives */ n = (rand () & 7) + 1; mp_rand (&a, n); mp_sqr (&a, &a); if (mp_is_square (&a, &n) != MP_OKAY) { printf ("\nfn:mp_is_square() error!"); return EXIT_FAILURE; } if (n == 0) { printf ("\nfn:mp_is_square() bad result!"); return EXIT_FAILURE; } /* test for false positives */ mp_add_d (&a, 1, &a); if (mp_is_square (&a, &n) != MP_OKAY) { printf ("\nfp:mp_is_square() error!"); return EXIT_FAILURE; } if (n == 1) { printf ("\nfp:mp_is_square() bad result!"); return EXIT_FAILURE; } } printf("\n\n"); // r^2 = n (mod p) for (i = 0; i < (int)(sizeof(sqrtmod_prime)/sizeof(sqrtmod_prime[0])); ++i) { mp_set_int(&a, sqrtmod_prime[i].p); mp_set_int(&b, sqrtmod_prime[i].n); if (mp_sqrtmod_prime(&b, &a, &c) != MP_OKAY) { printf("Failed executing %d. mp_sqrtmod_prime\n", (i+1)); return EXIT_FAILURE; } if (mp_cmp_d(&c, sqrtmod_prime[i].r) != MP_EQ) { printf("Failed %d. trivial mp_sqrtmod_prime\n", (i+1)); ndraw(&c, "r"); return EXIT_FAILURE; } } /* test for size */ for (ix = 10; ix < 128; ix++) { printf ("Testing (not safe-prime): %9d bits \r", ix); fflush (stdout); err = mp_prime_random_ex (&a, 8, ix, (rand () & 1) ? 0 : LTM_PRIME_2MSB_ON, myrng, NULL); if (err != MP_OKAY) { printf ("failed with err code %d\n", err); return EXIT_FAILURE; } if (mp_count_bits (&a) != ix) { printf ("Prime is %d not %d bits!!!\n", mp_count_bits (&a), ix); return EXIT_FAILURE; } } printf("\n"); for (ix = 16; ix < 128; ix++) { printf ("Testing ( safe-prime): %9d bits \r", ix); fflush (stdout); err = mp_prime_random_ex ( &a, 8, ix, ((rand () & 1) ? 0 : LTM_PRIME_2MSB_ON) | LTM_PRIME_SAFE, myrng, NULL); if (err != MP_OKAY) { printf ("failed with err code %d\n", err); return EXIT_FAILURE; } if (mp_count_bits (&a) != ix) { printf ("Prime is %d not %d bits!!!\n", mp_count_bits (&a), ix); return EXIT_FAILURE; } /* let's see if it's really a safe prime */ mp_sub_d (&a, 1, &a); mp_div_2 (&a, &a); mp_prime_is_prime (&a, 8, &cnt); if (cnt != MP_YES) { printf ("sub is not prime!\n"); return EXIT_FAILURE; } } printf("\n\n"); // test montgomery printf("Testing: montgomery...\n"); for (i = 1; i <= 10; i++) { if (i == 10) i = 1000; printf(" digit size: %2d\r", i); fflush(stdout); for (n = 0; n < 1000; n++) { mp_rand(&a, i); a.dp[0] |= 1; // let's see if R is right mp_montgomery_calc_normalization(&b, &a); mp_montgomery_setup(&a, &mp); // now test a random reduction for (ix = 0; ix < 100; ix++) { mp_rand(&c, 1 + abs(rand()) % (2*i)); mp_copy(&c, &d); mp_copy(&c, &e); mp_mod(&d, &a, &d); mp_montgomery_reduce(&c, &a, mp); mp_mulmod(&c, &b, &a, &c); if (mp_cmp(&c, &d) != MP_EQ) { printf("d = e mod a, c = e MOD a\n"); mp_todecimal(&a, buf); printf("a = %s\n", buf); mp_todecimal(&e, buf); printf("e = %s\n", buf); mp_todecimal(&d, buf); printf("d = %s\n", buf); mp_todecimal(&c, buf); printf("c = %s\n", buf); printf("compare no compare!\n"); return EXIT_FAILURE; } /* only one big montgomery reduction */ if (i > 10) { n = 1000; ix = 100; } } } } printf("\n\n"); mp_read_radix(&a, "123456", 10); mp_toradix_n(&a, buf, 10, 3); printf("a == %s\n", buf); mp_toradix_n(&a, buf, 10, 4); printf("a == %s\n", buf); mp_toradix_n(&a, buf, 10, 30); printf("a == %s\n", buf); #if 0 for (;;) { fgets(buf, sizeof(buf), stdin); mp_read_radix(&a, buf, 10); mp_prime_next_prime(&a, 5, 1); mp_toradix(&a, buf, 10); printf("%s, %lu\n", buf, a.dp[0] & 3); } #endif /* test mp_cnt_lsb */ printf("\n\nTesting: mp_cnt_lsb"); mp_set(&a, 1); for (ix = 0; ix < 1024; ix++) { if (mp_cnt_lsb (&a) != ix) { printf ("Failed at %d, %d\n", ix, mp_cnt_lsb (&a)); return EXIT_FAILURE; } mp_mul_2 (&a, &a); } /* test mp_reduce_2k */ printf("\n\nTesting: mp_reduce_2k\n"); for (cnt = 3; cnt <= 128; ++cnt) { mp_digit tmp; mp_2expt (&a, cnt); mp_sub_d (&a, 2, &a); /* a = 2**cnt - 2 */ printf ("\r %4d bits", cnt); printf ("(%d)", mp_reduce_is_2k (&a)); mp_reduce_2k_setup (&a, &tmp); printf ("(%lu)", (unsigned long) tmp); for (ix = 0; ix < 1000; ix++) { if (!(ix & 127)) { printf ("."); fflush (stdout); } mp_rand (&b, (cnt / DIGIT_BIT + 1) * 2); mp_copy (&c, &b); mp_mod (&c, &a, &c); mp_reduce_2k (&b, &a, 2); if (mp_cmp (&c, &b)) { printf ("FAILED\n"); return EXIT_FAILURE; } } } /* test mp_div_3 */ printf("\n\nTesting: mp_div_3...\n"); mp_set(&d, 3); for (cnt = 0; cnt < 10000;) { mp_digit r2; if (!(++cnt & 127)) { printf("%9d\r", cnt); fflush(stdout); } mp_rand(&a, abs(rand()) % 128 + 1); mp_div(&a, &d, &b, &e); mp_div_3(&a, &c, &r2); if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) { printf("\nmp_div_3 => Failure\n"); } } printf("\nPassed div_3 testing"); /* test the DR reduction */ printf("\n\nTesting: mp_dr_reduce...\n"); for (cnt = 2; cnt < 32; cnt++) { printf ("\r%d digit modulus", cnt); mp_grow (&a, cnt); mp_zero (&a); for (ix = 1; ix < cnt; ix++) { a.dp[ix] = MP_MASK; } a.used = cnt; a.dp[0] = 3; mp_rand (&b, cnt - 1); mp_copy (&b, &c); rr = 0; do { if (!(rr & 127)) { printf ("."); fflush (stdout); } mp_sqr (&b, &b); mp_add_d (&b, 1, &b); mp_copy (&b, &c); mp_mod (&b, &a, &b); mp_dr_setup(&a, &mp), mp_dr_reduce (&c, &a, mp); if (mp_cmp (&b, &c) != MP_EQ) { printf ("Failed on trial %u\n", rr); return EXIT_FAILURE; } } while (++rr < 500); printf (" passed"); fflush (stdout); } #if LTM_DEMO_TEST_REDUCE_2K_L /* test the mp_reduce_2k_l code */ #if LTM_DEMO_TEST_REDUCE_2K_L == 1 /* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */ mp_2expt(&a, 1024); mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16); mp_sub(&a, &b, &a); #elif LTM_DEMO_TEST_REDUCE_2K_L == 2 /* p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F */ mp_2expt(&a, 2048); mp_read_radix(&b, "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F", 16); mp_sub(&a, &b, &a); #else #error oops #endif mp_todecimal(&a, buf); printf("\n\np==%s\n", buf); /* now mp_reduce_is_2k_l() should return */ if (mp_reduce_is_2k_l(&a) != 1) { printf("mp_reduce_is_2k_l() return 0, should be 1\n"); return EXIT_FAILURE; } mp_reduce_2k_setup_l(&a, &d); /* now do a million square+1 to see if it varies */ mp_rand(&b, 64); mp_mod(&b, &a, &b); mp_copy(&b, &c); printf("Testing: mp_reduce_2k_l..."); fflush(stdout); for (cnt = 0; cnt < (int)(1UL << 20); cnt++) { mp_sqr(&b, &b); mp_add_d(&b, 1, &b); mp_reduce_2k_l(&b, &a, &d); mp_sqr(&c, &c); mp_add_d(&c, 1, &c); mp_mod(&c, &a, &c); if (mp_cmp(&b, &c) != MP_EQ) { printf("mp_reduce_2k_l() failed at step %d\n", cnt); mp_tohex(&b, buf); printf("b == %s\n", buf); mp_tohex(&c, buf); printf("c == %s\n", buf); return EXIT_FAILURE; } } printf("...Passed\n"); #endif /* LTM_DEMO_TEST_REDUCE_2K_L */ #else div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n = sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n = sub_d_n = 0; /* force KARA and TOOM to enable despite cutoffs */ KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 8; TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 16; for (;;) { /* randomly clear and re-init one variable, this has the affect of triming the alloc space */ switch (abs(rand()) % 7) { case 0: mp_clear(&a); mp_init(&a); break; case 1: mp_clear(&b); mp_init(&b); break; case 2: mp_clear(&c); mp_init(&c); break; case 3: mp_clear(&d); mp_init(&d); break; case 4: mp_clear(&e); mp_init(&e); break; case 5: mp_clear(&f); mp_init(&f); break; case 6: break; /* don't clear any */ } printf ("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ", add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n, expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n); ret=fgets(cmd, 4095, stdin); if(!ret){_panic(__LINE__);} cmd[strlen(cmd) - 1] = 0; printf("%-6s ]\r", cmd); fflush(stdout); if (!strcmp(cmd, "mul2d")) { ++mul2d_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} sscanf(buf, "%d", &rr); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); mp_mul_2d(&a, rr, &a); a.sign = b.sign; if (mp_cmp(&a, &b) != MP_EQ) { printf("mul2d failed, rr == %d\n", rr); draw(&a); draw(&b); return EXIT_FAILURE; } } else if (!strcmp(cmd, "div2d")) { ++div2d_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} sscanf(buf, "%d", &rr); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); mp_div_2d(&a, rr, &a, &e); a.sign = b.sign; if (a.used == b.used && a.used == 0) { a.sign = b.sign = MP_ZPOS; } if (mp_cmp(&a, &b) != MP_EQ) { printf("div2d failed, rr == %d\n", rr); draw(&a); draw(&b); return EXIT_FAILURE; } } else if (!strcmp(cmd, "add")) { ++add_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&c, buf, 64); mp_copy(&a, &d); mp_add(&d, &b, &d); if (mp_cmp(&c, &d) != MP_EQ) { printf("add %lu failure!\n", add_n); draw(&a); draw(&b); draw(&c); draw(&d); return EXIT_FAILURE; } /* test the sign/unsigned storage functions */ rr = mp_signed_bin_size(&c); mp_to_signed_bin(&c, (unsigned char *) cmd); memset(cmd + rr, rand() & 255, sizeof(cmd) - rr); mp_read_signed_bin(&d, (unsigned char *) cmd, rr); if (mp_cmp(&c, &d) != MP_EQ) { printf("mp_signed_bin failure!\n"); draw(&c); draw(&d); return EXIT_FAILURE; } rr = mp_unsigned_bin_size(&c); mp_to_unsigned_bin(&c, (unsigned char *) cmd); memset(cmd + rr, rand() & 255, sizeof(cmd) - rr); mp_read_unsigned_bin(&d, (unsigned char *) cmd, rr); if (mp_cmp_mag(&c, &d) != MP_EQ) { printf("mp_unsigned_bin failure!\n"); draw(&c); draw(&d); return EXIT_FAILURE; } } else if (!strcmp(cmd, "sub")) { ++sub_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&c, buf, 64); mp_copy(&a, &d); mp_sub(&d, &b, &d); if (mp_cmp(&c, &d) != MP_EQ) { printf("sub %lu failure!\n", sub_n); draw(&a); draw(&b); draw(&c); draw(&d); return EXIT_FAILURE; } } else if (!strcmp(cmd, "mul")) { ++mul_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&c, buf, 64); mp_copy(&a, &d); mp_mul(&d, &b, &d); if (mp_cmp(&c, &d) != MP_EQ) { printf("mul %lu failure!\n", mul_n); draw(&a); draw(&b); draw(&c); draw(&d); return EXIT_FAILURE; } } else if (!strcmp(cmd, "div")) { ++div_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&c, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&d, buf, 64); mp_div(&a, &b, &e, &f); if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) { printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e), mp_cmp(&d, &f)); draw(&a); draw(&b); draw(&c); draw(&d); draw(&e); draw(&f); return EXIT_FAILURE; } } else if (!strcmp(cmd, "sqr")) { ++sqr_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); mp_copy(&a, &c); mp_sqr(&c, &c); if (mp_cmp(&b, &c) != MP_EQ) { printf("sqr %lu failure!\n", sqr_n); draw(&a); draw(&b); draw(&c); return EXIT_FAILURE; } } else if (!strcmp(cmd, "gcd")) { ++gcd_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&c, buf, 64); mp_copy(&a, &d); mp_gcd(&d, &b, &d); d.sign = c.sign; if (mp_cmp(&c, &d) != MP_EQ) { printf("gcd %lu failure!\n", gcd_n); draw(&a); draw(&b); draw(&c); draw(&d); return EXIT_FAILURE; } } else if (!strcmp(cmd, "lcm")) { ++lcm_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&c, buf, 64); mp_copy(&a, &d); mp_lcm(&d, &b, &d); d.sign = c.sign; if (mp_cmp(&c, &d) != MP_EQ) { printf("lcm %lu failure!\n", lcm_n); draw(&a); draw(&b); draw(&c); draw(&d); return EXIT_FAILURE; } } else if (!strcmp(cmd, "expt")) { ++expt_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&c, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&d, buf, 64); mp_copy(&a, &e); mp_exptmod(&e, &b, &c, &e); if (mp_cmp(&d, &e) != MP_EQ) { printf("expt %lu failure!\n", expt_n); draw(&a); draw(&b); draw(&c); draw(&d); draw(&e); return EXIT_FAILURE; } } else if (!strcmp(cmd, "invmod")) { ++inv_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&c, buf, 64); mp_invmod(&a, &b, &d); mp_mulmod(&d, &a, &b, &e); if (mp_cmp_d(&e, 1) != MP_EQ) { printf("inv [wrong value from MPI?!] failure\n"); draw(&a); draw(&b); draw(&c); draw(&d); draw(&e); mp_gcd(&a, &b, &e); draw(&e); return EXIT_FAILURE; } } else if (!strcmp(cmd, "div2")) { ++div2_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); mp_div_2(&a, &c); if (mp_cmp(&c, &b) != MP_EQ) { printf("div_2 %lu failure\n", div2_n); draw(&a); draw(&b); draw(&c); return EXIT_FAILURE; } } else if (!strcmp(cmd, "mul2")) { ++mul2_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); mp_mul_2(&a, &c); if (mp_cmp(&c, &b) != MP_EQ) { printf("mul_2 %lu failure\n", mul2_n); draw(&a); draw(&b); draw(&c); return EXIT_FAILURE; } } else if (!strcmp(cmd, "add_d")) { ++add_d_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} sscanf(buf, "%d", &ix); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); mp_add_d(&a, ix, &c); if (mp_cmp(&b, &c) != MP_EQ) { printf("add_d %lu failure\n", add_d_n); draw(&a); draw(&b); draw(&c); printf("d == %d\n", ix); return EXIT_FAILURE; } } else if (!strcmp(cmd, "sub_d")) { ++sub_d_n; ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&a, buf, 64); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} sscanf(buf, "%d", &ix); ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);} mp_read_radix(&b, buf, 64); mp_sub_d(&a, ix, &c); if (mp_cmp(&b, &c) != MP_EQ) { printf("sub_d %lu failure\n", sub_d_n); draw(&a); draw(&b); draw(&c); printf("d == %d\n", ix); return EXIT_FAILURE; } } else if (!strcmp(cmd, "exit")) { printf("\nokay, exiting now\n"); break; } } #endif return 0; }
static int neg(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return mpi_to_ltc_error(mp_neg(a, b)); }
int mp_toom_cook_5_mul(mp_int *a, mp_int *b, mp_int *c) { mp_int w1, w2, w3, w4, w5, w6, w7, w8, w9; mp_int tmp1, tmp2; mp_int a0, a1, a2, a3, a4; mp_int b0, b1, b2, b3, b4; int e = MP_OKAY; int B, count, sign; B = (MAX(a->used, b->used)) / 5; sign = (a->sign != b->sign) ? MP_NEG : MP_ZPOS; if (MIN(a->used, b->used) < TOOM_COOK_5_MUL_CO) { if ((e = mp_mul(a, b, c)) != MP_OKAY) { return e; } c->sign = sign; return MP_OKAY; } if ((e = mp_init_multi(&w1, &w2, &w3, &w4, &w5, &w6, &w7, &w8, &w9, &tmp1, &tmp2, //&a0, &a1, &a2, &a3, &a4, &b0, &b1, &b2, &b3, &b4, NULL)) != MP_OKAY) { goto ERR0; //goto ERR; } if ((e = mp_init_size(&a0, B)) != MP_OKAY) { goto ERRa0; } if ((e = mp_init_size(&a1, B)) != MP_OKAY) { goto ERRa1; } if ((e = mp_init_size(&a2, B)) != MP_OKAY) { goto ERRa2; } if ((e = mp_init_size(&a3, B)) != MP_OKAY) { goto ERRa3; } if ((e = mp_init_size(&a4, B)) != MP_OKAY) { goto ERRa4; } if ((e = mp_init_size(&b0, B)) != MP_OKAY) { goto ERRb0; } if ((e = mp_init_size(&b1, B)) != MP_OKAY) { goto ERRb1; } if ((e = mp_init_size(&b2, B)) != MP_OKAY) { goto ERRb2; } if ((e = mp_init_size(&b3, B)) != MP_OKAY) { goto ERRb3; } if ((e = mp_init_size(&b4, B)) != MP_OKAY) { goto ERRb4; } // A = a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0 for (count = 0; count < a->used; count++) { switch (count / B) { case 0: a0.dp[count] = a->dp[count]; a0.used++; break; case 1: a1.dp[count - B] = a->dp[count]; a1.used++; break; case 2: a2.dp[count - 2 * B] = a->dp[count]; a2.used++; break; case 3: a3.dp[count - 3 * B] = a->dp[count]; a3.used++; break; case 4: a4.dp[count - 4 * B] = a->dp[count]; a4.used++; break; default: a4.dp[count - 4 * B] = a->dp[count]; a4.used++; break; } } mp_clamp(&a0); mp_clamp(&a1); mp_clamp(&a2); mp_clamp(&a3); mp_clamp(&a4); // B = b4*x^4 + b3*x^3 + b2*x^2 + b1*x + b0 for (count = 0; count < b->used; count++) { switch (count / B) { case 0: b0.dp[count] = b->dp[count]; b0.used++; break; case 1: b1.dp[count - B] = b->dp[count]; b1.used++; break; case 2: b2.dp[count - 2 * B] = b->dp[count]; b2.used++; break; case 3: b3.dp[count - 3 * B] = b->dp[count]; b3.used++; break; case 4: b4.dp[count - 4 * B] = b->dp[count]; b4.used++; break; default: b4.dp[count - 4 * B] = b->dp[count]; b4.used++; break; } } mp_clamp(&b0); mp_clamp(&b1); mp_clamp(&b2); mp_clamp(&b3); mp_clamp(&b4); /* if ((e = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { goto ERR; } if ((e = mp_copy(a, &a1)) != MP_OKAY) { goto ERR; } mp_rshd(&a1, B); mp_mod_2d(&a1, DIGIT_BIT * B, &a1); if ((e = mp_copy(a, &a2)) != MP_OKAY) { goto ERR; } mp_rshd(&a2, B * 2); mp_mod_2d(&a2, DIGIT_BIT * B, &a2); if ((e = mp_copy(a, &a3)) != MP_OKAY) { goto ERR; } mp_rshd(&a3, B * 3); mp_mod_2d(&a3, DIGIT_BIT * B, &a3); if ((e = mp_copy(a, &a4)) != MP_OKAY) { goto ERR; } mp_rshd(&a4, B * 4); if ((e = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { goto ERR; } if ((e = mp_copy(a, &b1)) != MP_OKAY) { goto ERR; } mp_rshd(&b1, B); mp_mod_2d(&b1, DIGIT_BIT * B, &b1); if ((e = mp_copy(b, &b2)) != MP_OKAY) { goto ERR; } mp_rshd(&b2, B * 2); mp_mod_2d(&b2, DIGIT_BIT * B, &b2); if ((e = mp_copy(b, &b3)) != MP_OKAY) { goto ERR; } mp_rshd(&b3, B * 3); mp_mod_2d(&b3, DIGIT_BIT * B, &b3); if ((e = mp_copy(b, &b4)) != MP_OKAY) { goto ERR; } mp_rshd(&b4, B * 4); */ // S1 = a4*b4 if ((e = mp_mul(&a4, &b4, &w1)) != MP_OKAY) { goto ERR; } // S9 = a0*b0 if ((e = mp_mul(&a0, &b0, &w9)) != MP_OKAY) { goto ERR; } // S2 = (a0- 2*a1 +4*a2 -8*a3 +16*a4) if ((e = mp_mul_2d(&a1, 1, &tmp1)) != MP_OKAY) { goto ERR; } // 2*a1 = tmp1 if ((e = mp_sub(&a0, &tmp1, &w2)) != MP_OKAY) { goto ERR; } // a0- 2*a1 = a0 - tmp1 = w2 if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) { goto ERR; } // 4*a2 = tmp1 if ((e = mp_add(&w2, &tmp1, &w2)) != MP_OKAY) { goto ERR; } // a0- 2*a1 +4*a2 = w2 + tmp1 = w2 if ((e = mp_mul_2d(&a3, 3, &tmp1)) != MP_OKAY) { goto ERR; } // 8*a3 = tmp1 if ((e = mp_sub(&w2, &tmp1, &w2)) != MP_OKAY) { goto ERR; } // a0- 2*a1 +4*a2 -8*a3 = w2 - tmp1 = w2 if ((e = mp_mul_2d(&a4, 4, &tmp1)) != MP_OKAY) { goto ERR; } // 16*a4 = tmp1 if ((e = mp_add(&w2, &tmp1, &w2)) != MP_OKAY) { goto ERR; } // a0- 2*a1 +4*a2 -8*a3 +16*a4 = w2 + tmp1 = w2 // * (b0- 2*b1 +4*b2 -8*b3 +16*b4) if ((e = mp_mul_2d(&b1, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&b0, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b3, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b4, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp2, &w2, &w2)) != MP_OKAY) { goto ERR; } // S5 = (a0+ 2*a1+ 4*a2+ 8*a3+ 16*a4) if ((e = mp_mul_2d(&a1, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&a0, &tmp1, &w5)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a3, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a4, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) { goto ERR; } // *(b0+ 2*b1+ 4*b2+ 8*b3+ 16*b4) if ((e = mp_mul_2d(&b1, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&b0, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b3, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b4, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp2, &w5, &w5)) != MP_OKAY) { goto ERR; } // S3 = (a4+ 2*a3+ 4*a2+ 8*a1+ 16*a0) if ((e = mp_mul_2d(&a3, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&a4, &tmp1, &w3)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a1, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a0, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) { goto ERR; } // * (b4+ 2*b3+ 4*b2+ 8*b1+ 16*b0) if ((e = mp_mul_2d(&b3, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&b4, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b1, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b0, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp2, &w3, &w3)) != MP_OKAY) { goto ERR; } // S8 = (a4- 2*a3+ 4*a2- 8*a1+ 16*a0) if ((e = mp_mul_2d(&a3, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&a4, &tmp1, &w8)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w8, &tmp1, &w8)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a1, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w8, &tmp1, &w8)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a0, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w8, &tmp1, &w8)) != MP_OKAY) { goto ERR; } //* (b4- 2*b3+ 4*b2- 8*b1+ 16*b0) if ((e = mp_mul_2d(&b3, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&b4, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b1, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b0, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp2, &w8, &w8)) != MP_OKAY) { goto ERR; } // S4 = (a0+ 4*a1+ 16*a2+ 64*a3+ 256*a4) if ((e = mp_mul_2d(&a1, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&a0, &tmp1, &w4)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a2, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a3, 6, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a4, 8, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } //* (b0+ 4*b1+ 16*b2+ 64*b3+ 256*b4) if ((e = mp_mul_2d(&b1, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&b0, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b2, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b3, 6, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b4, 8, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp2, &w4, &w4)) != MP_OKAY) { goto ERR; } // S6 = (a0- a1+ a2- a3 +a4) if ((e = mp_sub(&a0, &a1, &w6)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w6, &a2, &w6)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w6, &a3, &w6)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w6, &a4, &w6)) != MP_OKAY) { goto ERR; } // * (b0- b1+ b2- b3+ b4) if ((e = mp_sub(&b0, &b1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &b2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&tmp1, &b3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &b4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp1, &w6, &w6)) != MP_OKAY) { goto ERR; } // S7 = (a0+ a1+ a2+ a3+ a4) if ((e = mp_add(&a0, &a1, &w7)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w7, &a2, &w7)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w7, &a3, &w7)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w7, &a4, &w7)) != MP_OKAY) { goto ERR; } // * (b0+ b1+ b2+ b3+ b4) if ((e = mp_add(&b0, &b1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &b2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &b3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &b4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp1, &w7, &w7)) != MP_OKAY) { goto ERR; } // S6 -= S7 if ((e = mp_sub(&w6, &w7, &w6)) != MP_OKAY) { goto ERR; } // S2 -= S5 if ((e = mp_sub(&w2, &w5, &w2)) != MP_OKAY) { goto ERR; } // S4 -= S9 if ((e = mp_sub(&w4, &w9, &w4)) != MP_OKAY) { goto ERR; } // S4 -= (2^16*S1) if ((e = mp_mul_2d(&w1, 16, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S8 -= S3 if ((e = mp_sub(&w8, &w3, &w8)) != MP_OKAY) { goto ERR; } // S6 /= 2 if ((e = mp_div_2d(&w6, 1, &w6, NULL)) != MP_OKAY) { goto ERR; } // S5 *= 2 if ((e = mp_mul_2d(&w5, 1, &w5)) != MP_OKAY) { goto ERR; } // S5 += S2 if ((e = mp_add(&w5, &w2, &w5)) != MP_OKAY) { goto ERR; } // S2 = -S2 if ((e = mp_neg(&w2, &w2)) != MP_OKAY) { goto ERR; } // S8 = -S8 if ((e = mp_neg(&w8, &w8)) != MP_OKAY) { goto ERR; } // S7 += S6 if ((e = mp_add(&w7, &w6, &w7)) != MP_OKAY) { goto ERR; } // S6 = -S6 if ((e = mp_neg(&w6, &w6)) != MP_OKAY) { goto ERR; } // S3 -= S7 if ((e = mp_sub(&w3, &w7, &w3)) != MP_OKAY) { goto ERR; } // S5 -= (512*S7) if ((e = mp_mul_2d(&w7, 9, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w5, &tmp1, &w5)) != MP_OKAY) { goto ERR; } // S3 *= 2 if ((e = mp_mul_2d(&w3, 1, &w3)) != MP_OKAY) { goto ERR; } // S3 -= S8 if ((e = mp_sub(&w3, &w8, &w3)) != MP_OKAY) { goto ERR; } // S7 -= S1 if ((e = mp_sub(&w7, &w1, &w7)) != MP_OKAY) { goto ERR; } // S7 -= S9 if ((e = mp_sub(&w7, &w9, &w7)) != MP_OKAY) { goto ERR; } // S8 += S2 if ((e = mp_add(&w8, &w2, &w8)) != MP_OKAY) { goto ERR; } // S5 += S3 if ((e = mp_add(&w5, &w3, &w5)) != MP_OKAY) { goto ERR; } // S8 -= (80*S6) if ((e = mp_mul_d(&w6, 80, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w8, &tmp1, &w8)) != MP_OKAY) { goto ERR; } // S3 -= (510*S9) if ((e = mp_mul_d(&w9, 510, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { goto ERR; } // S4 -= S2 if ((e = mp_sub(&w4, &w2, &w4)) != MP_OKAY) { goto ERR; } // S3 *= 3 if ((e = mp_mul_d(&w3, 3, &w3)) != MP_OKAY) { goto ERR; } // S3 += S5 if ((e = mp_add(&w3, &w5, &w3)) != MP_OKAY) { goto ERR; } // S8 /= 180 \\ division by 180 if ((e = mp_div_d(&w8, 180, &w8, NULL)) != MP_OKAY) { goto ERR; } // S5 += (378*S7) if ((e = mp_mul_d(&w7, 378, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) { goto ERR; } // S2 /= 4 if ((e = mp_div_2d(&w2, 2, &w2, NULL)) != MP_OKAY) { goto ERR; } // S6 -= S2 if ((e = mp_sub(&w6, &w2, &w6)) != MP_OKAY) { goto ERR; } // S5 /= (-72) \\ division by -72 if ((e = mp_div_d(&w5, 72, &w5, NULL)) != MP_OKAY) { goto ERR; } if (&w5.sign == MP_ZPOS) (&w5)->sign = MP_NEG; (&w5)->sign = MP_ZPOS; // S3 /= (-360) \\ division by -360 if ((e = mp_div_d(&w3, 360, &w3, NULL)) != MP_OKAY) { goto ERR; } if (&w3.sign == MP_ZPOS) (&w3)->sign = MP_NEG; (&w3)->sign = MP_ZPOS; // S2 -= S8 if ((e = mp_sub(&w2, &w8, &w2)) != MP_OKAY) { goto ERR; } // S7 -= S3 if ((e = mp_sub(&w7, &w3, &w7)) != MP_OKAY) { goto ERR; } // S4 -= (256*S5) if ((e = mp_mul_2d(&w5, 8, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S3 -= S5 if ((e = mp_sub(&w3, &w5, &w3)) != MP_OKAY) { goto ERR; } // S4 -= (4096*S3) if ((e = mp_mul_2d(&w3, 12, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S4 -= (16*S7) if ((e = mp_mul_2d(&w7, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S4 += (256*S6) if ((e = mp_mul_2d(&w6, 8, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S6 += S2 if ((e = mp_add(&w6, &w2, &w6)) != MP_OKAY) { goto ERR; } // S2 *= 180 if ((e = mp_mul_d(&w2, 180, &w2)) != MP_OKAY) { goto ERR; } // S2 += S4 if ((e = mp_add(&w2, &w4, &w2)) != MP_OKAY) { goto ERR; } // S2 /= 11340 \\ division by 11340 if ((e = mp_div_d(&w2, 11340, &w2, NULL)) != MP_OKAY) { goto ERR; } // S4 += (720*S6) if ((e = mp_mul_d(&w6, 720, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S4 /= (-2160) \\ division by -2160 if ((e = mp_div_d(&w4, 2160, &w4, NULL)) != MP_OKAY) { goto ERR; } if (&w4.sign == MP_ZPOS) (&w4)->sign = MP_NEG; (&w4)->sign = MP_ZPOS; // S6 -= S4 if ((e = mp_sub(&w6, &w4, &w6)) != MP_OKAY) { goto ERR; } // S8 -= S2 if ((e = mp_sub(&w8, &w2, &w8)) != MP_OKAY) { goto ERR; } // P = S1*x^8 + S2*x^7 + S3*x^6 + S4*x^5 + S5*x^4 + S6*x^3 + S7*x^2 + S8*x + S9 if ((e = mp_copy(&w9, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w8, B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w8, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w7, 2 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w7, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w6, 3 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w6, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w5, 4 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w5, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w4, 5 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w3, 6 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w2, 7 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w1, 8 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w1, c)) != MP_OKAY) { goto ERR; } // P - A*B \\ == zero c->sign = sign; ERR: ERRb4: mp_clear(&b4); ERRb3: mp_clear(&b3); ERRb2: mp_clear(&b2); ERRb1: mp_clear(&b1); ERRb0: mp_clear(&b0); ERRa4: mp_clear(&a4); ERRa3: mp_clear(&a3); ERRa2: mp_clear(&a2); ERRa1: mp_clear(&a1); ERRa0: mp_clear(&a0); ERR0: mp_clear_multi(&w1, &w2, &w3, &w4, &w5, &w6, &w7, &w8, &w9, &tmp1, &tmp2, // &a0, &a1, &a2, &a3, &a4, &b0, &b1, &b2, &b3, &b4, NULL); return e; }
term_t bin2term(apr_byte_t **data, int *bytes_left, atoms_t *atoms, heap_t *heap) { #define require(__n) \ do { \ if (*bytes_left < __n) \ return noval; \ (*bytes_left) -= __n; \ } while (0) #define get_byte() (*(*data)++) require(1); switch (get_byte()) { case 97: { require(1); return tag_int(get_byte()); } case 98: { int a, b, c, d; require(4); a = get_byte(); b = get_byte(); c = get_byte(); d = get_byte(); return int_to_term((a << 24) | (b << 16) | (c << 8) | d, heap); } case 99: { double value; require(31); sscanf((const char *)*data, "%lf", &value); (*data) += 31; return heap_float(heap, value); } case 100: { int a, b; int len; cstr_t *s; int index; require(2); a = get_byte(); b = get_byte(); len = ((a << 8) | b); if (len > 255) return noval; require(len); s = (cstr_t *)heap_alloc(heap, sizeof(cstr_t) + len); s->size = len; memcpy(s->data, *data, len); index = atoms_set(atoms, s); (*data) += len; return tag_atom(index); } case 104: { int arity, i; term_t tuple; term_box_t *tbox; require(1); arity = get_byte(); tuple = heap_tuple(heap, arity); tbox = peel(tuple); for (i = 0; i < arity; i++) { term_t e = bin2term(data, bytes_left, atoms, heap); if (e == noval) return noval; tbox->tuple.elts[i] = e; } return tuple; } case 105: { int a, b, c, d; int arity, i; term_t tuple; term_box_t *tbox; require(4); a = get_byte(); b = get_byte(); c = get_byte(); d = get_byte(); arity = ((a << 24) | (b << 16) | (c << 8) | d); tuple = heap_tuple(heap, arity); tbox = peel(tuple); for (i = 0; i < arity; i++) { term_t e = bin2term(data, bytes_left, atoms, heap); if (e == noval) return noval; tbox->tuple.elts[i] = e; } return tuple; } case 106: { return nil; } case 107: { int a, b; int len, i; term_t cons = nil; require(2); a = get_byte(); b = get_byte(); len = ((a << 8) | b); require(len); i = len-1; while (i >= 0) cons = heap_cons2(heap, tag_int((*data)[i--]), cons); (*data) += len; return cons; } case 108: { int a, b, c, d; int len, i; term_t *es; term_t tail; require(4); a = get_byte(); b = get_byte(); c = get_byte(); d = get_byte(); len = ((a << 24) | (b << 16) | (c << 8) | d); es = (term_t *)heap_alloc(heap, len*sizeof(term_t)); for (i = 0; i < len; i++) { term_t e = bin2term(data, bytes_left, atoms, heap); if (e == noval) return noval; es[i] = e; } tail = bin2term(data, bytes_left, atoms, heap); if (tail == noval) return noval; i = len-1; while (i >= 0) tail = heap_cons2(heap, es[i--], tail); return tail; } case 109: { int a, b, c, d; int len; term_t bin; require(4); a = get_byte(); b = get_byte(); c = get_byte(); d = get_byte(); len = ((a << 24) | (b << 16) | (c << 8) | d); require(len); bin = heap_binary(heap, len*8, (*data)); (*data) += len; return bin; } case 110: { int len; int sign; mp_size prec; mp_int mp; mp_err rs; require(1); len = get_byte(); sign = get_byte(); require(len); prec = (len + (MP_DIGIT_SIZE-1)) / MP_DIGIT_SIZE; mp_init_size(&mp, prec, heap); //TODO: use mp_read_signed_bin rs = mp_read_unsigned_bin_lsb(&mp, *data, len, heap); if (rs != MP_OKAY) return noval; (*data) += len; if (sign == 1) mp_neg(&mp, &mp, heap); return mp_to_term(mp); } case 111: { int a, b, c, d; int len; int sign; mp_size prec; mp_int mp; mp_err rs; require(4); a = get_byte(); b = get_byte(); c = get_byte(); d = get_byte(); len = ((a << 24) | (b << 16) | (c << 8) | d); require(1); sign = get_byte(); require(len); prec = (len + (MP_DIGIT_SIZE-1)) / MP_DIGIT_SIZE; mp_init_size(&mp, prec, heap); rs = mp_read_unsigned_bin_lsb(&mp, *data, len, heap); if (rs != MP_OKAY) return noval; (*data) += len; if (sign == 1) mp_neg(&mp, &mp, heap); return mp_to_term(mp); } default: return noval; // only a subset of tags are supported; inspired by BERT } }
Integer* Integer::from_cstr(STATE, const char* str, const char* end, int base, Object* strict) { if(base == 1 || base > 36) return nil<Integer>(); // Skip any combination of leading whitespace and underscores. Leading // whitespace is OK in strict mode, but underscores are not. while(isspace(*str) || *str == '_') { if(*str == '_') { if(CBOOL(strict)) { return nil<Integer>(); } else { return Fixnum::from(0); } } str++; } bool negative = false; if(*str == '-') { str++; negative = true; } else if(*str == '+') { str++; } int detected_base = 0; const char* str_start = str; /* Try to detect a base prefix. We have to do this even though we might * have been told the base, we have to know if we should discard the bytes * that make up the prefix if it's redundant with the passed in base. * * For example, if base == 16 and str == "0xa", we return 10. But if base * == 10 and str == "0xa", we fail because we rewind and try to process 0x * as part of the base 10 string. */ if(*str == '0') { str++; switch(*str++) { case 'b': case 'B': detected_base = 2; break; case 'o': case 'O': detected_base = 8; break; case 'd': case 'D': detected_base = 10; break; case 'x': case 'X': detected_base = 16; break; default: // If passed "017" and a base of 0, that is octal 15. Otherwise, it // is whatever those digits would be in the specified base. str--; detected_base = 8; } } // If base is less than 0, then it's just a hint for how to process it // if there is no base detected. if(base < 0) { if(detected_base == 0) { // Ok, no detected because, use the base hint and start over. base = -base; str = str_start; } else { base = detected_base; } // If 0 was passed in as the base, we use the detected base. } else if(base == 0) { // Default to 10 if there is no input and no detected base. if(detected_base == 0) { base = 10; str = str_start; } else { base = detected_base; } // If the passed in base and the detected base contradict each other, then // rewind and process the whole string as digits of the passed in base. } else if(base != detected_base) { // Rewind the stream and try and consume the prefix as digits in the // number. str = str_start; } int max_digits = DIGIT_BIT / digit_bits[base]; int count = 0; int digit = 0; mp_digit shift = base, value = 0; mp_int a = { 0, 0, 0, 0, 0, }; for( ; str < end; str++) { digit = digit_value[int(*str)]; if(digit >= 0 && digit < base) { if(++count <= max_digits) { value = value * base + digit; } else { if(!mp_isinitialized(&a)) { mp_init_set_long(XST, &a, value); for(int i = 0; i < max_digits - 1; i++) { shift *= base; } } else { mp_mul_d(XST, &a, shift, &a); mp_add_d(XST, &a, value, &a); } value = digit; count = 1; } continue; } // An underscore is valid iff it is followed by a valid character for // this base. if(*str == '_') { if(!*(str + 1) || *(str + 1) == '_') goto error_check; continue; } if(digit >= base) goto error_check; // Consume any whitespace characters. if(digit < -1) { while(digit_value[int(*++str)] < -1) /* skip whitespace */ ; goto error_check; } // Done parsing. break; } error_check: if(str < end && CBOOL(strict)) { if(mp_isinitialized(&a)) mp_clear(&a); return nil<Integer>(); } if(!mp_isinitialized(&a)) { if(value < FIXNUM_MAX) { Fixnum* result = Fixnum::from(value); if(negative) { return result->neg(state); } else { return result; } } mp_init_set_long(XST, &a, value); } else { shift = base; for(int i = 0; i < count - 1; i++) { shift *= base; } mp_mul_d(XST, &a, shift, &a); mp_add_d(XST, &a, value, &a); } if(negative) { mp_neg(XST, &a, &a); } Integer* result = Bignum::from(state, &a); mp_clear(&a); return result; }
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and * R can be identical. Uses affine coordinates. Assumes input is already * field-encoded using field_enc, and returns output that is still * field-encoded. */ mp_err ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group) { mp_err res = MP_OKAY; mp_int k, k3, qx, qy, sx, sy; int b1, b3, i, l; MP_DIGITS(&k) = 0; MP_DIGITS(&k3) = 0; MP_DIGITS(&qx) = 0; MP_DIGITS(&qy) = 0; MP_DIGITS(&sx) = 0; MP_DIGITS(&sy) = 0; MP_CHECKOK(mp_init(&k)); MP_CHECKOK(mp_init(&k3)); MP_CHECKOK(mp_init(&qx)); MP_CHECKOK(mp_init(&qy)); MP_CHECKOK(mp_init(&sx)); MP_CHECKOK(mp_init(&sy)); /* if n = 0 then r = inf */ if (mp_cmp_z(n) == 0) { mp_zero(rx); mp_zero(ry); res = MP_OKAY; goto CLEANUP; } /* Q = P, k = n */ MP_CHECKOK(mp_copy(px, &qx)); MP_CHECKOK(mp_copy(py, &qy)); MP_CHECKOK(mp_copy(n, &k)); /* if n < 0 then Q = -Q, k = -k */ if (mp_cmp_z(n) < 0) { MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth)); MP_CHECKOK(mp_neg(&k, &k)); } #ifdef ECL_DEBUG /* basic double and add method */ l = mpl_significant_bits(&k) - 1; MP_CHECKOK(mp_copy(&qx, &sx)); MP_CHECKOK(mp_copy(&qy, &sy)); for (i = l - 1; i >= 0; i--) { /* S = 2S */ MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group)); /* if k_i = 1, then S = S + Q */ if (mpl_get_bit(&k, i) != 0) { MP_CHECKOK(group->point_add(&sx, &sy, &qx, &qy, &sx, &sy, group)); } } #else /* double and add/subtract method from \ * standard */ /* k3 = 3 * k */ MP_CHECKOK(mp_set_int(&k3, 3)); MP_CHECKOK(mp_mul(&k, &k3, &k3)); /* S = Q */ MP_CHECKOK(mp_copy(&qx, &sx)); MP_CHECKOK(mp_copy(&qy, &sy)); /* l = index of high order bit in binary representation of 3*k */ l = mpl_significant_bits(&k3) - 1; /* for i = l-1 downto 1 */ for (i = l - 1; i >= 1; i--) { /* S = 2S */ MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group)); b3 = MP_GET_BIT(&k3, i); b1 = MP_GET_BIT(&k, i); /* if k3_i = 1 and k_i = 0, then S = S + Q */ if ((b3 == 1) && (b1 == 0)) { MP_CHECKOK(group->point_add(&sx, &sy, &qx, &qy, &sx, &sy, group)); /* if k3_i = 0 and k_i = 1, then S = S - Q */ } else if ((b3 == 0) && (b1 == 1)) { MP_CHECKOK(group->point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group)); } } #endif /* output S */ MP_CHECKOK(mp_copy(&sx, rx)); MP_CHECKOK(mp_copy(&sy, ry)); CLEANUP: mp_clear(&k); mp_clear(&k3); mp_clear(&qx); mp_clear(&qy); mp_clear(&sx); mp_clear(&sy); return res; }