Beispiel #1
0
    def test_primes(self):
        values = primes(1000)
        self.assertEqual(values, self.primes_to_1000)

        values = primes(0)
        self.assertEqual(values, [])

        values = primes(-1)
        self.assertEqual(values, [])

        value = sum(primes(2 * 10**6))
        self.assertEqual(value, self.sum_of_primes_to_2000000)
Beispiel #2
0
    def test_primes(self):
        values = primes(1000)
        self.assertEqual(values, self.primes_to_1000)

        values = primes(0)
        self.assertEqual(values, [])

        values = primes(-1)
        self.assertEqual(values, [])

        value = sum(primes(2*10**6))
        self.assertEqual(value, self.sum_of_primes_to_2000000)
Beispiel #3
0
def pi_table(n):
    r"""Returns the primes <= n, as well as a table of pi(x) for x <= n.

    Parameters
    ----------
    n : int

    Returns
    -------
    (primes, table) : tuple
        The list `primes` contains the primes <= n. The list `table` is
        indexed 0 to n, with `table[k]` giving the number of primes <= k.

    Notes
    -----
    This method uses the function `primes` to compute the primes, and
    simple does some bookkeeping to maintain a running count.

    Examples
    --------
    >>> pi_table(10)
    ([2, 3, 5, 7], [0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4])
    """
    primes = sieves.primes(n)
    table = [0] * (n + 1)
    last = 0

    for (i, p) in enumerate(primes):
        table[last:p] = [i] * (p - last)
        last = p

    table[last:n + 1] = [i + 1] * (n + 1 - last)

    return primes, table
    def test_fibonacci_primitive_roots(self):
        values = [
            (5, [3]),
            (11, [8]),
            (19, [15]),
            (31, [13]),
            (41, [7, 35]),
            (59, [34]),
            (61, [18, 44]),
            (71, [63]),
            (79, [30]),
            (109, [11, 99]),
            (131, [120]),
            (149, [41, 109]),
            (179, [105]),
            (191, [89]),
        ]

        computed = []
        for p in primes(200):
            roots = fibonacci_primitive_roots(p)
            if roots:
                computed.append((p, roots))

        self.assertEqual(values, computed)
Beispiel #5
0
def moebius_xrange(a, b=None):
    """Return an generator over values of moebius(k) for a <= k < b.

    Input:
        * a: int (a > 0)
        * b: int (b > a) (default=None)

    Returns:
        * P: generator
            The values output by this generator are tuples (n, moebius(n)) where
            n is an integer in [a, b), and moebius(n) is the value of the
            moebius function.

    Examples:
        >>> list(moebius_xrange(10, 20))
        [(10, 1), (11, -1), (12, 0), (13, -1), (14, 1), (15, 1), (16, 0), (17, -1), (18, 0), (19, -1)]

    Details:
        All primes <= sqrt(b) are computed, and a segmented sieve is used to
        build the values using the multiplicative property of the moebius
        function. See the paper "Computing the Summation of the Moebius
        Function" by Deleglise and Rivat for more information.
    """
    if a < 2:
        a = 1

    if b is None:
        b, a = a, 1

    if b <= a:
        return

    block_size = integer_sqrt(b)
    prime_list = prime_sieves.primes(block_size)

    for start in xrange(a, b, block_size):
        block = [1] * block_size
        values = [1] * block_size

        for p in prime_list:
            offset = ((p * (start // p + 1) - a) % block_size) % p
            for i in xrange(offset, block_size, p):
                if (start + i) % (p * p) == 0:
                    block[i] = 0
                else:
                    block[i] *= -1
                    values[i] *= p

        for i in xrange(block_size):
            if start + i >= b:
                return
            if block[i] and values[i] < start + i:
                block[i] *= -1
            yield (start + i, block[i])
Beispiel #6
0
def moebius_list(n):
    """Return a list of the values of moebius(k) for 1 <= k <= n.

    Parameters
        * n: int (n > 0)

    Returns:
        * L: list
            This is a list of values of moebius(k) for 1 <= k <= n. The list
            begins with 0, so that L[k] holds the value of moebius(k).

    Raises:
        * ValueError: If n <= 0.

    Examples:
        >>> moebius_list(10)
        [0, 1, -1, -1, 0, -1, 1, -1, 0, 0, 1]
        >>> [0] + [moebius(k) for k in xrange(1, 11)]
        [0, 1, -1, -1, 0, -1, 1, -1, 0, 0, 1]
        >>> moebius_list(0)
        Traceback (most recent call last):
        ...
        ValueError: moebius_list: Must have n > 0.

    Details:
        This function creates a list of (n + 1) elements, and fills the list by
        sieving and using the product definition of moebius(n).
    """
    if n <= 0:
        raise ValueError("moebius_list: Must have n > 0.")

    sqrt = int(n**(0.5))
    prime_list = prime_sieves.primes(sqrt)

    values = [1] * (n + 1)
    block = [1] * (n + 1)
    block[0] = 0

    for p in prime_list:
        for i in xrange(p, n + 1, p):
            if i % (p * p) == 0:
                block[i] = 0
            else:
                block[i] *= -1
                values[i] *= p

    for i in xrange(n + 1):
        if block[i] and values[i] < i:
            block[i] *= -1

    return block
Beispiel #7
0
def moebius_list(n):
    """Return a list of the values of moebius(k) for 1 <= k <= n.

    Parameters
        * n: int (n > 0)

    Returns:
        * L: list
            This is a list of values of moebius(k) for 1 <= k <= n. The list
            begins with 0, so that L[k] holds the value of moebius(k).

    Raises:
        * ValueError: If n <= 0.

    Examples:
        >>> moebius_list(10)
        [0, 1, -1, -1, 0, -1, 1, -1, 0, 0, 1]
        >>> [0] + [moebius(k) for k in xrange(1, 11)]
        [0, 1, -1, -1, 0, -1, 1, -1, 0, 0, 1]
        >>> moebius_list(0)
        Traceback (most recent call last):
        ...
        ValueError: moebius_list: Must have n > 0.

    Details:
        This function creates a list of (n + 1) elements, and fills the list by
        sieving and using the product definition of moebius(n).
    """
    if n <= 0:
        raise ValueError("moebius_list: Must have n > 0.")

    sqrt = int(n**(0.5))
    prime_list = prime_sieves.primes(sqrt)

    values = [1]*(n + 1)
    block = [1]*(n + 1)
    block[0] = 0

    for p in prime_list:
        for i in xrange(p, n + 1, p):
            if i % (p*p) == 0:
                block[i] = 0
            else:
                block[i] *= -1
                values[i] *= p

    for i in xrange(n + 1):
        if block[i] and values[i] < i:
            block[i] *= -1

    return block
Beispiel #8
0
def lmo_bit(x):
    root = int(x**(2.0 / 3.0))

    primes = sieves.primes(root)
    t = x**(0.33333333333333)

    c = bisect(primes, t)
    b = bisect(primes, x**(0.5))

    value = (b + c - 2) * (b - c + 1) // 2

    for i in xrange(c, b):
        idx = bisect(primes, x // primes[i])
        value -= idx

    special = defaultdict(list)

    stack = [(1, c, 1)]
    push = stack.append
    pop = stack.pop

    while stack:
        (n, a, sign) = pop()

        if a == 1 and n <= t:
            if sign > 0:
                value += (x // n + 1) // 2
            else:
                value -= (x // n + 1) // 2
        elif n > t:
            special[a].append((x // n, sign))
        else:
            push((n, a - 1, sign))
            push((n * primes[a - 1], a - 1, -sign))

    block = bit_sieve.BITSieveArray(root)
    mark = block.mark_multiples
    total = block.partial_sum

    for a in sorted(special):
        p = primes[a - 1]

        mark(p)

        for v, sign in sorted(special[a]):
            if sign > 0:
                value += total(v)
            else:
                value -= total(v)

    return value
Beispiel #9
0
def legendre(n):
    r"""Returns the number of primes <= n.

    Parameters
    ----------
    n : int (n > 0)

    Returns
    -------
    count : int
        The number of primes <= n.

    Notes
    -----
    This method uses the function `primes` to compute the primes, and
    simple does some bookkeeping to maintain a running count.

    Examples
    --------
    >>> pi_table(10)
    ([2, 3, 5, 7], [0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4])
    """
    if n <= 1:
        return 0
    elif n <= _PRIME_LIST[-1]:
        return bisect(_PRIME_LIST, n)

    root = integer_sqrt(n)
    primes = sieves.primes(root)
    a = len(primes)

    def phi(x, a, cache={}):
        if (x, a) in cache:
            return cache[x, a]

        if a == 1:
            return (x + 1) // 2

        value = (x + 1) // 2
        for i in xrange(2, a + 1):
            p = primes[i - 1]
            if p > x:
                break
            value -= phi(x // p, i - 1)

        cache[x, a] = value
        return value

    return phi(n, a) + a - 1
Beispiel #10
0
def euler_phi_list(n):
    """Returns a list of values of euler_phi(k) for 1 <= k <= n.

    Parameters
        * n: int (n > 0)

    Returns:
        * values: list
            This is a list of values of euler_phi(k) for 1 <= k <= n. The list
            begins with 0, so that L[k] holds the value of euler_phi(k).

    Raises:
        * ValueError: If n <= 0.

    Examples:
        >>> euler_phi_list(10)
        [0, 1, 1, 2, 2, 4, 2, 6, 4, 6, 4]
        >>> [0] + [euler_phi(k) for k in xrange(1, 11)]
        [0, 1, 1, 2, 2, 4, 2, 6, 4, 6, 4]
        >>> euler_phi_list(0)
        Traceback (most recent call last):
        ...
        ValueError: euler_phi_list: Must have n > 0.

    Details:
        This function initially creates a list of (n + 1) zeros, and fills the
        list by sieving, using the product definition of euler_phi(n).
    """
    if n <= 0:
        raise ValueError("euler_phi_list: Must have n > 0.")

    block = [1] * (n + 1)
    block[0] = 0
    prime_list = prime_sieves.primes(n)

    for p in prime_list:
        for mul in xrange(p, n + 1, p):
            block[mul] *= (p - 1)
        pk = p * p
        while pk <= n:
            for mul in xrange(pk, n + 1, pk):
                block[mul] *= p
            pk *= p

    return block
Beispiel #11
0
def euler_phi_list(n):
    """Returns a list of values of euler_phi(k) for 1 <= k <= n.

    Parameters
        * n: int (n > 0)

    Returns:
        * values: list
            This is a list of values of euler_phi(k) for 1 <= k <= n. The list
            begins with 0, so that L[k] holds the value of euler_phi(k).

    Raises:
        * ValueError: If n <= 0.

    Examples:
        >>> euler_phi_list(10)
        [0, 1, 1, 2, 2, 4, 2, 6, 4, 6, 4]
        >>> [0] + [euler_phi(k) for k in xrange(1, 11)]
        [0, 1, 1, 2, 2, 4, 2, 6, 4, 6, 4]
        >>> euler_phi_list(0)
        Traceback (most recent call last):
        ...
        ValueError: euler_phi_list: Must have n > 0.

    Details:
        This function initially creates a list of (n + 1) zeros, and fills the
        list by sieving, using the product definition of euler_phi(n).
    """
    if n <= 0:
        raise ValueError("euler_phi_list: Must have n > 0.")

    block = [1]*(n + 1)
    block[0] = 0
    prime_list = prime_sieves.primes(n)

    for p in prime_list:
        for mul in xrange(p, n + 1, p):
            block[mul] *= (p - 1)
        pk = p*p
        while pk <= n:
            for mul in xrange(pk, n + 1, pk):
                block[mul] *= p
            pk *= p

    return block
Beispiel #12
0
def prime_sum2(n):
    root = integer_sqrt(n)
    primes = sieves.primes(root)
    a = len(primes)

    sum_table = [0] * (root + 1)
    accumulation = primes[:]
    for i in xrange(1, len(accumulation)):
        accumulation[i] += accumulation[i - 1]

    for (p, total) in zip(primes, accumulation):
        sum_table[p] = total

    for i in xrange(2, root + 1):
        if not sum_table[i]:
            sum_table[i] = sum_table[i - 1]

    def phi(x, a, cache={}):
        if (x, a) in cache:
            return cache[x, a]

        if x == 0:
            return 0
        if a == 0:
            return x * (x + 1) // 2

        value = x * (x + 1) // 2
        for i in xrange(1, a + 1):
            p = primes[i - 1]
            if p > x:
                break
            value -= p * phi(x // p, i - 1)

        cache[x, a] = value
        return value

    return phi(n, a) + sum(primes) - 1
Beispiel #13
0
def sigma_list(n, k=1):
    """Return a list of the values of sigma(i, k) for 1 <= i <= n.

    Parameters
        * n: int (n > 0)
        * k: int (k > 0) (default=1)

    Returns:
        * L: list
            This is a list of values of sigma(i, k) for 1 <= i <= n. The list
            begins with 0, so that L[i] holds the value of sigma(i, k).

    Raises:
        * ValueError: If n <= 1 or k < 0.

    Examples:
        >>> sigma_list(10)
        [0, 1, 3, 4, 7, 6, 12, 8, 15, 13, 18]
        >>> [0] + [sigma(k) for k in xrange(1, 11)]
        [0, 1, 3, 4, 7, 6, 12, 8, 15, 13, 18]
        >>> sigma_list(10, 2)
        [0, 1, 5, 10, 21, 26, 50, 50, 85, 91, 130]
        >>> [0] + [sigma(k, 2) for k in xrange(1, 11)]
        [0, 1, 5, 10, 21, 26, 50, 50, 85, 91, 130]
        >>> sigma_list(-1)
        Traceback (most recent call last):
        ...
        ValueError: sigma_list: Must have n > 0.
        >>> sigma_list(10, -1)
        Traceback (most recent call last):
        ...
        ValueError: sigma_list: Must have k >= 0.

    Details:
        This function creates a list of (n + 1) elements, and fills the list by
        sieving and using the product definition of sigma(n, k). For k == 1 and
        small values of n, a simpler but faster algorithm is used. See Section
        9.8 in "Algorithmic Number Theory - Efficient Algorithms" by Bach and
        Shallit for details.
    """
    if n <= 0:
        raise ValueError("sigma_list: Must have n > 0.")

    if k == 0:
        return tau_list(n)
    elif k < 0:
        raise ValueError("sigma_list: Must have k >= 0.")

    # Use a special algorithm when k == 1 for small values of n.
    if k == 1 and n <= 10**4:
        block = [0]*(n + 1)
        sqrt = int(n**(0.5))

        for j in xrange(1, sqrt + 1):
            block[j*j] += j
            for k in xrange(j + 1, n//j + 1):
                block[k*j] += j + k

    else:
        block = [1]*(n + 1)
        block[0] = 0
        prime_list = prime_sieves.primes(n)

        for p in prime_list:
            pk = p
            mul = p**k
            term = mul**2
            last = mul
            while pk <= n:
                for idx in xrange(pk, n + 1, pk):
                    block[idx] *= (term - 1)
                    block[idx] /= (last - 1)
                pk *= p
                last = term
                term *= mul

    return block
Beispiel #14
0
def sigma_list(n, k=1):
    """Return a list of the values of sigma(i, k) for 1 <= i <= n.

    Parameters
        * n: int (n > 0)
        * k: int (k > 0) (default=1)

    Returns:
        * L: list
            This is a list of values of sigma(i, k) for 1 <= i <= n. The list
            begins with 0, so that L[i] holds the value of sigma(i, k).

    Raises:
        * ValueError: If n <= 1 or k < 0.

    Examples:
        >>> sigma_list(10)
        [0, 1, 3, 4, 7, 6, 12, 8, 15, 13, 18]
        >>> [0] + [sigma(k) for k in xrange(1, 11)]
        [0, 1, 3, 4, 7, 6, 12, 8, 15, 13, 18]
        >>> sigma_list(10, 2)
        [0, 1, 5, 10, 21, 26, 50, 50, 85, 91, 130]
        >>> [0] + [sigma(k, 2) for k in xrange(1, 11)]
        [0, 1, 5, 10, 21, 26, 50, 50, 85, 91, 130]
        >>> sigma_list(-1)
        Traceback (most recent call last):
        ...
        ValueError: sigma_list: Must have n > 0.
        >>> sigma_list(10, -1)
        Traceback (most recent call last):
        ...
        ValueError: sigma_list: Must have k >= 0.

    Details:
        This function creates a list of (n + 1) elements, and fills the list by
        sieving and using the product definition of sigma(n, k). For k == 1 and
        small values of n, a simpler but faster algorithm is used. See Section
        9.8 in "Algorithmic Number Theory - Efficient Algorithms" by Bach and
        Shallit for details.
    """
    if n <= 0:
        raise ValueError("sigma_list: Must have n > 0.")

    if k == 0:
        return tau_list(n)
    elif k < 0:
        raise ValueError("sigma_list: Must have k >= 0.")

    # Use a special algorithm when k == 1 for small values of n.
    if k == 1 and n <= 10**4:
        block = [0] * (n + 1)
        sqrt = int(n**(0.5))

        for j in xrange(1, sqrt + 1):
            block[j * j] += j
            for k in xrange(j + 1, n // j + 1):
                block[k * j] += j + k

    else:
        block = [1] * (n + 1)
        block[0] = 0
        prime_list = prime_sieves.primes(n)

        for p in prime_list:
            pk = p
            mul = p**k
            term = mul**2
            last = mul
            while pk <= n:
                for idx in xrange(pk, n + 1, pk):
                    block[idx] *= (term - 1)
                    block[idx] /= (last - 1)
                pk *= p
                last = term
                term *= mul

    return block
Beispiel #15
0
def lmo(x):
    if x <= 1:
        return 0
    elif x <= _PRIME_LIST[-1]:
        return bisect(_PRIME_LIST, x)

    root = integer_nth_root(3, x**2)
    primes = sieves.primes(root)

    t = integer_nth_root(3, x)
    c = bisect(primes, t)
    b = bisect(primes, integer_nth_root(2, x))

    value = (b + c - 2) * (b - c + 1) // 2

    for i in xrange(c, b):
        idx = bisect(primes, x // primes[i])
        value -= idx

    special = defaultdict(list)

    stack = [(1, c, 1)]
    push = stack.append
    pop = stack.pop

    # print "recursing"

    while stack:
        (n, a, sign) = pop()

        if a == 1 and n <= t:
            if sign > 0:
                value += (x // n + 1) // 2
            else:
                value -= (x // n + 1) // 2
        elif n > t:
            special[a].append((x // n, sign))
        else:
            push((n, a - 1, sign))
            push((n * primes[a - 1], a - 1, -sign))

    block = [1] * (root + 1)
    block[0] = 0

    for a in sorted(special):
        p = primes[a - 1]

        block[p::p] = [0] * (root // p)
        last_v = 0
        last_s = 0

        for v, sign in sorted(special[a]):
            last_s += sum(block[last_v:v + 1])
            last_v = v + 1

            if sign > 0:
                value += last_s
            else:
                value -= last_s

    return value
Beispiel #16
0
def lehmer(n):
    if n <= 1:
        return 0
    elif n <= _PRIME_LIST[-1]:
        return bisect(_PRIME_LIST, n)

    root = integer_nth_root(4, n**3)
    primes = sieves.primes(root)

    a = bisect(primes, integer_nth_root(4, n))
    b = bisect(primes, integer_sqrt(n))
    c = bisect(primes, integer_nth_root(3, n))

    def phi(x, a, cache={}):
        if (x, a) in cache:
            return cache[x, a]

        if a <= 7:
            if a == 1:
                value = x - x // 2

            elif a == 2:
                value = x - x // 2 - x // 3 + x // 6

            elif a == 3:
                value = x - x // 2 - x // 3 - x // 5 + x // 6 + x // 10 + x // 15 - x // 30

            elif a == 4:
                value = (x - x // 2 - x // 3 - x // 5 - x // 7 + x // 6 +
                         x // 10 + x // 14 + x // 15 + x // 21 + x // 35 -
                         x // 30 - x // 42 - x // 70 - x // 105 + x // 210)
            elif a == 5:
                value = (x - x // 2 - x // 3 - x // 5 - x // 7 - x // 11 +
                         x // 6 + x // 10 + x // 14 + x // 22 + x // 15 +
                         x // 21 + x // 33 + x // 35 + x // 55 + x // 77 -
                         x // 30 - x // 42 - x // 66 - x // 70 - x // 110 -
                         x // 154 - x // 105 - x // 165 - x // 231 - x // 385 +
                         x // 210 + x // 330 + x // 462 + x // 770 +
                         x // 1155 - x // 2310)
            elif a == 6:
                value = (x - x // 2 - x // 3 - x // 5 - x // 7 - x // 11 -
                         x // 13 + x // 6 + x // 10 + x // 14 + x // 22 +
                         x // 26 + x // 15 + x // 21 + x // 33 + x // 39 +
                         x // 35 + x // 55 + x // 65 + x // 77 + x // 91 +
                         x // 143 - x // 30 - x // 42 - x // 66 - x // 78 -
                         x // 70 - x // 110 - x // 130 - x // 154 - x // 182 -
                         x // 286 - x // 105 - x // 165 - x // 195 - x // 231 -
                         x // 273 - x // 429 - x // 385 - x // 455 - x // 715 -
                         x // 1001 + x // 210 + x // 330 + x // 390 +
                         x // 462 + x // 546 + x // 858 + x // 770 + x // 910 +
                         x // 1430 + x // 2002 + x // 1155 + x // 1365 +
                         x // 2145 + x // 3003 + x // 5005 - x // 2310 -
                         x // 2730 - x // 4290 - x // 6006 - x // 10010 -
                         x // 15015 + x // 30030)
            else:
                value = (
                    x - x // 2 - x // 3 - x // 5 - x // 7 - x // 11 - x // 13 -
                    x // 17 + x // 6 + x // 10 + x // 14 + x // 22 + x // 26 +
                    x // 34 + x // 15 + x // 21 + x // 33 + x // 39 + x // 51 +
                    x // 35 + x // 55 + x // 65 + x // 85 + x // 77 + x // 91 +
                    x // 119 + x // 143 + x // 187 + x // 221 - x // 30 -
                    x // 42 - x // 66 - x // 78 - x // 102 - x // 70 -
                    x // 110 - x // 130 - x // 170 - x // 154 - x // 182 -
                    x // 238 - x // 286 - x // 374 - x // 442 - x // 105 -
                    x // 165 - x // 195 - x // 255 - x // 231 - x // 273 -
                    x // 357 - x // 429 - x // 561 - x // 663 - x // 385 -
                    x // 455 - x // 595 - x // 715 - x // 935 - x // 1105 -
                    x // 1001 - x // 1309 - x // 1547 - x // 2431 + x // 210 +
                    x // 330 + x // 390 + x // 510 + x // 462 + x // 546 +
                    x // 714 + x // 858 + x // 1122 + x // 1326 + x // 770 +
                    x // 910 + x // 1190 + x // 1430 + x // 1870 + x // 2210 +
                    x // 2002 + x // 2618 + x // 3094 + x // 4862 + x // 1155 +
                    x // 1365 + x // 1785 + x // 2145 + x // 2805 + x // 3315 +
                    x // 3003 + x // 3927 + x // 4641 + x // 7293 + x // 5005 +
                    x // 6545 + x // 7735 + x // 12155 + x // 17017 -
                    x // 2310 - x // 2730 - x // 3570 - x // 4290 - x // 5610 -
                    x // 6630 - x // 6006 - x // 7854 - x // 9282 -
                    x // 14586 - x // 10010 - x // 13090 - x // 15470 -
                    x // 24310 - x // 34034 - x // 15015 - x // 19635 -
                    x // 23205 - x // 36465 - x // 51051 - x // 85085 +
                    x // 30030 + x // 39270 + x // 46410 + x // 72930 +
                    x // 102102 + x // 170170 + x // 255255 - x // 510510)

        elif a >= bisect(primes, x**(0.5)) and x < primes[-1]:
            pi = bisect(primes, x)
            value = pi - a + 1

        else:
            value = (x + 1) // 2
            for i in xrange(1, a):
                if primes[i] > x:
                    break
                value -= phi(x // primes[i], i)

        cache[x, a] = value
        return value

    def phi2(n, a, b):
        s1 = 0
        for i in xrange(a, b):
            s1 += phi(n // primes[i], b) + b - 1
        return s1

    def phi3(n, a, b, c):
        s2 = 0
        for i in xrange(a, c):
            bi = phi(integer_sqrt(n // primes[i]), b) + b - 1
            for j in xrange(i, bi):
                idx = phi(n // (primes[i] * primes[j]), b) + b - 1
                s2 += idx - j
        return s2

    value = (b + a - 2) * (b - a + 1) // 2 + phi(n, a) - phi2(n, a, b) - phi3(
        n, a, b, c)
    return value
Beispiel #17
0
def pollard_p_minus_1(n, limit=100000):
    r"""Attempts to find a nontrivial factor of `n`.

    Given a composite number `n` and search bound `limit`, this algorithm
    attempts to find a nontrivial factor of `n` using Pollard's p - 1
    method.

    Parameters
    ----------
    n : int (n > 1)
        Integer to be factored.

    limit : int (limit > 0) (default=100000)
        Search limit for possible prime divisors of p - 1.

    Returns
    -------
    d : int
        Divisor of n.

    Notes
    -----
    The algorithm used here is a one-stage form of Pollard's p - 1 method.
    The idea used is that if p - 1 divides Q, then p divides a^Q - 1 if (a,
    p) == 1. So if p is a prime factor of an integer n, then p divides
    gcd(a^Q - 1, n). The idea here is to choose values Q with many divisors
    of the form p - 1, and so search for many primes p as possible divisors
    at once. This is not a general purpose factoring algorithm, but this
    technique works well when n has a prime factor P such that P - 1 is
    divisible by only small primes. See chapter 6 of [2] for details.

    References
    ----------
    .. [1] R. Crandall, C. Pomerance, "Prime Numbers: A Computational
    Perspective", Springer-Verlag, New York, 2001.

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

    Examples
    --------
    >>> pollard_p_minus_1(1112470797641561909)
    1056689261L
    """
    p_list = sieves.primes(limit)
    pow_list = []

    for p in p_list:
        pk = p
        while pk <= limit:
            pow_list.append((pk, p))
            pk *= p

    pow_list.sort()
    c = 13

    for (count, (pk, p)) in enumerate(pow_list):
        c = pow(c, p, n)
        if count % 100 == 0:
            g = gcd(c - 1, n)
            if 1 < g < n:
                return g

    return gcd(c - 1, n)
Beispiel #18
0
def cfrac(n, k=None):
    r"""Returns a nontrivial divisor of `n`.

    Given a composite integer `n` > 1, this algorithm attempts to find a
    factor of `n` using Morrison and Brillhart's continued fraction method
    CFRAC.

    Parameters
    ----------
    n : int (n > 1)
        Number to be factored.

    k : int, optional (default=None)
        Multiplier to use in case the period of sqrt(n) is too short.

    Returns
    -------
    d : int
        Divisor of n.

    Notes
    -----
    Morrison and Brillhart's continued fraction method was the first
    factorization algorithm of subexponential running time. The idea is to
    find a nontrivial solution to the congrunce x^2 = y^2 (mod n), and
    extracting a factor from gcd(x + y, n). See [1] for details, and see
    [2] for implementation details.

    References
    ----------
    .. [1] H. Cohen, "A Course in Computational Algebraic Number Theory",
    Springer-Verlag, New York, 2000.

    .. [2] M.A. Morrison, J. Brillhart, "A Method of Factoring and the
    Factorization of F7", Mathematics of Computation, Vol. 29, Num. 129,
    Jan. 1975.

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

    Examples
    --------
    >>> cfrac(12007001)
    4001
    >>> cfrac(1112470797641561909)
    1052788969L
    >>> cfrac(2175282241519502424792841)
    513741730823L
    """
    # B is our smoothness bound.
    B = int(exp(0.5 * sqrt(log(n) * log(log(n))))) + 1
    prime_list = sieves.primes(B)

    # Choose a multiplier if none is provided.
    if k is None:
        k = _cfrac_multiplier(n)
    kn = k * n

    # Perform simple trial division by the primes we computed to find any
    # small prime divisors.
    for p in prime_list:
        if n % p == 0:
            return p

    # Our factor base needs to include -1 and 2, and the odd primes p for
    # which (kN|p) = 0 or 1.
    factor_base = [-1]
    for p in prime_list:
        if p == 2 or jacobi_symbol(kn, p) >= 0:
            factor_base.append(p)

    num_primes = len(factor_base)

    # Compute the product of the elements in our factor base for smoothness
    # checking computations later.
    prod = 1
    for p in factor_base:
        prod *= p

    # Instead of using trial division to check each value for smoothness
    # individually, we use a batch smoothness test, processing batches of
    # size `batch_size` at once.

    # Set e as the least positive integer with n <= 2**e.
    e = 1
    while 2**e < n:
        e *= 2

    aq_pairs = _cfrac_aq_pairs(kn)

    num_smooths_found = 0
    exponent_matrix = []
    a_list = []

    while num_smooths_found <= num_primes:
        (i, a, q) = aq_pairs.next()

        # This is from the batch smoothness test given as Algorithm 3.3.1
        # in [1].
        if gcd(q, pow(prod, e, q)) != q:
            continue

        if i % 2 == 1:
            q *= -1

        # At this point, we know q is smooth, and we can factor it
        # completely using our factor base.
        exponent_vector = smooth_factor(q, factor_base)
        exponent_matrix.append(exponent_vector)
        num_smooths_found += 1
        a_list.append(a)

    kernel = _z2_gaussian_elimination(exponent_matrix)

    for i in xrange(len(kernel)):
        y = 1
        x2_exponents = [0] * num_primes
        for j in xrange(len(kernel[i])):
            if kernel[i][j]:
                y = (a_list[j] * y) % n
                for f in xrange(num_primes):
                    x2_exponents[f] += exponent_matrix[j][f]

        x = 1
        for j in xrange(num_primes):
            x *= factor_base[j]**(x2_exponents[j] // 2)

        for val in [x - y, x + y]:
            d = gcd(val, n)
            if 1 < d < n:
                return d
Beispiel #19
0
def cfrac(n, k=None):
    r"""Returns a nontrivial divisor of `n`.

    Given a composite integer `n` > 1, this algorithm attempts to find a
    factor of `n` using Morrison and Brillhart's continued fraction method
    CFRAC.

    Parameters
    ----------
    n : int (n > 1)
        Number to be factored.

    k : int, optional (default=None)
        Multiplier to use in case the period of sqrt(n) is too short.

    Returns
    -------
    d : int
        Divisor of n.

    Notes
    -----
    Morrison and Brillhart's continued fraction method was the first
    factorization algorithm of subexponential running time. The idea is to
    find a nontrivial solution to the congrunce x^2 = y^2 (mod n), and
    extracting a factor from gcd(x + y, n). See [1] for details, and see
    [2] for implementation details.

    References
    ----------
    .. [1] H. Cohen, "A Course in Computational Algebraic Number Theory",
    Springer-Verlag, New York, 2000.

    .. [2] M.A. Morrison, J. Brillhart, "A Method of Factoring and the
    Factorization of F7", Mathematics of Computation, Vol. 29, Num. 129,
    Jan. 1975.

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

    Examples
    --------
    >>> cfrac(12007001)
    4001
    >>> cfrac(1112470797641561909)
    1052788969L
    >>> cfrac(2175282241519502424792841)
    513741730823L
    """
    # B is our smoothness bound.
    B = int(exp(0.5*sqrt(log(n)*log(log(n))))) + 1
    prime_list = sieves.primes(B)

    # Choose a multiplier if none is provided.
    if k is None:
        k = _cfrac_multiplier(n)
    kn = k*n

    # Perform simple trial division by the primes we computed to find any
    # small prime divisors.
    for p in prime_list:
        if n % p == 0:
            return p

    # Our factor base needs to include -1 and 2, and the odd primes p for
    # which (kN|p) = 0 or 1.
    factor_base = [-1]
    for p in prime_list:
        if p == 2 or jacobi_symbol(kn, p) >= 0:
            factor_base.append(p)

    num_primes = len(factor_base)

    # Compute the product of the elements in our factor base for smoothness
    # checking computations later.
    prod = 1
    for p in factor_base:
        prod *= p

    # Instead of using trial division to check each value for smoothness
    # individually, we use a batch smoothness test, processing batches of
    # size `batch_size` at once.

    # Set e as the least positive integer with n <= 2**e.
    e = 1
    while 2**e < n:
        e *= 2

    aq_pairs = _cfrac_aq_pairs(kn)

    num_smooths_found = 0
    exponent_matrix = []
    a_list = []

    while num_smooths_found <= num_primes:
        (i, a, q) = aq_pairs.next()

        # This is from the batch smoothness test given as Algorithm 3.3.1
        # in [1].
        if gcd(q, pow(prod, e, q)) != q:
            continue

        if i % 2 == 1:
            q *= -1

        # At this point, we know q is smooth, and we can factor it
        # completely using our factor base.
        exponent_vector = smooth_factor(q, factor_base)
        exponent_matrix.append(exponent_vector)
        num_smooths_found += 1
        a_list.append(a)

    kernel = _z2_gaussian_elimination(exponent_matrix)

    for i in xrange(len(kernel)):
        y = 1
        x2_exponents = [0]*num_primes
        for j in xrange(len(kernel[i])):
            if kernel[i][j]:
                y = (a_list[j]*y) % n
                for f in xrange(num_primes):
                    x2_exponents[f] += exponent_matrix[j][f]

        x = 1
        for j in xrange(num_primes):
            x *= factor_base[j]**(x2_exponents[j]//2)

        for val in [x - y, x + y]:
            d = gcd(val, n)
            if 1 < d < n:
                return d
Beispiel #20
0
def factored_xrange(a, b=None):
    """Returns an iterator over the factorizations of the numbers in [a, b).

    Given positive integers a and b with a < b, this returns an iterator over
    all pairs (n, n_factorization) with a <= n < b, and n_factorization is the
    factorization of n into prime powers. If the optional parameter b is None,
    then a is taken to be 1, and b = a.

    Input:
        * a: int (a > 0)
        * b: int (b > a) (default=None)

    Returns:
        * P: generator
            The values output by this generator are tuples (n, n_factorization),
            where n is an integer in [a, b), and n_factorization is the prime
            factorization of n.

    Examples:
        >>> list(factored_xrange(10, 20))
        [(10, [(2, 1), (5, 1)]),
         (11, [(11, 1)]),
         (12, [(2, 2), (3, 1)]),
         (13, [(13, 1)]),
         (14, [(2, 1), (7, 1)]),
         (15, [(3, 1), (5, 1)]),
         (16, [(2, 4)]),
         (17, [(17, 1)]),
         (18, [(2, 1), (3, 2)]),
         (19, [(19, 1)])]

    Details:
        All primes <= sqrt(b) are computed, and a segmented sieve is used to
        construct the factorizations of the integers in the interval [a, b).
    """
    if a < 2:
        a = 1

    if b is None:
        b, a = a, 1

    if b <= a:
        return

    block_size = int(b**(0.5))
    prime_list = primes(block_size)

    if a == 1:
        yield (1, [(1, 1)])
        a += 1

    for start in xrange(a, b, block_size):
        block = range(start, start + block_size)
        factorizations = [[] for _ in xrange(block_size)]

        for p in prime_list:
            offset = ((p * (start // p + 1) - a) % block_size) % p
            for i in xrange(offset, block_size, p):
                k = 0
                while block[i] % p == 0:
                    block[i] /= p
                    k += 1
                factorizations[i].append((p, k))

        for i in xrange(block_size):
            if start + i >= b:
                return
            if block[i] != 1:
                factorizations[i].append((block[i], 1))
            yield (start + i, factorizations[i])
Beispiel #21
0
def pollard_p_minus_1(n, limit=100000):
    r"""Attempts to find a nontrivial factor of `n`.

    Given a composite number `n` and search bound `limit`, this algorithm
    attempts to find a nontrivial factor of `n` using Pollard's p - 1
    method.

    Parameters
    ----------
    n : int (n > 1)
        Integer to be factored.

    limit : int (limit > 0) (default=100000)
        Search limit for possible prime divisors of p - 1.

    Returns
    -------
    d : int
        Divisor of n.

    Notes
    -----
    The algorithm used here is a one-stage form of Pollard's p - 1 method.
    The idea used is that if p - 1 divides Q, then p divides a^Q - 1 if (a,
    p) == 1. So if p is a prime factor of an integer n, then p divides
    gcd(a^Q - 1, n). The idea here is to choose values Q with many divisors
    of the form p - 1, and so search for many primes p as possible divisors
    at once. This is not a general purpose factoring algorithm, but this
    technique works well when n has a prime factor P such that P - 1 is
    divisible by only small primes. See chapter 6 of [2] for details.

    References
    ----------
    .. [1] R. Crandall, C. Pomerance, "Prime Numbers: A Computational
    Perspective", Springer-Verlag, New York, 2001.

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

    Examples
    --------
    >>> pollard_p_minus_1(1112470797641561909)
    1056689261L
    """
    p_list = sieves.primes(limit)
    pow_list = []

    for p in p_list:
        pk = p
        while pk <= limit:
            pow_list.append((pk, p))
            pk *= p

    pow_list.sort()
    c = 13

    for (count, (pk, p)) in enumerate(pow_list):
        c = pow(c, p, n)
        if count % 100 == 0:
            g = gcd(c - 1, n)
            if 1 < g < n:
                return g

    return gcd(c - 1, n)