int main(void) { mpz_t a, r; mpz_init(a); mpz_init(r); int digsum = 0; mpz_fac_ui(a, 100); while (mpz_cmp_ui(a, 0)) { mpz_tdiv_qr_ui(a, r, a, 10); digsum += mpz_get_ui(r); } printf("%d\n", digsum); return 0; }
int doTrialDiv(long *factors, mpz_t n) /******************************************************************/ { long i; int numFacts=0; static mpz_t q, r; static int initialized=0; if (!(initialized)) { mpz_init(q); mpz_init(r); initialized=1; } for (i=0; i<num_td_primes; i++) { while (mpz_tdiv_qr_ui(q, r, n, td_primes[i])==0) { factors[numFacts++] = td_primes[i]; mpz_set(n, q); } } return numFacts; }
bool Algorithms::MillerRabin(mpz_t number, unsigned int numBits, unsigned int numTest) { unsigned int i, j, k; char *a_str; mpz_t buf, t, gcd, a, c; mpz_init(buf); mpz_init(t); mpz_init(gcd); mpz_init(a); mpz_init(c); if(mpz_cmp_ui(number,(unsigned long)2) == 0) return true; mpz_mod_ui(buf, number, (unsigned long)2); if(mpz_cmp_ui(buf,(unsigned long)0) == 0) return false; unsigned long s = 0; mpz_sub_ui(t,number,(unsigned long)1); mpz_mod_ui(buf, t, (unsigned long)2); while(mpz_cmp_ui(buf,(unsigned long)0) == 0) { mpz_tdiv_qr_ui(t, buf, t, (unsigned long)2); mpz_mod_ui(buf, t, (unsigned long)2); s++; } a_str = new char[numBits]; for(i = 0; i < numTest; i++) { for(k = 0; k < numBits - 1; k++) a_str[k] = (int)(2.0 * rand() / (RAND_MAX + 1.0)) + '0'; a_str[k] = '\0'; mpz_set_str(a,a_str,2); mpz_gcd(gcd,a,number); if(mpz_cmp_ui(gcd,(unsigned long)1) != 0) return false; mpz_powm(c, a, t, number); if(mpz_cmp_ui(c,(unsigned long)1) == 0) continue; mpz_sub_ui(buf,number,(unsigned long)1); if(mpz_cmp(c,buf) == 0) continue; bool f = true; for(j = 0; j < s - 1; j++) { mpz_powm_ui(c, c,(unsigned long)2, number); if(mpz_cmp(c,buf) == 0) f = false; } if(f) return false; } mpz_clear(buf); mpz_clear(t); mpz_clear(gcd); mpz_clear(a); mpz_clear(c); free(a_str); return true; }
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_tdiv_qr_ui (quotient, remainder, dividend, divisor); r_q = mpz_tdiv_q_ui (quotient2, dividend, divisor); r_r = mpz_tdiv_r_ui (remainder2, dividend, divisor); r = mpz_tdiv_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_tdiv_qr_ui and mpz_tdiv_q_ui differ", dividend, divisor); if (mpz_cmp (remainder, remainder2) != 0) dump_abort ("remainders from mpz_tdiv_qr_ui and mpz_tdiv_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 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 ("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_tdiv_qr_ui is wrong", dividend, divisor); if (mpz_cmp_ui (remainder, r_q) != 0) dump_abort ("remainder returned from mpz_tdiv_q_ui is wrong", dividend, divisor); if (mpz_cmp_ui (remainder, r_r) != 0) dump_abort ("remainder returned from mpz_tdiv_r_ui is wrong", dividend, divisor); if (mpz_cmp_ui (remainder, r) != 0) dump_abort ("remainder returned from mpz_tdiv_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); }
void generate_mod (int limb_bits, int nail_bits) { int numb_bits = limb_bits - nail_bits; int i, divisor; mpz_init_set_ui (pp, 0L); mpz_init_set_ui (pp_norm, 0L); mpz_init_set_ui (pp_inverted, 0L); /* no more than limb_bits many factors in a one limb modulus (and of course in reality nothing like that many) */ factor_alloc = limb_bits; factor = xmalloc (factor_alloc * sizeof (*factor)); rawfactor = xmalloc (factor_alloc * sizeof (*rawfactor)); if (numb_bits % 4 != 0) { strcpy (mod34_excuse, "GMP_NUMB_BITS % 4 != 0"); goto use_pp; } max_divisor = 2*limb_bits; max_divisor_bits = log2_ceil (max_divisor); if (numb_bits / 4 < max_divisor_bits) { /* Wind back to one limb worth of max_divisor, if that will let us use mpn_mod_34lsub1. */ max_divisor = limb_bits; max_divisor_bits = log2_ceil (max_divisor); if (numb_bits / 4 < max_divisor_bits) { strcpy (mod34_excuse, "GMP_NUMB_BITS / 4 too small"); goto use_pp; } } { /* Can use mpn_mod_34lsub1, find small factors of 2^mod34_bits-1. */ mpz_t m, q, r; int multiplicity; mod34_bits = (numb_bits / 4) * 3; /* mpn_mod_34lsub1 returns a full limb value, PERFSQR_MOD_34 folds it at the mod34_bits mark, adding the two halves for a remainder of at most mod34_bits+1 many bits */ mod_bits = mod34_bits + 1; mpz_init_set_ui (m, 1L); mpz_mul_2exp (m, m, mod34_bits); mpz_sub_ui (m, m, 1L); mpz_init (q); mpz_init (r); for (i = 3; i <= max_divisor; i++) { if (! isprime (i)) continue; mpz_tdiv_qr_ui (q, r, m, (unsigned long) i); if (mpz_sgn (r) != 0) continue; /* if a repeated prime is found it's used as an i^n in one factor */ divisor = 1; multiplicity = 0; do { if (divisor > max_divisor / i) break; multiplicity++; mpz_set (m, q); mpz_tdiv_qr_ui (q, r, m, (unsigned long) i); } while (mpz_sgn (r) == 0); assert (nrawfactor < factor_alloc); rawfactor[nrawfactor].divisor = i; rawfactor[nrawfactor].multiplicity = multiplicity; nrawfactor++; } mpz_clear (m); mpz_clear (q); mpz_clear (r); } if (nrawfactor <= 2) { mpz_t new_pp; sprintf (mod34_excuse, "only %d small factor%s", nrawfactor, nrawfactor == 1 ? "" : "s"); use_pp: /* reset to two limbs of max_divisor, in case the mpn_mod_34lsub1 code tried with just one */ max_divisor = 2*limb_bits; max_divisor_bits = log2_ceil (max_divisor); mpz_init (new_pp); nrawfactor = 0; mod_bits = MIN (numb_bits, limb_bits - max_divisor_bits); /* one copy of each small prime */ mpz_set_ui (pp, 1L); for (i = 3; i <= max_divisor; i++) { if (! isprime (i)) continue; mpz_mul_ui (new_pp, pp, (unsigned long) i); if (mpz_sizeinbase (new_pp, 2) > mod_bits) break; mpz_set (pp, new_pp); assert (nrawfactor < factor_alloc); rawfactor[nrawfactor].divisor = i; rawfactor[nrawfactor].multiplicity = 1; nrawfactor++; } /* Plus an extra copy of one or more of the primes selected, if that still fits in max_divisor and the total in mod_bits. Usually only 3 or 5 will be candidates */ for (i = nrawfactor-1; i >= 0; i--) { if (rawfactor[i].divisor > max_divisor / rawfactor[i].divisor) continue; mpz_mul_ui (new_pp, pp, (unsigned long) rawfactor[i].divisor); if (mpz_sizeinbase (new_pp, 2) > mod_bits) continue; mpz_set (pp, new_pp); rawfactor[i].multiplicity++; } mod_bits = mpz_sizeinbase (pp, 2); mpz_set (pp_norm, pp); while (mpz_sizeinbase (pp_norm, 2) < numb_bits) mpz_add (pp_norm, pp_norm, pp_norm); mpz_preinv_invert (pp_inverted, pp_norm, numb_bits); mpz_clear (new_pp); } /* start the factor array */ for (i = 0; i < nrawfactor; i++) { int j; assert (nfactor < factor_alloc); factor[nfactor].divisor = 1; for (j = 0; j < rawfactor[i].multiplicity; j++) factor[nfactor].divisor *= rawfactor[i].divisor; nfactor++; } combine: /* Combine entries in the factor array. Combine the smallest entry with the biggest one that will fit with it (ie. under max_divisor), then repeat that with the new smallest entry. */ qsort (factor, nfactor, sizeof (factor[0]), f_cmp_divisor); for (i = nfactor-1; i >= 1; i--) { if (factor[i].divisor <= max_divisor / factor[0].divisor) { factor[0].divisor *= factor[i].divisor; COLLAPSE_ELEMENT (factor, i, nfactor); goto combine; } } total_fraction = 1.0; for (i = 0; i < nfactor; i++) { mpz_init (factor[i].inverse); mpz_invert_ui_2exp (factor[i].inverse, (unsigned long) factor[i].divisor, (unsigned long) mod_bits); mpz_init (factor[i].mask); square_mask (factor[i].mask, factor[i].divisor); /* fraction of possible squares */ factor[i].fraction = (double) mpz_popcount (factor[i].mask) / factor[i].divisor; /* total fraction of possible squares */ total_fraction *= factor[i].fraction; } /* best tests first (ie. smallest fraction) */ qsort (factor, nfactor, sizeof (factor[0]), f_cmp_fraction); }