/*============================================================================= This file is part of FLINT. FLINT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. FLINT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLINT; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =============================================================================*/ /****************************************************************************** Copyright (C) 2006, 2011 William Hart ******************************************************************************/ #include #include "flint.h" #include "ulong_extras.h" #include "qsieve.h" prime_t * compute_factor_base(mp_limb_t * small_factor, qs_t qs_inf, slong num_primes) { mp_limb_t p, nmod, nmod2; mp_limb_t pinv; mp_limb_t k = qs_inf->k; slong num = qs_inf->num_primes; slong fb_prime = 2; prime_t * factor_base; int * sqrts; int kron; /* (re)allocate space for factor base */ if (num == 0) factor_base = (prime_t *) flint_malloc(num_primes*sizeof(prime_t)); else factor_base = (prime_t *) flint_realloc(qs_inf->factor_base, num_primes*sizeof(prime_t)); qs_inf->factor_base = factor_base; /* allocate space for square roots kn mod factor base primes */ if (num == 0) sqrts = flint_malloc(sizeof(int)*num_primes); else sqrts = flint_realloc(qs_inf->sqrts, sizeof(int)*num_primes); qs_inf->sqrts = sqrts; qs_inf->num_primes = num_primes; /* compute the two limbs of kn */ if (num == 0) { p = 2; num = 2; } else p = factor_base[num - 1].p; for (fb_prime = num; fb_prime < num_primes; ) /* leave space for k and 2 */ { p = n_nextprime(p, 0); pinv = n_preinvert_limb(p); nmod = n_ll_mod_preinv(qs_inf->hi, qs_inf->lo, p, pinv); /* n mod p */ if (nmod == 0) { *small_factor = p; return factor_base; } nmod2 = n_mulmod2_preinv(nmod, k, p, pinv); /* kn mod p */ if (nmod2 == 0) /* don't sieve with factors of multiplier */ continue; nmod = nmod2; /* save nmod2 */ kron = 1; /* n mod p is even, not handled by n_jacobi */ while ((nmod2 % 2) == 0) { if ((p % 8) == 3 || (p % 8) == 5) kron *= -1; nmod2 /= 2; } kron *= n_jacobi(nmod2, p); if (kron == 1) /* kn is a quadratic residue mod p (and hence a FB prime) */ { factor_base[fb_prime].p = p; factor_base[fb_prime].pinv = pinv; factor_base[fb_prime].size = FLINT_BIT_COUNT(p); sqrts[fb_prime] = n_sqrtmod(nmod, p); fb_prime++; } } *small_factor = 0; return factor_base; } mp_limb_t qsieve_ll_primes_init(qs_t qs_inf) { slong num_primes; slong i, s, min, fact, span; mp_limb_t fact_approx; fmpz_t temp; mp_limb_t k = qs_inf->k; mp_limb_t small_factor = 0; prime_t * factor_base; /* determine which index in the tuning table n corresponds to */ for (i = 1; i < QS_LL_TUNE_SIZE; i++) { if (qsieve_ll_tune[i][0] > qs_inf->bits) break; } i--; qs_inf->sieve_bits = 32; /* number of bits to exceed in evaluate_sieve */ qs_inf->sieve_size = qsieve_ll_tune[i][4]; /* size of sieve to use */ qs_inf->small_primes = qsieve_ll_tune[i][3]; /* number of primes to not sieve with */ num_primes = qsieve_ll_tune[i][2]; /* number of factor base primes */ qs_inf->qsort_rels = qsieve_ll_tune[i][1]; /* number of relations to accumulate before sorting */ qs_inf->num_primes = 0; /* start with 0 primes */ factor_base = compute_factor_base(&small_factor, qs_inf, num_primes); /* build up FB */ if (small_factor) return small_factor; /* figure out the number of factors of A and min, fact and span */ s = qs_inf->bits/28 + 1; /* number of prime factors in A coeff */ fmpz_init(temp); fmpz_mul_2exp(temp, qs_inf->kn, 1); fmpz_sqrt(temp, temp); fmpz_tdiv_q_ui(temp, temp, qs_inf->sieve_size); qs_inf->target_A = 2*fmpz_get_ui(temp); fmpz_root(temp, temp, s); fact_approx = fmpz_get_ui(temp); fmpz_clear(temp); fact = 2; while (fact_approx >= factor_base[fact].p) fact++; while (1) { span = num_primes/s/s/2; if (span < 6*s) span = 6*s; /* make sure we have plenty of primes to choose from */ min = fact - span/2; if (min < qs_inf->small_primes) min = qs_inf->small_primes; fact = min + span/2; if (min + span <= num_primes - 2) /* we have enough primes */ break; num_primes = (slong) (1.1 * (double) num_primes); factor_base = compute_factor_base(&small_factor, qs_inf, num_primes); /* increase size of FB */ if (small_factor) return small_factor; } qs_inf->s = s; qs_inf->min = min; qs_inf->fact = fact; qs_inf->span = span; /* these are used for the range of the middle factor of A when s is odd */ qs_inf->mid = qs_inf->min + ((s - 1) * qs_inf->span)/(2 * s); qs_inf->high = qs_inf->mid + qs_inf->span / s; #if (QS_DEBUG & 2) flint_printf("Using %wd factor base primes\n", qs_inf->num_primes); flint_printf("min = FB[%wd], span = %wd, number of A factors = %wd, target A = %wd\n", min, span, s, qs_inf->target_A); #endif /* consider k and 2 as factor base primes */ factor_base[0].p = k; factor_base[0].pinv = n_preinvert_limb(k); factor_base[0].size = FLINT_BIT_COUNT(k); factor_base[1].p = 2; factor_base[0].size = 2; return 0; }