Reputation:
I'm using strong known bases {2, 7, 61} to solve Miller-Rabin. Assume I take a = 2 in this piece of code and n = 5 to test its primality. The factorization of n-1, so 4, is 2*2*1 so my m is 1. If I test 2^1 = x mod 5, I of course get 2, which will make my Miller-Rabin test fail even if 5 is prime.
while(m > 0) {
if(m%2 == 0) {
pow *= a*a;
pow %= n;
m -= 2;
}
else {
pow *= a;
pow %= n;
m -= 1;
}
}
if(miller_rabin_single_base(pow, n) == 0) {
return 0;
}
...
The method I call at the end just checks if pow%n = 1 or n-1.
I can't understand if I misunderstood Miller-Rabin algorithm, or if there's some problem in the code. The code works with some primes only.
I'm also a C neophyte so I apologise if the error was just given by a bad coding.
Update:
declaration of the the single_base method:
int miller_rabin_single_base(int16 a, int16 n) {
if(a%n == n-1 || a%n == 1) {
return 1;
}
else {
return 0;
}
}
declaration of m and pow:
int16 nmu = n-1;
int16 m;
int16 k = 0;
while((nmu/2)%2 == 0) {
k++;
nmu = nmu/2;
}
m = nmu/2;
k++;
int16 pow = 1;
int16 is an unsigned short, I'm using it to test.
The n is an unsigned short number chosen by anyone who can run the code.
If I test for n = 5, 13 or 29 I get it is not prime, but If I test 7, 11 or 31 I get it's prime:
./p_test miller 17
composite number
./p_test miller 23
prime number
Upvotes: 0
Views: 247
Reputation: 38990
You've left out half of M-R. Given witness a=2 and n=5 with n-1=4 decomposed to 22·1 you need to:
compute a1 mod n = 2 and compare to 1 and n-1 (-1 mod n); if equal to either this witness would say prime and you advance to the next witness, but it is not, and you had more than one factor of 2 in n-1, so keep going
compute a1·2 mod n = 4 and compare to n-1 (only, not 1); it is equal, so this witness says prime; in general you would advance to the next witness (or if no more declare n probably prime). If it were not equal, since you have reached k-1=1 factors of 2, you declare n composite and stop, but for n-1 values containing more factors of 2 you would iterate this step multiple times.
In this case, your other witnessess are unnecessary; 7 mod 5 = 2 so it produces exactly the same result, and 61 mod 5 = 1 and 1 as a witness says every number is prime, which is useless. For a more realistic (larger) n, they would be useful.
Note computing am, am·2, am·2·2, am·2·2·2, etc all mod n can be done more efficiently by first computing x = am mod n then repeatedly computing x = x2 mod n .
See example in wikipedia (although they use different variable names).
Upvotes: 1