pqc/external/flint-2.4.3/qsieve/ll_primes_init.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;
}