From 52f80f33233140877c12191364d1cc4c1b5a9d97 Mon Sep 17 00:00:00 2001 From: Anzoteh96 Date: Wed, 23 Oct 2019 21:22:41 -0400 Subject: [PATCH 01/11] Added binary exponentiaion with respect to modulo --- maths/binary_exp_mod.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 maths/binary_exp_mod.py diff --git a/maths/binary_exp_mod.py b/maths/binary_exp_mod.py new file mode 100644 index 000000000000..e538465d6296 --- /dev/null +++ b/maths/binary_exp_mod.py @@ -0,0 +1,23 @@ +import math + +def bin_exp_mod(a, n, b): + # mod b + assert(not (b == 0)), "This cannot accept modulo that is == 0" + if (n == 0): + return 1 + + if (n % 2 == 1): + return (bin_exp_mod(a, n - 1, b) * a) % b + + r = bin_exp_mod(a, n/2, b) + return (r * r) % b + +if __name__ == '__main__': + try: + BASE = int(input("Enter Base : ").strip()) + POWER = int(input("Enter Power : ").strip()) + MODULO = int(input("Enter Modulo : ").strip()) + except ValueError: + print("Invalid literal for integer") + + print(bin_exp_mod(BASE, POWER, MODULO)) From 3150ebc59fb76fefe5b569a43d7dab7dff60572b Mon Sep 17 00:00:00 2001 From: Anzoteh96 Date: Wed, 23 Oct 2019 21:40:52 -0400 Subject: [PATCH 02/11] Added miller rabin: the probabilistic primality test for large numbers --- maths/miller_rabin.py | 47 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 maths/miller_rabin.py diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py new file mode 100644 index 000000000000..2eabf8993bfb --- /dev/null +++ b/maths/miller_rabin.py @@ -0,0 +1,47 @@ +import numpy as np +from binary_exp_mod import bin_exp_mod +import random + +# This is a probabilistic check to test primality, useful for big numbers! +def is_prime(n, prec = 1000): + if (n < 2): + return False + + if (n % 2 == 0): + return n == 2 + + # this means n is odd + d = n - 1 + exp = 0 + while d % 2 == 0: + d /= 2 + exp += 1 + + # n - 1=d*(2**exp) + count = 0 + while (count < prec): + a = random.randint(2, n - 1) + b = bin_exp_mod(a, d, n) + if (b != 1): + flag = True + for i in range(exp): + c = bin_exp_mod(b, (2 ** i), n) + if c == n - 1: + flag = False + break + if flag: + return False + count += 1 + return True + + +if __name__ == '__main__': + n = int(input("Enter bound : ").strip()) + primes = [] + for i in range(n + 1): + if is_prime(i): + primes.append(i) + print("Here's the list of primes") + for p in primes: + print(p, end=" ") + print() From 98667979ca1a3c7f476e846d0efa7a6c442d5512 Mon Sep 17 00:00:00 2001 From: Anzoteh96 Date: Wed, 23 Oct 2019 21:47:33 -0400 Subject: [PATCH 03/11] Removed unused import --- maths/binary_exp_mod.py | 2 -- maths/miller_rabin.py | 1 - 2 files changed, 3 deletions(-) diff --git a/maths/binary_exp_mod.py b/maths/binary_exp_mod.py index e538465d6296..d28b343baf9f 100644 --- a/maths/binary_exp_mod.py +++ b/maths/binary_exp_mod.py @@ -1,5 +1,3 @@ -import math - def bin_exp_mod(a, n, b): # mod b assert(not (b == 0)), "This cannot accept modulo that is == 0" diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py index 2eabf8993bfb..3a7d6de49f1a 100644 --- a/maths/miller_rabin.py +++ b/maths/miller_rabin.py @@ -1,4 +1,3 @@ -import numpy as np from binary_exp_mod import bin_exp_mod import random From 8dfa0d4bdf2d3d5bdc850b7b5ea7cb3c1e5ca70b Mon Sep 17 00:00:00 2001 From: Anzoteh96 Date: Thu, 24 Oct 2019 12:25:29 -0400 Subject: [PATCH 04/11] Added test for miller_rabin --- maths/miller_rabin.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py index 3a7d6de49f1a..955ceeaf4c2d 100644 --- a/maths/miller_rabin.py +++ b/maths/miller_rabin.py @@ -1,7 +1,11 @@ -from binary_exp_mod import bin_exp_mod +from .binary_exp_mod import bin_exp_mod +from .prime_check import prime_check import random +import unittest # This is a probabilistic check to test primality, useful for big numbers! +# if it's a prime, it will return true +# if it's not a prime, the chance of it returning true is at most 1/4**prec def is_prime(n, prec = 1000): if (n < 2): return False @@ -24,23 +28,24 @@ def is_prime(n, prec = 1000): if (b != 1): flag = True for i in range(exp): - c = bin_exp_mod(b, (2 ** i), n) - if c == n - 1: + if b == n - 1: flag = False break + b = b * b + b %= n if flag: return False count += 1 return True +# this test simply test if this method and the test generated by prime_check agrees +class Test(unittest.TestCase): + def test_primes(self, n): + for i in range(n): + self.assertTrue(is_prime(n) == prime_check(n)) if __name__ == '__main__': - n = int(input("Enter bound : ").strip()) - primes = [] - for i in range(n + 1): - if is_prime(i): - primes.append(i) - print("Here's the list of primes") - for p in primes: - print(p, end=" ") - print() + n = abs(int(input("Enter bound : ").strip())) + print("Here's the list of primes:") + print(", ".join(str(i) for i in range(n + 1) if is_prime(i))) + unittest.main(n + 1) From 752877c598dc23a355cbcb152387c658a4ebdc6e Mon Sep 17 00:00:00 2001 From: Anzoteh96 Date: Thu, 24 Oct 2019 12:28:26 -0400 Subject: [PATCH 05/11] Add test to binary_exp_mod --- maths/binary_exp_mod.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/maths/binary_exp_mod.py b/maths/binary_exp_mod.py index d28b343baf9f..ae0eb5d482a4 100644 --- a/maths/binary_exp_mod.py +++ b/maths/binary_exp_mod.py @@ -1,3 +1,5 @@ +import unittest + def bin_exp_mod(a, n, b): # mod b assert(not (b == 0)), "This cannot accept modulo that is == 0" @@ -10,6 +12,11 @@ def bin_exp_mod(a, n, b): r = bin_exp_mod(a, n/2, b) return (r * r) % b +class Test(unittest.TestCase): + def test_mod(self): + self.assertTrue(bin_exp_mod(3, 4, 5) == 1) + self.assertTrue(bin_exp_mod(7, 13, 10) == 7) + if __name__ == '__main__': try: BASE = int(input("Enter Base : ").strip()) @@ -19,3 +26,4 @@ def bin_exp_mod(a, n, b): print("Invalid literal for integer") print(bin_exp_mod(BASE, POWER, MODULO)) + unittest.main() From 0ed6926ad1e3f79daa2435b9554322bf500a1625 Mon Sep 17 00:00:00 2001 From: Anzoteh96 Date: Thu, 24 Oct 2019 12:35:45 -0400 Subject: [PATCH 06/11] Removed test parameter to make Travis CI happy --- maths/miller_rabin.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py index 955ceeaf4c2d..d04ae0102c6d 100644 --- a/maths/miller_rabin.py +++ b/maths/miller_rabin.py @@ -40,12 +40,12 @@ def is_prime(n, prec = 1000): # this test simply test if this method and the test generated by prime_check agrees class Test(unittest.TestCase): - def test_primes(self, n): - for i in range(n): - self.assertTrue(is_prime(n) == prime_check(n)) + def test_primes(self): + for i in range(1000): + self.assertTrue(is_prime(i) == prime_check(i)) if __name__ == '__main__': n = abs(int(input("Enter bound : ").strip())) print("Here's the list of primes:") print(", ".join(str(i) for i in range(n + 1) if is_prime(i))) - unittest.main(n + 1) + unittest.main() From ca630f0b9247b188dcb05a7945b59efb0a4abe5c Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 24 Dec 2019 06:55:06 +0100 Subject: [PATCH 07/11] unittest.main() # doctest: +ELLIPSIS ... --- maths/binary_exp_mod.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/maths/binary_exp_mod.py b/maths/binary_exp_mod.py index ae0eb5d482a4..4bfb6fdd5bb0 100644 --- a/maths/binary_exp_mod.py +++ b/maths/binary_exp_mod.py @@ -13,6 +13,10 @@ def bin_exp_mod(a, n, b): return (r * r) % b class Test(unittest.TestCase): + """ + >>> unittest.main() # doctest: +ELLIPSIS + ... + """ def test_mod(self): self.assertTrue(bin_exp_mod(3, 4, 5) == 1) self.assertTrue(bin_exp_mod(7, 13, 10) == 7) From 259f18b7eef673b29c429b328ea624bd871d9c59 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 24 Dec 2019 07:01:05 +0100 Subject: [PATCH 08/11] Update binary_exp_mod.py --- maths/binary_exp_mod.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maths/binary_exp_mod.py b/maths/binary_exp_mod.py index 4bfb6fdd5bb0..0b5773f6db2c 100644 --- a/maths/binary_exp_mod.py +++ b/maths/binary_exp_mod.py @@ -14,7 +14,8 @@ def bin_exp_mod(a, n, b): class Test(unittest.TestCase): """ - >>> unittest.main() # doctest: +ELLIPSIS + #>>> unittest.main() # doctest: +ELLIPSIS + >>> Test().test_mod() # doctest: +ELLIPSIS ... """ def test_mod(self): From 2b09e498816107ed6bf880bbe93eee7974891fc2 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 24 Dec 2019 07:08:30 +0100 Subject: [PATCH 09/11] Update binary_exp_mod.py --- maths/binary_exp_mod.py | 50 ++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/maths/binary_exp_mod.py b/maths/binary_exp_mod.py index 0b5773f6db2c..67dd1e728b18 100644 --- a/maths/binary_exp_mod.py +++ b/maths/binary_exp_mod.py @@ -1,34 +1,28 @@ -import unittest - def bin_exp_mod(a, n, b): - # mod b - assert(not (b == 0)), "This cannot accept modulo that is == 0" - if (n == 0): - return 1 + """ + >>> bin_exp_mod(3, 4, 5) + 1 + >>> bin_exp_mod(7, 13, 10) + 7 + """ + # mod b + assert not (b == 0), "This cannot accept modulo that is == 0" + if n == 0: + return 1 - if (n % 2 == 1): - return (bin_exp_mod(a, n - 1, b) * a) % b + if n % 2 == 1: + return (bin_exp_mod(a, n - 1, b) * a) % b - r = bin_exp_mod(a, n/2, b) - return (r * r) % b + r = bin_exp_mod(a, n / 2, b) + return (r * r) % b -class Test(unittest.TestCase): - """ - #>>> unittest.main() # doctest: +ELLIPSIS - >>> Test().test_mod() # doctest: +ELLIPSIS - ... - """ - def test_mod(self): - self.assertTrue(bin_exp_mod(3, 4, 5) == 1) - self.assertTrue(bin_exp_mod(7, 13, 10) == 7) -if __name__ == '__main__': - try: - BASE = int(input("Enter Base : ").strip()) - POWER = int(input("Enter Power : ").strip()) - MODULO = int(input("Enter Modulo : ").strip()) - except ValueError: - print("Invalid literal for integer") +if __name__ == "__main__": + try: + BASE = int(input("Enter Base : ").strip()) + POWER = int(input("Enter Power : ").strip()) + MODULO = int(input("Enter Modulo : ").strip()) + except ValueError: + print("Invalid literal for integer") - print(bin_exp_mod(BASE, POWER, MODULO)) - unittest.main() + print(bin_exp_mod(BASE, POWER, MODULO)) From 918c2e899f1fdb83b596e828f1f8d1d420e4518b Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 24 Dec 2019 07:14:19 +0100 Subject: [PATCH 10/11] Update miller_rabin.py --- maths/miller_rabin.py | 87 +++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py index d04ae0102c6d..1300b86fbc56 100644 --- a/maths/miller_rabin.py +++ b/maths/miller_rabin.py @@ -1,51 +1,50 @@ +import random + from .binary_exp_mod import bin_exp_mod from .prime_check import prime_check -import random -import unittest + # This is a probabilistic check to test primality, useful for big numbers! # if it's a prime, it will return true # if it's not a prime, the chance of it returning true is at most 1/4**prec -def is_prime(n, prec = 1000): - if (n < 2): - return False - - if (n % 2 == 0): - return n == 2 - - # this means n is odd - d = n - 1 - exp = 0 - while d % 2 == 0: - d /= 2 - exp += 1 - - # n - 1=d*(2**exp) - count = 0 - while (count < prec): - a = random.randint(2, n - 1) - b = bin_exp_mod(a, d, n) - if (b != 1): - flag = True - for i in range(exp): - if b == n - 1: - flag = False - break - b = b * b - b %= n - if flag: +def is_prime(n, prec=1000): + """ + >>> all(is_prime(i) == prime_check(i) for i in range(1000)) + True + """ + if n < 2: return False - count += 1 - return True - -# this test simply test if this method and the test generated by prime_check agrees -class Test(unittest.TestCase): - def test_primes(self): - for i in range(1000): - self.assertTrue(is_prime(i) == prime_check(i)) - -if __name__ == '__main__': - n = abs(int(input("Enter bound : ").strip())) - print("Here's the list of primes:") - print(", ".join(str(i) for i in range(n + 1) if is_prime(i))) - unittest.main() + + if n % 2 == 0: + return n == 2 + + # this means n is odd + d = n - 1 + exp = 0 + while d % 2 == 0: + d /= 2 + exp += 1 + + # n - 1=d*(2**exp) + count = 0 + while count < prec: + a = random.randint(2, n - 1) + b = bin_exp_mod(a, d, n) + if b != 1: + flag = True + for i in range(exp): + if b == n - 1: + flag = False + break + b = b * b + b %= n + if flag: + return False + count += 1 + return True + + +if __name__ == "__main__": + n = abs(int(input("Enter bound : ").strip())) + print("Here's the list of primes:") + print(", ".join(str(i) for i in range(n + 1) if is_prime(i))) From b10be9b51fd177ab0ab27bfbbafd0b80af5a1f32 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 24 Dec 2019 07:19:21 +0100 Subject: [PATCH 11/11] from .prime_check import prime_check --- maths/miller_rabin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py index 1300b86fbc56..fe992027190b 100644 --- a/maths/miller_rabin.py +++ b/maths/miller_rabin.py @@ -1,7 +1,6 @@ import random from .binary_exp_mod import bin_exp_mod -from .prime_check import prime_check # This is a probabilistic check to test primality, useful for big numbers! @@ -9,6 +8,7 @@ # if it's not a prime, the chance of it returning true is at most 1/4**prec def is_prime(n, prec=1000): """ + >>> from .prime_check import prime_check >>> all(is_prime(i) == prime_check(i) for i in range(1000)) True """