int solovay_strassen(mpz_t n, int k) { int i; for (i = 0; i < primes_count && mpz_cmp_si(n, primes[i]*primes[i]) >= 0; i++) if (mpz_divisible_ui_p(n, primes[i])) // Check if current prime divides n return 0; if (mpz_cmp_si(n, 2) < 0) return 0; if (mpz_cmp_si(n, 2) == 0) return 1; if (mpz_divisible_ui_p(n, 2)) return 0; gmp_randstate_t RAND; gmp_randinit_default(RAND); mpz_t a, jac, mod, exp, n1; mpz_init(a); mpz_init(jac); mpz_init(mod); mpz_init(exp); mpz_init(n1); mpz_sub_ui(n1, n, 1); while (k > 0) { k--; mpz_urandomm(a, RAND, n1); mpz_add_ui(a, a, 1); int j = jacobi(a, n); if (j == -1) { // jac = n + jac(a,n) mpz_sub_ui(jac, n, 1); } else if (j == 1) mpz_set_si(jac, j); mpz_divexact_ui(exp, n1, 2); // exp = (n-1)/2 mpz_powm(mod, a, exp, n); // mod = a^((n-1)/2) % n if (mpz_cmp_ui(jac, 0) == 0 || mpz_cmp(mod, jac) != 0) { // Is it a liar? mpz_clear(a); mpz_clear(jac); mpz_clear(mod); mpz_clear(exp); mpz_clear(n1); return 0; } } mpz_clear(a); mpz_clear(jac); mpz_clear(mod); mpz_clear(exp); mpz_clear(n1); return 1; }
static int has_small_prime_factor(mpz_t n) { for (unsigned i = 0; i < len(prime_list); i++) if (mpz_divisible_ui_p(n, prime_list[i])) return 1; return 0; }
void pollard(mpz_t x_1, mpz_t x_2, mpz_t d, mpz_t n, int init, int c, int counter) { if(mpz_divisible_ui_p(n, 2)) { mpz_set_ui(d, 2); return; } mpz_set_ui(x_1, init); NEXT_VALUE(x_1, x_1, n, c); NEXT_VALUE(x_2, x_1, n, c); mpz_set_ui(d, 1); while (mpz_cmp_ui(d, 1) == 0) { NEXT_VALUE(x_1, x_1, n, c); NEXT_VALUE(x_2, x_2, n, c); NEXT_VALUE(x_2, x_2, n, c); mpz_sub(d, x_2, x_1); mpz_abs(d, d); mpz_gcd(d, d, n); if (counter < 0) { mpz_set_ui(d, 0); return; } else { --counter; } } if(mpz_cmp(d, n) == 0) { return pollard(x_1, x_2, d, n, primes[RAND], primes[RAND], counter); } }
void check_one (mpz_srcptr a, mpz_srcptr d, int want) { int got; if (mpz_fits_ulong_p (d)) { unsigned long u = mpz_get_ui (d); got = (mpz_divisible_ui_p (a, u) != 0); if (want != got) { printf ("mpz_divisible_ui_p wrong\n"); printf (" expected %d got %d\n", want, got); mpz_trace (" a", a); printf (" d=%lu\n", u); mp_trace_base = -16; mpz_trace (" a", a); printf (" d=0x%lX\n", u); abort (); } } got = (mpz_divisible_p (a, d) != 0); if (want != got) { printf ("mpz_divisible_p wrong\n"); printf (" expected %d got %d\n", want, got); mpz_trace (" a", a); mpz_trace (" d", d); mp_trace_base = -16; mpz_trace (" a", a); mpz_trace (" d", d); abort (); } }
static PyObject * GMPy_MPZ_Method_IsDivisible(PyObject *self, PyObject *other) { unsigned long temp; int error, res; MPZ_Object *tempd; temp = GMPy_Integer_AsUnsignedLongAndError(other, &error); if (!error) { res = mpz_divisible_ui_p(MPZ(self), temp); if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; } if (!(tempd = GMPy_MPZ_From_Integer(other, NULL))) { TYPE_ERROR("is_divisible() requires integer argument"); return NULL; } res = mpz_divisible_p(MPZ(self), tempd->z); Py_DECREF((PyObject*)tempd); if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
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); }
/* ************************************************************************* * mpz_euler_prp: (also called a Solovay-Strassen pseudoprime) * An "Euler pseudoprime" to the base a is an odd composite number n with, * (a,n)=1 such that a^((n-1)/2)=(a/n) mod n [(a/n) is the Jacobi symbol] * *************************************************************************/ int mpz_euler_prp(mpz_t n, mpz_t a) { mpz_t res; mpz_t exp; int ret = 0; if (mpz_cmp_ui(a, 2) < 0) return PRP_ERROR; 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(res, 0); mpz_gcd(res, n, a); if (mpz_cmp_ui(res, 1) > 0) { mpz_clear(res); return PRP_COMPOSITE; } mpz_init_set(exp, n); mpz_sub_ui(exp, exp, 1); /* exp = n-1 */ mpz_divexact_ui(exp, exp, 2); /* exp = (n-1)/2 */ mpz_powm(res, a, exp, n); /* reuse exp to calculate jacobi(a,n) mod n */ ret = mpz_jacobi(a,n); mpz_set(exp, n); if (ret == -1) mpz_sub_ui(exp, exp, 1); else if (ret == 1) mpz_add_ui(exp, exp, 1); mpz_mod(exp, exp, n); if (mpz_cmp(res, exp) == 0) { mpz_clear(res); mpz_clear(exp); return PRP_PRP; } else { mpz_clear(res); mpz_clear(exp); return PRP_COMPOSITE; } }/* method mpz_euler_prp */
int jacobi(mpz_t aa, mpz_t nn) // Generalization of Legendre's symbol. { mpz_t a, n, n2; mpz_init_set(a, aa); mpz_init_set(n, nn); mpz_init(n2); if (mpz_divisible_p(a, n)) return 0; // (0/n) = 0 int ans = 1; if (mpz_cmp_ui(a, 0) < 0) { mpz_neg(a, a); // (a/n) = (-a/n)*(-1/n) if (mpz_congruent_ui_p(n, 3, 4)) // if n%4 == 3 ans = -ans; // (-1/n) = -1 if n = 3 (mod 4) } if (mpz_cmp_ui(a, 1) == 0) { mpz_clear(a); mpz_clear(n); mpz_clear(n2); return ans; // (1/n) = 1 } while (mpz_cmp_ui(a, 0) != 0) { if (mpz_cmp_ui(a, 0) < 0) { mpz_neg(a, a); // (a/n) = (-a/n)*(-1/n) if (mpz_congruent_ui_p(n, 3, 4)) // if n%4 == 3 ans = -ans; // (-1/n) = -1 if n = 3 ( mod 4 ) } while (mpz_divisible_ui_p(a, 2)) { mpz_divexact_ui(a, a, 2); // a = a/2 if (mpz_congruent_ui_p(n, 3, 8) || mpz_congruent_ui_p(n, 5, 8)) // n%8==3 || n%8==5 ans = -ans; } mpz_swap(a, n); // (a,n) = (n,a) if (mpz_congruent_ui_p(a, 3, 4) && mpz_congruent_ui_p(n, 3, 4)) // a%4==3 && n%4==3 ans = -ans; mpz_mod(a, a, n); // because (a/p) = (a%p / p ) and a%pi = (a%n)%pi if n % pi = 0 mpz_cdiv_q_ui(n2, n, 2); if (mpz_cmp(a, n2) > 0) // a > n/2 mpz_sub(a, a, n); // a = a-n } int cmp = mpz_cmp_ui(n, 1); mpz_clear(a); mpz_clear(n); mpz_clear(n2); if (cmp == 0) return ans; return 0; }
int aks_is_prime(mpz_t n) { // Peform simple checks before running the AKS algorithm if (mpz_cmp_ui(n, 2) == 0) { return PRIME; } if (mpz_cmp_ui(n, 1) <= 0 || mpz_divisible_ui_p(n, 2)) { return COMPOSITE; } // Step 1: Check if n is a perfect power, meaning n = a ^ b where a is a natural number and b > 1 if (mpz_perfect_power_p(n)) { return COMPOSITE; } // Step 2: Find the smallest r such that or(n) > log(n) ^ 2 mpz_t r; mpz_init(r); find_smallest_r(r, n); if (aks_debug) gmp_printf("r=%Zd\n", r); // Step 3: Check if there exists an a <= r such that 1 < (a,n) < n if (check_a_exists(n, r)) { mpz_clear(r); return COMPOSITE; } if (aks_debug) gmp_printf("a does not exist\n"); // Step 4: Check if n <= r if (mpz_cmp(n, r) <= 0) { mpz_clear(r); return PRIME; } if (aks_debug) gmp_printf("checking polynomial equation\n"); // Step 5 if (check_polys(r, n)) { mpz_clear(r); return COMPOSITE; } mpz_clear(r); // Step 6 return PRIME; }
/* Search the index to start sieving for one number */ uint64_t search_index_to_start_sieving(smooth_number_t** smooth_array, uint64_t size_base, uint64_t prime_number, mpz_t root){ uint64_t i; smooth_number_t* smooth; mpz_t remainder; mpz_init(remainder); for( i = 0; i < size_base; i++){ smooth = smooth_array[i]; // mpz_mod_ui(remainder, smooth->f_x, prime_number); if(mpz_divisible_ui_p(smooth->f_x, prime_number)){ return i; } } return -1; }
/* ****************************************************************** * mpz_prp: (also called a Fermat pseudoprime) * A "pseudoprime" to the base a is a composite number n such that, * (a,n)=1 and a^(n-1) = 1 mod n * ******************************************************************/ int mpz_prp(mpz_t n, mpz_t a) { mpz_t res; mpz_t nm1; if (mpz_cmp_ui(a, 2) < 0) return PRP_ERROR; 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(res, 0); mpz_gcd(res, n, a); if (mpz_cmp_ui(res, 1) > 0) { mpz_clear(res); return PRP_COMPOSITE; } mpz_init_set(nm1, n); mpz_sub_ui(nm1, nm1, 1); mpz_powm(res, a, nm1, n); if (mpz_cmp_ui(res, 1) == 0) { mpz_clear(res); mpz_clear(nm1); return PRP_PRP; } else { mpz_clear(res); mpz_clear(nm1); return PRP_COMPOSITE; } }/* method mpz_prp */
void pollard_brent(mpz_t x_1, mpz_t x_2, mpz_t d, mpz_t n, int init, int c, int counter) { int i; for(i = 0; i < 10000; ++i) { if(mpz_divisible_ui_p(n, primes[i])) { mpz_set_ui(d, primes[i]); return; } } unsigned long power = 1; unsigned long lam = 1; mpz_set_ui(x_1, init); mpz_set_ui(d, 1); while(mpz_cmp_ui(d, 1) == 0) { if (power == lam) { mpz_set(x_2, x_1); power *= 2; lam = 0; } mpz_mul(x_1, x_1, x_1); mpz_add_ui(x_1, x_1, c); mpz_mod(x_1, x_1, n); mpz_sub(d, x_2, x_1); mpz_abs(d, d); mpz_gcd(d, d, n); lam++; if (counter < 0) { mpz_set_ui(d, 0); return; } else { --counter; } } if(mpz_cmp(d, n) == 0) { return pollard_brent(x_1, x_2, d, n, rand(), rand(), counter); } }
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 ); }
// Check Fermat probable primality test (2-PRP): 2 ** (n-1) = 1 (mod n) // true: n is probable prime // false: n is composite; set fractional length in the nLength output static bool FermatProbablePrimalityTestFast(const mpz_class& n, unsigned int& nLength, CPrimalityTestParams& testParams, bool fFastDiv = false) { // Faster GMP version mpz_t& mpzN = testParams.mpzN; mpz_t& mpzE = testParams.mpzE; mpz_t& mpzR = testParams.mpzR; const unsigned int nPrimorialSeq = testParams.nPrimorialSeq; mpz_set(mpzN, n.get_mpz_t()); if (fFastDiv) { // Fast divisibility tests // Starting from the first prime not included in the round primorial const unsigned int nBeginSeq = nPrimorialSeq + 1; const unsigned int nEndSeq = nBeginSeq + nFastDivPrimes; for (unsigned int nPrimeSeq = nBeginSeq; nPrimeSeq < nEndSeq; nPrimeSeq++) { if (mpz_divisible_ui_p(mpzN, vPrimes[nPrimeSeq])) { return false; } } } ++fermats; mpz_sub_ui(mpzE, mpzN, 1); mpz_powm(mpzR, mpzTwo.get_mpz_t(), mpzE, mpzN); if (mpz_cmp_ui(mpzR, 1) == 0) { return true; } // Failed Fermat test, calculate fractional length mpz_sub(mpzE, mpzN, mpzR); mpz_mul_2exp(mpzR, mpzE, nFractionalBits); mpz_tdiv_q(mpzE, mpzR, mpzN); unsigned int nFractionalLength = mpz_get_ui(mpzE); if (nFractionalLength >= (1 << nFractionalBits)) { cout << "FermatProbablePrimalityTest() : fractional assert" << endl; return false; } nLength = (nLength & TARGET_LENGTH_MASK) | nFractionalLength; return false; }
static PyObject * GMPy_MPZ_Function_IsDivisible(PyObject *self, PyObject *args) { unsigned long temp; int error, res; MPZ_Object *tempx, *tempd; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("is_divisible() requires 2 integer arguments"); return NULL; } if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) { return NULL; } temp = GMPy_Integer_AsUnsignedLongAndError(PyTuple_GET_ITEM(args, 1), &error); if (!error) { res = mpz_divisible_ui_p(tempx->z, temp); Py_DECREF((PyObject*)tempx); if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; } if (!(tempd = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) { TYPE_ERROR("is_divisible() requires 2 integer arguments"); Py_DECREF((PyObject*)tempx); return NULL; } res = mpz_divisible_p(tempx->z, tempd->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempd); if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
static PyObject * GMPY_mpz_is_strong_prp(PyObject *self, PyObject *args) { MPZ_Object *a, *n; PyObject *result = 0; mpz_t s, nm1, mpz_test; mp_bitcnt_t r = 0; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_strong_prp() requires 2 integer arguments"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!a || !n) { TYPE_ERROR("is_strong_prp() requires 2 integer arguments"); goto cleanup; } mpz_init(s); mpz_init(nm1); mpz_init(mpz_test); /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_strong_prp() requires 'a' greater than or equal to 2"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_strong_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; } /* Check gcd(a,b) */ mpz_gcd(s, n->z, a->z); if (mpz_cmp_ui(s, 1) > 0) { VALUE_ERROR("is_strong_prp() requires gcd(n,a) == 1"); goto cleanup; } mpz_set(nm1, n->z); mpz_sub_ui(nm1, nm1, 1); /* Find s and r satisfying: n-1=(2^r)*s, s odd */ r = mpz_scan1(nm1, 0); mpz_fdiv_q_2exp(s, nm1, r); /* Check a^((2^t)*s) mod n for 0 <= t < r */ mpz_powm(mpz_test, a->z, s, n->z); if ((mpz_cmp_ui(mpz_test, 1) == 0) || (mpz_cmp(mpz_test, nm1) == 0)) { result = Py_True; goto cleanup; } while (--r) { /* mpz_test = mpz_test^2%n */ mpz_mul(mpz_test, mpz_test, mpz_test); mpz_mod(mpz_test, mpz_test, n->z); if (mpz_cmp(mpz_test, nm1) == 0) { result = Py_True; goto cleanup; } } result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(s); mpz_clear(nm1); mpz_clear(mpz_test); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; }
/* ******************************************************************************* * mpz_lucas_prp: * A "Lucas pseudoprime" with parameters (P,Q) is a composite n with D=P^2-4Q, * (n,2QD)=1 such that U_(n-(D/n)) == 0 mod n [(D/n) is the Jacobi symbol] * *******************************************************************************/ int mpz_lucas_prp(mpz_t n, long int p, long int q) { mpz_t zD; mpz_t res; mpz_t index; mpz_t uh, vl, vh, ql, qh, tmp; /* used for calculating the Lucas U sequence */ int s = 0, j = 0; int ret = 0; long int d = p*p - 4*q; if (d == 0) /* Does not produce a proper Lucas sequence */ return PRP_ERROR; 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(index); mpz_init_set_si(zD, d); mpz_init(res); mpz_mul_si(res, zD, q); mpz_mul_ui(res, res, 2); mpz_gcd(res, res, n); if ((mpz_cmp(res, n) != 0) && (mpz_cmp_ui(res, 1) > 0)) { mpz_clear(zD); mpz_clear(res); mpz_clear(index); return PRP_COMPOSITE; } /* index = n-(D/n), where (D/n) is the Jacobi symbol */ mpz_set(index, n); ret = mpz_jacobi(zD, n); if (ret == -1) mpz_add_ui(index, index, 1); else if (ret == 1) mpz_sub_ui(index, index, 1); /* mpz_lucasumod(res, p, q, index, n); */ mpz_init_set_si(uh, 1); mpz_init_set_si(vl, 2); mpz_init_set_si(vh, p); mpz_init_set_si(ql, 1); mpz_init_set_si(qh, 1); mpz_init_set_si(tmp,0); s = mpz_scan1(index, 0); for (j = mpz_sizeinbase(index,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n); if (mpz_tstbit(index,j) == 1) { /* qh = ql*q */ mpz_mul_si(qh, ql, q); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul_si(tmp, ql, p); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul_si(tmp, ql, p); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul_si(qh, ql, q); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul_si(tmp, ql, p); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* uh = uh*vl (mod n) */ mpz_mul(uh, uh, vl); mpz_mod(uh, uh, n); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n); } mpz_mod(res, uh, n); /* uh contains our return value */ mpz_clear(zD); mpz_clear(index); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); if (mpz_cmp_ui(res, 0) == 0) { mpz_clear(res); return PRP_PRP; } else { mpz_clear(res); return PRP_COMPOSITE; } }/* method mpz_lucas_prp */
/* ************************************************************************* * mpz_fibonacci_prp: * A "Fibonacci pseudoprime" with parameters (P,Q), P > 0, Q=+/-1, is a * composite n for which V_n == P mod n * [V is the Lucas V sequence with parameters P,Q] * *************************************************************************/ int mpz_fibonacci_prp(mpz_t n, long int p, long int q) { mpz_t pmodn, zP; mpz_t vl, vh, ql, qh, tmp; /* used for calculating the Lucas V sequence */ int s = 0, j = 0; if (p*p-4*q == 0) return PRP_ERROR; if (((q != 1) && (q != -1)) || (p <= 0)) return PRP_ERROR; 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(zP, p); mpz_init(pmodn); mpz_mod(pmodn, zP, n); /* mpz_lucasvmod(res, p, q, n, n); */ mpz_init_set_si(vl, 2); mpz_init_set_si(vh, p); mpz_init_set_si(ql, 1); mpz_init_set_si(qh, 1); mpz_init_set_si(tmp,0); s = mpz_scan1(n, 0); for (j = mpz_sizeinbase(n,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n); if (mpz_tstbit(n,j) == 1) { /* qh = ql*q */ mpz_mul_si(qh, ql, q); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul_si(tmp, ql, p); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n); } else { /* qh = ql */ mpz_set(qh, ql); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul_si(tmp, ql, p); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul_si(qh, ql, q); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul_si(tmp, ql, p); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n); } mpz_mod(vl, vl, n); /* vl contains our return value */ if (mpz_cmp(vl, pmodn) == 0) { mpz_clear(zP); mpz_clear(pmodn); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); return PRP_PRP; } mpz_clear(zP); mpz_clear(pmodn); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); return PRP_COMPOSITE; }/* method mpz_fibonacci_prp */
/* ********************************************************************************************* * mpz_sprp: (also called a Miller-Rabin pseudoprime) * A "strong pseudoprime" to the base a is an odd composite n = (2^r)*s+1 with s odd such that * either a^s == 1 mod n, or a^((2^t)*s) == -1 mod n, for some integer t, with 0 <= t < r. * *********************************************************************************************/ int mpz_sprp(mpz_t n, mpz_t a) { mpz_t s; mpz_t nm1; mpz_t mpz_test; unsigned long int r = 0; if (mpz_cmp_ui(a, 2) < 0) return PRP_ERROR; 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(mpz_test, 0); mpz_init_set_ui(s, 0); mpz_init_set(nm1, n); mpz_sub_ui(nm1, nm1, 1); /***********************************************/ /* Find s and r satisfying: n-1=(2^r)*s, s odd */ r = mpz_scan1(nm1, 0); mpz_fdiv_q_2exp(s, nm1, r); /******************************************/ /* Check a^((2^t)*s) mod n for 0 <= t < r */ mpz_powm(mpz_test, a, s, n); if ( (mpz_cmp_ui(mpz_test, 1) == 0) || (mpz_cmp(mpz_test, nm1) == 0) ) { mpz_clear(s); mpz_clear(nm1); mpz_clear(mpz_test); return PRP_PRP; } while ( --r ) { /* mpz_test = mpz_test^2%n */ mpz_mul(mpz_test, mpz_test, mpz_test); mpz_mod(mpz_test, mpz_test, n); if (mpz_cmp(mpz_test, nm1) == 0) { mpz_clear(s); mpz_clear(nm1); mpz_clear(mpz_test); return PRP_PRP; } } mpz_clear(s); mpz_clear(nm1); mpz_clear(mpz_test); return PRP_COMPOSITE; }/* method mpz_sprp */
/* * isprime : is this number prime ? * this use the Miller-Rabin method. The algorithm can be found at Wikipedia * return 1 (yes) and 0 (no) */ int isprime(mpz_t p) { gmp_randstate_t st; /* random init stat */ mpz_t a, d, tmp, x; int i, ret, j; unsigned long s; ret = 1; /* * ensure that p is odd and greater than 3 */ if (mpz_cmp_ui(p, 3) <= 0 || !mpz_tstbit(p, 0)) return 0; /* * put p in the 2^s.d form */ mpz_init(d); mpz_sub_ui(d, p, 1); /* d = p-1 */ s = 0; do { s++; mpz_divexact_ui(d, d, 2); } while (mpz_divisible_ui_p(d, 2)); /* * now we have p as 2^s.d */ gmp_randinit_default(st); gmp_randseed_ui(st, time(NULL)); mpz_init(a); mpz_init(x); mpz_init(tmp); mpz_sub_ui(tmp, p, 1); /* tmp = p - 1 */ for (i = 0; i < ACCURACY; i++) { /* * generate a as 2 <= a <= n-2 */ do { mpz_urandomm(a, st, tmp); /* a will be between 0 and * tmp-1 * inclusive */ } while (mpz_cmp_ui(a, 2) < 0); mpz_powm(x, a, d, p); /* do x = a^d mod p */ /* * if x == 1 or x == p-1 */ if (!mpz_cmp_ui(x, 1) || !mpz_cmp(x, tmp)) continue; for (j = 1; j < s; j++) { mpz_powm_ui(x, x, 2, p); /* do x = x^2 mod p */ if (!mpz_cmp_ui(x, 1) || !mpz_cmp(x, tmp)) /* x == 1 */ break; } if (mpz_cmp(x, tmp) || !mpz_cmp_ui(x, 1)) { /* x != p-1 */ ret = 0; break; } } /* * Free Ressources */ gmp_randclear(st); mpz_clear(a); mpz_clear(d); mpz_clear(tmp); return ret; }
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; }
static PyObject * GMPY_mpz_is_extrastronglucas_prp(PyObject *self, PyObject *args) { MPZ_Object *n, *p; PyObject *result = 0; mpz_t zD, s, nmj, nm2, res; /* these are needed for the LucasU and LucasV part of this function */ mpz_t uh, vl, vh, ql, qh, tmp; mp_bitcnt_t r = 0, j = 0; int ret = 0; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments"); return NULL; } mpz_init(zD); mpz_init(s); mpz_init(nmj); mpz_init(nm2); mpz_init(res); mpz_init(uh); mpz_init(vl); mpz_init(vh); mpz_init(ql); mpz_init(qh); mpz_init(tmp); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!n || !p) { TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments"); goto cleanup; } /* Check if p*p - 4 == 0. */ mpz_mul(zD, p->z, p->z); mpz_sub_ui(zD, zD, 4); if (mpz_sgn(zD) == 0) { VALUE_ERROR("invalid value for p in is_extra_strong_lucas_prp()"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_extra_strong_lucas_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; } /* Check GCD */ mpz_mul_ui(res, zD, 2); mpz_gcd(res, res, n->z); if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) { VALUE_ERROR("is_extra_strong_lucas_prp() requires gcd(n,2*D) == 1"); goto cleanup; } /* nmj = n - (D/n), where (D/n) is the Jacobi symbol */ mpz_set(nmj, n->z); ret = mpz_jacobi(zD, n->z); if (ret == -1) mpz_add_ui(nmj, nmj, 1); else if (ret == 1) mpz_sub_ui(nmj, nmj, 1); r = mpz_scan1(nmj, 0); mpz_fdiv_q_2exp(s, nmj, r); mpz_set(nm2, n->z); mpz_sub_ui(nm2, nm2, 2); /* make sure that either U_s == 0 mod n or V_s == +/-2 mod n, or */ /* V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 */ mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); for (j = mpz_sizeinbase(s,2)-1; j >= 1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(s,j) == 1) { /* qh = ql*q */ mpz_set(qh, ql); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n->z); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_set(qh, ql); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); mpz_mod(uh, uh, n->z); mpz_mod(vl, vl, n->z); /* uh contains LucasU_s and vl contains LucasV_s */ if ((mpz_cmp_ui(uh, 0) == 0) || (mpz_cmp_ui(vl, 0) == 0) || (mpz_cmp(vl, nm2) == 0) || (mpz_cmp_si(vl, 2) == 0)) { result = Py_True; goto cleanup; } for (j = 1; j < r-1; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); if (mpz_cmp_ui(vl, 0) == 0) { result = Py_True; goto cleanup; } } result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(zD); mpz_clear(s); mpz_clear(nmj); mpz_clear(nm2); mpz_clear(res); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)n); return result; }
int main(int argc, char **argv) { mpz_t year, tmp1, tmp2, tmp3, tmp4; unsigned long day_of_week = 0; uintmax_t month_min = 1, month_max = 12; int_fast8_t month_days = 0; const int_fast8_t months_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; time_t t = time(NULL); char weekday[13] = {0}, weekdays[92] = {0}, month_name[13] = {0}; struct tm *time_struct = localtime(&t); setlocale(LC_ALL, ""); mpz_init(year); switch(argc) { case 1: mpz_set_ui(year, time_struct->tm_year + 1900); month_min = month_max = time_struct->tm_mon + 1; break; case 2: mpz_set_str(year, argv[1], 10); break; default: month_min = month_max = strtoumax(argv[1], NULL, 10); mpz_set_str(year, argv[2], 10); } if(mpz_sgn(year) < 1 || !month_min || month_min > 12) { fputs("http://opengroup.org/onlinepubs/9699919799/utilities/cal.html\n", stderr); exit(1); } for(int_fast8_t i = 0; i < 7; ++i) { time_struct->tm_wday = i; strftime(weekday, 13, "%a", time_struct); strcat(weekdays, weekday); strcat(weekdays, " "); } strcat(weekdays, "\n"); for(uintmax_t month = month_min; month <= month_max; ++month) { time_struct->tm_mon = month - 1; strftime(month_name, 13, "%b", time_struct); if(month > month_min) putchar('\n'); for(int_fast8_t i = (23 - strlen(mpz_get_str(NULL, 10, year))) / 2; i > 0; --i) putchar(' '); fputs(month_name, stdout); putchar(' '); printf("%s\n", mpz_get_str(NULL, 10, year)); fputs(weekdays, stdout); if(!mpz_cmp_ui(year, 1752) && month == 9) { fputs(" 1 2 14 15 16", stdout); fputs("17 18 19 20 21 22 23", stdout); fputs("24 25 26 27 28 29 30", stdout); } else { month_days = months_days[month - 1]; mpz_init(tmp1); mpz_init(tmp2); mpz_init(tmp3); mpz_init(tmp4); if(mpz_cmp_ui(year, 1752) > 0 || (!mpz_cmp_ui(year, 1752) && month > 9)) { /* Gregorian */ if(month == 2 && mpz_divisible_ui_p(year, 4) && (!mpz_divisible_ui_p(year, 100) || mpz_divisible_ui_p(year, 400))) month_days = 29; mpz_add_ui(tmp4, year, 4800 - (14 - month) / 12); mpz_tdiv_q_ui(tmp1, tmp4, 4); mpz_tdiv_q_ui(tmp2, tmp4, 100); mpz_tdiv_q_ui(tmp3, tmp4, 400); mpz_mul_ui(tmp4, tmp4, 365); mpz_add(tmp4, tmp4, tmp1); mpz_sub(tmp4, tmp4, tmp2); mpz_add(tmp4, tmp4, tmp3); mpz_add_ui(tmp4, tmp4, (153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5); mpz_sub_ui(tmp4, tmp4, 32043); day_of_week = mpz_tdiv_ui(tmp4, 7); } else { /* Julian */ if(month == 2 && mpz_divisible_ui_p(year, 4)) month_days = 29; mpz_add_ui(tmp2, year, 4800 - (14 - month) / 12); mpz_tdiv_q_ui(tmp1, tmp2, 4); mpz_mul_ui(tmp2, tmp2, 365); mpz_add(tmp2, tmp2, tmp1); mpz_add_ui(tmp2, tmp2, (153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5); mpz_sub_ui(tmp2, tmp2, 32081); day_of_week = mpz_tdiv_ui(tmp2, 7); } mpz_clear(tmp1); mpz_clear(tmp2); mpz_clear(tmp3); mpz_clear(tmp4); for(uint_fast8_t i = 0; i < day_of_week; ++i) fputs(" ", stdout); for(int_fast8_t i = 1; i <= month_days; ++i) { printf("%2u", i); ++day_of_week; if(i < month_days) fputs((day_of_week %= 7) ? " " : "\n", stdout); } } putchar('\n'); } mpz_clear(year); return 0; }
static PyObject * GMPY_mpz_is_lucas_prp(PyObject *self, PyObject *args) { MPZ_Object *n, *p, *q; PyObject *result = 0; mpz_t zD, res, index; /* used for calculating the Lucas U sequence */ mpz_t uh, vl, vh, ql, qh, tmp; mp_bitcnt_t s = 0, j = 0; int ret; if (PyTuple_Size(args) != 3) { TYPE_ERROR("is_lucas_prp() requires 3 integer arguments"); return NULL; } mpz_init(zD); mpz_init(res); mpz_init(index); mpz_init(uh); mpz_init(vl); mpz_init(vh); mpz_init(ql); mpz_init(qh); mpz_init(tmp); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL); if (!n || !p || !q) { TYPE_ERROR("is_lucas_prp() requires 3 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(zD, p->z, p->z); mpz_mul_ui(tmp, q->z, 4); mpz_sub(zD, zD, tmp); if (mpz_sgn(zD) == 0) { VALUE_ERROR("invalid values for p,q in is_lucas_prp()"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_lucas_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; } /* Check GCD */ mpz_mul(res, zD, q->z); mpz_mul_ui(res, res, 2); mpz_gcd(res, res, n->z); if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) { VALUE_ERROR("is_lucas_prp() requires gcd(n,2*q*D) == 1"); goto cleanup; } /* index = n-(D/n), where (D/n) is the Jacobi symbol */ mpz_set(index, n->z); ret = mpz_jacobi(zD, n->z); if (ret == -1) mpz_add_ui(index, index, 1); else if (ret == 1) mpz_sub_ui(index, index, 1); /* mpz_lucasumod(res, p, q, index, n); */ mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(index, 0); for (j = mpz_sizeinbase(index,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(index,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n->z); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* uh = uh*vl (mod n) */ mpz_mul(uh, uh, vl); mpz_mod(uh, uh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } /* uh contains our return value */ mpz_mod(res, uh, n->z); if (mpz_cmp_ui(res, 0) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(zD); mpz_clear(res); mpz_clear(index); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)n); return result; }
static PyObject * GMPY_mpz_is_fermat_prp(PyObject *self, PyObject *args) { MPZ_Object *a, *n; PyObject *result = 0; mpz_t res, nm1; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_fermat_prp() requires 2 integer arguments"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!a || !n) { TYPE_ERROR("is_fermat_prp() requires 2 integer arguments"); goto cleanup; } mpz_init(res); mpz_init(nm1); /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_fermat_prp() requires 'a' greater than or equal to 2"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_fermat_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. */ /* Should n even raise an exception? */ 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; } /* Check gcd(a,n) */ mpz_gcd(res, n->z, a->z); if (mpz_cmp_ui(res, 1) > 0) { VALUE_ERROR("is_fermat_prp() requires gcd(n,a) == 1"); goto cleanup; } mpz_set(nm1, n->z); mpz_sub_ui(nm1, nm1, 1); mpz_powm(res, a->z, nm1, n->z); if (mpz_cmp_ui(res, 1) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(res); mpz_clear(nm1); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; }
static PyObject * GMPY_mpz_is_euler_prp(PyObject *self, PyObject *args) { MPZ_Object *a, *n; PyObject *result = 0; mpz_t res, exp; int ret; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_euler_prp() requires 2 integer arguments"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!a || !n) { TYPE_ERROR("is_euler_prp() requires 2 integer arguments"); goto cleanup; } mpz_init(res); mpz_init(exp); /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_euler_prp() requires 'a' greater than or equal to 2"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_euler_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; } /* Check gcd(a,b) */ mpz_gcd(res, n->z, a->z); if (mpz_cmp_ui(res, 1) > 0) { VALUE_ERROR("is_euler_prp() requires gcd(n,a) == 1"); goto cleanup; } mpz_set(exp, n->z); mpz_sub_ui(exp, exp, 1); mpz_divexact_ui(exp, exp, 2); mpz_powm(res, a->z, exp, n->z); /* reuse exp to calculate jacobi(a,n) mod n */ ret = mpz_jacobi(a->z,n->z); mpz_set(exp, n->z); if (ret == -1) mpz_sub_ui(exp, exp, 1); else if (ret == 1) mpz_add_ui(exp, exp, 1); mpz_mod(exp, exp, n->z); if (mpz_cmp(res, exp) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(res); mpz_clear(exp); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; }
/* ******************************************************************************************* * mpz_extrastronglucas_prp: * Let U_n = LucasU(p,1), V_n = LucasV(p,1), and D=p^2-4. * An "extra strong Lucas pseudoprime" to the base p is a composite n = (2^r)*s+(D/n), where * s is odd and (n,2D)=1, such that either U_s == 0 mod n and V_s == +/-2 mod n, or * V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 [(D/n) is the Jacobi symbol] * *******************************************************************************************/ int mpz_extrastronglucas_prp(mpz_t n, long int p) { mpz_t zD; mpz_t s; mpz_t nmj; /* n minus jacobi(D/n) */ mpz_t res; mpz_t uh, vl, vh, ql, qh, tmp; /* these are needed for the LucasU and LucasV part of this function */ long int d = p*p - 4; long int q = 1; unsigned long int r = 0; int ret = 0; int j = 0; if (d == 0) /* Does not produce a proper Lucas sequence */ return PRP_ERROR; 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_si(zD, d); mpz_init(res); mpz_mul_ui(res, zD, 2); mpz_gcd(res, res, n); if ((mpz_cmp(res, n) != 0) && (mpz_cmp_ui(res, 1) > 0)) { mpz_clear(zD); mpz_clear(res); return PRP_COMPOSITE; } mpz_init(s); mpz_init(nmj); /* nmj = n - (D/n), where (D/n) is the Jacobi symbol */ mpz_set(nmj, n); ret = mpz_jacobi(zD, n); if (ret == -1) mpz_add_ui(nmj, nmj, 1); else if (ret == 1) mpz_sub_ui(nmj, nmj, 1); r = mpz_scan1(nmj, 0); mpz_fdiv_q_2exp(s, nmj, r); /* make sure that either (U_s == 0 mod n and V_s == +/-2 mod n), or */ /* V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 */ mpz_init_set_si(uh, 1); mpz_init_set_si(vl, 2); mpz_init_set_si(vh, p); mpz_init_set_si(ql, 1); mpz_init_set_si(qh, 1); mpz_init_set_si(tmp,0); for (j = mpz_sizeinbase(s,2)-1; j >= 1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n); if (mpz_tstbit(s,j) == 1) { /* qh = ql*q */ mpz_mul_si(qh, ql, q); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul_si(tmp, ql, p); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul_si(tmp, ql, p); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul_si(qh, ql, q); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul_si(tmp, ql, p); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); mpz_mod(uh, uh, n); mpz_mod(vl, vl, n); /* tmp = n-2, for the following comparison */ mpz_sub_ui(tmp, n, 2); /* uh contains LucasU_s and vl contains LucasV_s */ if (((mpz_cmp_ui(uh, 0) == 0) && ((mpz_cmp(vl, tmp) == 0) || (mpz_cmp_si(vl, 2) == 0))) || (mpz_cmp_ui(vl, 0) == 0)) { mpz_clear(zD); mpz_clear(s); mpz_clear(nmj); mpz_clear(res); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); return PRP_PRP; } for (j = 1; j < r-1; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n); if (mpz_cmp_ui(vl, 0) == 0) { mpz_clear(zD); mpz_clear(s); mpz_clear(nmj); mpz_clear(res); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); return PRP_PRP; } } mpz_clear(zD); mpz_clear(s); mpz_clear(nmj); mpz_clear(res); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); return PRP_COMPOSITE; }/* method mpz_extrastronglucas_prp */
static PyObject * GMPY_mpz_is_strongbpsw_prp(PyObject *self, PyObject *args) { MPZ_Object *n; PyObject *result = 0, *temp = 0; if (PyTuple_Size(args) != 1) { TYPE_ERROR("is_strong_bpsw_prp() requires 1 integer argument"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); if (!n) { TYPE_ERROR("is_strong_bpsw_prp() requires 1 integer argument"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_strong_bpsw_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; } /* "O" is used to increment the reference to n so deleting temp won't * delete n. */ temp = Py_BuildValue("Oi", n, 2); if (!temp) goto cleanup; result = GMPY_mpz_is_strong_prp(NULL, temp); Py_DECREF(temp); if (result == Py_False) goto return_result; /* Remember to ignore the preceding result */ Py_DECREF(result); temp = Py_BuildValue("O", n); if (!temp) goto cleanup; result = GMPY_mpz_is_selfridge_prp(NULL, temp); Py_DECREF(temp); goto return_result; cleanup: Py_XINCREF(result); return_result: Py_DECREF((PyObject*)n); return result; }
/* *********************************************************************************************** * 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 */
static PyObject * GMPY_mpz_is_fibonacci_prp(PyObject *self, PyObject *args) { MPZ_Object *n, *p, *q; PyObject *result = 0; mpz_t pmodn, zP; /* used for calculating the Lucas V sequence */ mpz_t vl, vh, ql, qh, tmp; mp_bitcnt_t s = 0, j = 0; if (PyTuple_Size(args) != 3) { TYPE_ERROR("is_fibonacci_prp() requires 3 integer arguments"); return NULL; } mpz_init(pmodn); mpz_init(zP); mpz_init(vl); mpz_init(vh); mpz_init(ql); mpz_init(qh); mpz_init(tmp); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL); if (!n || !p || !q) { TYPE_ERROR("is_fibonacci_prp() requires 3 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(tmp, p->z, p->z); mpz_mul_ui(qh, q->z, 4); mpz_sub(tmp, tmp, qh); if (mpz_sgn(tmp) == 0) { VALUE_ERROR("invalid values for p,q in is_fibonacci_prp()"); goto cleanup; } /* Verify q = +/-1 */ if ((mpz_cmp_si(q->z, 1) && mpz_cmp_si(q->z, -1)) || (mpz_sgn(p->z) <= 0)) { VALUE_ERROR("invalid values for p,q in is_fibonacci_prp()"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_fibonacci_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(zP, p->z); mpz_mod(pmodn, zP, n->z); /* mpz_lucasvmod(res, p, q, n, n); */ mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(n->z, 0); for (j = mpz_sizeinbase(n->z,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(n->z,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } /* vl contains our return value */ mpz_mod(vl, vl, n->z); if (mpz_cmp(vl, pmodn) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(pmodn); mpz_clear(zP); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)n); return result; }