def test_next(self): # Test basic use of next. next = compat23.next it = iter([1, 'a']) self.assertEqual(next(it), 1) self.assertEqual(next(it), 'a') self.assertRaises(StopIteration, next, it)
def primes(strategy, start=None, end=None): """Yield primes using the given strategy function. See this module's docstring for specifications for the ``strategy`` function. If the optional arguments ``start`` and ``end`` are given, they must be either None or an integer. Only primes in the half-open range ``start`` (inclusive) to ``end`` (exclusive) are yielded. If ``start`` is None, the range begins at the lowest prime (namely 2), if ``end`` is None, the range has no upper limit. >>> from pyprimes.awful import turner >>> list(primes(turner, 6, 30)) [7, 11, 13, 17, 19, 23, 29] """ #return filter_between(gen(), start, end) it = strategy() p = next(it) if start is not None: # Drop the primes below start as fast as possible, then yield. while p < start: p = next(it) assert start is None or p >= start if end is not None: while p < end: yield p p = next(it) else: while True: yield p p = next(it)
def test_next_default(self): # Test next with a default argument. next = compat23.next it = iter([2, 'b']) self.assertEqual(next(it, -99), 2) self.assertEqual(next(it, -99), 'b') self.assertEqual(next(it, -99), -99) self.assertRaises(TypeError, next, it, -1, -2)
def test_moderate_composites(self): # Test is_probable_prime with moderate-sized composites. for i in range(10): # We should not run out of primes here. If we do, it's a bug # in the test. p, q = next(self.primes), next(self.primes) n = p*q assert n < 2**60, "n not in deterministic range for i_p_p" self.assertEqual(probabilistic.is_probable_prime(n), 0)
def test_moderate_composites(self): # Test is_probable_prime with moderate-sized composites. for i in range(10): # We should not run out of primes here. If we do, it's a bug # in the test. p, q = next(self.primes), next(self.primes) n = p * q assert n < 2**60, "n not in deterministic range for i_p_p" self.assertEqual(probabilistic.is_probable_prime(n), 0)
def test_prime_sum(self): # Test the prime_sum function by comparing it to prime_partial_sums. it = pyprimes.prime_partial_sums() for i in range(100): expected = next(it) actual = pyprimes.prime_sum(i) self.assertEqual(actual, expected)
def turner(): """Generate prime numbers very slowly using Euler's sieve. >>> p = turner() >>> [next(p) for _ in range(10)] [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] The function is named for David Turner, who developed this implementation in a paper in 1975. Due to its simplicity, it has become very popular, particularly in Haskell circles where it is usually implemented as some variation of:: primes = sieve [2..] sieve (p : xs) = p : sieve [x | x <- xs, x `mod` p > 0] This algorithm is sometimes wrongly described as the Sieve of Eratosthenes, but it is not, it is a version of Euler's Sieve. Although simple, it is extremely slow and inefficient, with asymptotic behaviour of O(N**2/(log N)**2) which is worse than trial division, and only marginally better than ``primes0``. In her paper http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf O'Neill calls this the "Sleight on Eratosthenes". """ # See also: # http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes # http://en.literateprograms.org/Sieve_of_Eratosthenes_(Haskell) # http://www.haskell.org/haskellwiki/Prime_numbers nums = itertools.count(2) while True: prime = next(nums) yield prime nums = filter(lambda v, p=prime: (v % p) != 0, nums)
def sieve(): """Yield prime integers using the Sieve of Eratosthenes. This recursive algorithm is modified to generate the primes lazily rather than the traditional version which operates on a fixed size array of integers. """ # This is based on a paper by Melissa E. O'Neill, with an implementation # given by Gerald Britton: # http://mail.python.org/pipermail/python-list/2009-January/1188529.html innersieve = sieve() prevsq = 1 table = {} i = 2 while True: # This explicit test is slightly faster than using # prime = table.pop(i, None) and testing for None. if i in table: prime = table[i] del table[i] nxt = i + prime while nxt in table: nxt += prime table[nxt] = prime else: yield i if i > prevsq: j = next(innersieve) prevsq = j**2 table[prevsq] = j i += 1
def test_primes_start(self): # Test the prime generator with start argument only. expected = [211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293] assert len(expected) == 16 it = pyprimes.primes(200) values = [next(it) for _ in range(16)] self.assertEqual(values, expected)
def test_primes_start(self): # Test the prime generator with start argument only. expected = [ 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293 ] assert len(expected) == 16 it = pyprimes.primes(200) values = [next(it) for _ in range(16)] self.assertEqual(values, expected)
def trial(generator, count, repeat=1): timer = Stopwatch() best = YEAR100 for i in range(repeat): it = generator() timer.reset() timer.start() # Go to the count-th prime as fast as possible. p = next(islice(it, count - 1, count)) timer.stop() best = min(best, timer.elapsed) return best
def test_prime_partial_sums(self): it = pyprimes.prime_partial_sums() self.assertTrue(it is iter(it)) # Table of values from http://oeis.org/A007504 expected = [ 0, 2, 5, 10, 17, 28, 41, 58, 77, 100, 129, 160, 197, 238, 281, 328, 381, 440, 501, 568, 639, 712, 791, 874, 963, 1060, 1161, 1264, 1371, 1480, 1593, 1720, 1851, 1988, 2127, 2276, 2427, 2584, 2747, 2914, 3087, 3266, 3447, 3638, 3831, 4028, 4227, 4438, 4661, 4888 ] actual = [next(it) for _ in range(len(expected))] self.assertEqual(actual, expected)
def trial(generator, count, repeat=1): timer = Stopwatch() best = YEAR100 for i in range(repeat): it = generator() timer.reset() timer.start() # Go to the count-th prime as fast as possible. p = next(islice(it, count-1, count)) timer.stop() best = min(best, timer.elapsed) return best
def test_prime_partial_sums(self): it = pyprimes.prime_partial_sums() self.assertTrue(it is iter(it)) # Table of values from http://oeis.org/A007504 expected = [ 0, 2, 5, 10, 17, 28, 41, 58, 77, 100, 129, 160, 197, 238, 281, 328, 381, 440, 501, 568, 639, 712, 791, 874, 963, 1060, 1161, 1264, 1371, 1480, 1593, 1720, 1851, 1988, 2127, 2276, 2427, 2584, 2747, 2914, 3087, 3266, 3447, 3638, 3831, 4028, 4227, 4438, 4661, 4888] actual = [next(it) for _ in range(len(expected))] self.assertEqual(actual, expected)
def nth_prime(n): """nth_prime(n) -> int Return the nth prime number, starting counting from 1. Equivalent to p[n] (p subscript n) in standard maths notation. >>> nth_prime(1) # First prime is 2. 2 >>> nth_prime(5) 11 >>> nth_prime(50) 229 """ # http://oeis.org/A000040 if n < 1: raise ValueError('argument must be a positive integer') return next(itertools.islice(primes(), n-1, n))
def test_primes_end_none(self): # Check that None is allowed as an end argument. it = pyprimes.primes(end=None) self.assertEqual(next(it), 2)
def test_primes_start_is_inclusive(self): # Start argument to primes() is inclusive. n = 211 assert pyprimes.is_prime(n) it = pyprimes.primes(start=n) self.assertEqual(next(it), n)
def check_against_known_prime_list(self, prime_maker): """Check that generator produces the first 100 primes.""" it = prime_maker() primes = [next(it) for _ in range(100)] self.assertEqual(primes, PRIMES)