Miller-Rabin Primality test FIPS 186-3 implementation - c++

Im trying to implement the Miller-Rabin primality test according to the description in FIPS 186-3 C.3.1. No matter what I do, I cannot get it to work. The instructions are pretty specific, and I dont think I missed anything, and yet Im getting true for non-prime values.
What did I do wrong?
template <typename R, typename S, typename T>
T POW(R base, S exponent, const T mod){
T result = 1;
while (exponent){
if (exponent & 1)
result = (result * base) % mod;
exponent >>= 1;
base = (base * base) % mod;
}
return result;
}
// used uint64_t to prevent overflow, but only testing with small numbers for now
bool MillerRabin_FIPS186(uint64_t w, unsigned int iterations = 50){
srand(time(0));
unsigned int a = 0;
uint64_t W = w - 1; // dont want to keep calculating w - 1
uint64_t m = W;
while (!(m & 1)){
m >>= 1;
a++;
}
// skipped getting wlen
// when i had this function using my custom arbitrary precision integer class,
// and could get len(w), getting it and using it in an actual RBG
// made no difference
for(unsigned int i = 0; i < iterations; i++){
uint64_t b = (rand() % (W - 3)) + 2; // 2 <= b <= w - 2
uint64_t z = POW(b, m, w);
if ((z == 1) || (z == W))
continue;
else
for(unsigned int j = 1; j < a; j++){
z = POW(z, 2, w);
if (z == W)
continue;
if (z == 1)
return 0;// Composite
}
}
return 1;// Probably Prime
}
this:
std::cout << MillerRabin_FIPS186(33) << std::endl;
std::cout << MillerRabin_FIPS186(35) << std::endl;
std::cout << MillerRabin_FIPS186(37) << std::endl;
std::cout << MillerRabin_FIPS186(39) << std::endl;
std::cout << MillerRabin_FIPS186(45) << std::endl;
std::cout << MillerRabin_FIPS186(49) << std::endl;
is giving me:
0
1
1
1
0
1

The only difference between your implementation and Wikipedia's is that you forgot the second return composite statement. You should have a return 0 at the end of the loop.
Edit: As pointed out by Daniel, there is a second difference. The continue is continuing the inner loop, rather than the outer loop like it's supposed to.
for(unsigned int i = 0; i < iterations; i++){
uint64_t b = (rand() % (W - 3)) + 2; // 2 <= b <= w - 2
uint64_t z = POW(b, m, w);
if ((z == 1) || (z == W))
continue;
else{
int continueOuter = 0;
for(unsigned int j = 1; j < a; j++){
z = POW(z, 2, w);
if (z == W)
continueOuter = 1;
break;
if (z == 1)
return 0;// Composite
}
if (continueOuter) {continue;}
}
return 0; //This is the line you're missing.
}
return 1;// Probably Prime
Also, if the input is even, it will always return probably prime since a is 0. You should add an extra check at the start for that.

In the inner loop,
for(unsigned int j = 1; j < a; j++){
z = POW(z, 2, w);
if (z == W)
continue;
if (z == 1)
return 0;// Composite
}
you should break; instead of continue; when z == W. By continueing, in the next iteration of that loop, if there is one, z will become 1 and the candidate is possibly wrongly declared composite. Here, that happens for 17, 41, 73, 89 and 97 among the primes less than 100.

Related

The next prime number

Among the given input of two numbers, check if the second number is exactly the next prime number of the first number. If so return "YES" else "NO".
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int nextPrime(int x){
int y =x;
for(int i=2; i <=sqrt(y); i++){
if(y%i == 0){
y = y+2;
nextPrime(y);
return (y);
}
}
return y;
}
int main()
{
int n,m, x(0);
cin >> n >> m;
x = n+2;
if(n = 2 && m == 3){
cout << "YES\n";
exit(0);
}
nextPrime(x) == m ? cout << "YES\n" : cout << "NO\n";
return 0;
}
Where is my code running wrong? It only returns true if next number is either +2 or +4.
Maybe it has something to do with return statement.
I can tell you two things you are doing wrong:
Enter 2 4 and you will check 4, 6, 8, 10, 12, 14, 16, 18, ... for primality forever.
The other thing is
y = y+2;
nextPrime(y);
return (y);
should just be
return nextPrime(y + 2);
Beyond that your loop is highly inefficient:
for(int i=2; i <=sqrt(y); i++){
Handle even numbers as special case and then use
for(int i=3; i * i <= y; i += 2){
Using a different primality test would also be faster. For example Miller-Rabin primality test:
#include <iostream>
#include <cstdint>
#include <array>
#include <ranges>
#include <cassert>
#include <bitset>
#include <bit>
// square and multiply algorithm for a^d mod n
uint32_t pow_n(uint32_t a, uint32_t d, uint32_t n) {
if (d == 0) __builtin_unreachable();
unsigned shift = std::countl_zero(d) + 1;
uint32_t t = a;
int32_t m = d << shift;
for (unsigned i = 32 - shift; i > 0; --i) {
t = ((uint64_t)t * t) % n;
if (m < 0) t = ((uint64_t)t * a) % n;
m <<= 1;
}
return t;
}
bool test(uint32_t n, unsigned s, uint32_t d, uint32_t a) {
uint32_t x = pow_n(a, d, n);
//std::cout << " x = " << x << std::endl;
if (x == 1 || x == n - 1) return true;
for (unsigned i = 1; i < s; ++i) {
x = ((uint64_t)x * x) % n;
if (x == n - 1) return true;
}
return false;
}
bool is_prime(uint32_t n) {
static const std::array witnesses{2u, 3u, 5u, 7u, 11u};
static const std::array bounds{
2'047u, 1'373'653u, 25'326'001u, 3'215'031'751u, UINT_MAX
};
static_assert(witnesses.size() == bounds.size());
if (n == 2) return true; // 2 is prime
if (n % 2 == 0) return false; // other even numbers are not
if (n <= witnesses.back()) { // I know the first few primes
return (std::ranges::find(witnesses, n) != std::end(witnesses));
}
// write n = 2^s * d + 1 with d odd
unsigned s = 0;
uint32_t d = n - 1;
while (d % 2 == 0) {
++s;
d /= 2;
}
// test widtnesses until the bounds say it's a sure thing
auto it = bounds.cbegin();
for (auto a : witnesses) {
//std::cout << a << " ";
if (!test(n, s, d, a)) return false;
if (n < *it++) return true;
}
return true;
}
And yes, that is an awful lot of code but it runs very few times.
Something to do with the return statement
I would say so
y = y+2;
nextPrime(y);
return (y);
can be replaced with
return nextPrime(y + 2);
Your version calls nextPrime but fails to do anything with the return value, instead it just returns y.
It would be more usual to code the nextPrime function with another loop, instead of writing a recursive function.

Modulo of difference of terms

As an answer to a particular problem, I have to print n*k^n - (n-1)*k.
for(i=0;i<n;i++){
c=(c%p*k%p)%p;
c=(c%p*n%p)%p;
d=((n-1)%p*k%p)%p;
s=(c%p-d%p)%p;
cout<<s<<endl;
}
Initially c=1, p=1000000007 and s is my final answer.
I have to take the modulo of s with respect to p.
For large values of n, s becomes negative. This happens because the modulo value changes. So even if c>d, it is possible that c%p<d%p. For n=1000000000 and k=25, s=-727999801. I am not being able to think of a suitable workaround.
-2 % 7 = 5, because -2 = 7 * (-1) + 5, while c++ modulo operation would return -2, so to get positive number you just need to add p.
if (s < 0) s += p;
I advise you to rewrite your code in the following way:
for (int i = 0; i < n; i++) {
c = (c * (k % p)) % p;
}
c = (c * (n % p)) % p;
int d = ((n - 1) % p * (k % p)) % p;
int s = (c - d) % p;
if (s < 0) s += p;
cout << s << endl;
To check with some small inputs you can use the following line:
cout << (n * (int)pow(k, n) - (n-1)*k) % p << endl;
Try to run with this input:
const int n = 5;
const int p = 7;
const int k = 10;
int c = 1;
You will see that without if (s < 0) s += p; it is -1. This line fixes it to 6 - the right answer.

Square Root in C/C++

I am trying to implement my own square root function which gives square root's integral part only e.g. square root of 3 = 1.
I saw the method here and tried to implement the method
int mySqrt(int x)
{
int n = x;
x = pow(2, ceil(log(n) / log(2)) / 2);
int y=0;
while (y < x)
{
y = (x + n / x) / 2;
x = y;
}
return x;
}
The above method fails for input 8. Also, I don't get why it should work.
Also, I tried the method here
int mySqrt(int x)
{
if (x == 0) return 0;
int x0 = pow(2, (log(x) / log(2))/2) ;
int y = x0;
int diff = 10;
while (diff>0)
{
x0 = (x0 + x / x0) / 2; diff = y - x0;
y = x0;
if (diff<0) diff = diff * (-1);
}
return x0;
}
In this second way, for input 3 the loop continues ... indefinitely (x0 toggles between 1 and 2).
I am aware that both are essentially versions of Netwon's method but I can't figure out why they fail in certain cases and how could I make them work for all cases. I guess i have the correct logic in implementation. I debugged my code but still I can't find a way to make it work.
This one works for me:
uintmax_t zsqrt(uintmax_t x)
{
if(x==0) return 0;
uintmax_t yn = x; // The 'next' estimate
uintmax_t y = 0; // The result
uintmax_t yp; // The previous estimate
do{
yp = y;
y = yn;
yn = (y + x/y) >> 1; // Newton step
}while(yn ^ yp); // (yn != yp) shortcut for dumb compilers
return y;
}
returns floor(sqrt(x))
Instead of testing for 0 with a single estimate, test with 2 estimates.
When I was writing this, I noticed the result estimate would sometimes oscillate. This is because, if the exact result is a fraction, the algorithm could only jump between the two nearest values. So, terminating when the next estimate is the same as the previous will prevent an infinite loop.
Try this
int n,i;//n is the input number
i=0;
while(i<=n)
{
if((i*i)==n)
{
cout<<"The number has exact root : "<<i<<endl;
}
else if((i*i)>n)
{
cout<<"The integer part is "<<(i-1)<<endl;
}
i++;
}
Hope this helps.
You can try there C sqrt implementations :
// return the number that was multiplied by itself to reach N.
unsigned square_root_1(const unsigned num) {
unsigned a, b, c, d;
for (b = a = num, c = 1; a >>= 1; ++c);
for (c = 1 << (c & -2); c; c >>= 2) {
d = a + c;
a >>= 1;
if (b >= d)
b -= d, a += c;
}
return a;
}
// return the number that was multiplied by itself to reach N.
unsigned square_root_2(unsigned n){
unsigned a = n > 0, b;
if (n > 3)
for (a = n >> 1, b = (a + n / a) >> 1; b < a; a = b, b = (a + n / a) >> 1);
return a ;
}
Example of usage :
#include <assert.h>
int main(void){
unsigned num, res ;
num = 1847902954, res = square_root_1(num), assert(res == 42987);
num = 2, res = square_root_2(num), assert(res == 1);
num = 0, res = square_root_2(num), assert(res == 0);
}
Source

Convert this recursive function to iterative

How can I convert this recursive function to an iterative function?
#include <cmath>
int M(int H, int T){
if (H == 0) return T;
if (H + 1 >= T) return pow(2, T) - 1;
return M(H - 1, T - 1) + M(H, T - 1) + 1;
}
Well it's a 3-line code but it's very hard for me to convert this to an iterative function. Because it has 2 variables. And I don't know anything about Stacks so I couldn't convert that.
My purpose for doing this is speed of the function. This function is too slow. I wanted to use map to make this faster but I have 3 variables M, H and T so I couldn't use map
you could use dynamic programming - start from the bottom up when H == 0 and T == 0 calculate M and iterate them. here is a link explaining how to do this for Fibonacci numbers, which are quite similar to your problem.
Check this,recursive and not recursive versions gave equal results for all inputs i gave so far. The idea is to keep intermediate results in matrix, where H is row index, T is col index, and the value is M(H,T). By the way, you can calculate it once and later just obtain the result from the matrix, so you will have performance O(1)
int array[10][10]={{0}};
int MNR(int H, int T)
{
if(array[H][T])
return array[H][T];
for(int i =0; i<= H;++i)
{
for(int j = 0; j<= T;++j)
{
if(i == 0)
array[i][j] = j;
else if( i+1 > j)
array[i][j] = pow(2,j) -1;
else
array[i][j] = array[i-1][j-1] + array[i][j-1] + 1;
}
}
return array[H][T];
}
int M(int H, int T)
{
if (H == 0) return T;
if (H + 1 >= T) return pow(2, T) - 1;
return M(H - 1, T - 1) + M(H, T - 1) + 1;
}
int main()
{
printf("%d\n", M(6,3));
printf("%d\n", MNR(6,3));
}
Unless you know the formula for n-th (in your case, (m,n)-th) element of the sequence, the easiest way is to simulate the recursion using a stack.
The code should look like the following:
#include <cmath>
#include <stack>
struct Data
{
public:
Data(int newH, int newT)
: T(newT), H(newH)
{
}
int H;
int T;
};
int M(int H, int T)
{
std::stack<Data> st;
st.push(Data(H, T));
int sum = 0;
while (st.size() > 0)
{
Data top = st.top();
st.pop();
if (top.H == 0)
sum += top.T;
else if (top.H + 1 >= top.T)
sum += pow(2, top.T) - 1;
else
{
st.push(Data(top.H - 1, top.T - 1));
st.push(Data(top.H, top.T - 1));
sum += 1;
}
}
return sum;
}
The main reason why this function is slow is because it has exponential complexity, and it keeps recalculating the same members again and again. One possible cure is memoize pattern (handily explained with examples in C++ here). The idea is to store every result in a structure with a quick access (e.g. an array) and every time you need it again, retrieve already precomputed result. Of course, this approach is limited by the size of your memory, so it won't work for extremely big numbers...
In your case, we could do something like that (keeping the recursion but memoizing the results):
#include <cmath>
#include <map>
#include <utility>
std::map<std::pair<int,int>,int> MM;
int M(int H, int T){
std::pair<int,int> key = std::make_pair(H,T);
std::map<std::pair<int,int>,int>::iterator found = MM.find(key);
if (found!=MM.end()) return found->second; // skip the calculations if we can
int result = 0;
if (H == 0) result = T;
else if (H + 1 >= T) result = pow(2, T) - 1;
else result = M(H - 1, T - 1) + M(H, T - 1) + 1;
MM[key] = result;
return result;
}
Regarding time complexity, C++ maps are tree maps, so searching there is of the order of N*log(N) where N is the size of the map (number of results which have been already computed). There are also hash maps for C++ which are part of the STL but not part of the standard library, as was already mentioned on SO. Hash map promises constant search time (the value of the constant is not specified though :) ), so you might also give them a try.
You may calculate using one demintional array. Little theory,
Let F(a,b) == M(H,T)
1. F(0,b) = b
2. F(a,b) = 2^b - 1, when a+1 >= b
3. F(a,b) = F(a-1,b-1) + F(a,b-1) + 1
Let G(x,y) = F(y,x) ,then
1. G(x,0) = x // RULE (1)
2. G(x,y) = 2^x - 1, when y+1 >= x // RULE (2)
3. G(x,y) = G(x-1,y-1) + G(x-1,y) + 1 // RULE(3) --> this is useful,
// because for G(x,y) need only G(x-1,?), i.e if G - is two deminsions array, then
// for calculating G[x][?] need only previous row G[x-1][?],
// so we need only last two rows of array.
// Here some values of G(x,y)
4. G(0,y) = 2^0 - 1 = 0 from (2) rule.
5. G(1,0) = 1 from (1) rule.
6. G(1,y) = 2^1 - 1 = 1, when y > 0, from (2) rule.
G(0,0) = 0, G(0,1) = 0, G(0,2) = 0, G(0,3) = 0 ...
G(1,0) = 1, G(1,1) = 1, G(1,2) = 1, G(1,3) = 1 ...
7. G(2,0) = 2 from (1) rule
8. G(2,1) = 2^2 - 1 = 3 from (2) rule
9. G(2,y) = 2^2 - 1 = 3 when y > 0, from (2) rule.
G(2,0) = 2, G(2,1) = 3, G(2,2) = 3, G(2,3) = 3, ....
10. G(3,0) = 3 from (1) rule
11. G(3,1) = G(2,0) + G(2,1) + 1 = 2 + 3 + 1 = 6 from (3) rule
12. G(3,2) = 2^3 - 1 = 7, from (2) rule
Now, how to calculate this G(x,y)
int M(int H, int T ) { return G(T,H); }
int G(int x, int y)
{
const int MAX_Y = 100; // or something else
int arr[2][MAX_Y] = {0} ;
int icurr = 0, inext = 1;
for(int xi = 0; xi < x; ++xi)
{
for( int yi = 0; yi <= y ;++yi)
{
if ( yi == 0 )
arr[inext][yi] = xi; // rule (1);
else if ( yi + 1 >= xi )
arr[inext][yi] = (1 << xi) - 1; // rule ( 2 )
else arr[inext][yi] =
arr[icurr][yi-1] + arr[icurr][yi] + 1; // rule (3)
}
icurr ^= 1; inext ^= 1; //swap(i1,i2);
}
return arr[icurr][y];
}
// Or some optimizing
int G(int x, int y)
{
const int MAX_Y = 100;
int arr[2][MAX_Y] = {0};
int icurr = 0, inext = 1;
for(int ix = 0; ix < x; ++ix)
{
arr[inext][0] = ix; // rule (1)
for(int iy = 1; iy < ix - 1; ++ iy)
arr[inext][iy] = arr[icurr][iy-1] + arr[icurr][iy] + 1; // rule (3)
for(int iy = max(0,ix-1); iy <= y; ++iy)
arr[inext][iy] = (1 << ix ) - 1; // rule(2)
icurr ^= 1 ; inext ^= 1;
}
return arr[icurr][y];
}

Miller-Rabin primality test issue in C++

I've been trying to implement the algorithm from wikipedia and while it's never outputting composite numbers as primes, it's outputting like 75% of primes as composites.
Up to 1000 it gives me this output for primes:
3, 5, 7, 11, 13, 17, 41, 97, 193, 257, 641, 769
As far as I know, my implementation is EXACTLY the same as the pseudo-code algorithm. I've debugged it line by line and it produced all of the expected variable values (I was following along with my calculator). Here's my function:
bool primeTest(int n)
{
int s = 0;
int d = n - 1;
while (d % 2 == 0)
{
d /= 2;
s++;
}
// this is the LOOP from the pseudo-algorithm
for (int i = 0; i < 10; i++)
{
int range = n - 4;
int a = rand() % range + 2;
//int a = rand() % (n/2 - 2) + 2;
bool skip = false;
long x = long(pow(a, d)) % n;
if (x == 1 || x == n - 1)
continue;
for (int r = 1; r < s; r++)
{
x = long(pow(x, 2)) % n;
if (x == 1)
{
// is not prime
return false;
}
else if (x == n - 1)
{
skip = true;
break;
}
}
if (!skip)
{
// is not prime
return false;
}
}
// is prime
return true;
}
Any help would be appreciated D:
EDIT: Here's the entire program, edited as you guys suggested - and now the output is even more broken:
bool primeTest(int n);
int main()
{
int count = 1; // number of found primes, 2 being the first of course
int maxCount = 10001;
long n = 3;
long maxN = 1000;
long prime = 0;
while (count < maxCount && n <= maxN)
{
if (primeTest(n))
{
prime = n;
cout << prime << endl;
count++;
}
n += 2;
}
//cout << prime;
return 0;
}
bool primeTest(int n)
{
int s = 0;
int d = n - 1;
while (d % 2 == 0)
{
d /= 2;
s++;
}
for (int i = 0; i < 10; i++)
{
int range = n - 4;
int a = rand() % range + 2;
//int a = rand() % (n/2 - 2) + 2;
bool skip = false;
//long x = long(pow(a, d)) % n;
long x = a;
for (int z = 1; z < d; z++)
{
x *= x;
}
x = x % n;
if (x == 1 || x == n - 1)
continue;
for (int r = 1; r < s; r++)
{
//x = long(pow(x, 2)) % n;
x = (x * x) % n;
if (x == 1)
{
return false;
}
else if (x == n - 1)
{
skip = true;
break;
}
}
if (!skip)
{
return false;
}
}
return true;
}
Now the output of primes, from 3 to 1000 (as before), is:
3, 5, 17, 257
I see now that x gets too big and it just turns into a garbage value, but I wasn't seeing that until I removed the "% n" part.
The likely source of error is the two calls to the pow function. The intermediate results will be huge (especially for the first call) and will probably overflow, causing the error. You should look at the modular exponentiation topic at Wikipedia.
Source of problem is probably here:
x = long(pow(x, 2)) % n;
pow from C standard library works on floating point numbers, so using it is a very bad idea if you just want to compute powers modulo n. Solution is really simple, just square the number by hand:
x = (x * x) % n