Reputation: 1935
I am implementing Wikipedia's Miller-Rabin algorithm but don't seem to be getting even vaguely apt results. 7, 11, 19, 23 etc. are reported composite. Infact, when k>12, even 5 is shown composite. I have read the maths behind Miller-Rabin but don't quite understand it very well and am relying on the algorithm blindly. Any cues on where I'm going wrong?
Here's my code:
#include<stdio.h>
#include<math.h>
int modpow(int b, int e, int m) {
long result = 1;
while (e > 0) {
if ((e & 1) == 1) {
result = (result * b) % m;
}
b = (b * b) % m;
e >>= 1;
}
return result;
}
int isPrime(long n,int k){
int a,s,d,r,i,x,loop;
if(n<2)return 0;
if(n==2||n==3)return 1;
if(n%2==0)return 0;
d=n-1;
s=0;
while(d&1==0){
d>>=1;
s++;
}
for(i=0;i<k;i++){
loop=0;
a=(int)(rand()*(n-1))+1;
x=modpow(a,d,n);
if(x==1 || x==n-1){
continue;
}
for(r=1;r<=s;r++){
x=modpow(x,2,n);
if(x==1)return 0;
if(x==n-1){
loop=1;
break;
}
}
if(!loop)return 0;
}
return 1;
}
int main(){
int i,k;
scanf("%d",&k);
for(i=5;i<100;i+=2){
printf("%d : %d\n",i,isPrime(i,k));
}
return 0;
}
Upvotes: 2
Views: 373
Reputation: 183968
If the base is not coprime to the candidate, the strong Fermat check always returns "not a probable prime".
With your mistake
a=(int)(rand()*(n-1))+1;
for a prime p
, the base is not coprime to p
(a multiple of p
), if and only if the result of rand()
has the form
k*p + 1
For small primes, that is practically guaranteed to happen even with few iterations.
The base should lie between 2 ans n/2
(choosing bases larger than n/2
is not necessary since a
is a witness for compositeness if and only if n - a
is one), so you want something like
a = rand() % (n/2 - 2) + 2;
if you don't mind the modulo bias in the random number generation that favours small remainders, or
a = rand() /(RAND_MAX + 1.0) * (n/2 - 2) + 2;
if you want to distribute the bias over the entire possible range.
Upvotes: 4