Primality test function doesn't work on large numbers?
Timon Gehr via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Jan 8 14:10:36 PST 2017
On 08.01.2017 08:52, Elronnd wrote:
> I'm working on writing an RSA implementation, but I've run into a
> roadblock generating primes. With a more than 9 bits, my program either
> hangs for a long time (utilizing %100 CPU!) or returns a composite
> number. With 9 or fewer bits, I get primes, but I have to run with a
> huge number of iterations to actually _get_ a random number. It runs
> fast, though. Why might this be? Code:
> http://lpaste.net/1034777940820230144
Fixed version:
import std.bigint;
import std.stdio;
private alias bigint = BigInt;
bigint pow(bigint base,bigint exponent){
bigint tmp=1;
for(auto x=base,y=exponent;y;x*=x,y/=2)
if(y%2) tmp*=x;
return tmp;
}
bigint powm(bigint base,bigint exponent,bigint modulus){
bigint tmp=1;
for(auto x=base,y=exponent;y;x=x*x%modulus,y/=2)
if(y%2) tmp=tmp*x%modulus;
return tmp;
}
private pragma(inline, true) bigint pow(int base, bigint exponent) {
return pow(bigint(base), exponent);
}
private pragma(inline, true) bigint pow(bigint base, int exponent) {
return pow(base, bigint(exponent));
}
private pragma(inline, true) bigint pow(int base, int exponent) {
return pow(bigint(base), bigint(exponent));
}
// Credit to
http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf appendix C.3
private bigint genprime(int bits, int numtests){
import std.random: uniform;
bool mrprime(bigint integer, int iterations) {
if(integer%2==0)
return false;
bigint m, a = 0, tmp = integer, b, z;
int length;
for(m=integer-1;m%2==0;m/=2,++a){}
assert((integer-1)%pow(bigint(2), a)==0);
while(tmp != 0) {
tmp >>=1;
length += 1;
}
for (int i=0; i<iterations; i++) {
// Create b such that b has the same number of bits as
"integer"
for (int j = 1; j<=length; j++) {
b <<= 1;
b += uniform(0, 2);
}
while ((b <= 1) || (b >= (integer-1))) {
b = 0;
for (int j = 1; j<=length; j++) {
b <<= 1;
b += uniform(0, 2);
}
}
z = powm(b, m, integer);
if((z == 1) || (z == integer-1))
goto endofloop;
for(int k=1; k<=a-1; k++) {
z = z*z%integer;
if(z == integer-1)
goto endofloop;
if(z == 1)
return false;
}
return false;
endofloop:
}
return true;
}
bigint genbigint(int numbits) {
bigint tmp;
while (numbits --> 0) {
tmp <<= 1;
tmp += uniform(0, 2);
}
return tmp;
}
bigint currnum;
while (true) {
currnum = genbigint(bits);
if (mrprime(currnum, numtests)) {
return currnum;
}
}
assert(0);
}
void main(){
writeln(genprime(300,30));
}
More information about the Digitalmars-d-learn
mailing list