2
2
Several prime number functions
3
3
"""
4
4
from math import gcd , log
5
- from typing import Any , Iterable , List , Optional , Tuple , Sequence , Set
5
+ from typing import Any , Iterator , Iterable , List , Optional , Tuple , Sequence , Set
6
6
7
7
from numpy import ones , zeros
8
8
9
9
from binary_search import binary_search , list_up_to
10
10
11
- class Primes (List [int ]):
11
+ class Primes (Sequence [int ]):
12
12
"""
13
13
List subclass that supports slicing and membership checking, automatically
14
14
generating new primes when needed
15
15
"""
16
16
17
+ def __init__ (self ) -> None :
18
+ self .primes : List [int ] = []
19
+
17
20
def __contains__ (self , item : Any ) -> bool :
18
21
"""
19
22
Check if a number is prime:
@@ -36,28 +39,38 @@ def __getitem__(self, key: Any) -> Any:
36
39
return []
37
40
38
41
if key .start is not None and len (self )- 1 < key .start :
39
- self += n_primes (key .start + 1 , list ( self ) )[len (self ):]
42
+ self . primes += n_primes (key .start + 1 , self )[len (self ):]
40
43
if key .stop is not None and len (self ) < key .stop :
41
- self += n_primes (key .stop , list ( self ) )[len (self ):]
44
+ self . primes += n_primes (key .stop , self )[len (self ):]
42
45
elif isinstance (key , int ):
43
46
if len (self )- 1 < key :
44
- self += n_primes (key + 1 , list ( self ) )[len (self ):]
47
+ self . primes += n_primes (key + 1 , self )[len (self ):]
45
48
else :
46
49
raise TypeError ()
47
50
48
- # pylint: disable=no-member
49
- return super ().__getitem__ (key )
50
- # pylint: enable=no-member
51
+ return self .primes [key ]
51
52
52
53
def index (self , prime : int , start : int = 0 , stop : Optional [int ] = None ) -> int :
53
54
"""
54
55
The index of the prime
55
56
"""
56
57
if not self or self [- 1 ] < prime :
57
- self += primes_up_to (prime , self )[len (self ):]
58
- # pylint: disable=no-member
59
- return super ().index (prime , start , stop or len (self ))
60
- # pylint: enable=no-member
58
+ self .primes += primes_up_to (prime , self )[len (self ):]
59
+ idx = binary_search (self .primes , prime , start , stop )
60
+ if idx < 0 :
61
+ raise ValueError (f"{ prime } is not prime" )
62
+ return idx
63
+
64
+ def __eq__ (self , other : Any ) -> Any :
65
+ if isinstance (other , Primes ):
66
+ other = other .primes
67
+ return self .primes == other
68
+
69
+ def __iter__ (self ) -> Iterator [int ]:
70
+ return iter (self .primes )
71
+
72
+ def __len__ (self ) -> int :
73
+ return len (self .primes )
61
74
62
75
def _first_multiple_of (num : int , above : int ) -> int :
63
76
"""
@@ -421,7 +434,7 @@ def composites_up_to(limit: int, primes: Optional[Sequence[int]] = None) -> Sequ
421
434
composites .extend (range (primes [- 1 ]+ 1 , limit + 1 ))
422
435
return composites
423
436
424
- def next_prime (primes : List [int ]) -> int :
437
+ def next_prime (primes : Sequence [int ]) -> int :
425
438
"""
426
439
Given primes, returns the next prime
427
440
0 commit comments