March 2014 update

This commit is contained in:
Ingy döt Net 2014-04-02 16:56:35 +00:00
parent 09687c4926
commit a25938f123
1846 changed files with 21876 additions and 5203 deletions

View file

@ -1,7 +1,18 @@
from __future__ import print_function
import sys
from itertools import islice, cycle, count
try:
from itertools import compress
except ImportError:
def compress(data, selectors):
"""compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F"""
return (d for d, s in zip(data, selectors) if s)
def is_prime(n):
return zip((True, False), decompose(n))[-1][0]
return list(zip((True, False), decompose(n)))[-1][0]
class IsPrimeCached(dict):
def __missing__(self, n):
@ -11,24 +22,54 @@ class IsPrimeCached(dict):
is_prime_cached = IsPrimeCached()
def primes():
yield 2
n = 3
while n < sys.maxint - 2:
yield n
n += 2
while n < sys.maxint - 2 and not is_prime_cached[n]:
n += 2
def croft():
"""Yield prime integers using the Croft Spiral sieve.
This is a variant of wheel factorisation modulo 30.
"""
# Copied from:
# https://code.google.com/p/pyprimes/source/browse/src/pyprimes.py
# Implementation is based on erat3 from here:
# http://stackoverflow.com/q/2211990
# and this website:
# http://www.primesdemystified.com/
# Memory usage increases roughly linearly with the number of primes seen.
# dict ``roots`` stores an entry x:p for every prime p.
for p in (2, 3, 5):
yield p
roots = {9: 3, 25: 5} # Map d**2 -> d.
primeroots = frozenset((1, 7, 11, 13, 17, 19, 23, 29))
selectors = (1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0)
for q in compress(
# Iterate over prime candidates 7, 9, 11, 13, ...
islice(count(7), 0, None, 2),
# Mask out those that can't possibly be prime.
cycle(selectors)
):
# Using dict membership testing instead of pop gives a
# 5-10% speedup over the first three million primes.
if q in roots:
p = roots[q]
del roots[q]
x = q + 2*p
while x in roots or (x % 30) not in primeroots:
x += 2*p
roots[x] = p
else:
roots[q*q] = q
yield q
primes = croft
def decompose(n):
for p in primes():
if p*p > n: break
while n % p == 0:
yield p
n /=p
n //=p
if n > 1:
yield n
if __name__ == '__main__':
# Example: calculate factors of Mersenne numbers to M59 #
@ -36,10 +77,10 @@ if __name__ == '__main__':
for m in primes():
p = 2 ** m - 1
print( "2**{0:d}-1 = {0:d}, with factors:".format(m, p) )
print( "2**{0:d}-1 = {1:d}, with factors:".format(m, p) )
start = time.time()
for factor in decompose(p):
print factor,
print(factor, end=' ')
sys.stdout.flush()
print( "=> {0:.2f}s".format( time.time()-start ) )

View file

@ -1,21 +1,27 @@
primelist = [2, 3]
def is_prime(n):
if n in primelist: return True
if n < primelist[-1]: return False
from math import floor, sqrt
try:
long
except NameError:
long = int
for y in primes():
if not n % y: return False
if n < y * y: return True
def fac(n):
step = lambda x: 1 + x*4 - (x//2)*2
maxq = long(floor(sqrt(n)))
d = 1
q = n % 2 == 0 and 2 or 3
while q <= maxq and n % q != 0:
q = step(d)
d += 1
res = []
if q <= maxq:
res.extend(fac(n//q))
res.extend(fac(q))
else: res=[n]
return res
def primes():
for n in primelist: yield n
n = primelist[-1]
while True:
n += 2
for x in primelist:
if not n % x: break
if x * x > n:
primelist.append(n)
yield n
break
if __name__ == '__main__':
import time
start = time.time()
tocalc = 2**59-1
print("%s = %s" % (tocalc, fac(tocalc)))
print("Needed %ss" % (time.time() - start))