Beispiel #1
0
 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))
Beispiel #2
0
 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))
Beispiel #3
0
 def sympit(w):
     return map(sympify, iff(isinstance(w, (list, tuple, set)), w, [w]))
Beispiel #4
0
 def sympit(w):
     return map(sympify, iff(isinstance(w, (list, tuple, set)), w, [w]))
Beispiel #5
0
 def sympified_list(w):
     return map(sympify, iff(iterable(w), w, [w]))
Beispiel #6
0
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
Beispiel #7
0
 def sympified_list(w):
     return map(sympify, iff(iterable(w), w, [w]))
Beispiel #8
0
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