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;
}
If the base is not coprime to the candidate, the strong Fermat check always returns “not a probable prime”.
With your mistake
for a prime
p, the base is not coprime top(a multiple ofp), if and only if the result ofrand()has the formFor small primes, that is practically guaranteed to happen even with few iterations.
The base should lie between 2 ans
n/2(choosing bases larger thann/2is not necessary sinceais a witness for compositeness if and only ifn - ais one), so you want something likeif you don’t mind the modulo bias in the random number generation that favours small remainders, or
if you want to distribute the bias over the entire possible range.