passagemath-eclib 10.6.42__cp313-cp313-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. passagemath_eclib/__init__.py +3 -0
  2. passagemath_eclib-10.6.42.dist-info/METADATA +161 -0
  3. passagemath_eclib-10.6.42.dist-info/RECORD +35 -0
  4. passagemath_eclib-10.6.42.dist-info/WHEEL +5 -0
  5. passagemath_eclib-10.6.42.dist-info/top_level.txt +3 -0
  6. passagemath_eclib.libs/libec-7d1d8090.so.14.1.0 +0 -0
  7. passagemath_eclib.libs/libflint-edf7fb90.so.22.0.0 +0 -0
  8. passagemath_eclib.libs/libgcc_s-2d945d6c.so.1 +0 -0
  9. passagemath_eclib.libs/libgf2x-e54d5509.so.3.0.0 +0 -0
  10. passagemath_eclib.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  11. passagemath_eclib.libs/libmpfr-1fc8ea36.so.6.2.2 +0 -0
  12. passagemath_eclib.libs/libntl-21cb123c.so.45.0.0 +0 -0
  13. passagemath_eclib.libs/libpari-gmp-tls-f714c61d.so.2.17.2 +0 -0
  14. passagemath_eclib.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  15. sage/all__sagemath_eclib.py +17 -0
  16. sage/interfaces/all__sagemath_eclib.py +1 -0
  17. sage/interfaces/mwrank.py +370 -0
  18. sage/libs/all__sagemath_eclib.py +11 -0
  19. sage/libs/eclib/__init__.pxd +158 -0
  20. sage/libs/eclib/__init__.py +1 -0
  21. sage/libs/eclib/all.py +5 -0
  22. sage/libs/eclib/constructor.py +75 -0
  23. sage/libs/eclib/homspace.cpython-313-aarch64-linux-musl.so +0 -0
  24. sage/libs/eclib/homspace.pxd +5 -0
  25. sage/libs/eclib/homspace.pyx +285 -0
  26. sage/libs/eclib/interface.py +1329 -0
  27. sage/libs/eclib/mat.cpython-313-aarch64-linux-musl.so +0 -0
  28. sage/libs/eclib/mat.pxd +8 -0
  29. sage/libs/eclib/mat.pyx +247 -0
  30. sage/libs/eclib/mwrank.cpython-313-aarch64-linux-musl.so +0 -0
  31. sage/libs/eclib/mwrank.pyx +1327 -0
  32. sage/libs/eclib/newforms.cpython-313-aarch64-linux-musl.so +0 -0
  33. sage/libs/eclib/newforms.pxd +8 -0
  34. sage/libs/eclib/newforms.pyx +394 -0
  35. sage_wheels/bin/mwrank +0 -0
@@ -0,0 +1,1327 @@
1
+ # sage_setup: distribution = sagemath-eclib
2
+ """
3
+ Cython interface to Cremona's ``eclib`` library (also known as ``mwrank``)
4
+
5
+ EXAMPLES::
6
+
7
+ sage: from sage.libs.eclib.mwrank import _Curvedata, _mw
8
+ sage: c = _Curvedata(1,2,3,4,5)
9
+
10
+ sage: print(c)
11
+ [1,2,3,4,5]
12
+ b2 = 9 b4 = 11 b6 = 29 b8 = 35
13
+ c4 = -183 c6 = -3429
14
+ disc = -10351 (# real components = 1)
15
+ #torsion not yet computed
16
+
17
+ sage: t= _mw(c)
18
+ sage: t.search(10)
19
+ sage: t
20
+ [[1:2:1]]
21
+ """
22
+ import os
23
+
24
+ from cysignals.memory cimport sig_free
25
+ from cysignals.signals cimport sig_on, sig_off
26
+
27
+ from sage.cpython.string cimport char_to_str, str_to_bytes
28
+ from sage.cpython.string import FS_ENCODING
29
+ from sage.libs.eclib cimport bigint, Curvedata, mw, two_descent
30
+ from sage.rings.integer import Integer
31
+
32
+ cdef extern from "wrap.cpp":
33
+ ### misc functions ###
34
+ long mwrank_get_precision()
35
+ void mwrank_set_precision(long n)
36
+ void mwrank_initprimes(char* pfilename, int verb)
37
+
38
+ ### bigint ###
39
+ bigint* str_to_bigint(char* s)
40
+ char* bigint_to_str(bigint* x)
41
+
42
+ ### Curvedata ###
43
+ char* Curvedata_repr(Curvedata* curve)
44
+ double Curvedata_silverman_bound(Curvedata* curve)
45
+ double Curvedata_cps_bound(Curvedata* curve)
46
+ double Curvedata_height_constant(Curvedata* curve)
47
+ char* Curvedata_getdiscr(Curvedata* curve)
48
+ char* Curvedata_conductor(Curvedata* m)
49
+ char* Curvedata_isogeny_class(Curvedata* E, int verbose)
50
+
51
+ ## mw ##
52
+ int mw_process(Curvedata* curve, mw* m,
53
+ bigint* x, bigint* y,
54
+ bigint* z, int sat)
55
+ char* mw_getbasis(mw* m)
56
+ double mw_regulator(mw* m)
57
+ int mw_rank(mw* m)
58
+ int mw_saturate(mw* m, long* index, char** unsat,
59
+ long sat_bd, long sat_low_bd)
60
+ void mw_search(mw* m, char* h_lim, int moduli_option, int verb)
61
+
62
+ ### two_descent ###
63
+ int two_descent_ok(two_descent* t)
64
+ long two_descent_get_certain(two_descent* t)
65
+ char* two_descent_get_basis(two_descent* t)
66
+ double two_descent_regulator(two_descent* t)
67
+ long two_descent_get_rank(two_descent* t)
68
+ long two_descent_get_rank_bound(two_descent* t)
69
+ long two_descent_get_selmer_rank(two_descent* t)
70
+ void two_descent_saturate(two_descent* t, long sat_bd, long sat_low_bd)
71
+
72
+ cdef object string_sigoff(char* s):
73
+ sig_off()
74
+ # Makes a python string and deletes what is pointed to by s.
75
+ t = char_to_str(s)
76
+ sig_free(s)
77
+ return t
78
+
79
+
80
+ # set the default bit precision
81
+ mwrank_set_precision(150)
82
+
83
+
84
+ def get_precision():
85
+ """
86
+ Return the working floating point bit precision of mwrank, which is
87
+ equal to the global NTL real number precision.
88
+
89
+ OUTPUT: integer; the current precision in bits
90
+
91
+ See also :meth:`set_precision`.
92
+
93
+ EXAMPLES::
94
+
95
+ sage: mwrank_get_precision()
96
+ 150
97
+ """
98
+ return mwrank_get_precision()
99
+
100
+
101
+ def set_precision(n):
102
+ """
103
+ Set the working floating point bit precision of mwrank, which is
104
+ equal to the global NTL real number precision.
105
+
106
+ NTL real number bit precision. This has a massive effect on the
107
+ speed of mwrank calculations. The default (used if this function is
108
+ not called) is ``n=150``, but it might have to be increased if a
109
+ computation fails.
110
+
111
+ INPUT:
112
+
113
+ - ``n`` -- positive integer; the number of bits of precision
114
+
115
+ .. warning::
116
+
117
+ This change is global and affects *all* future calls of eclib
118
+ functions by Sage.
119
+
120
+ .. NOTE::
121
+
122
+ The minimal value to which the precision may be set is 53.
123
+ Lower values will be increased to 53.
124
+
125
+ See also :meth:`get_precision`.
126
+
127
+ EXAMPLES::
128
+
129
+ sage: from sage.libs.eclib.mwrank import set_precision, get_precision
130
+ sage: old_prec = get_precision(); old_prec
131
+ 150
132
+ sage: set_precision(50)
133
+ sage: get_precision()
134
+ 53
135
+ sage: set_precision(old_prec)
136
+ sage: get_precision()
137
+ 150
138
+ """
139
+ mwrank_set_precision(n)
140
+
141
+
142
+ def initprimes(filename, verb=False):
143
+ """
144
+ Initialises mwrank/eclib's internal prime list.
145
+
146
+ INPUT:
147
+
148
+ - ``filename`` -- string; the name of a file of primes
149
+
150
+ - ``verb`` -- boolean (default: ``False``); verbose or not
151
+
152
+ EXAMPLES::
153
+
154
+ sage: import tempfile
155
+ sage: with tempfile.NamedTemporaryFile(mode='w+t') as f:
156
+ ....: data = ' '.join(str(p) for p in prime_range(10^7, 10^7 + 20))
157
+ ....: _ = f.write(data)
158
+ ....: f.flush()
159
+ ....: mwrank_initprimes(f.name, verb=True)
160
+ Computed 78519 primes, largest is 1000253
161
+ reading primes from file ...
162
+ read extra prime 10000019
163
+ finished reading primes from file ...
164
+ Extra primes in list: 10000019
165
+
166
+ sage: mwrank_initprimes(f.name, True)
167
+ Traceback (most recent call last):
168
+ ...
169
+ OSError: No such file or directory: ...
170
+ """
171
+ if not os.path.exists(filename):
172
+ raise IOError('No such file or directory: %s' % filename)
173
+ filename = str_to_bytes(filename, FS_ENCODING, 'surrogateescape')
174
+ mwrank_initprimes(filename, verb)
175
+
176
+
177
+ ############# bigint ###########################################
178
+ #
179
+ # In mwrank (and eclib) bigint is synonymous with NTL's ZZ class.
180
+ #
181
+ ################################################################
182
+
183
+ cdef class _bigint:
184
+ """
185
+ Cython class wrapping eclib's bigint class.
186
+ """
187
+ cdef bigint* x
188
+
189
+ def __init__(self, x='0'):
190
+ """
191
+ Constructor for bigint class.
192
+
193
+ INPUT:
194
+
195
+ - ``x`` -- string or int: a string representing a decimal
196
+ integer, or a Sage integer
197
+
198
+ EXAMPLES::
199
+
200
+ sage: from sage.libs.eclib.mwrank import _bigint
201
+ sage: _bigint(123)
202
+ 123
203
+ sage: _bigint('123')
204
+ 123
205
+ sage: type(_bigint(123))
206
+ <class 'sage.libs.eclib.mwrank._bigint'>
207
+ """
208
+ s = str(x)
209
+ if s.isdigit() or s[0] == "-" and s[1:].isdigit():
210
+ self.x = str_to_bigint(str_to_bytes(s))
211
+ else:
212
+ raise ValueError("invalid _bigint: %r" % x)
213
+
214
+ def __dealloc__(self):
215
+ """
216
+ Destructor for bigint class (releases memory).
217
+ """
218
+ del self.x
219
+
220
+ def __repr__(self):
221
+ """
222
+ String representation of bigint.
223
+
224
+ OUTPUT:
225
+
226
+ (string) the bigint as a string (decimal)
227
+
228
+ EXAMPLES::
229
+
230
+ sage: from sage.libs.eclib.mwrank import _bigint
231
+ sage: a = _bigint('123')
232
+ sage: a.__repr__()
233
+ '123'
234
+ sage: a = _bigint('-456')
235
+ sage: a.__repr__()
236
+ '-456'
237
+ """
238
+ sig_on()
239
+ return string_sigoff(bigint_to_str(self.x))
240
+
241
+
242
+ cdef make_bigint(bigint* x):
243
+ cdef _bigint y
244
+ sig_off()
245
+ y = _bigint.__new__(_bigint)
246
+ y.x = x
247
+ return y
248
+
249
+ ############# Curvedata #################
250
+
251
+ cdef class _Curvedata: # cython class wrapping eclib's Curvedata class
252
+ cdef Curvedata* x
253
+
254
+ def __init__(self, a1, a2, a3, a4, a6, min_on_init=0):
255
+ """
256
+ Constructor for Curvedata class.
257
+
258
+ INPUT:
259
+
260
+ - ``a1``, ``a2``, ``a3``, ``a4``, ``a6`` -- integer coefficients of a
261
+ Weierstrass equation (must be nonsingular)
262
+
263
+ - ``min_on_init`` -- integer (default: 0); flag controlling whether
264
+ the constructed curve is replaced by a global minimal model.
265
+ If nonzero then this minimisation does take place.
266
+
267
+ EXAMPLES::
268
+
269
+ sage: from sage.libs.eclib.mwrank import _Curvedata
270
+ sage: _Curvedata(1,2,3,4,5)
271
+ [1,2,3,4,5]
272
+ b2 = 9 b4 = 11 b6 = 29 b8 = 35
273
+ c4 = -183 c6 = -3429
274
+ disc = -10351 (# real components = 1)
275
+ #torsion not yet computed
276
+
277
+ A non-minimal example::
278
+
279
+ sage: _Curvedata(0,0,0,0,64)
280
+ [0,0,0,0,64]
281
+ b2 = 0 b4 = 0 b6 = 256 b8 = 0
282
+ c4 = 0 c6 = -55296
283
+ disc = -1769472 (# real components = 1)
284
+ #torsion not yet computed
285
+
286
+ sage: _Curvedata(0,0,0,0,64,min_on_init=1)
287
+ [0,0,0,0,1] (reduced minimal model)
288
+ b2 = 0 b4 = 0 b6 = 4 b8 = 0
289
+ c4 = 0 c6 = -864
290
+ disc = -432 (# real components = 1)
291
+ #torsion not yet computed
292
+ """
293
+ cdef _bigint _a1, _a2, _a3, _a4, _a6
294
+ _a1 = _bigint(a1)
295
+ _a2 = _bigint(a2)
296
+ _a3 = _bigint(a3)
297
+ _a4 = _bigint(a4)
298
+ _a6 = _bigint(a6)
299
+ self.x = new Curvedata(_a1.x[0], _a2.x[0], _a3.x[0], _a4.x[0], _a6.x[0], min_on_init)
300
+ if self.discriminant() == 0:
301
+ msg = "Invariants (= {},{},{},{},{}) do not describe an elliptic curve."
302
+ raise ArithmeticError(msg.format(a1, a2, a3, a4, a6))
303
+
304
+ def __dealloc__(self):
305
+ """
306
+ Destructor for Curvedata class.
307
+ """
308
+ del self.x
309
+
310
+ def __repr__(self):
311
+ r"""
312
+ String representation of Curvedata.
313
+
314
+ EXAMPLES::
315
+
316
+ sage: from sage.libs.eclib.mwrank import _Curvedata
317
+ sage: E = _Curvedata(1,2,3,4,5)
318
+ sage: E.__repr__()
319
+ '[1,2,3,4,5]\nb2 = 9\t b4 = 11\t b6 = 29\t b8 = 35\nc4 = -183\t\tc6 = -3429\ndisc = -10351\t(# real components = 1)\n#torsion not yet computed'
320
+ sage: E
321
+ [1,2,3,4,5]
322
+ b2 = 9 b4 = 11 b6 = 29 b8 = 35
323
+ c4 = -183 c6 = -3429
324
+ disc = -10351 (# real components = 1)
325
+ #torsion not yet computed
326
+ """
327
+ sig_on()
328
+ return string_sigoff(Curvedata_repr(self.x))[:-1]
329
+
330
+ def silverman_bound(self):
331
+ r"""
332
+ The Silverman height bound for this elliptic curve.
333
+
334
+ OUTPUT:
335
+
336
+ (float) A nonnegative real number `B` such that for every
337
+ rational point on this elliptic curve `E`, `h(P)\le\hat{h}(P)
338
+ + B`, where `h(P)` is the naive height and `\hat{h}(P)` the
339
+ canonical height.
340
+
341
+ .. NOTE::
342
+
343
+ Since eclib can compute this to arbitrary precision, we
344
+ could return a Sage real, but this is only a bound and in
345
+ the contexts in which it is used extra precision is
346
+ irrelevant.
347
+
348
+ EXAMPLES::
349
+
350
+ sage: from sage.libs.eclib.mwrank import _Curvedata
351
+ sage: E = _Curvedata(1,2,3,4,5)
352
+ sage: E.silverman_bound()
353
+ 6.52226179519101...
354
+ sage: type(E.silverman_bound())
355
+ <class 'float'>
356
+ """
357
+ return Curvedata_silverman_bound(self.x)
358
+
359
+ def cps_bound(self):
360
+ r"""
361
+ The Cremona-Prickett-Siksek height bound for this elliptic curve.
362
+
363
+ OUTPUT:
364
+
365
+ (float) A nonnegative real number `B` such that for every
366
+ rational point on this elliptic curve `E`, `h(P)\le\hat{h}(P)
367
+ + B`, where `h(P)` is the naive height and `\hat{h}(P)` the
368
+ canonical height.
369
+
370
+ .. NOTE::
371
+
372
+ Since ``eclib`` can compute this to arbitrary precision, we
373
+ could return a Sage real, but this is only a bound and in
374
+ the contexts in which it is used extra precision is irrelevant.
375
+
376
+ EXAMPLES::
377
+
378
+ sage: from sage.libs.eclib.mwrank import _Curvedata
379
+ sage: E = _Curvedata(1,2,3,4,5)
380
+ sage: E.cps_bound()
381
+ 0.11912451909250982...
382
+
383
+ Note that this is a better bound than Silverman's in this case::
384
+
385
+ sage: E.silverman_bound()
386
+ 6.52226179519101...
387
+ """
388
+ sig_on()
389
+ x = Curvedata_cps_bound(self.x)
390
+ sig_off()
391
+ return x
392
+
393
+ def height_constant(self):
394
+ r"""
395
+ A height bound for this elliptic curve.
396
+
397
+ OUTPUT:
398
+
399
+ (float) A nonnegative real number `B` such that for every
400
+ rational point on this elliptic curve `E`, `h(P)\le\hat{h}(P)
401
+ + B`, where `h(P)` is the naive height and `\hat{h}(P)` the
402
+ canonical height. This is the minimum of the Silverman and
403
+ Cremona_Prickett-Siksek height bounds.
404
+
405
+ .. NOTE::
406
+
407
+ Since ``eclib`` can compute this to arbitrary precision, we
408
+ could return a Sage real, but this is only a bound and in
409
+ the contexts in which it is used extra precision is irrelevant.
410
+
411
+ EXAMPLES::
412
+
413
+ sage: from sage.libs.eclib.mwrank import _Curvedata
414
+ sage: E = _Curvedata(1,2,3,4,5)
415
+ sage: E.height_constant()
416
+ 0.119124519092509...
417
+ """
418
+ return Curvedata_height_constant(self.x)
419
+
420
+ def discriminant(self):
421
+ """
422
+ The discriminant of this elliptic curve.
423
+
424
+ OUTPUT:
425
+
426
+ (Integer) The discriminant.
427
+
428
+ EXAMPLES::
429
+
430
+ sage: from sage.libs.eclib.mwrank import _Curvedata
431
+ sage: E = _Curvedata(1,2,3,4,5)
432
+ sage: E.discriminant()
433
+ -10351
434
+ sage: E = _Curvedata(100,200,300,400,500)
435
+ sage: E.discriminant()
436
+ -1269581104000000
437
+ sage: ZZ(E.discriminant())
438
+ -1269581104000000
439
+ """
440
+ sig_on()
441
+ return Integer(string_sigoff(Curvedata_getdiscr(self.x)))
442
+
443
+ def conductor(self):
444
+ """
445
+ The conductor of this elliptic curve.
446
+
447
+ OUTPUT:
448
+
449
+ (Integer) The conductor.
450
+
451
+ EXAMPLES::
452
+
453
+ sage: from sage.libs.eclib.mwrank import _Curvedata
454
+ sage: E = _Curvedata(1,2,3,4,5)
455
+ sage: E.discriminant()
456
+ -10351
457
+ sage: E = _Curvedata(100,200,300,400,500)
458
+ sage: E.conductor()
459
+ 126958110400
460
+ """
461
+ sig_on()
462
+ return Integer(string_sigoff(Curvedata_conductor(self.x)))
463
+
464
+ def isogeny_class(self, verbose=False):
465
+ """
466
+ The isogeny class of this elliptic curve.
467
+
468
+ OUTPUT:
469
+
470
+ (tuple) A tuple consisting of (1) a list of the curves in the
471
+ isogeny class, each as a list of its Weierstrass coefficients;
472
+ (2) a matrix of the degrees of the isogenies between the
473
+ curves in the class (prime degrees only).
474
+
475
+ .. warning::
476
+
477
+ The list may not be complete, if the precision is too low.
478
+ Use ``mwrank_set_precision()`` to increase the precision.
479
+
480
+ EXAMPLES::
481
+
482
+ sage: from sage.libs.eclib.mwrank import _Curvedata
483
+ sage: E = _Curvedata(1,0,1,4,-6)
484
+ sage: E.conductor()
485
+ 14
486
+ sage: E.isogeny_class()
487
+ ([[1, 0, 1, 4, -6], [1, 0, 1, -36, -70], [1, 0, 1, -1, 0], [1, 0, 1, -171, -874], [1, 0, 1, -11, 12], [1, 0, 1, -2731, -55146]], [[0, 2, 3, 3, 0, 0], [2, 0, 0, 0, 3, 3], [3, 0, 0, 0, 2, 0], [3, 0, 0, 0, 0, 2], [0, 3, 2, 0, 0, 0], [0, 3, 0, 2, 0, 0]])
488
+ """
489
+ sig_on()
490
+ s = string_sigoff(Curvedata_isogeny_class(self.x, verbose))
491
+ return eval(s)
492
+
493
+
494
+ ############# _mw #################
495
+
496
+ def parse_point_list(s):
497
+ r"""
498
+ Parse a string representing a list of points.
499
+
500
+ INPUT:
501
+
502
+ - ``s`` -- string representation of a list of points; for
503
+ example '[]', '[[1:2:3]]', or '[[1:2:3],[4:5:6]]'
504
+
505
+ OUTPUT: list of triples of integers, for example [], [[1,2,3]],
506
+ [[1,2,3],[4,5,6]]
507
+
508
+ EXAMPLES::
509
+
510
+ sage: from sage.libs.eclib.mwrank import parse_point_list
511
+ sage: parse_point_list('[]')
512
+ []
513
+ sage: parse_point_list('[[1:2:3]]')
514
+ [[1, 2, 3]]
515
+ sage: parse_point_list('[[1:2:3],[4:5:6]]')
516
+ [[1, 2, 3], [4, 5, 6]]
517
+ """
518
+ s = s.replace(":", ",").replace(" ", "")
519
+ if s == '[]':
520
+ return []
521
+ pts = s[2:-2].split('],[')
522
+ return [[Integer(x) for x in pt.split(",")] for pt in pts]
523
+
524
+
525
+ cdef class _mw:
526
+ """
527
+ Cython class wrapping eclib's mw class.
528
+ """
529
+ cdef mw* x
530
+ cdef Curvedata* curve
531
+ cdef int verb
532
+
533
+ def __init__(self, _Curvedata curve, verb=False, pp=1, maxr=999):
534
+ r"""
535
+ Constructor for mw class.
536
+
537
+ INPUT:
538
+
539
+ - ``curve`` -- _Curvedata; an elliptic curve
540
+
541
+ - ``verb`` -- boolean (default: ``False``); verbosity flag (controls
542
+ amount of output produced in point searches)
543
+
544
+ - ``pp`` -- integer (default: 1); process points flag (if nonzero,
545
+ the points found are processed, so that at all times only a
546
+ `\ZZ`-basis for the subgroup generated by the points found
547
+ so far is stored. If zero, no processing is done and all
548
+ points found are stored).
549
+
550
+ - ``maxr`` -- integer (default: 999); maximum rank (quit point
551
+ searching once the points found generate a subgroup of this
552
+ rank. Useful if an upper bound for the rank is already known).
553
+
554
+ EXAMPLES::
555
+
556
+ sage: from sage.libs.eclib.mwrank import _mw
557
+ sage: from sage.libs.eclib.mwrank import _Curvedata
558
+ sage: E = _Curvedata(1,0,1,4,-6)
559
+ sage: EQ = _mw(E)
560
+ sage: EQ
561
+ []
562
+ sage: type(EQ)
563
+ <class 'sage.libs.eclib.mwrank._mw'>
564
+
565
+ sage: E = _Curvedata(0,0,1,-7,6)
566
+ sage: EQ = _mw(E)
567
+ sage: EQ.search(2)
568
+ sage: EQ
569
+ [[1:-1:1], [-2:3:1], [-14:25:8]]
570
+
571
+ Example to illustrate the verbose parameter::
572
+
573
+ sage: from sage.libs.eclib.mwrank import _mw
574
+ sage: from sage.libs.eclib.mwrank import _Curvedata
575
+ sage: E = _Curvedata(0,0,1,-7,6)
576
+ sage: EQ = _mw(E, verb=False)
577
+ sage: EQ.search(1)
578
+ sage: EQ = _mw(E, verb=True)
579
+ sage: EQ.search(1)
580
+ P1 = [0:1:0] is torsion point, order 1
581
+ P1 = [-3:0:1] is generator number 1
582
+ saturating up to 20...Saturation index bound (for points of good reduction) = 3
583
+ Reducing saturation bound from given value 20 to computed index bound 3
584
+ Tamagawa index primes are [ 2 ]...
585
+ Checking saturation at [ 2 3 ]
586
+ Checking 2-saturation
587
+ Points were proved 2-saturated (max q used = 7)
588
+ Checking 3-saturation
589
+ Points were proved 3-saturated (max q used = 7)
590
+ done
591
+ P2 = [-2:3:1] is generator number 2
592
+ saturating up to 20...Saturation index bound (for points of good reduction) = 4
593
+ Reducing saturation bound from given value 20 to computed index bound 4
594
+ Tamagawa index primes are [ 2 ]...
595
+ Checking saturation at [ 2 3 ]
596
+ Checking 2-saturation
597
+ possible kernel vector = [1,1]
598
+ This point may be in 2E(Q): [14:-52:1]
599
+ ...and it is!
600
+ Replacing old generator #1 with new generator [1:-1:1]
601
+ Reducing index bound from 4 to 2
602
+ Points have successfully been 2-saturated (max q used = 7)
603
+ Index gain = 2^1
604
+ done, index = 2.
605
+ Gained index 2, new generators = [ [1:-1:1] [-2:3:1] ]
606
+ P3 = [-14:25:8] is generator number 3
607
+ saturating up to 20...Saturation index bound (for points of good reduction) = 3
608
+ Reducing saturation bound from given value 20 to computed index bound 3
609
+ Tamagawa index primes are [ 2 ]...
610
+ Checking saturation at [ 2 3 ]
611
+ Checking 2-saturation
612
+ Points were proved 2-saturated (max q used = 11)
613
+ Checking 3-saturation
614
+ Points were proved 3-saturated (max q used = 13)
615
+ done, index = 1.
616
+ P4 = [-1:3:1] = -1*P1 + -1*P2 + -1*P3 (mod torsion)
617
+ P4 = [0:2:1] = 2*P1 + 0*P2 + 1*P3 (mod torsion)
618
+ P4 = [2:13:8] = -3*P1 + 1*P2 + -1*P3 (mod torsion)
619
+ P4 = [1:0:1] = -1*P1 + 0*P2 + 0*P3 (mod torsion)
620
+ P4 = [2:0:1] = -1*P1 + 1*P2 + 0*P3 (mod torsion)
621
+ P4 = [18:7:8] = -2*P1 + -1*P2 + -1*P3 (mod torsion)
622
+ P4 = [3:3:1] = 1*P1 + 0*P2 + 1*P3 (mod torsion)
623
+ P4 = [4:6:1] = 0*P1 + -1*P2 + -1*P3 (mod torsion)
624
+ P4 = [36:69:64] = 1*P1 + -2*P2 + 0*P3 (mod torsion)
625
+ P4 = [68:-25:64] = -2*P1 + -1*P2 + -2*P3 (mod torsion)
626
+ P4 = [12:35:27] = 1*P1 + -1*P2 + -1*P3 (mod torsion)
627
+ sage: EQ
628
+ [[1:-1:1], [-2:3:1], [-14:25:8]]
629
+
630
+ Example to illustrate the process points ``pp`` parameter::
631
+
632
+ sage: from sage.libs.eclib.mwrank import _mw
633
+ sage: from sage.libs.eclib.mwrank import _Curvedata
634
+ sage: E = _Curvedata(0,0,1,-7,6)
635
+ sage: EQ = _mw(E, pp=1)
636
+ sage: EQ.search(1); EQ
637
+ [[1:-1:1], [-2:3:1], [-14:25:8]]
638
+ sage: EQ = _mw(E, pp=0)
639
+ sage: EQ.search(1); EQ
640
+ [[-3:0:1], [-2:3:1], [-14:25:8], [-1:3:1], [0:2:1], [2:13:8], [1:0:1], [2:0:1], [18:7:8], [3:3:1], [4:6:1], [36:69:64], [68:-25:64], [12:35:27]]
641
+ """
642
+ self.curve = curve.x
643
+ self.x = new mw(curve.x, verb, pp, maxr)
644
+ self.verb = verb
645
+
646
+ def __dealloc__(self):
647
+ """
648
+ Destructor for mw class.
649
+ """
650
+ del self.x
651
+
652
+ def __repr__(self):
653
+ """
654
+ String representation of the current basis of this mw group.
655
+
656
+ OUTPUT:
657
+
658
+ (string) the current basis of this mw as a string
659
+
660
+ EXAMPLES::
661
+
662
+ sage: from sage.libs.eclib.mwrank import _Curvedata
663
+ sage: from sage.libs.eclib.mwrank import _mw
664
+ sage: E = _Curvedata(0,0,1,-7,6)
665
+ sage: EQ = _mw(E)
666
+ sage: EQ # indirect doctest
667
+ []
668
+ sage: EQ.search(2)
669
+ sage: EQ
670
+ [[1:-1:1], [-2:3:1], [-14:25:8]]
671
+ """
672
+ sig_on()
673
+ return string_sigoff(mw_getbasis(self.x))
674
+
675
+ def process(self, point, saturation_bound=0):
676
+ """
677
+ Processes the given point, adding it to the mw group.
678
+
679
+ INPUT:
680
+
681
+ - ``point`` -- tuple or list of 3 integers; an :exc:`ArithmeticError` is
682
+ raised if the point is not on the curve
683
+
684
+ - ``saturation_bound`` -- integer (default: 0); saturate at primes up
685
+ to ``saturation_bound``. No saturation is done if
686
+ ``saturation_bound=0``. If ``saturation_bound=-1`` then
687
+ saturation is done at all primes, by computing a bound on
688
+ the saturation index. Note that it is more efficient to add
689
+ several points at once and then saturate just once at the end.
690
+
691
+ .. NOTE::
692
+
693
+ The eclib function which implements this only carries out
694
+ any saturation if the rank of the points increases upon
695
+ adding the new point. This is because it is assumed that
696
+ one saturates as ones goes along.
697
+
698
+ EXAMPLES::
699
+
700
+ sage: from sage.libs.eclib.mwrank import _Curvedata
701
+ sage: from sage.libs.eclib.mwrank import _mw
702
+ sage: E = _Curvedata(0,1,1,-2,0)
703
+ sage: EQ = _mw(E)
704
+
705
+ Initially the list of gens is empty::
706
+
707
+ sage: EQ
708
+ []
709
+
710
+ We process a point of infinite order::
711
+
712
+ sage: EQ.process([-1,1,1])
713
+ sage: EQ
714
+ [[-1:1:1]]
715
+
716
+ And another independent one::
717
+
718
+ sage: EQ.process([0,-1,1])
719
+ sage: EQ
720
+ [[-1:1:1], [0:-1:1]]
721
+
722
+ Processing a point dependent on the current basis will not
723
+ change the basis::
724
+
725
+ sage: EQ.process([4,8,1])
726
+ sage: EQ
727
+ [[-1:1:1], [0:-1:1]]
728
+ """
729
+ if not isinstance(point, (tuple, list)) and len(point) == 3:
730
+ raise TypeError("point must be a list or tuple of length 3.")
731
+ cdef _bigint x,y,z
732
+ sig_on()
733
+ x,y,z = _bigint(point[0]), _bigint(point[1]), _bigint(point[2])
734
+ r = mw_process(self.curve, self.x, x.x, y.x, z.x, saturation_bound)
735
+ sig_off()
736
+ if r != 0:
737
+ raise ArithmeticError("point (=%s) not on curve." % point)
738
+
739
+ def getbasis(self):
740
+ """
741
+ Return the current basis of the mw structure.
742
+
743
+ OUTPUT:
744
+
745
+ (list) list of integer triples giving the projective
746
+ coordinates of the points in the basis.
747
+
748
+ EXAMPLES::
749
+
750
+ sage: from sage.libs.eclib.mwrank import _Curvedata
751
+ sage: from sage.libs.eclib.mwrank import _mw
752
+ sage: E = _Curvedata(0,1,1,-2,0)
753
+ sage: EQ = _mw(E)
754
+ sage: EQ.search(3)
755
+ sage: EQ.getbasis()
756
+ [[0, -1, 1], [-1, 1, 1]]
757
+ sage: EQ.rank()
758
+ 2
759
+ """
760
+ sig_on()
761
+ s = string_sigoff(mw_getbasis(self.x))
762
+ return parse_point_list(s)
763
+
764
+ def regulator(self):
765
+ """
766
+ Return the regulator of the current basis of the mw group.
767
+
768
+ OUTPUT:
769
+
770
+ (double) The current regulator.
771
+
772
+ .. TODO::
773
+
774
+ ``eclib`` computes the regulator to arbitrary precision, and
775
+ the full precision value should be returned.
776
+
777
+ EXAMPLES::
778
+
779
+ sage: from sage.libs.eclib.mwrank import _Curvedata
780
+ sage: from sage.libs.eclib.mwrank import _mw
781
+ sage: E = _Curvedata(0,1,1,-2,0)
782
+ sage: EQ = _mw(E)
783
+ sage: EQ.search(3)
784
+ sage: EQ.getbasis()
785
+ [[0, -1, 1], [-1, 1, 1]]
786
+ sage: EQ.rank()
787
+ 2
788
+ sage: EQ.regulator()
789
+ 0.15246017794314376
790
+ """
791
+ sig_on()
792
+ f = mw_regulator(self.x)
793
+ sig_off()
794
+ return f
795
+
796
+ def rank(self):
797
+ """
798
+ Return the rank of the current basis of the mw group.
799
+
800
+ OUTPUT:
801
+
802
+ (Integer) The current rank.
803
+
804
+ EXAMPLES::
805
+
806
+ sage: from sage.libs.eclib.mwrank import _Curvedata
807
+ sage: from sage.libs.eclib.mwrank import _mw
808
+ sage: E = _Curvedata(0,1,1,-2,0)
809
+ sage: EQ = _mw(E)
810
+ sage: EQ.search(3)
811
+ sage: EQ.getbasis()
812
+ [[0, -1, 1], [-1, 1, 1]]
813
+ sage: EQ.rank()
814
+ 2
815
+ """
816
+ sig_on()
817
+ r = mw_rank(self.x)
818
+ sig_off()
819
+ return Integer(r)
820
+
821
+ def saturate(self, int sat_bd=-1, int sat_low_bd=2):
822
+ """
823
+ Saturates the current subgroup of the mw group.
824
+
825
+ INPUT:
826
+
827
+ - ``sat_bnd`` -- integer (default: -1); upper bound on primes at
828
+ which to saturate. If -1 (default), compute a bound for the
829
+ primes which may not be saturated, and use that. Otherwise,
830
+ the bound used is the minimum of the value of ``sat_bnd``
831
+ and the computed bound.
832
+
833
+ - ``sat_low_bd`` -- integer (default: 2); only do saturation at
834
+ prime not less than this. For example, if the points have
835
+ been found via 2-descent they should already be 2-saturated,
836
+ and ``sat_low_bd=3`` is appropriate.
837
+
838
+ OUTPUT:
839
+
840
+ (tuple) (success flag, index, list) The success flag will be 1
841
+ unless something failed (usually an indication that the points
842
+ were not saturated but eclib was not able to divide out
843
+ successfully). The index is the index of the mw group before
844
+ saturation in the mw group after. The list is a string
845
+ representation of the primes at which saturation was not
846
+ proved or achieved.
847
+
848
+ .. NOTE::
849
+
850
+ ``eclib`` will compute a bound on the saturation index. If
851
+ the computed saturation bound is very large and ``sat_bnd`` is
852
+ -1, ``eclib`` may output a warning, but will still attempt to
853
+ saturate up to the computed bound. If a positive value of
854
+ ``sat_bnd`` is given which is greater than the computed bound,
855
+ `p`-saturation will only be carried out for primes up to the
856
+ compated bound. Setting ``sat_low_bnd`` to a value greater
857
+ than 2 allows for saturation to be done incrementally, or for
858
+ exactly one prime `p` by setting both ``sat_bd`` and
859
+ ``sat_low_bd`` to `p`.
860
+
861
+ EXAMPLES::
862
+
863
+ sage: from sage.libs.eclib.mwrank import _Curvedata
864
+ sage: from sage.libs.eclib.mwrank import _mw
865
+ sage: E = _Curvedata(0,1,1,-2,0)
866
+ sage: EQ = _mw(E)
867
+ sage: EQ.process([494, -5720, 6859]) # 3 times another point
868
+ sage: EQ
869
+ [[494:-5720:6859]]
870
+ sage: EQ.saturate()
871
+ (1, 3, '[ ]')
872
+ sage: EQ
873
+ [[-1:1:1]]
874
+
875
+ If we set the saturation bound at 2, then saturation will not
876
+ enlarge the basis, but the success flag is still 1 (True)
877
+ since we did not ask to check 3-saturation::
878
+
879
+ sage: EQ = _mw(E)
880
+ sage: EQ.process([494, -5720, 6859]) # 3 times another point
881
+ sage: EQ.saturate(sat_bd=2)
882
+ (1, 1, '[ ]')
883
+ sage: EQ
884
+ [[494:-5720:6859]]
885
+ """
886
+ cdef long index
887
+ cdef char* s
888
+ cdef int ok
889
+ sig_on()
890
+ ok = mw_saturate(self.x, &index, &s, sat_bd, sat_low_bd)
891
+ unsat = string_sigoff(s)
892
+ return ok, index, unsat
893
+
894
+ def search(self, h_lim, int moduli_option=0, int verb=0):
895
+ r"""
896
+ Search for points in the mw group.
897
+
898
+ INPUT:
899
+
900
+ - ``h_lim`` -- integer; bound on logarithmic naive height of points
901
+
902
+ - ``moduli_option`` -- integer (default: 0); option for sieving
903
+ strategy. The default (0) uses an adapted version of
904
+ Stoll's ratpoints code and is recommended.
905
+
906
+ - ``verb`` -- integer (default: 0); level of verbosity. If 0, no
907
+ output. If positive, the points are output as found and
908
+ some details of the processing, finding linear relations,
909
+ and partial saturation are output.
910
+
911
+ .. NOTE::
912
+
913
+ The effect of the search is also governed by the class
914
+ options, notably whether the points found are processed:
915
+ meaning that linear relations are found and saturation is
916
+ carried out, with the result that the list of generators
917
+ will always contain a `\ZZ`-span of the saturation of the
918
+ points found, modulo torsion.
919
+
920
+ OUTPUT: none; the effect of the search is to update the list of generators
921
+
922
+ EXAMPLES::
923
+
924
+ sage: from sage.libs.eclib.mwrank import _Curvedata
925
+ sage: from sage.libs.eclib.mwrank import _mw
926
+ sage: E = _Curvedata(0,0,1,-19569,-4064513) # 873c1
927
+ sage: EQ = _mw(E)
928
+ sage: EQ = _mw(E)
929
+ sage: for i in [1..11]:
930
+ ....: print("{} {} {}".format(i, EQ.search(i), EQ))
931
+ 1 None []
932
+ 2 None []
933
+ 3 None []
934
+ 4 None []
935
+ 5 None []
936
+ 6 None []
937
+ 7 None []
938
+ 8 None []
939
+ 9 None []
940
+ 10 None []
941
+ 11 None [[3639568:106817593:4096]]
942
+ """
943
+
944
+ h_lim = str_to_bytes(str(h_lim))
945
+
946
+ sig_on()
947
+ mw_search(self.x, h_lim, moduli_option, verb)
948
+ sig_off()
949
+
950
+
951
+ ############# two_descent #################
952
+ cdef class _two_descent:
953
+ """
954
+ Cython class wrapping eclib's two_descent class.
955
+ """
956
+ cdef two_descent* x
957
+
958
+ def __init__(self):
959
+ """
960
+ Constructor for two_descent class.
961
+
962
+ EXAMPLES::
963
+
964
+ sage: from sage.libs.eclib.mwrank import _two_descent
965
+ sage: D2 = _two_descent()
966
+ """
967
+ self.x = <two_descent*> 0
968
+
969
+ def __dealloc__(self):
970
+ """
971
+ Destructor for two_descent class.
972
+ """
973
+ del self.x
974
+
975
+ def do_descent(self, _Curvedata curve,
976
+ int verb = 1,
977
+ int sel = 0,
978
+ int firstlim = 20,
979
+ int secondlim = 8,
980
+ int n_aux = -1,
981
+ int second_descent = 1):
982
+ """
983
+ Carry out a 2-descent.
984
+
985
+ INPUT:
986
+
987
+ - ``curvedata`` -- _Curvedata; the curve on which to do descent
988
+
989
+ - ``verb`` -- integer (default: 1); verbosity level
990
+
991
+ - ``sel`` -- integer (default: 0); Selmer-only flag. If 1, only
992
+ the 2-Selmer group will be computed, with no rational
993
+ points. Useful as a faster way of getting an upper bound on
994
+ the rank.
995
+
996
+ - ``firstlim``, ``secondlim``, ``n_aux``, ``second_descent`` --
997
+ see ``first_limit``, ``second_limit``, ``n_aux``, ``second_descent``
998
+ respectively in :meth:`~sage.libs.eclib.interface.mwrank_EllipticCurve.two_descent`
999
+ (although ``second_descent`` here is ``1`` or ``0`` instead of ``True`` or ``False``
1000
+ respectively)
1001
+
1002
+ OUTPUT: none
1003
+
1004
+ EXAMPLES::
1005
+
1006
+ sage: from sage.libs.eclib.mwrank import _Curvedata
1007
+ sage: CD = _Curvedata(0,0,1,-7,6)
1008
+ sage: from sage.libs.eclib.mwrank import _two_descent
1009
+ sage: D2 = _two_descent()
1010
+ sage: D2.do_descent(CD)
1011
+ Basic pair: I=336, J=-10800
1012
+ disc=35092224
1013
+ ...
1014
+ Mordell rank contribution from B=im(eps) = 3
1015
+ Selmer rank contribution from B=im(eps) = 3
1016
+ Sha rank contribution from B=im(eps) = 0
1017
+ Mordell rank contribution from A=ker(eps) = 0
1018
+ Selmer rank contribution from A=ker(eps) = 0
1019
+ Sha rank contribution from A=ker(eps) = 0
1020
+ sage: D2.getrank()
1021
+ 3
1022
+ sage: D2.getcertain()
1023
+ 1
1024
+ sage: D2.ok()
1025
+ 1
1026
+ """
1027
+ sig_on()
1028
+ self.x = new two_descent(curve.x, verb, sel, firstlim, secondlim, n_aux, second_descent)
1029
+ sig_off()
1030
+
1031
+ def getrank(self):
1032
+ """
1033
+ Return the rank (after doing a 2-descent).
1034
+
1035
+ OUTPUT:
1036
+
1037
+ (Integer) the rank (or an upper bound).
1038
+
1039
+ EXAMPLES::
1040
+
1041
+ sage: from sage.libs.eclib.mwrank import _Curvedata
1042
+ sage: CD = _Curvedata(0,0,1,-7,6)
1043
+ sage: from sage.libs.eclib.mwrank import _two_descent
1044
+ sage: D2 = _two_descent()
1045
+ sage: D2.do_descent(CD)
1046
+ Basic pair: I=336, J=-10800
1047
+ disc=35092224
1048
+ ...
1049
+ Mordell rank contribution from B=im(eps) = 3
1050
+ Selmer rank contribution from B=im(eps) = 3
1051
+ Sha rank contribution from B=im(eps) = 0
1052
+ Mordell rank contribution from A=ker(eps) = 0
1053
+ Selmer rank contribution from A=ker(eps) = 0
1054
+ Sha rank contribution from A=ker(eps) = 0
1055
+ sage: D2.getrank()
1056
+ 3
1057
+ """
1058
+ cdef int r
1059
+ sig_on()
1060
+ r = two_descent_get_rank(self.x)
1061
+ sig_off()
1062
+ return Integer(r)
1063
+
1064
+ def getrankbound(self):
1065
+ """
1066
+ Return the rank upper bound (after doing a 2-descent).
1067
+
1068
+ OUTPUT:
1069
+
1070
+ (Integer) an upper bound on the rank.
1071
+
1072
+ EXAMPLES::
1073
+
1074
+ sage: from sage.libs.eclib.mwrank import _Curvedata
1075
+ sage: CD = _Curvedata(0,0,1,-7,6)
1076
+ sage: from sage.libs.eclib.mwrank import _two_descent
1077
+ sage: D2 = _two_descent()
1078
+ sage: D2.do_descent(CD)
1079
+ Basic pair: I=336, J=-10800
1080
+ disc=35092224
1081
+ ...
1082
+ Mordell rank contribution from B=im(eps) = 3
1083
+ Selmer rank contribution from B=im(eps) = 3
1084
+ Sha rank contribution from B=im(eps) = 0
1085
+ Mordell rank contribution from A=ker(eps) = 0
1086
+ Selmer rank contribution from A=ker(eps) = 0
1087
+ Sha rank contribution from A=ker(eps) = 0
1088
+ sage: D2.getrankbound()
1089
+ 3
1090
+ """
1091
+ cdef int r
1092
+ sig_on()
1093
+ r = two_descent_get_rank_bound(self.x)
1094
+ sig_off()
1095
+ return Integer(r)
1096
+
1097
+ def getselmer(self):
1098
+ """
1099
+ Return the 2-Selmer rank (after doing a 2-descent).
1100
+
1101
+ OUTPUT:
1102
+
1103
+ (Integer) The 2-Selmer rank.
1104
+
1105
+ EXAMPLES::
1106
+
1107
+ sage: from sage.libs.eclib.mwrank import _Curvedata
1108
+ sage: CD = _Curvedata(0,0,1,-7,6)
1109
+ sage: from sage.libs.eclib.mwrank import _two_descent
1110
+ sage: D2 = _two_descent()
1111
+ sage: D2.do_descent(CD)
1112
+ Basic pair: I=336, J=-10800
1113
+ disc=35092224
1114
+ ...
1115
+ Mordell rank contribution from B=im(eps) = 3
1116
+ Selmer rank contribution from B=im(eps) = 3
1117
+ Sha rank contribution from B=im(eps) = 0
1118
+ Mordell rank contribution from A=ker(eps) = 0
1119
+ Selmer rank contribution from A=ker(eps) = 0
1120
+ Sha rank contribution from A=ker(eps) = 0
1121
+ sage: D2.getselmer()
1122
+ 3
1123
+ """
1124
+ sig_on()
1125
+ r = two_descent_get_selmer_rank(self.x)
1126
+ sig_off()
1127
+ return Integer(r)
1128
+
1129
+ def ok(self):
1130
+ """
1131
+ Return the success flag (after doing a 2-descent).
1132
+
1133
+ OUTPUT: boolean flag indicating whether or not 2-descent was successful
1134
+
1135
+ EXAMPLES::
1136
+
1137
+ sage: from sage.libs.eclib.mwrank import _Curvedata
1138
+ sage: CD = _Curvedata(0,0,1,-7,6)
1139
+ sage: from sage.libs.eclib.mwrank import _two_descent
1140
+ sage: D2 = _two_descent()
1141
+ sage: D2.do_descent(CD)
1142
+ Basic pair: I=336, J=-10800
1143
+ disc=35092224
1144
+ ...
1145
+ Mordell rank contribution from B=im(eps) = 3
1146
+ Selmer rank contribution from B=im(eps) = 3
1147
+ Sha rank contribution from B=im(eps) = 0
1148
+ Mordell rank contribution from A=ker(eps) = 0
1149
+ Selmer rank contribution from A=ker(eps) = 0
1150
+ Sha rank contribution from A=ker(eps) = 0
1151
+ sage: D2.ok()
1152
+ 1
1153
+ """
1154
+ return two_descent_ok(self.x)
1155
+
1156
+ def getcertain(self):
1157
+ """
1158
+ Return the certainty flag (after doing a 2-descent).
1159
+
1160
+ OUTPUT: boolean; ``True`` if the rank upper and lower bounds are equal
1161
+
1162
+ EXAMPLES::
1163
+
1164
+ sage: from sage.libs.eclib.mwrank import _Curvedata
1165
+ sage: CD = _Curvedata(0,0,1,-7,6)
1166
+ sage: from sage.libs.eclib.mwrank import _two_descent
1167
+ sage: D2 = _two_descent()
1168
+ sage: D2.do_descent(CD)
1169
+ Basic pair: I=336, J=-10800
1170
+ disc=35092224
1171
+ ...
1172
+ Mordell rank contribution from B=im(eps) = 3
1173
+ Selmer rank contribution from B=im(eps) = 3
1174
+ Sha rank contribution from B=im(eps) = 0
1175
+ Mordell rank contribution from A=ker(eps) = 0
1176
+ Selmer rank contribution from A=ker(eps) = 0
1177
+ Sha rank contribution from A=ker(eps) = 0
1178
+ sage: D2.getcertain()
1179
+ 1
1180
+ """
1181
+ return two_descent_get_certain(self.x)
1182
+
1183
+ def saturate(self, saturation_bound=0, lower=3):
1184
+ """
1185
+ Carries out saturation of the points found by a 2-descent.
1186
+
1187
+ INPUT:
1188
+
1189
+ - ``saturation_bound`` -- integer; an upper bound on the primes
1190
+ `p` at which `p`-saturation will be carried out, or -1, in
1191
+ which case ``eclib`` will compute an upper bound on the
1192
+ saturation index.
1193
+
1194
+ - ``lower`` -- integer (default: 3); do no `p`-saturation for `p`
1195
+ less than this. The default is 3 since the points found
1196
+ during 2-descent will be 2-saturated.
1197
+
1198
+ OUTPUT: none
1199
+
1200
+ EXAMPLES::
1201
+
1202
+ sage: from sage.libs.eclib.mwrank import _Curvedata
1203
+ sage: CD = _Curvedata(0,0,1,-7,6)
1204
+ sage: from sage.libs.eclib.mwrank import _two_descent
1205
+ sage: D2 = _two_descent()
1206
+ sage: D2.do_descent(CD)
1207
+ Basic pair: I=336, J=-10800
1208
+ disc=35092224
1209
+ ...
1210
+ Mordell rank contribution from B=im(eps) = 3
1211
+ Selmer rank contribution from B=im(eps) = 3
1212
+ Sha rank contribution from B=im(eps) = 0
1213
+ Mordell rank contribution from A=ker(eps) = 0
1214
+ Selmer rank contribution from A=ker(eps) = 0
1215
+ Sha rank contribution from A=ker(eps) = 0
1216
+ sage: D2.saturate()
1217
+ Searching for points (bound = 8)...done:
1218
+ found points which generate a subgroup of rank 3
1219
+ and regulator 0.417...
1220
+ Processing points found during 2-descent...done:
1221
+ now regulator = 0.417...
1222
+ No saturation being done
1223
+ sage: D2.getbasis()
1224
+ '[[1:-1:1], [-2:3:1], [-14:25:8]]'
1225
+ """
1226
+ sig_on()
1227
+ two_descent_saturate(self.x, saturation_bound, 3)
1228
+ sig_off()
1229
+
1230
+ def getbasis(self):
1231
+ r"""
1232
+ Return the basis of points found by doing a 2-descent.
1233
+
1234
+ If the success and certain flags are 1, this will be a
1235
+ `\ZZ/2\ZZ`-basis for `E(\QQ)/2E(\QQ)` (modulo torsion),
1236
+ otherwise possibly only for a proper subgroup.
1237
+
1238
+ .. NOTE::
1239
+
1240
+ You must call ``saturate()`` first, or a :exc:`RunTimeError`
1241
+ will be raised.
1242
+
1243
+ OUTPUT:
1244
+
1245
+ (string) String representation of the list of points after
1246
+ saturation.
1247
+
1248
+ EXAMPLES::
1249
+
1250
+ sage: from sage.libs.eclib.mwrank import _Curvedata
1251
+ sage: CD = _Curvedata(0,0,1,-7,6)
1252
+ sage: from sage.libs.eclib.mwrank import _two_descent
1253
+ sage: D2 = _two_descent()
1254
+ sage: D2.do_descent(CD)
1255
+ Basic pair: I=336, J=-10800
1256
+ disc=35092224
1257
+ ...
1258
+ Mordell rank contribution from B=im(eps) = 3
1259
+ Selmer rank contribution from B=im(eps) = 3
1260
+ Sha rank contribution from B=im(eps) = 0
1261
+ Mordell rank contribution from A=ker(eps) = 0
1262
+ Selmer rank contribution from A=ker(eps) = 0
1263
+ Sha rank contribution from A=ker(eps) = 0
1264
+ sage: D2.saturate()
1265
+ Searching for points (bound = 8)...done:
1266
+ found points which generate a subgroup of rank 3
1267
+ and regulator 0.417...
1268
+ Processing points found during 2-descent...done:
1269
+ now regulator = 0.417...
1270
+ No saturation being done
1271
+ sage: D2.getbasis()
1272
+ '[[1:-1:1], [-2:3:1], [-14:25:8]]'
1273
+ """
1274
+ sig_on()
1275
+ return string_sigoff(two_descent_get_basis(self.x))
1276
+
1277
+ def regulator(self):
1278
+ """
1279
+ Return the regulator of the points found by doing a 2-descent.
1280
+
1281
+ OUTPUT:
1282
+
1283
+ (double) The regulator (of the subgroup found by 2-descent).
1284
+
1285
+ EXAMPLES::
1286
+
1287
+ sage: from sage.libs.eclib.mwrank import _Curvedata
1288
+ sage: CD = _Curvedata(0,0,1,-7,6)
1289
+ sage: from sage.libs.eclib.mwrank import _two_descent
1290
+ sage: D2 = _two_descent()
1291
+ sage: D2.do_descent(CD)
1292
+ Basic pair: I=336, J=-10800
1293
+ disc=35092224
1294
+ ...
1295
+ Mordell rank contribution from B=im(eps) = 3
1296
+ Selmer rank contribution from B=im(eps) = 3
1297
+ Sha rank contribution from B=im(eps) = 0
1298
+ Mordell rank contribution from A=ker(eps) = 0
1299
+ Selmer rank contribution from A=ker(eps) = 0
1300
+ Sha rank contribution from A=ker(eps) = 0
1301
+
1302
+ If called before calling ``saturate()``, a bogus value of 1.0
1303
+ is returned::
1304
+
1305
+ sage: D2.regulator()
1306
+ 1.0
1307
+
1308
+ After saturation, both ``getbasis()`` and ``regulator()``
1309
+ return the basis and regulator of the subgroup found by
1310
+ 2-descent::
1311
+
1312
+ sage: D2.saturate()
1313
+ Searching for points (bound = 8)...done:
1314
+ found points which generate a subgroup of rank 3
1315
+ and regulator 0.417...
1316
+ Processing points found during 2-descent...done:
1317
+ now regulator = 0.417...
1318
+ No saturation being done
1319
+ sage: D2.getbasis()
1320
+ '[[1:-1:1], [-2:3:1], [-14:25:8]]'
1321
+ sage: D2.regulator()
1322
+ 0.417143558758384
1323
+ """
1324
+ sig_on()
1325
+ reg = two_descent_regulator(self.x)
1326
+ sig_off()
1327
+ return reg