-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path__init__.py
173 lines (127 loc) · 4.58 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
r"""
Python interface to Frank Lübeck's Conway polynomial database
First, call ``database()`` to load the database into a python
dictionary, and then look up the coefficients of your polynomial using
two keys ``p`` (your prime) and ``n`` (your degree). The following
results for ``p=2`` can be found at,
https://www.math.rwth-aachen.de/~Frank.Luebeck/data/ConwayPol/CP2.html
::
>>> import conway_polynomials
>>> cpdb = conway_polynomials.database()
>>> p = 2; n = 5
>>> cpdb[p][n]
(1, 0, 1, 0, 0, 1)
>>> p = 2; n = 17
>>> cpdb[p][n]
(1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
>>> p = 23; n = 19
>>> cpdb[p][n]
(18, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
>>> p = 307; n = 1
>>> cpdb[p][n]
(302, 1)
>>> p = 40013; n = 2
>>> cpdb[p][n]
(2, 40009, 1)
If ``n`` is the degree of our polynomial, there should be ``n+1``
coefficients, the last of which is unity by definition::
>>> from random import choice
>>> p = choice(list(cpdb.keys()))
>>> n = choice(list(cpdb[p].keys()))
>>> len(cpdb[p][n]) == n + 1
True
>>> cpdb[p][n][n] == 1
True
"""
from typing import Optional, TextIO
def _parse_line(l: str) -> tuple[int, int, tuple[int,...]]:
r"""
Parse a single line (not the first or the last) from Frank
Lübeck's data file.
According to Frank's webpage, each line has the form,
[p, n, [a0, a1, ..., 1]],
and corresponds to a single Conway polynomial with prime p and
degree n. In reality, there are no spaces in the data.
Parameters
----------
l : str
A line from the data file.
Returns
-------
tuple[int, int, tuple[int,...]]
A triplet ``(p, n, coeffs)``, where ``p`` and ``n`` are python
integers representing the prime and degree of this polynomial,
respectively, and ``coeffs`` is a tuple of its coefficients.
"""
# Remove all of the brackets, the trailing comma, and the trailing
# newline to obtain "p, n, a0, a1, ..., 1".
l = l.replace("[","")[:-4]
# Now we know that p and n are the first two (CSV) fields, and
# that the coefficients are whatever's left.
fields = l.split(",")
# Convert everything to integers before returning.
p = int(fields[0])
n = int(fields[1])
coeffs = tuple( int(c) for c in fields[2:] )
return (p, n, coeffs)
def _open_database() -> TextIO:
r"""
Open the database, possibly xz compressed.
Typically, the build/install process for the package will compress
the database and remove the uncompressed copy. During development,
however, it would be annoying to have to build/install the package
to a temporary location before the test suite could be run. For
that reason we retain the uncompressed filename as a fallback.
Returns
-------
file : TextIO
A file-like object, opened for reading in text mode, representing the
database.
"""
import lzma
from importlib.resources import as_file, files
from io import TextIOWrapper
dbpath = files('conway_polynomials').joinpath('CPimport.txt')
with as_file(dbpath) as p:
try:
# Open as binary and wrap in TextIO to guarantee
# that the return type is correct.
return TextIOWrapper(lzma.open(p.with_suffix(".txt.xz")))
except FileNotFoundError:
return open(p, "r")
_conway_dict: Optional[ dict[int,dict[int,tuple[int,...]]] ]
_conway_dict = None # cached result of database()
def database() -> dict[int,dict[int,tuple[int,...]]]:
r"""
Load (if necessary) and return a dict of pre-computed Conway
polynomial coefficients.
The result is cached.
Returns
-------
dict
A dictionary of the form ``{p: {n: coefficients}}``, where ``p``
is a prime, ``n`` is a degree, and ``coefficients`` is a tuple
of coefficients. The coefficients are listed in "ascending"
order; that is, they are indexed by the degree of the monomial
they sit in front of.
"""
global _conway_dict
if _conway_dict is not None:
return _conway_dict
_conway_dict = {}
with _open_database() as f:
# The first line of the file is "allConwayPolynomials := ["
f.readline()
for line in f:
if line[0] == "0":
# This is the last line in the file; otherwise it would
# start with a square bracket.
break
(p, n, coeffs) = _parse_line(line)
if p not in _conway_dict:
_conway_dict[p] = {}
_conway_dict[p][n] = coeffs
return _conway_dict
if __name__ == "__main__":
import doctest
doctest.testmod()