pqc/external/flint-2.4.3/qsieve.h

310 lines
9.1 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
******************************************************************************/
#ifndef QSIEVE_H
#define QSIEVE_H
#include <gmp.h>
#include "flint.h"
#include "fmpz.h"
#ifdef __cplusplus
extern "C" {
#endif
#if FLINT_BITS==64
#ifndef uint64_t
#define uint64_t ulong
#endif
#else
#include <stdint.h>
#endif
/*
Debug verbosity (bits are as follows):
>0 - print headings for each phase of the sieve and some
simple data about the number of FB primes used, etc.
2 - print poly A coeffs
4 - print polynomials used
8 - print relations
16 - print statistics for sieve contents
32 - print X values for each sieve entry that passes initial sieve test
64 - print information about the number of duplicate relations
128 - print lanczos information and errors
*/
#define QS_DEBUG 0
#define CACHE_SIZE 65536 /* size of L1 cache */
typedef struct prime_t
{
mp_limb_t pinv; /* precomputed inverse */
int p; /* prime */
char size;
} prime_t;
typedef struct fac_t /* struct for factors of relations */
{
slong ind;
slong exp;
} fac_t;
typedef struct la_col_t /* matrix column */
{
slong * data; /* The list of occupied rows in this column */
slong weight; /* Number of nonzero entries in this column */
slong orig; /* Original relation number */
} la_col_t;
typedef struct qs_s
{
mp_limb_t hi; /* Number to factor */
mp_limb_t lo;
mp_bitcnt_t bits; /* Number of bits of n */
ulong ks_primes; /* number of Knuth-Schroeppel primes */
mp_limb_t k; /* Multiplier */
fmpz_t kn; /* kn as a multiprecision integer */
slong num_primes; /* number of factor base primes including k and 2 */
slong small_primes; /* number of primes to not sieve with */
slong sieve_size; /* size of sieve to use */
prime_t * factor_base; /* data about factor base primes */
int * sqrts; /* square roots of kn mod factor base primes */
char sieve_bits; /* number of bits to exceed in sieve */
/******************
Polynomial data
******************/
mp_limb_t A; /* coefficient A */
mp_limb_t B; /* coefficient B */
fmpz_t C; /* coefficient C */
mp_limb_t * A_ind; /* indices of factor base primes dividing A */
mp_limb_t * A_modp; /* (A/p) mod p for each prime p dividing A */
mp_limb_t * inv_p2; /* newton inverse of p^2 for each factor p of A */
mp_limb_t * B_terms; /*
Let A_i = (A/p) mod p where p is the i-th prime
which is a factor of A, then B_terms[i] is
{p^(1/2) / A_i} mod p * (A/p) where we take
the smaller square root of p
*/
mp_limb_t * A_inv; /* A^(-1) mod p */
mp_limb_t ** A_inv2B; /* A_inv[j][i] = 2*B_terms[j]*A^(-1) mod p */
mp_limb_t * soln1; /* first root of poly */
mp_limb_t * soln2; /* second root of poly */
mp_limb_t target_A; /* approximate target value for A coeff of poly */
slong s; /* number of prime factors of A coeff */
slong min; /* minimum FB prime that can appear as factor of A */
slong span; /* size of set of possible prime factors of A */
slong fact; /* middle of set of possible prime factors of A */
slong mid; /* start of range for middle factor */
slong high; /* end of range for middle factor */
/*********************
Relations data
**********************/
slong qsort_rels; /* number of relations to accumulate before sorting */
slong extra_rels; /* number of extra relations beyond num_primes */
slong max_factors; /* maximum number of factors a relation can have */
slong * small; /* exponents of small prime factors in relations */
fac_t * factor; /* factors for a relation */
fmpz * Y_arr; /* array of Y's corresponding to relations */
slong * curr_rel; /* current relation in array of relations */
slong * relation; /* relation array */
slong buffer_size; /* size of buffer of relations */
slong num_relations; /* number of relations so far */
slong num_factors; /* number of factors found in a relation */
/*********************
Linear algebra data
**********************/
la_col_t * matrix; /* the main matrix over GF(2) in sparse format */
la_col_t * unmerged; /* unmerged matrix columns */
la_col_t ** qsort_arr; /* array of columns ready to be sorted */
slong num_unmerged; /* number of columns unmerged */
slong columns; /* number of columns in matrix so far */
/*********************
Square root data
**********************/
slong * prime_count; /* counts of the exponents of primes appearing in the square */
/*********************
Statistics
**********************/
#if (QS_DEBUG & 16)
slong * sieve_tally;
#endif
} qs_s;
typedef qs_s qs_t[1];
/*
Tuning parameters { bits, ks_primes, fb_primes, small_primes }
for qsieve_ll_factor where:
* bits is the number of bits of n
* ks_primes is the max number of primes to try in Knuth-Schroeppel algo
* fb_primes is the number of factor base primes to use (including k and 2)
* small_primes is the number of small primes to not factor with (including k and 2)
* sieve_size is the size of the sieve to use
*/
static const mp_limb_t qsieve_ll_tune[][5] =
{
{0, 50, 80, 2, 14000 },
{30, 50, 80, 2, 16000 },
{40, 50, 100, 3, 18000 },
{50, 50, 120, 3, 20000 },
{60, 50, 140, 4, 22000 },
{70, 50, 160, 4, 24000 },
{80, 100, 180, 5, 26000 },
{90, 100, 200, 5, 28000 },
{100, 100, 250, 6, 30000 },
{110, 100, 300, 6, 34000 },
{120, 100, 500, 7, 40000 },
{130, 100, 550, 7, 60000 }
};
/* number of entries in the tuning table */
#define QS_LL_TUNE_SIZE (sizeof(qsieve_ll_tune)/(5*sizeof(mp_limb_t)))
#define P_GOODNESS 100 /* within what factor of target_A must A be */
#define P_GOODNESS2 200 /* within what factor of target_A must A be when s = 2 */
#define BITS_ADJUST 10 /* no. bits less than f(X) to qualify for trial division */
void qsieve_ll_init(qs_t qs_inf, mp_limb_t hi, mp_limb_t lo);
void qsieve_ll_clear(qs_t qs_inf);
mp_limb_t qsieve_ll_knuth_schroeppel(qs_t qs_inf);
mp_limb_t qsieve_ll_primes_init(qs_t qs_inf);
mp_limb_t qsieve_ll_poly_init(qs_t qs_inf);
void qsieve_ll_linalg_init(qs_t qs_inf);
void qsieve_ll_compute_poly_data(qs_t qs_inf);
void qsieve_ll_compute_A_factor_offsets(qs_t qs_inf);
void qsieve_ll_compute_C(qs_t qs_inf);
slong qsieve_ll_collect_relations(qs_t qs_inf, char * sieve);
slong qsieve_ll_merge_sort(qs_t qs_inf);
slong qsieve_ll_merge_relations(qs_t qs_inf);
slong qsieve_ll_insert_relation(qs_t qs_inf, fmpz_t Y);
mp_limb_t qsieve_ll_factor(mp_limb_t hi, mp_limb_t lo);
static __inline__ void insert_col_entry(la_col_t * col, slong entry)
{
if (((col->weight >> 4) << 4) == col->weight) /* need more space */
{
if (col->weight != 0) col->data =
(slong *) flint_realloc(col->data, (col->weight + 16)*sizeof(slong));
else col->data = (slong *) flint_malloc(16*sizeof(slong));
}
col->data[col->weight] = entry;
col->weight++;
}
static __inline__ void copy_col(la_col_t * col2, la_col_t * col1)
{
col2->weight = col1->weight;
col2->data = col1->data;
col2->orig = col1->orig;
}
static __inline__ void swap_cols(la_col_t * col2, la_col_t * col1)
{
la_col_t temp;
temp.weight = col1->weight;
temp.data = col1->data;
temp.orig = col1->orig;
col1->weight = col2->weight;
col1->data = col2->data;
col1->orig = col2->orig;
col2->weight = temp.weight;
col2->data = temp.data;
col2->orig = temp.orig;
}
static __inline__ void clear_col(la_col_t * col)
{
col->weight = 0;
}
static __inline__ void free_col(la_col_t * col)
{
if (col->weight) flint_free(col->data);
}
uint64_t get_null_entry(uint64_t * nullrows, slong i, slong l);
void reduce_matrix(qs_t qs_inf, slong * nrows, slong * ncols, la_col_t * cols);
uint64_t * block_lanczos(flint_rand_t state, slong nrows, slong dense_rows,
slong ncols, la_col_t *B);
void qsieve_ll_square_root(fmpz_t X, fmpz_t Y, qs_t qs_inf,
uint64_t * nullrows, slong ncols, slong l, fmpz_t N);
#ifdef __cplusplus
}
#endif
#endif