-
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
Added is_probable_prime using Rabin Miller testing #16
Conversation
Codecov Report
@@ Coverage Diff @@
## master #16 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 13 12 -1
Lines 536 533 -3
=====================================
- Hits 536 533 -3
Continue to review full report at Codecov.
|
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.
gcd()
has been added so please merge the changes from upstream.- Add spaces on both sides of all binary operators.
- See the coverage report to see which lines haven't been hit while running the tests, and add a few such cases that would execute those lines.
- Use
or
andand
instead of||
and&&
respectively.
include/BigInt.hpp
Outdated
@@ -99,6 +99,9 @@ class BigInt { | |||
int to_int() const; | |||
long to_long() const; | |||
long long to_long_long() const; | |||
|
|||
// Math functions: | |||
bool is_probable_prime(size_t certainty); |
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.
Add the const
modifier at the end as in the methods above.
include/functions/math.hpp
Outdated
@@ -125,4 +124,60 @@ BigInt sqrt(const BigInt& num) { | |||
return sqrt_current; | |||
} | |||
|
|||
/* | |||
is_portable_prime |
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.
Typo!
include/functions/math.hpp
Outdated
BigInt temp_d = d; | ||
BigInt temp2_d = d; | ||
BigInt TWO = 2; | ||
for (;0<certainty;certainty--) { |
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.
You can change this to a while
loop.
while (certainty-- > 0) {
...
}
Just added the changes, thanks for the feedback |
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.
Sorry for the late review 😅
include/functions/math.hpp
Outdated
while (temp2_d > 0) { | ||
// Getting last character from BigInt and checking if even or odd | ||
std::string temp_s = temp2_d.to_string(); | ||
if ((int) temp_s.back() & 1) { |
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.
The following is easier to read and is also more efficient since the string returned by to_string()
is temporary and is automatically destroyed:
int last_digit = temp2_d.to_string().back() - '0';
if (last_digit % 2)
...
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.
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.
The "ModVersion" one is slightly faster. Is it the one with the suggested change?
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.
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.
I found the following to be the fastest of the 4 ways that I tested:
int last_digit = y.to_string().back() - '0';
if (last_digit & 1)
...
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.
That should work, the operation that was causing the most performance loss was the modulo so we should be able to use this code. I'm about to test it now.
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.
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.
Dropping the - '0'
part should also work correctly and will be slightly faster.
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.
The results have been very strange. Sometimes it runs faster, sometimes it's the same speed and sometimes it's slower. I'm going to use a profiler to measure the performance because I don't trust the time command to be completely accurate.
include/functions/math.hpp
Outdated
// Corner cases ensure num > 4 | ||
BigInt a = TWO + BigInt(rand()) % (num - 4); | ||
BigInt res = 1; | ||
BigInt x = a % num; |
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.
Try to use better names for a
and x
.
include/functions/math.hpp
Outdated
} | ||
|
||
BigInt temp_d = d; | ||
BigInt temp2_d = d; |
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.
Can you come up with better names for d
, temp_d
and temp2_d
?
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.
I can't really think of really creative names for them but I've put more comments to explain their function.
include/functions/math.hpp
Outdated
if (num <= 1 or num == 4) return false; | ||
if (num <= 3) return true; | ||
|
||
// Find r such that n = 2^d * r + 1 for some r >= 1 |
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.
Is n
= num
and r
= res
? If so, then please make sure that the names in the formula and in the code are the same in order to explain the code better.
include/functions/math.hpp
Outdated
*/ | ||
|
||
bool BigInt::is_probable_prime(size_t certainty) const { | ||
BigInt num = this->value; |
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.
This will set num
to the absolute value of this object (same as num = abs(*this)
). Is that desired behaviour when a number is negative? (I'm just confirming since I'm not sure myself.)
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.
From Wolfram MathWorld:
A prime number (or prime integer, often simply called a "prime" for short) is a positive integer p>1 that has no positive integer divisors other than 1 and p itself.
Negative integers are therefore not prime. So you should change this line to:
BigInt num = *this;
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.
Alright, thanks I've fixed that issue
test/functions/math.test.cpp
Outdated
num = "4702877858580764415667235078667510929270158248348"; | ||
REQUIRE(num.is_probable_prime(1) == false); | ||
num = "378348910233465647859184421334615532543749747185321634086219"; | ||
REQUIRE(num.is_probable_prime(1) == true); |
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.
It would be good to have checks for even larger numbers, and with more variation in the value of certainty.
Also, please add a few cases for negative numbers too.
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.
Using bigger numbers and raising certainty will raise the time dramatically but I will implement both.
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.
Using bigger numbers and raising certainty will raise the time dramatically
Yes, that's why we're testing it with bigger values - to check that it shouldn't take too long to work out the result for much larger numbers.
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.
Understood, because of the way the algorithm works with certainty. It's going to take a long time unless we optimize the operations for BigInt. I agree with you though, I believed that it shouldn't take too long to work out result for much larger numbers. How would you like to tackle the problem?
include/functions/math.hpp
Outdated
/* | ||
Gcd (BigInt, BigInt) : | ||
-------------------- | ||
|
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.
Seems like these 4 lines were added my mistake while resolving merge conflicts.
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.
I'll make sure to get that done.
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.
Are you sure that you want me to remove this comment? It's above the function definition for BigInt gcd(const BigInt &num1, const BigInt &num2)
would you like me to delete this function also?
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.
This comment is extra. If you look further, you'll see the comment for gcd(BigInt, BigInt)
. So just remove these 4 lines.
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.
Understood, thanks
test/functions/math.test.cpp
Outdated
Naive gcd for testing purpose. | ||
*/ | ||
|
||
long long naive_gcd(long long a, long long b){ |
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.
Lines 290-311 were replaced by gcd(long long, long long)
that follows, so please remove them.
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.
I'll also get this done.
is_probable_prime is a public member method of BigInt that uses the Rabin Miller primality test, a user-selected number ,passed in as a parameter named "certainty", of times to determine if a BigInt is prime or not.