;
~FFc@sdZeZdfdYZdefdYZdefdYZdefdYZd Zd
kl Z dee fdYZ
e
ZeiZei
Zd
ZdklZlZlZlZlZfeedZdZdS(sCached prime numbers.
This module provides an object, primes, which masquerades as the infinite list
of all primes, in their proper order. If you ask it how long it is, it'll be
finite, but if you ask for an element past the `end' you'll still get it (though
you may have to wait). Ask for its last element and you'll get some prime: ask
whether some bigger prime is in the list and the answer will be yes, none the
less.
Building on that, this module also provides facilities for factorisation and
multiplying back together again:
prodict(dict) -- product of pow(key, dict[key])
factorise(numb) -- returns a dictionary, which prodict will map to numb: its
keys are irreducible (so generally primes, but -1, at least, may also appear).
See also generic integer manipulators in natural.py, combinatorial tools in
permute.py and polynomials in polynomial.py: some day, it'd be fun to do some
stuff with prime polynomials ...
$Id: primes.py,v 1.15 2007/05/06 11:48:08 eddy Exp $
s lazyTuplecBstZdZedZdZdZdZeZdZ dZ
dZdZd Z
d
ZdZdZRS(
sEvaluation on demand of a (possibly infinite) tuple.
Some of what's in this class should be split out into _Prime, below.
cCs^|tjo
g}n||_y|d}Wn|ij
o
d}nXd||_dS(sNInitialises a lazy Tuple.
Optional argument, row, should be a sorted list.
iiiN(srowsNonesselfs
_item_carrierstops
_entry_error_s_ask(sselfsrowstop((s(/home/eddy/.sys/py/study/maths/primes.pys__init__ s
cCsSt|i
}t|djo|d d|dSn|d d|dSdS(Niis...s, ...(stuplesselfs
_item_carrierstextslen(sselfstext((s(/home/eddy/.sys/py/study/maths/primes.pys__repr__,scCst|iSdS(N(slensselfs
_item_carrier(sself((s(/home/eddy/.sys/py/study/maths/primes.pys__len__1scCs:x(|t|ijo
|ioqW|i|SdS(N(skeyslensselfs
_item_carriersgrow(sselfskey((s(/home/eddy/.sys/py/study/maths/primes.pys__getitem__4s#ccs+d}xto||Vd|}q WdS(Nii(sisTruesself(sselfsi((s(/home/eddy/.sys/py/study/maths/primes.pys__iter__;s
cCs6|djp
|djo
tn|i||!SdS(s self[i:j]iN(sisjs
IndexErrorsselfs
_item_carrier(sselfsisj((s(/home/eddy/.sys/py/study/maths/primes.pys__getslice__As
cCs6x"||ijo
|ioqW||ijSdS(s3Is val in self ?
Override this in base-classes.
N(svalsselfs_asksgrows
_item_carrier(sselfsval((s(/home/eddy/.sys/py/study/maths/primes.pys__contains__Gs
cCs||jodSndSdS(Nii(sitemsself(sselfsitem((s(/home/eddy/.sys/py/study/maths/primes.pyscountOs
cCs)||jo|ii|SndSdS(Ni(sitemsselfs
_item_carriersindex(sselfsitem((s(/home/eddy/.sys/py/study/maths/primes.pysindexSs
cCs|idSdS(Ni(sselfs
_item_carrier(sself((s(/home/eddy/.sys/py/study/maths/primes.pysminYscCs|idSdS(Ni(sselfs
_item_carrier(sself((s(/home/eddy/.sys/py/study/maths/primes.pysmax\scCs.|i}|ii|d||_|SdS(sExtend self._item_carrier, return true on success.
Over-ride this method in derived classes - don't call this one.
It implements lazy range(infinity).
iN(sselfs_asksresults
_item_carriersappend(sselfsresult((s(/home/eddy/.sys/py/study/maths/primes.pysgrow_s
(s__name__s
__module__s__doc__sNones__init__s__repr__s__len__s__getitem__s__call__s__iter__s__getslice__s__contains__scountsindexsminsmaxsgrow(((s(/home/eddy/.sys/py/study/maths/primes.pys lazyTuples slistcBstZeiZdZRS(NcCs|i|i||SdS(N(sselfs __class__s_list__upgetslsisj(sselfsisj((s(/home/eddy/.sys/py/study/maths/primes.pys__getslice__ms(s__name__s
__module__slists__getslice__s_list__upgetsl(((s(/home/eddy/.sys/py/study/maths/primes.pyslistjs s risingSetcBs/tZeiZedZeiZdZRS(NcCs|i|pgdS(N(sselfs_risingSet__upinitsval(sselfsval((s(/home/eddy/.sys/py/study/maths/primes.pys__init__rscCs||p|d|jo|g|d*nO|d|jo|i|n-||jodt|df\}}x|d|jo||d}||jo
|jnp
td||||jo||jnp
td|||jo
|}n|}|||jo||jnp
tdqxW|d|jp
td|i||ndS( Niiiis
arithmeticsprior ordersbinary chop missedsbinary chop mis-terminating( sselfsvalsappendslensbotstopsatsAssertionErrors_risingSet__upins(sselfsvalsbotsatstop((s(/home/eddy/.sys/py/study/maths/primes.pysinsertvs"
(4
5(s__name__s
__module__slists__init__s_risingSet__upinitsNonesinserts_risingSet__upins(((s(/home/eddy/.sys/py/study/maths/primes.pys risingSetps s_PrimecBstZdZdZeedZdZdZdZdZ dZ
dZed Zed
Z
edZdZd
ZRS(szList of all primes, generated as needed.
Needs to use a paged-in-and-out item carrier. Use that to do cacheing.
s
From Tuple, this inherits ._item_carrier in which we store all the primes
less than ._ask, which is the next number we're going to check to see if
it's prime. Any higher primes we've discovered (usually thanks to
factorise(), see below) are kept in _sparse (in their correct order, albeit
probably with gaps). All currently known primes may be listed as .known().
self._ask will be an ordinary integer as long as it can, then switch over to
being a long one. Entries in .known() will be ordinary integers most of the
time, unless they are so big they must be long(). However, some entries
which could be ordinary may still be long().
cCs_|tjo
dg}n|o|idnti||d|_t||_ dS(Ni(
srowsNonesappends lazyTuples__init__sselfs_sqrts risingSetssparses_sparse(sselfsrowssparse((s(/home/eddy/.sys/py/study/maths/primes.pys__init__s
cCsd|iiSdS(Ns%s()(sselfs __class__s__name__(sself((s(/home/eddy/.sys/py/study/maths/primes.pys__repr__scCsKt|djo'dt|d dd!|dfSnti|SdS(Nis
(%s, ..., %s)ii(slensselfsstrs lazyTuples__repr__(sself((s(/home/eddy/.sys/py/study/maths/primes.pys__str__s'cCs|i|iSdS(N(sselfs
_item_carriers_sparse(sself((s(/home/eddy/.sys/py/study/maths/primes.pysknownscCs|iSdS(s:Returns a number about which self would like to be asked. N(sselfs_ask(sself((s(/home/eddy/.sys/py/study/maths/primes.pysaskscCsd}xno||i|jp
||ijo|Sn||ijotSnx=|i|D].}||djotSnt|i}qbW|id}t |||jo|i
|Snx<|iD]1}||djotSn||joPqqW|ioPq qWxYnoQ|i}||djotSnt |||jo|i
|Sq#q*WdS(Niii(
sseensnumsselfs
_item_carriers_sparses_asksNonespslenslongs_knows get_cachesgrow(sselfsnumspsseen((s(/home/eddy/.sys/py/study/maths/primes.pys__contains__s<$
cCs|i|djod|d|_n|i}x|d|jo|i|ijo|iq5x|iD]v}|i|djo|iPn||ijoqqnt |||ijo|iPqq|d|_qqWq5W|idSdS(Niii(
sselfs_askswass_sparses_knows
_item_carriersps
_Prime__throws_sqrtslong(sselfspswas((s(/home/eddy/.sys/py/study/maths/primes.pysgrows&
cCs.|t|ifjod|i|_ndS(sRecords a non-prime.
Argument, other, defaults to self._ask: it must not be a prime. The
only time it matters is when it's self._ask: which is then stepped
forward to the next integer. iN(sothersNonesselfs_ask(sselfsother((s(/home/eddy/.sys/py/study/maths/primes.pys__throwscCs|p
||ijo||ii|i|i|ijo<|i|idjptd|i|id|_n|i}d||_nT||ijp
||ijo2|i|jptd||ii|n|SdS(sRecords a prime.
Argument, other, defaults to self._ask: it must be a prime. If it is
self._ask, we append it and advance _ask. Otherwise, if it isn't
already in self or _sparse, we add it to _sparse in its proper place.
is$sparse primes array disordered at %dis%missed out a prime, %d, in the searchN(sothersselfs_asks
_item_carriersappends_sparsesAssertionErrorsinsert(sselfsother((s(/home/eddy/.sys/py/study/maths/primes.pys_knows( !cCsW|tjo
h}n"|}|iddo|Sn|djo)|idddd|d<|}n|dt|otd|fn|djo|id|dx;|i|iD]%}||ptd||fqWn|i|qWWn*tj
o}td||inXto8|i|i}||it| jp
tdn|i|i|i)x6|io|id|ijo|id|_qW|io|id|id jptd
|iddSdS(seLoads data that's been imported from a file.
Argument, found, is the module object as which the file was imported: it
should have integer attributes, found.at and found.to and list
attributes found.sparse and found.block, with each member of sparse
greater than any member of block, and at+len(block)==to. The given
block is used as self[at:to], while entries in sparse are added to
_sparse in their right order.
The bits of the file we'll examine are variables in the global scope
with names 'at', 'to', 'sparse' and 'block'. Most of this function
checks things, the actual loading is quite brief ! sinconsistent load-files;new slice, [%d:], does not meet up with what we have, [:%d]s-mis-ordered loading of cache-files (%d > %d).s#alleged prime, %d, has a factor, %ds#cache-file lacks necessary variables5new block of primes doesn't match what I know alreadyiiis'sparse prime, %d, missed in "full" listN(slensselfs
_item_carrierssizesfoundstosblocksatsAssertionErrorssparsesitems_sparsescheckingsps_knowsAttributeErrorswhatsargsstest(sselfsfoundswhatspsitemstestssize((s(/home/eddy/.sys/py/study/maths/primes.pys_loads4*''
'(!;cCsd|idSdS(Nii(sselfs
_item_carrier(sselfsig((s(/home/eddy/.sys/py/study/maths/primes.pys_lazy_get__ask_4scCs[y3x,|i|idjo|id|_qWWntj
onX|i|iSdS(Nii(sselfs_cachePrimes__steps_cachePrimes__high_waters
OverflowError(sself((s(/home/eddy/.sys/py/study/maths/primes.pys
_next_high7sc Cs.dk}|ii|i|}|d}|i}x|t |i
jo||i
d|
d}|p|ii|ot|d}zY|idd|i
d|
d |i
d
gt||i
|i|!|idWd|iX|i||n||_|i}q:WdS(sjRecords `most' of what the primes module knows in files for later reference.
Arguments are all optional:
name -- name-stem for cache files. Default is 'c'.
force -- flag, default is false. Normally, persist() trusts files
already in the cache and doesn't bother re-writing them: set force to
some true value to make all the files be written anew.
Updates the cache. Each cache file contains a sub-list of the known
primes: small primes are recorded in files with 1024 entries, but
subsequent sub-lists are longer (by a factor of 2 whenever the
chunk-size gets bigger than an eighth of the number of primes in all
earlier cache files). Each cache-file's name expresses the range of
indices it contains: this information is also present in the cache-file,
along with the current value of _sparse. The block of primes stored in
the file is formatted to be readable on an 80-column display. The data
are stored in the file under the names
at -- index, in self, of first prime in block
to -- index, in self, of first prime after block
sparse -- current _sparse list
block -- self[at:to]
Ns.tmps-s.pysws)"""Persistence data for primes module."""s
at = s
to = s
sparse = s
block = [s
]
(sosspathsjoinsselfsprime_cache_dirsnamestmpfiles
_next_highsnewslens
_item_carriers_cachePrimes__high_watersoutfilesforcesexistssopensfiles
writeliness_sparses_tabulate_blockswritesclosesrename(sselfsnamesforcestmpfilesoutfilesfilesnewsos((s(/home/eddy/.sys/py/study/maths/primes.pyspersist>s(
. (s__name__s
__module__s_Primes__init__s_cachePrimes__upinitsNones nosuchdirs_lazy_get_prime_cache_dir_s_lazy_get__caches_sDummys
_do_imports get_caches_loads_lazy_get__ask_s
_next_highspersist(((s(/home/eddy/.sys/py/study/maths/primes.pyscachePrimess < cCs/tdtt|i|idSdS(s\Returns the product of a factorisation dictionary.
Argument, dict, is a dictionary whose keys are multipliable and whose values
are powers to which one may sensibly raise these keys. The result is the
same as would result from
answer = 1
for key, val in dict.items():
answer = answer * pow(key, val)
return answer
This implementation uses reduce() and map(). This might be more efficient
than doing it as above, but I don't know. It's only really here to give me
a handy way to do the inverse of factorise(), above.
See also, in module basEddy.quantity: adddict, subdict and scaledict. They
and this may one day migrate elsewhere to be together. We get:
* prodict(adddict(a,b)) = prodict(a) * prodict(b),
* prodict(subdict(a,b)) = prodict(a) / prodict(b),
* prodict(scaledict(d,n)) = pow(prodict(d), n).
cCs||S(N(sasb(sasb((s(/home/eddy/.sys/py/study/maths/primes.pyssiN(sreducesmapspowsdictskeyssvalues(sdict((s(/home/eddy/.sys/py/study/maths/primes.pysprodict}s(s TupleTypesListTypes FloatTypesIntTypesLongTypecCs|tjo
h}ny=t|djo
|}n|d}|d|d fWnttttfj
o|p
|djo
|}n
t
i}t|t
joVyt|}Wntj
ot|}nX||jo
tdn|}nt
i||}nQX|}xF|D]>}y||Wq(tj
ot|dt||
cCsD|djo|}hdd<}nh}ti|}t|i|d