int main (int argc, char **argv) { mpz_t op1, op2, ref; int i, j, chain_len; gmp_randstate_t rands; mpz_t bs; unsigned long bsi, size_range; int reps = 200; if (argc == 2) reps = atoi (argv[1]); tests_start (); gmp_randinit_default(rands); check_data (); mpz_init (bs); mpz_init (op1); mpz_init (op2); mpz_init (ref); mpz_init (gcd1); mpz_init (gcd2); mpz_init (temp1); mpz_init (temp2); mpz_init (s); mpz_init (t); for (i = 0; i < reps; i++) { /* Generate plain operands with unknown gcd. These types of operands have proven to trigger certain bugs in development versions of the gcd code. The "hgcd->row[3].rsize > M" ASSERT is not triggered by the division chain code below, but that is most likely just a result of that other ASSERTs are triggered before it. */ mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 16 + 2; mpz_urandomb (bs, rands, size_range); mpz_urandomb (op1, rands, mpz_get_ui (bs) + MIN_OPERAND_BITSIZE); mpz_urandomb (bs, rands, size_range); mpz_urandomb (op2, rands, mpz_get_ui (bs) + MIN_OPERAND_BITSIZE); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (op1, op1); if ((bsi & 2) != 0) mpz_neg (op2, op2); one_test (op1, op2, NULL, i); /* Generate a division chain backwards, allowing otherwise unlikely huge quotients. */ mpz_set_ui (op1, 0); mpz_urandomb (bs, rands, 32); mpz_urandomb (bs, rands, mpz_get_ui (bs) % 16 + 1); mpz_rrandomb (op2, rands, mpz_get_ui (bs)); mpz_add_ui (op2, op2, 1); mpz_set (ref, op2); mpz_urandomb (bs, rands, 32); chain_len = mpz_get_ui (bs) % 50; for (j = 0; j < chain_len; j++) { mpz_urandomb (bs, rands, 32); mpz_urandomb (bs, rands, mpz_get_ui (bs) % 12 + 1); mpz_rrandomb (temp2, rands, mpz_get_ui (bs) + 1); mpz_add_ui (temp2, temp2, 1); mpz_mul (temp1, op2, temp2); mpz_add (op1, op1, temp1); /* Don't generate overly huge operands. */ if (SIZ (op1) > 1000) break; mpz_urandomb (bs, rands, 32); mpz_urandomb (bs, rands, mpz_get_ui (bs) % 12 + 1); mpz_rrandomb (temp2, rands, mpz_get_ui (bs) + 1); mpz_add_ui (temp2, temp2, 1); mpz_mul (temp1, op1, temp2); mpz_add (op2, op2, temp1); /* Don't generate overly huge operands. */ if (SIZ (op2) > 1000) break; } one_test (op1, op2, ref, i); } mpz_clear (bs); mpz_clear (op1); mpz_clear (op2); mpz_clear (ref); mpz_clear (gcd1); mpz_clear (gcd2); mpz_clear (temp1); mpz_clear (temp2); mpz_clear (s); mpz_clear (t); gmp_randclear(rands); tests_end (); exit (0); }
void mpz_sqrtmp_r (mpz_ptr root, mpz_srcptr a, mpz_srcptr p) { /* ? a \neq 0 */ if (mpz_get_ui(a) != 0) { /* ? p = 3 (mod 4) */ if (mpz_congruent_ui_p(p, 3L, 4L)) { mpz_t foo; mpz_init_set(foo, p); mpz_add_ui(foo, foo, 1L); mpz_fdiv_q_2exp(foo, foo, 2L); mpz_powm(root, a, foo, p); mpz_clear(foo); return; } /* ! p = 1 (mod 4) */ else { /* ! s = (p-1)/4 */ mpz_t s; mpz_init_set(s, p); mpz_sub_ui(s, s, 1L); mpz_fdiv_q_2exp(s, s, 2L); /* ? p = 5 (mod 8) */ if (mpz_congruent_ui_p(p, 5L, 8L)) { mpz_t foo, b; mpz_init(foo); mpz_powm(foo, a, s, p); mpz_init_set(b, p); mpz_add_ui(b, b, 3L); mpz_fdiv_q_2exp(b, b, 3L); mpz_powm(root, a, b, p); /* ? a^{(p-1)/4} = 1 (mod p) */ if (mpz_cmp_ui(foo, 1L) == 0) { mpz_clear(foo), mpz_clear(s), mpz_clear(b); return; } /* ! a^{(p-1)/4} = -1 (mod p) */ else { do mpz_wrandomm(b, p); while (mpz_jacobi(b, p) != -1); mpz_powm(b, b, s, p); mpz_mul(root, root, b); mpz_mod(root, root, p); mpz_clear(foo), mpz_clear(s), mpz_clear(b); return; } } /* ! p = 1 (mod 8) */ else { mpz_t foo, bar, b, t; mpz_init(foo), mpz_init(bar); mpz_powm(foo, a, s, p); /* while a^s = 1 (mod p) */ while (mpz_cmp_ui(foo, 1L) == 0) { /* ? s odd */ if (mpz_odd_p(s)) { mpz_add_ui(s, s, 1L); mpz_fdiv_q_2exp(s, s, 1L); mpz_powm(root, a, s, p); mpz_clear(foo), mpz_clear(s); return; } /* ! s even */ else { mpz_fdiv_q_2exp(s, s, 1L); } mpz_powm(foo, a, s, p); } /* ! a^s = -1 (mod p) */ mpz_init(b); do mpz_wrandomm(b, p); while (mpz_jacobi(b, p) != -1); mpz_init_set(t, p); mpz_sub_ui(t, t, 1L); mpz_fdiv_q_2exp(t, t, 1L); /* while s even */ while (mpz_even_p(s)) { mpz_fdiv_q_2exp(s, s, 1L); mpz_fdiv_q_2exp(t, t, 1L); mpz_powm(foo, a, s, p); mpz_powm(bar, b, t, p); mpz_mul(foo, foo, bar); mpz_mod(foo, foo, p); mpz_set_si(bar, -1L); /* ? a^s * b^t = -1 (mod p) */ if (mpz_congruent_p(foo, bar, p)) { mpz_set(bar, p); mpz_sub_ui(bar, bar, 1L); mpz_fdiv_q_2exp(bar, bar, 1L); mpz_add(t, t, bar); } } mpz_add_ui(s, s, 1L); mpz_fdiv_q_2exp(s, s, 1L); mpz_fdiv_q_2exp(t, t, 1L); mpz_powm(foo, a, s, p); mpz_powm(bar, b, t, p); mpz_mul(root, foo, bar); mpz_mod(root, root, p); mpz_clear(foo), mpz_clear(bar); mpz_clear(s), mpz_clear(b), mpz_clear(t); return; } } } /* error, return zero root */ mpz_set_ui(root, 0L); }
/* get value as a ui, on the assumption it fits */ static int e_mpq_get_ui_fits (mpq_srcptr q) { return mpz_get_ui (mpq_numref (q)); }
int main (int argc, char **argv) { mpz_t base, exp, mod; mpz_t r1, r2, base2; mp_size_t base_size, exp_size, mod_size; unsigned long int exp2; int i; int reps = 100; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); rands = RANDS; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (base); mpz_init (exp); mpz_init (mod); mpz_init (r1); mpz_init (r2); mpz_init (base2); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 18 + 2; do /* Loop until mathematically well-defined. */ { mpz_urandomb (bs, rands, size_range); base_size = mpz_get_ui (bs); mpz_rrandomb (base, rands, base_size); mpz_urandomb (bs, rands, 6L); exp_size = mpz_get_ui (bs); mpz_rrandomb (exp, rands, exp_size); exp2 = mpz_getlimbn (exp, (mp_size_t) 0); } while (mpz_cmp_ui (base, 0) == 0 && exp2 == 0); do { mpz_urandomb (bs, rands, size_range); mod_size = mpz_get_ui (bs); mpz_rrandomb (mod, rands, mod_size); } while (mpz_cmp_ui (mod, 0) == 0); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (base, base); /* printf ("%ld %ld\n", SIZ (base), SIZ (mod)); */ #if 0 putc ('\n', stderr); debug_mp (base, -16); debug_mp (mod, -16); #endif mpz_powm_ui (r1, base, exp2, mod); MPZ_CHECK_FORMAT (r1); mpz_set_ui (r2, 1); mpz_set (base2, base); mpz_mod (r2, r2, mod); /* needed when exp==0 and mod==1 */ while (exp2 != 0) { if (exp2 % 2 != 0) { mpz_mul (r2, r2, base2); mpz_mod (r2, r2, mod); } mpz_mul (base2, base2, base2); mpz_mod (base2, base2, mod); exp2 = exp2 / 2; } #if 0 debug_mp (r1, -16); debug_mp (r2, -16); #endif if (mpz_cmp (r1, r2) != 0) { fprintf (stderr, "\ntest %d: Incorrect results for operands:\n", i); debug_mp (base, -16); debug_mp (exp, -16); debug_mp (mod, -16); fprintf (stderr, "mpz_powm_ui result:\n"); debug_mp (r1, -16); fprintf (stderr, "reference result:\n"); debug_mp (r2, -16); abort (); } } mpz_clear (bs); mpz_clear (base); mpz_clear (exp); mpz_clear (mod); mpz_clear (r1); mpz_clear (r2); mpz_clear (base2); tests_end (); exit (0); }
void filter_SPV(uint8 parity, uint8 *sieve, uint32 poly_id, uint32 bnum, static_conf_t *sconf, dynamic_conf_t *dconf) { //we have flagged this sieve offset as likely to produce a relation //nothing left to do now but check and see. int i; uint32 bound, tmp, prime, root1, root2; int smooth_num; sieve_fb *fb; sieve_fb_compressed *fbc; tiny_fb_element_siqs *fullfb_ptr, *fullfb = sconf->factor_base->tinylist; uint8 logp, bits; uint32 tmp1, tmp2, tmp3, tmp4, offset, report_num; fullfb_ptr = fullfb; if (parity) { fb = dconf->fb_sieve_n; fbc = dconf->comp_sieve_n; } else { fb = dconf->fb_sieve_p; fbc = dconf->comp_sieve_p; } //the minimum value for the current poly_a and poly_b occur at offset (-b + sqrt(N))/a //make it slightly easier for a number to go through full trial division for //nearby blocks, since these offsets are more likely to factor over the FB. mpz_sub(dconf->gmptmp1, sconf->sqrt_n, dconf->curr_poly->mpz_poly_b); mpz_tdiv_q(dconf->gmptmp1, dconf->gmptmp1, dconf->curr_poly->mpz_poly_a); if (mpz_sgn(dconf->gmptmp1) < 0) mpz_neg(dconf->gmptmp1, dconf->gmptmp1); mpz_tdiv_q_2exp(dconf->gmptmp1, dconf->gmptmp1, sconf->qs_blockbits); if (abs(bnum - mpz_get_ui(dconf->gmptmp1)) == 0) dconf->tf_small_cutoff = sconf->tf_small_cutoff - 5; else if (abs(bnum - mpz_get_ui(dconf->gmptmp1)) == 1) dconf->tf_small_cutoff = sconf->tf_small_cutoff - 3; else dconf->tf_small_cutoff = sconf->tf_small_cutoff; #ifdef QS_TIMING gettimeofday(&qs_timing_start, NULL); #endif for (report_num = 0; report_num < dconf->num_reports; report_num++) { uint64 q64; #ifdef USE_YAFU_TDIV z32 *tmp32 = &dconf->Qvals32[report_num]; #endif //this one qualifies to check further, log that fact. dconf->num++; smooth_num = -1; //this one is close enough, compute //Q(x)/a = (ax + b)^2 - N, where x is the sieve index //Q(x)/a = (ax + 2b)x + c; offset = (bnum << sconf->qs_blockbits) + dconf->reports[report_num]; //multiple precision arithmetic. all the qstmp's are a global hack //but I don't want to Init/Free millions of times if I don't have to. mpz_mul_2exp(dconf->gmptmp2, dconf->curr_poly->mpz_poly_b, 1); mpz_mul_ui(dconf->gmptmp1, dconf->curr_poly->mpz_poly_a, offset); if (parity) mpz_sub(dconf->Qvals[report_num], dconf->gmptmp1, dconf->gmptmp2); else mpz_add(dconf->Qvals[report_num], dconf->gmptmp1, dconf->gmptmp2); mpz_mul_ui(dconf->Qvals[report_num], dconf->Qvals[report_num], offset); mpz_add(dconf->Qvals[report_num], dconf->Qvals[report_num], dconf->curr_poly->mpz_poly_c); if (mpz_sgn(dconf->Qvals[report_num]) < 0) { mpz_neg(dconf->Qvals[report_num], dconf->Qvals[report_num]); dconf->fb_offsets[report_num][++smooth_num] = 0; } //we have two signs to worry about. the sign of the offset tells us how to calculate ax + b, while //the sign of Q(x) tells us how to factor Q(x) (with or without a factor of -1) //the square root phase will need to know both. fboffset holds the sign of Q(x). the sign of the //offset is stored standalone in the relation structure. //compute the bound for small primes. if we can't find enough small //primes, then abort the trial division early because it is likely to fail to //produce even a partial relation. bits = sieve[dconf->reports[report_num]]; bits = (255 - bits) + sconf->tf_closnuf + 1; #ifdef USE_YAFU_TDIV mpz_to_z32(dconf->Qvals[report_num], tmp32); //take care of powers of two while ((tmp32->val[0] & 0x1) == 0) { zShiftRight32_x(tmp32, tmp32, 1); dconf->fb_offsets[report_num][++smooth_num] = 1; bits++; } #else //take care of powers of two while (mpz_even_p(dconf->Qvals[report_num])) { //zShiftRight32_x(Q,Q,1); mpz_tdiv_q_2exp(dconf->Qvals[report_num], dconf->Qvals[report_num], 1); dconf->fb_offsets[report_num][++smooth_num] = 1; bits++; } #endif i=2; //explicitly trial divide by small primes which we have not //been sieving. because we haven't been sieving, their progressions //have not been updated and thus we can't use the faster methods //seen below. fortunately, there shouldn't be many of these to test //to speed things up, use multiplication by inverse rather than //division, and do things in batches of 4 so we can use //the whole cache line at once (16 byte structure) //do the small primes in optimized batches of 4 bound = (sconf->sieve_small_fb_start - 4); while ((uint32)i < bound) { tmp1 = offset + fullfb_ptr->correction[i]; q64 = (uint64)tmp1 * (uint64)fullfb_ptr->small_inv[i]; tmp1 = q64 >> 32; //at this point tmp1 is offset / prime tmp1 = offset - tmp1 * fullfb_ptr->prime[i]; //now tmp1 is offset % prime i++; tmp2 = offset + fullfb_ptr->correction[i]; q64 = (uint64)tmp2 * (uint64)fullfb_ptr->small_inv[i]; tmp2 = q64 >> 32; tmp2 = offset - tmp2 * fullfb_ptr->prime[i]; i++; tmp3 = offset + fullfb_ptr->correction[i]; q64 = (uint64)tmp3 * (uint64)fullfb_ptr->small_inv[i]; tmp3 = q64 >> 32; tmp3 = offset - tmp3 * fullfb_ptr->prime[i]; i++; tmp4 = offset + fullfb_ptr->correction[i]; q64 = (uint64)tmp4 * (uint64)fullfb_ptr->small_inv[i]; tmp4 = q64 >> 32; tmp4 = offset - tmp4 * fullfb_ptr->prime[i]; i -= 3; root1 = fbc->root1[i]; root2 = fbc->root2[i]; if (tmp1 == root1 || tmp1 == root2) { prime = fbc->prime[i]; logp = fbc->logp[i]; DIVIDE_ONE_PRIME } i++; root1 = fbc->root1[i]; root2 = fbc->root2[i]; if (tmp2 == root1 || tmp2 == root2) { prime = fbc->prime[i]; logp = fbc->logp[i]; DIVIDE_ONE_PRIME } i++; root1 = fbc->root1[i]; root2 = fbc->root2[i]; if (tmp3 == root1 || tmp3 == root2) { prime = fbc->prime[i]; logp = fbc->logp[i]; DIVIDE_ONE_PRIME }
void mpq_vec_to_digest(hash_t* digest, const mpq_t* vec) { for(int i = 0; i < NUM_HASH_CHUNKS; i++){ digest->bit[i] = mpz_get_ui(mpq_numref(vec[i])); //gmp_printf("Vec->Digest %Qd %Lu\n", vec[i], digest->bit[i]); } }
int mpfi_sin (mpfi_ptr a, mpfi_srcptr b) { int inexact_left, inexact_right, inexact = 0; mp_prec_t prec, prec_left, prec_right; mpfr_t tmp; mpz_t z, zmod4; mpz_t quad_left, quad_right; int ql_mod4, qr_mod4; if (MPFI_NAN_P (b)) { mpfr_set_nan (&(a->left)); mpfr_set_nan (&(a->right)); MPFR_RET_NAN; } if (MPFI_INF_P (b)) { /* the two endpoints are the same infinite */ if ( mpfr_cmp (&(b->left), &(b->right)) == 0) { mpfr_set_nan (&(a->left)); mpfr_set_nan (&(a->right)); MPFR_RET_NAN; } mpfr_set_si (&(a->left), -1, MPFI_RNDD); mpfr_set_si (&(a->right), 1, MPFI_RNDU); return 0; } mpz_init (quad_left); mpz_init (quad_right); mpz_init (z); /* quad_left gives the quadrant where the left endpoint of b is */ /* quad_left = floor (2 b->left / pi) */ /* idem for quad_right and b->right */ prec_left = mpfi_quadrant (quad_left, &(b->left)); prec_right = mpfi_quadrant (quad_right, &(b->right)); /* if there is at least one period in b, then a = [-1, 1] */ mpz_sub (z, quad_right, quad_left); if (mpz_cmp_ui (z, 4) >= 0) { mpfr_set_si (&(a->left), -1, MPFI_RNDD); mpfr_set_si (&(a->right), 1, MPFI_RNDU); inexact = 0; } else { /* there is less than one period in b */ /* let us discuss according to the position (quadrant) of the endpoints of b */ /* computing precision = maximal precision required to determine the */ /* relative position of the endpoints of b and of integer multiples of Pi / 2 */ prec = mpfi_get_prec (a); if (prec_left > prec) prec = prec_left; if (prec_right > prec) prec = prec_right; mpz_add (z, quad_left, quad_right); /* z = quad_right + quad_left */ mpz_init (zmod4); /* qr_mod4 gives the quadrant where the right endpoint of b is */ /* qr_mod4 = floor (2 b->right / pi) mod 4 */ mpz_mod_ui (zmod4, quad_right, 4); qr_mod4 = mpz_get_ui (zmod4); /* quad_left gives the quadrant where the left endpoint of b is */ /* quad_left = floor (2 b->left / pi) mod 4 */ mpz_mod_ui (zmod4, quad_left, 4); ql_mod4 = mpz_get_ui (zmod4); switch (qr_mod4) { case 0: switch (ql_mod4) { case 0: case 3: inexact_left = mpfr_sin (&(a->left), &(b->left), MPFI_RNDD); inexact_right = mpfr_sin (&(a->right), &(b->right), MPFI_RNDU); break; case 1: mpz_add_ui (z, z, 1); if (mpfi_cmp_sym_pi (z, &(b->left), &(b->right), prec) >= 0) inexact_right = mpfr_sin (&(a->right), &(b->left), MPFI_RNDU); else inexact_right = mpfr_sin (&(a->right), &(b->right), MPFI_RNDU); inexact_left = mpfr_set_si (&(a->left), -1, MPFI_RNDD); break; case 2: inexact_left = mpfr_set_si (&(a->left), -1, MPFI_RNDD); inexact_right = mpfr_sin (&(a->right), &(b->right), MPFI_RNDU); break; } break; case 1: switch (ql_mod4) { case 0: mpz_add_ui (z, z, 1); if (mpfi_cmp_sym_pi (z, &(b->right), &(b->left), prec) >= 0) inexact_left = mpfr_sin (&(a->left), &(b->left), MPFI_RNDD); else inexact_left = mpfr_sin (&(a->left), &(b->right), MPFI_RNDD); inexact_right = mpfr_set_si (&(a->right), 1, MPFI_RNDU); break; case 1: mpfr_init2 (tmp, mpfr_get_prec (&(a->left))); inexact_left = mpfr_sin (tmp, &(b->right), MPFI_RNDD); inexact_right = mpfr_sin (&(a->right), &(b->left), MPFI_RNDU); mpfr_set (&(a->left), tmp, MPFI_RNDD); /* exact */ mpfr_clear (tmp); break; case 2: inexact_left = mpfr_set_si (&(a->left), -1, MPFI_RNDD); inexact_right = mpfr_set_si (&(a->right), 1, MPFI_RNDU); break; case 3: inexact_left = mpfr_sin (&(a->left), &(b->left), MPFI_RNDD); inexact_right = mpfr_set_si (&(a->right), 1, MPFI_RNDU); break; } break; case 2: switch (ql_mod4) { case 0: inexact_left = mpfr_sin (&(a->left), &(b->right), MPFI_RNDD); inexact_right = mpfr_set_si (&(a->right), 1, MPFI_RNDU); break; case 1: case 2: mpfr_init2 (tmp, mpfr_get_prec (&(a->left))); inexact_left = mpfr_sin (tmp, &(b->right), MPFI_RNDD); inexact_right = mpfr_sin (&(a->right), &(b->left), MPFI_RNDU); mpfr_set (&(a->left), tmp, MPFI_RNDD); /* exact */ mpfr_clear (tmp); break; case 3: mpz_add_ui (z, z, 1); if (mpfi_cmp_sym_pi (z, &(b->left), &(b->right), prec) >= 0) inexact_left = mpfr_sin (&(a->left), &(b->left), MPFI_RNDD); else inexact_left = mpfr_sin (&(a->left), &(b->right), MPFI_RNDD); inexact_right = mpfr_set_si (&(a->right), 1, MPFI_RNDU); break; } break; case 3: switch (ql_mod4) { case 0: inexact_left = mpfr_set_si (&(a->left), -1, MPFI_RNDD); inexact_right = mpfr_set_si (&(a->right), 1, MPFI_RNDU); break; case 1: inexact_right = mpfr_sin (&(a->right), &(b->left), MPFI_RNDU); inexact_left = mpfr_set_si (&(a->left), -1, MPFI_RNDD); break; case 2: mpz_add_ui (z, z, 1); if (mpfi_cmp_sym_pi (z, &(b->right), &(b->left), prec) >= 0) inexact_right = mpfr_sin (&(a->right), &(b->left), MPFI_RNDU); else inexact_right = mpfr_sin (&(a->right), &(b->right), MPFI_RNDU); inexact_left = mpfr_set_si (&(a->left), -1, MPFI_RNDD); break; case 3: inexact_left = mpfr_sin (&(a->left), &(b->left), MPFI_RNDD); inexact_right = mpfr_sin (&(a->right), &(b->right), MPFI_RNDU); break; } break; } if (inexact_left) inexact = 1; if (inexact_right) inexact += 2; mpz_clear (zmod4); } mpz_clear (quad_left); mpz_clear (quad_right); mpz_clear (z); return inexact; }
// Return a LookupData struct with relevant fields set for the given terminal // // Set lookup_data->index to -1 if no match, to match expected output of // indexInTerminalGroup, which calls this function to perform the lookup. // // NOTE: This function assumes that terminals_size_ is accurate so we can // iterate up to terminals_size_ entries from the start of the group // (terminal_data_) without anything horrible happening. Otherwise, we should // check the return values from ReadLineFromCharArray and ParseNonterminalLine // to make sure they work correctly. // // Die on failure to parse source_ids // LookupData* SeenTerminalGroup::lookup(const char *terminal) const { // just for debug output char space[1024]; char *read_buffer = space; LookupData *lookup_data = new LookupData; mpz_init(lookup_data->index); unsigned long int index = 0; unsigned long int terminalsSize = mpz_get_ui(terminals_size_); const char* current_data_position = group_data_start_; size_t bytes_remaining = group_data_size_; // Iterate over the group, looking for the input string while(index < terminalsSize) { unsigned int bytes_read; grammartools::ReadLineFromCharArray2(current_data_position, bytes_read); // Parse the line const char *read_terminal, *source_ids; double probability; // just for debug output assert(bytes_read + 1 <= 1024); strncpy(read_buffer, current_data_position, bytes_read); read_buffer[bytes_read] = 0; grammartools::ParseNonterminalLine(current_data_position, bytes_read, &read_terminal, probability, &source_ids); auto len = strlen(terminal); if ((len == strlen(read_terminal)) && (strncmp(terminal, read_terminal, len) == 0)) { lookup_data->parse_status = kCanParse; if (probability_ != probability) { fprintf(stderr, "Probability of terminal group doesn't match in line %s in " "SeenTerminalGroup::lookup (should be %f, found %f)!\n", read_buffer, probability_, probability); exit(EXIT_FAILURE); } lookup_data->probability = probability_; // index is already set correctly if (!grammartools::AddSourceIDsFromString(source_ids, lookup_data->source_ids)) { fprintf(stderr, "Could not parse source ids %s in line %s in " "SeenTerminalGroup::lookup!\n", source_ids, read_buffer); exit(EXIT_FAILURE); } mpz_set_ui(lookup_data->index, index); return lookup_data; } // Increment counters index++; current_data_position += bytes_read; bytes_remaining -= bytes_read; } // If we are here, then terminal was not found lookup_data->parse_status = kTerminalNotFound; lookup_data->probability = -1; mpz_set_si(lookup_data->index, -1); return lookup_data; }
int main(void) { int i, result; flint_rand_t state; mp_limb_t d; mpz_t d_m; printf("is_prime...."); fflush(stdout); flint_randinit(state); for (i = 0; i < 100000; i++) /* Test that primes pass the test */ { mpz_init(d_m); do { d = n_randtest(state) | 1; mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = mpz_get_ui(d_m); } while (mpz_size(d_m) > 1); result = n_is_prime(d); if (!result) { printf("FAIL:\n"); printf("d = %lu is declared composite\n", d); abort(); } mpz_clear(d_m); } for (i = 0; i < 100000; i++) /* Test that composites do not pass */ { mpz_init(d_m); do { d = n_randtest(state) | 1; if (d == 1UL) d++; mpz_set_ui(d_m, d); } while (mpz_probab_prime_p(d_m, 12)); result = !n_is_prime(d); if (!result) { printf("FAIL:\n"); printf("d = %lu is declared prime\n", d); abort(); } mpz_clear(d_m); } flint_randclear(state); printf("PASS\n"); return 0; }
int mpz_probab_prime_p (mpz_srcptr n, int reps) { mp_limb_t r; mpz_t n2; /* Handle small and negative n. */ if (mpz_cmp_ui (n, 1000000L) <= 0) { int is_prime; if (mpz_cmpabs_ui (n, 1000000L) <= 0) { is_prime = isprime (mpz_get_ui (n)); return is_prime ? 2 : 0; } /* Negative number. Negate and fall out. */ PTR(n2) = PTR(n); SIZ(n2) = -SIZ(n); n = n2; } /* If n is now even, it is not a prime. */ if ((mpz_get_ui (n) & 1) == 0) return 0; #if defined (PP) /* Check if n has small factors. */ #if defined (PP_INVERTED) r = MPN_MOD_OR_PREINV_MOD_1 (PTR(n), (mp_size_t) SIZ(n), (mp_limb_t) PP, (mp_limb_t) PP_INVERTED); #else r = mpn_mod_1 (PTR(n), (mp_size_t) SIZ(n), (mp_limb_t) PP); #endif if (r % 3 == 0 #if BITS_PER_MP_LIMB >= 4 || r % 5 == 0 #endif #if BITS_PER_MP_LIMB >= 8 || r % 7 == 0 #endif #if BITS_PER_MP_LIMB >= 16 || r % 11 == 0 || r % 13 == 0 #endif #if BITS_PER_MP_LIMB >= 32 || r % 17 == 0 || r % 19 == 0 || r % 23 == 0 || r % 29 == 0 #endif #if BITS_PER_MP_LIMB >= 64 || r % 31 == 0 || r % 37 == 0 || r % 41 == 0 || r % 43 == 0 || r % 47 == 0 || r % 53 == 0 #endif ) { return 0; } #endif /* PP */ /* Do more dividing. We collect small primes, using umul_ppmm, until we overflow a single limb. We divide our number by the small primes product, and look for factors in the remainder. */ { unsigned long int ln2; unsigned long int q; mp_limb_t p1, p0, p; unsigned int primes[15]; int nprimes; nprimes = 0; p = 1; ln2 = mpz_sizeinbase (n, 2); /* FIXME: tune this limit */ for (q = PP_FIRST_OMITTED; q < ln2; q += 2) { if (isprime (q)) { umul_ppmm (p1, p0, p, q); if (p1 != 0) { r = MPN_MOD_OR_MODEXACT_1_ODD (PTR(n), (mp_size_t) SIZ(n), p); while (--nprimes >= 0) if (r % primes[nprimes] == 0) { ASSERT_ALWAYS (mpn_mod_1 (PTR(n), (mp_size_t) SIZ(n), (mp_limb_t) primes[nprimes]) == 0); return 0; } p = q; nprimes = 0; } else { p = p0; } primes[nprimes++] = q; } } } /* Perform a number of Miller-Rabin tests. */ return mpz_millerrabin (n, reps); }
int main (int argc, char **argv) { mpz_t dividend; mpz_t quotient, remainder; mpz_t quotient2, remainder2; mpz_t temp; mp_size_t dividend_size; unsigned long divisor; int i; int reps = 10000; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; unsigned long r_rq, r_q, r_r, r; tests_start (); rands = RANDS; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (dividend); mpz_init (quotient); mpz_init (remainder); mpz_init (quotient2); mpz_init (remainder2); mpz_init (temp); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */ do { mpz_rrandomb (bs, rands, 64); divisor = mpz_get_ui (bs); } while (divisor == 0); mpz_urandomb (bs, rands, size_range); dividend_size = mpz_get_ui (bs); mpz_rrandomb (dividend, rands, dividend_size); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (dividend, dividend); /* printf ("%ld\n", SIZ (dividend)); */ r_rq = mpz_cdiv_qr_ui (quotient, remainder, dividend, divisor); r_q = mpz_cdiv_q_ui (quotient2, dividend, divisor); r_r = mpz_cdiv_r_ui (remainder2, dividend, divisor); r = mpz_cdiv_ui (dividend, divisor); /* First determine that the quotients and remainders computed with different functions are equal. */ if (mpz_cmp (quotient, quotient2) != 0) dump_abort ("quotients from mpz_cdiv_qr_ui and mpz_cdiv_q_ui differ", dividend, divisor); if (mpz_cmp (remainder, remainder2) != 0) dump_abort ("remainders from mpz_cdiv_qr_ui and mpz_cdiv_r_ui differ", dividend, divisor); /* Check if the sign of the quotient is correct. */ if (mpz_cmp_ui (quotient, 0) != 0) if ((mpz_cmp_ui (quotient, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0)) dump_abort ("quotient sign wrong", dividend, divisor); /* Check if the remainder has the opposite sign as the (positive) divisor (quotient rounded towards minus infinity). */ if (mpz_cmp_ui (remainder, 0) != 0) if (mpz_cmp_ui (remainder, 0) > 0) dump_abort ("remainder sign wrong", dividend, divisor); mpz_mul_ui (temp, quotient, divisor); mpz_add (temp, temp, remainder); if (mpz_cmp (temp, dividend) != 0) dump_abort ("n mod d != n - [n/d]*d", dividend, divisor); mpz_abs (remainder, remainder); if (mpz_cmp_ui (remainder, divisor) >= 0) dump_abort ("remainder greater than divisor", dividend, divisor); if (mpz_cmp_ui (remainder, r_rq) != 0) dump_abort ("remainder returned from mpz_cdiv_qr_ui is wrong", dividend, divisor); if (mpz_cmp_ui (remainder, r_q) != 0) dump_abort ("remainder returned from mpz_cdiv_q_ui is wrong", dividend, divisor); if (mpz_cmp_ui (remainder, r_r) != 0) dump_abort ("remainder returned from mpz_cdiv_r_ui is wrong", dividend, divisor); if (mpz_cmp_ui (remainder, r) != 0) dump_abort ("remainder returned from mpz_cdiv_ui is wrong", dividend, divisor); } mpz_clear (bs); mpz_clear (dividend); mpz_clear (quotient); mpz_clear (remainder); mpz_clear (quotient2); mpz_clear (remainder2); mpz_clear (temp); tests_end (); exit (0); }
/* assuming slaves (workers)) are all homogenous, let them all do the calculations regarding primes sieving, calculating the smoothness base and the modular roots */ int main(int argc, char **argv) { MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); MPI_Comm_size(MPI_COMM_WORLD, &mpi_group_size); int len; MPI_Get_processor_name(processor_name, &len); gettimeofday(&start_global, NULL); print_lib_version(); mpz_init(N); mpz_t B; mpz_init(B); unsigned long int uBase; int64_t nb_primes; modular_root_t *modular_roots; uint64_t i, j; if (argc < 2) { PRINT(my_rank, "usage: %s Number_to_factorize\n", argv[0]); exit(2); } if (mpz_init_set_str(N, argv[1], 10) == -1) { PRINT(my_rank, "Cannot load N %s\n", argv[1]); exit(2); } mpz_t sqrtN, rem; mpz_init(sqrtN); mpz_init(rem); mpz_sqrtrem(sqrtN, rem, N); if (mpz_cmp_ui(rem, 0) != 0) /* if not perfect square, calculate the ceiling */ mpz_add_ui(sqrtN, sqrtN, 1); else /* N is a perfect square, factored! */ { PRINT(my_rank, "\n<<<[FACTOR]>>> %s\n", mpz_get_str(NULL, 10, sqrtN)); return 0; } if (mpz_probab_prime_p(N, 10) > 0) /* don't bother factoring */ { PRINT(my_rank, "N:%s is prime\n", mpz_get_str(NULL, 10, N)); exit(0); } OPEN_LOG_FILE("freq"); //-------------------------------------------------------- // calculate the smoothness base for the given N //-------------------------------------------------------- get_smoothness_base(B, N); /* if N is too small, the program will surely fail, please consider a pen and paper instead */ uBase = mpz_get_ui(B); PRINT(my_rank, "n: %s\tBase: %s\n", mpz_get_str(NULL, 10, N), mpz_get_str(NULL, 10, B)); //-------------------------------------------------------- // sieve primes that are less than the smoothness base using Eratosthenes sieve //-------------------------------------------------------- START_TIMER(); nb_primes = sieve_primes_up_to((int64_t) (uBase)); PRINT(my_rank, "\tPrimes found %" PRId64 " [Smoothness Base %lu]\n", nb_primes, uBase); STOP_TIMER_PRINT_TIME("\tEratosthenes Sieving done"); //-------------------------------------------------------- // fill the primes array with primes to which n is a quadratic residue //-------------------------------------------------------- START_TIMER(); primes = calloc(nb_primes, sizeof(int64_t)); nb_qr_primes = fill_primes_with_quadratic_residue(primes, N); /*for(i=0; i<nb_qr_primes; i++) PRINT(my_rank, "%" PRId64 "\n", primes[i]);*/ PRINT(my_rank, "\tN-Quadratic primes found %" PRId64 "\n", nb_qr_primes); STOP_TIMER_PRINT_TIME("\tQuadratic prime filtering done"); //-------------------------------------------------------- // calculate modular roots //-------------------------------------------------------- START_TIMER(); modular_roots = calloc(nb_qr_primes, sizeof(modular_root_t)); mpz_t tmp, r1, r2; mpz_init(tmp); mpz_init(r1); mpz_init(r2); for (i = 0; i < nb_qr_primes; i++) { mpz_set_ui(tmp, (unsigned long) primes[i]); mpz_sqrtm(r1, N, tmp); /* calculate the modular root */ mpz_neg(r2, r1); /* -q mod n */ mpz_mod(r2, r2, tmp); modular_roots[i].root1 = mpz_get_ui(r1); modular_roots[i].root2 = mpz_get_ui(r2); } mpz_clear(tmp); mpz_clear(r1); mpz_clear(r2); STOP_TIMER_PRINT_TIME("Modular roots calculation done"); //-------------------------------------------------------- // ***** initialize the matrix ***** //-------------------------------------------------------- if (my_rank == 0) /* only the master have the matrix */ { START_TIMER(); init_matrix(&matrix, nb_qr_primes + NB_VECTORS_OFFSET, nb_qr_primes); mpz_init2(tmp_matrix_row, nb_qr_primes); STOP_TIMER_PRINT_TIME("Matrix initialized"); } //-------------------------------------------------------- // [Sieving] - everyones sieves including the master //-------------------------------------------------------- START_TIMER(); mpz_t x, sieving_index, next_sieving_index, relative_start, global_step; unsigned long ui_index, SIEVING_STEP = 50000; /* we sieve for 50000 elements at each loop */ int LOCAL_SIEVING_ROUNDS = 10; /* number of iterations a worker sieves before communicating results to the master */ unsigned long sieving_round = 0; unsigned long nb_big_rounds = 0; uint64_t p_pow; smooth_number_t *x_squared; x_squared = calloc(SIEVING_STEP, sizeof(smooth_number_t)); if (my_rank == 0) smooth_numbers = calloc(nb_qr_primes + NB_VECTORS_OFFSET, sizeof(smooth_number_t)); else temp_slaves_smooth_numbers = calloc(500, sizeof(smooth_number_t)); /* TODO: this is not properly correct, using a linkedlist is better to keep track of temporary * smooth numbers at the slaves nodes however it's pretty rare to find 500 smooth numbers in * 50000 * 10 interval. */ mpz_init_set(x, sqrtN); mpz_init(global_step); mpz_init(relative_start); mpz_init(sieving_index); mpz_init(next_sieving_index); mpz_t p; mpz_init(p); mpz_t str; mpz_init_set(str, sieving_index); PRINT(my_rank, "\n[%s] Sieving ...\n", processor_name); //-------------------------------------------------------- // Init before sieving //-------------------------------------------------------- for (i = 0; i < SIEVING_STEP; i++) { mpz_init(x_squared[i].value_x); mpz_init(x_squared[i].value_x_squared); mpz_init2(x_squared[i].factors_vect, nb_qr_primes); mpz_add_ui(x, x, 1); } int nb_smooth_per_round = 0; char s[512]; //-------------------------------------------------------- // WHILE smooth numbers found less than the primes in the smooth base + NB_VECTORS_OFFSET for master // Or master asked for more smooth numbers from slaves //-------------------------------------------------------- while (1) { mpz_set_ui(global_step, nb_big_rounds); /* calculates the coordinate where the workers start sieving from */ mpz_mul_ui(global_step, global_step, (unsigned long) mpi_group_size); mpz_mul_ui(global_step, global_step, SIEVING_STEP); mpz_mul_ui(global_step, global_step, LOCAL_SIEVING_ROUNDS); mpz_add(global_step, global_step, sqrtN); mpz_set_ui(relative_start, SIEVING_STEP); mpz_mul_ui(relative_start, relative_start, LOCAL_SIEVING_ROUNDS); mpz_mul_ui(relative_start, relative_start, (unsigned long) my_rank); mpz_add(relative_start, relative_start, global_step); mpz_set(sieving_index, relative_start); mpz_set(next_sieving_index, relative_start); for (sieving_round = 0; sieving_round < LOCAL_SIEVING_ROUNDS; /* each slave sieves for LOCAL_SIEVING_ROUNDS rounds */ sieving_round++) { nb_smooth_per_round = 0; mpz_set(x, next_sieving_index); /* sieve numbers from sieving_index to sieving_index + sieving_step */ mpz_set(sieving_index, next_sieving_index); if (my_rank == 0) { printf("\r"); printf( "\t\tSieving at: %s30 <--> Smooth numbers found: %" PRId64 "/%" PRId64 "", mpz_get_str(NULL, 10, sieving_index), nb_global_smooth_numbers_found, nb_qr_primes); fflush(stdout); } for (i = 0; i < SIEVING_STEP; i++) { mpz_set(x_squared[i].value_x, x); mpz_pow_ui(x_squared[i].value_x_squared, x, 2); /* calculate value_x_squared <- x²-n */ mpz_sub(x_squared[i].value_x_squared, x_squared[i].value_x_squared, N); mpz_clear(x_squared[i].factors_vect); mpz_init2(x_squared[i].factors_vect, nb_qr_primes); /* reconstruct a new fresh 0ed vector of size nb_qr_primes bits */ mpz_add_ui(x, x, 1); } mpz_set(next_sieving_index, x); //-------------------------------------------------------- // eliminate factors in the x_squared array, those who are 'destructed' to 1 are smooth //-------------------------------------------------------- for (i = 0; i < nb_qr_primes; i++) { mpz_set_ui(p, (unsigned long) primes[i]); mpz_set(x, sieving_index); /* get the first multiple of p that is directly larger that sieving_index * Quadratic SIEVING: all elements from this number and in positions multiples of root1 and root2 * are also multiples of p */ get_sieving_start_index(x, x, p, modular_roots[i].root1); mpz_set(str, x); mpz_sub(x, x, sieving_index); /* x contains index of first number that is divisible by p */ for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) { p_pow = mpz_remove(x_squared[j].value_x_squared, x_squared[j].value_x_squared, p); /* eliminate all factors of p */ if (p_pow & 1) /* mark bit if odd power of p exists in this x_squared[j] */ { mpz_setbit(x_squared[j].factors_vect, i); } if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) { save_smooth_number(x_squared[j]); nb_smooth_per_round++; } /* sieve next element located p steps from here */ } /* same goes for root2 */ if (modular_roots[i].root2 == modular_roots[i].root1) continue; mpz_set(x, sieving_index); get_sieving_start_index(x, x, p, modular_roots[i].root2); mpz_set(str, x); mpz_sub(x, x, sieving_index); for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) { p_pow = mpz_remove(x_squared[j].value_x_squared, x_squared[j].value_x_squared, p); if (p_pow & 1) { mpz_setbit(x_squared[j].factors_vect, i); } if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) { save_smooth_number(x_squared[j]); nb_smooth_per_round++; } } } } if (my_rank == 0) /* master gathers smooth numbers from slaves */ { gather_smooth_numbers(); notify_slaves(); } else /* slaves send their smooth numbers to master */ { send_smooth_numbers_to_master(); nb_global_smooth_numbers_found = get_server_notification(); } if (nb_global_smooth_numbers_found >= nb_qr_primes + NB_VECTORS_OFFSET) break; nb_big_rounds++; } STOP_TIMER_PRINT_TIME("\nSieving DONE"); if (my_rank == 0) { uint64_t t = 0; //-------------------------------------------------------- //the matrix ready, start Gauss elimination. The Matrix is filled on the call of save_smooth_number() //-------------------------------------------------------- START_TIMER(); gauss_elimination(&matrix); STOP_TIMER_PRINT_TIME("\nGauss elimination done"); uint64_t row_index = nb_qr_primes + NB_VECTORS_OFFSET - 1; /* last row in the matrix */ int nb_linear_relations = 0; mpz_t linear_relation_z, solution_z; mpz_init(linear_relation_z); mpz_init(solution_z); get_matrix_row(linear_relation_z, &matrix, row_index--); /* get the last few rows in the Gauss eliminated matrix*/ while (mpz_cmp_ui(linear_relation_z, 0) == 0) { nb_linear_relations++; get_matrix_row(linear_relation_z, &matrix, row_index--); } PRINT(my_rank, "\tLinear dependent relations found : %d\n", nb_linear_relations); //-------------------------------------------------------- // Factor //-------------------------------------------------------- //We use the last linear relation to reconstruct our solution START_TIMER(); PRINT(my_rank, "%s", "\nFactorizing..\n"); mpz_t solution_X, solution_Y; mpz_init(solution_X); mpz_init(solution_Y); /* we start testing from the first linear relation encountered in the matrix */ for (j = nb_linear_relations; j > 0; j--) { PRINT(my_rank, "Trying %d..\n", nb_linear_relations - j + 1); mpz_set_ui(solution_X, 1); mpz_set_ui(solution_Y, 1); get_identity_row(solution_z, &matrix, nb_qr_primes + NB_VECTORS_OFFSET - j + 1); for (i = 0; i < nb_qr_primes; i++) { if (mpz_tstbit(solution_z, i)) { mpz_mul(solution_X, solution_X, smooth_numbers[i].value_x); mpz_mod(solution_X, solution_X, N); /* reduce x to modulo N */ mpz_mul(solution_Y, solution_Y, smooth_numbers[i].value_x_squared); /*TODO: handling huge stuff here, there is no modulo N like in the solution_X case! * eliminate squares as long as you go*/ } } mpz_sqrt(solution_Y, solution_Y); mpz_mod(solution_Y, solution_Y, N); /* y = sqrt(MUL(xi²-n)) mod N */ mpz_sub(solution_X, solution_X, solution_Y); mpz_gcd(solution_X, solution_X, N); if (mpz_cmp(solution_X, N) != 0 && mpz_cmp_ui(solution_X, 1) != 0) /* factor can be 1 or N, try another relation */ break; } mpz_cdiv_q(solution_Y, N, solution_X); PRINT(my_rank, "\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N)); PRINT( my_rank, "\tFactor 1: %s \n\tFactor 2: %s", mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y)); sprintf(s, "\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N)); APPEND_TO_LOG_FILE(s); sprintf(s, "\tFactor 1: %s \n\tFactor 2: %s", mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y)); APPEND_TO_LOG_FILE(s); gettimeofday(&end_global, NULL); timersub(&end_global, &start_global, &elapsed); sprintf(s, "****** TOTAL TIME: %.3f ms\n", elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000); APPEND_TO_LOG_FILE(s); STOP_TIMER_PRINT_TIME("\nFactorizing done"); } PRINT(my_rank, "%s", "\nCleaning memory..\n"); /********************** clear the x_squared array **********************/ for (i = 0; i < SIEVING_STEP; i++) { mpz_clear(x_squared[i].value_x); mpz_clear(x_squared[i].value_x_squared); //free(x_squared[i].factors_exp); mpz_clear(x_squared[i].factors_vect); } free(x_squared); /********************** clear the x_squared array **********************/ free(modular_roots); /********************** clear the smooth_numbers array **********************/ if (my_rank == 0) { for (i = 0; i < nb_qr_primes + NB_VECTORS_OFFSET; i++) { mpz_clear(smooth_numbers[i].value_x); mpz_clear(smooth_numbers[i].value_x_squared); mpz_clear(smooth_numbers[i].factors_vect); //free(smooth_numbers[i].factors_exp); } free(smooth_numbers); } else { for (i = 0; i < 500; i++) { mpz_clear(temp_slaves_smooth_numbers[i].value_x); mpz_clear(temp_slaves_smooth_numbers[i].value_x_squared); mpz_clear(temp_slaves_smooth_numbers[i].factors_vect); } free(temp_slaves_smooth_numbers); } /********************** clear the smooth_numbers array **********************/ free(primes); /********************** clear mpz _t **********************/mpz_clear(B); mpz_clear(N); sqrtN, rem; mpz_clear(x); mpz_clear(sieving_index); mpz_clear(next_sieving_index); mpz_clear(p); mpz_clear(str); /********************** clear mpz _t **********************/ free_matrix(&matrix); gettimeofday(&end_global, NULL); timersub(&end_global, &start_global, &elapsed); PRINT(my_rank, "****** TOTAL TIME: %.3f ms\n", elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000); show_mem_usage(); MPI_Finalize(); return 0; }
int main(void) { int i, result; flint_rand_t state; printf("is_oddprime_binary...."); fflush(stdout); flint_randinit(state); n_compute_primes(10000); for (i = 0; i < 100000; i++) /* Test that primes pass the test */ { mp_limb_t d; mpz_t d_m; mpz_init(d_m); do { d = n_randint(state, flint_primes_cutoff) | 1; if (d == 1UL) d += 2; mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = mpz_get_ui(d_m); } while (d > flint_primes_cutoff); result = n_is_oddprime_binary(d); if (!result) { printf("FAIL:\n"); printf("d = %lu is declared composite\n", d); abort(); } mpz_clear(d_m); } for (i = 0; i < 100000; i++) /* Test that not too many composites pass */ { mp_limb_t d; mpz_t d_m; mpz_init(d_m); do { d = n_randint(state, flint_primes_cutoff) | 1; mpz_set_ui(d_m, d); } while ((mpz_probab_prime_p(d_m, 12)) || (d > flint_primes_cutoff)); result = !n_is_oddprime_binary(d); if (!result) { printf("FAIL:\n"); printf("d = %lu is declared prime\n", d); abort(); } mpz_clear(d_m); } flint_randclear(state); printf("PASS\n"); return 0; }
void check_all (mpz_ptr want, mpz_srcptr x_orig, mpz_srcptr y_orig) { mpz_t got, x, y; int negx, negy, swap, inplace; mpz_init (got); mpz_init_set (x, x_orig); mpz_init_set (y, y_orig); for (swap = 0; swap < 2; swap++) { mpz_swap (x, y); for (negx = 0; negx < 2; negx++) { mpz_neg (x, x); for (negy = 0; negy < 2; negy++) { mpz_neg (y, y); for (inplace = 0; inplace <= 1; inplace++) { if (inplace) { mpz_set (got, x); mpz_lcm (got, got, y); } else mpz_lcm (got, x, y); MPZ_CHECK_FORMAT (got); if (mpz_cmp (got, want) != 0) { printf ("mpz_lcm wrong, inplace=%d\n", inplace); fail: mpz_trace ("x", x); mpz_trace ("y", y); mpz_trace ("got", got); mpz_trace ("want", want); abort (); } if (mpz_fits_ulong_p (y)) { unsigned long yu = mpz_get_ui (y); if (inplace) { mpz_set (got, x); mpz_lcm_ui (got, got, yu); } else mpz_lcm_ui (got, x, yu); if (mpz_cmp (got, want) != 0) { printf ("mpz_lcm_ui wrong, inplace=%d\n", inplace); printf ("yu=%lu\n", yu); goto fail; } } } } } } mpz_clear (got); mpz_clear (x); mpz_clear (y); }
int main (int argc, char *argv[]) { char *progname = argv[0]; mpz_t fr, to; mpz_t fr2, to2; unsigned long sieve_lim; unsigned long est_n_primes; unsigned char *s; mpz_t tmp; mpz_t siev_sqr_lim; while (argc != 1) { if (strcmp (argv[1], "-c") == 0) { flag_count = 1; argv++; argc--; } else if (strcmp (argv[1], "-p") == 0) { flag_print = 2; argv++; argc--; } else if (strcmp (argv[1], "-g") == 0) { flag_maxgap = 1; argv++; argc--; } else break; } if (flag_count || flag_maxgap) flag_print--; /* clear unless an explicit -p */ mpz_init (fr); mpz_init (to); mpz_init (fr2); mpz_init (to2); if (argc == 3) { mpz_set_str (fr, argv[1], 0); if (argv[2][0] == '+') { mpz_set_str (to, argv[2] + 1, 0); mpz_add (to, to, fr); } else mpz_set_str (to, argv[2], 0); } else if (argc == 2) { mpz_set_ui (fr, 0); mpz_set_str (to, argv[1], 0); } else { fprintf (stderr, "usage: %s [-c] [-p] [-g] [from [+]]to\n", progname); exit (1); } mpz_set (fr2, fr); if (mpz_cmp_ui (fr2, 3) < 0) { mpz_set_ui (fr2, 2); report (fr2); mpz_set_ui (fr2, 3); } mpz_setbit (fr2, 0); /* make odd */ mpz_sub_ui (to2, to, 1); mpz_setbit (to2, 0); /* make odd */ mpz_init (tmp); mpz_init (siev_sqr_lim); mpz_sqrt (tmp, to2); #define SIEVE_LIMIT 10000000 if (mpz_cmp_ui (tmp, SIEVE_LIMIT) < 0) { sieve_lim = mpz_get_ui (tmp); } else { sieve_lim = SIEVE_LIMIT; mpz_sub (tmp, to2, fr2); if (mpz_cmp_ui (tmp, sieve_lim) < 0) sieve_lim = mpz_get_ui (tmp); /* limit sieving for small ranges */ } mpz_set_ui (siev_sqr_lim, sieve_lim + 1); mpz_mul_ui (siev_sqr_lim, siev_sqr_lim, sieve_lim + 1); est_n_primes = (size_t) (sieve_lim / log((double) sieve_lim) * 1.13) + 10; primes = malloc (est_n_primes * sizeof primes[0]); make_primelist (sieve_lim); assert (est_n_primes >= n_primes); #if DEBUG printf ("sieve_lim = %lu\n", sieve_lim); printf ("n_primes = %lu (3..%u)\n", n_primes, primes[n_primes - 1].prime); #endif #define S (1 << 15) /* FIXME: Figure out L1 cache size */ s = malloc (S/2); while (mpz_cmp (fr2, to2) <= 0) { unsigned long rsize; rsize = S; mpz_add_ui (tmp, fr2, rsize); if (mpz_cmp (tmp, to2) > 0) { mpz_sub (tmp, to2, fr2); rsize = mpz_get_ui (tmp) + 2; } #if DEBUG printf ("Sieving region ["); mpz_out_str (stdout, 10, fr2); printf (","); mpz_add_ui (tmp, fr2, rsize - 2); mpz_out_str (stdout, 10, tmp); printf ("]\n"); #endif sieve_region (s, fr2, rsize); find_primes (s, fr2, rsize / 2, siev_sqr_lim); mpz_add_ui (fr2, fr2, S); } free (s); if (flag_count) printf ("Pi(interval) = %lu\n", total_primes); if (flag_maxgap) printf ("max gap: %lu\n", maxgap); return 0; }
int main (int argc, char **argv) { mpz_t x2; mpz_t x, rem; mpz_t temp, temp2; mp_size_t x2_size; int i; int reps = 20000; gmp_randstate_t rands; mpz_t bs; unsigned long size_range; tests_start (); gmp_randinit_default(rands); mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (x2); mpz_init (x); mpz_init (rem); mpz_init (temp); mpz_init (temp2); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 12 + 2; /* 0..8191 bit operands */ mpz_urandomb (bs, rands, size_range); x2_size = mpz_get_ui (bs); mpz_rrandomb (x2, rands, x2_size); /* printf ("%ld\n", SIZ (x2)); */ mpz_sqrtrem (x, rem, x2); mpz_mul (temp, x, x); /* Is square of result > argument? */ if (mpz_cmp (temp, x2) > 0) dump_abort (x2, x, rem); mpz_add_ui (temp2, x, 1); mpz_mul (temp2, temp2, temp2); /* Is square of (result + 1) <= argument? */ if (mpz_cmp (temp2, x2) <= 0) dump_abort (x2, x, rem); mpz_add (temp2, temp, rem); /* Is the remainder wrong? */ if (mpz_cmp (x2, temp2) != 0) dump_abort (x2, x, rem); } mpz_clear (bs); mpz_clear (x2); mpz_clear (x); mpz_clear (rem); mpz_clear (temp); mpz_clear (temp2); gmp_randclear(rands); tests_end (); exit (0); }
int main (int argc, char **argv) { mpz_t op1, op2; mpz_t prod, quot; mp_size_t size; int i; int reps = 20000; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); rands = RANDS; mp_trace_base = -16; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (op1); mpz_init (op2); mpz_init (prod); mpz_init (quot); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */ mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (op1, rands, size); do { mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (op2, rands, size); } while (mpz_sgn (op2) == 0); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (op1, op1); if ((bsi & 2) != 0) mpz_neg (op2, op2); mpz_mul (prod, op1, op2); mpz_divexact (quot, prod, op2); MPZ_CHECK_FORMAT (quot); if (mpz_cmp (quot, op1) != 0) { printf ("Wrong results:\n"); mpz_trace (" got ", quot); mpz_trace (" want ", op1); mpz_trace (" dividend", prod); mpz_trace (" divisor ", op2); abort (); } } mpz_clear (bs); mpz_clear (op1); mpz_clear (op2); mpz_clear (prod); mpz_clear (quot); tests_end (); exit (0); }
int main(long argc, char *argv[]) { if(argc != 4) { printf("Three arguments required\n"); printf("Usage: test6 a b c calculates pi(a*b^c)\n"); exit(1); } //Legacy GMP code below; the input must fit in a 64 bit unsigned integer mpz_t n; mpz_init(n); mpz_ui_pow_ui(n,atol(argv[2]), atol(argv[3])); mpz_mul_ui(n, n, atol(argv[1])); uint64_t n2 = mpz_get_ui(n); uint64_t* s = malloc((n2/64+3)*sizeof(uint64_t)); assert(s != NULL); //for wheel mod 6 uint64_t word1 = 0x28A28A28A28A28A2; uint64_t word2 = 0xA28A28A28A28A28A; uint64_t word3 = 0x8A28A28A28A28A28; uint64_t k; for(k=0; k <= n2/64; k+=3) { s[k]=word1; s[k+1]=word2; s[k+2]=word3; } uint64_t sieve_to=floor(sqrt(n2)); uint64_t i,j; i=5; //5 is the first number which is relatively prime to 6 int next = 4; //If i%6 = 5 then add 2 to i; if i%6 = 1 then add 4 to i; while (i<=sieve_to) { next = 6 - next; //Alternate jumps of 2 and 4 to move through all the numbers congruent to +/- 1 mod 6 if(TEST(s,i)!=0) //Only sieve by primes { for(j=i*i; j<=n2; j+= 6*i) CLEAR(s,j); //since i*i is always 1 (mod 6), this sieves out all the multiples of i congruent to 1 (mod 6) for(j=i*(i + next); j<=n2; j+= 6*i) CLEAR(s,j); //i*(i+next) is the first multiple of i which exceeds i*i and is congruent to -1 (mod 6) } i += next; //Advance pointer to the next number which is congruent to +/- 1 } s[0] &= (~0 - 0xF); //Remove sieve entries for numbers less than 5; s[0] += 0xC; //Put in the correct entries; 2 and 3 are prime, 1100b = 4d + 8d = 12d = 0xC #if 0 for(i=0; i<=n2; i++) if(TEST(s,i)>0) printf("%" PRIu64 "\n",i); #endif //Note ridiculous macro format required to print unit64_t without generating a compiler warning printf("%" PRIu64 "\n", count_bits(s,0,n2)); return(0); }
static PyObject * GMPy_Integer_Pow(PyObject *b, PyObject *e, PyObject *m, CTXT_Object *context) { MPZ_Object *result = NULL, *tempb = NULL, *tempe = NULL, *tempm = NULL; int has_mod; /* Try to parse the modulus value first. */ if (m == Py_None) { has_mod = 0; } else { has_mod = 1; if (!IS_INTEGER(m)) { Py_RETURN_NOTIMPLEMENTED; } else { if (!(tempm = GMPy_MPZ_From_Integer(m, context))) { goto err; } } } result = GMPy_MPZ_New(context); tempb = GMPy_MPZ_From_Integer(b, context); tempe = GMPy_MPZ_From_Integer(e, context); if (!tempb || !tempe || !result) { goto err; } if (!has_mod) { /* When no modulo is present, the exponent must fit in unsigned long. */ unsigned long el; if (mpz_sgn(tempe->z) < 0) { VALUE_ERROR("pow() exponent cannot be negative"); goto err; } if (!mpz_fits_ulong_p(tempe->z)) { VALUE_ERROR("pow() outrageous exponent"); goto err; } el = mpz_get_ui(tempe->z); mpz_pow_ui(result->z, tempb->z, el); } else { /* Modulo is present. */ int sign; mpz_t mm, base, exp; sign = mpz_sgn(tempm->z); if (sign == 0) { VALUE_ERROR("pow() 3rd argument cannot be 0"); goto err; } mpz_inoc(mm); mpz_abs(mm, tempm->z); /* A negative exponent is allowed if inverse exists. */ if (mpz_sgn(tempe->z) < 0) { mpz_inoc(base); mpz_inoc(exp); if (!mpz_invert(base, tempb->z, mm)) { VALUE_ERROR("pow() base not invertible"); mpz_cloc(base); mpz_cloc(exp); mpz_cloc(mm); goto err; } else { mpz_abs(exp, tempe->z); } mpz_powm(result->z, base, exp, mm); mpz_cloc(base); mpz_cloc(exp); } else { mpz_powm(result->z, tempb->z, tempe->z, mm); } mpz_cloc(mm); /* Python uses a rather peculiar convention for negative modulos * If the modulo is negative, result should be in the interval * m < r <= 0 . */ if ((sign < 0) && (mpz_sgn(MPZ(result)) > 0)) { mpz_add(result->z, result->z, tempm->z); } } Py_XDECREF((PyObject*)tempb); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempm); return (PyObject*)result; err: Py_XDECREF((PyObject*)tempb); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempm); Py_DECREF((PyObject*)result); return NULL; }
num_t num_int_part_sel(pseltype_t op_type, num_t hi, num_t lo, num_t a) { num_t r, m; unsigned long mask_shl, lo_ui; r = num_new_z(N_TEMP, NULL); m = num_new_z(N_TEMP, NULL); a = num_new_z(N_TEMP, a); hi = num_new_z(N_TEMP, hi); if (lo != NULL) lo = num_new_z(N_TEMP, lo); switch (op_type) { case PSEL_SINGLE: lo = num_new_z(N_TEMP, hi); break; case PSEL_FRANGE: break; case PSEL_DRANGE: if (mpz_cmp_si(Z(lo), 0L) < 0) { yyxerror("low index of part select operation must be " "positive"); return NULL; } mpz_sub_ui(Z(lo), Z(lo), 1UL); mpz_sub(Z(lo), Z(hi), Z(lo)); break; } if (mpz_cmp_si(Z(hi), 0L) < 0) { yyxerror("high index of part select operation must be " "positive"); return NULL; } if (mpz_cmp_si(Z(lo), 0L) < 0) { yyxerror("low index of part select operation must be " "positive"); return NULL; } if (!mpz_fits_ulong_p(Z(hi))) { yyxerror("high index of part select operation needs to fit " "into an unsigned long C datatype"); return NULL; } if (!mpz_fits_ulong_p(Z(lo))) { yyxerror("low index of part select operation needs to fit " "into an unsigned long C datatype"); return NULL; } lo_ui = mpz_get_ui(Z(lo)); mask_shl = 1 + (mpz_get_ui(Z(hi)) - lo_ui); /* * We do the part sel by: * (1) shifting right by 'lo' * (2) anding with ((1 << mask_shl)-1) */ mpz_div_2exp(Z(r), Z(a), lo_ui); mpz_set_ui(Z(m), 1UL); mpz_mul_2exp(Z(m), Z(m), mask_shl); mpz_sub_ui(Z(m), Z(m), 1UL); mpz_and(Z(r), Z(r), Z(m)); return r; }
int main (int argc, char **argv) { mpz_t dividend, divisor; mpz_t quotient, remainder; mpz_t quotient2, remainder2; mpz_t temp; mp_size_t dividend_size, divisor_size; int i; int reps = 1000; gmp_randstate_t rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); special_tests(); gmp_randinit_default(rands); mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (dividend); mpz_init (divisor); mpz_init (quotient); mpz_init (remainder); mpz_init (quotient2); mpz_init (remainder2); mpz_init (temp); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 16 + 2; /* 0..131071 bit operands */ do { mpz_urandomb (bs, rands, size_range); divisor_size = mpz_get_ui (bs); mpz_rrandomb (divisor, rands, divisor_size); } while (mpz_sgn (divisor) == 0); mpz_urandomb (bs, rands, size_range); dividend_size = mpz_get_ui (bs) + divisor_size; mpz_rrandomb (dividend, rands, dividend_size); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (dividend, dividend); if ((bsi & 2) != 0) mpz_neg (divisor, divisor); /* printf ("%ld %ld\n", SIZ (dividend), SIZ (divisor)); */ mpz_tdiv_qr (quotient, remainder, dividend, divisor); mpz_tdiv_q (quotient2, dividend, divisor); mpz_tdiv_r (remainder2, dividend, divisor); /* First determine that the quotients and remainders computed with different functions are equal. */ if (mpz_cmp (quotient, quotient2) != 0) dump_abort (dividend, divisor); if (mpz_cmp (remainder, remainder2) != 0) dump_abort (dividend, divisor); /* Check if the sign of the quotient is correct. */ if (mpz_cmp_ui (quotient, 0) != 0) if ((mpz_cmp_ui (quotient, 0) < 0) != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0)) dump_abort (dividend, divisor); /* Check if the remainder has the same sign as the dividend (quotient rounded towards 0). */ if (mpz_cmp_ui (remainder, 0) != 0) if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0)) dump_abort (dividend, divisor); mpz_mul (temp, quotient, divisor); mpz_add (temp, temp, remainder); if (mpz_cmp (temp, dividend) != 0) dump_abort (dividend, divisor); mpz_abs (temp, divisor); mpz_abs (remainder, remainder); if (mpz_cmp (remainder, temp) >= 0) dump_abort (dividend, divisor); } mpz_clear (bs); mpz_clear (dividend); mpz_clear (divisor); mpz_clear (quotient); mpz_clear (remainder); mpz_clear (quotient2); mpz_clear (remainder2); mpz_clear (temp); gmp_randclear(rands); tests_end (); exit (0); }
void check_random (int argc, char *argv[]) { gmp_randstate_ptr rands = RANDS; mpz_t a, c, d, ra, rc; int i; int want; int reps = 10000; mpz_t bs; unsigned long size_range, size; if (argc >= 2) reps = atoi (argv[1]); mpz_init (bs); mpz_init (a); mpz_init (c); mpz_init (d); mpz_init (ra); mpz_init (rc); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 16 + 1; /* 0..65536 bit operands */ mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (a, rands, size); mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 16 + 1; /* 0..65536 bit operands */ mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (c, rands, size); do { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 16 + 1; /* 0..65536 bit operands */ mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (d, rands, size); } while (SIZ(d) == 0); mpz_negrandom (a, rands); MPZ_CHECK_FORMAT (a); mpz_negrandom (c, rands); MPZ_CHECK_FORMAT (c); mpz_negrandom (d, rands); mpz_fdiv_r (ra, a, d); mpz_fdiv_r (rc, c, d); want = (mpz_cmp (ra, rc) == 0); check_one (a, c, d, want); mpz_sub (ra, ra, rc); mpz_sub (a, a, ra); MPZ_CHECK_FORMAT (a); check_one (a, c, d, 1); if (! mpz_pow2abs_p (d)) { refmpz_combit (a, urandom() % (8*GMP_LIMB_BITS)); check_one (a, c, d, 0); } } mpz_clear (bs); mpz_clear (a); mpz_clear (c); mpz_clear (d); mpz_clear (ra); mpz_clear (rc); }
static bool bp_script_eval(parr *stack, const cstring *script, const struct bp_tx *txTo, unsigned int nIn, unsigned int flags, int nHashType) { struct const_buffer pc = { script->str, script->len }; struct const_buffer pend = { script->str + script->len, 0 }; struct const_buffer pbegincodehash = { script->str, script->len }; struct bscript_op op; bool rc = false; cstring *vfExec = cstr_new(NULL); parr *altstack = parr_new(0, buffer_freep); mpz_t bn, bn_Zero, bn_One; mpz_init(bn); mpz_init_set_ui(bn_Zero, 0); mpz_init_set_ui(bn_One,1); if (script->len > MAX_SCRIPT_SIZE) goto out; unsigned int nOpCount = 0; bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; struct bscript_parser bp; bsp_start(&bp, &pc); while (pc.p < pend.p) { bool fExec = !count_false(vfExec); if (!bsp_getop(&op, &bp)) goto out; enum opcodetype opcode = op.op; if (op.data.len > MAX_SCRIPT_ELEMENT_SIZE) goto out; if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) goto out; if (disabled_op[opcode]) goto out; if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) { if (fRequireMinimal && !CheckMinimalPush(&op.data, opcode)) goto out; stack_push(stack, (struct buffer *) &op.data); } else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) { // // Push value // case OP_1NEGATE: case OP_1: case OP_2: case OP_3: case OP_4: case OP_5: case OP_6: case OP_7: case OP_8: case OP_9: case OP_10: case OP_11: case OP_12: case OP_13: case OP_14: case OP_15: case OP_16: mpz_set_si(bn, (int)opcode - (int)(OP_1 - 1)); stack_push_str(stack, bn_getvch(bn)); break; // // Control // case OP_NOP: break; case OP_CHECKLOCKTIMEVERIFY: { if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) { // not enabled; treat as a NOP2 if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) goto out; break; } if (stack->len < 1) goto out; // Note that elsewhere numeric opcodes are limited to // operands in the range -2**31+1 to 2**31-1, however it is // legal for opcodes to produce results exceeding that // range. This limitation is implemented by CastToBigNum's // default 4-byte limit. // // If we kept to that limit we'd have a year 2038 problem, // even though the nLockTime field in transactions // themselves is uint32 which only becomes meaningless // after the year 2106. // // Thus as a special case we tell CastToBigNum to accept up // to 5-byte bignums, which are good until 2**39-1, well // beyond the 2**32-1 limit of the nLockTime field itself. if (!CastToBigNum(bn, stacktop(stack, -1), fRequireMinimal, 5)) goto out; // In the rare event that the argument may be < 0 due to // some arithmetic being done first, you can always use // 0 MAX CHECKLOCKTIMEVERIFY. if (mpz_sgn(bn) < 0) goto out; uint64_t nLockTime = mpz_get_ui(bn); // Actually compare the specified lock time with the transaction. if (!CheckLockTime(nLockTime, txTo, nIn)) goto out; break; } case OP_CHECKSEQUENCEVERIFY: { if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) { // not enabled; treat as a NOP3 if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) goto out; break; } if (stack->len < 1) goto out; // nSequence, like nLockTime, is a 32-bit unsigned integer // field. See the comment in CHECKLOCKTIMEVERIFY regarding // 5-byte numeric operands. if (!CastToBigNum(bn, stacktop(stack, -1), fRequireMinimal, 5)) goto out; // In the rare event that the argument may be < 0 due to // some arithmetic being done first, you can always use // 0 MAX CHECKSEQUENCEVERIFY. if (mpz_sgn(bn) < 0) goto out; uint32_t nSequence = mpz_get_ui(bn); // To provide for future soft-fork extensibility, if the // operand has the disabled lock-time flag set, // CHECKSEQUENCEVERIFY behaves as a NOP. if ((nSequence & SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0) break; // Compare the specified sequence number with the input. if (!CheckSequence(nSequence, txTo, nIn)) goto out; break; } case OP_NOP1: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) goto out; break; case OP_IF: case OP_NOTIF: { // <expression> if [statements] [else [statements]] endif bool fValue = false; if (fExec) { if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; popstack(stack); } uint8_t vc = (uint8_t) fValue; cstr_append_c(vfExec, vc); break; } case OP_ELSE: { if (vfExec->len == 0) goto out; uint8_t *v = (uint8_t *) &vfExec->str[vfExec->len - 1]; *v = !(*v); break; } case OP_ENDIF: if (vfExec->len == 0) goto out; cstr_erase(vfExec, vfExec->len - 1, 1); break; case OP_VERIFY: { if (stack->len < 1) goto out; bool fValue = CastToBool(stacktop(stack, -1)); if (fValue) popstack(stack); else goto out; break; } case OP_RETURN: goto out; // // Stack ops // case OP_TOALTSTACK: if (stack->len < 1) goto out; stack_push(altstack, stacktop(stack, -1)); popstack(stack); break; case OP_FROMALTSTACK: if (altstack->len < 1) goto out; stack_push(stack, stacktop(altstack, -1)); popstack(altstack); break; case OP_2DROP: // (x1 x2 -- ) if (stack->len < 2) goto out; popstack(stack); popstack(stack); break; case OP_2DUP: { // (x1 x2 -- x1 x2 x1 x2) if (stack->len < 2) goto out; struct buffer *vch1 = stacktop(stack, -2); struct buffer *vch2 = stacktop(stack, -1); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_3DUP: { // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) if (stack->len < 3) goto out; struct buffer *vch1 = stacktop(stack, -3); struct buffer *vch2 = stacktop(stack, -2); struct buffer *vch3 = stacktop(stack, -1); stack_push(stack, vch1); stack_push(stack, vch2); stack_push(stack, vch3); break; } case OP_2OVER: { // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) if (stack->len < 4) goto out; struct buffer *vch1 = stacktop(stack, -4); struct buffer *vch2 = stacktop(stack, -3); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_2ROT: { // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) if (stack->len < 6) goto out; struct buffer *vch1 = stack_take(stack, -6); struct buffer *vch2 = stack_take(stack, -5); parr_remove_range(stack, stack->len - 6, 2); stack_push_nocopy(stack, vch1); stack_push_nocopy(stack, vch2); break; } case OP_2SWAP: // (x1 x2 x3 x4 -- x3 x4 x1 x2) if (stack->len < 4) goto out; stack_swap(stack, -4, -2); stack_swap(stack, -3, -1); break; case OP_IFDUP: { // (x - 0 | x x) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); if (CastToBool(vch)) stack_push(stack, vch); break; } case OP_DEPTH: // -- stacksize mpz_set_ui(bn, stack->len); stack_push_str(stack, bn_getvch(bn)); break; case OP_DROP: // (x -- ) if (stack->len < 1) goto out; popstack(stack); break; case OP_DUP: { // (x -- x x) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); stack_push(stack, vch); break; } case OP_NIP: // (x1 x2 -- x2) if (stack->len < 2) goto out; parr_remove_idx(stack, stack->len - 2); break; case OP_OVER: { // (x1 x2 -- x1 x2 x1) if (stack->len < 2) goto out; struct buffer *vch = stacktop(stack, -2); stack_push(stack, vch); break; } case OP_PICK: case OP_ROLL: { // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack->len < 2) goto out; int n = stackint(stack, -1, fRequireMinimal); popstack(stack); if (n < 0 || n >= (int)stack->len) goto out; struct buffer *vch = stacktop(stack, -n-1); if (opcode == OP_ROLL) { vch = buffer_copy(vch->p, vch->len); parr_remove_idx(stack, stack->len - n - 1); stack_push_nocopy(stack, vch); } else stack_push(stack, vch); break; } case OP_ROT: { // (x1 x2 x3 -- x2 x3 x1) // x2 x1 x3 after first swap // x2 x3 x1 after second swap if (stack->len < 3) goto out; stack_swap(stack, -3, -2); stack_swap(stack, -2, -1); break; } case OP_SWAP: { // (x1 x2 -- x2 x1) if (stack->len < 2) goto out; stack_swap(stack, -2, -1); break; } case OP_TUCK: { // (x1 x2 -- x2 x1 x2) if (stack->len < 2) goto out; struct buffer *vch = stacktop(stack, -1); stack_insert(stack, vch, -2); break; } case OP_SIZE: { // (in -- in size) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); mpz_set_ui(bn, vch->len); stack_push_str(stack, bn_getvch(bn)); break; } case OP_EQUAL: case OP_EQUALVERIFY: { // (x1 x2 - bool) if (stack->len < 2) goto out; struct buffer *vch1 = stacktop(stack, -2); struct buffer *vch2 = stacktop(stack, -1); bool fEqual = buffer_equal(vch1, vch2); // OP_NOTEQUAL is disabled because it would be too easy to say // something like n != 1 and have some wiseguy pass in 1 with extra // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) //if (opcode == OP_NOTEQUAL) // fEqual = !fEqual; popstack(stack); popstack(stack); stack_push_str(stack, fEqual ? bn_getvch(bn_One) : bn_getvch(bn_Zero)); if (opcode == OP_EQUALVERIFY) { if (fEqual) popstack(stack); else goto out; } break; } // // Numeric // case OP_1ADD: case OP_1SUB: case OP_NEGATE: case OP_ABS: case OP_NOT: case OP_0NOTEQUAL: { // (in -- out) if (stack->len < 1) goto out; if (!CastToBigNum(bn, stacktop(stack, -1), fRequireMinimal, nDefaultMaxNumSize)) goto out; switch (opcode) { case OP_1ADD: mpz_add_ui(bn, bn, 1); break; case OP_1SUB: mpz_sub_ui(bn, bn, 1); break; case OP_NEGATE: mpz_neg(bn, bn); break; case OP_ABS: mpz_abs(bn, bn); break; case OP_NOT: mpz_set_ui(bn, mpz_sgn(bn) == 0 ? 1 : 0); break; case OP_0NOTEQUAL: mpz_set_ui(bn, mpz_sgn(bn) == 0 ? 0 : 1); break; default: // impossible goto out; } popstack(stack); stack_push_str(stack, bn_getvch(bn)); break; } case OP_ADD: case OP_SUB: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: case OP_NUMNOTEQUAL: case OP_LESSTHAN: case OP_GREATERTHAN: case OP_LESSTHANOREQUAL: case OP_GREATERTHANOREQUAL: case OP_MIN: case OP_MAX: { // (x1 x2 -- out) if (stack->len < 2) goto out; mpz_t bn1, bn2; mpz_init(bn1); mpz_init(bn2); if (!CastToBigNum(bn1, stacktop(stack, -2), fRequireMinimal, nDefaultMaxNumSize) || !CastToBigNum(bn2, stacktop(stack, -1), fRequireMinimal, nDefaultMaxNumSize)) { mpz_clear(bn1); mpz_clear(bn2); goto out; } switch (opcode) { case OP_ADD: mpz_add(bn, bn1, bn2); break; case OP_SUB: mpz_sub(bn, bn1, bn2); break; case OP_BOOLAND: mpz_set_ui(bn, !(mpz_sgn(bn1) == 0) && !(mpz_sgn(bn2) == 0) ? 1 : 0); break; case OP_BOOLOR: mpz_set_ui(bn, !(mpz_sgn(bn1) == 0) || !(mpz_sgn(bn2) == 0) ? 1 : 0); break; case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: mpz_set_ui(bn, mpz_cmp(bn1, bn2) == 0 ? 1 : 0); break; case OP_NUMNOTEQUAL: mpz_set_ui(bn, mpz_cmp(bn1, bn2) != 0 ? 1 : 0); break; case OP_LESSTHAN: mpz_set_ui(bn, mpz_cmp(bn1, bn2) < 0 ? 1 : 0); break; case OP_GREATERTHAN: mpz_set_ui(bn, mpz_cmp(bn1, bn2) > 0 ? 1 : 0); break; case OP_LESSTHANOREQUAL: mpz_set_ui(bn, mpz_cmp(bn1, bn2) <= 0 ? 1 : 0); break; case OP_GREATERTHANOREQUAL: mpz_set_ui(bn, mpz_cmp(bn1, bn2) >= 0 ? 1 : 0); break; case OP_MIN: if (mpz_cmp(bn1, bn2) < 0) mpz_set(bn, bn1); else mpz_set(bn, bn2); break; case OP_MAX: if (mpz_cmp(bn1, bn2) > 0) mpz_set(bn, bn1); else mpz_set(bn, bn2); break; default: // impossible break; } popstack(stack); popstack(stack); stack_push_str(stack, bn_getvch(bn)); mpz_clear(bn1); mpz_clear(bn2); if (opcode == OP_NUMEQUALVERIFY) { if (CastToBool(stacktop(stack, -1))) popstack(stack); else goto out; } break; } case OP_WITHIN: { // (x min max -- out) if (stack->len < 3) goto out; mpz_t bn1, bn2, bn3; mpz_init(bn1); mpz_init(bn2); mpz_init(bn3); bool rc1 = CastToBigNum(bn1, stacktop(stack, -3), fRequireMinimal, nDefaultMaxNumSize); bool rc2 = CastToBigNum(bn2, stacktop(stack, -2), fRequireMinimal, nDefaultMaxNumSize); bool rc3 = CastToBigNum(bn3, stacktop(stack, -1), fRequireMinimal, nDefaultMaxNumSize); bool fValue = (mpz_cmp(bn2, bn1) <= 0 && mpz_cmp(bn1, bn3) < 0); popstack(stack); popstack(stack); popstack(stack); stack_push_str(stack, fValue ? bn_getvch(bn_One) : bn_getvch(bn_Zero)); mpz_clear(bn1); mpz_clear(bn2); mpz_clear(bn3); if (!rc1 || !rc2 || !rc3) goto out; break; } // // Crypto // case OP_RIPEMD160: case OP_SHA1: case OP_SHA256: case OP_HASH160: case OP_HASH256: { // (in -- hash) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); unsigned int hashlen; unsigned char md[32]; switch (opcode) { case OP_RIPEMD160: hashlen = 20; ripemd160(vch->p, vch->len, md); break; case OP_SHA1: hashlen = 20; sha1_Raw(vch->p, vch->len, md); break; case OP_SHA256: hashlen = 32; sha256_Raw(vch->p, vch->len, md); break; case OP_HASH160: hashlen = 20; bu_Hash160(md, vch->p, vch->len); break; case OP_HASH256: hashlen = 32; bu_Hash(md, vch->p, vch->len); break; default: // impossible goto out; } popstack(stack); struct buffer buf = { md, hashlen }; stack_push(stack, &buf); break; } case OP_CODESEPARATOR: // Hash starts after the code separator memcpy(&pbegincodehash, &pc, sizeof(pc)); break; case OP_CHECKSIG: case OP_CHECKSIGVERIFY: { // (sig pubkey -- bool) if (stack->len < 2) goto out; struct buffer *vchSig = stacktop(stack, -2); struct buffer *vchPubKey = stacktop(stack, -1); // Subset of script starting at the most recent codeseparator cstring *scriptCode = cstr_new_buf(pbegincodehash.p, pbegincodehash.len); // Drop the signature, since there's no way for // a signature to sign itself string_find_del(scriptCode, vchSig); if (!CheckSignatureEncoding(vchSig, flags) || !CheckPubKeyEncoding(vchPubKey, flags)) { cstr_free(scriptCode, true); goto out; } bool fSuccess = bp_checksig(vchSig, vchPubKey, scriptCode, txTo, nIn); cstr_free(scriptCode, true); popstack(stack); popstack(stack); stack_push_str(stack, fSuccess ? bn_getvch(bn_One) : bn_getvch(bn_Zero)); if (opcode == OP_CHECKSIGVERIFY) { if (fSuccess) popstack(stack); else goto out; } break; } case OP_CHECKMULTISIG: case OP_CHECKMULTISIGVERIFY: { // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) int i = 1; if ((int)stack->len < i) goto out; int nKeysCount = stackint(stack, -i, fRequireMinimal); if (nKeysCount < 0 || nKeysCount > MAX_PUBKEYS_PER_MULTISIG) goto out; nOpCount += nKeysCount; if (nOpCount > MAX_OPS_PER_SCRIPT) goto out; int ikey = ++i; i += nKeysCount; if ((int)stack->len < i) goto out; int nSigsCount = stackint(stack, -i, fRequireMinimal); if (nSigsCount < 0 || nSigsCount > nKeysCount) goto out; int isig = ++i; i += nSigsCount; if ((int)stack->len < i) goto out; // Subset of script starting at the most recent codeseparator cstring *scriptCode = cstr_new_buf(pbegincodehash.p, pbegincodehash.len); // Drop the signatures, since there's no way for // a signature to sign itself int k; for (k = 0; k < nSigsCount; k++) { struct buffer *vchSig =stacktop(stack, -isig-k); string_find_del(scriptCode, vchSig); } bool fSuccess = true; while (fSuccess && nSigsCount > 0) { struct buffer *vchSig = stacktop(stack, -isig); struct buffer *vchPubKey = stacktop(stack, -ikey); // Note how this makes the exact order of pubkey/signature evaluation // distinguishable by CHECKMULTISIG NOT if the STRICTENC flag is set. // See the script_(in)valid tests for details. if (!CheckSignatureEncoding(vchSig, flags) || !CheckPubKeyEncoding(vchPubKey, flags)) { cstr_free(scriptCode, true); goto out; } // Check signature bool fOk = bp_checksig(vchSig, vchPubKey, scriptCode, txTo, nIn); if (fOk) { isig++; nSigsCount--; } ikey++; nKeysCount--; // If there are more signatures left than keys left, // then too many signatures have failed if (nSigsCount > nKeysCount) fSuccess = false; } cstr_free(scriptCode, true); // Clean up stack of actual arguments while (i-- > 1) popstack(stack); // A bug causes CHECKMULTISIG to consume one extra argument // whose contents were not checked in any way. // // Unfortunately this is a potential source of mutability, // so optionally verify it is exactly equal to zero prior // to removing it from the stack. if ((int)stack->len < 1) goto out; if ((flags & SCRIPT_VERIFY_NULLDUMMY) && stacktop(stack, -1)->len) goto out; popstack(stack); stack_push_str(stack, fSuccess ? bn_getvch(bn_One) : bn_getvch(bn_Zero)); if (opcode == OP_CHECKMULTISIGVERIFY) { if (fSuccess) popstack(stack); else goto out; } break; } default: goto out; } // Size limits if (stack->len + altstack->len > 1000) goto out; } rc = (vfExec->len == 0 && bp.error == false); out: mpz_clears(bn, bn_Zero, bn_One, NULL); parr_free(altstack, true); cstr_free(vfExec, true); return rc; }
int main (int argc, char **argv) { gmp_randstate_ptr rands; unsigned long maxnbits, maxdbits, nbits, dbits; mpz_t n, d, tz; mp_size_t maxnn, maxdn, nn, dn, clearn, i; mp_ptr np, dp, qp, rp; mp_limb_t rh; mp_limb_t t; mp_limb_t dinv; int count = COUNT; mp_ptr scratch; mp_limb_t ran; mp_size_t alloc, itch; mp_limb_t rran0, rran1, qran0, qran1; TMP_DECL; if (argc > 1) { char *end; count = strtol (argv[1], &end, 0); if (*end || count <= 0) { fprintf (stderr, "Invalid test count: %s.\n", argv[1]); return 1; } } maxdbits = MAX_DN; maxnbits = MAX_NN; tests_start (); rands = RANDS; mpz_init (n); mpz_init (d); mpz_init (tz); maxnn = maxnbits / GMP_NUMB_BITS + 1; maxdn = maxdbits / GMP_NUMB_BITS + 1; TMP_MARK; qp = TMP_ALLOC_LIMBS (maxnn + 2) + 1; rp = TMP_ALLOC_LIMBS (maxnn + 2) + 1; alloc = 1; scratch = __GMP_ALLOCATE_FUNC_LIMBS (alloc); for (test = 0; test < count;) { nbits = random_word (rands) % (maxnbits - GMP_NUMB_BITS) + 2 * GMP_NUMB_BITS; if (maxdbits > nbits) dbits = random_word (rands) % nbits + 1; else dbits = random_word (rands) % maxdbits + 1; #if RAND_UNIFORM #define RANDFUNC mpz_urandomb #else #define RANDFUNC mpz_rrandomb #endif do { RANDFUNC (n, rands, nbits); do { RANDFUNC (d, rands, dbits); } while (mpz_sgn (d) == 0); np = PTR (n); dp = PTR (d); nn = SIZ (n); dn = SIZ (d); } while (nn < dn); dp[0] |= 1; mpz_urandomb (tz, rands, 32); t = mpz_get_ui (tz); if (t % 17 == 0) dp[0] = GMP_NUMB_MAX; switch ((int) t % 16) { case 0: clearn = random_word (rands) % nn; for (i = 0; i <= clearn; i++) np[i] = 0; break; case 1: mpn_sub_1 (np + nn - dn, dp, dn, random_word (rands)); break; case 2: mpn_add_1 (np + nn - dn, dp, dn, random_word (rands)); break; } test++; binvert_limb (dinv, dp[0]); rran0 = random_word (rands); rran1 = random_word (rands); qran0 = random_word (rands); qran1 = random_word (rands); qp[-1] = qran0; qp[nn - dn + 1] = qran1; rp[-1] = rran0; ran = random_word (rands); if ((double) (nn - dn) * dn < 1e5) { if (nn > dn) { /* Test mpn_sbpi1_bdiv_qr */ MPN_ZERO (qp, nn - dn); MPN_ZERO (rp, dn); MPN_COPY (rp, np, nn); rh = mpn_sbpi1_bdiv_qr (qp, rp, nn, dp, dn, -dinv); ASSERT_ALWAYS (qp[-1] == qran0); ASSERT_ALWAYS (qp[nn - dn + 1] == qran1); ASSERT_ALWAYS (rp[-1] == rran0); check_one (qp, rp + nn - dn, rh, np, nn, dp, dn, "mpn_sbpi1_bdiv_qr"); } if (nn > dn) { /* Test mpn_sbpi1_bdiv_q */ MPN_COPY (rp, np, nn); MPN_ZERO (qp, nn - dn); mpn_sbpi1_bdiv_q (qp, rp, nn - dn, dp, MIN(dn,nn-dn), -dinv); ASSERT_ALWAYS (qp[-1] == qran0); ASSERT_ALWAYS (qp[nn - dn + 1] == qran1); ASSERT_ALWAYS (rp[-1] == rran0); check_one (qp, NULL, 0, np, nn, dp, dn, "mpn_sbpi1_bdiv_q"); } } if (dn >= 4 && nn - dn >= 2) { /* Test mpn_dcpi1_bdiv_qr */ MPN_COPY (rp, np, nn); MPN_ZERO (qp, nn - dn); rh = mpn_dcpi1_bdiv_qr (qp, rp, nn, dp, dn, -dinv); ASSERT_ALWAYS (qp[-1] == qran0); ASSERT_ALWAYS (qp[nn - dn + 1] == qran1); ASSERT_ALWAYS (rp[-1] == rran0); check_one (qp, rp + nn - dn, rh, np, nn, dp, dn, "mpn_dcpi1_bdiv_qr"); } if (dn >= 4 && nn - dn >= 2) { /* Test mpn_dcpi1_bdiv_q */ MPN_COPY (rp, np, nn); MPN_ZERO (qp, nn - dn); mpn_dcpi1_bdiv_q (qp, rp, nn - dn, dp, MIN(dn,nn-dn), -dinv); ASSERT_ALWAYS (qp[-1] == qran0); ASSERT_ALWAYS (qp[nn - dn + 1] == qran1); ASSERT_ALWAYS (rp[-1] == rran0); check_one (qp, NULL, 0, np, nn, dp, dn, "mpn_dcpi1_bdiv_q"); } if (nn > dn) { /* Test mpn_bdiv_qr */ itch = mpn_bdiv_qr_itch (nn, dn); if (itch + 1 > alloc) { scratch = __GMP_REALLOCATE_FUNC_LIMBS (scratch, alloc, itch + 1); alloc = itch + 1; } scratch[itch] = ran; MPN_ZERO (qp, nn - dn); MPN_ZERO (rp, dn); rp[dn] = rran1; rh = mpn_bdiv_qr (qp, rp, np, nn, dp, dn, scratch); ASSERT_ALWAYS (ran == scratch[itch]); ASSERT_ALWAYS (qp[-1] == qran0); ASSERT_ALWAYS (qp[nn - dn + 1] == qran1); ASSERT_ALWAYS (rp[-1] == rran0); ASSERT_ALWAYS (rp[dn] == rran1); check_one (qp, rp, rh, np, nn, dp, dn, "mpn_bdiv_qr"); } if (nn - dn < 2 || dn < 2) continue; /* Test mpn_mu_bdiv_qr */ itch = mpn_mu_bdiv_qr_itch (nn, dn); if (itch + 1 > alloc) { scratch = __GMP_REALLOCATE_FUNC_LIMBS (scratch, alloc, itch + 1); alloc = itch + 1; } scratch[itch] = ran; MPN_ZERO (qp, nn - dn); MPN_ZERO (rp, dn); rp[dn] = rran1; rh = mpn_mu_bdiv_qr (qp, rp, np, nn, dp, dn, scratch); ASSERT_ALWAYS (ran == scratch[itch]); ASSERT_ALWAYS (qp[-1] == qran0); ASSERT_ALWAYS (qp[nn - dn + 1] == qran1); ASSERT_ALWAYS (rp[-1] == rran0); ASSERT_ALWAYS (rp[dn] == rran1); check_one (qp, rp, rh, np, nn, dp, dn, "mpn_mu_bdiv_qr"); /* Test mpn_mu_bdiv_q */ itch = mpn_mu_bdiv_q_itch (nn, dn); if (itch + 1 > alloc) { scratch = __GMP_REALLOCATE_FUNC_LIMBS (scratch, alloc, itch + 1); alloc = itch + 1; } scratch[itch] = ran; MPN_ZERO (qp, nn - dn + 1); mpn_mu_bdiv_q (qp, np, nn - dn, dp, dn, scratch); ASSERT_ALWAYS (ran == scratch[itch]); ASSERT_ALWAYS (qp[-1] == qran0); ASSERT_ALWAYS (qp[nn - dn + 1] == qran1); check_one (qp, NULL, 0, np, nn, dp, dn, "mpn_mu_bdiv_q"); } __GMP_FREE_FUNC_LIMBS (scratch, alloc); TMP_FREE; mpz_clear (n); mpz_clear (d); mpz_clear (tz); tests_end (); return 0; }
int main (int argc, char **argv) { mpz_t op1, op2; mp_size_t size; int i; int reps = 10000; FILE *fp; int base, base_out; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; size_t nread; tests_start (); rands = RANDS; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (op1); mpz_init (op2); fp = fopen (FILENAME, "w+"); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 10 + 2; mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (op1, rands, size); mpz_urandomb (bs, rands, 1); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (op1, op1); mpz_urandomb (bs, rands, 16); bsi = mpz_get_ui (bs); base = bsi % 62 + 1; if (base == 1) base = 0; if (i % 2 == 0 && base <= 36) base_out = -base; else base_out = base; rewind (fp); if (mpz_out_str (fp, base_out, op1) == 0 || putc (' ', fp) == EOF || fflush (fp) != 0) { printf ("mpz_out_str write error\n"); abort (); } rewind (fp); nread = mpz_inp_str (op2, fp, base); if (nread == 0) { if (ferror (fp)) printf ("mpz_inp_str stream read error\n"); else printf ("mpz_inp_str data conversion error\n"); abort (); } if (nread != ftell(fp)) { printf ("mpz_inp_str nread doesn't match ftell\n"); printf (" nread %lu\n", (unsigned long) nread); printf (" ftell %ld\n", ftell(fp)); abort (); } if (mpz_cmp (op1, op2)) { printf ("ERROR\n"); printf ("op1 = "); debug_mp (op1, -16); printf ("op2 = "); debug_mp (op2, -16); printf ("base = %d\n", base); abort (); } } fclose (fp); unlink (FILENAME); mpz_clear (bs); mpz_clear (op1); mpz_clear (op2); tests_end (); exit (0); }
static unsigned long get_int(void *a) { LTC_ARGCHK(a != NULL); return mpz_get_ui(a); }
u32_t* mpz_trialdiv(mpz_t N,u32_t*pbuf,u32_t ncp,char*errmsg) { u32_t np,np1,i,e2,nlimb; if(mpz_sgn(N)<=0){ if(mpz_sgn(N)==0)return pbuf; mpz_neg(N,N); } if(mibuf_alloc<ncp){ if(mibuf_alloc> 0)free(mibuf); mibuf_alloc= ncp; mibuf= xmalloc(mibuf_alloc*sizeof(*mibuf)); } e2= 0; while((mpz_get_ui(N)%2)==0){ mpz_fdiv_q_2exp(N,N,1); e2++; } nlimb= N[0]._mp_size; if(lbuf_alloc<nlimb){ if(lbuf_alloc> 0)free(lbuf); lbuf_alloc= nlimb; lbuf= xmalloc(lbuf_alloc*sizeof(*lbuf)); } memcpy(lbuf,N[0]._mp_d,nlimb*sizeof(*lbuf)); np= 0; for(i= 0;i<ncp;i++){ mp_limb_t x,p,r; p= pbuf[i]; x= mpqs_256_inv_table[(p&255)/2]; x= 2*x-p*x*x; x= 2*x-p*x*x; x= 2*x-p*x*x; r= mpz_asm_td(p,x,lbuf,nlimb); if(r!=0){ if(errmsg!=NULL) Schlendrian("%s : %u does not divide\n",errmsg,pbuf[i]); memcpy(lbuf,N[0]._mp_d,nlimb*sizeof(*lbuf)); continue; } while(lbuf[nlimb-1]==0)nlimb--; if(errmsg==NULL)memcpy(N[0]._mp_d,lbuf,nlimb*sizeof(*lbuf)); mibuf[np]= x; pbuf[np++]= p; } np1= np; if(errmsg!=NULL)memcpy(N[0]._mp_d,lbuf,nlimb*sizeof(*lbuf)); for(i= 0;i<np1;i++){ mp_limb_t x,p,r; p= pbuf[i]; x= mibuf[i]; for(;;){ r= mpz_asm_td(p,x,lbuf,nlimb); if(r!=0){ memcpy(lbuf,N[0]._mp_d,nlimb*sizeof(*lbuf)); break; } while(lbuf[nlimb-1]==0)nlimb--; memcpy(N[0]._mp_d,lbuf,nlimb*sizeof(*lbuf)); pbuf[np++]= p; } } N[0]._mp_size= nlimb; for(i= 0;i<e2;i++) pbuf[np++]= 2; return pbuf+np; }/*:1*/
/* Find primes in region [fr,fr+rsize). Requires that fr is odd and that rsize is even. The sieving array s should be aligned for "long int" and have rsize/2 entries, rounded up to the nearest multiple of "long int". */ void sieve_region (unsigned char *s, mpz_t fr, unsigned long rsize) { unsigned long ssize = rsize / 2; unsigned long start, start2, prime; unsigned long i; mpz_t tmp; mpz_init (tmp); #if 0 /* initialize sieving array */ for (ii = 0; ii < (ssize + sizeof (long) - 1) / sizeof (long); ii++) ((long *) s) [ii] = ~0L; #else { signed long k; long *se = (long *) (s + ((ssize + sizeof (long) - 1) & -sizeof (long))); for (k = -((ssize + sizeof (long) - 1) / sizeof (long)); k < 0; k++) se[k] = ~0L; } #endif for (i = 0; i < n_primes; i++) { prime = primes[i].prime; if (primes[i].rem >= 0) { start2 = primes[i].rem; } else { mpz_set_ui (tmp, prime); mpz_mul_ui (tmp, tmp, prime); if (mpz_cmp (fr, tmp) <= 0) { mpz_sub (tmp, tmp, fr); if (mpz_cmp_ui (tmp, 2 * ssize) > 0) break; /* avoid overflow at next line, also speedup */ start = mpz_get_ui (tmp); } else { start = (prime - mpz_tdiv_ui (fr, prime)) % prime; if (start % 2 != 0) start += prime; /* adjust if even divisable */ } start2 = start / 2; } #if 0 for (ii = start2; ii < ssize; ii += prime) s[ii] = 0; primes[i].rem = ii - ssize; #else { signed long k; unsigned char *se = s + ssize; /* point just beyond sieving range */ for (k = start2 - ssize; k < 0; k += prime) se[k] = 0; primes[i].rem = k; } #endif } mpz_clear (tmp); }
int ecpp_test(unsigned long n) { mpz_t a, b, x0, y0, xt, yt, tmp; int z; int is_prime = 0; if (n <= USHRT_MAX) { return sieve_test(n); } mpz_init(a); mpz_init(b); mpz_init(x0); mpz_init(y0); mpz_init(xt); mpz_init(yt); mpz_init(tmp); #ifdef DEBUG gmp_fprintf(stderr, "\nTesting %d with ECPP...\n", n); #endif /* DEBUG */ for (;;) /* keep trying while the curve order factoring fails */ { for (;;) /* keep trying while n divides curve discriminant */ { /* initialise a random point P = (x0, y0) * and a random elliptic curve E(a, b): y^2 = x^3 + a*x + b * with b expressed in terms of (a, x0, y0) so the point lies on the curve */ mpz_set_ui(a, rand() % n); mpz_set_ui(x0, rand() % n); mpz_set_ui(y0, rand() % n); mpz_init(b); mpz_mul(b, y0, y0); mpz_mul(tmp, x0, x0); mpz_submul(b, tmp, x0); mpz_submul(b, a, x0); mpz_mod_ui(b, b, n); #ifdef DEBUG gmp_fprintf(stderr, "\n\tn = %d\n", n); gmp_fprintf(stderr, "\tE: y^2 = x^3 + %Zd * x + %Zd\n", a, b); gmp_fprintf(stderr, "\tP = (%Zd,%Zd,1)\n", x0, y0); #endif /* DEBUG */ /* the discriminant of the curve and n are required to be coprimes * -- if not, then either * A) n divides the discriminant -- a new curve must be generated * B) n is composite and a proper factor is found -- the algorithm can * terminate */ ec_discriminant(tmp, a, b); #ifdef DEBUG mpz_mod_ui(tmp, tmp, n); gmp_fprintf(stderr, "\tdelta(E/GF(n)) = %Zd\n", tmp); #endif /* DEBUG */ mpz_gcd_ui(tmp, tmp, n); #ifdef DEBUG gmp_fprintf(stderr, "\tgcd(delta, n) = %Zd\n", tmp); #endif /* DEBUG */ if (0 == mpz_cmp_ui(tmp, 1)) { break; } else if (0 != mpz_cmp_ui(tmp, n)) { #ifdef DEBUG gmp_fprintf(stderr, "\tfound a proper factor, %d is composite\n", n); #endif /* DEBUG */ is_prime = 0; goto cleanup_and_return; } } /* P + P != 0, or a new curve is generated */ z = ec_add(xt, yt, x0, y0, 1, x0, y0, 1, n, a); #ifdef DEBUG gmp_fprintf(stderr, "\t2 * P = (%Zd,%Zd,%d)\n", xt, yt, z); #endif /* DEBUG */ if (0 == z) { continue; } /* the curve order algorithm failing indicates n is composite */ if (!(ec_order(tmp, a, b, n))) { #ifdef DEBUG gmp_fprintf(stderr, "\tcurve order algorithm failed, %d must be composite\n", n); #endif /* DEBUG */ is_prime = 0; break; } #ifdef DEBUG gmp_fprintf(stderr, "\t|E/GF(n)| = %Zd\n", tmp); #endif /* DEBUG */ /* the curve order should be the multiple of 2 and a "probable prime" n -- * if the order is not even, a new curve is generated */ if (!mpz_even_p(tmp)) { #ifdef DEBUG gmp_fprintf(stderr, "\t|E/GF(n)| is odd, generating new curve...\n"); #endif /* DEBUG */ continue; } /* order * P = 0, or n is composite */ z = ec_times(xt, yt, x0, y0, 1, tmp, n, a); #ifdef DEBUG gmp_fprintf(stderr, "\t|E| * P = (%Zd,%Zd,%d)\n", xt, yt, z); #endif /* DEBUG */ if (0 != z) { #ifdef DEBUG gmp_fprintf(stderr, "\t|E| * P is non-zero, %d is composite\n", n); #endif /* DEBUG */ is_prime = 0; break; } /* at this point, order/2 being a prime implies n is a prime -- * a recursive call to ecpp_test is used to test order/2 for primality */ mpz_div_ui(tmp, tmp, 2); if (ecpp_test(mpz_get_ui(tmp))) { is_prime = 1; break; } } cleanup_and_return: mpz_clear(a); mpz_clear(b); mpz_clear(x0); mpz_clear(y0); mpz_clear(xt); mpz_clear(yt); mpz_clear(tmp); return is_prime; }
void one_test (mpz_t op1, mpz_t op2, mpz_t ref, int i) { /* printf ("%ld %ld %ld\n", SIZ (op1), SIZ (op2), SIZ (ref)); fflush (stdout); */ /* fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); */ mpz_gcdext (gcd1, s, NULL, op1, op2); if (ref && mpz_cmp (ref, gcd1) != 0) { fprintf (stderr, "ERROR in test %d\n", i); fprintf (stderr, "mpz_gcdext returned incorrect result\n"); fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); fprintf (stderr, "expected result:\n"); debug_mp (ref, -16); fprintf (stderr, "mpz_gcdext returns:\n");debug_mp (gcd1, -16); abort (); } if (!gcdext_valid_p(op1, op2, gcd1, s)) { fprintf (stderr, "ERROR in test %d\n", i); fprintf (stderr, "mpz_gcdext returned invalid result\n"); fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); fprintf (stderr, "mpz_gcdext returns:\n");debug_mp (gcd1, -16); abort (); } mpz_gcd (gcd2, op1, op2); if (mpz_cmp (gcd2, gcd1) != 0) { fprintf (stderr, "ERROR in test %d\n", i); fprintf (stderr, "mpz_gcd returned incorrect result\n"); fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); fprintf (stderr, "expected result:\n"); debug_mp (gcd1, -16); fprintf (stderr, "mpz_gcd returns:\n"); debug_mp (gcd2, -16); abort (); } /* This should probably move to t-gcd_ui.c */ if (mpz_fits_ulong_p (op1) || mpz_fits_ulong_p (op2)) { if (mpz_fits_ulong_p (op1)) mpz_gcd_ui (gcd2, op2, mpz_get_ui (op1)); else mpz_gcd_ui (gcd2, op1, mpz_get_ui (op2)); if (mpz_cmp (gcd2, gcd1)) { fprintf (stderr, "ERROR in test %d\n", i); fprintf (stderr, "mpz_gcd_ui returned incorrect result\n"); fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); fprintf (stderr, "expected result:\n"); debug_mp (gcd1, -16); fprintf (stderr, "mpz_gcd_ui returns:\n"); debug_mp (gcd2, -16); abort (); } } mpz_gcdext (gcd2, temp1, temp2, op1, op2); mpz_mul (temp1, temp1, op1); mpz_mul (temp2, temp2, op2); mpz_add (temp1, temp1, temp2); if (mpz_cmp (gcd1, gcd2) != 0 || mpz_cmp (gcd2, temp1) != 0) { fprintf (stderr, "ERROR in test %d\n", i); fprintf (stderr, "mpz_gcdext returned incorrect result\n"); fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); fprintf (stderr, "expected result:\n"); debug_mp (gcd1, -16); fprintf (stderr, "mpz_gcdext returns:\n");debug_mp (gcd2, -16); abort (); } }