198 lines
6.2 KiB
C
198 lines
6.2 KiB
C
/*=============================================================================
|
|
|
|
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 <gmp.h>
|
|
#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;
|
|
}
|