/* In the _vast_ majority of cases this simply checks that your chosen random * number is >= KLastSmallPrimeSquared and return EFalse and lets the normal * prime generation routines handle the situation. In the case where it is * smaller, it generates a provable prime and returns ETrue. The algorithm for * finding a provable prime < KLastPrimeSquared is not the most efficient in the * world, but two points come to mind * 1) The two if statements hardly _ever_ evaluate to ETrue in real life. * 2) Even when it is, the distribution of primes < KLastPrimeSquared is pretty * dense, so you aren't going to have check many. * This function is essentially here for two reasons: * 1) Ensures that it is possible to generate primes < KLastPrimeSquared (the * test code does this) * 2) Ensures that if you request a prime of a large bit size that there is an * even probability distribution across all integers < 2^aBits */ TBool TInteger::SmallPrimeRandomizeL(void) { TBool foundPrime = EFalse; //If the random number we've chosen is less than KLastSmallPrime, //testing for primality is easy. if(*this <= KLastSmallPrime) { //If Zero or One, or two, next prime number is two if(IsZero() || *this == One() || *this == Two()) { CopyL(TInteger::Two()); foundPrime = ETrue; } else { //Make sure any number we bother testing is at least odd SetBit(0); //Binary search the small primes. while(!IsSmallPrime(ConvertToUnsignedLong())) { //If not prime, add two and try the next odd number. //will never carry as the minimum size of an RInteger is 2 //words. Much bigger than KLastSmallPrime on 32bit //architectures. IncrementNoCarry(Ptr(), Size(), 2); } assert(IsSmallPrime(ConvertToUnsignedLong())); foundPrime = ETrue; } } else if(*this <= KLastSmallPrimeSquared) { //Make sure any number we bother testing is at least odd SetBit(0); while(HasSmallDivisorL(*this) && *this <= KLastSmallPrimeSquared) { //If not prime, add two and try the next odd number. //will never carry as the minimum size of an RInteger is 2 //words. Much bigger than KLastSmallPrime on 32bit //architectures. IncrementNoCarry(Ptr(), Size(), 2); } //If we exited while loop because it had no small divisor then it is //prime. Otherwise, we've exceeded the limit of what we can provably //generate. Therefore the normal prime gen routines will be run on it //now. if(*this < KLastSmallPrimeSquared) { foundPrime = ETrue; } } //This doesn't mean there is no such prime, simply means that the number //wasn't less than KSmallPrimeSquared and needs to be handled by the normal //prime generation routines. return foundPrime; }
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; } }
bool IsPrime(const Integer &p) { if (p <= s_lastSmallPrime) return IsSmallPrime(p); else if (p <= Singleton<Integer, NewLastSmallPrimeSquared>().Ref()) return SmallDivisorsTest(p); else return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p); }
bool IsPrime(const Integer &p) { static const Integer lastSmallPrimeSquared = Integer(lastSmallPrime).Squared(); if (p <= lastSmallPrime) return IsSmallPrime(p); else if (p <= lastSmallPrimeSquared) return SmallDivisorsTest(p); else return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p); }
TBool TInteger::IsPrimeL(void) const { if( NotPositive() ) { return EFalse; } else if( IsEven() ) { return *this == Two(); } else if( *this <= KLastSmallPrime ) { assert(KLastSmallPrime < KMaxTUint); return IsSmallPrime(this->ConvertToUnsignedLong()); } else if( *this <= KLastSmallPrimeSquared ) { return !HasSmallDivisorL(*this); } else { return !HasSmallDivisorL(*this) && IsStrongProbablePrimeL(*this); } }