static PyObject * GMPy_MPZ_Function_Isqrt(PyObject *self, PyObject *other) { MPZ_Object *result; if (CHECK_MPZANY(other)) { if (mpz_sgn(MPZ(other)) < 0) { VALUE_ERROR("isqrt() of negative number"); return NULL; } if ((result = GMPy_MPZ_New(NULL))) { mpz_sqrt(result->z, MPZ(other)); } } else { if (!(result = GMPy_MPZ_From_Integer(other, NULL))) { TYPE_ERROR("isqrt() requires 'mpz' argument"); return NULL; } if (mpz_sgn(result->z) < 0) { VALUE_ERROR("isqrt() of negative number"); Py_DECREF((PyObject*)result); return NULL; } mpz_sqrt(result->z, result->z); } return (PyObject*)result; }
/* See Cohen 1.5.3 */ int modified_cornacchia(mpz_t x, mpz_t y, mpz_t D, mpz_t p) { int result = 0; mpz_t a, b, c, d; if (mpz_cmp_ui(p, 2) == 0) { mpz_add_ui(x, D, 8); if (mpz_perfect_square_p(x)) { mpz_sqrt(x, x); mpz_set_ui(y, 1); result = 1; } return result; } if (mpz_jacobi(D, p) == -1) /* No solution */ return 0; mpz_init(a); mpz_init(b); mpz_init(c); mpz_init(d); sqrtmod(x, D, p, a, b, c, d); if ( (mpz_even_p(D) && mpz_odd_p(x)) || (mpz_odd_p(D) && mpz_even_p(x)) ) mpz_sub(x, p, x); mpz_mul_ui(a, p, 2); mpz_set(b, x); mpz_sqrt(c, p); mpz_mul_ui(c, c, 2); /* Euclidean algorithm */ while (mpz_cmp(b, c) > 0) { mpz_set(d, a); mpz_set(a, b); mpz_mod(b, d, b); } mpz_mul_ui(c, p, 4); mpz_mul(a, b, b); mpz_sub(a, c, a); /* a = 4p - b^2 */ mpz_abs(d, D); /* d = |D| */ if (mpz_divisible_p(a, d)) { mpz_divexact(c, a, d); if (mpz_perfect_square_p(c)) { mpz_set(x, b); mpz_sqrt(y, c); result = 1; } } mpz_clear(a); mpz_clear(b); mpz_clear(c); mpz_clear(d); return result; }
bool PrGlib::PrG_prime_test(const ZZZ& n,unsigned int len) { /*kiem tra gia nguyen to fermat co so */ ZZZ tmp; mpz_powm(tmp.get_mpz_t(), ZZZ(2).get_mpz_t(),ZZZ((n - 1)).get_mpz_t(), n.get_mpz_t()); if (tmp != 1) return false; /**************************************/ /*let k and m such that: n-1=m*2^k*/ ZZZ m = n^1; //sub(m, n, 1); because n is odd long k; // MakeOdd(m); k = 0; do{ m >>= 1; //= > m = m / 2; //y = m & 1; //check m is even number k++; } while ((m & 1) == 0); /*check prime number with the first 20 prime numbers*/ gmp_randclass r(gmp_randinit_default); ZZZ x; for (int i = 0; i < 20; i++) { x = PrG_prime_sample[i]; if (PrG_rabin_miller_test(n, x, k, m))return false; } /*check prime number with the random 44 numbers <= sqrt(n)*/ ZZZ qk; mpz_sqrt(qk.get_mpz_t(),n.get_mpz_t()); for (int i = 0; i < len; i++) { do { x= r.get_z_range(qk); //RandomBnd(x, n); } while (x <= 73); if (PrG_rabin_miller_test(n, x, k, m))return false; } return true; }
/* compute in s an approximation of S1 = sum((n-k)!/k!*y^k,k=0..n) return e >= 0 the exponent difference between the maximal value of |s| during the for loop and the final value of |s|. */ static mpfr_exp_t mpfr_yn_s1 (mpfr_ptr s, mpfr_srcptr y, unsigned long n) { unsigned long k; mpz_t f; mpfr_exp_t e, emax; mpz_init_set_ui (f, 1); /* we compute n!*S1 = sum(a[k]*y^k,k=0..n) where a[k] = n!*(n-k)!/k!, a[0] = (n!)^2, a[1] = n!*(n-1)!, ..., a[n-1] = n, a[n] = 1 */ mpfr_set_ui (s, 1, MPFR_RNDN); /* a[n] */ emax = MPFR_EXP(s); for (k = n; k-- > 0;) { /* a[k]/a[k+1] = (n-k)!/k!/(n-(k+1))!*(k+1)! = (k+1)*(n-k) */ mpfr_mul (s, s, y, MPFR_RNDN); mpz_mul_ui (f, f, n - k); mpz_mul_ui (f, f, k + 1); /* invariant: f = a[k] */ mpfr_add_z (s, s, f, MPFR_RNDN); e = MPFR_EXP(s); if (e > emax) emax = e; } /* now we have f = (n!)^2 */ mpz_sqrt (f, f); mpfr_div_z (s, s, f, MPFR_RNDN); mpz_clear (f); return emax - MPFR_EXP(s); }
static void generator_inverse_pi(Generator *gen, mpz_t pi1, mpz_t pi2, mpz_t seed) { int res; /* * Inverse pairing function that takes @seed as input and returns the * inverse-pair as @pi1 and @pi2. We use storage on @gen as temporary * variables, to avoid dynamic allocation on each call. */ /* CAREFUL: pi1/pi2/seed may *overlap*! */ mpz_sqrt(gen->root, seed); mpz_pow_ui(gen->root_squared, gen->root, 2); mpz_sub(gen->index, seed, gen->root_squared); res = mpz_cmp(gen->index, gen->root); if (res < 0) { mpz_sub(pi1, seed, gen->root_squared); mpz_set(pi2, gen->root); } else { mpz_sub(gen->index, seed, gen->root_squared); mpz_sub(pi2, gen->index, gen->root); mpz_set(pi1, gen->root); } }
mpz_class chudnovsky(int digits) { digits += EXTRA_DIGITS; const double digits_per_term = log10(151931373056000ll); // log(C_cubed_over_24 / 72); int N = int(digits / digits_per_term) + 1; std::cout << "Binary splitting max: " << N << std::endl; mpz_class P, Q, T; bs(0, N, P, Q, T); mpz_class one; mpz_ui_pow_ui(one.get_mpz_t(), 10, digits); mpz_class sqrt_10005 = one * 10005; mpz_sqrt(sqrt_10005.get_mpz_t(), sqrt_10005.get_mpz_t()); mpz_class pi = (Q * 426880 * sqrt_10005) / T; //int bin_digits = int(digits * log2(10)); //int precision = bin_digits + EXTRA_DIGITS; //std::cout << "Precision: " << precision << std::endl; //mpf_set_default_prec(precision); //mpf_class Q_float(Q); //mpf_class T_float(T); //mpf_class sqrt_10005; //mpf_sqrt_ui(sqrt_10005.get_mpf_t(), 10005); //std::cout << sqrt_10005 << std::endl; // Correct precision //mpf_class pi = (Q_float * 426880 * sqrt_10005) / T_float; return pi; }
/* See Cohen 1.5.2 */ int cornacchia(mpz_t x, mpz_t y, mpz_t D, mpz_t p) { int result = 0; mpz_t a, b, c, d; if (mpz_jacobi(D, p) < 0) /* No solution */ return 0; mpz_init(a); mpz_init(b); mpz_init(c); mpz_init(d); sqrtmod(x, D, p, a, b, c, d); mpz_set(a, p); mpz_set(b, x); mpz_sqrt(c, p); while (mpz_cmp(b,c) > 0) { mpz_set(d, a); mpz_set(a, b); mpz_mod(b, d, b); } mpz_mul(a, b, b); mpz_sub(a, p, a); /* a = p - b^2 */ mpz_abs(d, D); /* d = |D| */ if (mpz_divisible_p(a, d)) { mpz_divexact(c, a, d); if (mpz_perfect_square_p(c)) { mpz_set(x, b); mpz_sqrt(y, c); result = 1; } } mpz_clear(a); mpz_clear(b); mpz_clear(c); mpz_clear(d); return result; }
int main(int argc, char **argv) { char line[INTEGER_LIMIT]; if (argc > 1) strncpy(&line[0], argv[1], INTEGER_LIMIT); else if (scanf("%s\n", &line[0]) != 1) { fprintf(stderr, "factor: unable to read number from stdin\n"); return 1; } mpz_t n; mpz_init(n); if (mpz_set_str(n, &line[0], 0) == -1 || mpz_cmp_ui(n, 1) < 0) { fprintf(stderr, "factor: input must be a positive integer\n"); mpz_clear(n); return 1; } if (mpz_cmp_ui(n, 1) == 0 || mpz_probab_prime_p(n, MILLERRABIN_REPEATS) > 0) { gmp_printf("%Zd: %Zd\n", n, n); mpz_clear(n); return 0; } mpz_t t; mpz_init(t); mpz_sqrt(t, n); struct factors *f = factors_create(); struct prime_sieve *ps = prime_sieve_create(MIN(TRIALDIVISION_LIMIT, mpz_get_ui(t))); if (mpz_perfect_square_p(n)) { factors_push(f, t); factors_push(f, t); } else { mpz_set(t, n); factors_push(f, t); } /* run trial division to find find small factors */ while (factors_remove_composite(f, t) && trial_division(t, f, ps)); prime_sieve_destroy(ps); /* run quadratic sieve until factorized into only prime numbers */ while (factors_remove_composite(f, t) && quadratic_sieve(t, f, QUADRATIC_SIEVE_SIZE)); factors_sort(f); print_result(n, f); mpz_clears(n, t, NULL); factors_destroy(f); return 0; }
// Factor using lehman method. int _factor_lehman_method(mpz_class &rop, const mpz_class &n) { if (n < 21) throw std::runtime_error("Require n >= 21 to use lehman method"); int ret_val = 0; mpz_class u_bound; mpz_root(u_bound.get_mpz_t(), n.get_mpz_t(), 3); u_bound = u_bound + 1; Sieve::iterator pi(u_bound.get_ui()); unsigned p; while ((p = pi.next_prime()) <= u_bound.get_ui()) { if (n % p == 0) { rop = n / p; ret_val = 1; break; } } if (!ret_val) { mpz_class k, a, b, l; mpf_class t; k = 1; while (k <= u_bound) { t = 2 * sqrt(k * n); mpz_set_f(a.get_mpz_t(), t.get_mpf_t()); mpz_root(b.get_mpz_t(), n.get_mpz_t(), 6); mpz_root(l.get_mpz_t(), k.get_mpz_t(), 2); b = b / (4 * l); b = b + a; while (a <= b) { l = a * a - 4 * k * n; if (mpz_perfect_square_p(l.get_mpz_t())) { mpz_sqrt(b.get_mpz_t(), l.get_mpz_t()); b = a + b; mpz_gcd(rop.get_mpz_t(), n.get_mpz_t(), b.get_mpz_t()); ret_val = 1; break; } a = a + 1; } if (ret_val) break; k = k + 1; } } return ret_val; }
/* Return non-zero iff c+i*d is an exact square (a+i*b)^2, with a, b both of the form m*2^e with m, e integers. If so, returns in a+i*b the corresponding square root, with a >= 0. The variables a, b must not overlap with c, d. We have c = a^2 - b^2 and d = 2*a*b. If one of a, b is exact, then both are (see algorithms.tex). Case 1: a <> 0 and b <> 0. Let a = m*2^e and b = n*2^f with m, e, n, f integers, m and n odd (we will treat apart the case a = 0 or b = 0). Then 2*a*b = m*n*2^(e+f+1), thus necessarily e+f >= -1. Assume e < 0, then f >= 0, then a^2 - b^2 = m^2*2^(2e) - n^2*2^(2f) cannot be an integer, since n^2*2^(2f) is an integer, and m^2*2^(2e) is not. Similarly when f < 0 (and thus e >= 0). Thus we have e, f >= 0, and a, b are both integers. Let A = 2a^2, then eliminating b between c = a^2 - b^2 and d = 2*a*b gives A^2 - 2c*A - d^2 = 0, which has solutions c +/- sqrt(c^2+d^2). We thus need c^2+d^2 to be a square, and c + sqrt(c^2+d^2) --- the solution we are interested in --- to be two times a square. Then b = d/(2a) is necessarily an integer. Case 2: a = 0. Then d is necessarily zero, thus it suffices to check whether c = -b^2, i.e., if -c is a square. Case 3: b = 0. Then d is necessarily zero, thus it suffices to check whether c = a^2, i.e., if c is a square. */ static int mpc_perfect_square_p (mpz_t a, mpz_t b, mpz_t c, mpz_t d) { if (mpz_cmp_ui (d, 0) == 0) /* case a = 0 or b = 0 */ { /* necessarily c < 0 here, since we have already considered the case where x is real non-negative and y is real */ MPC_ASSERT (mpz_cmp_ui (c, 0) < 0); mpz_neg (b, c); if (mpz_perfect_square_p (b)) /* case 2 above */ { mpz_sqrt (b, b); mpz_set_ui (a, 0); return 1; /* c + i*d = (0 + i*b)^2 */ } } else /* both a and b are non-zero */ { if (mpz_divisible_2exp_p (d, 1) == 0) return 0; /* d must be even */ mpz_mul (a, c, c); mpz_addmul (a, d, d); /* c^2 + d^2 */ if (mpz_perfect_square_p (a)) { mpz_sqrt (a, a); mpz_add (a, c, a); /* c + sqrt(c^2+d^2) */ if (mpz_divisible_2exp_p (a, 1)) { mpz_tdiv_q_2exp (a, a, 1); if (mpz_perfect_square_p (a)) { mpz_sqrt (a, a); mpz_tdiv_q_2exp (b, d, 1); /* d/2 */ mpz_divexact (b, b, a); /* d/(2a) */ return 1; } } } } return 0; /* not a square */ }
/* return non zero iff x^y is exact. Assumes x and y are ordinary numbers (neither NaN nor Inf), and y is not zero. */ int mpfr_pow_is_exact (mpfr_srcptr x, mpfr_srcptr y) { mp_exp_t d; unsigned long i, c; mp_limb_t *yp; if ((mpfr_sgn (x) < 0) && (mpfr_isinteger (y) == 0)) return 0; if (mpfr_sgn (y) < 0) return mpfr_cmp_si_2exp (x, MPFR_SIGN(x), MPFR_EXP(x) - 1) == 0; /* compute d such that y = c*2^d with c odd integer */ d = MPFR_EXP(y) - MPFR_PREC(y); /* since y is not zero, necessarily one of the mantissa limbs is not zero, thus we can simply loop until we find a non zero limb */ yp = MPFR_MANT(y); for (i = 0; yp[i] == 0; i++, d += BITS_PER_MP_LIMB); /* now yp[i] is not zero */ count_trailing_zeros (c, yp[i]); d += c; if (d < 0) { mpz_t a; mp_exp_t b; mpz_init (a); b = mpfr_get_z_exp (a, x); /* x = a * 2^b */ c = mpz_scan1 (a, 0); mpz_div_2exp (a, a, c); b += c; /* now a is odd */ while (d != 0) { if (mpz_perfect_square_p (a)) { d++; mpz_sqrt (a, a); } else { mpz_clear (a); return 0; } } mpz_clear (a); } return 1; }
RCP<const Integer> isqrt(const Integer &n) { mpz_class m; mpz_t m_t; mpz_init(m_t); mpz_sqrt(m_t, n.as_mpz().get_mpz_t()); m = mpz_class(m_t); mpz_clear(m_t); return integer(m); }
/** * Returns sqrt(totient(r)) * log(n) which is used by step 5. */ void compute_upper_limit(mpz_t rop, mpz_t r, mpz_t n) { mpz_t tot, logn; mpz_init(tot); mpz_init(logn); totient(tot, r); if (aks_debug) gmp_printf("tot=%Zd\n", tot); mpz_sqrt(tot, tot); compute_logn(logn, n); mpz_mul(rop, tot, logn); mpz_clear(tot); mpz_clear(logn); }
/* Exercise mpz_perfect_square_p compared to what mpz_sqrt says. */ void check_sqrt (int reps) { mpz_t x2, x2t, x; mp_size_t x2n; int res; int i; /* int cnt = 0; */ gmp_randstate_ptr rands = RANDS; mpz_t bs; mpz_init (bs); mpz_init (x2); mpz_init (x); mpz_init (x2t); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 9); x2n = mpz_get_ui (bs); mpz_rrandomb (x2, rands, x2n); /* mpz_out_str (stdout, -16, x2); puts (""); */ res = mpz_perfect_square_p (x2); mpz_sqrt (x, x2); mpz_mul (x2t, x, x); if (res != (mpz_cmp (x2, x2t) == 0)) { printf ("mpz_perfect_square_p and mpz_sqrt differ\n"); mpz_trace (" x ", x); mpz_trace (" x2 ", x2); mpz_trace (" x2t", x2t); printf (" mpz_perfect_square_p %d\n", res); printf (" mpz_sqrt %d\n", mpz_cmp (x2, x2t) == 0); abort (); } /* cnt += res != 0; */ } /* printf ("%d/%d perfect squares\n", cnt, reps); */ mpz_clear (bs); mpz_clear (x2); mpz_clear (x); mpz_clear (x2t); }
int main(){ printf("ciao pippo1 \n"); mpz_t n; mpz_init(n); mpz_set_ui(n,4); printf("ciao pippo2 \n"); unsigned int p = 17; printf("ciao pippo3 \n"); mpz_t s; mpz_init(s); mpz_sqrt(s,n); printf("ciao pippo4 \n"); pair solution; printf("ciao pippo5 \n"); inizializza_pair(&solution); printf("ciao pippo6 \n"); unsigned int pippo=-3; printf("ciao pippo7 \n"); pippo = legendre(n,p); printf("ciao pippo8 \n"); printf("%d\n",pippo); pippo = legendre_sol(n,p,&solution); printf("ciao pippo9 \n"); printf("%d\n",pippo); printf("%d\n",solution.sol1); printf("%d\n",solution.sol2); }
//------------------------------------------------------------------------------ // Name: sqrt //------------------------------------------------------------------------------ knumber_base *knumber_integer::sqrt() { if(sign() < 0) { delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } if(mpz_perfect_square_p(mpz_)) { mpz_sqrt(mpz_, mpz_); return this; } else { knumber_float *f = new knumber_float(this); delete this; return f->sqrt(); } }
int isprime( mpz_t n ) { mpz_t i, n2, tmp; int d, ret; /* 1は素数ではない */ if( mpz_cmp_ui( n, 1 ) == 0 ) return( 0 ); /* 2,3は素数 */ if( mpz_cmp_ui( n, 2 ) == 0 || mpz_cmp_ui( n, 3 ) == 0 ) return( 1 ); /* 2,3で割り切れたら合成数 */ if( mpz_even_p( n ) || mpz_divisible_ui_p( n, 3 ) ) return( 0 ); mpz_init( i ); mpz_init( n2 ); mpz_init( tmp ); /* sqrt(n)+1を求める */ mpz_sqrt( n2, n ); /* n2以下の2,3の倍数以外での剰余が0かどうか調べる */ d = 2; mpz_set_ui( i, 5 ); ret = 1; while( mpz_cmp( i, n2 ) <= 0 ) { if( mpz_divisible_p( n, i ) ) { ret = 0; break; } mpz_add_ui( tmp, i, d ); mpz_set( i, tmp ); d = ( d == 2 ? 4 : 2 ); } mpz_clear( i ); mpz_clear( n2 ); mpz_clear( tmp ); return( ret ); }
unsigned int factorCount(mpz_t number) { mpz_t maxNumber; mpz_t counter; mpz_t q; mpz_t r; unsigned int result = 0; //if (mpz_cmp_ui(number, 1) == 0) // return 1; mpz_init_set(maxNumber, number); mpz_init(r); mpz_init(q); mpz_sqrt(maxNumber, number); for (mpz_init_set_ui(counter, 1); mpz_cmp(counter, maxNumber) <= 0; mpz_add_ui(counter, counter, 1)) if (mpz_divisible_p(number, counter)) result += 2; return result; }
void sieve_factor(mpz_t num) { mpz_t gmp_root; mpz_init(gmp_root); mpz_sqrt(gmp_root, num); if(mpz_root(gmp_root, num, 2) != 0) { mpz_set(factors[num_factors++], gmp_root); mpz_set(factors[num_factors++], gmp_root); mpz_clear(gmp_root); return; } fail = true; find_candidates(num, gmp_root); mpz_clear(gmp_root); }
inline vector<mpz_class> sieve_of_eratosthenes_factorization(const mpz_class& n) { mpz_class remaining = n; vector<mpz_class> factors; unsigned int limit = pow(2, 26); mpz_class tmp; mpz_sqrt(tmp.get_mpz_t(), n.get_mpz_t()); tmp++; if (tmp.fits_uint_p() && tmp < limit) { limit = tmp.get_ui(); } vector<bool> is_prime (limit, true); is_prime[0] = false; is_prime[1] = false; for (int i = 2; i < limit; i++) { if (is_prime[i]) { while (remaining % i == 0) { remaining /= i; factors.push_back(i); } for (int j = i*i; j < limit; j += i) { is_prime[j] = false; } } } // Don't forget the last factor if one exists. if (remaining > 1) factors.push_back(remaining); return factors; }
// ----------------------------------------------------------------------------- // Calculate a compressed Rabin signature (see Compressing Rabin Signatures, // Daniel Bleichenbacher) // // zsig: (output) the resulting signature // s: the Rabin signature // n: the composite group order // ----------------------------------------------------------------------------- static void signature_compress(mpz_t zsig, mpz_t s, mpz_t n) { mpz_t vs[4]; mpz_init_set_ui(vs[0], 0); mpz_init_set_ui(vs[1], 1); mpz_init(vs[2]); mpz_init(vs[3]); mpz_t root; mpz_init(root); mpz_sqrt(root, n); mpz_t cf; mpz_init(cf); unsigned i = 1; do { i = (i + 1) & 3; if (i & 1) { mpz_fdiv_qr(cf, s, s, n); } else { mpz_fdiv_qr(cf, n, n, s); } mpz_mul(vs[i], vs[(i-1)&3], cf); mpz_add(vs[i], vs[i], vs[(i-2)&3]); } while (mpz_cmp(vs[i], root) < 0); mpz_init(zsig); mpz_set(zsig, vs[(i-1) & 3]); mpz_clear(root); mpz_clear(cf); mpz_clear(vs[0]); mpz_clear(vs[1]); mpz_clear(vs[2]); mpz_clear(vs[3]); }
/* Compute log(2)/log(b) as a fixnum. */ void mp_2logb (mpz_t r, int bi, int prec) { mpz_t t, t2, two, b; int i; mpz_init_set_ui (t, 1); mpz_mul_2exp (t, t, prec+EXTRA); mpz_init (t2); mpz_init_set_ui (two, 2); mpz_mul_2exp (two, two, prec+EXTRA); mpz_set_ui (r, 0); mpz_init_set_ui (b, bi); mpz_mul_2exp (b, b, prec+EXTRA); for (i = prec-1; i >= 0; i--) { mpz_mul_2exp (b, b, prec+EXTRA); mpz_sqrt (b, b); mpz_mul (t2, t, b); mpz_tdiv_q_2exp (t2, t2, prec+EXTRA); if (mpz_cmp (t2, two) < 0) /* not too large? */ { mpz_setbit (r, i); /* set next less significant bit */ mpz_swap (t, t2); /* new value acceptable */ } } mpz_clear (t); mpz_clear (t2); mpz_clear (two); mpz_clear (b); }
int isPrime(mpz_t n) { mpz_t iterator; mpz_t maxIterator; mpz_t remainder; if (mpz_cmp_ui(n, 1) <= 0) // negatives, zero, 1 : not prime return 0; if (mpz_cmp_ui(n, 2) == 0) // 2 : prime return 1; mpz_init(remainder); mpz_init(iterator); mpz_init(maxIterator); mpz_sqrt(maxIterator, n); mpz_add_ui(maxIterator, maxIterator, 1); // round up for (mpz_set_ui(iterator, 2); mpz_cmp(iterator, maxIterator) <= 0; mpz_add_ui(iterator, iterator, 1)) { mpz_cdiv_r(remainder, n, iterator); if (mpz_cmp_ui(remainder, 0) == 0) return 0; } return 1; }
static Variant HHVM_FUNCTION(gmp_sqrt, const Variant& data) { mpz_t gmpReturn, gmpData; if (!variantToGMPData(cs_GMP_FUNC_NAME_GMP_SQRT, gmpData, data)) { return false; } if (mpz_sgn(gmpData) < 0) { raise_warning(cs_GMP_INVALID_NUMBER_IS_NEGATIVE, cs_GMP_FUNC_NAME_GMP_SQRT); return false; } mpz_init(gmpReturn); mpz_sqrt(gmpReturn, gmpData); Variant ret = NEWOBJ(GMPResource)(gmpReturn); mpz_clear(gmpData); mpz_clear(gmpReturn); return ret; }
int shankSquares(mpz_t *n) { mpz_t myN, constA, constB, tmp, tmp2; mpz_t Pi, Qi, Plast, Qlast, Qnext, bi; long counter = 1; int status = FAIL; printf("[INFO ] Trying shank squares\n"); mpz_init_set(myN, *n); mpz_init(tmp); mpz_init(tmp2); mpz_init(bi); mpz_init(Qnext); mpz_init(Pi); mpz_mul_ui(tmp, myN, SHANKQUAREK); // constA = k*N mpz_init_set(constA, tmp); mpz_sqrt(tmp, constA); // constB = floor(sqrt(constA)) mpz_init_set(constB, tmp); mpz_init_set(Plast, constB); mpz_pow_ui(tmp, Plast, 2); // Qi = (constA) - (Pi**2) mpz_sub(tmp, constA, tmp); mpz_init_set(Qi, tmp); mpz_init_set_ui(Qlast, 1); while (counter < SHANKQUAREMAX) { mpz_add(tmp, constB, Plast); //bi = floor( (constB) + (Plast) / Qi ) mpz_fdiv_q(bi, tmp, Qi); mpz_mul(tmp, bi, Qi); //Pi = (bi * Qi) - (Plast) mpz_sub(Pi, tmp, Plast); mpz_sub(tmp, Plast, Pi); //Qnext = Qlast + (bi * (Plast - Pi)) mpz_mul(tmp, tmp, bi); mpz_add(Qnext, Qlast, tmp); if (mpz_perfect_square_p(Qi) != 0 && counter % 2 == 0) { break; } else { mpz_set(Plast, Pi); mpz_set(Qlast, Qi); mpz_set(Qi, Qnext); } counter += 1; } mpz_sub(tmp, constB, Plast); //bi = floor( ( constB - Plast ) / sqrt(Qi) ) mpz_sqrt(tmp2, Qi); mpz_fdiv_q(bi, tmp, tmp2); mpz_sqrt(tmp, Qi); //Plast = (bi * sqrt(Qi)) + Plast mpz_mul(tmp, tmp, bi); mpz_add(Plast, tmp, Plast); mpz_sqrt(Qlast, Qi); mpz_pow_ui(tmp2, Plast, 2); //Qnext = ((constA) - Plast**2) / Qlast mpz_sub(tmp, constA, tmp2); mpz_div(Qnext, tmp, Qlast); mpz_set(Qi, Qnext); counter = 0; while (counter < SHANKQUAREMAX) { mpz_add(tmp, constB, Plast); //bi = floor( ( constB + Plast ) / Qi ) mpz_fdiv_q(bi, tmp, Qi); mpz_mul(tmp, bi, Qi); //Pi = (bi*Qi) - Plast mpz_sub(Pi, tmp, Plast); mpz_sub(tmp, Plast, Pi); //Qnext = Qlast + (bi * (Plast - Pi)) mpz_mul(tmp, tmp, bi); mpz_add(Qnext, Qlast, tmp); if (mpz_cmp(Pi, Plast) == 0) { break; } mpz_set(Plast, Pi); mpz_set(Qlast, Qi); mpz_set(Qi, Qnext); counter += 1; } mpz_gcd(tmp, myN, Pi); if (mpz_cmp_ui(tmp, 1) != 0 && mpz_cmp(tmp, myN) != 0) { printWin(&tmp, "Shanks squares"); status = WIN; } mpz_clear(myN); mpz_clear(constA); mpz_clear(constB); mpz_clear(tmp); mpz_clear(tmp2); mpz_clear(Pi); mpz_clear(Qi); mpz_clear(Plast); mpz_clear(Qlast); mpz_clear(Qnext); mpz_clear(bi); return status; }
//----------------------- NFS ENTRY POINT ------------------------------------// void nfs(fact_obj_t *fobj) { //expect the input in fobj->nfs_obj.gmp_n char *input; msieve_obj *obj = NULL; char *nfs_args = NULL; // unused as yet enum cpu_type cpu = yafu_get_cpu_type(); mp_t mpN; factor_list_t factor_list; uint32 flags = 0; nfs_job_t job; uint32 relations_needed = 1; uint32 last_specialq = 0; struct timeval stop; // stop time of this job struct timeval start; // start time of this job struct timeval bstop; // stop time of sieving batch struct timeval bstart; // start time of sieving batch TIME_DIFF * difference; double t_time; uint32 pre_batch_rels = 0; char tmpstr[GSTR_MAXSIZE]; int process_done; enum nfs_state_e nfs_state; // initialize some job parameters memset(&job, 0, sizeof(nfs_job_t)); obj_ptr = NULL; //below a certain amount, revert to SIQS if (gmp_base10(fobj->nfs_obj.gmp_n) < fobj->nfs_obj.min_digits) { mpz_set(fobj->qs_obj.gmp_n, fobj->nfs_obj.gmp_n); SIQS(fobj); mpz_set(fobj->nfs_obj.gmp_n, fobj->qs_obj.gmp_n); return; } if (mpz_probab_prime_p(fobj->nfs_obj.gmp_n, NUM_WITNESSES)) { add_to_factor_list(fobj, fobj->nfs_obj.gmp_n); if (VFLAG >= 0) gmp_printf("PRP%d = %Zd\n", gmp_base10(fobj->nfs_obj.gmp_n), fobj->nfs_obj.gmp_n); logprint_oc(fobj->flogname, "a", "PRP%d = %s\n", gmp_base10(fobj->nfs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); mpz_set_ui(fobj->nfs_obj.gmp_n, 1); return; } if (mpz_perfect_square_p(fobj->nfs_obj.gmp_n)) { mpz_sqrt(fobj->nfs_obj.gmp_n, fobj->nfs_obj.gmp_n); add_to_factor_list(fobj, fobj->nfs_obj.gmp_n); logprint_oc(fobj->flogname, "a", "prp%d = %s\n", gmp_base10(fobj->nfs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); add_to_factor_list(fobj, fobj->nfs_obj.gmp_n); logprint_oc(fobj->flogname, "a", "prp%d = %s\n", gmp_base10(fobj->nfs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); mpz_set_ui(fobj->nfs_obj.gmp_n, 1); return; } if (mpz_perfect_power_p(fobj->nfs_obj.gmp_n)) { FILE *flog; uint32 j; if (VFLAG > 0) printf("input is a perfect power\n"); factor_perfect_power(fobj, fobj->nfs_obj.gmp_n); flog = fopen(fobj->flogname, "a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for appending\n", fobj->flogname); exit(1); } logprint(flog,"input is a perfect power\n"); for (j=0; j<fobj->num_factors; j++) { uint32 k; for (k=0; k<fobj->fobj_factors[j].count; k++) { logprint(flog,"prp%d = %s\n",gmp_base10(fobj->fobj_factors[j].factor), mpz_conv2str(&gstr1.s, 10, fobj->fobj_factors[j].factor)); } } fclose(flog); return; } if (fobj->nfs_obj.filearg[0] != '\0') { if (VFLAG > 0) printf("test: starting trial sieving\n"); trial_sieve(fobj); return; } //initialize the flag to watch for interrupts, and set the //pointer to the function to call if we see a user interrupt NFS_ABORT = 0; signal(SIGINT,nfsexit); //start a counter for the whole job gettimeofday(&start, NULL); //nfs state machine: input = (char *)malloc(GSTR_MAXSIZE * sizeof(char)); nfs_state = NFS_STATE_INIT; process_done = 0; while (!process_done) { switch (nfs_state) { case NFS_STATE_INIT: // write the input bigint as a string input = mpz_conv2str(&input, 10, fobj->nfs_obj.gmp_n); // create an msieve_obj // this will initialize the savefile to the outputfile name provided obj = msieve_obj_new(input, flags, fobj->nfs_obj.outputfile, fobj->nfs_obj.logfile, fobj->nfs_obj.fbfile, g_rand.low, g_rand.hi, (uint32)0, cpu, (uint32)L1CACHE, (uint32)L2CACHE, (uint32)THREADS, (uint32)0, nfs_args); fobj->nfs_obj.mobj = obj; // initialize these before checking existing files. If poly // select is resumed they will be changed by check_existing_files. job.last_leading_coeff = 0; job.poly_time = 0; job.use_max_rels = 0; job.snfs = NULL; // determine what to do next based on the state of various files. // this will set job.current_rels if it finds any nfs_state = check_existing_files(fobj, &last_specialq, &job); // before we get started, check to make sure we can find ggnfs sievers // if we are going to be doing sieving if (check_for_sievers(fobj, 1) == 1) nfs_state = NFS_STATE_DONE; if (VFLAG >= 0 && nfs_state != NFS_STATE_DONE) gmp_printf("nfs: commencing nfs on c%d: %Zd\n", gmp_base10(fobj->nfs_obj.gmp_n), fobj->nfs_obj.gmp_n); if (nfs_state != NFS_STATE_DONE) logprint_oc(fobj->flogname, "a", "nfs: commencing nfs on c%d: %s\n", gmp_base10(fobj->nfs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); // convert input to msieve bigint notation and initialize a list of factors gmp2mp_t(fobj->nfs_obj.gmp_n,&mpN); factor_list_init(&factor_list); if (fobj->nfs_obj.rangeq > 0) job.qrange = ceil((double)fobj->nfs_obj.rangeq / (double)THREADS); break; case NFS_STATE_POLY: if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_POLY)) { // always check snfs forms (it is fast) snfs_choose_poly(fobj, &job); if( job.snfs == NULL ) { // either we never were doing snfs, or snfs form detect failed. // if the latter then bail with an error because the user // explicitly wants to run snfs... if (fobj->nfs_obj.snfs) { printf("nfs: failed to find snfs polynomial!\n"); exit(-1); } // init job.poly for gnfs job.poly = (mpz_polys_t*)malloc(sizeof(mpz_polys_t)); if (job.poly == NULL) { printf("nfs: couldn't allocate memory!\n"); exit(-1); } mpz_polys_init(job.poly); job.poly->rat.degree = 1; // maybe way off in the future this isn't true // assume gnfs for now job.poly->side = ALGEBRAIC_SPQ; do_msieve_polyselect(fobj, obj, &job, &mpN, &factor_list); } else { fobj->nfs_obj.snfs = 1; mpz_set(fobj->nfs_obj.gmp_n, job.snfs->n); } } nfs_state = NFS_STATE_SIEVE; break; case NFS_STATE_SIEVE: pre_batch_rels = job.current_rels; gettimeofday(&bstart, NULL); // sieve if the user has requested to (or by default). else, // set the done sieving flag. this will prevent some infinite loops, // for instance if we only want to post-process, but filtering // doesn't produce a matrix. if we don't want to sieve in that case, // then we're done. if (((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_SIEVE)) && !(fobj->nfs_obj.nfs_phases & NFS_DONE_SIEVING)) do_sieving(fobj, &job); else fobj->nfs_obj.nfs_phases |= NFS_DONE_SIEVING; // if this has been previously marked, then go ahead and exit. if (fobj->nfs_obj.nfs_phases & NFS_DONE_SIEVING) process_done = 1; // if user specified -ns with a fixed start and range, // then mark that we're done sieving. if (fobj->nfs_obj.rangeq > 0) { // we're done sieving the requested range, but there may be // more phases to check, so don't exit yet fobj->nfs_obj.nfs_phases |= NFS_DONE_SIEVING; } // then move on to the next phase nfs_state = NFS_STATE_FILTCHECK; break; case NFS_STATE_FILTER: // if we've flagged not to do filtering, then assume we have // enough relations and move on to linear algebra if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_FILTER)) relations_needed = do_msieve_filtering(fobj, obj, &job); else relations_needed = 0; if (relations_needed == 0) nfs_state = NFS_STATE_LINALG; else { // if we filtered, but didn't produce a matrix, raise the target // min rels by a few percent. this will prevent too frequent // filtering attempts while allowing the q_batch size to remain small. if (job.current_rels > job.min_rels) job.min_rels = job.current_rels * fobj->nfs_obj.filter_min_rels_nudge; else job.min_rels *= fobj->nfs_obj.filter_min_rels_nudge; if (VFLAG > 0) printf("nfs: raising min_rels by %1.2f percent to %u\n", 100*(fobj->nfs_obj.filter_min_rels_nudge-1), job.min_rels); nfs_state = NFS_STATE_SIEVE; } break; case NFS_STATE_LINALG: if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA_RESUME)) { // msieve: build matrix flags = 0; flags = flags | MSIEVE_FLAG_USE_LOGFILE; if (VFLAG > 0) flags = flags | MSIEVE_FLAG_LOG_TO_STDOUT; flags = flags | MSIEVE_FLAG_NFS_LA; // add restart flag if requested if (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA_RESUME) flags |= MSIEVE_FLAG_NFS_LA_RESTART; obj->flags = flags; if (VFLAG >= 0) printf("nfs: commencing msieve linear algebra\n"); logprint_oc(fobj->flogname, "a", "nfs: commencing msieve linear algebra\n"); // use a different number of threads for the LA, if requested if (LATHREADS > 0) { msieve_obj_free(obj); obj = msieve_obj_new(input, flags, fobj->nfs_obj.outputfile, fobj->nfs_obj.logfile, fobj->nfs_obj.fbfile, g_rand.low, g_rand.hi, (uint32)0, cpu, (uint32)L1CACHE, (uint32)L2CACHE, (uint32)LATHREADS, (uint32)0, nfs_args); } // try this hack - store a pointer to the msieve obj so that // we can change a flag on abort in order to interrupt the LA. obj_ptr = obj; nfs_solve_linear_system(obj, fobj->nfs_obj.gmp_n); if (obj_ptr->flags & MSIEVE_FLAG_STOP_SIEVING) nfs_state = NFS_STATE_DONE; else { // check for a .dat.deps file. if we don't have one, assume // its because the job was way oversieved and only trivial // dependencies were found. try again from filtering with // 20% less relations. FILE *t; sprintf(tmpstr, "%s.dep", fobj->nfs_obj.outputfile); if ((t = fopen(tmpstr, "r")) == NULL) { if (job.use_max_rels > 0) { // we've already tried again with an attempted fix to the trivial // dependencies problem, so either that wasn't the problem or // it didn't work. either way, give up. printf("nfs: no dependency file retry failed\n"); fobj->flags |= FACTOR_INTERRUPT; nfs_state = NFS_STATE_DONE; } else { // this should be sufficient to produce a matrix, but not too much // to trigger the assumed failure mode. if (job.min_rels == 0) { // if min_rels is not set, then we need to parse the .job file to compute it. parse_job_file(fobj, &job); nfs_set_min_rels(&job); } job.use_max_rels = job.min_rels * 1.5; printf("nfs: no dependency file found - trying again with %u relations\n", job.use_max_rels); nfs_state = NFS_STATE_FILTER; } } else { fclose(t); nfs_state = NFS_STATE_SQRT; } } // set the msieve threads back to where it was if we used // a different amount for linalg if (LATHREADS > 0) { msieve_obj_free(obj); obj = msieve_obj_new(input, flags, fobj->nfs_obj.outputfile, fobj->nfs_obj.logfile, fobj->nfs_obj.fbfile, g_rand.low, g_rand.hi, (uint32)0, cpu, (uint32)L1CACHE, (uint32)L2CACHE, (uint32)THREADS, (uint32)0, nfs_args); } obj_ptr = NULL; } else // not doing linalg nfs_state = NFS_STATE_SQRT; break; case NFS_STATE_SQRT: if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_SQRT)) { uint32 retcode; // msieve: find factors flags = 0; flags = flags | MSIEVE_FLAG_USE_LOGFILE; if (VFLAG > 0) flags = flags | MSIEVE_FLAG_LOG_TO_STDOUT; flags = flags | MSIEVE_FLAG_NFS_SQRT; obj->flags = flags; if (VFLAG >= 0) printf("nfs: commencing msieve sqrt\n"); logprint_oc(fobj->flogname, "a", "nfs: commencing msieve sqrt\n"); // try this hack - store a pointer to the msieve obj so that // we can change a flag on abort in order to interrupt the sqrt. obj_ptr = obj; retcode = nfs_find_factors(obj, fobj->nfs_obj.gmp_n, &factor_list); obj_ptr = NULL; if (retcode) { extract_factors(&factor_list,fobj); if (mpz_cmp_ui(fobj->nfs_obj.gmp_n, 1) == 0) nfs_state = NFS_STATE_CLEANUP; //completely factored, clean up everything else nfs_state = NFS_STATE_DONE; //not factored completely, keep files and stop } else { if (VFLAG >= 0) { printf("nfs: failed to find factors... possibly no dependencies found\n"); printf("nfs: continuing with sieving\n"); } logprint_oc(fobj->flogname, "a", "nfs: failed to find factors... " "possibly no dependencies found\n" "nfs: continuing with sieving\n"); nfs_state = NFS_STATE_SIEVE; } } else nfs_state = NFS_STATE_DONE; //not factored completely, keep files and stop break; case NFS_STATE_CLEANUP: remove(fobj->nfs_obj.outputfile); remove(fobj->nfs_obj.fbfile); sprintf(tmpstr, "%s.p",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.br",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.cyc",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.dep",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.hc",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.mat",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.lp",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.d",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.mat.chk",fobj->nfs_obj.outputfile); remove(tmpstr); gettimeofday(&stop, NULL); difference = my_difftime (&start, &stop); t_time = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if (VFLAG >= 0) printf("NFS elapsed time = %6.4f seconds.\n",t_time); logprint_oc(fobj->flogname, "a", "NFS elapsed time = %6.4f seconds.\n",t_time); logprint_oc(fobj->flogname, "a", "\n"); logprint_oc(fobj->flogname, "a", "\n"); // free stuff nfs_state = NFS_STATE_DONE; break; case NFS_STATE_DONE: process_done = 1; break; case NFS_STATE_FILTCHECK: if (job.current_rels >= job.min_rels) { if (VFLAG > 0) printf("nfs: found %u relations, need at least %u, proceeding with filtering ...\n", job.current_rels, job.min_rels); nfs_state = NFS_STATE_FILTER; } else { // compute eta by dividing how many rels we have left to find // by the average time per relation. we have average time // per relation because we've saved the time it took to do // the last batch of sieving and we know how many relations we // found in that batch. uint32 est_time; gettimeofday(&bstop, NULL); difference = my_difftime (&bstart, &bstop); t_time = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); est_time = (uint32)((job.min_rels - job.current_rels) * (t_time / (job.current_rels - pre_batch_rels))); // if the user doesn't want to sieve, then we can't make progress. if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_SIEVE)) { if (VFLAG > 0) printf("nfs: found %u relations, need at least %u " "(filtering ETA: %uh %um), continuing with sieving ...\n", // uh... um... hmm... idk *shrug* job.current_rels, job.min_rels, est_time / 3600, (est_time % 3600) / 60); nfs_state = NFS_STATE_SIEVE; } else { if (VFLAG > 0) printf("nfs: found %u relations, need at least %u " "(filtering ETA: %uh %um), sieving not selected, finishing ...\n", job.current_rels, job.min_rels, est_time / 3600, (est_time % 3600) / 60); nfs_state = NFS_STATE_DONE; } } break; case NFS_STATE_STARTNEW: nfs_state = NFS_STATE_POLY; // create a new directory for this job //#ifdef _WIN32 // sprintf(tmpstr, "%s\%s", fobj->nfs_obj.ggnfs_dir, // mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); // mkdir(tmpstr); //#else // sprintf(tmpstr, "%s/%s", fobj->nfs_obj.ggnfs_dir, // mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); // mkdir(tmpstr, S_IRWXU); //#endif // point msieve and ggnfs to the new directory //#ifdef _WIN32 // sprintf(fobj->nfs_obj.outputfile, "%s\%s", // tmpstr, fobj->nfs_obj.outputfile); // sprintf(fobj->nfs_obj.logfile, "%s\%s", // tmpstr, fobj->nfs_obj.logfile); // sprintf(fobj->nfs_obj.fbfile, "%s\%s", // tmpstr, fobj->nfs_obj.fbfile); //#else // sprintf(fobj->nfs_obj.outputfile, "%s%s", // tmpstr, fobj->nfs_obj.outputfile); // sprintf(fobj->nfs_obj.logfile, "%s%s", // tmpstr, fobj->nfs_obj.logfile); // sprintf(fobj->nfs_obj.fbfile, "%s%s", // tmpstr, fobj->nfs_obj.fbfile); // //#endif // // msieve_obj_free(fobj->nfs_obj.mobj); // obj = msieve_obj_new(input, flags, fobj->nfs_obj.outputfile, fobj->nfs_obj.logfile, // fobj->nfs_obj.fbfile, g_rand.low, g_rand.hi, (uint32)0, nfs_lower, nfs_upper, cpu, // (uint32)L1CACHE, (uint32)L2CACHE, (uint32)THREADS, (uint32)0, (uint32)0, 0.0); // fobj->nfs_obj.mobj = obj; // // printf("output: %s\n", fobj->nfs_obj.mobj->savefile.name); // printf("log: %s\n", fobj->nfs_obj.mobj->logfile_name); // printf("fb: %s\n", fobj->nfs_obj.mobj->nfs_fbfile_name); break; // should really be "resume_job", since we do more than just resume sieving... case NFS_STATE_RESUMESIEVE: // last_specialq == 0 if: // 1) user specifies -R and -ns with params // 2) user specifies post processing steps only // 3) user wants to resume sieving (either with a solo -ns or no arguements) // but no data file or special-q was found // 4) -R was not specified (but then we won't be in this state, we'll be in DONE) // last_specialq > 1 if: // 5) user wants to resume sieving (either with a solo -ns or no arguements) // and a data file and special-q was found // 6) it contains poly->time info (in which case we'll be in NFS_STATE_RESUMEPOLY) strcpy(tmpstr, ""); if ((last_specialq == 0) && ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_SIEVE))) { // this if-block catches cases 1 and 3 from above uint32 missing_params = parse_job_file(fobj, &job); // set min_rels. get_ggnfs_params(fobj, &job); fill_job_file(fobj, &job, missing_params); // if any ggnfs params are missing, fill them // this means the user can provide an SNFS poly or external GNFS poly, // but let YAFU choose the other params // this won't override any params in the file. if (fobj->nfs_obj.startq > 0) { job.startq = fobj->nfs_obj.startq; sprintf(tmpstr, "nfs: resuming with sieving at user specified special-q %u\n", job.startq); } else { // this is a guess, may be completely wrong job.startq = (job.poly->side == RATIONAL_SPQ ? job.rlim : job.alim) / 2; sprintf(tmpstr, "nfs: continuing with sieving - could not determine " "last special q; using default startq\n"); } // next step is sieving nfs_state = NFS_STATE_SIEVE; } else if ((last_specialq == 0) && ((fobj->nfs_obj.nfs_phases & NFS_PHASE_FILTER) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA_RESUME) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_SQRT))) { // this if-block catches case 2 from above // with these options we don't check for the last special-q, so this isn't // really a new factorization if ((fobj->nfs_obj.nfs_phases & NFS_PHASE_FILTER)) { nfs_state = NFS_STATE_FILTCHECK; sprintf(tmpstr, "nfs: resuming with filtering\n"); } else if ((fobj->nfs_obj.nfs_phases & NFS_PHASE_LA) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA_RESUME)) { nfs_state = NFS_STATE_LINALG; sprintf(tmpstr, "nfs: resuming with linear algebra\n"); } else if (fobj->nfs_obj.nfs_phases & NFS_PHASE_SQRT) { nfs_state = NFS_STATE_SQRT; sprintf(tmpstr, "nfs: resuming with sqrt\n"); } } else // data file already exists { // this if-block catches case 5 from above (void) parse_job_file(fobj, &job); // set min_rels. get_ggnfs_params(fobj, &job); if (fobj->nfs_obj.startq > 0) { // user wants to resume sieving. // i don't believe this case is ever executed... // because if startq is > 0, then last_specialq will be 0... job.startq = fobj->nfs_obj.startq; nfs_state = NFS_STATE_SIEVE; } else { job.startq = last_specialq; // we found some relations - find the appropriate state // given user input if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_FILTER)) { nfs_state = NFS_STATE_FILTCHECK; sprintf(tmpstr, "nfs: resuming with filtering\n"); } else if (fobj->nfs_obj.nfs_phases & NFS_PHASE_SIEVE) { nfs_state = NFS_STATE_SIEVE; sprintf(tmpstr, "nfs: resuming with sieving at special-q = %u\n", last_specialq); } else if ((fobj->nfs_obj.nfs_phases & NFS_PHASE_LA) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA_RESUME)) { nfs_state = NFS_STATE_LINALG; sprintf(tmpstr, "nfs: resuming with linear algebra\n"); } else if (fobj->nfs_obj.nfs_phases & NFS_PHASE_SQRT) { nfs_state = NFS_STATE_SQRT; sprintf(tmpstr, "nfs: resuming with sqrt\n"); } } } if (VFLAG >= 0) printf("%s", tmpstr); logprint_oc(fobj->flogname, "a", "%s", tmpstr); // if there is a job file and the user has specified -np, print // this warning. if (fobj->nfs_obj.nfs_phases & NFS_PHASE_POLY) { printf("WARNING: .job file exists! If you really want to redo poly selection," " delete the .job file.\n"); // non ideal solution to infinite loop in factor() if we return without factors // (should return error code instead) NFS_ABORT = 1; process_done = 1; } break; case NFS_STATE_RESUMEPOLY: if (VFLAG > 1) printf("nfs: resuming poly select\n"); fobj->nfs_obj.polystart = job.last_leading_coeff; nfs_state = NFS_STATE_POLY; break; default: printf("unknown state, bailing\n"); // non ideal solution to infinite loop in factor() if we return without factors // (should return error code instead) NFS_ABORT = 1; break; } //after every state, check elasped time against a specified timeout value gettimeofday(&stop, NULL); difference = my_difftime (&start, &stop); t_time = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if ((fobj->nfs_obj.timeout > 0) && (t_time > (double)fobj->nfs_obj.timeout)) { if (VFLAG >= 0) printf("NFS timeout after %6.4f seconds.\n",t_time); logprint_oc(fobj->flogname, "a", "NFS timeout after %6.4f seconds.\n",t_time); process_done = 1; } if (NFS_ABORT) { print_factors(fobj); exit(1); } } //reset signal handler to default (no handler). signal(SIGINT,NULL); if (obj != NULL) msieve_obj_free(obj); free(input); if( job.snfs ) { snfs_clear(job.snfs); free(job.snfs); } else if( job.poly ) { mpz_polys_free(job.poly); free(job.poly); } return; }
int main(int argc, char **argv) { gettimeofday(&start_global, NULL); print_lib_version(); mpz_init(N); mpz_t B; mpz_init(B); unsigned long int uBase; int64_t nb_primes; modular_root_t *modular_roots; uint64_t i, j; if (mpz_init_set_str(N, argv[1], 10) == -1) { printf("Cannot load N %s\n", argv[1]); exit(2); } mpz_t sqrtN, rem; mpz_init(sqrtN); mpz_init(rem); mpz_sqrtrem(sqrtN, rem, N); if (mpz_cmp_ui(rem, 0) != 0) /* if not perfect square, calculate the ceiling */ mpz_add_ui(sqrtN, sqrtN, 1); else /* N is a perfect square, factored! */ { printf("\n<<<[FACTOR]>>> %s\n", mpz_get_str(NULL, 10, sqrtN)); return 0; } if (mpz_probab_prime_p(N, 10) > 0) /* don't bother factoring */ { printf("N:%s is prime\n", mpz_get_str(NULL, 10, N)); exit(0); } OPEN_LOG_FILE("freq"); //-------------------------------------------------------- // calculate the smoothness base for the given N //-------------------------------------------------------- get_smoothness_base(B, N); /* if N is too small, the program will surely fail, please consider a pen and paper instead */ uBase = mpz_get_ui(B); printf("n: %s\tBase: %s\n", mpz_get_str(NULL, 10, N), mpz_get_str(NULL, 10, B)); //-------------------------------------------------------- // sieve primes that are less than the smoothness base using Eratosthenes sieve //-------------------------------------------------------- START_TIMER(); nb_primes = sieve_primes_up_to((int64_t) (uBase)); printf("\nPrimes found %" PRId64 " [Smoothness Base %lu]\n", nb_primes, uBase); STOP_TIMER_PRINT_TIME("\tEratosthenes Sieving done"); //-------------------------------------------------------- // fill the primes array with primes to which n is a quadratic residue //-------------------------------------------------------- START_TIMER(); primes = calloc(nb_primes, sizeof(int64_t)); nb_qr_primes = fill_primes_with_quadratic_residue(primes, N); /*for(i=0; i<nb_qr_primes; i++) printf("%" PRId64 "\n", primes[i]);*/ printf("\nN-Quadratic primes found %" PRId64 "\n", nb_qr_primes); STOP_TIMER_PRINT_TIME("\tQuadratic prime filtering done"); //-------------------------------------------------------- // calculate modular roots //-------------------------------------------------------- START_TIMER(); modular_roots = calloc(nb_qr_primes, sizeof(modular_root_t)); mpz_t tmp, r1, r2; mpz_init(tmp); mpz_init(r1); mpz_init(r2); for (i = 0; i < nb_qr_primes; i++) { mpz_set_ui(tmp, (unsigned long) primes[i]); mpz_sqrtm(r1, N, tmp); /* calculate the modular root */ mpz_neg(r2, r1); /* -q mod n */ mpz_mod(r2, r2, tmp); modular_roots[i].root1 = mpz_get_ui(r1); modular_roots[i].root2 = mpz_get_ui(r2); } mpz_clear(tmp); mpz_clear(r1); mpz_clear(r2); STOP_TIMER_PRINT_TIME("\nModular roots calculation done"); /*for(i=0; i<nb_qr_primes; i++) { printf("[%10" PRId64 "-> roots: %10u - %10u]\n", primes[i], modular_roots[i].root1, modular_roots[i].root2); }*/ //-------------------------------------------------------- // ***** initialize the matrix ***** //-------------------------------------------------------- START_TIMER(); init_matrix(&matrix, nb_qr_primes + NB_VECTORS_OFFSET, nb_qr_primes); mpz_init2(tmp_matrix_row, nb_qr_primes); STOP_TIMER_PRINT_TIME("\nMatrix initialized"); //-------------------------------------------------------- // [Sieving] //-------------------------------------------------------- START_TIMER(); mpz_t x, sieving_index, next_sieving_index; unsigned long ui_index, SIEVING_STEP = 50000; /* we sieve for 50000 elements at each loop */ uint64_t p_pow; smooth_number_t *x_squared; x_squared = calloc(SIEVING_STEP, sizeof(smooth_number_t)); smooth_numbers = calloc(nb_qr_primes + NB_VECTORS_OFFSET, sizeof(smooth_number_t)); mpz_init_set(x, sqrtN); mpz_init_set(sieving_index, x); mpz_init_set(next_sieving_index, x); mpz_t p; mpz_init(p); mpz_t str; mpz_init_set(str, sieving_index); printf("\nSieving ...\n"); //-------------------------------------------------------- // Init before sieving //-------------------------------------------------------- for (i = 0; i < SIEVING_STEP; i++) { mpz_init(x_squared[i].value_x); mpz_init(x_squared[i].value_x_squared); /* the factors_exp array is used to keep track of exponents */ //x_squared[i].factors_exp = calloc(nb_qr_primes, sizeof(uint64_t)); /* we use directly the exponents vector modulo 2 to preserve space */mpz_init2( x_squared[i].factors_vect, nb_qr_primes); mpz_add_ui(x, x, 1); } int nb_smooth_per_round = 0; char s[512]; //-------------------------------------------------------- // WHILE smooth numbers found less than the primes in the smooth base + NB_VECTORS_OFFSET //-------------------------------------------------------- while (nb_smooth_numbers_found < nb_qr_primes + NB_VECTORS_OFFSET) { nb_smooth_per_round = 0; mpz_set(x, next_sieving_index); /* sieve numbers from sieving_index to sieving_index + sieving_step */ mpz_set(sieving_index, next_sieving_index); printf("\r"); printf( "\t\tSieving at: %s30 <--> Smooth numbers found: %" PRId64 "/%" PRId64 "", mpz_get_str(NULL, 10, sieving_index), nb_smooth_numbers_found, nb_qr_primes); fflush(stdout); for (i = 0; i < SIEVING_STEP; i++) { mpz_set(x_squared[i].value_x, x); mpz_pow_ui(x_squared[i].value_x_squared, x, 2); /* calculate value_x_squared <- x²-n */ mpz_sub(x_squared[i].value_x_squared, x_squared[i].value_x_squared, N); mpz_clear(x_squared[i].factors_vect); mpz_init2(x_squared[i].factors_vect, nb_qr_primes); /* reconstruct a new fresh 0ed vector of size nb_qr_primes bits */ mpz_add_ui(x, x, 1); } mpz_set(next_sieving_index, x); //-------------------------------------------------------- // eliminate factors in the x_squared array, those who are 'destructed' to 1 are smooth //-------------------------------------------------------- for (i = 0; i < nb_qr_primes; i++) { mpz_set_ui(p, (unsigned long) primes[i]); mpz_set(x, sieving_index); /* get the first multiple of p that is directly larger that sieving_index * Quadratic SIEVING: all elements from this number and in positions multiples of root1 and root2 * are also multiples of p */ get_sieving_start_index(x, x, p, modular_roots[i].root1); mpz_set(str, x); mpz_sub(x, x, sieving_index); /* x contains index of first number that is divisible by p */ for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) { p_pow = mpz_remove(x_squared[j].value_x_squared, x_squared[j].value_x_squared, p); /* eliminate all factors of p */ if (p_pow & 1) /* mark bit if odd power of p exists in this x_squared[j] */ { mpz_setbit(x_squared[j].factors_vect, i); } if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) { save_smooth_number(x_squared[j]); nb_smooth_per_round++; } /* sieve next element located p steps from here */ } /* same goes for root2 */ if (modular_roots[i].root2 == modular_roots[i].root1) continue; mpz_set(x, sieving_index); get_sieving_start_index(x, x, p, modular_roots[i].root2); mpz_set(str, x); mpz_sub(x, x, sieving_index); for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) { p_pow = mpz_remove(x_squared[j].value_x_squared, x_squared[j].value_x_squared, p); if (p_pow & 1) { mpz_setbit(x_squared[j].factors_vect, i); } if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) { save_smooth_number(x_squared[j]); nb_smooth_per_round++; } } } //printf("\tSmooth numbers found %" PRId64 "\n", nb_smooth_numbers_found); /*sprintf(s, "[start: %s - end: %s - step: %" PRId64 "] nb_smooth_per_round: %d", mpz_get_str(NULL, 10, sieving_index), mpz_get_str(NULL, 10, next_sieving_index), SIEVING_STEP, nb_smooth_per_round); APPEND_TO_LOG_FILE(s);*/ } STOP_TIMER_PRINT_TIME("\nSieving DONE"); uint64_t t = 0; //-------------------------------------------------------- //the matrix ready, start Gauss elimination. The Matrix is filled on the call of save_smooth_number() //-------------------------------------------------------- START_TIMER(); gauss_elimination(&matrix); STOP_TIMER_PRINT_TIME("\nGauss elimination done"); //print_matrix_matrix(&matrix); //print_matrix_identity(&matrix); uint64_t row_index = nb_qr_primes + NB_VECTORS_OFFSET - 1; /* last row in the matrix */ int nb_linear_relations = 0; mpz_t linear_relation_z, solution_z; mpz_init(linear_relation_z); mpz_init(solution_z); get_matrix_row(linear_relation_z, &matrix, row_index--); /* get the last few rows in the Gauss eliminated matrix*/ while (mpz_cmp_ui(linear_relation_z, 0) == 0) { nb_linear_relations++; get_matrix_row(linear_relation_z, &matrix, row_index--); } printf("\tLinear dependent relations found : %d\n", nb_linear_relations); //-------------------------------------------------------- // Factor //-------------------------------------------------------- //We use the last linear relation to reconstruct our solution START_TIMER(); printf("\nFactorizing..\n"); mpz_t solution_X, solution_Y; mpz_init(solution_X); mpz_init(solution_Y); /* we start testing from the first linear relation encountered in the matrix */ for (j = nb_linear_relations; j > 0; j--) { printf("Trying %d..\n", nb_linear_relations - j + 1); mpz_set_ui(solution_X, 1); mpz_set_ui(solution_Y, 1); get_identity_row(solution_z, &matrix, nb_qr_primes + NB_VECTORS_OFFSET - j + 1); for (i = 0; i < nb_qr_primes; i++) { if (mpz_tstbit(solution_z, i)) { mpz_mul(solution_X, solution_X, smooth_numbers[i].value_x); mpz_mod(solution_X, solution_X, N); /* reduce x to modulo N */ mpz_mul(solution_Y, solution_Y, smooth_numbers[i].value_x_squared); /*TODO: handling huge stuff here, there is no modulo N like in the solution_X case! * eliminate squares as long as you go*/ } } mpz_sqrt(solution_Y, solution_Y); mpz_mod(solution_Y, solution_Y, N); /* y = sqrt(MUL(xi²-n)) mod N */ mpz_sub(solution_X, solution_X, solution_Y); mpz_gcd(solution_X, solution_X, N); if (mpz_cmp(solution_X, N) != 0 && mpz_cmp_ui(solution_X, 1) != 0) /* factor can be 1 or N, try another relation */ break; } mpz_cdiv_q(solution_Y, N, solution_X); printf("\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N)); printf("\tFactor 1: %s \n\tFactor 2: %s", mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y)); /*sprintf(s, "\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N)); APPEND_TO_LOG_FILE(s); sprintf(s, "\tFactor 1: %s \n\tFactor 2: %s", mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y)); APPEND_TO_LOG_FILE(s); gettimeofday(&end_global, NULL); timersub(&end_global, &start_global, &elapsed); sprintf(s, "****** TOTAL TIME: %.3f ms\n", elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000); APPEND_TO_LOG_FILE(s);*/ STOP_TIMER_PRINT_TIME("\nFactorizing done"); printf("Cleaning memory..\n"); /********************** clear the x_squared array **********************/ for (i = 0; i < SIEVING_STEP; i++) { mpz_clear(x_squared[i].value_x); mpz_clear(x_squared[i].value_x_squared); //free(x_squared[i].factors_exp); mpz_clear(x_squared[i].factors_vect); } free(x_squared); /********************** clear the x_squared array **********************/ free(modular_roots); /********************** clear the smooth_numbers array **********************/ for (i = 0; i < nb_qr_primes + NB_VECTORS_OFFSET; i++) { mpz_clear(smooth_numbers[i].value_x); mpz_clear(smooth_numbers[i].value_x_squared); //free(smooth_numbers[i].factors_exp); } free(smooth_numbers); /********************** clear the smooth_numbers array **********************/ free(primes); /********************** clear mpz _t **********************/mpz_clear(B); mpz_clear(N); sqrtN, rem; mpz_clear(x); mpz_clear(sieving_index); mpz_clear(next_sieving_index); mpz_clear(p); mpz_clear(str); /********************** clear mpz _t **********************/ free_matrix(&matrix); gettimeofday(&end_global, NULL); timersub(&end_global, &start_global, &elapsed); printf("****** TOTAL TIME: %.3f ms\n", elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000); show_mem_usage(); return 0; }
void poly_init(QS_t * qs_inf, poly_t * poly_inf, mpz_t N) { unsigned long num_primes = qs_inf->num_primes; unsigned long s = (qs_inf->bits-1)/28+1; if (s <= 2) s = 3; prime_t * factor_base = qs_inf->factor_base; unsigned long fact_approx, fact, span; unsigned long sieve_size = qs_inf->sieve_size; unsigned long small_primes = qs_inf->small_primes; long min; poly_inf->s = s; poly_inf->B = (unsigned long*) flint_stack_alloc(qs_inf->prec+1); poly_inf->B_terms = (unsigned long*) flint_stack_alloc(s*(qs_inf->prec+1)); poly_inf->A = (unsigned long*) flint_stack_alloc(qs_inf->prec+1); poly_inf->target_A = (unsigned long*) flint_stack_alloc(qs_inf->prec+1); poly_inf->A_ind = (unsigned long*) flint_stack_alloc(s); poly_inf->A_modp = (unsigned long*) flint_stack_alloc(s); poly_inf->A_inv2B = (uint32_t**) flint_stack_alloc(s); poly_inf->inv_p2 = (double*) flint_stack_alloc_bytes(s*sizeof(double)); poly_inf->A_inv = (uint32_t *) flint_stack_alloc_bytes(num_primes*sizeof(uint32_t)); poly_inf->soln1 = (uint32_t *) flint_stack_alloc_bytes(num_primes*sizeof(uint32_t)); poly_inf->soln2 = (uint32_t *) flint_stack_alloc_bytes(num_primes*sizeof(uint32_t)); poly_inf->posn1 = (uint32_t *) flint_stack_alloc_bytes(num_primes*sizeof(uint32_t)); poly_inf->posn2 = (uint32_t *) flint_stack_alloc_bytes(num_primes*sizeof(uint32_t)); uint32_t ** A_inv2B = poly_inf->A_inv2B; A_inv2B[0] = (uint32_t *) flint_stack_alloc_bytes(num_primes*s*sizeof(uint32_t)); mpz_init(poly_inf->A_mpz); mpz_init(poly_inf->B_mpz); mpz_init(poly_inf->C); for (unsigned long i = 1; i < s; i++) { A_inv2B[i] = A_inv2B[i-1] + num_primes; } mpz_t temp; mpz_init(temp); mpz_mul_ui(temp, N, 2*qs_inf->k); mpz_sqrt(temp, temp); mpz_div_ui(temp, temp, 47*sieve_size/100); mpz_to_fmpz(poly_inf->target_A, temp); mpz_root(temp, temp, s); fact_approx = mpz_get_ui(temp); for (fact = 0; fact_approx >= factor_base[fact].p; fact++); span = num_primes/s/s/2; if (span < 6*s) span = 6*s; min = fact - span/2; if (min < (long) small_primes) min = small_primes; if (min + span >= qs_inf->num_primes - 1) span = num_primes - min - 1; fact = min + span/2; #if POLY_PARAMS printf("min = FB[%ld], span = %ld, number of factors = %ld\n", min, span, s); #endif poly_inf->min = min; poly_inf->fact = fact; poly_inf->span = span; mpz_clear(temp); }
extern void _jl_mpz_sqrt(mpz_t* rop, mpz_t* op) { mpz_sqrt(*rop, *op); }
unsigned int sieve( mpz_t n, unsigned int* factor_base, unsigned int base_dim, pair* solutions, unsigned int** exponents, mpz_t* As, unsigned int poly_val_num, unsigned int max_fact, unsigned int intervals ) { unsigned int i; unsigned int** expo2; init_matrix(&expo2, intervals, base_dim); word** is_used_expo2; init_matrix_l(&is_used_expo2, 1, (intervals / N_BITS) + 1); for(i = 0; i < ((intervals / N_BITS) + 1); ++i) { set_matrix_l(is_used_expo2, 0, i, 0); } mpz_t n_root; mpz_t intermed; mpz_init(n_root); mpz_init(intermed); mpz_sqrt(n_root, n); unsigned char go_on = 1; unsigned int fact_count = 0; unsigned int j, k; mpz_t* evaluated_poly; init_vector_mpz(&evaluated_poly, poly_val_num); word** is_used; init_matrix_l(&is_used, 1, (poly_val_num / N_BITS) + 1); for(i = 0; i < ((poly_val_num / N_BITS) + 1); ++i) { set_matrix_l(is_used, 0, i, 0); } max_fact += base_dim; // Trovo poly_val_num valori del polinomio (A + s)^2 - n, variando A for(i = 0; i < poly_val_num; ++i) { mpz_add_ui(intermed, n_root, i); mpz_mul(intermed, intermed, intermed); mpz_sub(evaluated_poly[i], intermed, n); mpz_add_ui(As[i], n_root, i); } // Per ogni primo nella base di fattori for(i = 0; i < base_dim && go_on; ++i) { // Provo tutte le possibili fattorizzazioni nella base di fattori for(j = solutions[i].sol1; j < poly_val_num && go_on; j += factor_base[i]) { // Divido e salvo l'esponente va bene while(mpz_divisible_ui_p(evaluated_poly[j], factor_base[i])) { // Se non sono mai stati usati gli esponenti if(get_k_i(is_used, 0, j) == 0) { for(k = 0; k < base_dim; ++k) set_matrix(exponents, j, k, 0); set_k_i(is_used, 0, j, 1); } set_matrix(exponents, j, i, get_matrix(exponents, j, i) + 1); // ++exponents[j][i]; mpz_divexact_ui(evaluated_poly[j], evaluated_poly[j], factor_base[i]); } if(mpz_cmp_ui(evaluated_poly[j], 1) == 0) { ++fact_count; if(fact_count >= max_fact) { go_on = 0; } } } // Faccio la stessa cosa con entrambe le soluzioni, a meno che non stia usando 2 if(factor_base[i] != 2) { for(j = solutions[i].sol2; j < poly_val_num && go_on; j += factor_base[i]) { while(mpz_divisible_ui_p(evaluated_poly[j], factor_base[i])) { // Se non sono mai stati usati gli esponenti if(get_k_i(is_used, 0, j) == 0) { for(k = 0; k < base_dim; ++k) set_matrix(exponents, j, k, 0); set_k_i(is_used, 0, j, 1); } set_matrix(exponents, j, i, get_matrix(exponents, j, i) + 1); // ++exponents[j][i]; mpz_divexact_ui(evaluated_poly[j], evaluated_poly[j], factor_base[i]); } if(mpz_cmp_ui(evaluated_poly[j], 1) == 0) { ++fact_count; if(fact_count >= max_fact) { go_on = 0; } } } } } mpz_clear(n_root); mpz_clear(intermed); remove_not_factorized(exponents, evaluated_poly, As, poly_val_num, base_dim); // finalize_vector_mpz(&evaluated_poly, poly_val_num); // Si noti che questa istruzione apparentemente innocua porta all'uscita di demoni dal naso del programmatore return fact_count; }