Jump to content

Miller Rabin Primality Test Wrong Result

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
3 replies to this topic

#1
Peter_APIIT

Peter_APIIT

    Newbie

  • Members
  • Pip
  • 2 posts
Hello to all, i have developed a miller rabin primality test program but return me wrong result all the time.

I don't know what wrong with it after few days of debug.

Code:
  

#include <iostream>

#include <sstream>

#include <string>

#include <bitset>

#include <vector>

#include <limits>

#include <algorithm>

#include <functional>

#include <utility>


#include <ctime>


using namespace std;


// =========================================

/*

Miller Rabin PT

= Further enhancement by testing n using first

7 primes(2, 3, 5, 7, 11, 13, 17, 19)

= depends on correctness of

Extended Riemann Hypothesis

= If N is an odd composite number then

the number of witnesses to the

compositeness of N is at least

(N - 1) / 2.


Example


1. n = 15

(15 - 1) / 2 = 7 composite number

4, 6, 8, 9, 10, 12, 14

2. n = 9

(9 - 1) / 2 = 4 composite number

4, 6, 8, 9

= Test 32 bit n using 2, 7, and 61 only

Add 3 and 5 for correctness



Algorithm Background

Let p be number to test

x is a nontrivial square root of 1 mod p. Then:

X ^ 2 congruence 1 (mod p)

(x-1)(x+1) congruence 0 (mod p)


Since x is nontrivial, x is neither

1 nor −1 mod p, and

therefore both x−1 and x+1 are coprime to p


If p does not divide (x-1) or (x+1)

but product of(x-1)(x+1) then

IsNotPrime

X=1;

X=-1;



Algorithm Steps

Let n be odd prime then n-1 is even rewrite

them as 2 ^ s * d(Odd)


Therefore,


1)a ^ d = 1 (mod n) or


2)a ^ 2r * d = -1 (mod n) for some 0 <= r <= s-1


If a is chosen uniformly at random and n is prime,

these formulas hold with probability 1/4.


Fermat Little Theorem used

to proove these two formula.


a ^ n-1 = 1 (mod n)


if Sqrt(a ^ n-1) must be either 1 or -1 == -1

2) true

else

a ^ 2^0 * d

a^d != -1 mod(n)

1) true


If find a ^ d != 1 (mod n) or

a ^ 2r * d != -1 (mod n)

a is a witness for the compositeness of n




Example

n = 221


n-1

= 221 - 1

= 220

= 2 ^ s * d

= 2 ^ 2 * 55


Randomly select a < n


a = 174



Test the two formula


a ^ d = 1 (mod 221)

a ^ 2r *d = -1 (mod 221)


174 ^ 55

= 47 not congruence to 1 (mod 221)


174 ^ 2(1) * 55

= 174 ^ 110 (mod 221)

= 220 (n-1)



Choose a = 137

137 ^ 55 (mod 221)

= 188 not congruence to 1 (mod 221)


137 ^ 2(1) * 55 (mod 221)

= 205 not congruence to -1 (mod 221)


Therefore, 221 is not prime




Solovay–Strassen primality test





*/

// =========================================


const unsigned short NITE = 50;


typedef unsigned long long ulong;


void Userinput(ulong&);

bool MillerRabinPrimeTest(const ulong&);

ulong ComputeModularExponentiation(const ulong&, const ulong&, const ulong&);

ulong ComputeExponentiation(const ulong&, const ulong&);


// =========================================

int main()

{

ulong number(0);


while (1)

{

cout << "\n";

Userinput(number);

cout << boolalpha << MillerRabinPrimeTest(number);

}


return 0;

}

// =========================================

void Userinput(ulong& number)

{

cout << "Enter Number : ";

cin >> number;


while (cin.fail())

{

cin.clear();

cin.ignore(numeric_limits<int>::max(), '\n');


cout << "\nEnter Number : ";

cin >> number;

}

}

// =========================================

bool MillerRabinPrimeTest(const ulong& number)

{

ulong a(0), x(0), y(0), tempNumber(0);

bool IsPrime(false);


tempNumber = number - 1;


if (number > 2)

{

// Write them as 2 ^ s * d

while (tempNumber % 2 == 0)

{

// tempNumber is d

tempNumber /= 2;

}


for (int loop = 0;loop < NITE;++loop)

{

srand((unsigned int)time(0));

// rand() % upperBound + startnumber

a = rand() % (number - 2) + 2;

// a = primeFactor[loop];

x = ComputeModularExponentiation(a, tempNumber, number);


y = (x * x) % number;

if (x == 1 || y == -1)

{

return true;

}


}

}


return IsPrime;

}

// =========================================

ulong ComputeModularExponentiation(

const ulong& a, const ulong& d,

const ulong& n)

{

enum {NBITS = numeric_limits<ulong>::digits };

string bitExponent = bitset<NBITS>((unsigned long)d).to_string();

typedef string::size_type strType;

strType MSSB = bitExponent.find_first_of('1');

ulong result(a % n);


MSSB += 1;


while (MSSB < NBITS)

{

result *= result;


if (bitExponent[MSSB] == '1')

{

result = result * a % n;

}

++MSSB;

}


return result;

}

// =========================================

ulong ComputeExponentiation(const ulong& base, const ulong& exponent)

{

enum {NBITS = numeric_limits<ulong>::digits };

string bitExponent = bitset<NBITS>((unsigned long)exponent).to_string();

typedef string::size_type strType;

strType MSSB = bitExponent.find_first_of('1');

ulong result(base);


MSSB += 1;


while (MSSB < NBITS)

{

result *= result;


if (bitExponent[MSSB] == '1')

{

result *= base;

}

++MSSB;

}


return result;

}

// =========================================




// =========================================



// =========================================




// =========================================





// =========================================



// =========================================

 

Thanks for any comments.

#2
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
You are not checking for overflows in ComputeModularExponentiation. It is highly likely that it does not work correctly for large exponents. Have you verified that it works correctly?
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#3
Peter_APIIT

Peter_APIIT

    Newbie

  • Members
  • Pip
  • 2 posts

Quote

Have you verified that it works correctly?

Since i using long long and its value is quite big and in each step there are a possibility to modulus to keep the value small.

I have checked it with base = 4, exponent = 13 and modulus = 497 and result is 445.

The wrong part is when i enter 2 or 3 it display composite number.

Thanks.

#4
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
Unfortunately, taking the modulus too soon can corrupt your results.

5*5 == 25

(5%3)*(5%3) != 25%3
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog