Esempio n. 1
0
def gauss_circle_norm(r2, trace=False):
    """
    Return the number of lattice points in R2
    whose norm is less than or equal to r.

    O(sqrt(r2)) time complexity algorithm
    based on Jacobi's two square theorem.
    """
    retval = 0

    quotient = 0
    if trace:
        print('=1(4) divisors')
    for d in range(1, sqrtInt(r2 // 4)):
        count = (r2 // d + 3) // 4 - (r2 // (d + 1) + 3) // 4
        quotient = d
        if trace:
            print(count, quotient, '*')
        retval += count * quotient

    ub = (r2 // (quotient + 1) - 1) // 4
    prev_quot = quotient

    for i in range(ub, -1, -1):
        quotient = r2 // (4 * i + 1)
        if quotient == prev_quot:
            continue
        if trace:
            print(1, quotient)
        retval += quotient

    if trace:
        print('=3(4) divisors')
    quotient = 0
    for d in range(1, sqrtInt(r2 // 4)):
        count = (r2 // d + 1) // 4 - (r2 // (d + 1) + 1) // 4
        quotient = d
        if trace:
            print(count, quotient, '*')
        retval -= count * quotient
    ub = (r2 // (quotient + 1) - 1) // 4
    prev_quot = quotient

    for i in range(ub, -1, -1):
        quotient = r2 // (4 * i + 3)
        if quotient == prev_quot:
            continue
        if trace:
            print(1, quotient)
        retval -= quotient

    retval *= 4

    return retval + 1  # don't forget the origin
def principal_representations(n, m):
    """
    yield a sequence of positive (a, b) such that
    a**2 + n * b**2 = m
    """
    ub = sqrtInt(m / n)
    ii = 0
    while ii <= ub:
        xx = m - n * ii**2
        if issq(xx):
            yield sqrtInt(xx), ii
        ii += 1
Esempio n. 3
0
def sievecntsum(n, p=None):
    """
    Return both the count and the sum of the
    numbers not excluded by a sieve of [1..n]
    by all primes up to and including p.
    """
    if p is None:
        p = sqrtInt(n)
    V = [n // i for i in range(1, p + 1)]
    V += list(range(V[-1] - 1, 0, -1))
    S0 = {i: i - 1 for i in V}
    S1 = {i: i * (i + 1) // 2 - 1 for i in V}
    SP = {i: i * (i + 1) // 2 - 1 for i in V}

    for p in chain([2], range(3, p + 1, 2)):
        if S0[p] > S0[p - 1]:  # p is prime
            p2 = p * p
            for v in V:
                if v < p2:
                    break
                vmodp = v // p
                D0 = S0[vmodp] - S0[p - 1]
                D1 = S1[vmodp] - S1[p - 1]
                S0[v] -= D0
                S1[v] -= p * D1
                SP[v] -= p * (D1 - D0)
    return S0[n], S1[n], SP[n]
Esempio n. 4
0
def fundamental_unit_old(d):
    if d <= 1:
        raise ValueError('%d is not >= 2' % (d, ))
    b = 1
    while True:
        if issq(b * b * d - 4):
            a = sqrtInt(b * b * d - 4)
            break
        if issq(b * b * d + 4):
            a = sqrtInt(b * b * d + 4)
            break
        b += 1
    if d % 4 == 1:
        return QuadInt(d, (a - b) / 2, b)
    else:
        return QuadInt(d, a / 2, b / 2)
Esempio n. 5
0
def sum_sigma1(n):
    r"""
    :param n: a positive integer
    :return: :math:`\displaystyle\sum_{k\in[1\dots n]} \sigma(k)`
    """
    sqrtk = sqrtInt(n)
    part1 = sum(d * (n // d) for d in range(1, n // sqrtk + 1))
    part2 = sum(sumrange(n // (d + 1), n // d) * d for d in range(1, sqrtk))
    return part1 + part2
Esempio n. 6
0
def sieve(n):
    """
    Return the list of primes in [2..n]
    """
    S = np.ones((n + 1, ), dtype=bool)
    S[0] = False
    S[1] = False
    p = 2
    sqrtn = sqrtInt(n)
    while p <= sqrtn:
        if S[p]:
            S[2 * p::p] = False
        p += 1
    return filter(lambda pp: S[pp], range(n + 1))
Esempio n. 7
0
def _partial_totient_alternate(n, k):
    r"""
    :param n: a positive integer
    :return: the number of integers in [1..n]
             that are relatively prime to k
    """
    if n == 0:
        return 0
    kps = [p for (p, _) in factorize2(k)]
    V = [n // i for i in range(1, sqrtInt(n) + 1)]
    V += list(range(V[-1] - 1, -1, -1))
    S1 = {i: i for i in V}
    for p in kps:
        for v in V:
            if v < p:
                break
            S1[v] -= S1[v // p]
    return S1[n]
Esempio n. 8
0
def sievesum(n, p=None):
    """
    Return the sum of all numbers not excluded
    by a sieve of [1..n] by all primes up to
    and including p.
    """
    if p is None:
        p = sqrtInt(n)
    V = [n // i for i in range(1, p + 1)]
    V += list(range(V[-1] - 1, 0, -1))
    S = {i: i * (i + 1) // 2 - 1 for i in V}
    for p in range(2, p + 1):
        if S[p] > S[p - 1]:  # p is prime
            sp = S[p - 1]  # sum of primes smaller than p
            p2 = p * p
            for v in V:
                if v < p2:
                    break
                S[v] -= p * (S[v // p] - sp)
    return S[n]
Esempio n. 9
0
def sievecnt(n, p=None):
    """
    Return the count of numbers not excluded
    by a sieve of [1..n] by all primes up to
    and including p.  If p is not given then
    sieve up to sqrt(n). 
    """
    if p is None:
        p = sqrtInt(n)

    V = [n // i for i in range(1, p + 1)]
    V += list(range(V[-1] - 1, 0, -1))
    S = {i: i - 1 for i in V}
    for p in range(2, p + 1):
        if S[p] > S[p - 1]:  # p is prime
            sp = S[p - 1]  # number of primes smaller than p
            p2 = p * p
            for v in V:
                if v < p2:
                    break
                S[v] -= (S[v // p] - sp)
    return S[n]
Esempio n. 10
0
def sievecntsum(n):
    p = sqrtInt(n)
    if (p + 1)**2 <= n:
        p += 1
    V = [n // i for i in range(1, p + 1)]
    V += list(range(V[-1] - 1, 0, -1))
    S0 = {i: i - 1 for i in V}
    S1 = {i: i * (i + 1) // 2 - 1 for i in V}
    SP = {i: i * (i + 1) // 2 - 1 for i in V}
    for p in range(2, p + 1):
        if S0[p] > S0[p - 1]:  # p is prime
            p2 = p * p
            for v in V:
                if v < p2:
                    break
                vmodp = v // p
                D0 = S0[vmodp] - S0[p - 1]
                D1 = S1[vmodp] - S1[p - 1]
                S0[v] -= D0
                S1[v] -= p * D1
                SP[v] -= p * (D1 - D0)
    return S0[n], S1[n], SP[n]
Esempio n. 11
0
def segmented_sieve(n, trace=False):
    """
    Return the list of all prime numbers
    less than or equal to n.  Runtime
    complexity of O(n) (or a bit better)
    with space complexity of O(sqrt(n)).
    """
    if n <= 2:
        if n == 2:
            yield 2
        return

    seglen = sqrtInt(n + 1)

    # always make seglen a multiple of 6
    # add 6 so that the first segment contains sqrt(n)
    seglen = max(6, 6 * (seglen // 6)) + 6

    wheel = [4, 2]
    wheel_len = len(wheel)

    if trace:
        print('segment length = %d' % (seglen, ))
    nsegs = (n + 1) // seglen
    if seglen * nsegs < n + 1:
        nsegs += 1
    if trace:
        print('number of segments = %d' % (nsegs, ))
    ps = [2, 3]
    for p in ps:
        yield p
    segi = 0
    seg_start = 0
    seg = np.ones((seglen, ), dtype=np.int8)
    seg[:4] = [0, 0, 1, 1]

    while segi < nsegs:
        seg_end = seg_start + seglen - 1

        if trace:
            print('segment number = %d' % (segi, ))
            print('segment start = %d' % (seg_start, ))
            print('segment end = %d' % (seg_end, ))

        ub = math.sqrt(seg_end)
        for p in ps:
            if p > ub:
                break
            zeroit(seg, (p - seg_start) % p, p)
            if trace:
                print(p, '%s' % (seg, ))

        starti = 1
        endi = min(seglen, ub - seg_start + 1)
        stepi = 2

        i = starti
        wheeli = 0
        while i < endi:
            if seg[i]:
                p = seg_start + i
                yield p
                if segi == 0:
                    ps.append(p)
                zeroit(seg, p * p - seg_start, p)
                if trace:
                    print(p, '%s' % (seg, ))
            i += wheel[wheeli]  # stepi
            wheeli = (wheeli + 1) % wheel_len

        maxi = min(seglen, n - seg_start + 1)
        while i < maxi:
            if seg[i]:  # seq_start+i is prime
                p = seg_start + i
                yield p
                if segi == 0:
                    ps.append(p)
            i += wheel[wheeli]
            wheeli = (wheeli + 1) % wheel_len

        segi += 1
        seg_start += seglen
        seg[:] = 1
Esempio n. 12
0
def bps_facts_w_rep_powerful(n, ps):
    """
    n: the integer upper bound
    ps: the list of primes

    yields: all factorized integers [(p1, e1), ..., (pk, ek)]
        where p1**e1 * ... * pk**ek <= n and all pi are
        from the list ps

    Note: the implementation is iterative, and not recursive,
    and so is suitable for cases where ps is large (i.e. cases
    where the stack would normally grow to the size of ps)
    """
    num_primes = len(ps)
    if n < 1:
        return
    yield []
    val = [[ps[-1], num_primes - 1, 2, n // (ps[-1]**2)]]
    while True:
        yield [(v[0], v[2]) for v in val]
        #
        # find the largest prime that is
        # 1) as large or larger than the
        #    primes already in the factorization, and
        # 2) less than what is left
        #
        pi = num_primes - 1
        p = ps[pi]
        last_val = val[-1]
        last_p = last_val[0]
        last_pi = last_val[1]
        last_n = last_val[3]
        sqrt_last_n = sqrtInt(last_n)
        lb = max(last_p, sqrt_last_n)
        if last_p > last_n:  # sqrt_last_n:
            pi = last_pi - 1
            if pi >= 0:
                p = ps[pi]
        else:
            while p > lb:
                pi -= 1
                if pi < 0:
                    break
                p = ps[pi]
            if p == last_p and p > last_n:
                pi -= 1
                if pi >= 0:
                    p = ps[pi]
        if pi < 0:
            return

        #
        # if there is no such prime, we have to back
        # track over the previous prime used.
        #
        if p < last_p:  # if there is not an add'l prime
            pi = last_val[1] - 1
            p = ps[pi]
            if len(val) == 1:
                last_val[:] = [p, pi, 2, n // (p * p)]
            else:
                del val[-1]
                last_val = val[-1]
                if p == last_val[0]:
                    last_val[2] += 1
                    last_val[3] //= p
                else:
                    val.append([p, pi, 2, last_val[3] // (p * p)])
        elif p == last_p:  # we can divide by our prime again
            last_val[2] += 1
            last_val[3] //= p
        else:
            val.append([p, pi, 2, last_n // (p * p)])