void PrimeAndGenerator::Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits) { // no prime exists for delta = -1, qbits = 4, and pbits = 5 assert(qbits > 4); assert(pbits > qbits); if (qbits+1 == pbits) { Integer minP = Integer::Power2(pbits-1); Integer maxP = Integer::Power2(pbits) - 1; bool success = false; while (!success) { p.Randomize(rng, minP, maxP, Integer::ANY, 6+5*delta, 12); PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*12, maxP), 12, delta); while (sieve.NextCandidate(p)) { assert(IsSmallPrime(p) || SmallDivisorsTest(p)); q = (p-delta) >> 1; assert(IsSmallPrime(q) || SmallDivisorsTest(q)); if (FastProbablePrimeTest(q) && FastProbablePrimeTest(p) && IsPrime(q) && IsPrime(p)) { success = true; break; } } } if (delta == 1) { // find g such that g is a quadratic residue mod p, then g has order q // g=4 always works, but this way we get the smallest quadratic residue (other than 1) for (g=2; Jacobi(g, p) != 1; ++g) {} // contributed by Walt Tuvell: g should be the following according to the Law of Quadratic Reciprocity assert((p%8==1 || p%8==7) ? g==2 : (p%12==1 || p%12==11) ? g==3 : g==4); } else { assert(delta == -1); // find g such that g*g-4 is a quadratic non-residue, // and such that g has order q for (g=3; ; ++g) if (Jacobi(g*g-4, p)==-1 && Lucas(q, g, p)==2) break; } }
Integer MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int pbits) { Integer p; Integer minP = Integer::Power2(pbits-1); Integer maxP = Integer::Power2(pbits) - 1; if (maxP <= Integer(s_lastSmallPrime).Squared()) { // Randomize() will generate a prime provable by trial division p.Randomize(rng, minP, maxP, Integer::PRIME); return p; } unsigned int qbits = (pbits+2)/3 + 1 + rng.GenerateWord32(0, pbits/36); Integer q = MihailescuProvablePrime(rng, qbits); Integer q2 = q<<1; while (true) { // this initializes the sieve to search in the arithmetic // progression p = p_0 + \lambda * q2 = p_0 + 2 * \lambda * q, // with q the recursively generated prime above. We will be able // to use Lucas tets for proving primality. A trick of Quisquater // allows taking q > cubic_root(p) rather then square_root: this // decreases the recursion. p.Randomize(rng, minP, maxP, Integer::ANY, 1, q2); PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*q2, maxP), q2); while (sieve.NextCandidate(p)) { if (FastProbablePrimeTest(p) && ProvePrime(p, q)) return p; } } // not reached return p; }
bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod) { assert(!equiv.IsNegative() && equiv < mod); Integer gcd = GCD(equiv, mod); if (gcd != Integer::One()) { // the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv) if (p <= gcd && gcd <= max && IsPrime(gcd)) { p = gcd; return true; } else return false; } BuildPrimeTable(); if (p <= primeTable[primeTableSize-1]) { word *pItr; --p; if (p.IsPositive()) pItr = std::upper_bound(primeTable, primeTable+primeTableSize, p.ConvertToLong()); else pItr = primeTable; while (pItr < primeTable+primeTableSize && *pItr%mod != equiv) ++pItr; if (pItr < primeTable+primeTableSize) { p = *pItr; return p <= max; } p = primeTable[primeTableSize-1]+1; } assert(p > primeTable[primeTableSize-1]); if (mod.IsOdd()) return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1); p += (equiv-p)%mod; if (p>max) return false; PrimeSieve sieve(p, max, mod); while (sieve.NextCandidate(p)) { if (FastProbablePrimeTest(p) && IsPrime(p)) return true; } return false; }
bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector) { assert(!equiv.IsNegative() && equiv < mod); Integer gcd = GCD(equiv, mod); if (gcd != Integer::One()) { // the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv) if (p <= gcd && gcd <= max && IsPrime(gcd) && (!pSelector || pSelector->IsAcceptable(gcd))) { p = gcd; return true; } else return false; } unsigned int primeTableSize; const word16 * primeTable = GetPrimeTable(primeTableSize); if (p <= primeTable[primeTableSize-1]) { const word16 *pItr; --p; if (p.IsPositive()) pItr = std::upper_bound(primeTable, primeTable+primeTableSize, (word)p.ConvertToLong()); else pItr = primeTable; while (pItr < primeTable+primeTableSize && !(*pItr%mod == equiv && (!pSelector || pSelector->IsAcceptable(*pItr)))) ++pItr; if (pItr < primeTable+primeTableSize) { p = *pItr; return p <= max; } p = primeTable[primeTableSize-1]+1; } assert(p > primeTable[primeTableSize-1]); if (mod.IsOdd()) return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1, pSelector); p += (equiv-p)%mod; if (p>max) return false; PrimeSieve sieve(p, max, mod); while (sieve.NextCandidate(p)) { if ((!pSelector || pSelector->IsAcceptable(p)) && FastProbablePrimeTest(p) && IsPrime(p)) return true; } return false; }