コード例 #1
0
def core(n, t=2):
    """Calculate core(n,t) = `core_t(n)` of a positive integer n.

    ``core_2(n)`` is equal to the squarefree part of n

    If n's prime factorization is:

    .. math ::
        n = \prod_{i=1}^\omega p_i^{m_i},

    then

    .. math ::
        core_t(n) = \prod_{i=1}^\omega p_i^{m_i \mod t}.

    Parameters
    ==========

    t : core(n,t) calculates the t-th power free part of n

        ``core(n, 2)`` is the squarefree part of ``n``
        ``core(n, 3)`` is the cubefree part of ``n``

        Default for t is 2.

    References
    ==========

    .. [1] http://en.wikipedia.org/wiki/Square-free_integer#Squarefree_core

    Examples
    ========

    >>> from diofant.ntheory.factor_ import core
    >>> core(24, 2)
    6
    >>> core(9424, 3)
    1178
    >>> core(379238)
    379238
    >>> core(15**11, 10)
    15

    See Also
    ========

    factorint
    """

    n = as_int(n)
    t = as_int(t)
    if n <= 0:
        raise ValueError("n must be a positive integer")
    elif t <= 1:
        raise ValueError("t must be >= 2")
    else:
        y = 1
        for p, e in factorint(n).items():
            y *= p**(e % t)
        return y
コード例 #2
0
    def __new__(cls, partition, integer=None):
        """
        Generates a new IntegerPartition object from a list or dictionary.

        The partition can be given as a list of positive integers or a
        dictionary of (integer, multiplicity) items. If the partition is
        preceeded by an integer an error will be raised if the partition
        does not sum to that given integer.

        Examples
        ========

        >>> from diofant.combinatorics.partitions import IntegerPartition
        >>> a = IntegerPartition([5, 4, 3, 1, 1])
        >>> a
        IntegerPartition(14, (5, 4, 3, 1, 1))
        >>> print(a)
        [5, 4, 3, 1, 1]
        >>> IntegerPartition({1:3, 2:1})
        IntegerPartition(5, (2, 1, 1, 1))

        If the value that the partion should sum to is given first, a check
        will be made to see n error will be raised if there is a discrepancy:

        >>> IntegerPartition(10, [5, 4, 3, 1])
        Traceback (most recent call last):
        ...
        ValueError: The partition is not valid

        """
        if integer is not None:
            integer, partition = partition, integer
        if isinstance(partition, (dict, Dict)):
            _ = []
            for k, v in sorted(partition.items(), reverse=True):
                if not v:
                    continue
                k, v = as_int(k), as_int(v)
                _.extend([k]*v)
            partition = tuple(_)
        else:
            partition = tuple(sorted(map(as_int, partition), reverse=True))
        sum_ok = False
        if integer is None:
            integer = sum(partition)
            sum_ok = True
        else:
            integer = as_int(integer)

        if not sum_ok and sum(partition) != integer:
            raise ValueError("Partition did not add to %s" % integer)
        if any(i < 1 for i in partition):
            raise ValueError("The summands must all be positive.")

        obj = Basic.__new__(cls, integer, partition)
        obj.partition = list(partition)
        obj.integer = integer
        return obj
コード例 #3
0
 def give(a, b, seq=seed):
     a, b = as_int(a), as_int(b)
     w = b - a
     if w < 0:
         raise ValueError('_randint got empty range')
     try:
         x = seq.pop()
     except AttributeError:
         raise ValueError('_randint expects a list-like sequence')
     except IndexError:
         raise ValueError('_randint sequence was too short')
     if a <= x <= b:
         return x
     else:
         return give(a, b, seq)
コード例 #4
0
    def __init__(self, *args):

        if len(args) == 1 and isinstance(args[0], SparseMatrix):
            self.rows = args[0].rows
            self.cols = args[0].cols
            self._smat = dict(args[0]._smat)
            return

        self._smat = {}

        if len(args) == 3:
            self.rows = as_int(args[0])
            self.cols = as_int(args[1])

            if isinstance(args[2], collections.Callable):
                op = args[2]
                for i in range(self.rows):
                    for j in range(self.cols):
                        value = self._sympify(
                            op(self._sympify(i), self._sympify(j)))
                        if value:
                            self._smat[(i, j)] = value
            elif isinstance(args[2], (dict, Dict)):
                # manual copy, copy.deepcopy() doesn't work
                for key in args[2].keys():
                    v = args[2][key]
                    if v:
                        self._smat[key] = self._sympify(v)
            elif is_sequence(args[2]):
                if len(args[2]) != self.rows * self.cols:
                    raise ValueError('List length (%s) != rows*columns (%s)' %
                                     (len(args[2]), self.rows * self.cols))
                flat_list = args[2]
                for i in range(self.rows):
                    for j in range(self.cols):
                        value = self._sympify(flat_list[i * self.cols + j])
                        if value:
                            self._smat[(i, j)] = value
        else:
            # handle full matrix forms with _handle_creation_inputs
            r, c, _list = Matrix._handle_creation_inputs(*args)
            self.rows = r
            self.cols = c
            for i in range(self.rows):
                for j in range(self.cols):
                    value = _list[self.cols * i + j]
                    if value:
                        self._smat[(i, j)] = value
コード例 #5
0
 def dict(self):
     n, p, succ, fail = self.n, self.p, self.succ, self.fail
     n = as_int(n)
     return {
         k * succ + (n - k) * fail: binomial(n, k) * p**k * (1 - p)**(n - k)
         for k in range(0, n + 1)
     }
コード例 #6
0
def prime(nth):
    """Return the nth prime, with the primes indexed as prime(1) = 2,
    prime(2) = 3, etc.... The nth prime is approximately n*log(n) and
    can never be larger than 2**n.

    References
    ==========

    .. [1] http://primes.utm.edu/glossary/xpage/BertrandsPostulate.html

    Examples
    ========

    >>> from diofant import prime
    >>> prime(10)
    29
    >>> prime(1)
    2

    See Also
    ========

    diofant.ntheory.primetest.isprime : Test if n is prime
    primerange : Generate all primes in a given range
    primepi : Return the number of primes less than or equal to n
    """
    n = as_int(nth)
    if n < 1:
        raise ValueError("nth must be a positive integer; prime(1) == 2")
    return sieve[n]
コード例 #7
0
def antidivisor_count(n):
    """Return the number of antidivisors [1]_ of ``n``.

    References
    ==========

    .. [1] formula from https://oeis.org/A066272

    Examples
    ========

    >>> from diofant.ntheory.factor_ import antidivisor_count
    >>> antidivisor_count(13)
    4
    >>> antidivisor_count(27)
    5

    See Also
    ========

    factorint, divisors, antidivisors, divisor_count, totient
    """

    n = as_int(abs(n))
    if n <= 2:
        return 0
    return divisor_count(2*n-1) + divisor_count(2*n+1) + \
        divisor_count(n) - divisor_count(n, 2) - 5
コード例 #8
0
def antidivisors(n, generator=False):
    r"""Return all antidivisors of n sorted from 1..n by default.

    Antidivisors [1]_ of n are numbers that do not divide n by the largest
    possible margin.  If generator is True an unordered generator is returned.

    References
    ==========

    .. [1] definition is described in http://oeis.org/A066272/a066272a.html

    Examples
    ========

    >>> from diofant.ntheory.factor_ import antidivisors
    >>> antidivisors(24)
    [7, 16]

    >>> sorted(antidivisors(128, generator=True))
    [3, 5, 15, 17, 51, 85]

    See Also
    ========

    primefactors, factorint, divisors, divisor_count, antidivisor_count
    """

    n = as_int(abs(n))
    if n <= 2:
        return []
    rv = _antidivisors(n)
    if not generator:
        return sorted(rv)
    return rv
コード例 #9
0
def primorial(n, nth=True):
    """Returns the product of the first n primes (default) or
    the primes less than or equal to n (when ``nth=False``).

    >>> from diofant.ntheory.generate import primorial, randprime, primerange
    >>> from diofant import factorint, Mul, primefactors, sqrt
    >>> primorial(4) # the first 4 primes are 2, 3, 5, 7
    210
    >>> primorial(4, nth=False) # primes <= 4 are 2 and 3
    6
    >>> primorial(1)
    2
    >>> primorial(1, nth=False)
    1
    >>> primorial(sqrt(101), nth=False)
    210

    One can argue that the primes are infinite since if you take
    a set of primes and multiply them together (e.g. the primorial) and
    then add or subtract 1, the result cannot be divided by any of the
    original factors, hence either 1 or more new primes must divide this
    product of primes.

    In this case, the number itself is a new prime:

    >>> factorint(primorial(4) + 1)
    {211: 1}

    In this case two new primes are the factors:

    >>> factorint(primorial(4) - 1) == {11: 1, 19: 1}
    True

    Here, some primes smaller and larger than the primes multiplied together
    are obtained:

    >>> p = list(primerange(10, 20))
    >>> sorted(set(primefactors(Mul(*p) + 1)).difference(set(p)))
    [2, 5, 31, 149]

    See Also
    ========

    primerange : Generate all primes in a given range
    """
    if nth:
        n = as_int(n)
    else:
        n = int(n)
    if n < 1:
        raise ValueError("primorial argument must be >= 1")
    p = 1
    if nth:
        for i in range(1, n + 1):
            p *= prime(i)
    else:
        for i in primerange(2, n + 1):
            p *= i
    return p
コード例 #10
0
def nextprime(n, ith=1):
    """Return the ith prime greater than n.

    i must be an integer.

    Notes
    =====

    Potential primes are located at 6*j +/- 1. This
    property is used during searching.

    >>> from diofant import nextprime
    >>> [(i, nextprime(i)) for i in range(10, 15)]
    [(10, 11), (11, 13), (12, 13), (13, 17), (14, 17)]
    >>> nextprime(2, ith=2)  # the 2nd prime after 2
    5

    See Also
    ========

    prevprime : Return the largest prime smaller than n
    primerange : Generate all primes in a given range
    """
    n = int(n)
    i = as_int(ith)
    if i > 1:
        pr = n
        j = 1
        while 1:
            pr = nextprime(pr)
            j += 1
            if j > i:
                break
        return pr

    if n < 2:
        return 2
    if n < 7:
        return {2: 3, 3: 5, 4: 5, 5: 7, 6: 7}[n]
    nn = 6 * (n // 6)
    if nn == n:
        n += 1
        if isprime(n):
            return n
        n += 4
    elif n - nn == 5:
        n += 2
        if isprime(n):
            return n
        n += 4
    else:
        n = nn + 5
    while 1:
        if isprime(n):
            return n
        n += 2
        if isprime(n):
            return n
        n += 4
コード例 #11
0
    def unrank(cls, rank, n):
        """Finds the unranked Prufer sequence.

        Examples
        ========

        >>> from diofant.combinatorics.prufer import Prufer
        >>> Prufer.unrank(0, 4)
        Prufer([0, 0])

        """
        n, rank = as_int(n), as_int(rank)
        L = defaultdict(int)
        for i in range(n - 3, -1, -1):
            L[i] = rank % n
            rank = (rank - L[i]) // n
        return Prufer([L[i] for i in range(len(L))])
コード例 #12
0
 def give(a, b=None, seq=seed):
     if b is None:
         a, b = 0, a
     a, b = as_int(a), as_int(b)
     w = b - a
     if w < 1:
         raise ValueError('_randrange got empty range')
     try:
         x = seq.pop()
     except AttributeError:
         raise ValueError('_randrange expects a list-like sequence')
     except IndexError:
         raise ValueError('_randrange sequence was too short')
     if a <= x < b:
         return x
     else:
         return give(a, b, seq)
コード例 #13
0
def ones(r, c=None):
    """Returns a matrix of ones with ``r`` rows and ``c`` columns;
    if ``c`` is omitted a square matrix will be returned.

    See Also
    ========

    diofant.matrices.dense.zeros
    diofant.matrices.dense.eye
    diofant.matrices.dense.diag
    """
    from .dense import Matrix

    c = r if c is None else c
    r = as_int(r)
    c = as_int(c)
    return Matrix(r, c, [S.One] * r * c)
コード例 #14
0
 def __getitem__(self, n):
     """Return the nth prime number"""
     if isinstance(n, slice):
         self.extend_to_no(n.stop)
         return self._list[n.start - 1:n.stop - 1:n.step]
     else:
         n = as_int(n)
         self.extend_to_no(n)
         return self._list[n - 1]
コード例 #15
0
 def __contains__(self, n):
     try:
         n = as_int(n)
         assert n >= 2
     except (ValueError, AssertionError):
         return False
     if n % 2 == 0:
         return n == 2
     a, b = self.search(n)
     return a == b
コード例 #16
0
ファイル: test_compatibility.py プロジェクト: cbm755/diofant
def test_as_int():
    pytest.raises(ValueError, lambda: as_int(1.1))
    pytest.raises(ValueError, lambda: as_int([]))
    pytest.raises(ValueError, lambda: as_int(nan))
    pytest.raises(ValueError, lambda: as_int(oo))
    pytest.raises(ValueError, lambda: as_int(-oo))
    pytest.raises(ValueError, lambda: as_int(zoo))
コード例 #17
0
def test_as_int():
    pytest.raises(ValueError, lambda: as_int(1.1))
    pytest.raises(ValueError, lambda: as_int([]))
    pytest.raises(ValueError, lambda: as_int(S.NaN))
    pytest.raises(ValueError, lambda: as_int(S.Infinity))
    pytest.raises(ValueError, lambda: as_int(S.NegativeInfinity))
    pytest.raises(ValueError, lambda: as_int(S.ComplexInfinity))
コード例 #18
0
def test_as_int():
    pytest.raises(ValueError, lambda: as_int(1.1))
    pytest.raises(ValueError, lambda: as_int([]))
    pytest.raises(ValueError, lambda: as_int(nan))
    pytest.raises(ValueError, lambda: as_int(oo))
    pytest.raises(ValueError, lambda: as_int(-oo))
    pytest.raises(ValueError, lambda: as_int(zoo))
コード例 #19
0
def rs_pow(p1, n, x, prec):
    """
    return ``p1**n`` modulo ``O(x**prec)``

    Examples
    ========

    >>> from diofant.polys.domains import QQ
    >>> from diofant.polys.rings import ring

    >>> R, x = ring('x', QQ)
    >>> p = x + 1
    >>> rs_pow(p, 4, x, 3)
    6*x**2 + 4*x + 1
    """
    R = p1.ring
    p = R.zero
    if isinstance(n, Rational):
        raise NotImplementedError('to be implemented')

    n = as_int(n)
    if n == 0:
        if p1:
            return R(1)
        else:
            raise ValueError('0**0 is undefined')
    if n < 0:
        p1 = rs_pow(p1, -n, x, prec)
        return rs_series_inversion(p1, x, prec)
    if n == 1:
        return rs_trunc(p1, x, prec)
    if n == 2:
        return rs_square(p1, x, prec)
    if n == 3:
        p2 = rs_square(p1, x, prec)
        return rs_mul(p1, p2, x, prec)
    p = R(1)
    while 1:
        if n & 1:
            p = rs_mul(p1, p, x, prec)
            n -= 1
            if not n:
                break
        p1 = rs_square(p1, x, prec)
        n = n // 2
    return p
コード例 #20
0
def divisors(n, generator=False):
    r"""Return all divisors of n.

    Divisors are sorted from 1..n by default.  If generator is True an
    unordered generator is returned.

    The number of divisors of n can be quite large if there are many
    prime factors (counting repeated factors). If only the number of
    factors is desired use divisor_count(n).

    Examples
    ========

    >>> from diofant import divisors, divisor_count
    >>> divisors(24)
    [1, 2, 3, 4, 6, 8, 12, 24]
    >>> divisor_count(24)
    8

    >>> list(divisors(120, generator=True))
    [1, 2, 4, 8, 3, 6, 12, 24, 5, 10, 20, 40, 15, 30, 60, 120]

    See Also
    ========

    primefactors, factorint, divisor_count

    References
    ==========

    .. [1] http://stackoverflow.com/questions/1010381/python-factorization
    """

    n = as_int(abs(n))
    if isprime(n):
        return [1, n]
    if n == 1:
        return [1]
    if n == 0:
        return []
    rv = _divisors(n)
    if not generator:
        return sorted(rv)
    return rv
コード例 #21
0
    def extend_to_no(self, i):
        """Extend to include the ith prime number.

        i must be an integer.

        The list is extended by 50% if it is too short, so it is
        likely that it will be longer than requested.

        Examples
        ========

        >>> from diofant import sieve
        >>> from array import array # this line and next for doctest only
        >>> sieve._list = array('l', [2, 3, 5, 7, 11, 13])

        >>> sieve.extend_to_no(9)
        >>> sieve._list
        array('l', [2, 3, 5, 7, 11, 13, 17, 19, 23])
        """
        i = as_int(i)
        while len(self._list) < i:
            self.extend(int(self._list[-1] * 1.5))
コード例 #22
0
def jordan_cell(eigenval, n):
    """
    Create matrix of Jordan cell kind:

    Examples
    ========

    >>> from diofant.matrices import jordan_cell
    >>> from diofant.abc import x
    >>> jordan_cell(x, 4)
    Matrix([
    [x, 1, 0, 0],
    [0, x, 1, 0],
    [0, 0, x, 1],
    [0, 0, 0, x]])
    """
    n = as_int(n)
    out = zeros(n)
    for i in range(n - 1):
        out[i, i] = eigenval
        out[i, i + 1] = S.One
    out[n - 1, n - 1] = eigenval
    return out
コード例 #23
0
    def __add__(self, other):
        """
        Return permutation whose rank is ``other`` greater than current rank,
        (mod the maximum rank for the set).

        Examples
        ========

        >>> from diofant.combinatorics.partitions import Partition
        >>> a = Partition([1, 2], [3])
        >>> a.rank
        1
        >>> (a + 1).rank
        2
        >>> (a + 100).rank
        1
        """
        other = as_int(other)
        offset = self.rank + other
        result = RGS_unrank((offset) %
                            RGS_enum(self.size),
                            self.size)
        return Partition.from_rgs(result, self.members)
コード例 #24
0
def random_integer_partition(n, seed=None):
    """
    Generates a random integer partition summing to ``n`` as a list
    of reverse-sorted integers.

    Examples
    ========

    >>> from diofant.combinatorics.partitions import random_integer_partition

    For the following, a seed is given so a known value can be shown; in
    practice, the seed would not be given.

    >>> random_integer_partition(100, seed=[1, 1, 12, 1, 2, 1, 85, 1])
    [85, 12, 2, 1]
    >>> random_integer_partition(10, seed=[1, 2, 3, 1, 5, 1])
    [5, 3, 1, 1]
    >>> random_integer_partition(1)
    [1]
    """
    from diofant.utilities.randtest import _randint

    n = as_int(n)
    if n < 1:
        raise ValueError('n must be a positive integer')

    randint = _randint(seed)

    partition = []
    while (n > 0):
        k = randint(1, n)
        mult = randint(1, n//k)
        partition.append((k, mult))
        n -= k*mult
    partition.sort(reverse=True)
    partition = flatten([[k]*m for k, m in partition])
    return partition
コード例 #25
0
    def __new__(cls, *args):
        from diofant.functions.elementary.integers import ceiling
        # expand range
        slc = slice(*args)
        start, stop, step = slc.start or 0, slc.stop, slc.step or 1
        try:
            start, stop, step = [
                w if w in [S.NegativeInfinity, S.Infinity] else Integer(
                    as_int(w)) for w in (start, stop, step)
            ]
        except ValueError:
            raise ValueError("Inputs to Range must be Integer Valued\n" +
                             "Use ImageSets of Ranges for other cases")

        if not step.is_finite:
            raise ValueError("Infinite step is not allowed")
        if start == stop:
            return S.EmptySet

        n = ceiling((stop - start) / step)
        if n <= 0:
            return S.EmptySet

        # normalize args: regardless of how they are entered they will show
        # canonically as Range(inf, sup, step) with step > 0
        if n.is_finite:
            start, stop = sorted((start, start + (n - 1) * step))
        else:
            start, stop = sorted((start, stop - step))

        step = abs(step)
        if (start, stop) == (S.NegativeInfinity, S.Infinity):
            raise ValueError("Both the start and end value of "
                             "Range cannot be unbounded")
        else:
            return Basic.__new__(cls, start, stop + step, step)
コード例 #26
0
 def zeros(cls, r, c=None):
     """Return an r x c matrix of zeros, square if c is omitted."""
     c = r if c is None else c
     r = as_int(r)
     c = as_int(c)
     return cls._new(r, c, [cls._sympify(0)] * r * c)
コード例 #27
0
 def dict(self):
     sides = as_int(self.sides)
     return super(DieDistribution, self).dict
コード例 #28
0
def nsimplify(expr, constants=[], tolerance=None, full=False, rational=None):
    """
    Find a simple representation for a number or, if there are free symbols or
    if rational=True, then replace Floats with their Rational equivalents. If
    no change is made and rational is not False then Floats will at least be
    converted to Rationals.

    For numerical expressions, a simple formula that numerically matches the
    given numerical expression is sought (and the input should be possible
    to evalf to a precision of at least 30 digits).

    Optionally, a list of (rationally independent) constants to
    include in the formula may be given.

    A lower tolerance may be set to find less exact matches. If no tolerance
    is given then the least precise value will set the tolerance (e.g. Floats
    default to 15 digits of precision, so would be tolerance=10**-15).

    With full=True, a more extensive search is performed
    (this is useful to find simpler numbers when the tolerance
    is set low).

    Examples
    ========

    >>> from diofant import nsimplify, sqrt, GoldenRatio, exp, I, exp, pi
    >>> nsimplify(4/(1+sqrt(5)), [GoldenRatio])
    -2 + 2*GoldenRatio
    >>> nsimplify((1/(exp(3*pi*I/5)+1)))
    1/2 - I*sqrt(sqrt(5)/10 + 1/4)
    >>> nsimplify(I**I, [pi])
    E**(-pi/2)
    >>> nsimplify(pi, tolerance=0.01)
    22/7

    See Also
    ========
    diofant.core.function.nfloat

    """
    try:
        return sympify(as_int(expr))
    except (TypeError, ValueError):
        pass
    expr = sympify(expr)
    if rational or expr.free_symbols:
        return _real_to_rational(expr, tolerance)

    # Diofant's default tolerance for Rationals is 15; other numbers may have
    # lower tolerances set, so use them to pick the largest tolerance if None
    # was given
    if tolerance is None:
        tolerance = 10**-min([15] + [
            mpmath.libmp.libmpf.prec_to_dps(n._prec) for n in expr.atoms(Float)
        ])
    # XXX should prec be set independent of tolerance or should it be computed
    # from tolerance?
    prec = 30
    bprec = int(prec * 3.33)

    constants_dict = {}
    for constant in constants:
        constant = sympify(constant)
        v = constant.evalf(prec)
        if not v.is_Float:
            raise ValueError("constants must be real-valued")
        constants_dict[str(constant)] = v._to_mpmath(bprec)

    exprval = expr.evalf(prec, chop=True)
    re, im = exprval.as_real_imag()

    # safety check to make sure that this evaluated to a number
    if not (re.is_Number and im.is_Number):
        return expr

    def nsimplify_real(x):
        orig = mpmath.mp.dps
        xv = x._to_mpmath(bprec)
        try:
            # We'll be happy with low precision if a simple fraction
            if not (tolerance or full):
                mpmath.mp.dps = 15
                rat = mpmath.findpoly(xv, 1)
                if rat is not None:
                    return Rational(-int(rat[1]), int(rat[0]))
            mpmath.mp.dps = prec
            newexpr = mpmath.identify(xv,
                                      constants=constants_dict,
                                      tol=tolerance,
                                      full=full)
            if not newexpr:
                raise ValueError
            if full:
                newexpr = newexpr[0]
            expr = sympify(newexpr)
            if x and not expr:  # don't let x become 0
                raise ValueError
            if expr.is_finite is False and xv not in [mpmath.inf, mpmath.ninf]:
                raise ValueError
            return expr
        finally:
            # even though there are returns above, this is executed
            # before leaving
            mpmath.mp.dps = orig

    try:
        if re:
            re = nsimplify_real(re)
        if im:
            im = nsimplify_real(im)
    except ValueError:
        if rational is None:
            return _real_to_rational(expr)
        return expr

    rv = re + im * S.ImaginaryUnit
    # if there was a change or rational is explicitly not wanted
    # return the value, else return the Rational representation
    if rv != expr or rational is False:
        return rv
    return _real_to_rational(expr)
コード例 #29
0
def factorint(n,
              limit=None,
              use_trial=True,
              use_rho=True,
              use_pm1=True,
              verbose=False,
              visual=None):
    r"""
    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 diofant.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``

    Partial Factorization:

    If ``limit`` (> 3) 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. Since checking for perfect power is relatively cheap, it is
    done regardless of the limit setting.

    This number, for example, has two small factors and a huge
    semi-prime factor that cannot be reduced easily:

    >>> from diofant.ntheory import isprime
    >>> a = 1407633717262338957430697921446883
    >>> f = factorint(a, limit=10000)
    >>> f == {991: 1, int(202916782076162456022877024859): 1, 7: 1}
    True
    >>> isprime(max(f))
    False

    This number has a small factor and a residual perfect power whose
    base is greater than the limit:

    >>> factorint(3*101**7, limit=5)
    {3: 1, 101: 7}

    Visual Factorization:

    If ``visual`` is set to ``True``, then it will return a visual
    factorization of the integer.  For example:

    >>> from diofant import pprint
    >>> pprint(factorint(4200, visual=True), use_unicode=False)
     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.

    You can easily switch between the two forms by sending them back to
    factorint:

    >>> from diofant import Mul, Pow
    >>> regular = factorint(1764); regular
    {2: 2, 3: 2, 7: 2}
    >>> pprint(factorint(regular), use_unicode=False)
     2  2  2
    2 *3 *7

    >>> visual = factorint(1764, visual=True); pprint(visual, use_unicode=False)
     2  2  2
    2 *3 *7
    >>> print(factorint(visual))
    {2: 2, 3: 2, 7: 2}

    If you want to send a number to be factored in a partially factored form
    you can do so with a dictionary or unevaluated expression:

    >>> factorint(factorint({4: 2, 12: 3})) # twice to toggle to dict form
    {2: 10, 3: 3}
    >>> factorint(Mul(4, 12, evaluate=False))
    {2: 4, 3: 1}

    The table of the output logic is:

        ====== ====== ======= =======
                       Visual
        ------ ----------------------
        Input  True   False   other
        ====== ====== ======= =======
        dict    mul    dict    mul
        n       mul    dict    dict
        mul     mul    dict    dict
        ====== ====== ======= =======

    Notes
    =====

    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('%s %s' % (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.


    If ``verbose`` is set to ``True``, detailed progress is printed.

    See Also
    ========

    smoothness, smoothness_p, divisors
    """
    factordict = {}
    if visual and not isinstance(n, Mul) and not isinstance(n, dict):
        factordict = factorint(n,
                               limit=limit,
                               use_trial=use_trial,
                               use_rho=use_rho,
                               use_pm1=use_pm1,
                               verbose=verbose,
                               visual=False)
    elif isinstance(n, Mul):
        factordict = {
            int(k): int(v)
            for k, v in list(n.as_powers_dict().items())
        }
    elif isinstance(n, dict):
        factordict = n
    if factordict and (isinstance(n, Mul) or isinstance(n, dict)):
        # check it
        for k in list(factordict.keys()):
            if isprime(k):
                continue
            e = factordict.pop(k)
            d = factorint(k,
                          limit=limit,
                          use_trial=use_trial,
                          use_rho=use_rho,
                          use_pm1=use_pm1,
                          verbose=verbose,
                          visual=False)
            for k, v in d.items():
                if k in factordict:
                    factordict[k] += v * e
                else:
                    factordict[k] = v * e
    if visual or (type(n) is dict and visual is not True
                  and visual is not False):
        if factordict == {}:
            return S.One
        if -1 in factordict:
            factordict.pop(-1)
            args = [S.NegativeOne]
        else:
            args = []
        args.extend(
            [Pow(*i, evaluate=False) for i in sorted(factordict.items())])
        return Mul(*args, evaluate=False)
    elif isinstance(n, dict) or isinstance(n, Mul):
        return factordict

    assert use_trial or use_rho or use_pm1

    n = as_int(n)
    if limit:
        limit = int(limit)

    # special cases
    if n < 0:
        factors = factorint(-n,
                            limit=limit,
                            use_trial=use_trial,
                            use_rho=use_rho,
                            use_pm1=use_pm1,
                            verbose=verbose,
                            visual=False)
        factors[-1] = 1
        return factors

    if limit and limit < 2:
        if n == 1:
            return {}
        return {n: 1}
    elif n < 10:
        # doing this we are assured of getting a limit > 2
        # when we have to compute it later
        return [{
            0: 1
        }, {}, {
            2: 1
        }, {
            3: 1
        }, {
            2: 2
        }, {
            5: 1
        }, {
            2: 1,
            3: 1
        }, {
            7: 1
        }, {
            2: 3
        }, {
            3: 2
        }][n]

    factors = {}

    # do simplistic factorization
    if verbose:
        sn = str(n)
        if len(sn) > 50:
            print('Factoring %s' % sn[:5] + '..(%i other digits)..' %
                  (len(sn) - 10) + sn[-5:])
        else:
            print('Factoring', n)

    if use_trial:
        # this is the preliminary factorization for small factors
        small = 2**15
        fail_max = 600
        small = min(small, limit or small)
        if verbose:
            print(trial_int_msg % (2, small, fail_max))
        n, next_p = _factorint_small(factors, n, small, fail_max)
    else:
        next_p = 2
    if factors and verbose:
        for k in sorted(factors):
            print(factor_msg % (k, factors[k]))
    if next_p == 0:
        if n > 1:
            factors[int(n)] = 1
        if verbose:
            print(complete_msg)
        return factors

    # continue with more advanced factorization methods

    # first check if the simplistic run didn't finish
    # because of the limit and check for a perfect
    # power before exiting
    try:
        if limit and next_p > limit:
            if verbose:
                print('Exceeded limit:', limit)

            _check_termination(factors, n, limit, use_trial, use_rho, use_pm1,
                               verbose)

            if n > 1:
                factors[int(n)] = 1
            return factors
        else:
            # Before quitting (or continuing on)...

            # ...do a Fermat test since it's so easy and we need the
            # square root anyway. Finding 2 factors is easy if they are
            # "close enough." This is the big root equivalent of dividing by
            # 2, 3, 5.
            sqrt_n = integer_nthroot(n, 2)[0]
            a = sqrt_n + 1
            a2 = a**2
            b2 = a2 - n
            for i in range(3):
                b, fermat = integer_nthroot(b2, 2)
                if fermat:
                    break
                b2 += 2 * a + 1  # equiv to (a+1)**2 - n
                a += 1
            if fermat:
                if verbose:
                    print(fermat_msg)
                if limit:
                    limit -= 1
                for r in [a - b, a + b]:
                    facs = factorint(r,
                                     limit=limit,
                                     use_trial=use_trial,
                                     use_rho=use_rho,
                                     use_pm1=use_pm1,
                                     verbose=verbose)
                    factors.update(facs)
                raise StopIteration

            # ...see if factorization can be terminated
            _check_termination(factors, n, limit, use_trial, use_rho, use_pm1,
                               verbose)

    except StopIteration:
        if verbose:
            print(complete_msg)
        return factors

    # these are the limits for trial division which will
    # be attempted in parallel with pollard methods
    low, high = next_p, 2 * next_p

    limit = limit or sqrt_n
    # add 1 to make sure limit is reached in primerange calls
    limit += 1

    while 1:

        try:
            high_ = high
            if limit < high_:
                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)
                if found_trial:
                    _check_termination(factors, n, limit, use_trial, use_rho,
                                       use_pm1, verbose)
            else:
                found_trial = False

            if high > limit:
                if verbose:
                    print('Exceeded limit:', limit)
                if n > 1:
                    factors[int(n)] = 1
                raise StopIteration

            # Only used advanced methods when no small factors were found
            if not found_trial:
                if (use_pm1 or use_rho):
                    high_root = max(int(math.log(high_**0.7)), low, 3)

                    # Pollard p-1
                    if use_pm1:
                        if verbose:
                            print(pm1_msg % (high_root, high_))
                        c = pollard_pm1(n, B=high_root, seed=high_)
                        if c:
                            # factor it and let _trial do the update
                            ps = factorint(c,
                                           limit=limit - 1,
                                           use_trial=use_trial,
                                           use_rho=use_rho,
                                           use_pm1=use_pm1,
                                           verbose=verbose)
                            n, _ = _trial(factors, n, ps, verbose=False)
                            _check_termination(factors, n, limit, use_trial,
                                               use_rho, use_pm1, verbose)

                    # Pollard rho
                    if use_rho:
                        max_steps = high_root
                        if verbose:
                            print(rho_msg % (1, max_steps, high_))
                        c = pollard_rho(n,
                                        retries=1,
                                        max_steps=max_steps,
                                        seed=high_)
                        if c:
                            # factor it and let _trial do the update
                            ps = factorint(c,
                                           limit=limit - 1,
                                           use_trial=use_trial,
                                           use_rho=use_rho,
                                           use_pm1=use_pm1,
                                           verbose=verbose)
                            n, _ = _trial(factors, n, ps, verbose=False)
                            _check_termination(factors, n, limit, use_trial,
                                               use_rho, use_pm1, verbose)

        except StopIteration:
            if verbose:
                print(complete_msg)
            return factors

        low, high = high, high * 2
コード例 #30
0
def multiplicity(p, n):
    """Find the greatest integer m such that p**m divides n.

    Examples
    ========

    >>> from diofant.ntheory import multiplicity
    >>> from diofant.core.numbers import Rational as R
    >>> [multiplicity(5, n) for n in [8, 5, 25, 125, 250]]
    [0, 1, 2, 3, 3]
    >>> multiplicity(3, R(1, 9))
    -2
    """
    try:
        p, n = as_int(p), as_int(n)
    except ValueError:
        if all(isinstance(i, (DIOFANT_INTS, Rational)) for i in (p, n)):
            try:
                p = Rational(p)
                n = Rational(n)
                if p.q == 1:
                    if n.p == 1:
                        return -multiplicity(p.p, n.q)
                    return S.Zero
                elif p.p == 1:
                    return multiplicity(p.q, n.q)
                else:
                    like = min(multiplicity(p.p, n.p), multiplicity(p.q, n.q))
                    cross = min(multiplicity(p.q, n.p), multiplicity(p.p, n.q))
                    return like - cross
            except AttributeError:
                pass
        raise ValueError('expecting ints or fractions, got %s and %s' % (p, n))

    if n == 0:
        raise ValueError('multiplicity of 0 is not defined')
    if p == 2:
        return trailing(n)
    if p < 2:
        raise ValueError('p must be an integer, 2 or larger, but got %s' % p)
    if p == n:
        return 1

    m = 0
    n, rem = divmod(n, p)
    while not rem:
        m += 1
        if m > 5:
            # The multiplicity could be very large. Better
            # to increment in powers of two
            e = 2
            while 1:
                ppow = p**e
                if ppow < n:
                    nnew, rem = divmod(n, ppow)
                    if not rem:
                        m += e
                        e *= 2
                        n = nnew
                        continue
                return m + multiplicity(p, n)
        n, rem = divmod(n, p)
    return m
コード例 #31
0
 def eye(cls, n):
     """Return an n x n identity matrix."""
     n = as_int(n)
     mat = [cls._sympify(0)] * n * n
     mat[::n + 1] = [cls._sympify(1)] * n
     return cls._new(n, n, mat)