def eval(cls, arg): if arg is S.NaN: return S.NaN if arg is S.Zero: return S.Zero if arg.is_positive: return S.One if arg.is_negative: return S.NegativeOne if arg.is_Function: if arg.func is sign: return arg if arg.is_Mul: c, args = arg.as_coeff_terms() unk = [] is_neg = c.is_negative for ai in args: if ai.is_negative == None: unk.append(ai) elif ai.is_negative: is_neg = not is_neg if c is S.One and len(unk) == len(args): return None return iff(is_neg, S.NegativeOne, S.One) * cls(C.Mul(*unk))
def eval(cls, arg): if arg is S.NaN: return S.NaN if arg is S.Zero: return S.Zero if arg.is_positive: return S.One if arg.is_negative: return S.NegativeOne if arg.is_Function: if arg.func is sign: return arg if arg.is_Mul: c, args = arg.as_coeff_mul() unk = [] is_neg = c.is_negative for ai in args: if ai.is_negative is None: unk.append(ai) elif ai.is_negative: is_neg = not is_neg if c is S.One and len(unk) == len(args): return None return iff(is_neg, S.NegativeOne, S.One) * cls(arg._new_rawargs(*unk))
def sympit(w): return map(sympify, iff(isinstance(w, (list, tuple, set)), w, [w]))
def sympified_list(w): return map(sympify, iff(iterable(w), w, [w]))
def factorint(n, limit=None, use_trial=True, use_rho=True, use_pm1=True, verbose=False): """ Given a positive integer ``n``, ``factorint(n)`` returns a dict containing the prime factors of ``n`` as keys and their respective multiplicities as values. For example: >>> from sympy.ntheory import factorint >>> factorint(2000) # 2000 = (2**4) * (5**3) {2: 4, 5: 3} >>> factorint(65537) # This number is prime {65537: 1} For input less than 2, factorint behaves as follows: - ``factorint(1)`` returns the empty factorization, ``{}`` - ``factorint(0)`` returns ``{0:1}`` - ``factorint(-n)`` adds ``-1:1`` to the factors and then factors ``n`` Algorithm ========= The function switches between multiple algorithms. Trial division quickly finds small factors (of the order 1-5 digits), and finds all large factors if given enough time. The Pollard rho and p-1 algorithms are used to find large factors ahead of time; they will often find factors of the order of 10 digits within a few seconds: >>> factors = factorint(12345678910111213141516) >>> for base, exp in sorted(factors.items()): ... print base, exp ... 2 2 2507191691 1 1231026625769 1 Any of these methods can optionally be disabled with the following boolean parameters: - ``use_trial``: Toggle use of trial division - ``use_rho``: Toggle use of Pollard's rho method - ``use_pm1``: Toggle use of Pollard's p-1 method ``factorint`` also periodically checks if the remaining part is a prime number or a perfect power, and in those cases stops. Partial factorization ===================== If ``limit`` is specified, the search is stopped after performing trial division up to (but not including) the limit (or taking a corresponding number of rho/p-1 steps). This is useful if one has a large number and only is interested in finding small factors (if any). Note that setting a limit does not prevent larger factors from being found early; it simply means that any larger factors returned may be composite. This number, for example, has two small factors and a huge semi-prime factor that cannot be reduced easily: >>> from sympy.ntheory import isprime >>> a = 1407633717262338957430697921446883 >>> f = factorint(a, limit=10000) >>> f == {991: 1, 202916782076162456022877024859L: 1, 7: 1} True >>> isprime(max(f)) False Miscellaneous options ===================== If ``verbose`` is set to ``True``, detailed progress is printed. """ assert use_trial or use_rho or use_pm1 n = int(n) if not n: return {0:1} if n < 0: n = -n factors = {-1:1} else: factors = {} # Power of two t = trailing(n) if t: factors[2] = t n >>= t if n == 1: return factors low, high = 3, 250 # It is sufficient to perform trial division up to sqrt(n) try: limit = iff(limit, lambda: max(limit, low), lambda: int(n**0.5) + 2) except OverflowError: limit = 1e1000 # Setting to True here forces _check_termination if first round of # trial division fails found_trial_previous = True if verbose and n < 1e300: print "Factoring", n while 1: try: high_ = min(high, limit) # Trial division if use_trial: if verbose: print trial_msg % (low, high_) ps = sieve.primerange(low, high_) n, found_trial = _trial(factors, n, ps, verbose) else: found_trial = False if high > limit: factors[n] = 1 raise StopIteration # Only used advanced (and more expensive) methods as long as # trial division fails to locate small factors if not found_trial: if found_trial_previous: _check_termination(factors, n, verbose) # Pollard p-1 if use_pm1 and not found_trial: B = int(high_**0.7) if verbose: print (pm1_msg % (high_, high_)) ps = factorint(pollard_pm1(n, B=high_, seed=high_) or 1, \ limit=limit, verbose=verbose) n, found_pm1 = _trial(factors, n, ps, verbose) if found_pm1: _check_termination(factors, n, verbose) # Pollard rho if use_rho and not found_trial: max_steps = int(high_**0.7) if verbose: print (rho_msg % (1, max_steps, high_)) ps = factorint(pollard_rho(n, retries=1, max_steps=max_steps, \ seed=high_) or 1, limit=limit, verbose=verbose) n, found_rho = _trial(factors, n, ps, verbose) if found_rho: _check_termination(factors, n, verbose) except StopIteration: return factors found_trial_previous = found_trial low, high = high, high*2
def factorint(n, limit=None, use_trial=True, use_rho=True, use_pm1=True, verbose=False, visual=False): """ Given a positive integer ``n``, ``factorint(n)`` returns a dict containing the prime factors of ``n`` as keys and their respective multiplicities as values. For example: >>> from sympy.ntheory import factorint >>> factorint(2000) # 2000 = (2**4) * (5**3) {2: 4, 5: 3} >>> factorint(65537) # This number is prime {65537: 1} For input less than 2, factorint behaves as follows: - ``factorint(1)`` returns the empty factorization, ``{}`` - ``factorint(0)`` returns ``{0:1}`` - ``factorint(-n)`` adds ``-1:1`` to the factors and then factors ``n`` Algorithm ========= The function switches between multiple algorithms. Trial division quickly finds small factors (of the order 1-5 digits), and finds all large factors if given enough time. The Pollard rho and p-1 algorithms are used to find large factors ahead of time; they will often find factors of the order of 10 digits within a few seconds: >>> factors = factorint(12345678910111213141516) >>> for base, exp in sorted(factors.items()): ... print base, exp ... 2 2 2507191691 1 1231026625769 1 Any of these methods can optionally be disabled with the following boolean parameters: - ``use_trial``: Toggle use of trial division - ``use_rho``: Toggle use of Pollard's rho method - ``use_pm1``: Toggle use of Pollard's p-1 method ``factorint`` also periodically checks if the remaining part is a prime number or a perfect power, and in those cases stops. Partial Factorization ===================== If ``limit`` (> 2) is specified, the search is stopped after performing trial division up to (and including) the limit (or taking a corresponding number of rho/p-1 steps). This is useful if one has a large number and only is interested in finding small factors (if any). Note that setting a limit does not prevent larger factors from being found early; it simply means that the largest factor may be composite. This number, for example, has two small factors and a huge semi-prime factor that cannot be reduced easily: >>> from sympy.ntheory import isprime >>> a = 1407633717262338957430697921446883 >>> f = factorint(a, limit=10000) >>> f == {991: 1, 202916782076162456022877024859L: 1, 7: 1} True >>> isprime(max(f)) False Visual Factorization ==================== If ``visual`` is set to ``True``, then it will return a visual factorization of the integer. For example: >>> from sympy import pprint >>> pprint(factorint(4200, visual=True)) 3 1 2 1 2 *3 *5 *7 Note that this is achieved by using the evaluate=False flag in Mul and Pow. If you do other manipulations with an expression where evaluate=False, it may evaluate. Therefore, you should use the visual option only for visualization, and use the normal dictionary returned by visual=False if you want to perform operations on the factors. If you find that you want one from the other but you do not want to run expensive factorint again, you can easily switch between the two forms using the following list comprehensions: >>> from sympy import Mul, Pow >>> regular = factorint(1764); regular {2: 2, 3: 2, 7: 2} >>> pprint(Mul(*[Pow(*i, **{'evaluate':False}) for i in regular.items()], ... **{'evaluate':False})) 2 2 2 2 *3 *7 >>> visual = factorint(1764, visual=True); pprint(visual) 2 2 2 2 *3 *7 >>> dict([i.args for i in visual.args]) {2: 2, 3: 2, 7: 2} Miscellaneous Options ===================== If ``verbose`` is set to ``True``, detailed progress is printed. """ if visual: factordict = factorint(n, limit=limit, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose, visual=False) if factordict == {}: return S.One return Mul( *[Pow(*i, **{'evaluate': False}) for i in factordict.items()], **{'evaluate': False}) assert use_trial or use_rho or use_pm1 n = int(n) if not n: return {0: 1} if n < 0: n = -n factors = {-1: 1} else: factors = {} # Power of two t = trailing(n) if t: factors[2] = t n >>= t if n == 1: return factors low, high = 3, 250 # It is sufficient to perform trial division up to sqrt(n) try: # add 1 to sqrt in case there is round off; add 1 overall to make # sure that the limit is included limit = iff(limit, lambda: max(limit, low), lambda: int(n**0.5) + 1) + 1 except OverflowError: limit = 1e1000 # Setting to True here forces _check_termination if first round of # trial division fails found_trial_previous = True if verbose and n < 1e300: print "Factoring", n while 1: try: high_ = min(high, limit) # Trial division if use_trial: if verbose: print trial_msg % (low, high_) ps = sieve.primerange(low, high_) n, found_trial = _trial(factors, n, ps, verbose) else: found_trial = False if high > limit: factors[n] = 1 raise StopIteration # Only used advanced (and more expensive) methods as long as # trial division fails to locate small factors if not found_trial: if found_trial_previous: _check_termination(factors, n, verbose) # Pollard p-1 if use_pm1 and not found_trial: B = int(high_**0.7) if verbose: print(pm1_msg % (high_, high_)) ps = factorint(pollard_pm1(n, B=high_, seed=high_) or 1, \ limit=limit-1, verbose=verbose) n, found_pm1 = _trial(factors, n, ps, verbose) if found_pm1: _check_termination(factors, n, verbose) # Pollard rho if use_rho and not found_trial: max_steps = int(high_**0.7) if verbose: print(rho_msg % (1, max_steps, high_)) ps = factorint(pollard_rho(n, retries=1, max_steps=max_steps, \ seed=high_) or 1, limit=limit-1, verbose=verbose) n, found_rho = _trial(factors, n, ps, verbose) if found_rho: _check_termination(factors, n, verbose) except StopIteration: return factors found_trial_previous = found_trial low, high = high, high * 2