/*============================================================================= 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, 2007, 2008, 2009 William Hart Copyright (C) 2008, Peter Shrimpton Copyright (C) 2009, Tom Boothby Copyright (C) 2010, Fredrik Johansson ******************************************************************************/ #ifndef ULONG_EXTRAS_H #define ULONG_EXTRAS_H #include #include "flint.h" #ifdef __cplusplus extern "C" { #endif typedef struct pair_s { mp_limb_t x, y; } n_pair_t; #define FLINT_MAX_FACTORS_IN_LIMB 15 typedef struct { int num; int exp[FLINT_MAX_FACTORS_IN_LIMB]; mp_limb_t p[FLINT_MAX_FACTORS_IN_LIMB]; } n_factor_t; #define FLINT_ODDPRIME_SMALL_CUTOFF 4096 #define FLINT_NUM_PRIMES_SMALL 172 #define FLINT_PRIMES_SMALL_CUTOFF 1030 #define FLINT_PSEUDOSQUARES_CUTOFF 1000 #define FLINT_FACTOR_TRIAL_PRIMES 3000 /* nth_prime(FLINT_FACTOR_TRIAL_PRIMES) */ #define FLINT_FACTOR_TRIAL_PRIMES_PRIME UWORD(27449) #define FLINT_FACTOR_TRIAL_CUTOFF (UWORD(27449) * UWORD(27449)) #define FLINT_PRIMES_TAB_DEFAULT_CUTOFF 1000000 #define FLINT_FACTOR_SQUFOF_ITERS 50000 #define FLINT_FACTOR_ONE_LINE_MAX (UWORD(1)<<39) #define FLINT_FACTOR_ONE_LINE_ITERS 40000 #define FLINT_PRIME_PI_ODD_LOOKUP_CUTOFF 311 #define FLINT_SIEVE_SIZE 65536 #if FLINT64 #define UWORD_MAX_PRIME UWORD(18446744073709551557) #else #define UWORD_MAX_PRIME UWORD(4294967291) #endif typedef struct { slong small_i; slong small_num; unsigned int * small_primes; mp_limb_t sieve_a; mp_limb_t sieve_b; slong sieve_i; slong sieve_num; char * sieve; } n_primes_struct; typedef n_primes_struct n_primes_t[1]; void n_primes_init(n_primes_t iter); void n_primes_clear(n_primes_t iter); void n_primes_extend_small(n_primes_t iter, mp_limb_t bound); void n_primes_sieve_range(n_primes_t iter, mp_limb_t a, mp_limb_t b); void n_primes_jump_after(n_primes_t iter, mp_limb_t n); static __inline__ mp_limb_t n_primes_next(n_primes_t iter) { if (iter->small_i < iter->small_num) return iter->small_primes[(iter->small_i)++]; for (;;) { while (iter->sieve_i < iter->sieve_num) if (iter->sieve[iter->sieve_i++] != 0) return iter->sieve_a + 2 * (iter->sieve_i - 1); if (iter->sieve_b == 0) n_primes_jump_after(iter, iter->small_primes[iter->small_num-1]); else n_primes_jump_after(iter, iter->sieve_b); } } extern const unsigned int flint_primes_small[]; extern FLINT_TLS_PREFIX mp_limb_t * _flint_primes[FLINT_BITS]; extern FLINT_TLS_PREFIX double * _flint_prime_inverses[FLINT_BITS]; extern FLINT_TLS_PREFIX int _flint_primes_used; void n_compute_primes(ulong num_primes); void n_cleanup_primes(void); const mp_limb_t * n_primes_arr_readonly(ulong n); const double * n_prime_inverses_arr_readonly(ulong n); mp_limb_t n_randlimb(flint_rand_t state); mp_limb_t n_randint(flint_rand_t state, mp_limb_t limit); mp_limb_t n_randbits(flint_rand_t state, unsigned int bits); mp_limb_t n_randtest_bits(flint_rand_t state, int bits); mp_limb_t n_randtest(flint_rand_t state); mp_limb_t n_randtest_not_zero(flint_rand_t state); mp_limb_t n_randprime(flint_rand_t state, ulong bits, int proved); mp_limb_t n_randtest_prime(flint_rand_t state, int proved); mp_limb_t n_pow(mp_limb_t n, ulong exp); mp_limb_t n_flog(mp_limb_t n, mp_limb_t b); mp_limb_t n_clog(mp_limb_t n, mp_limb_t b); static __inline__ double n_precompute_inverse(mp_limb_t n) { return (double) 1 / (double) n; } static __inline__ mp_limb_t n_preinvert_limb(mp_limb_t n) { mp_limb_t norm, ninv; count_leading_zeros(norm, n); invert_limb(ninv, n< x ? x + y : x + y - n); } static __inline__ mp_limb_t n_submod(mp_limb_t x, mp_limb_t y, mp_limb_t n) { return (y > x ? x - y + n : x - y); } static __inline__ mp_limb_t n_negmod(mp_limb_t x, mp_limb_t n) { return n_submod(0, x, n); } mp_limb_t n_sqrtmod(mp_limb_t a, mp_limb_t p); slong n_sqrtmod_2pow(mp_limb_t ** sqrt, mp_limb_t a, slong exp); slong n_sqrtmod_primepow(mp_limb_t ** sqrt, mp_limb_t a, mp_limb_t p, slong exp); slong n_sqrtmodn(mp_limb_t ** sqrt, mp_limb_t a, n_factor_t * fac); mp_limb_t n_gcd(mp_limb_t x, mp_limb_t y); static __inline__ mp_limb_t n_gcd_full(mp_limb_t x, mp_limb_t y) { if (x >= y) return n_gcd(x, y); else return n_gcd(y, x); } mp_limb_t n_xgcd(mp_limb_t * a, mp_limb_t * b, mp_limb_t x, mp_limb_t y); mp_limb_t n_invmod(mp_limb_t x, mp_limb_t y); mp_limb_t n_gcdinv(mp_limb_t * a, mp_limb_t x, mp_limb_t y); ulong n_revbin(ulong in, ulong bits); int n_jacobi(mp_limb_signed_t x, mp_limb_t y); int n_jacobi_unsigned(mp_limb_t x, mp_limb_t y); mp_limb_t n_sqrt(mp_limb_t a); mp_limb_t n_sqrtrem(mp_limb_t * r, mp_limb_t a); int n_is_square(mp_limb_t x); int n_is_perfect_power235(mp_limb_t n); int n_is_oddprime_small(mp_limb_t n); int n_is_oddprime_binary(mp_limb_t n); int n_is_probabprime_fermat(mp_limb_t n, mp_limb_t i); int n_is_probabprime_fibonacci(mp_limb_t n); int n_is_probabprime_lucas(mp_limb_t n); int n_is_probabprime_BPSW(mp_limb_t n); int n_is_strong_probabprime_precomp(mp_limb_t n, double npre, mp_limb_t a, mp_limb_t d); int n_is_strong_probabprime2_preinv(mp_limb_t n, mp_limb_t ninv, mp_limb_t a, mp_limb_t d); int n_is_probabprime(mp_limb_t n); int n_is_prime_pseudosquare(mp_limb_t n); int n_is_prime_pocklington(mp_limb_t n, ulong iterations); int n_is_prime(mp_limb_t n); mp_limb_t n_nth_prime(ulong n); void n_nth_prime_bounds(mp_limb_t *lo, mp_limb_t *hi, ulong n); ulong n_prime_pi(mp_limb_t n); void n_prime_pi_bounds(ulong *lo, ulong *hi, mp_limb_t n); int n_remove(mp_limb_t * n, mp_limb_t p); int n_remove2_precomp(mp_limb_t * n, mp_limb_t p, double ppre); static __inline__ void n_factor_init(n_factor_t * factors) { factors->num = UWORD(0); } void n_factor_insert(n_factor_t * factors, mp_limb_t p, ulong exp); mp_limb_t n_factor_trial_range(n_factor_t * factors, mp_limb_t n, ulong start, ulong num_primes); mp_limb_t n_factor_trial_partial(n_factor_t * factors, mp_limb_t n, mp_limb_t * prod, ulong num_primes, mp_limb_t limit); mp_limb_t n_factor_trial(n_factor_t * factors, mp_limb_t n, ulong num_primes); mp_limb_t n_factor_partial(n_factor_t * factors, mp_limb_t n, mp_limb_t limit, int proved); mp_limb_t n_factor_power235(ulong *exp, mp_limb_t n); mp_limb_t n_factor_one_line(mp_limb_t n, ulong iters); mp_limb_t n_factor_lehman(mp_limb_t n); mp_limb_t n_factor_SQUFOF(mp_limb_t n, ulong iters); void n_factor(n_factor_t * factors, mp_limb_t n, int proved); mp_limb_t n_factor_pp1(mp_limb_t n, ulong B1, ulong c); int n_is_squarefree(mp_limb_t n); int n_moebius_mu(mp_limb_t n); void n_moebius_mu_vec(int * mu, ulong len); mp_limb_t n_euler_phi(mp_limb_t n); int n_sizeinbase(mp_limb_t n, int base); mp_limb_t n_nextprime(mp_limb_t n, int proved); mp_limb_t n_factorial_mod2_preinv(ulong n, mp_limb_t p, mp_limb_t pinv); mp_limb_t n_factorial_fast_mod2_preinv(ulong n, mp_limb_t p, mp_limb_t pinv); mp_limb_t n_primitive_root_prime_prefactor(mp_limb_t p, n_factor_t * factors); mp_limb_t n_primitive_root_prime(mp_limb_t p); mp_limb_t n_discrete_log_bsgs(mp_limb_t b, mp_limb_t a, mp_limb_t n); #ifdef __cplusplus } #endif #endif