예제 #1
0
    def test_is_power(self):
        self.assertRaisesRegexp(ValueError, "is_power: Must have k >= 1.", is_power, 10, 0)
        self.assertRaisesRegexp(ValueError, "is_power: Must have n >= 1.", is_power, 0, 3)

        for k in [2, 3, 5, 7, 11]:
            self.assertEqual(is_power(k), False)

        for k in xrange(10):
            a = random.randint(10, 100)
            b = random.randint(10, 100)
            n = a**b
            x, y = is_power(n)

            self.assertTrue(x**y == n)

        for k in xrange(10):
            a = random.randint(10, 100)
            b = random.randint(10, 100)
            n = a**b
            x, y = is_power(n, b)

            self.assertTrue(x**y == n)

        values = [
            4, 8, 9, 16, 25, 27, 32, 36, 49, 64, 81, 100, 121, 125, 128, 144, 169, 196, 216, 225, 243, 256, 289, 324,
            343, 361, 400, 441, 484, 512, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1000
        ]

        powers = [e for e in xrange(1, 1001) if is_power(e)]

        self.assertEqual(values, powers)

        self.assertEqual(is_power([(2, 4), (3, 2)]), (12, 2))
        self.assertEqual(is_power([(2, 4), (3, 3)]), False)

        self.assertEqual(is_power([(3, 4), (5, 4)]), (15, 4))
        self.assertEqual(is_power([(3, 4), (5, 4)], 2), (225, 2))
예제 #2
0
def factor(n, skip_trial_division=False, use_cfrac=False):
    r"""Returns the factorization of the integer `n`.

    Parameters
    ----------
    n : int
        Integer to be factored.

    skip_trial_division : bool, optional (default=False)
        If False, performs a preliminary trial division using the
        precomputed list of primes. If True, then this step is skipped.

    use_cfrac : bool, optional (default=False)
        If True, applies the cfrac method to search for factors instead of
        the Pollard rho method. If False, then the Pollard rho method is
        used to search for factors.

    Returns
    -------
    factorization : list
        A list of pairs (p, e) consisting of the primes p and exponents e
        such that ``p**e`` divides `n`.

    Notes
    -----
    This method uses a variety of techniques to obtain a factorization of
    `n`. First, we perform trial division using a precomputed list of
    primes to find all small prime factors. After this, we apply Pollard's
    rho method to find any remaining small prime divisors.

    References
    ----------
    .. [1] H. Riesel, "Prime Numbers and Computer Methods for
    Factorization", 2nd edition, Birkhauser Verlag, Basel, Switzerland,
    1994.

    Examples
    --------
    >>> factor(100)
    [(2, 2), (5, 2)]
    >>> factor(537869)
    [(37, 1), (14537, 1)]
    >>> factor(2**91 - 1)
    [(127, 1), (911, 1), (8191, 1), (112901153L, 1), (23140471537L, 1)]
    >>> factor(10**22 + 1)
    [(89, 1), (101, 1), (1052788969L, 1), (1056689261L, 1)]
    """
    fac = collections.defaultdict(int)

    _is_prime = primality.is_probable_prime
    if use_cfrac:
        _factor = algorithms.cfrac
    else:
        _factor = algorithms.pollard_rho_brent

    if n == 0:
        raise ValueError("Prime factorization of 0 not defined")

    # Detect perfect powers.
    ab = is_power(n)
    if ab:
        (n, multiplier) = ab
    else:
        (n, multiplier) = (n, 1)

    # Take care of the sign
    if n < 0:
        fac[-1] = 1
        n *= -1

    # Strip off all small factors of n
    for p in _PRIME_LIST:
        if n == 1:
            break
        elif p*p > n:
            fac[n] += 1
            n = 1
            break

        while n % p == 0:
            fac[p] += 1
            n //= p

    # Next, strip off remaining factors.
    while n > 1:
        if _is_prime(n):
            fac[n] += 1
            n = 1
        else:
            d = _factor(n)
            while not _is_prime(d):
                d = _factor(d)
            while n % d == 0:
                fac[d] += 1
                n = n // d

    factorization = sorted([(p, fac[p]*multiplier) for p in fac])
    return factorization