summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntonio Rojas2021-07-02 08:12:28 +0200
committerAntonio Rojas2021-07-02 08:12:28 +0200
commit77efa60fab89187663b9d577d8fa8c1a18fcd645 (patch)
tree89a2da7ead968bd9a6e1042e8425a2222be4461d
parentc2f716eb0bdcfe64296554c80901299e3557611f (diff)
downloadaur-77efa60fab89187663b9d577d8fa8c1a18fcd645.tar.gz
Drop merged patch
-rw-r--r--.SRCINFO4
-rw-r--r--PKGBUILD10
-rw-r--r--sagemath-eclib-20210310.patch1406
3 files changed, 4 insertions, 1416 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 0e0cb0c102e5..a1ad2406ab52 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = sagemath-git
pkgdesc = Open Source Mathematics Software, free alternative to Magma, Maple, Mathematica, and Matlab
- pkgver = 9.4.beta3.r0.ga60179ab6b
+ pkgver = 9.4.beta4.r0.g473cd41f19
pkgrel = 1
url = http://www.sagemath.org
arch = x86_64
@@ -101,12 +101,10 @@ pkgbase = sagemath-git
source = latte-count.patch
source = test-optional.patch
source = sagemath-lrcalc2.patch
- source = sagemath-eclib-20210310.patch
sha256sums = SKIP
sha256sums = c100a61c8dfade43bebc622a363abcb3d935a2f40958371ad87a9eb00689f8b0
sha256sums = 88e944f23c3b2391dc2e9f9be8e1131152d837dc8c829dfc714663869a272e81
sha256sums = af984186f852d2847d770a18fb6822296c50a652dbf55a1ed59d27517c3d3ee4
sha256sums = 240ac4c29d96d56407a20e1b7f9846e342a7eb2bb4edd6e5c86b3b5a8ff462f9
- sha256sums = e7b31f5e7ea88681c6eda41e5a74a2859a12dd128e75c00db3cfbd1d8ddf080d
pkgname = sagemath-git
diff --git a/PKGBUILD b/PKGBUILD
index defa4e5e682c..54bf65e5375b 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -6,7 +6,7 @@
# Contributor: Stefan Husmann <stefan-husmann at t-online dot de>
pkgname=sagemath-git
-pkgver=9.4.beta3.r0.ga60179ab6b
+pkgver=9.4.beta4.r0.g473cd41f19
pkgrel=1
pkgdesc='Open Source Mathematics Software, free alternative to Magma, Maple, Mathematica, and Matlab'
arch=(x86_64)
@@ -41,14 +41,12 @@ source=(git://git.sagemath.org/sage.git#branch=develop
sagemath-optional-packages.patch
latte-count.patch
test-optional.patch
- sagemath-lrcalc2.patch
- sagemath-eclib-20210310.patch)
+ sagemath-lrcalc2.patch)
sha256sums=('SKIP'
'c100a61c8dfade43bebc622a363abcb3d935a2f40958371ad87a9eb00689f8b0'
'88e944f23c3b2391dc2e9f9be8e1131152d837dc8c829dfc714663869a272e81'
'af984186f852d2847d770a18fb6822296c50a652dbf55a1ed59d27517c3d3ee4'
- '240ac4c29d96d56407a20e1b7f9846e342a7eb2bb4edd6e5c86b3b5a8ff462f9'
- 'e7b31f5e7ea88681c6eda41e5a74a2859a12dd128e75c00db3cfbd1d8ddf080d')
+ '240ac4c29d96d56407a20e1b7f9846e342a7eb2bb4edd6e5c86b3b5a8ff462f9')
pkgver() {
cd sage
@@ -61,8 +59,6 @@ prepare(){
# Upstream patches
# Replace lrcalc.pyx with a wrapper over lrcalc's python bindings https://trac.sagemath.org/ticket/31355
patch -p1 -i ../sagemath-lrcalc2.patch
-# Fix build with eclib 20210310 https://trac.sagemath.org/ticket/31443
- patch -p1 -i ../sagemath-eclib-20210310.patch
# Arch-specific patches
# assume all optional packages are installed
diff --git a/sagemath-eclib-20210310.patch b/sagemath-eclib-20210310.patch
deleted file mode 100644
index bea233239119..000000000000
--- a/sagemath-eclib-20210310.patch
+++ /dev/null
@@ -1,1406 +0,0 @@
-diff --git a/src/sage/libs/eclib/__init__.pxd b/src/sage/libs/eclib/__init__.pxd
-index 3f99f99..d44d4fb 100644
---- a/src/sage/libs/eclib/__init__.pxd
-+++ b/src/sage/libs/eclib/__init__.pxd
-@@ -12,9 +12,11 @@ from libcpp.pair cimport pair
- from sage.libs.ntl.types cimport ZZ_c
-
-
--# NOTE: eclib includes have specific dependencies and must be included
--# in a specific order. So we start by listing all relevant include files
--# in the correct order.
-+# NOTE: eclib used to have specific dependencies, so that they had to
-+# be included in a specific order. Although this is no longer the
-+# case, we start by listing all relevant include files in the correct
-+# order.
-+
- cdef extern from "eclib/vector.h": pass
- cdef extern from "eclib/xmod.h": pass
- cdef extern from "eclib/svector.h": pass
-diff --git a/src/sage/libs/eclib/interface.py b/src/sage/libs/eclib/interface.py
-index e898456..493b5f1 100644
---- a/src/sage/libs/eclib/interface.py
-+++ b/src/sage/libs/eclib/interface.py
-@@ -21,17 +21,16 @@ Check that ``eclib`` is imported as needed::
- sage: [k for k in sys.modules if k.startswith("sage.libs.eclib")]
- []
- sage: EllipticCurve('11a1').mwrank_curve()
-- y^2+ y = x^3 - x^2 - 10*x - 20
-+ y^2 + y = x^3 - x^2 - 10 x - 20
- sage: [k for k in sys.modules if k.startswith("sage.libs.eclib")]
- ['...']
- """
--
-+import sys
- from sage.structure.sage_object import SageObject
- from sage.rings.all import Integer
- from sage.rings.integer_ring import IntegerRing
-
--from .mwrank import _Curvedata, _two_descent, _mw
--
-+from .mwrank import _Curvedata, _two_descent, _mw, parse_point_list
-
- class mwrank_EllipticCurve(SageObject):
- r"""
-@@ -67,7 +66,7 @@ class mwrank_EllipticCurve(SageObject):
-
- sage: e = mwrank_EllipticCurve([3, -4])
- sage: e
-- y^2 = x^3 + 3*x - 4
-+ y^2 = x^3 + 3 x - 4
- sage: e.ainvs()
- [0, 0, 0, 3, -4]
-
-@@ -127,6 +126,7 @@ class mwrank_EllipticCurve(SageObject):
-
- # place holders
- self.__saturate = -2 # not yet saturated
-+ self.__descent = None
-
- def __reduce__(self):
- r"""
-@@ -137,12 +137,9 @@ class mwrank_EllipticCurve(SageObject):
- sage: E = mwrank_EllipticCurve([0,0,1,-7,6])
- sage: E.__reduce__()
- (<class 'sage.libs.eclib.interface.mwrank_EllipticCurve'>, ([0, 0, 1, -7, 6], False))
--
--
- """
- return mwrank_EllipticCurve, (self.__ainvs, self.__verbose)
-
--
- def set_verbose(self, verbose):
- """
- Set the verbosity of printing of output by the :meth:`two_descent()` and
-@@ -247,53 +244,27 @@ class mwrank_EllipticCurve(SageObject):
-
- sage: E = mwrank_EllipticCurve([0,-1,1,0,0])
- sage: E.__repr__()
-- 'y^2+ y = x^3 - x^2 '
-+ 'y^2 + y = x^3 - x^2'
- """
-- # TODO: Is the use (or omission) of spaces here intentional?
-- a = self.ainvs()
-- s = "y^2"
-- if a[0] == -1:
-- s += "- x*y "
-- elif a[0] == 1:
-- s += "+ x*y "
-- elif a[0] != 0:
-- s += "+ %s*x*y "%a[0]
-- if a[2] == -1:
-- s += " - y"
-- elif a[2] == 1:
-- s += "+ y"
-- elif a[2] != 0:
-- s += "+ %s*y"%a[2]
-- s += " = x^3 "
-- if a[1] == -1:
-- s += "- x^2 "
-- elif a[1] == 1:
-- s += "+ x^2 "
-- elif a[1] != 0:
-- s += "+ %s*x^2 "%a[1]
-- if a[3] == -1:
-- s += "- x "
-- elif a[3] == 1:
-- s += "+ x "
-- elif a[3] != 0:
-- s += "+ %s*x "%a[3]
-- if a[4] == -1:
-- s += "-1"
-- elif a[4] == 1:
-- s += "+1"
-- elif a[4] != 0:
-- s += "+ %s"%a[4]
-- s = s.replace("+ -","- ")
-- return s
--
-+ a1, a2, a3, a4, a6 = self.__ainvs
-+ # we do not assume a1, a2, a3 are reduced to {0,1}, {-1,0,1}, {0,1}
-+ coeff = lambda a: ''.join([" +" if a > 0 else " -",
-+ " " + str(abs(a)) if abs(a) > 1 else ""])
-+ return ''.join(['y^2',
-+ ' '.join([coeff(a1), 'xy']) if a1 else '',
-+ ' '.join([coeff(a3), 'y']) if a3 else '',
-+ ' = x^3',
-+ ' '.join([coeff(a2), 'x^2']) if a2 else '',
-+ ' '.join([coeff(a4), 'x']) if a4 else '',
-+ ' '.join([" +" if a6 > 0 else " -", str(abs(a6))]) if a6 else ''])
-
- def two_descent(self,
-- verbose = True,
-- selmer_only = False,
-- first_limit = 20,
-- second_limit = 8,
-- n_aux = -1,
-- second_descent = True):
-+ verbose=True,
-+ selmer_only=False,
-+ first_limit=20,
-+ second_limit=8,
-+ n_aux=-1,
-+ second_descent=True):
- r"""
- Compute 2-descent data for this curve.
-
-@@ -374,16 +345,14 @@ class mwrank_EllipticCurve(SageObject):
- second_limit = int(second_limit)
- n_aux = int(n_aux)
- second_descent = int(second_descent) # convert from bool to (int) 0 or 1
-- # TODO: Don't allow limits above some value...???
-- # (since otherwise mwrank just sets limit tiny)
- self.__descent = _two_descent()
- self.__descent.do_descent(self.__curve,
-- verbose,
-- selmer_only,
-- first_limit,
-- second_limit,
-- n_aux,
-- second_descent)
-+ verbose,
-+ selmer_only,
-+ first_limit,
-+ second_limit,
-+ n_aux,
-+ second_descent)
- if not self.__descent.ok():
- raise RuntimeError("A 2-descent did not complete successfully.")
- self.__saturate = -2 # not yet saturated
-@@ -398,11 +367,9 @@ class mwrank_EllipticCurve(SageObject):
- sage: E._mwrank_EllipticCurve__two_descent_data()
- <sage.libs.eclib.mwrank._two_descent object at ...>
- """
-- try:
-- return self.__descent
-- except AttributeError:
-+ if self.__descent is None:
- self.two_descent(self.__verbose)
-- return self.__descent
-+ return self.__descent
-
- def conductor(self):
- """
-@@ -565,22 +532,24 @@ class mwrank_EllipticCurve(SageObject):
- R = self.__two_descent_data().regulator()
- return float(R)
-
-- def saturate(self, bound=-1):
-+ def saturate(self, bound=-1, lower=2):
- """
-- Compute the saturation of the Mordell-Weil group at all
-- primes up to ``bound``.
-+ Compute the saturation of the Mordell-Weil group.
-
- INPUT:
-
-- - ``bound`` (int, default -1) -- Use `-1` (the default) to
-- saturate at *all* primes, `0` for no saturation, or `n` (a
-- positive integer) to saturate at all primes up to `n`.
-+ - ``bound`` (int, default -1) -- If `-1`, saturate at *all*
-+ primes by computing a bound on the saturation index,
-+ otherwise saturate at all primes up to the minimum of
-+ ``bound`` and the saturation index bound.
-+
-+ - ``lower`` (int, default 2) -- Only saturate at primes not
-+ less than this.
-
- EXAMPLES:
-
- Since the 2-descent automatically saturates at primes up to
-- 20, it is not easy to come up with an example where saturation
-- has any effect::
-+ 20, further saturation often has no effect::
-
- sage: E = mwrank_EllipticCurve([0, 0, 0, -1002231243161, 0])
- sage: E.gens()
-@@ -599,7 +568,7 @@ class mwrank_EllipticCurve(SageObject):
- """
- bound = int(bound)
- if self.__saturate < bound:
-- self.__two_descent_data().saturate(bound)
-+ self.__two_descent_data().saturate(bound, lower)
- self.__saturate = bound
-
- def gens(self):
-@@ -613,8 +582,7 @@ class mwrank_EllipticCurve(SageObject):
- [[0, -1, 1]]
- """
- self.saturate()
-- L = eval(self.__two_descent_data().getbasis().replace(":",","))
-- return [[Integer(x), Integer(y), Integer(z)] for (x,y,z) in L]
-+ return parse_point_list(self.__two_descent_data().getbasis())
-
- def certain(self):
- r"""
-@@ -760,65 +728,37 @@ class mwrank_MordellWeil(SageObject):
- sage: EQ.search(1)
- P1 = [0:1:0] is torsion point, order 1
- P1 = [-3:0:1] is generator number 1
-- saturating up to 20...Checking 2-saturation
-- Points have successfully been 2-saturated (max q used = 7)
-- Checking 3-saturation
-- Points have successfully been 3-saturated (max q used = 7)
-- Checking 5-saturation
-- Points have successfully been 5-saturated (max q used = 23)
-- Checking 7-saturation
-- Points have successfully been 7-saturated (max q used = 41)
-- Checking 11-saturation
-- Points have successfully been 11-saturated (max q used = 17)
-- Checking 13-saturation
-- Points have successfully been 13-saturated (max q used = 43)
-- Checking 17-saturation
-- Points have successfully been 17-saturated (max q used = 31)
-- Checking 19-saturation
-- Points have successfully been 19-saturated (max q used = 37)
-+ saturating up to 20...Saturation index bound (for points of good reduction) = 3
-+ Reducing saturation bound from given value 20 to computed index bound 3
-+ Checking saturation at [ 2 3 ]
-+ Checking 2-saturation
-+ Points were proved 2-saturated (max q used = 7)
-+ Checking 3-saturation
-+ Points were proved 3-saturated (max q used = 7)
- done
- P2 = [-2:3:1] is generator number 2
-- saturating up to 20...Checking 2-saturation
-+ saturating up to 20...Saturation index bound (for points of good reduction) = 4
-+ Reducing saturation bound from given value 20 to computed index bound 4
-+ Checking saturation at [ 2 3 ]
-+ Checking 2-saturation
- possible kernel vector = [1,1]
- This point may be in 2E(Q): [14:-52:1]
-- ...and it is!
-+ ...and it is!
- Replacing old generator #1 with new generator [1:-1:1]
-+ Reducing index bound from 4 to 2
- Points have successfully been 2-saturated (max q used = 7)
- Index gain = 2^1
-- Checking 3-saturation
-- Points have successfully been 3-saturated (max q used = 13)
-- Checking 5-saturation
-- Points have successfully been 5-saturated (max q used = 67)
-- Checking 7-saturation
-- Points have successfully been 7-saturated (max q used = 53)
-- Checking 11-saturation
-- Points have successfully been 11-saturated (max q used = 73)
-- Checking 13-saturation
-- Points have successfully been 13-saturated (max q used = 103)
-- Checking 17-saturation
-- Points have successfully been 17-saturated (max q used = 113)
-- Checking 19-saturation
-- Points have successfully been 19-saturated (max q used = 47)
-- done (index = 2).
-+ done, index = 2.
- Gained index 2, new generators = [ [1:-1:1] [-2:3:1] ]
- P3 = [-14:25:8] is generator number 3
-- saturating up to 20...Checking 2-saturation
-- Points have successfully been 2-saturated (max q used = 11)
-- Checking 3-saturation
-- Points have successfully been 3-saturated (max q used = 13)
-- Checking 5-saturation
-- Points have successfully been 5-saturated (max q used = 71)
-- Checking 7-saturation
-- Points have successfully been 7-saturated (max q used = 101)
-- Checking 11-saturation
-- Points have successfully been 11-saturated (max q used = 127)
-- Checking 13-saturation
-- Points have successfully been 13-saturated (max q used = 151)
-- Checking 17-saturation
-- Points have successfully been 17-saturated (max q used = 139)
-- Checking 19-saturation
-- Points have successfully been 19-saturated (max q used = 179)
-- done (index = 1).
-+ saturating up to 20...Saturation index bound (for points of good reduction) = 3
-+ Reducing saturation bound from given value 20 to computed index bound 3
-+ Checking saturation at [ 2 3 ]
-+ Checking 2-saturation
-+ Points were proved 2-saturated (max q used = 11)
-+ Checking 3-saturation
-+ Points were proved 3-saturated (max q used = 13)
-+ done, index = 1.
- P4 = [-1:3:1] = -1*P1 + -1*P2 + -1*P3 (mod torsion)
- P4 = [0:2:1] = 2*P1 + 0*P2 + 1*P3 (mod torsion)
- P4 = [2:13:8] = -3*P1 + 1*P2 + -1*P3 (mod torsion)
-@@ -878,7 +818,7 @@ class mwrank_MordellWeil(SageObject):
- sage: E = mwrank_EllipticCurve([0,0,1,-7,6])
- sage: EQ = mwrank_MordellWeil(E)
- sage: EQ.__reduce__()
-- (<class 'sage.libs.eclib.interface.mwrank_MordellWeil'>, (y^2+ y = x^3 - 7*x + 6, True, 1, 999))
-+ (<class 'sage.libs.eclib.interface.mwrank_MordellWeil'>, (y^2 + y = x^3 - 7 x + 6, True, 1, 999))
- """
- return mwrank_MordellWeil, (self.__curve, self.__verbose, self.__pp, self.__maxr)
-
-@@ -902,12 +842,10 @@ class mwrank_MordellWeil(SageObject):
- """
- return "Subgroup of Mordell-Weil group: %s"%self.__mw
-
-- def process(self, v, sat=0):
-- """
-- This function allows one to add points to a :class:`mwrank_MordellWeil` object.
-+ def process(self, v, saturation_bound=0):
-+ """Process points in the list ``v``.
-
-- Process points in the list ``v``, with saturation at primes up to
-- ``sat``. If ``sat`` is zero (the default), do no saturation.
-+ This function allows one to add points to a :class:`mwrank_MordellWeil` object.
-
- INPUT:
-
-@@ -915,8 +853,9 @@ class mwrank_MordellWeil(SageObject):
- list of triples of integers, which define points on the
- curve.
-
-- - ``sat`` (int, default 0) -- saturate at primes up to ``sat``, or at
-- *all* primes if ``sat`` is zero.
-+ - ``saturation_bound`` (int, default 0) -- saturate at primes up to
-+ ``saturation_bound``, or at *all* primes if ``saturation_bound`` is -1; when ``saturation_bound``
-+ is 0 (the default), do no saturation..
-
- OUTPUT:
-
-@@ -939,11 +878,11 @@ class mwrank_MordellWeil(SageObject):
- sage: EQ.points()
- [[1, -1, 1], [-2, 3, 1], [-14, 25, 8]]
-
-- Example to illustrate the saturation parameter ``sat``::
-+ Example to illustrate the saturation parameter ``saturation_bound``::
-
- sage: E = mwrank_EllipticCurve([0,0,1,-7,6])
- sage: EQ = mwrank_MordellWeil(E)
-- sage: EQ.process([[1547, -2967, 343], [2707496766203306, 864581029138191, 2969715140223272], [-13422227300, -49322830557, 12167000000]], sat=20)
-+ sage: EQ.process([[1547, -2967, 343], [2707496766203306, 864581029138191, 2969715140223272], [-13422227300, -49322830557, 12167000000]], saturation_bound=20)
- P1 = [1547:-2967:343] is generator number 1
- ...
- Gained index 5, new generators = [ [-2:3:1] [-14:25:8] [1:-1:1] ]
-@@ -956,7 +895,7 @@ class mwrank_MordellWeil(SageObject):
-
- sage: E = mwrank_EllipticCurve([0,0,1,-7,6])
- sage: EQ = mwrank_MordellWeil(E)
-- sage: EQ.process([[1547, -2967, 343], [2707496766203306, 864581029138191, 2969715140223272], [-13422227300, -49322830557, 12167000000]], sat=0)
-+ sage: EQ.process([[1547, -2967, 343], [2707496766203306, 864581029138191, 2969715140223272], [-13422227300, -49322830557, 12167000000]], saturation_bound=0)
- P1 = [1547:-2967:343] is generator number 1
- P2 = [2707496766203306:864581029138191:2969715140223272] is generator number 2
- P3 = [-13422227300:-49322830557:12167000000] is generator number 3
-@@ -965,55 +904,92 @@ class mwrank_MordellWeil(SageObject):
- sage: EQ.regulator()
- 375.42920288254555
- sage: EQ.saturate(2) # points were not 2-saturated
-- saturating basis...Saturation index bound = 93
-- WARNING: saturation at primes p > 2 will not be done;
-- ...
-+ saturating basis...Saturation index bound (for points of good reduction) = 93
-+ Only p-saturating for p up to given value 2.
-+ The resulting points may not be p-saturated for p between this and the computed index bound 93
-+ Checking saturation at [ 2 ]
-+ Checking 2-saturation
-+ possible kernel vector = [1,0,0]
-+ This point may be in 2E(Q): [1547:-2967:343]
-+ ...and it is!
-+ Replacing old generator #1 with new generator [-2:3:1]
-+ Reducing index bound from 93 to 46
-+ Points have successfully been 2-saturated (max q used = 11)
-+ Index gain = 2^1
-+ done
- Gained index 2
-- New regulator = 93.857...
-- (False, 2, '[ ]')
-+ New regulator = 93.85730072
-+ (True, 2, '[ ]')
- sage: EQ.points()
- [[-2, 3, 1], [2707496766203306, 864581029138191, 2969715140223272], [-13422227300, -49322830557, 12167000000]]
- sage: EQ.regulator()
- 93.85730072063639
- sage: EQ.saturate(3) # points were not 3-saturated
-- saturating basis...Saturation index bound = 46
-- WARNING: saturation at primes p > 3 will not be done;
-- ...
-+ saturating basis...Saturation index bound (for points of good reduction) = 46
-+ Only p-saturating for p up to given value 3.
-+ The resulting points may not be p-saturated for p between this and the computed index bound 46
-+ Checking saturation at [ 2 3 ]
-+ Checking 2-saturation
-+ Points were proved 2-saturated (max q used = 11)
-+ Checking 3-saturation
-+ possible kernel vector = [0,1,0]
-+ This point may be in 3E(Q): [2707496766203306:864581029138191:2969715140223272]
-+ ...and it is!
-+ Replacing old generator #2 with new generator [-14:25:8]
-+ Reducing index bound from 46 to 15
-+ Points have successfully been 3-saturated (max q used = 13)
-+ Index gain = 3^1
-+ done
- Gained index 3
-- New regulator = 10.428...
-- (False, 3, '[ ]')
-+ New regulator = 10.42858897
-+ (True, 3, '[ ]')
- sage: EQ.points()
- [[-2, 3, 1], [-14, 25, 8], [-13422227300, -49322830557, 12167000000]]
- sage: EQ.regulator()
- 10.4285889689596
- sage: EQ.saturate(5) # points were not 5-saturated
-- saturating basis...Saturation index bound = 15
-- WARNING: saturation at primes p > 5 will not be done;
-- ...
-+ saturating basis...Saturation index bound (for points of good reduction) = 15
-+ Only p-saturating for p up to given value 5.
-+ The resulting points may not be p-saturated for p between this and the computed index bound 15
-+ Checking saturation at [ 2 3 5 ]
-+ Checking 2-saturation
-+ Points were proved 2-saturated (max q used = 11)
-+ Checking 3-saturation
-+ Points were proved 3-saturated (max q used = 13)
-+ Checking 5-saturation
-+ possible kernel vector = [0,0,1]
-+ This point may be in 5E(Q): [-13422227300:-49322830557:12167000000]
-+ ...and it is!
-+ Replacing old generator #3 with new generator [1:-1:1]
-+ Reducing index bound from 15 to 3
-+ Points have successfully been 5-saturated (max q used = 71)
-+ Index gain = 5^1
-+ done
- Gained index 5
-- New regulator = 0.417...
-- (False, 5, '[ ]')
-+ New regulator = 0.4171435588
-+ (True, 5, '[ ]')
- sage: EQ.points()
- [[-2, 3, 1], [-14, 25, 8], [1, -1, 1]]
- sage: EQ.regulator()
- 0.417143558758384
- sage: EQ.saturate() # points are now saturated
-- saturating basis...Saturation index bound = 3
-+ saturating basis...Saturation index bound (for points of good reduction) = 3
-+ Tamagawa index primes are [ ]
- Checking saturation at [ 2 3 ]
-- Checking 2-saturation
-+ Checking 2-saturation
- Points were proved 2-saturated (max q used = 11)
-- Checking 3-saturation
-+ Checking 3-saturation
- Points were proved 3-saturated (max q used = 13)
- done
- (True, 1, '[ ]')
- """
- if not isinstance(v, list):
- raise TypeError("v (=%s) must be a list"%v)
-- sat = int(sat)
-+ saturation_bound = int(saturation_bound)
- for P in v:
-- if not isinstance(P, (list,tuple)) or len(P) != 3:
-+ if not isinstance(P, (list, tuple)) or len(P) != 3:
- raise TypeError("v (=%s) must be a list of 3-tuples (or 3-element lists) of ints"%v)
-- self.__mw.process(P, sat)
-+ self.__mw.process(P, saturation_bound)
-
- def regulator(self):
- """
-@@ -1091,23 +1067,21 @@ class mwrank_MordellWeil(SageObject):
- """
- return self.__mw.rank()
-
-- def saturate(self, max_prime=-1, odd_primes_only=False):
-- r"""
-- Saturate this subgroup of the Mordell-Weil group.
-+ def saturate(self, max_prime=-1, min_prime=2):
-+ r"""Saturate this subgroup of the Mordell-Weil group.
-
- INPUT:
-
-- - ``max_prime`` (int, default -1) -- saturation is performed for
-- all primes up to ``max_prime``. If `-1` (the default), an
-+ - ``max_prime`` (int, default -1) -- If `-1` (the default), an
- upper bound is computed for the primes at which the subgroup
-- may not be saturated, and this is used; however, if the
-- computed bound is greater than a value set by the ``eclib``
-- library (currently 97) then no saturation will be attempted
-- at primes above this.
-+ may not be saturated, and saturation is performed for all
-+ primes up to this bound. Otherwise, the bound used is the
-+ minimum of ``max_prime`` and the computed bound.
-
-- - ``odd_primes_only`` (bool, default ``False``) -- only do
-- saturation at odd primes. (If the points have been found
-- via :meth:`two_descent` they should already be 2-saturated.)
-+ - ``min_prime`` (int, default 2) -- only do saturation at
-+ primes no less than this. (For example, if the points have
-+ been found via :meth:`two_descent` they should already be
-+ 2-saturated so a value of 3 is appropriate.)
-
- OUTPUT:
-
-@@ -1115,40 +1089,35 @@ class mwrank_MordellWeil(SageObject):
-
- - ``ok`` (bool) -- ``True`` if and only if the saturation was
- provably successful at all primes attempted. If the default
-- was used for ``max_prime`` and no warning was output about
-- the computed saturation bound being too high, then ``True``
-- indicates that the subgroup is saturated at *all*
-- primes.
-+ was used for ``max_prime``, then ``True`` indicates that the
-+ subgroup is saturated at *all* primes.
-
- - ``index`` (int) -- the index of the group generated by the
- original points in their saturation.
-
- - ``unsatlist`` (list of ints) -- list of primes at which
-- saturation could not be proved or achieved. Increasing the
-- precision should correct this, since it happens when
-- a linear combination of the points appears to be a multiple
-- of `p` but cannot be divided by `p`. (Note that ``eclib``
-- uses floating point methods based on elliptic logarithms to
-- divide points.)
-+ saturation could not be proved or achieved.
-
- .. note::
-
-- We emphasize that if this function returns ``True`` as the
-- first return argument (``ok``), and if the default was used for the
-- parameter ``max_prime``, then the points in the basis after
-- calling this function are saturated at *all* primes,
-- i.e., saturating at the primes up to ``max_prime`` are
-- sufficient to saturate at all primes. Note that the
-- function might not have needed to saturate at all primes up
-- to ``max_prime``. It has worked out what prime you need to
-- saturate up to, and that prime might be smaller than ``max_prime``.
-+ In versions up to v20190909, ``eclib`` used floating point
-+ methods based on elliptic logarithms to divide points, and
-+ did not compute the precision necessary, which could casue
-+ failures. Since v20210310, ``eclib`` uses exact method based
-+ on division polynomials, which should mean that such
-+ failures does not happen.
-
- .. note::
-
-- Currently (May 2010), this does not remember the result of
-- calling :meth:`search()`. So calling :meth:`search()` up
-- to height 20 then calling :meth:`saturate()` results in
-- another search up to height 18.
-+ We emphasize that if this function returns ``True`` as the
-+ first return argument (``ok``), and if the default was used
-+ for the parameter ``max_prime``, then the points in the
-+ basis after calling this function are saturated at *all*
-+ primes, i.e., saturating at the primes up to ``max_prime``
-+ are sufficient to saturate at all primes. Note that the
-+ function computes an upper bound for the index of
-+ saturation, and does no work for primes greater than this
-+ even if ``max_prime`` is larger.
-
- EXAMPLES::
-
-@@ -1160,7 +1129,7 @@ class mwrank_MordellWeil(SageObject):
- automatic saturation at this stage we set the parameter
- ``sat`` to 0 (which is in fact the default)::
-
-- sage: EQ.process([[1547, -2967, 343], [2707496766203306, 864581029138191, 2969715140223272], [-13422227300, -49322830557, 12167000000]], sat=0)
-+ sage: EQ.process([[1547, -2967, 343], [2707496766203306, 864581029138191, 2969715140223272], [-13422227300, -49322830557, 12167000000]], saturation_bound=0)
- P1 = [1547:-2967:343] is generator number 1
- P2 = [2707496766203306:864581029138191:2969715140223272] is generator number 2
- P3 = [-13422227300:-49322830557:12167000000] is generator number 3
-@@ -1172,12 +1141,12 @@ class mwrank_MordellWeil(SageObject):
- Now we saturate at `p=2`, and gain index 2::
-
- sage: EQ.saturate(2) # points were not 2-saturated
-- saturating basis...Saturation index bound = 93
-- WARNING: saturation at primes p > 2 will not be done;
-+ saturating basis...Saturation index bound (for points of good reduction) = 93
-+ Only p-saturating for p up to given value 2.
- ...
- Gained index 2
- New regulator = 93.857...
-- (False, 2, '[ ]')
-+ (True, 2, '[ ]')
- sage: EQ
- Subgroup of Mordell-Weil group: [[-2:3:1], [2707496766203306:864581029138191:2969715140223272], [-13422227300:-49322830557:12167000000]]
- sage: EQ.regulator()
-@@ -1186,12 +1155,12 @@ class mwrank_MordellWeil(SageObject):
- Now we saturate at `p=3`, and gain index 3::
-
- sage: EQ.saturate(3) # points were not 3-saturated
-- saturating basis...Saturation index bound = 46
-- WARNING: saturation at primes p > 3 will not be done;
-+ saturating basis...Saturation index bound (for points of good reduction) = 46
-+ Only p-saturating for p up to given value 3.
- ...
- Gained index 3
- New regulator = 10.428...
-- (False, 3, '[ ]')
-+ (True, 3, '[ ]')
- sage: EQ
- Subgroup of Mordell-Weil group: [[-2:3:1], [-14:25:8], [-13422227300:-49322830557:12167000000]]
- sage: EQ.regulator()
-@@ -1200,12 +1169,12 @@ class mwrank_MordellWeil(SageObject):
- Now we saturate at `p=5`, and gain index 5::
-
- sage: EQ.saturate(5) # points were not 5-saturated
-- saturating basis...Saturation index bound = 15
-- WARNING: saturation at primes p > 5 will not be done;
-+ saturating basis...Saturation index bound (for points of good reduction) = 15
-+ Only p-saturating for p up to given value 5.
- ...
- Gained index 5
- New regulator = 0.417...
-- (False, 5, '[ ]')
-+ (True, 5, '[ ]')
- sage: EQ
- Subgroup of Mordell-Weil group: [[-2:3:1], [-14:25:8], [1:-1:1]]
- sage: EQ.regulator()
-@@ -1215,7 +1184,8 @@ class mwrank_MordellWeil(SageObject):
- the points are now provably saturated at all primes::
-
- sage: EQ.saturate() # points are now saturated
-- saturating basis...Saturation index bound = 3
-+ saturating basis...Saturation index bound (for points of good reduction) = 3
-+ Tamagawa index primes are [ ]
- Checking saturation at [ 2 3 ]
- Checking 2-saturation
- Points were proved 2-saturated (max q used = 11)
-@@ -1229,7 +1199,7 @@ class mwrank_MordellWeil(SageObject):
-
- sage: E = mwrank_EllipticCurve([0,0,1,-7,6])
- sage: EQ = mwrank_MordellWeil(E)
-- sage: EQ.process([[1547, -2967, 343], [2707496766203306, 864581029138191, 2969715140223272], [-13422227300, -49322830557, 12167000000]], sat=5)
-+ sage: EQ.process([[1547, -2967, 343], [2707496766203306, 864581029138191, 2969715140223272], [-13422227300, -49322830557, 12167000000]], saturation_bound=5)
- P1 = [1547:-2967:343] is generator number 1
- ...
- Gained index 5, new generators = [ [-2:3:1] [-14:25:8] [1:-1:1] ]
-@@ -1242,7 +1212,8 @@ class mwrank_MordellWeil(SageObject):
- verify that full saturation has been done::
-
- sage: EQ.saturate()
-- saturating basis...Saturation index bound = 3
-+ saturating basis...Saturation index bound (for points of good reduction) = 3
-+ Tamagawa index primes are [ ]
- Checking saturation at [ 2 3 ]
- Checking 2-saturation
- Points were proved 2-saturated (max q used = 11)
-@@ -1255,8 +1226,9 @@ class mwrank_MordellWeil(SageObject):
- index of the points in their saturation is at most 3, then
- proves saturation at 2 and at 3, by reducing the points modulo
- all primes of good reduction up to 11, respectively 13.
-+
- """
-- ok, index, unsat = self.__mw.saturate(int(max_prime), odd_primes_only)
-+ ok, index, unsat = self.__mw.saturate(int(max_prime), int(min_prime))
- return bool(ok), int(str(index)), unsat
-
- def search(self, height_limit=18, verbose=False):
-@@ -1271,9 +1243,9 @@ class mwrank_MordellWeil(SageObject):
-
- .. note::
-
-- On 32-bit machines, this *must* be < 21.48 else
-+ On 32-bit machines, this *must* be < 21.48 (`31\log(2)`) else
- `\exp(h_{\text{lim}}) > 2^{31}` and overflows. On 64-bit machines, it
-- must be *at most* 43.668. However, this bound is a logarithmic
-+ must be *at most* 43.668 (`63\log(2)`) . However, this bound is a logarithmic
- bound and increasing it by just 1 increases the running time
- by (roughly) `\exp(1.5)=4.5`, so searching up to even 20
- takes a very long time.
-@@ -1320,8 +1292,10 @@ class mwrank_MordellWeil(SageObject):
- Subgroup of Mordell-Weil group: [[4413270:10381877:27000]]
- """
- height_limit = float(height_limit)
-- if height_limit >= 21.4: # TODO: docstring says 21.48 (for 32-bit machines; what about 64-bit...?)
-- raise ValueError("The height limit must be < 21.4.")
-+ int_bits = sys.maxsize.bit_length()
-+ max_height_limit = int_bits * 0.693147 # log(2.0) = 0.693147 approx
-+ if height_limit >= max_height_limit:
-+ raise ValueError("The height limit must be < {} = {}log(2) on a {}-bit machine.".format(max_height_limit, int_bits, int_bits+1))
-
- moduli_option = 0 # Use Stoll's sieving program... see strategies in ratpoints-1.4.c
-
-@@ -1352,5 +1326,4 @@ class mwrank_MordellWeil(SageObject):
- [[1, -1, 1], [-2, 3, 1], [-14, 25, 8]]
-
- """
-- L = eval(self.__mw.getbasis().replace(":",","))
-- return [[Integer(x), Integer(y), Integer(z)] for (x,y,z) in L]
-+ return self.__mw.getbasis()
-diff --git a/src/sage/libs/eclib/mwrank.pyx b/src/sage/libs/eclib/mwrank.pyx
-index b82831d..ce5090c 100644
---- a/src/sage/libs/eclib/mwrank.pyx
-+++ b/src/sage/libs/eclib/mwrank.pyx
-@@ -28,6 +28,7 @@ from cysignals.signals cimport sig_on, sig_off
- from sage.cpython.string cimport char_to_str, str_to_bytes
- from sage.cpython.string import FS_ENCODING
- from sage.libs.eclib cimport bigint, Curvedata, mw, two_descent
-+from sage.rings.all import Integer
-
- cdef extern from "wrap.cpp":
- ### misc functions ###
-@@ -55,8 +56,8 @@ cdef extern from "wrap.cpp":
- char* mw_getbasis(mw* m)
- double mw_regulator(mw* m)
- int mw_rank(mw* m)
-- int mw_saturate(mw* m, bigint* index, char** unsat,
-- long sat_bd, int odd_primes_only)
-+ int mw_saturate(mw* m, long* index, char** unsat,
-+ long sat_bd, long sat_low_bd)
- void mw_search(mw* m, char* h_lim, int moduli_option, int verb)
-
- ### two_descent ###
-@@ -67,8 +68,7 @@ cdef extern from "wrap.cpp":
- long two_descent_get_rank(two_descent* t)
- long two_descent_get_rank_bound(two_descent* t)
- long two_descent_get_selmer_rank(two_descent* t)
-- void two_descent_saturate(two_descent* t, long sat_bd)
--
-+ void two_descent_saturate(two_descent* t, long sat_bd, long sat_low_bd)
-
- cdef object string_sigoff(char* s):
- sig_off()
-@@ -445,7 +445,6 @@ cdef class _Curvedata: # cython class wrapping eclib's Curvedata class
- -1269581104000000
- """
- sig_on()
-- from sage.rings.all import Integer
- return Integer(string_sigoff(Curvedata_getdiscr(self.x)))
-
- def conductor(self):
-@@ -467,7 +466,6 @@ cdef class _Curvedata: # cython class wrapping eclib's Curvedata class
- 126958110400
- """
- sig_on()
-- from sage.rings.all import Integer
- return Integer(string_sigoff(Curvedata_conductor(self.x)))
-
- def isogeny_class(self, verbose=False):
-@@ -503,6 +501,36 @@ cdef class _Curvedata: # cython class wrapping eclib's Curvedata class
-
- ############# _mw #################
-
-+def parse_point_list(s):
-+ r"""
-+ Parse a string representing a list of points.
-+
-+ INPUT:
-+
-+ - ``s`` (string) -- string representation of a list of points, for
-+ example '[]', '[[1:2:3]]', or '[[1:2:3],[4:5:6]]'.
-+
-+ OUTPUT:
-+
-+ (list) a list of triples of integers, for example [], [[1,2,3]], [[1,2,3],[4,5,6]].
-+
-+ EXAMPLES::
-+
-+ sage: from sage.libs.eclib.mwrank import parse_point_list
-+ sage: parse_point_list('[]')
-+ []
-+ sage: parse_point_list('[[1:2:3]]')
-+ [[1, 2, 3]]
-+ sage: parse_point_list('[[1:2:3],[4:5:6]]')
-+ [[1, 2, 3], [4, 5, 6]]
-+
-+ """
-+ s = s.replace(":", ",").replace(" ", "")
-+ if s == '[]':
-+ return []
-+ pts = s[2:-2].split('],[')
-+ return [[Integer(x) for x in pt.split(",")] for pt in pts]
-+
- cdef class _mw:
- """
- Cython class wrapping eclib's mw class.
-@@ -561,72 +589,37 @@ cdef class _mw:
- sage: EQ.search(1)
- P1 = [0:1:0] is torsion point, order 1
- P1 = [-3:0:1] is generator number 1
-- ...
-- P4 = [12:35:27] = 1*P1 + -1*P2 + -1*P3 (mod torsion)
--
-- The previous command produces the following output::
--
-- P1 = [0:1:0] is torsion point, order 1
-- P1 = [-3:0:1] is generator number 1
-- saturating up to 20...Checking 2-saturation
-- Points have successfully been 2-saturated (max q used = 7)
-- Checking 3-saturation
-- Points have successfully been 3-saturated (max q used = 7)
-- Checking 5-saturation
-- Points have successfully been 5-saturated (max q used = 23)
-- Checking 7-saturation
-- Points have successfully been 7-saturated (max q used = 41)
-- Checking 11-saturation
-- Points have successfully been 11-saturated (max q used = 17)
-- Checking 13-saturation
-- Points have successfully been 13-saturated (max q used = 43)
-- Checking 17-saturation
-- Points have successfully been 17-saturated (max q used = 31)
-- Checking 19-saturation
-- Points have successfully been 19-saturated (max q used = 37)
-+ saturating up to 20...Saturation index bound (for points of good reduction) = 3
-+ Reducing saturation bound from given value 20 to computed index bound 3
-+ Checking saturation at [ 2 3 ]
-+ Checking 2-saturation
-+ Points were proved 2-saturated (max q used = 7)
-+ Checking 3-saturation
-+ Points were proved 3-saturated (max q used = 7)
- done
- P2 = [-2:3:1] is generator number 2
-- saturating up to 20...Checking 2-saturation
-+ saturating up to 20...Saturation index bound (for points of good reduction) = 4
-+ Reducing saturation bound from given value 20 to computed index bound 4
-+ Checking saturation at [ 2 3 ]
-+ Checking 2-saturation
- possible kernel vector = [1,1]
- This point may be in 2E(Q): [14:-52:1]
-- ...and it is!
-+ ...and it is!
- Replacing old generator #1 with new generator [1:-1:1]
-+ Reducing index bound from 4 to 2
- Points have successfully been 2-saturated (max q used = 7)
- Index gain = 2^1
-- Checking 3-saturation
-- Points have successfully been 3-saturated (max q used = 13)
-- Checking 5-saturation
-- Points have successfully been 5-saturated (max q used = 67)
-- Checking 7-saturation
-- Points have successfully been 7-saturated (max q used = 53)
-- Checking 11-saturation
-- Points have successfully been 11-saturated (max q used = 73)
-- Checking 13-saturation
-- Points have successfully been 13-saturated (max q used = 103)
-- Checking 17-saturation
-- Points have successfully been 17-saturated (max q used = 113)
-- Checking 19-saturation
-- Points have successfully been 19-saturated (max q used = 47)
-- done (index = 2).
-+ done, index = 2.
- Gained index 2, new generators = [ [1:-1:1] [-2:3:1] ]
- P3 = [-14:25:8] is generator number 3
-- saturating up to 20...Checking 2-saturation
-- Points have successfully been 2-saturated (max q used = 11)
-- Checking 3-saturation
-- Points have successfully been 3-saturated (max q used = 13)
-- Checking 5-saturation
-- Points have successfully been 5-saturated (max q used = 71)
-- Checking 7-saturation
-- Points have successfully been 7-saturated (max q used = 101)
-- Checking 11-saturation
-- Points have successfully been 11-saturated (max q used = 127)
-- Checking 13-saturation
-- Points have successfully been 13-saturated (max q used = 151)
-- Checking 17-saturation
-- Points have successfully been 17-saturated (max q used = 139)
-- Checking 19-saturation
-- Points have successfully been 19-saturated (max q used = 179)
-- done (index = 1).
-+ saturating up to 20...Saturation index bound (for points of good reduction) = 3
-+ Reducing saturation bound from given value 20 to computed index bound 3
-+ Checking saturation at [ 2 3 ]
-+ Checking 2-saturation
-+ Points were proved 2-saturated (max q used = 11)
-+ Checking 3-saturation
-+ Points were proved 3-saturated (max q used = 13)
-+ done, index = 1.
- P4 = [-1:3:1] = -1*P1 + -1*P2 + -1*P3 (mod torsion)
- P4 = [0:2:1] = 2*P1 + 0*P2 + 1*P3 (mod torsion)
- P4 = [2:13:8] = -3*P1 + 1*P2 + -1*P3 (mod torsion)
-@@ -687,7 +680,7 @@ cdef class _mw:
- sig_on()
- return string_sigoff(mw_getbasis(self.x))
-
-- def process(self, point, sat=0):
-+ def process(self, point, saturation_bound=0):
- """
- Processes the given point, adding it to the mw group.
-
-@@ -697,10 +690,12 @@ cdef class _mw:
- An ``ArithmeticError`` is raised if the point is not on the
- curve.
-
-- - ``sat`` (int, default 0) --saturate at primes up to ``sat``.
-- No saturation is done if ``sat=0``. (Note that it is more
-- efficient to add several points at once and then saturate
-- just once at the end).
-+ - ``saturation_bound`` (int, default 0) --saturate at primes up to ``saturation_bound``.
-+ No saturation is done if ``saturation_bound=0``. If ``saturation_bound=-1`` then
-+ saturation is done at all primes, by computing a bound on
-+ the saturation index. Note that it is more efficient to add
-+ several points at once and then saturate just once at the
-+ end.
-
- .. NOTE::
-
-@@ -746,7 +741,7 @@ cdef class _mw:
- cdef _bigint x,y,z
- sig_on()
- x,y,z = _bigint(point[0]), _bigint(point[1]), _bigint(point[2])
-- r = mw_process(self.curve, self.x, x.x, y.x, z.x, sat)
-+ r = mw_process(self.curve, self.x, x.x, y.x, z.x, saturation_bound)
- sig_off()
- if r != 0:
- raise ArithmeticError("point (=%s) not on curve." % point)
-@@ -757,8 +752,8 @@ cdef class _mw:
-
- OUTPUT:
-
-- (string) String representation of the points in the basis of
-- the mw group.
-+ (list) list of integer triples giving the projective
-+ coordinates of the points in the basis.
-
- EXAMPLES::
-
-@@ -768,13 +763,13 @@ cdef class _mw:
- sage: EQ = _mw(E)
- sage: EQ.search(3)
- sage: EQ.getbasis()
-- '[[0:-1:1], [-1:1:1]]'
-+ [[0, -1, 1], [-1, 1, 1]]
- sage: EQ.rank()
- 2
- """
- sig_on()
- s = string_sigoff(mw_getbasis(self.x))
-- return s
-+ return parse_point_list(s)
-
- def regulator(self):
- """
-@@ -797,7 +792,7 @@ cdef class _mw:
- sage: EQ = _mw(E)
- sage: EQ.search(3)
- sage: EQ.getbasis()
-- '[[0:-1:1], [-1:1:1]]'
-+ [[0, -1, 1], [-1, 1, 1]]
- sage: EQ.rank()
- 2
- sage: EQ.regulator()
-@@ -824,39 +819,54 @@ cdef class _mw:
- sage: EQ = _mw(E)
- sage: EQ.search(3)
- sage: EQ.getbasis()
-- '[[0:-1:1], [-1:1:1]]'
-+ [[0, -1, 1], [-1, 1, 1]]
- sage: EQ.rank()
- 2
- """
- sig_on()
- r = mw_rank(self.x)
- sig_off()
-- from sage.rings.all import Integer
- return Integer(r)
-
-- def saturate(self, int sat_bd=-1, int odd_primes_only=0):
-+ def saturate(self, int sat_bd=-1, int sat_low_bd=2):
- """
- Saturates the current subgroup of the mw group.
-
- INPUT:
-
-- - ``sat_bnd`` (int, default -1) -- bound on primes at which to
-- saturate. If -1 (default), compute a bound for the primes
-- which may not be saturated, and use that.
-+ - ``sat_bnd`` (int, default -1) -- upper bound on primes at
-+ which to saturate. If -1 (default), compute a bound for the
-+ primes which may not be saturated, and use that. Otherwise,
-+ the bound used is the minumum of the value of ``sat_bnd``
-+ and the computed bound.
-
-- - ``odd_primes_only`` (bool, default ``False``) -- only do
-- saturation at odd primes. (If the points have been found
-- via 2-descent they should already be 2-saturated.)
-+ - ``sat_low_bd`` (int, default 2) -- only do saturation at
-+ prime not less than this. For exampe, if the points have
-+ been found via 2-descent they should already be 2-saturated,
-+ and ``sat_low_bd=3`` is appropriate.
-
- OUTPUT:
-
- (tuple) (success flag, index, list) The success flag will be 1
- unless something failed (usually an indication that the points
-- were not saturated but the precision is not high enough to
-- divide out successfully). The index is the index of the mw
-- group before saturation in the mw group after. The list is a
-- string representation of the primes at which saturation was
-- not proved or achieved.
-+ were not saturated but eclib was not able to divide out
-+ successfully). The index is the index of the mw group before
-+ saturation in the mw group after. The list is a string
-+ representation of the primes at which saturation was not
-+ proved or achieved.
-+
-+ .. NOTE::
-+
-+ ``eclib`` will compute a bound on the saturation index. If
-+ the computed saturation bound is very large and ``sat_bnd`` is
-+ -1, ``eclib`` may output a warning, but will still attempt to
-+ saturate up to the computed bound. If a positive value of
-+ ``sat_bnd`` is given which is greater than the computed bound,
-+ `p`-saturation will only be carried out for primes up to the
-+ compated bound. Setting ``sat_low_bnd`` to a value greater
-+ than 2 allows for saturation to be done incrementally, or for
-+ exactly one prime `p` by setting both ``sat_bd`` and
-+ ``sat_low_bd`` to `p`.
-
- EXAMPLES::
-
-@@ -872,34 +882,23 @@ cdef class _mw:
- sage: EQ
- [[-1:1:1]]
-
-- If we set the saturation bound at 2, then saturation will fail::
-+ If we set the saturation bound at 2, then saturation will not
-+ enlarge the basis, but the success flag is still 1 (True)
-+ since we did not ask to check 3-saturation::
-
- sage: EQ = _mw(E)
- sage: EQ.process([494, -5720, 6859]) # 3 times another point
- sage: EQ.saturate(sat_bd=2)
-- Saturation index bound = 10
-- WARNING: saturation at primes p > 2 will not be done;
-- points may be unsaturated at primes between 2 and index bound
-- Failed to saturate MW basis at primes [ ]
-- (0, 1, '[ ]')
-+ (1, 1, '[ ]')
- sage: EQ
- [[494:-5720:6859]]
-
-- The following output is also seen in the preceding example::
--
-- Saturation index bound = 10
-- WARNING: saturation at primes p > 2 will not be done;
-- points may be unsaturated at primes between 2 and index bound
-- Failed to saturate MW basis at primes [ ]
--
--
- """
-- cdef _bigint index
-+ cdef long index
- cdef char* s
- cdef int ok
- sig_on()
-- index = _bigint()
-- ok = mw_saturate(self.x, index.x, &s, sat_bd, odd_primes_only)
-+ ok = mw_saturate(self.x, &index, &s, sat_bd, sat_low_bd)
- unsat = string_sigoff(s)
- return ok, index, unsat
-
-@@ -1094,7 +1093,6 @@ cdef class _two_descent:
- sig_on()
- r = two_descent_get_rank(self.x)
- sig_off()
-- from sage.rings.all import Integer
- return Integer(r)
-
- def getrankbound(self):
-@@ -1128,7 +1126,6 @@ cdef class _two_descent:
- sig_on()
- r = two_descent_get_rank_bound(self.x)
- sig_off()
-- from sage.rings.all import Integer
- return Integer(r)
-
- def getselmer(self):
-@@ -1161,7 +1158,6 @@ cdef class _two_descent:
- sig_on()
- r = two_descent_get_selmer_rank(self.x)
- sig_off()
-- from sage.rings.all import Integer
- return Integer(r)
-
- def ok(self):
-@@ -1222,10 +1218,21 @@ cdef class _two_descent:
- """
- return two_descent_get_certain(self.x)
-
-- def saturate(self, saturation_bound=0):
-+ def saturate(self, saturation_bound=0, lower=3):
- """
- Carries out saturation of the points found by a 2-descent.
-
-+ INPUT:
-+
-+ - ``saturation_bound`` (int) -- an upper bound on the primes
-+ `p` at which `p`-saturation will be carried out, or -1, in
-+ which case ``eclib`` will compute an upper bound on the
-+ saturation index.
-+
-+ - ``lower`` (int, default 3) -- do no `p`-saturation for `p`
-+ less than this. The default is 3 since the points found
-+ during 2-descent will be 2-saturated.
-+
- OUTPUT:
-
- None.
-@@ -1257,7 +1264,7 @@ cdef class _two_descent:
- '[[1:-1:1], [-2:3:1], [-14:25:8]]'
- """
- sig_on()
-- two_descent_saturate(self.x, saturation_bound)
-+ two_descent_saturate(self.x, saturation_bound, 3)
- sig_off()
-
- def getbasis(self):
-diff --git a/src/sage/libs/eclib/newforms.pyx b/src/sage/libs/eclib/newforms.pyx
-index b50b606..96263cd 100644
---- a/src/sage/libs/eclib/newforms.pyx
-+++ b/src/sage/libs/eclib/newforms.pyx
-@@ -140,6 +140,7 @@ cdef class ECModularSymbol:
-
- - ``nap`` - (int, default 1000): the number of ap of E to use
- in determining the normalisation of the modular symbols.
-+ Note that eclib will increase this to 100*sqrt(N) if necessary.
-
- EXAMPLES::
-
-diff --git a/src/sage/libs/eclib/t b/src/sage/libs/eclib/t
-new file mode 100644
-index 00000000..e69de29
---- /dev/null
-+++ b/src/sage/libs/eclib/t
-diff --git a/src/sage/libs/eclib/wrap.cpp b/src/sage/libs/eclib/wrap.cpp
-index 58c18ab..28e6da8 100644
---- a/src/sage/libs/eclib/wrap.cpp
-+++ b/src/sage/libs/eclib/wrap.cpp
-@@ -178,11 +178,11 @@ int mw_rank(struct mw* m)
- }
-
- /* Returns index and unsat long array, which user must deallocate */
--int mw_saturate(struct mw* m, bigint* index, char** unsat,
-- long sat_bd, int odd_primes_only)
-+int mw_saturate(struct mw* m, long* index, char** unsat,
-+ long sat_bd, long sat_low_bd)
- {
- vector<long> v;
-- int s = m->saturate(*index, v, sat_bd, odd_primes_only);
-+ int s = m->saturate(*index, v, sat_bd, sat_low_bd);
- ostringstream instore;
- instore << v;
- *unsat = stringstream_to_char(instore);
-@@ -236,9 +236,9 @@ long two_descent_get_certain(const two_descent* t)
- return t->getcertain();
- }
-
--void two_descent_saturate(struct two_descent* t, long sat_bd)
-+void two_descent_saturate(struct two_descent* t, long sat_bd, long sat_low_bd)
- {
-- t->saturate(sat_bd);
-+ t->saturate(sat_bd, sat_low_bd);
- }
-
- double two_descent_regulator(struct two_descent* t)
-diff --git a/src/sage/schemes/elliptic_curves/ell_modular_symbols.py b/src/sage/schemes/elliptic_curves/ell_modular_symbols.py
-index a32f64e..30a61e1 100644
---- a/src/sage/schemes/elliptic_curves/ell_modular_symbols.py
-+++ b/src/sage/schemes/elliptic_curves/ell_modular_symbols.py
-@@ -298,19 +298,27 @@ class ModularSymbolECLIB(ModularSymbol):
- sage: m(0)
- 1/5
-
-- If ``nap`` is too small, the normalization in eclib may be incorrect. See :trac:`31317`::
-+ If ``nap`` is too small, the normalization in eclib used to be
-+ incorrect (see :trac:`31317`), but since ``eclib`` version
-+ v20210310 the value of ``nap`` is increased automatically by
-+ ``eclib``::
-
- sage: from sage.schemes.elliptic_curves.ell_modular_symbols import ModularSymbolECLIB
- sage: E = EllipticCurve('1590g1')
- sage: m = ModularSymbolECLIB(E, sign=+1, nap=300)
- sage: [m(a/5) for a in [1..4]]
-- [1001/153, -1001/153, -1001/153, 1001/153]
-+ [13/2, -13/2, -13/2, 13/2]
-
-- Those values are incorrect. The correct values are::
-+ These values are correct, and increasing ``nap`` has no
-+ effect. The correct values may verified by the numerical
-+ implementation::
-
- sage: m = ModularSymbolECLIB(E, sign=+1, nap=400)
- sage: [m(a/5) for a in [1..4]]
- [13/2, -13/2, -13/2, 13/2]
-+ sage: m = E.modular_symbol(implementation='num')
-+ sage: [m(a/5) for a in [1..4]]
-+ [13/2, -13/2, -13/2, 13/2]
-
- """
- from sage.libs.eclib.newforms import ECModularSymbol
-diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py
-index a792afc..5a56389 100644
---- a/src/sage/schemes/elliptic_curves/ell_rational_field.py
-+++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py
-@@ -779,7 +779,7 @@ class EllipticCurve_rational_field(EllipticCurve_number_field):
- sage: E = EllipticCurve('11a1')
- sage: EE = E.mwrank_curve()
- sage: EE
-- y^2+ y = x^3 - x^2 - 10*x - 20
-+ y^2 + y = x^3 - x^2 - 10 x - 20
- sage: type(EE)
- <class 'sage.libs.eclib.interface.mwrank_EllipticCurve'>
- sage: EE.isogeny_class()
-@@ -1283,22 +1283,21 @@ class EllipticCurve_rational_field(EllipticCurve_number_field):
- sage: [Mminus(1/i) for i in [1..11]]
- [0, 0, 1/2, 1/2, 0, 0, -1/2, -1/2, 0, 0, 0]
-
-- With the default 'eclib' implementation, if ``nap`` is too
-- small, the normalization may be computed incorrectly. See
-- :trac:`31317`::
-+ With older version of eclib, in the default 'eclib'
-+ implementation, if ``nap`` is too small, the normalization may
-+ be computed incorrectly (see :trac:`31317`). This was fixed
-+ in eclib version v20210310, since now eclib increase ``nap``
-+ automatically. The following used to give incorrect results.
-+ See :trac:`31443`::
-
- sage: E = EllipticCurve('1590g1')
- sage: m = E.modular_symbol(nap=300)
- sage: [m(a/5) for a in [1..4]]
-- [1001/153, -1001/153, -1001/153, 1001/153]
-+ [13/2, -13/2, -13/2, 13/2]
-
-- Those values are incorrect. The correct values may be
-- obtained by increasing ``nap``, as verified by the numerical
-+ These values are correct, as verified by the numerical
- implementation::
-
-- sage: m = E.modular_symbol(nap=400)
-- sage: [m(a/5) for a in [1..4]]
-- [13/2, -13/2, -13/2, 13/2]
- sage: m = E.modular_symbol(implementation='num')
- sage: [m(a/5) for a in [1..4]]
- [13/2, -13/2, -13/2, 13/2]
-@@ -2525,7 +2524,7 @@ class EllipticCurve_rational_field(EllipticCurve_number_field):
- assert reg.parent() is R
- return reg
-
-- def saturation(self, points, verbose=False, max_prime=0, odd_primes_only=False):
-+ def saturation(self, points, verbose=False, max_prime=-1, min_prime=2):
- """
- Given a list of rational points on E, compute the saturation in
- E(Q) of the subgroup they generate.
-@@ -2538,17 +2537,24 @@ class EllipticCurve_rational_field(EllipticCurve_number_field):
- - ``verbose (bool)`` - (default: ``False``), if ``True``, give
- verbose output
-
-- - ``max_prime (int)`` - (default: 0), saturation is
-- performed for all primes up to max_prime. If max_prime==0,
-- perform saturation at *all* primes, i.e., compute the true
-- saturation.
-+ - ``max_prime`` (int, default -1) -- If `-1` (the default), an
-+ upper bound is computed for the primes at which the subgroup
-+ may not be saturated, and saturation is performed for all
-+ primes up to this bound. Otherwise, the bound used is the
-+ minimum of ``max_prime`` and the computed bound.
-
-- - ``odd_primes_only (bool)`` - only do saturation at
-- odd primes
-+ - ``min_prime (int)`` - (default: 2), only do `p`-saturation
-+ at primes `p` greater than or equal to this.
-
-+ .. note::
-
-- OUTPUT:
-+ To saturate at a single prime `p`, set ``max_prime`` and
-+ ``min_prime`` both to `p`. One situation where this is
-+ useful is after mapping saturated points from another
-+ elliptic curve by a `p`-isogeny, since the images may not
-+ be `p`-saturated but with be saturated at all other primes.
-
-+ OUTPUT:
-
- - ``saturation (list)`` - points that form a basis for
- the saturation
-@@ -2559,12 +2565,32 @@ class EllipticCurve_rational_field(EllipticCurve_number_field):
- - ``regulator (real with default precision)`` -
- regulator of saturated points.
-
-+ ALGORITHM: Uses Cremona's ``eclib`` package, which computes a
-+ bound on the saturation index. To `p`-saturate, or prove
-+ `p`-saturation, we consider the reductions of the points
-+ modulo primes `q` of good reduction such that `E(\FF_q)` has
-+ order divisible by `p`.
-+
-+ .. note::
-+
-+ In versons of ``eclib`` up to ``v20190909``, division of
-+ points in ``eclib`` was done using floating point methods,
-+ without automatic handling of precision, so that
-+ `p`-saturation sometimes failed unless
-+ ``mwrank_set_precision()`` was called in advance with a
-+ suitably high bit precision. Since version ``v20210310``
-+ of ``eclib``, division is done using exact methods based on
-+ division polynomials, and `p`-saturation cannot fail in
-+ this way.
-+
-+ .. note::
-+
-+ The computed index of saturation may be large, in which
-+ case saturation may take a long time. For example, the
-+ rank 4 curve ``EllipticCurve([0,1,1,-9872,374262])`` has a
-+ saturation index bound of 86682 and takes around 15 minutes
-+ to prove saturation.
-
-- ALGORITHM: Uses Cremona's ``mwrank`` package. With ``max_prime=0``,
-- we call ``mwrank`` with successively larger prime bounds until the full
-- saturation is provably found. The results of saturation at the
-- previous primes is stored in each case, so this should be
-- reasonably fast.
-
- EXAMPLES::
-
-@@ -2577,7 +2603,9 @@ class EllipticCurve_rational_field(EllipticCurve_number_field):
-
- TESTS:
-
-- See :trac:`10590`. This example would loop forever at default precision::
-+ See :trac:`10590`. With ``eclib`` versions up to
-+ ``v20190909``, this example would loop forever at default
-+ precision. Since version ``v20210310`` it runs fine::
-
- sage: E = EllipticCurve([1, 0, 1, -977842, -372252745])
- sage: P = E([-192128125858676194585718821667542660822323528626273/336995568430319276695106602174283479617040716649, 70208213492933395764907328787228427430477177498927549075405076353624188436/195630373799784831667835900062564586429333568841391304129067339731164107, 1])
-@@ -2585,7 +2613,7 @@ class EllipticCurve_rational_field(EllipticCurve_number_field):
- 113.302910926080
- sage: E.saturation([P])
- ([(-192128125858676194585718821667542660822323528626273/336995568430319276695106602174283479617040716649 : 70208213492933395764907328787228427430477177498927549075405076353624188436/195630373799784831667835900062564586429333568841391304129067339731164107 : 1)], 1, 113.302910926080)
-- sage: (Q,), ind, reg = E.saturation([2*P]) # needs higher precision, handled by eclib
-+ sage: (Q,), ind, reg = E.saturation([2*P])
- sage: 2*Q == 2*P
- True
- sage: ind
-@@ -2634,36 +2662,16 @@ class EllipticCurve_rational_field(EllipticCurve_number_field):
- c = Emin.mwrank_curve()
- from sage.libs.eclib.all import mwrank_MordellWeil
- mw = mwrank_MordellWeil(c, verbose)
-- mw.process(v)
-- repeat_until_saturated = False
-- if max_prime == 0:
-- repeat_until_saturated = True
-- max_prime = 9973
-- from sage.libs.all import mwrank_get_precision, mwrank_set_precision
-- prec0 = mwrank_get_precision()
-- prec = 100
-- if prec0<prec:
-- mwrank_set_precision(prec)
-- else:
-- prec = prec0
-- while True:
-- ok, index, unsat = mw.saturate(max_prime=max_prime, odd_primes_only = odd_primes_only)
-- reg = mw.regulator()
-- if ok or not repeat_until_saturated:
-- break
-- max_prime = arith.next_prime(max_prime + 1000)
-- prec += 50
-- mwrank_set_precision(prec)
-- if prec != prec0:
-- mwrank_set_precision(prec0)
-- sat = mw.points()
-- sat = [Emin(P) for P in sat]
-+ mw.process(v) # by default, this does no saturation yet
-+ ok, index, unsat = mw.saturate(max_prime=max_prime, min_prime = min_prime)
-+ if not ok:
-+ print("Failed to saturate failed at the primes {}".format(unsat))
-+ sat = [Emin(P) for P in mw.points()]
- if not minimal:
- phi_inv = ~phi
- sat = [phi_inv(P) for P in sat]
- reg = self.regulator_of_points(sat)
-- return sat, index, R(reg)
--
-+ return sat, index, reg
-
- def CPS_height_bound(self):
- r"""