def mr(n, bases): """Perform a Miller-Rabin strong pseudoprime test on n using a given list of bases/witnesses. References ========== - Richard Crandall & Carl Pomerance (2005), "Prime Numbers: A Computational Perspective", Springer, 2nd edition, 135-138 A list of thresholds and the bases they require are here: http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test#Deterministic_variants_of_the_test Examples ======== >>> from sympy.ntheory.primetest import mr >>> mr(1373651, [2, 3]) False >>> mr(479001599, [31, 73]) True """ from sympy.ntheory.factor_ import trailing from sympy.polys.domains import ZZ n = as_int(n) if n < 2: return False # remove powers of 2 from n-1 (= t * 2**s) s = trailing(n - 1) t = n >> s for base in bases: # Bases >= n are wrapped, bases < 2 are invalid if base >= n: base %= n if base >= 2: base = ZZ(base) if not _test(n, base, s, t): return False return True
def _info(bases): """ Analyze the list of bases, reporting the number of 'j-loops' that will be required if this list is passed to _test (stot) and the primes that must be cleared by a previous test. This info tag should then be appended to any new mr_safe line that is added so someone can easily see whether that line satisfies the requirements of mr_safe (see docstring there for details). """ from sympy.ntheory.factor_ import factorint, trailing factors = [] tot = 0 for b in bases: tot += trailing(b - 1) f = factorint(b) factors.extend(f) factors = sorted(set(factors)) bases = sorted(set(bases)) if bases == factors: factors = '== bases' else: factors = str(factors) return ' # %s stot = %s clear %s' % tuple( [str(x).replace('L', '') for x in (list(bases), tot, factors)])
def is_strong_lucas_prp(n): """Strong Lucas compositeness test with Selfridge parameters. Returns False if n is definitely composite, and True if n is a strong Lucas probable prime. This is often used in combination with the Miller-Rabin test, and in particular, when combined with M-R base 2 creates the strong BPSW test. References ========== - "Lucas Pseudoprimes", Baillie and Wagstaff, 1980. http://mpqs.free.fr/LucasPseudoprimes.pdf - OEIS A217255: Strong Lucas Pseudoprimes https://oeis.org/A217255 - https://en.wikipedia.org/wiki/Lucas_pseudoprime - https://en.wikipedia.org/wiki/Baillie-PSW_primality_test Examples ======== >>> from sympy.ntheory.primetest import isprime, is_strong_lucas_prp >>> for i in range(20000): ... if is_strong_lucas_prp(i) and not isprime(i): ... print(i) 5459 5777 10877 16109 18971 """ from sympy.ntheory.factor_ import trailing n = as_int(n) if n == 2: return True if n < 2 or (n % 2) == 0: return False if is_square(n, False): return False D, P, Q = _lucas_selfridge_params(n) if D == 0: return False # remove powers of 2 from n+1 (= k * 2**s) s = trailing(n + 1) k = (n + 1) >> s U, V, Qk = _lucas_sequence(n, P, Q, k) if U == 0 or V == 0: return True for r in range(1, s): V = (V * V - 2 * Qk) % n if V == 0: return True Qk = pow(Qk, 2, n) return False
def _test(n, base): from sympy.ntheory.factor_ import trailing n = int(n) if n < 2: return False s = trailing(n - 1) t = n >> s #Ферма b = pow(base, t, n) if b == 1 or b == n - 1: return True else: for j in range(1, s): b = (b**2) % n if b == n - 1: return True return False
def is_euler_pseudoprime(n, b): """Return True if n is prime or an Euler pseudoprime to base b, else False.""" from sympy.ntheory.factor_ import trailing if not mr(n, [b]): return False n = as_int(n) r = n - 1 c = pow(b, r >> trailing(r), n) if c == 1: return True while True: if c == n - 1: return True c = pow(c, 2, n) if c == 1: return False
def is_euler_pseudoprime(n, b): """Returns True if n is prime or an Euler pseudoprime to base b, else False. Euler Pseudoprime : In arithmetic, an odd composite integer n is called an euler pseudoprime to base a, if a and n are coprime and satisfy the modular arithmetic congruence relation : a ^ (n-1)/2 = + 1(mod n) or a ^ (n-1)/2 = - 1(mod n) (where mod refers to the modulo operation). Examples ======== >>> from sympy.ntheory.primetest import is_euler_pseudoprime >>> is_euler_pseudoprime(2, 5) True References ========== .. [1] https://en.wikipedia.org/wiki/Euler_pseudoprime """ from sympy.ntheory.factor_ import trailing if not mr(n, [b]): return False n = as_int(n) r = n - 1 c = pow(b, r >> trailing(r), n) if c == 1: return True while True: if c == n - 1: return True c = pow(c, 2, n) if c == 1: return False
def mr(n, bases): """Perform a Miller-Rabin strong pseudoprime test on n using a given list of bases/witnesses. References ========== - Richard Crandall & Carl Pomerance (2005), "Prime Numbers: A Computational Perspective", Springer, 2nd edition, 135-138 A list of thresholds and the bases they require are here: https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test#Deterministic_variants_of_the_test Examples ======== >>> from sympy.ntheory.primetest import mr >>> mr(1373651, [2, 3]) False >>> mr(479001599, [31, 73]) True """ from sympy.ntheory.factor_ import trailing from sympy.polys.domains import ZZ n = as_int(n) if n < 2: return False # remove powers of 2 from n-1 (= t * 2**s) s = trailing(n - 1) t = n >> s for base in bases: # Bases >= n are wrapped, bases < 2 are invalid if base >= n: base %= n if base >= 2: base = ZZ(base) if not _test(n, base, s, t): return False return True
def _test(n, base): """Miller-Rabin strong pseudoprime test for one base. Return False if n is definitely composite, True if n is probably prime, with a probability greater than 3/4. """ from sympy.ntheory.factor_ import trailing n = int(n) if n < 2: return False # remove powers of 2 from n (= t * 2**s) s = trailing(n - 1) t = n >> s # do the Fermat test b = pow(base, t, n) if b == 1 or b == n - 1: return True else: for j in xrange(1, s): b = (b**2) % n if b == n - 1: return True return False
def is_extra_strong_lucas_prp(n): """Extra Strong Lucas compositeness test. Returns False if n is definitely composite, and True if n is a "extra strong" Lucas probable prime. The parameters are selected using P = 3, Q = 1, then incrementing P until (D|n) == -1. The test itself is as defined in Grantham 2000, from the Mo and Jones preprint. The parameter selection and test are the same as used in OEIS A217719, Perl's Math::Prime::Util, and the Lucas pseudoprime page on Wikipedia. With these parameters, there are no counterexamples below 2^64 nor any known above that range. It is 20-50% faster than the strong test. Because of the different parameters selected, there is no relationship between the strong Lucas pseudoprimes and extra strong Lucas pseudoprimes. In particular, one is not a subset of the other. References ========== - "Frobenius Pseudoprimes", Jon Grantham, 2000. http://www.ams.org/journals/mcom/2001-70-234/S0025-5718-00-01197-2/ - OEIS A217719: Extra Strong Lucas Pseudoprimes https://oeis.org/A217719 - https://en.wikipedia.org/wiki/Lucas_pseudoprime Examples ======== >>> from sympy.ntheory.primetest import isprime, is_extra_strong_lucas_prp >>> for i in range(20000): ... if is_extra_strong_lucas_prp(i) and not isprime(i): ... print(i) 989 3239 5777 10877 """ # Implementation notes: # 1) the parameters differ from Thomas R. Nicely's. His parameter # selection leads to pseudoprimes that overlap M-R tests, and # contradict Baillie and Wagstaff's suggestion of (D|n) = -1. # 2) The MathWorld page as of June 2013 specifies Q=-1. The Lucas # sequence must have Q=1. See Grantham theorem 2.3, any of the # references on the MathWorld page, or run it and see Q=-1 is wrong. from sympy.ntheory.factor_ import trailing n = as_int(n) if n == 2: return True if n < 2 or (n % 2) == 0: return False if is_square(n, False): return False D, P, Q = _lucas_extrastrong_params(n) if D == 0: return False # remove powers of 2 from n+1 (= k * 2**s) s = trailing(n + 1) k = (n + 1) >> s U, V, Qk = _lucas_sequence(n, P, Q, k) if U == 0 and (V == 2 or V == n - 2): return True if V == 0: return True for r in range(1, s): V = (V * V - 2) % n if V == 0: return True return False
def is_extra_strong_lucas_prp(n): """Extra Strong Lucas compositeness test. Returns False if n is definitely composite, and True if n is a "extra strong" Lucas probable prime. The parameters are selected using P = 3, Q = 1, then incrementing P until (D|n) == -1. The test itself is as defined in Grantham 2000, from the Mo and Jones preprint. The parameter selection and test are the same as used in OEIS A217719, Perl's Math::Prime::Util, and the Lucas pseudoprime page on Wikipedia. With these parameters, there are no counterexamples below 2^64 nor any known above that range. It is 20-50% faster than the strong test. Because of the different parameters selected, there is no relationship between the strong Lucas pseudoprimes and extra strong Lucas pseudoprimes. In particular, one is not a subset of the other. References ========== - "Frobenius Pseudoprimes", Jon Grantham, 2000. http://www.ams.org/journals/mcom/2001-70-234/S0025-5718-00-01197-2/ - OEIS A217719: Extra Strong Lucas Pseudoprimes https://oeis.org/A217719 - https://en.wikipedia.org/wiki/Lucas_pseudoprime Examples ======== >>> from sympy.ntheory.primetest import isprime, is_extra_strong_lucas_prp >>> for i in range(20000): ... if is_extra_strong_lucas_prp(i) and not isprime(i): ... print(i) 989 3239 5777 10877 """ # Implementation notes: # 1) the parameters differ from Thomas R. Nicely's. His parameter # selection leads to pseudoprimes that overlap M-R tests, and # contradict Baillie and Wagstaff's suggestion of (D|n) = -1. # 2) The MathWorld page as of June 2013 specifies Q=-1. The Lucas # sequence must have Q=1. See Grantham theorem 2.3, any of the # references on the MathWorld page, or run it and see Q=-1 is wrong. from sympy.ntheory.factor_ import trailing n = as_int(n) if n == 2: return True if n < 2 or (n % 2) == 0: return False if is_square(n, False): return False D, P, Q = _lucas_extrastrong_params(n) if D == 0: return False # remove powers of 2 from n+1 (= k * 2**s) s = trailing(n + 1) k = (n+1) >> s U, V, Qk = _lucas_sequence(n, P, Q, k) if U == 0 and (V == 2 or V == n - 2): return True if V == 0: return True for r in range(1, s): V = (V*V - 2) % n if V == 0: return True return False