Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/libs/ratpoints.pyx
8815 views
1
r"""
2
Hyperelliptic Curve Point Finding, via ratpoints.
3
4
"""
5
6
cdef int process(long x, long z, mpz_t y, void *info0, int *quit):
7
# ratpoints calls this function when it finds a point [x : y : z]
8
# info0 is the pointer passed to ratpoints originally
9
# if quit[0] is set to a nonzero value, ratpoints will abort immediately
10
cdef point_list *plist = <point_list *> info0
11
cdef long i
12
if plist.array_size == plist.num_points:
13
i = plist.array_size
14
plist.array_size *= 2
15
plist.xes = <long *> sage_realloc(plist.xes, plist.array_size * sizeof(long))
16
plist.ys = <mpz_t *> sage_realloc(plist.ys, plist.array_size * sizeof(mpz_t))
17
plist.zs = <long *> sage_realloc(plist.zs, plist.array_size * sizeof(long))
18
while i < plist.array_size:
19
mpz_init(plist.ys[i])
20
i += 1
21
plist.xes[plist.num_points] = x
22
mpz_set(plist.ys[plist.num_points], y)
23
plist.zs[plist.num_points] = z
24
plist.num_points += 1
25
if plist.max_num_points > 0:
26
if plist.max_num_points == plist.num_points:
27
quit[0] = -1
28
return 1 # weight for counting the points
29
30
def ratpoints(list coeffs, long H, verbose=False, long max=0,
31
min_x_denom=None, max_x_denom=None, intervals=[]):
32
"""
33
Access the ratpoints library to find points on the hyperelliptic curve:
34
35
`y^2 = a_n x^n + \cdots + a_1 x + a_0.`
36
37
INPUT::
38
39
coeffs -- list of integer coefficients a_0, a_1, ..., a_n
40
41
H -- the bound for the denominator and the absolute value of the
42
numerator of the x-coordinate
43
44
verbose -- if True, ratpoints will print comments about its progress
45
46
max -- maximum number of points to find (if 0, find all of them)
47
48
OUTPUT::
49
50
The points output by this program are points in (1, ceil(n/2), 1)-weighted
51
projective space. If n is even, then the associated homogeneous equation is
52
`y^2 = a_n x^n + \cdots + a_1 x z^{n-1} + a_0 z^n` while if n is odd, it is
53
`y^2 = a_n x^n z + \cdots + a_1 x z^n + a_0 z^{n+1}`.
54
55
EXAMPLE::
56
57
sage: from sage.libs.ratpoints import ratpoints
58
sage: for x,y,z in ratpoints([1..6], 200):
59
... print -1*y^2 + 1*z^6 + 2*x*z^5 + 3*x^2*z^4 + 4*x^3*z^3 + 5*x^4*z^2 + 6*x^5*z
60
0
61
0
62
0
63
0
64
0
65
0
66
0
67
sage: for x,y,z in ratpoints([1..5], 200):
68
... print -1*y^2 + 1*z^4 + 2*x*z^3 + 3*x^2*z^2 + 4*x^3*z + 5*x^4
69
0
70
0
71
0
72
0
73
0
74
0
75
0
76
0
77
78
sage: for x,y,z in ratpoints([1..200], 1000):
79
... print x,y,z
80
1 0 0
81
0 1 1
82
0 -1 1
83
201 25353012004564588029934064107520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 200
84
201 -25353012004564588029934064107520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 200
85
86
The denominator of `x` can be restricted, for example to find
87
integral points::
88
89
sage: from sage.libs.ratpoints import ratpoints
90
sage: coeffs = [400, -112, 0, 1]
91
sage: ratpoints(coeffs, 10^6, max_x_denom=1, intervals=[[-10,0],[1000,2000]])
92
[(1, 0, 0), (-8, 28, 1), (-8, -28, 1), (-7, 29, 1), (-7, -29, 1),
93
(-4, 28, 1), (-4, -28, 1), (0, 20, 1), (0, -20, 1), (1368, 50596, 1),
94
(1368, -50596, 1), (1624, 65444, 1), (1624, -65444, 1)]
95
96
sage: ratpoints(coeffs, 1000, min_x_denom=100, max_x_denom=200)
97
[(1, 0, 0),
98
(-656, 426316, 121),
99
(-656, -426316, 121),
100
(452, 85052, 121),
101
(452, -85052, 121),
102
(988, 80036, 121),
103
(988, -80036, 121),
104
(-556, 773188, 169),
105
(-556, -773188, 169),
106
(264, 432068, 169),
107
(264, -432068, 169)]
108
109
Finding the integral points on the compact component of an elliptic curve::
110
111
sage: E = EllipticCurve([0,1,0,-35220,-1346400])
112
sage: e1, e2, e3 = E.division_polynomial(2).roots(multiplicities=False)
113
sage: coeffs = [E.a6(),E.a4(),E.a2(),1]
114
sage: ratpoints(coeffs, 1000, max_x_denom=1, intervals=[[e3,e2]])
115
[(1, 0, 0),
116
(-165, 0, 1),
117
(-162, 366, 1),
118
(-162, -366, 1),
119
(-120, 1080, 1),
120
(-120, -1080, 1),
121
(-90, 1050, 1),
122
(-90, -1050, 1),
123
(-85, 1020, 1),
124
(-85, -1020, 1),
125
(-42, 246, 1),
126
(-42, -246, 1),
127
(-40, 0, 1)]
128
"""
129
cdef ratpoints_args args
130
cdef long i, total, verby
131
cdef Integer sage_int, s_x, s_y, s_z
132
cdef point_list *plist
133
134
135
verby = ~0 if verbose else 0
136
137
# Set the soefficient array:
138
coeffs = [Integer(a) for a in coeffs]
139
args.degree = len(coeffs)-1
140
args.cof = <mpz_t *> sage_malloc((args.degree+1) * sizeof(mpz_t))
141
142
# Create an array to hold the points found:
143
plist = <point_list *> sage_malloc(sizeof(point_list))
144
if max == 0:
145
plist.array_size = 64
146
else:
147
plist.array_size = max
148
plist.xes = <long *> sage_malloc(plist.array_size * sizeof(long))
149
plist.ys = <mpz_t *> sage_malloc(plist.array_size * sizeof(mpz_t))
150
for i from 0 <= i < plist.array_size:
151
mpz_init(plist.ys[i])
152
plist.zs = <long *> sage_malloc(plist.array_size * sizeof(long))
153
plist.num_points = 0
154
plist.max_num_points = max
155
156
# Set the height bound:
157
args.height = H
158
159
# Set the intervals to be searched, including any specified:
160
args.num_inter = len(intervals)
161
args.domain = <ratpoints_interval *> sage_malloc((args.num_inter + args.degree) * sizeof(ratpoints_interval))
162
for i,I in enumerate(intervals):
163
args.domain[i].low = I[0]
164
args.domain[i].up = I[1]
165
166
# Set the minimum and maximum denominators:
167
if not min_x_denom: min_x_denom = 1
168
if not max_x_denom: max_x_denom = H
169
args.b_low = min_x_denom
170
args.b_high = max_x_denom
171
172
# Set the remaining arguments, whose non-default use is technical
173
# (see ratpoints documentation)
174
args.sp1 = RATPOINTS_DEFAULT_SP1
175
args.sp2 = RATPOINTS_DEFAULT_SP2
176
args.array_size = RATPOINTS_ARRAY_SIZE
177
args.sturm = RATPOINTS_DEFAULT_STURM
178
args.num_primes = RATPOINTS_DEFAULT_NUM_PRIMES
179
args.max_forbidden = RATPOINTS_DEFAULT_MAX_FORBIDDEN
180
args.flags = (RATPOINTS_VERBOSE & verby)
181
182
for i from 0 <= i <= args.degree:
183
mpz_init(args.cof[i])
184
sage_int = <Integer> coeffs[i]
185
mpz_set(args.cof[i], sage_int.value)
186
187
sig_on()
188
total = find_points(&args, process, <void *>plist)
189
sig_off()
190
if total == RATPOINTS_NON_SQUAREFREE:
191
raise RuntimeError('Polynomial must be square-free')
192
if total == RATPOINTS_BAD_ARGS:
193
raise RuntimeError('Bad arguments to ratpoints')
194
195
for i from 0 <= i <= args.degree:
196
mpz_clear(args.cof[i])
197
198
sage_free(args.cof)
199
sage_free(args.domain)
200
201
cdef list L = []
202
for i from 0 <= i < plist.num_points:
203
s_x = Integer(0)
204
s_y = Integer(0)
205
s_z = Integer(0)
206
mpz_set_si(s_x.value, plist.xes[i])
207
mpz_set(s_y.value, plist.ys[i])
208
mpz_set_si(s_z.value, plist.zs[i])
209
L.append((s_x,s_y,s_z))
210
211
for i from 0 <= i < plist.array_size:
212
mpz_clear(plist.ys[i])
213
sage_free(plist.xes)
214
sage_free(plist.ys)
215
sage_free(plist.zs)
216
sage_free(plist)
217
218
return L
219
220
cdef int process_exists_only(long x, long z, mpz_t y, void *info0, int *quit):
221
cdef info_struct_exists_only *info_s = <info_struct_exists_only *>info0
222
cdef Integer YY
223
if info_s.verbose:
224
YY = Integer(0); mpz_set(YY.value, y)
225
print 'Found point [ %d : %d : %d ], quitting'%(x,YY,z)
226
quit[0] = -1
227
return 1
228
229
cdef int ratpoints_mpz_exists_only(mpz_t *coeffs, long H, int degree, bint verbose) except -1:
230
"""
231
Direct call to ratpoints to search for existence only.
232
233
WARNING - The coefficient array will be modified by ratpoints.
234
"""
235
cdef ratpoints_args args
236
cdef info_struct_exists_only info_s
237
cdef long total, verby = ~0 if verbose else 0
238
info_s.verbose = verbose
239
assert degree <= RATPOINTS_MAX_DEGREE
240
args.degree = degree
241
args.cof = coeffs
242
args.domain = <ratpoints_interval *> sage_malloc(2*args.degree * sizeof(ratpoints_interval))
243
args.height = H
244
args.num_inter = 0
245
args.b_low = 1
246
args.b_high = H
247
args.sp1 = RATPOINTS_DEFAULT_SP1
248
args.sp2 = RATPOINTS_DEFAULT_SP2
249
args.array_size = RATPOINTS_ARRAY_SIZE
250
args.sturm = RATPOINTS_DEFAULT_STURM
251
args.num_primes = RATPOINTS_DEFAULT_NUM_PRIMES
252
args.max_forbidden = RATPOINTS_DEFAULT_MAX_FORBIDDEN
253
args.flags = (RATPOINTS_VERBOSE & verby)
254
sig_on()
255
total = find_points(&args, process_exists_only, <void *>(&info_s))
256
sig_off()
257
sage_free(args.domain)
258
if total == RATPOINTS_NON_SQUAREFREE:
259
raise RuntimeError('Polynomial must be square-free')
260
if total == RATPOINTS_BAD_ARGS:
261
raise RuntimeError('Bad arguments to ratpoints')
262
return 1 if (total > 0) else 0
263
264
265
266
267
268