static PyObject * GMPy_MPZ_Function_IsSquare(PyObject *self, PyObject *other) { int res; MPZ_Object *tempx; if (MPZ_Check(other)) { res = mpz_perfect_square_p(MPZ(other)); } else { if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) { TYPE_ERROR("is_square() requires 'mpz' argument"); return NULL; } else { res = mpz_perfect_square_p(tempx->z); Py_DECREF((PyObject*)tempx); } } if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
/* 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; }
int main(int argc, const char **argv) { char str[100]; uint64_t n, maxn; if(argc > 1) maxn=atoll(argv[1]); else maxn=1000; mpz_t fac; mpz_t fac_plus; mpz_init_set_ui(fac, 1UL); mpz_init_set_ui(fac_plus, 1UL); for(n = 2; n < maxn; n++) { // fac *= n; mpz_mul_ui(fac, fac, n); // fac_plus = fac + 1; mpz_add_ui(fac_plus, fac, 1UL); if(mpz_perfect_square_p(fac_plus)) printf("found %" PRIu64 "\n", n); else if(0){ mpz_get_str(str, 10, fac_plus); printf("n=1: n!+1=%s\n", str); } } printf("last checked n=%" PRIu64 "\n", n); return 0; }
int main() { unsigned long long a,b; mpz_t a2, b3, v, sum; mpz_init(a2); mpz_init(b3); mpz_init(v); mpz_init_set_ui(sum, 0); for (b = 1; b < sqrt(MAX); b++) { mpz_ui_pow_ui(b3, b, 3); for (a = 1; a < b ; a++) { mpz_ui_pow_ui(a2, a, 2); mpz_add(v, a2, b3); if (!mpz_divisible_ui_p(v, a)) { continue; } mpz_div_ui(v, v, a); if (mpz_perfect_square_p(v)) { mpz_add(sum, sum, v); printf("%s %llu %llu\n", mpz_get_str(NULL, 10, v), a, b); } } } return(0); }
// NOTE: Runs in 1 minutes. Not satisfactory. // // Gotta redo this using Pythagorean triples int main() { const int N = 1000000000; mpz_class sumOfPerimeters = 0, p = 0; for (int n = 3; 3 * n + 1 <= N; n += 2) { // HACK p = 3 * n - 1; p *= n + 1; if (mpz_perfect_square_p(p.get_mpz_t())) sumOfPerimeters += 3 * n - 1; p = 3 * n + 1; p *= n - 1; if (mpz_perfect_square_p(p.get_mpz_t())) sumOfPerimeters += 3 * n + 1; } std::cout << sumOfPerimeters << "\n"; return 0; }
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 */ }
static PyObject * GMPy_MPZ_Method_IsSquare(PyObject *self, PyObject *other) { int res; res = mpz_perfect_square_p(MPZ(self)); if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
/* 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; }
static bool HHVM_FUNCTION(gmp_perfect_square, const Variant& data) { mpz_t gmpData; if (!variantToGMPData(cs_GMP_FUNC_NAME_GMP_PERFECT_SQUARE, gmpData, data)) { return false; } bool isPerfectSquare = (mpz_perfect_square_p(gmpData) != 0); mpz_clear(gmpData); return isPerfectSquare; }
int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_square...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; int r1, r2; fmpz_init(a); mpz_init(b); fmpz_randtest(a, state, 200); if (n_randint(state, 2) == 0) fmpz_mul(a, a, a); fmpz_get_mpz(b, a); r1 = fmpz_is_square(a); r2 = mpz_perfect_square_p(b); result = (r1 == r2); if (!result) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd\n", b); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; }
/* 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); }
//------------------------------------------------------------------------------ // 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(); } }
/* 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; }
void check_modulo (void) { static const unsigned long divisor[] = PERFSQR_DIVISORS; unsigned long i, j; mpz_t alldiv, others, n; mpz_init (alldiv); mpz_init (others); mpz_init (n); /* product of all divisors */ mpz_set_ui (alldiv, 1L); for (i = 0; i < numberof (divisor); i++) mpz_mul_ui (alldiv, alldiv, divisor[i]); for (i = 0; i < numberof (divisor); i++) { /* product of all divisors except i */ mpz_set_ui (others, 1L); for (j = 0; j < numberof (divisor); j++) if (i != j) mpz_mul_ui (others, others, divisor[j]); for (j = 1; j <= divisor[i]; j++) { /* square */ mpz_mul_ui (n, others, j); mpz_mul (n, n, n); if (! mpz_perfect_square_p (n)) { printf ("mpz_perfect_square_p got 0, want 1\n"); mpz_trace (" n", n); abort (); } } } mpz_clear (alldiv); mpz_clear (others); mpz_clear (n); }
int check_specialcase(FILE *sieve_log, fact_obj_t *fobj) { //check for some special cases of input number //sieve_log is passed in already open, and should return open if (mpz_even_p(fobj->qs_obj.gmp_n)) { printf("input must be odd\n"); return 1; } if (mpz_probab_prime_p(fobj->qs_obj.gmp_n, NUM_WITNESSES)) { add_to_factor_list(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) logprint(sieve_log,"prp%d = %s\n", gmp_base10(fobj->qs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n)); mpz_set_ui(fobj->qs_obj.gmp_n,1); return 1; } if (mpz_perfect_square_p(fobj->qs_obj.gmp_n)) { mpz_sqrt(fobj->qs_obj.gmp_n,fobj->qs_obj.gmp_n); add_to_factor_list(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->qs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n)); add_to_factor_list(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->qs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n)); mpz_set_ui(fobj->qs_obj.gmp_n,1); return 1; } if (mpz_perfect_power_p(fobj->qs_obj.gmp_n)) { if (VFLAG > 0) printf("input is a perfect power\n"); factor_perfect_power(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) { uint32 j; logprint(sieve_log,"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(sieve_log,"prp%d = %s\n",gmp_base10(fobj->fobj_factors[j].factor), mpz_conv2str(&gstr1.s, 10, fobj->fobj_factors[j].factor)); } } } return 1; } if (mpz_sizeinbase(fobj->qs_obj.gmp_n,2) < 115) { //run MPQS, as SIQS doesn't work for smaller inputs //MPQS will take over the log file, so close it now. int i; // we've verified that the input is not odd or prime. also // do some very quick trial division before calling smallmpqs, which // does none of these things. for (i=1; i<25; i++) { if (mpz_tdiv_ui(fobj->qs_obj.gmp_n, spSOEprimes[i]) == 0) mpz_tdiv_q_ui(fobj->qs_obj.gmp_n, fobj->qs_obj.gmp_n, spSOEprimes[i]); } smallmpqs(fobj); return 1; //tells SIQS to not try to close the logfile } if (gmp_base10(fobj->qs_obj.gmp_n) > 140) { printf("input too big for SIQS\n"); return 1; } return 0; }
/* return non zero iff x^y is exact. Assumes x and y are ordinary numbers, y is not an integer, x is not a power of 2 and x is positive If x^y is exact, it computes it and sets *inexact. */ static int mpfr_pow_is_exact (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode, int *inexact) { mpz_t a, c; mpfr_exp_t d, b; unsigned long i; int res; MPFR_ASSERTD (!MPFR_IS_SINGULAR (y)); MPFR_ASSERTD (!MPFR_IS_SINGULAR (x)); MPFR_ASSERTD (!mpfr_integer_p (y)); MPFR_ASSERTD (mpfr_cmp_si_2exp (x, MPFR_INT_SIGN (x), MPFR_GET_EXP (x) - 1) != 0); MPFR_ASSERTD (MPFR_IS_POS (x)); if (MPFR_IS_NEG (y)) return 0; /* x is not a power of two => x^-y is not exact */ /* compute d such that y = c*2^d with c odd integer */ mpz_init (c); d = mpfr_get_z_2exp (c, y); i = mpz_scan1 (c, 0); mpz_fdiv_q_2exp (c, c, i); d += i; /* now y=c*2^d with c odd */ /* Since y is not an integer, d is necessarily < 0 */ MPFR_ASSERTD (d < 0); /* Compute a,b such that x=a*2^b */ mpz_init (a); b = mpfr_get_z_2exp (a, x); i = mpz_scan1 (a, 0); mpz_fdiv_q_2exp (a, a, i); b += i; /* now x=a*2^b with a is odd */ for (res = 1 ; d != 0 ; d++) { /* a*2^b is a square iff (i) a is a square when b is even (ii) 2*a is a square when b is odd */ if (b % 2 != 0) { mpz_mul_2exp (a, a, 1); /* 2*a */ b --; } MPFR_ASSERTD ((b % 2) == 0); if (!mpz_perfect_square_p (a)) { res = 0; goto end; } mpz_sqrt (a, a); b = b / 2; } /* Now x = (a'*2^b')^(2^-d) with d < 0 so x^y = ((a'*2^b')^(2^-d))^(c*2^d) = ((a'*2^b')^c with c odd integer */ { mpfr_t tmp; mpfr_prec_t p; MPFR_MPZ_SIZEINBASE2 (p, a); mpfr_init2 (tmp, p); /* prec = 1 should not be possible */ res = mpfr_set_z (tmp, a, MPFR_RNDN); MPFR_ASSERTD (res == 0); res = mpfr_mul_2si (tmp, tmp, b, MPFR_RNDN); MPFR_ASSERTD (res == 0); *inexact = mpfr_pow_z (z, tmp, c, rnd_mode); mpfr_clear (tmp); res = 1; } end: mpz_clear (a); mpz_clear (c); return res; }
static PyObject * GMPY_mpz_is_strongselfridge_prp(PyObject *self, PyObject *args) { MPZ_Object *n; PyObject *result = 0, *temp = 0; long d = 5, p = 1, q = 0, max_d = 1000000; int jacobi = 0; mpz_t zD; if (PyTuple_Size(args) != 1) { TYPE_ERROR("is_strong_selfridge_prp() requires 1 integer argument"); return NULL; } mpz_init(zD); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); if (!n) { TYPE_ERROR("is_strong_selfridge_prp() requires 1 integer argument"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_strong_selfridge_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } mpz_set_ui(zD, d); while (1) { jacobi = mpz_jacobi(zD, n->z); /* if jacobi == 0, d is a factor of n, therefore n is composite... */ /* if d == n, then either n is either prime or 9... */ if (jacobi == 0) { if ((mpz_cmpabs(zD, n->z) == 0) && (mpz_cmp_ui(zD, 9) != 0)) { result = Py_True; goto cleanup; } else { result = Py_False; goto cleanup; } } if (jacobi == -1) break; /* if we get to the 5th d, make sure we aren't dealing with a square... */ if (d == 13) { if (mpz_perfect_square_p(n->z)) { result = Py_False; goto cleanup; } } if (d < 0) { d *= -1; d += 2; } else { d += 2; d *= -1; } /* make sure we don't search forever */ if (d >= max_d) { VALUE_ERROR("appropriate value for D cannot be found in is_strong_selfridge_prp()"); goto cleanup; } mpz_set_si(zD, d); } q = (1-d)/4; /* Since "O" is used, the refcount for n is incremented so deleting * temp will not delete n. */ temp = Py_BuildValue("Oll", n, p, q); if (!temp) goto cleanup; result = GMPY_mpz_is_stronglucas_prp(NULL, temp); Py_DECREF(temp); goto return_result; cleanup: Py_XINCREF(result); return_result: mpz_clear(zD); Py_DECREF((PyObject*)n); return result; }
int perfect_square(const Integer &n) { return mpz_perfect_square_p(n.as_mpz().get_mpz_t()); }
//----------------------- 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 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; }
void zFermat(uint64 limit, uint32 mult, fact_obj_t *fobj) { // Fermat's factorization method with a sieve-based improvement // provided by 'neonsignal' mpz_t a, b2, tmp, multN, a2; int i; int numChars; uint64 reportIt, reportInc; uint64 count; uint64 i64; FILE *flog = NULL; uint32 M = 2 * 2 * 2 * 2 * 3 * 3 * 5 * 5 * 7 * 7; //176400u uint32 M1 = 11 * 17 * 23 * 31; //133331u uint32 M2 = 13 * 19 * 29 * 37; //265031u uint8 *sqr, *sqr1, *sqr2, *mod, *mod1, *mod2; uint16 *skip; uint32 m, mmn, s, d; uint8 masks[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; uint8 nmasks[8]; uint32 iM = 0, iM1 = 0, iM2 = 0; if (mpz_even_p(fobj->div_obj.gmp_n)) { mpz_init(tmp); mpz_set_ui(tmp, 2); mpz_tdiv_q_2exp(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, 1); add_to_factor_list(fobj, tmp); mpz_clear(tmp); return; } if (mpz_perfect_square_p(fobj->div_obj.gmp_n)) { //open the log file flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for writing\n",fobj->flogname); return; } mpz_sqrt(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n); if (is_mpz_prp(fobj->div_obj.gmp_n)) { logprint(flog, "Fermat method found perfect square factorization:\n"); logprint(flog,"prp%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); logprint(flog,"prp%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); } else { logprint(flog, "Fermat method found perfect square factorization:\n"); logprint(flog,"c%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); logprint(flog,"c%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); } add_to_factor_list(fobj, fobj->div_obj.gmp_n); add_to_factor_list(fobj, fobj->div_obj.gmp_n); mpz_set_ui(fobj->div_obj.gmp_n, 1); fclose(flog); return; } mpz_init(a); mpz_init(b2); mpz_init(tmp); mpz_init(multN); mpz_init(a2); // apply the user supplied multiplier mpz_mul_ui(multN, fobj->div_obj.gmp_n, mult); // compute ceil(sqrt(multN)) mpz_sqrt(a, multN); // form b^2 mpz_mul(b2, a, a); mpz_sub(b2, b2, multN); // test successive 'a' values using a sieve-based approach. // the idea is that not all 'a' values allow a^2 or b^2 to be square. // we pre-compute allowable 'a' values modulo various smooth numbers and // build tables to allow us to quickly iterate over 'a' values that are // more likely to produce squares. // init sieve structures sqr = (uint8 *)calloc((M / 8 + 1) , sizeof(uint8)); sqr1 = (uint8 *)calloc((M1 / 8 + 1) , sizeof(uint8)); sqr2 = (uint8 *)calloc((M2 / 8 + 1) , sizeof(uint8)); mod = (uint8 *)calloc((M / 8 + 1) , sizeof(uint8)); mod1 = (uint8 *)calloc((M1 / 8 + 1) , sizeof(uint8)); mod2 = (uint8 *)calloc((M2 / 8 + 1) , sizeof(uint8)); skip = (uint16 *)malloc(M * sizeof(uint16)); // test it. This will be good enough if |u*p-v*q| < 2 * N^(1/4), where // mult = u*v count = 0; if (mpz_perfect_square_p(b2)) goto found; for (i=0; i<8; i++) nmasks[i] = ~masks[i]; // marks locations where squares can occur mod M, M1, M2 for (i64 = 0; i64 < M; ++i64) setbit(sqr, (i64*i64)%M); for (i64 = 0; i64 < M1; ++i64) setbit(sqr1, (i64*i64)%M1); for (i64 = 0; i64 < M2; ++i64) setbit(sqr2, (i64*i64)%M2); // for the modular sequence of b*b = a*a - n values // (where b2_2 = b2_1 * 2a + 1), mark locations where // b^2 can be a square m = mpz_mod_ui(tmp, a, M); mmn = mpz_mod_ui(tmp, b2, M); for (i = 0; i < M; ++i) { if (getbit(sqr, mmn)) setbit(mod, i); mmn = (mmn+m+m+1)%M; m = (m+1)%M; } // we only consider locations where the modular sequence mod M can // be square, so compute the distance to the next square location // at each possible value of i mod M. s = 0; d = 0; for (i = 0; !getbit(mod,i); ++i) ++s; for (i = M; i > 0;) { --i; ++s; skip[i] = s; if (s > d) d = s; if (getbit(mod,i)) s = 0; } //printf("maxSkip = %u\n", d); // for the modular sequence of b*b = a*a - n values // (where b2_2 = b2_1 * 2a + 1), mark locations where the // modular sequence can be a square mod M1. These will // generally differ from the sequence mod M. m = mpz_mod_ui(tmp, a, M1); mmn = mpz_mod_ui(tmp, b2, M1); for (i = 0; i < M1; ++i) { if (getbit(sqr1, mmn)) setbit(mod1, i); mmn = (mmn+m+m+1)%M1; m = (m+1)%M1; } // for the modular sequence of b*b = a*a - n values // (where b2_2 = b2_1 * 2a + 1), mark locations where the // modular sequence can be a square mod M2. These will // generally differ from the sequence mod M or M1. m = mpz_mod_ui(tmp, a, M2); mmn = mpz_mod_ui(tmp, b2, M2); for (i = 0; i < M2; ++i) { if (getbit(sqr2, mmn)) setbit(mod2, i); mmn = (mmn+m+m+1)%M2; m = (m+1)%M2; } // loop, checking for perfect squares mpz_mul_2exp(a2, a, 1); count = 0; numChars = 0; reportIt = limit / 100; reportInc = reportIt; do { d = 0; i64 = 0; do { // skip to the next possible square residue of b*b mod M s = skip[iM]; // remember how far we skipped d += s; // update the other residue indices if ((iM1 += s) >= M1) iM1 -= M1; if ((iM2 += s) >= M2) iM2 -= M2; if ((iM += s) >= M) iM -= M; // some multpliers can lead to infinite loops. bail out // if so. if (++i64 > M) goto done; // continue if either of the other residues indicates // non-square. } while (!getbit(mod1,iM1) || !getbit(mod2,iM2)); // form b^2 by incrementing by many factors of 2*a+1 mpz_add_ui(tmp, a2, d); mpz_mul_ui(tmp, tmp, d); mpz_add(b2, b2, tmp); // accumulate so that we can reset d // (and thus keep it single precision) mpz_add_ui(a2, a2, d*2); count += d; if (count > limit) break; //progress report if ((count > reportIt) && (VFLAG > 1)) { for (i=0; i< numChars; i++) printf("\b"); numChars = printf("%" PRIu64 "%%",(uint64)((double)count / (double)limit * 100)); fflush(stdout); reportIt += reportInc; } } while (!mpz_perfect_square_p(b2)); found: // 'count' is how far we had to scan 'a' to find a square b mpz_add_ui(a, a, count); //printf("count is %" PRIu64 "\n", count); if ((mpz_size(b2) > 0) && mpz_perfect_square_p(b2)) { //printf("found square at count = %d: a = %s, b2 = %s",count, // z2decstr(&a,&gstr1),z2decstr(&b2,&gstr2)); mpz_sqrt(tmp, b2); mpz_add(tmp, a, tmp); mpz_gcd(tmp, fobj->div_obj.gmp_n, tmp); flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for writing\n",fobj->flogname); goto done; } logprint(flog, "Fermat method found factors:\n"); add_to_factor_list(fobj, tmp); if (is_mpz_prp(tmp)) { logprint(flog,"prp%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } else { logprint(flog,"c%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } mpz_tdiv_q(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, tmp); mpz_sqrt(tmp, b2); mpz_sub(tmp, a, tmp); mpz_gcd(tmp, fobj->div_obj.gmp_n, tmp); add_to_factor_list(fobj, tmp); if (is_mpz_prp(tmp)) { logprint(flog,"prp%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } else { logprint(flog,"c%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } mpz_tdiv_q(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, tmp); } done: mpz_clear(tmp); mpz_clear(a); mpz_clear(b2); mpz_clear(multN); mpz_clear(a2); free(sqr); free(sqr1); free(sqr2); free(mod); free(mod1); free(mod2); free(skip); if (flog != NULL) fclose(flog); return; }
/* *********************************************************************************************** * mpz_selfridge_prp: * A "Lucas-Selfridge pseudoprime" n is a "Lucas pseudoprime" using Selfridge parameters of: * Find the first element D in the sequence {5, -7, 9, -11, 13, ...} such that Jacobi(D,n) = -1 * Then use P=1 and Q=(1-D)/4 in the Lucas pseudoprime test. * Make sure n is not a perfect square, otherwise the search for D will only stop when D=n. * ***********************************************************************************************/ int mpz_selfridge_prp(mpz_t n) { long int d = 5, p = 1, q = 0; int max_d = 1000000; int jacobi = 0; mpz_t zD; if (mpz_cmp_ui(n, 2) < 0) return PRP_COMPOSITE; if (mpz_divisible_ui_p(n, 2)) { if (mpz_cmp_ui(n, 2) == 0) return PRP_PRIME; else return PRP_COMPOSITE; } mpz_init_set_ui(zD, d); while (1) { jacobi = mpz_jacobi(zD, n); /* if jacobi == 0, d is a factor of n, therefore n is composite... */ /* if d == n, then either n is either prime or 9... */ if (jacobi == 0) { if ((mpz_cmpabs(zD, n) == 0) && (mpz_cmp_ui(zD, 9) != 0)) { mpz_clear(zD); return PRP_PRIME; } else { mpz_clear(zD); return PRP_COMPOSITE; } } if (jacobi == -1) break; /* if we get to the 5th d, make sure we aren't dealing with a square... */ if (d == 13) { if (mpz_perfect_square_p(n)) { mpz_clear(zD); return PRP_COMPOSITE; } } if (d < 0) { d *= -1; d += 2; } else { d += 2; d *= -1; } /* make sure we don't search forever */ if (d >= max_d) { mpz_clear(zD); return PRP_ERROR; } mpz_set_si(zD, d); } mpz_clear(zD); q = (1-d)/4; return mpz_lucas_prp(n, p, q); }/* method mpz_selfridge_prp */
/* * Run the randomized quadratic frobenius test to check whether [n] is a a * prime. The Parameter [k] determines how many times the test will be run at * most. If the test returns "composite", it will not be run again. */ int main(int argc, char *argv[]) { Primality result; #define VARS n, b, c, bb4c mpz_t VARS; uint64_t n_, b_ = 0, c_; uint64_t false_positives = 0; uint64_t lower_bound = 5, upper_bound = 1000000; mpz_inits(VARS, NULL); if (argc > 2) lower_bound = strtoul(argv[1], NULL, 10); if (argc > 1) upper_bound = strtoul(argv[argc > 2 ? 2 : 1], NULL, 10); printf("%lu to %lu\n", lower_bound, upper_bound); for (n_ = lower_bound | 1; n_ <= upper_bound; n_+=2) { mpz_set_ui(n, n_); if (mpz_perfect_square_p(n) || mpz_probab_prime_p(n, 100)) continue; #ifdef SMALL_C for (c_ = 2; c_ < n_; c_++) { if (jacobi(n_ - c_, n_) != 1) continue; #else c_ = n_ - 4; mpz_sub_ui(c, n, 4); #endif for (b_ = 1; b_ < n_; b_++) { mpz_mul(bb4c, b, b); mpz_addmul_ui(bb4c, c, 4); mpz_mod(bb4c, bb4c, n); if (mpz_jacobi(bb4c, n) == -1) break; if (b_ % 1000 == 999) { fprintf(stderr, "Could not find a valid parameter pair (b, c)\n"); goto next_n; } } #ifdef SMALL_C break; } #endif result = steps_3_4_5(n, b, c); if (result != composite) { false_positives++; fflush(stdout); printf("Found a false positive: n = %lu, b = %lu, c = %lu\n", n_, b_, c_); } if (n_ % 10000000 == 1) { fprintf(stderr, "."); fflush(stderr); } next_n: ; } printf("\nA total number of %lu false positives were found among the numbers %lu,...,%lu\n", false_positives, lower_bound, upper_bound); mpz_clears(VARS, NULL); return 0; }