/*======================================================================== Compute Factor Base: Function: Computes primes p up to B for which n is a square mod p, allocates memory and stores them in an array pointed to by factorBase. Additionally allocates and computes the primeSizes array. Returns: number of primes actually in the factor base ========================================================================*/ static void computeFactorBase(mpz_t n, unsigned long B,unsigned long multiplier) { UV p; UV primesinbase = 0; PRIME_ITERATOR(iter); if (factorBase) { Safefree(factorBase); factorBase = 0; } New(0, factorBase, B, unsigned int); factorBase[primesinbase++] = multiplier; if (multiplier != 2) factorBase[primesinbase++] = 2; prime_iterator_setprime(&iter, 3); for (p = 3; primesinbase < B; p = prime_iterator_next(&iter)) { if (mpz_kronecker_ui(n, p) == 1) factorBase[primesinbase++] = p; } prime_iterator_destroy(&iter); #ifdef LARGESTP gmp_printf("Largest prime less than %Zd\n",p); #endif /* Allocate and compute the number of bits required to store each prime */ New(0, primeSizes, B, unsigned char); for (p = 0; p < B; p++) primeSizes[p] = (unsigned char) floor( log(factorBase[p]) / log(2.0) - SIZE_FUDGE + 0.5 ); }
static unsigned long knuthSchroeppel(mpz_t n, unsigned long numPrimes) { unsigned int i, j, best_mult, knmod8; unsigned int maxprimes = (2*numPrimes <= 1000) ? 2*numPrimes : 1000; float best_score, contrib; float scores[NUMMULTS]; mpz_t temp; mpz_init(temp); for (i = 0; i < NUMMULTS; i++) { scores[i] = 0.5 * logf((float)multipliers[i]); mpz_mul_ui(temp, n, multipliers[i]); knmod8 = mpz_mod_ui(temp, temp, 8); switch (knmod8) { case 1: scores[i] -= 2 * M_LN2; break; case 5: scores[i] -= M_LN2; break; case 3: case 7: scores[i] -= 0.5 * M_LN2; break; default: break; } } { unsigned long prime, modp, knmodp; PRIME_ITERATOR(iter); for (i = 1; i < maxprimes; i++) { prime = prime_iterator_next(&iter); modp = mpz_mod_ui(temp, n, prime); contrib = logf((float)prime) / (float)(prime-1); for (j = 0; j < NUMMULTS; j++) { knmodp = (modp * multipliers[j]) % prime; if (knmodp == 0) { scores[j] -= contrib; } else { mpz_set_ui(temp, knmodp); if (mpz_kronecker_ui(temp, prime) == 1) scores[j] -= 2*contrib; } } } prime_iterator_destroy(&iter); } mpz_clear(temp); best_score = 1000.0; best_mult = 1; for (i = 0; i < NUMMULTS; i++) { float score = scores[i]; if (score < best_score) { best_score = score; best_mult = multipliers[i]; } } /* gmp_printf("%Zd mult %lu\n", n, best_mult); */ return best_mult; }
double qcn_estimate (mpz_t d) { #define P_LIMIT 132000 double h; unsigned long p; /* p=2 */ h = sqrt (-mpz_get_d (d)) / M_PI * 2.0 / (2.0 - mpz_kronecker_ui (d, 2)); if (mpz_cmp_si (d, -3) == 0) h *= 3; else if (mpz_cmp_si (d, -4) == 0) h *= 2; for (p = 3; p < P_LIMIT; p += 2) if (prime_p (p)) h *= (double) p / (double) (p - mpz_kronecker_ui (d, p)); return h; }
/* evaluate the Knuth-Schroeppel function, cf Robert D. Silverman, "The Multiple Polynomial Quadratic Sieve", Math. of Comp. volume 48, number 177, 1987, page 335 */ unsigned long find_multiplier (mpz_t N, double B) { unsigned long k, bestk = 1; double p, f, g, maxf = 0.0; mpz_t kN; mpz_init (kN); for (k = 1; k < 100; k = nextprime (k)) { mpz_mul_ui (kN, N, k); /* FIXME: Silverman writes "if N = 1 mod 8" but isn't it kN instead? */ if (mpz_kronecker_ui (kN, 2) == 1 && mpz_fdiv_ui (kN, 8) == 1) f = 2.0 * log (2.0); else f = 0.0; for (p = getprime (2.0); p <= B; p = getprime (p)) { if (mpz_kronecker_ui (kN, (unsigned long) p) == 1) { g = ((k % (unsigned long) p) == 0) ? (1.0 / p) : (2.0 / p); f += g * log (p); } } f -= 0.5 * log ((double) k); if (f > maxf) { maxf = f; bestk = k; } getprime (0.0); /* free prime buffer */ } mpz_clear (kN); return bestk; }
static int ec_order(mpz_t order, mpz_t a, mpz_t b, unsigned long n) { /* use the inefficient naive approach to count the points of an elliptic * curve E(a, b) over finite field GF(n): * |(E(a, b))/GF(n)| = * n + 1 + sum (x in GF(n)) (jacobi_symbol((x^3 + a*x + b), n)) */ unsigned long i; mpz_t tmp; int order_exists; if (!(n & 1)) { order_exists = 0; } else { mpz_init(tmp); mpz_set_ui(order, n); mpz_add_ui(order, order, 1); for (i = 0; i < n; ++i) { mpz_set_ui(tmp, i); mpz_mul_ui(tmp, tmp, i); mpz_mul_ui(tmp, tmp, i); mpz_addmul_ui(tmp, a, i); mpz_add(tmp, tmp, b); mpz_set_si(tmp, mpz_kronecker_ui(tmp, n)); mpz_add(order, order, tmp); } order_exists = 1; mpz_clear(tmp); } return order_exists; }