diff --git a/prime_fact.py b/prime_fact.py index d325880..72d0023 100644 --- a/prime_fact.py +++ b/prime_fact.py @@ -1,25 +1,37 @@ -from math import gcd +from math import gcd, isqrt import random from collections import Counter def is_probable_prime(n): - if n == 2: - return True - if n == 1 or n & 1 == 0: + if n < 2: return False - d = (n - 1) >> 1 - while d & 1 == 0: - d >>= 1 + SMALL_PRIME = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37) + for p in SMALL_PRIME: + if n == p: + return True + if n % p == 0: + return False + + r = isqrt(n) + if r * r == n: + return False + + d = n - 1 + s = (d & -d).bit_length() - 1 + d >>= s - for k in range(100): - a = random.randint(1, n - 1) - t = d - y = pow(a, t, n) - while t != n - 1 and y != 1 and y != n - 1: - y = (y * y) % n - t <<= 1 - if y != n - 1 and t & 1 == 0: + for a in SMALL_PRIME: + if a >= n: + continue + x = pow(a, d, n) + if x == 1 or x == n - 1: + continue + for _ in range(s - 1): + x = (x * x) % n + if x == n - 1: + break + else: return False return True diff --git a/tests/test_prime_fact.py b/tests/test_prime_fact.py index 32bb122..b38fed5 100644 --- a/tests/test_prime_fact.py +++ b/tests/test_prime_fact.py @@ -17,10 +17,45 @@ def test_prime_factorization(self): # TODO: Add test cases for prime factorization pass + def is_prime_example(self): + numList = [1, 2, 3, 4, 998244353, 1000000000000000000] + ansList = [False, True, True, False, True, False] + for n,f in zip(numList, ansList): + self.assertEqual(prime_fact.is_probable_prime(n), f) + + def is_prime_hackissue1325(self): + numList = [10, 2047, 1373653, 9080191, 25326001, 3215031751, 4759123141, 1122004669633, 2152302898747, 3474749660383, 341550071728321] + for n in numList: + self.assertEqual(prime_fact.is_probable_prime(n), False) + + def is_prime_carmichael(self): + numList = [1000, 1055384929, 37964809, 178482151, 4903921, 395044651, 721244161, 87318001, 455106601, 631071001, 2801124001, 45890209, 136625941, 496050841, 171679561, 1190790721, 252601, 854197345, 41041, 473847121, 1505432881, 133800661, 2693939401, 396262945, 129255841, 1699279441, 1776450565, 280067761, 1445084173, 2199931651, 3044970001, 1576826161, 683032801, 2140538401, 382536001, 172081, 1382114881, 633639097, 440707345, 517937581, 2797002901, 151813201, 1676203201, 1615681, 357380101, 64377991, 346808881, 1183104001, 1100674561, 2628073, 625482001, 1442761201, 92625121, 228842209, 1163659861, 8927101, 230996949, 395136505, 1214703721, 558977761, 101649241, 1955324449, 37280881, 488881, 23382529, 392099401, 13696033, 2178944461, 256828321, 93869665, 1836304561, 2301745249, 116682721, 38151361, 642708001, 2690867401, 902645857, 280761481, 390489121, 518706721, 1674309385, 8911, 2244932281, 1817067169, 1082809, 3078386641, 288120421, 449065, 70561921, 867800701, 1746692641, 1726372441, 14913991, 200753281, 1676641681, 2704801, 530881, 11921001, 1545387481, 1384157161, 314821, 101101, 2605557781, 1916729101, 1831048561, 2232385345, 115921, 38624041, 16046641, 1618206745, 629692801, 555465601, 1772267281, 99036001, 2414829781, 75681541, 602593441, 3044238121, 533860309, 843704401, 15888313, 2588653081, 246446929, 2811315361, 2539024741, 918661501, 1919767681, 2766172501, 26280073, 698548201, 118901521, 1574601601, 172290241, 208969201, 2467813621, 1152793621, 1206057601, 294409, 2302419601, 2212935985, 3828001, 1688639041, 65241793, 8719921, 8355841, 1708549501, 609865201, 1984089601, 1801558201, 4463641, 689880801, 109393201, 328573477, 34657141, 569332177, 842202361, 2617181281, 266003101, 9494101, 225745345, 527761081, 1773289, 1093916341, 2529410281, 977737321, 1571503801, 300614161, 544101481, 419520241, 2320224481, 3224065, 1698623641, 1318126321, 120981601, 10024561, 194120389, 1942608529, 1441316269, 490503601, 139592101, 977892241, 662086041, 133344793, 188516329, 3035837161, 1689411601, 1949646601, 10877581, 26719701, 84350561, 338740417, 1958102641, 230630401, 426821473, 2547621973, 2833846561, 8134561, 1269295201, 833608321, 1312332001, 2339165521, 31146661, 638959321, 1569457, 704934361, 46483633, 839275921, 2470348441, 81638401, 271794601, 1848112761, 189941761, 1992841201, 882796321, 705101761, 17236801, 60957361, 84417985, 809883361, 12261061, 552721, 606057985, 2509860961, 5049001, 19384289, 1461241, 1887933601, 958762729, 214850881, 53245921, 277241401, 891706861, 2443829641, 206955841, 161913961, 602426161, 1180398961, 139952671, 43331401, 968553181, 130032865, 1309440001, 35571601, 2806205689, 2170282969, 2332627249, 1035608041, 417241045, 2586927553, 997633, 5148001, 1855100017, 710541481, 41471521, 1705470481, 1778382541, 1483199641, 153927961, 115039081, 31692805, 161242705, 717164449, 1033669, 545570641, 1264145401, 168659569, 17098369, 2544590161, 561, 1520467201, 2598933481, 957044881, 702683101, 2049293401, 11205601, 1136739745, 939947009, 38637361, 403317421, 43584481, 2821, 2265650401, 184353001, 2359686241, 334783585, 1271325841, 3086434561, 834244501, 1216631521, 2642025673, 744866305, 44238481, 12945745, 2735309521, 167979421, 9585541, 1193229577, 2494621585, 10606681, 291848401, 258634741, 49333201, 134857801, 37167361, 1659935761, 360067201, 993905641, 849064321, 41298985, 860056705, 75765313, 54767881, 1362132541, 814056001, 146843929, 140241361, 7995169, 1103145121, 2048751901, 169057801, 178451857, 557795161, 5968873, 144218341, 1521835381, 1848681121, 82929001, 1268604001, 461854261, 36765901, 80282161, 434330401, 135556345, 1125038377, 683379841, 710382401, 34196401, 1988071801, 2140699681, 1648076041, 413058601, 194675041, 484662529, 2531845, 2396357041, 2616662881, 568227241, 157731841, 158864833, 18307381, 2508013, 88689601, 1785507361, 2527812001, 250200721, 2601144001, 824405041, 548871961, 2564889601, 9613297, 822531841, 658801, 2246916001, 590754385, 47006785, 1641323905, 1162202581, 67902031, 847491361, 836515681, 2489462641, 1795216501, 2176838049, 37354465, 2444950561, 1954174465, 1481619601, 3024774901, 130497361, 1140441121, 2101170097, 739444021, 1299963601, 1423668961, 6601, 18900973, 532758241, 247095361, 975303121, 545363281, 612347905, 362569201, 3007991701, 2216430721, 77826001, 169570801, 1321983937, 62756641, 557160241, 393716701, 271481329, 556450777, 151530401, 99830641, 492559141, 367804801, 1685266561, 15247621, 26921089, 529782121, 63973, 104852881, 1828377001, 2107535221, 1528936501, 461502097, 2607237361, 595405201, 3072080089, 804978721, 1909001, 962500561, 8341201, 518117041, 106041937, 3581761, 127664461, 1845871105, 1027334881, 181154701, 171454321, 188461, 1773486001, 1232469001, 2465, 1177195201, 440306461, 1784975941, 2100901, 483006889, 2597928961, 462199681, 2080544005, 2965085641, 1632785701, 1213619761, 1540454761, 945959365, 216821881, 52633, 3025708561, 1597821121, 684106401, 301704985, 129762001, 17586361, 6840001, 1207252621, 9439201, 434932961, 516684961, 6868261, 2561945401, 2367379201, 193708801, 2067887557, 511338241, 1198650961, 40280065, 2479305985, 838201, 11119105, 6313681, 1913016001, 580565233, 1132988545, 962442001, 477726145, 672389641, 182356993, 2470894273, 620169409, 981789337, 1918052065, 22665505, 2258118721, 851934601, 67994641, 238527745, 161035057, 1879480513, 212027401, 2322648901, 16778881, 841340521, 29111881, 790623289, 213835861, 2105594401, 1150270849, 83099521, 60112885, 2111416021, 14469841, 94536001, 798770161, 399001, 278545, 1200778753, 399906001, 1846817281, 231194965, 292776121, 221884001, 25603201, 507726901, 1894344001, 163954561, 955134181, 2573686441, 503758801, 2159003281, 124630273, 187188001, 2942952481, 930745621, 1899525601, 2560104001, 781347841, 935794081, 2201169601, 321602401, 851703301, 1223475841, 2361232477, 2278677961, 34901461, 102090781, 2436691321, 26932081, 45318561, 1200456577, 2224519921, 618068881, 1376844481, 2455921, 1784291041, 14676481, 2560600351, 2272748401, 1588247851, 299736181, 1404228421, 278152381, 703995733, 2407376665, 26474581, 1138049137, 270857521, 745864945, 334153, 41341321, 2766901501, 1760460481, 1018928485, 697906561, 75361, 393513121, 928482241, 357277921, 824389441, 1227220801, 2867755969, 1189238401, 2815304401, 1750412161, 1394746081, 2320690177, 1105, 2048443501, 9890881, 306871201, 3034203361, 707926801, 3030758401, 458368201, 50201089, 114910489, 963163201, 2943556201, 227752993, 1410833281, 93030145, 1534274841, 107714881, 9582145, 1227280681, 172430401, 547652161, 18162001, 2438403661, 1439328001, 1573132561, 193910977, 602074585, 109577161, 2064236401, 99861985, 7519441, 367939585, 20964961, 2064373921, 105309289, 1134044821, 743404663, 1696572001, 759472561, 1254318481, 825265, 1583582113, 7207201, 561481921, 1317828601, 1825568641, 3068534701, 1690230241, 53711113, 2342644921, 58489201, 33596641, 552894301, 45877861, 241242001, 186782401, 1090842145, 993420289, 96895441, 145124785, 670033, 311388337, 74165065, 27336673, 340561, 1024651, 6189121, 2574243721, 159492061, 611397865, 954732853, 128697361, 1001152801, 2519819281, 1194866101, 914801665, 2832480001, 2607162961, 40160737, 1420379065, 27402481, 765245881, 2998467901, 12262321, 968915521, 366532321, 2770560241, 410041, 1038165961, 1349671681, 1348964401, 1074363265, 2575260241, 413631505, 237597361, 2723859001, 852841, 348612265, 876850801, 104404861, 931694401, 393122521, 2391137281, 509033161, 188689501, 656187001, 1394942473, 1729, 2709611521, 616463809, 76595761, 132511681, 2215407601, 1419339691, 1841034961, 69331969, 302751505, 888700681, 1251992281, 2111488561, 15829633, 40622401, 2433601, 564651361, 1592668441, 111291181, 13992265, 1251295501, 686059921, 279377281, 403043257, 1330655041, 31405501, 39353665, 1507746241, 325546585, 6054985, 1896961801, 186393481, 329769721, 809702401, 981567505, 2602378721, 273769921, 540066241, 79624621, 72108421, 295826581, 79411201, 2480343553, 2239622113, 1260332137, 499310197, 490099681, 784966297, 413138881, 122785741, 1615335085, 556199281, 242641153, 32914441, 1626167341, 4767841, 29341, 153589801, 75151441, 5444489, 274569601, 868234081, 558570961, 1152271, 5031181, 1504651681, 21584305, 2858298301, 941056273, 1378483393, 64774081, 6049681, 1193221, 2230305949, 2199700321, 333065305, 577240273, 561777121, 2497638781, 292244833, 794937601, 48628801, 711374401, 55462177, 549333121, 748657, 1529544961, 5481451, 2073560401, 3001561441, 551672221, 1404111241, 958735681, 579606301, 852729121, 1050985, 1849811041, 834720601, 10585, 2456536681, 2029554241, 78091201, 2657502001, 162401, 4335241, 746706961, 226509361, 2457411265, 8719309, 3022354401, 1999004365, 855734401, 133205761, 67653433, 8830801, 1932608161, 438359041, 1428966001, 1079556193, 134809921, 2733494401, 1490522545, 1030401901, 10837321, 2000436751, 947993761, 35703361, 1407548341, 727083001, 625060801, 172947529, 17316001, 13187665, 121247281, 105869401, 119327041, 10267951, 1803278401, 1312114945, 1657700353, 255160621, 2117725921, 36121345, 713588401, 3057601, 775368901, 775866001, 2323147201, 1031750401, 11972017, 238244041, 963168193, 2787998641, 12490201, 84311569, 43620409, 481239361, 1439492041, 126217, 257495641, 368113411, 722923201, 1210178305, 1943951041, 471905281, 180115489, 19683001, 1962804565, 104569501, 990893569, 776176261, 15841, 2677147201, 321197185, 1752710401, 958970545, 863984881, 1070659201, 1597009393, 1976295241, 612816751, 600892993, 2217951073, 158404141, 2630374741, 196358977, 27062101, 934784929, 3072094201, 43286881, 101957401, 105117481, 2126689501, 170947105, 150846961, 56052361, 2523947041, 829678141, 93614521, 2842912381, 510825601, 10402561, 940123801, 4909177, 1833328621, 471441001, 68154001, 1316958721, 2353639681, 597717121, 78120001, 382304161, 1950276565, 252141121, 2097317377, 40430401, 15403285, 1490078305, 790020001, 366652201, 2665141921, 593234929, 1672719217, 80927821, 81926461, 1131222841, 549117205, 1701016801, 6733693, 2494465921, 621101185, 1678569121, 364590721, 2510085721, 214852609, 986088961, 1422477001, 289860481, 100427041, 3077802001, 318266641, 358940737, 90698401, 652969351, 2377166401, 1854001513, 2685422593, 67371265, 173085121, 416964241, 42490801, 40917241, 2313774001, 17812081, 48321001, 1257102001, 1857241, 296559361, 530443201, 2223876601, 1332521065, 65037817, 333229141, 29020321, 178837201, 1858395529, 2113921, 2023528501, 1646426881, 656601, 289766701, 354938221, 549538081, 752102401, 573896881, 1177800481, 5310721, 512461, 2295209281, 1452767521, 5632705, 175997185, 3146221, 176659201, 28787185, 2309027281, 83966401, 1337805505, 1295577361, 832060801, 295643089, 1769031901, 2776874941, 405739681, 3069196417, 1256855041, 2702470861, 897880321, 542497201, 985052881, 771043201, 429553345, 2430556381, 2335640077, 885336481, 1688214529, 115542505, 174352641, 275283401, 72286501, 1072570801, 46657, 33302401, 3664585, 1515785041, 62745] + for n in numList: + self.assertEqual(prime_fact.is_probable_prime(n), False) + + def is_prime_true_case_18_dig(self): + numList = [100000000000000003, 100000000000000013, 100000000000000019, 100000000000000021, 100000000000000049, 100000000000000081, 100000000000000099, 100000000000000141, 100000000000000181, 100000000000000337, 100000000000000339, 100000000000000369, 100000000000000379, 100000000000000423, 100000000000000519, 100000000000000543, 100000000000000589, 100000000000000591, 100000000000000609, 100000000000000669, 100000000000000691, 100000000000000781, 100000000000000787, 100000000000000817, 100000000000000819, 100000000000000871, 100000000000000889, 100000000000001053, 100000000000001071, 100000000000001093, 100000000000001099, 100000000000001107, 100000000000001201, 100000000000001219, 100000000000001221, 100000000000001243, 100000000000001249, 100000000000001287, 100000000000001293, 100000000000001327, 100000000000001399, 100000000000001429, 100000000000001449, 100000000000001459, 100000000000001573, 100000000000001603, 100000000000001623, 100000000000001641, 100000000000001903, 100000000000001921, 100000000000001947, 100000000000001971, 100000000000001989, 100000000000002029, 100000000000002041, 100000000000002139, 100000000000002169, 100000000000002197, 100000000000002203, 100000000000002307, 100000000000002341, 100000000000002409, 100000000000002433, 100000000000002461, 100000000000002493, 100000000000002569, 100000000000002587, 100000000000002589, 100000000000002643, 100000000000002649, 100000000000002701, 100000000000002709, 100000000000002733, 100000000000002737, 100000000000002799, 100000000000002821, 100000000000002833, 100000000000002857, 100000000000002859, 100000000000002911, 100000000000002913, 100000000000002929, 100000000000002937, 100000000000002959, 100000000000003007, 100000000000003021, 100000000000003039, 100000000000003079, 100000000000003177, 100000000000003253, 100000000000003289, 100000000000003307, 100000000000003417, 100000000000003447, 100000000000003457, 100000000000003487, 100000000000003559, 100000000000003561, 100000000000003699, 100000000000003777] + for n in numList: + self.assertEqual(prime_fact.is_probable_prime(n), True) + + def is_prime_sieve_eratosthenes(self): + MAX_N = 2000 + sieveList = [True for i in range(MAX_N)] + sieveList[0] = False + sieveList[1] = False + for i in range(2, MAX_N): + if sieveList[i]: + for j in range(2*i, MAX_N, i): + sieveList[j]=False + for i in range(MAX_N): + self.assertEqual(prime_fact.is_probable_prime(i), sieveList[i]) + def test_is_prime(self): - """Test primality testing""" - # TODO: Add test cases for primality testing - pass + self.is_prime_example() + self.is_prime_hackissue1325() + self.is_prime_carmichael() + self.is_prime_true_case_18_dig() + self.is_prime_sieve_eratosthenes() def test_divisors(self): """Test divisor enumeration"""