-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is probable prime #32
base: master
Are you sure you want to change the base?
Changes from 7 commits
83d4971
0650ee8
58e673a
c5bcbde
773c667
59927ec
0a8eba1
d58e8d2
c59028a
f6a56ac
5028105
e1eda6f
5b4919a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,9 +7,13 @@ | |
#ifndef BIG_INT_MATH_FUNCTIONS_HPP | ||
#define BIG_INT_MATH_FUNCTIONS_HPP | ||
|
||
#include <string> | ||
|
||
#include <tuple> | ||
#include <random> | ||
#include <functional> | ||
|
||
#include "functions/conversion.hpp" | ||
#include "functions/utility.hpp" | ||
|
||
|
||
/* | ||
|
@@ -153,6 +157,63 @@ BigInt gcd(const BigInt &num1, const BigInt &num2){ | |
return abs_num1; | ||
} | ||
|
||
/* | ||
BigInt::is_probable_prime(size_t) | ||
--------------------------------- | ||
Returns boolean representing the primality of the BigInt object that this method refers | ||
to using Rabin-Miller Primality testing. | ||
NOTE: This test is probablisitic so it is not failproof. A composite number passes the test | ||
for at most 1/4 of the possible bases. This is true for each iteration of the test, so the | ||
Probability a composite number passes is 1/4^N or less, where N is equal to certainty | ||
*/ | ||
|
||
bool BigInt::is_probable_prime(size_t certainty) { | ||
// The BigInt object that this method refers to will be referred to as n in comments | ||
#define COMPOSITE false | ||
#define PRIME true | ||
|
||
if (*this <= BigInt(3) || *this == BigInt(5)) { | ||
return PRIME; | ||
} | ||
|
||
std::default_random_engine generator; | ||
std::uniform_int_distribution<int> distribution(2, this->to_long_long()-2); | ||
auto random_number = std::bind(distribution, generator); | ||
|
||
const BigInt ONE = 1; | ||
const BigInt TWO = 2; | ||
BigInt a; | ||
while (certainty-- > 0) { | ||
// 1 <= a < n | ||
a = random_number(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rename |
||
// If there exists an x > 1 such that a % x == 0 && n % x == 0 | ||
// then n is composite | ||
if (gcd(a, *this) != ONE) { | ||
return COMPOSITE; | ||
} | ||
int s, m; | ||
// Calculates needed variables that fit the equation | ||
// n - 1 = 2^s*m such that s >= 1 and m is odd | ||
std::tie(s, m) = calculate_vars(this->to_long_long()); | ||
// x = a^m%n | ||
BigInt x = pow(a, m)%*this; | ||
if (x == ONE || x == *this-ONE) { | ||
continue; | ||
} | ||
for (int i = 0; i < s-1; i++) { | ||
// x = x^2%n | ||
x = pow(x, 2)%*this; | ||
if (x == 1) { | ||
return COMPOSITE; | ||
} else if (x == *this-ONE) { | ||
continue; | ||
} | ||
return COMPOSITE; | ||
} | ||
} | ||
return PRIME; | ||
} | ||
|
||
|
||
/* | ||
gcd(BigInt, Integer) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
#define BIG_INT_UTILITY_FUNCTIONS_HPP | ||
|
||
#include <tuple> | ||
|
||
#include <math.h> | ||
|
||
/* | ||
is_valid_number | ||
|
@@ -110,4 +110,36 @@ bool is_power_of_10(const std::string& num){ | |
return true; // first digit is 1 and the following digits are all 0 | ||
} | ||
|
||
|
||
/* | ||
calculate_vars | ||
-------------- | ||
Calculates the s and m variables needed to complete Rabin Miller Primality | ||
test. | ||
|
||
s and m come from the formula n-1 = 2^s*m, where m is odd and s >= 1 | ||
*/ | ||
|
||
std::tuple<int, int> calculate_vars(long long n) { | ||
int s = 1; | ||
int m = 1; | ||
const long long sentinel_value = n-1; | ||
long long calculated_value = 2; | ||
|
||
while (sentinel_value >= calculated_value) { | ||
if (sentinel_value > calculated_value) { | ||
s++; | ||
long long spower = pow(2, s); | ||
if (spower > sentinel_value) { | ||
return std::make_tuple(0,0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please indent your code with 4 spaces per level. |
||
} | ||
m = sentinel_value/spower; | ||
calculated_value = spower*m; | ||
} else if (sentinel_value == calculated_value) { | ||
return std::make_tuple(s, m); | ||
} | ||
} | ||
return std::make_tuple(s, m); | ||
} | ||
|
||
#endif // BIG_INT_UTILITY_FUNCTIONS_HPP |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -91,8 +91,8 @@ TEST_CASE("Base cases for pow()", "[functions][math][pow]") { | |
} | ||
|
||
TEST_CASE("pow() with BigInt base", "[functions][math][pow]") { | ||
BigInt num = 11; | ||
REQUIRE(pow(num, 9) == 2357947691); | ||
BigInt num = 11; | ||
REQUIRE(pow(num, 9) == 2357947691); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please indent your code with 4 spaces per level. |
||
num = -27; | ||
REQUIRE(pow(num, 16) == "79766443076872509863361"); | ||
num = 174; | ||
|
@@ -382,3 +382,14 @@ TEST_CASE("lcm()of big integers", "[functions][math][lcm][big]") { | |
"533220692127153044311875258011747917053108027629278373174251200266431" | ||
"428784066739966"); | ||
} | ||
|
||
TEST_CASE("Base cases for is_probable_prime()", "[functions][math][is_probable_prime]") { | ||
BigInt num = 1; | ||
REQUIRE(num.is_probable_prime(25) == 1); | ||
num = 2; | ||
REQUIRE(num.is_probable_prime(25) == 1); | ||
num = 3; | ||
REQUIRE(num.is_probable_prime(25) == 1); | ||
num = 5; | ||
REQUIRE(num.is_probable_prime(25) == 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about larger cases? Can you check that it returns
and
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is because |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These
#defines
are not required.