Path: blob/master/sage/schemes/elliptic_curves/constructor.py
4099 views
"""1Elliptic curve constructor23AUTHORS:45- William Stein (2005): Initial version67- John Cremona (2008-01): EllipticCurve(j) fixed for all cases8"""910#*****************************************************************************11# Copyright (C) 2005 William Stein <[email protected]>12#13# Distributed under the terms of the GNU General Public License (GPL)14#15# This code is distributed in the hope that it will be useful,16# but WITHOUT ANY WARRANTY; without even the implied warranty of17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU18# General Public License for more details.19#20# The full text of the GPL is available at:21#22# http://www.gnu.org/licenses/23#*****************************************************************************242526import sage.rings.all as rings2728from sage.structure.sequence import Sequence29from sage.structure.element import parent30from sage.symbolic.ring import SR31from sage.symbolic.expression import is_SymbolicEquation323334def EllipticCurve(x=None, y=None, j=None):35r"""36There are several ways to construct an elliptic curve:3738.. math::3940y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6.414243- EllipticCurve([a1,a2,a3,a4,a6]): Elliptic curve with given44a-invariants. The invariants are coerced into the parent of the45first element. If all are integers, they are coerced into the46rational numbers.4748- EllipticCurve([a4,a6]): Same as above, but a1=a2=a3=0.4950- EllipticCurve(label): Returns the elliptic curve over Q from the51Cremona database with the given label. The label is a string, such52as "11a" or "37b2". The letters in the label *must* be lower case53(Cremona's new labeling).5455- EllipticCurve(R, [a1,a2,a3,a4,a6]): Create the elliptic curve56over R with given a-invariants. Here R can be an arbitrary ring.57Note that addition need not be defined.585960- EllipticCurve(j): Return an elliptic curve with j-invariant61`j`. Warning: this is deprecated. Use ``EllipticCurve_from_j(j)``62or ``EllipticCurve(j=j)`` instead.6364In each case above where the input is a list of length 2 or 5, one65can instead give a 2 or 5-tuple instead.6667EXAMPLES: We illustrate creating elliptic curves.6869::7071sage: EllipticCurve([0,0,1,-1,0])72Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field7374We create a curve from a Cremona label::7576sage: EllipticCurve('37b2')77Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field78sage: EllipticCurve('5077a')79Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field80sage: EllipticCurve('389a')81Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field8283Unicode labels are allowed::8485sage: EllipticCurve(u'389a')86Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field8788We create curves over a finite field as follows::8990sage: EllipticCurve([GF(5)(0),0,1,-1,0])91Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 592sage: EllipticCurve(GF(5), [0, 0,1,-1,0])93Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 59495Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type96"elliptic curve over a finite field"::9798sage: F = Zmod(101)99sage: EllipticCurve(F, [2, 3])100Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101101sage: E = EllipticCurve([F(2), F(3)])102sage: type(E)103<class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'>104sage: E.category()105Category of schemes over Ring of integers modulo 101106107In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite108are of type "generic elliptic curve"::109110sage: F = Zmod(95)111sage: EllipticCurve(F, [2, 3])112Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95113sage: E = EllipticCurve([F(2), F(3)])114sage: type(E)115<class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'>116sage: E.category()117Category of schemes over Ring of integers modulo 95118119The following is a curve over the complex numbers::120121sage: E = EllipticCurve(CC, [0,0,1,-1,0])122sage: E123Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision124sage: E.j_invariant()1252988.97297297297126127We can also create elliptic curves by giving the Weierstrass equation::128129sage: x, y = var('x,y')130sage: EllipticCurve(y^2 + y == x^3 + x - 9)131Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field132133sage: R.<x,y> = GF(5)[]134sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x)135Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 2 over Finite Field of size 5136137We can explicitly specify the `j`-invariant::138139sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.label()140Elliptic Curve defined by y^2 = x^3 - x over Rational Field1411728142'32a2'143144sage: E = EllipticCurve(j=GF(5)(2)); E; E.j_invariant()145Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 51462147148See trac #6657::149150sage: EllipticCurve(GF(144169),j=1728)151Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169152153154TESTS::155156sage: R = ZZ['u', 'v']157sage: EllipticCurve(R, [1,1])158Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v159over Integer Ring160161We create a curve and a point over QQbar (see #6879)::162163sage: E = EllipticCurve(QQbar,[0,1])164sage: E(0)165(0 : 1 : 0)166sage: E.base_field()167Algebraic Field168169sage: E = EllipticCurve(RR,[1,2]); E; E.base_field()170Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision171Real Field with 53 bits of precision172sage: EllipticCurve(CC,[3,4]); E; E.base_field()173Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000 over Complex Field with 53 bits of precision174Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision175Real Field with 53 bits of precision176sage: E = EllipticCurve(QQbar,[5,6]); E; E.base_field()177Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field178Algebraic Field179180See trac #6657::181182sage: EllipticCurve(3,j=1728)183Traceback (most recent call last):184...185ValueError: First parameter (if present) must be a ring when j is specified186187sage: EllipticCurve(GF(5),j=3/5)188Traceback (most recent call last):189...190ValueError: First parameter must be a ring containing 3/5191192If the universe of the coefficients is a general field, the object193constructed has type EllipticCurve_field. Otherwise it is194EllipticCurve_generic. See trac #9816::195196sage: E = EllipticCurve([QQbar(1),3]); E197Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field198sage: type(E)199<class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>200201sage: E = EllipticCurve([RR(1),3]); E202Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000 over Real Field with 53 bits of precision203sage: type(E)204<class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>205206sage: E = EllipticCurve([i,i]); E207Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring208sage: type(E)209<class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>210sage: E.category()211Category of schemes over Symbolic Ring212sage: is_field(SR)213True214215sage: F = FractionField(PolynomialRing(QQ,'t'))216sage: t = F.gen()217sage: E = EllipticCurve([t,0]); E218Elliptic Curve defined by y^2 = x^3 + t*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field219sage: type(E)220<class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>221sage: E.category()222Category of schemes over Fraction Field of Univariate Polynomial Ring in t over Rational Field223224See :trac:`12517`::225226sage: E = EllipticCurve([1..5])227sage: EllipticCurve(E.a_invariants())228Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field229"""230import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field # here to avoid circular includes231232if j is not None:233if not x is None:234if rings.is_Ring(x):235try:236j = x(j)237except (ZeroDivisionError, ValueError, TypeError):238raise ValueError, "First parameter must be a ring containing %s"%j239else:240raise ValueError, "First parameter (if present) must be a ring when j is specified"241return EllipticCurve_from_j(j)242243assert x is not None244245if is_SymbolicEquation(x):246x = x.lhs() - x.rhs()247248if parent(x) is SR:249x = x._polynomial_(rings.QQ['x', 'y'])250251if rings.is_MPolynomial(x) and y is None:252f = x253if f.degree() != 3:254raise ValueError, "Elliptic curves must be defined by a cubic polynomial."255if f.degrees() == (3,2):256x, y = f.parent().gens()257elif f.degree() == (2,3):258y, x = f.parent().gens()259elif len(f.parent().gens()) == 2 or len(f.parent().gens()) == 3 and f.is_homogeneous():260# We'd need a point too...261raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented."262else:263raise ValueError, "Defining polynomial must be a cubic polynomial in two variables."264265try:266if f.coefficient(x**3) < 0:267f = -f268# is there a nicer way to extract the coefficients?269a1 = a2 = a3 = a4 = a6 = 0270for coeff, mon in f:271if mon == x**3:272assert coeff == 1273elif mon == x**2:274a2 = coeff275elif mon == x:276a4 = coeff277elif mon == 1:278a6 = coeff279elif mon == y**2:280assert coeff == -1281elif mon == x*y:282a1 = -coeff283elif mon == y:284a3 = -coeff285else:286assert False287return EllipticCurve([a1, a2, a3, a4, a6])288except AssertionError:289raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented."290291if rings.is_Ring(x):292if rings.is_RationalField(x):293return ell_rational_field.EllipticCurve_rational_field(x, y)294elif rings.is_FiniteField(x) or (rings.is_IntegerModRing(x) and x.characteristic().is_prime()):295return ell_finite_field.EllipticCurve_finite_field(x, y)296elif rings.is_pAdicField(x):297return ell_padic_field.EllipticCurve_padic_field(x, y)298elif rings.is_NumberField(x):299return ell_number_field.EllipticCurve_number_field(x, y)300elif rings.is_Field(x):301return ell_field.EllipticCurve_field(x, y)302return ell_generic.EllipticCurve_generic(x, y)303304if isinstance(x, unicode):305x = str(x)306307if isinstance(x, str):308return ell_rational_field.EllipticCurve_rational_field(x)309310if rings.is_RingElement(x) and y is None:311from sage.misc.misc import deprecation312deprecation("'EllipticCurve(j)' is deprecated; use 'EllipticCurve_from_j(j)' or 'EllipticCurve(j=j)' instead.")313# Fixed for all characteristics and cases by John Cremona314j=x315F=j.parent().fraction_field()316char=F.characteristic()317if char==2:318if j==0:319return EllipticCurve(F, [ 0, 0, 1, 0, 0 ])320else:321return EllipticCurve(F, [ 1, 0, 0, 0, 1/j ])322if char==3:323if j==0:324return EllipticCurve(F, [ 0, 0, 0, 1, 0 ])325else:326return EllipticCurve(F, [ 0, j, 0, 0, -j**2 ])327if j == 0:328return EllipticCurve(F, [ 0, 0, 0, 0, 1 ])329if j == 1728:330return EllipticCurve(F, [ 0, 0, 0, 1, 0 ])331k=j-1728332return EllipticCurve(F, [0,0,0,-3*j*k, -2*j*k**2])333334if not isinstance(x, (list, tuple)):335raise TypeError, "invalid input to EllipticCurve constructor"336337x = Sequence(x)338if not (len(x) in [2,5]):339raise ValueError, "sequence of coefficients must have length 2 or 5"340R = x.universe()341342if isinstance(x[0], (rings.Rational, rings.Integer, int, long)):343return ell_rational_field.EllipticCurve_rational_field(x, y)344345elif rings.is_NumberField(R):346return ell_number_field.EllipticCurve_number_field(x, y)347348elif rings.is_pAdicField(R):349return ell_padic_field.EllipticCurve_padic_field(x, y)350351elif rings.is_FiniteField(R) or (rings.is_IntegerModRing(R) and R.characteristic().is_prime()):352return ell_finite_field.EllipticCurve_finite_field(x, y)353354elif rings.is_Field(R):355return ell_field.EllipticCurve_field(x, y)356357return ell_generic.EllipticCurve_generic(x, y)358359360def EllipticCurve_from_c4c6(c4, c6):361"""362Return an elliptic curve with given `c_4` and363`c_6` invariants.364365EXAMPLES::366367sage: E = EllipticCurve_from_c4c6(17, -2005)368sage: E369Elliptic Curve defined by y^2 = x^3 - 17/48*x + 2005/864 over Rational Field370sage: E.c_invariants()371(17, -2005)372"""373try:374K = c4.parent()375except AttributeError:376K = rings.RationalField()377if not rings.is_Field(K):378K = K.fraction_field()379return EllipticCurve([-K(c4)/K(48), -K(c6)/K(864)])380381def EllipticCurve_from_j(j):382"""383Return an elliptic curve with given `j`-invariant.384385EXAMPLES::386387sage: E = EllipticCurve_from_j(0); E; E.j_invariant(); E.label()388Elliptic Curve defined by y^2 + y = x^3 over Rational Field3890390'27a3'391392sage: E = EllipticCurve_from_j(1728); E; E.j_invariant(); E.label()393Elliptic Curve defined by y^2 = x^3 - x over Rational Field3941728395'32a2'396397sage: E = EllipticCurve_from_j(1); E; E.j_invariant()398Elliptic Curve defined by y^2 + x*y = x^3 + 36*x + 3455 over Rational Field3991400401"""402try:403K = j.parent()404except AttributeError:405K = rings.RationalField()406if not rings.is_Field(K):407K = K.fraction_field()408409char=K.characteristic()410if char==2:411if j == 0:412return EllipticCurve(K, [ 0, 0, 1, 0, 0 ])413else:414return EllipticCurve(K, [ 1, 0, 0, 0, 1/j ])415if char == 3:416if j==0:417return EllipticCurve(K, [ 0, 0, 0, 1, 0 ])418else:419return EllipticCurve(K, [ 0, j, 0, 0, -j**2 ])420421if K is rings.RationalField():422# we construct the minimal twist, i.e. the curve with minimal423# conductor with this j_invariant:424425if j == 0:426return EllipticCurve(K, [ 0, 0, 1, 0, 0 ]) # 27a3427if j == 1728:428return EllipticCurve(K, [ 0, 0, 0, -1, 0 ]) # 32a2429430n = j.numerator()431m = n-1728*j.denominator()432a4 = -3*n*m433a6 = -2*n*m**2434435# Now E=[0,0,0,a4,a6] has j-invariant j=n/d436437from sage.sets.set import Set438for p in Set(n.prime_divisors()+m.prime_divisors()):439e = min(a4.valuation(p)//2,a6.valuation(p)//3)440if e>0:441p = p**e442a4 /= p**2443a6 /= p**3444445# Now E=[0,0,0,a4,a6] is minimal at all p != 2,3446447tw = [-1,2,-2,3,-3,6,-6]448E1 = EllipticCurve([0,0,0,a4,a6])449Elist = [E1] + [E1.quadratic_twist(t) for t in tw]450crv_cmp = lambda E,F: cmp(E.conductor(),F.conductor())451Elist.sort(cmp=crv_cmp)452return Elist[0]453454# defaults for all other fields:455if j == 0:456return EllipticCurve(K, [ 0, 0, 0, 0, 1 ])457if j == 1728:458return EllipticCurve(K, [ 0, 0, 0, 1, 0 ])459k=j-1728460return EllipticCurve(K, [0,0,0,-3*j*k, -2*j*k**2])461462def EllipticCurve_from_cubic(F, P):463r"""464Construct an elliptic curve from a ternary cubic with a rational point.465466INPUT:467468- ``F`` -- a homogeneous cubic in three variables with rational469coefficients (either as a polynomial ring element or as a470string) defining a smooth plane cubic curve.471472- ``P`` -- a 3-tuple `(x,y,z)` defining a projective point on the473curve `F=0`.474475OUTPUT:476477(elliptic curve) An elliptic curve (in minimal Weierstrass form)478isomorphic to the curve `F=0`.479480.. note::481482USES MAGMA - This function will not work on computers that483do not have magma installed.484485TO DO: implement this without using MAGMA.486487For a more general version, see the function488``EllipticCurve_from_plane_curve()``.489490EXAMPLES:491492First we find that the Fermat cubic is isomorphic to the curve493with Cremona label 27a1::494495sage: E = EllipticCurve_from_cubic('x^3 + y^3 + z^3', [1,-1,0]) # optional - magma496sage: E # optional - magma497Elliptic Curve defined by y^2 + y = x^3 - 7 over Rational Field498sage: E.cremona_label() # optional - magma499'27a1'500501Next we find the minimal model and conductor of the Jacobian of the502Selmer curve.503504::505506sage: E = EllipticCurve_from_cubic('u^3 + v^3 + 60*w^3', [1,-1,0]) # optional - magma507sage: E # optional - magma508Elliptic Curve defined by y^2 = x^3 - 24300 over Rational Field509sage: E.conductor() # optional - magma51024300511"""512from sage.interfaces.all import magma513cmd = "P<%s,%s,%s> := ProjectivePlane(RationalField());"%SR(F).variables()514magma.eval(cmd)515cmd = 'aInvariants(MinimalModel(EllipticCurve(Curve(Scheme(P, %s)),P!%s)));'%(F, P)516s = magma.eval(cmd)517return EllipticCurve(rings.RationalField(), eval(s))518519def EllipticCurve_from_plane_curve(C, P):520r"""521Construct an elliptic curve from a smooth plane cubic with a rational point.522523INPUT:524525- ``C`` -- a plane curve of genus one.526527- ``P`` -- a 3-tuple `(x,y,z)` defining a projective point on the528curve ``C``.529530OUTPUT:531532(elliptic curve) An elliptic curve (in minimal Weierstrass form)533isomorphic to ``C``.534535536.. note::537538USES MAGMA - This function will not work on computers that539do not have magma installed.540541TO DO: implement this without using MAGMA.542543EXAMPLES:544545First we check that the Fermat cubic is isomorphic to the curve546with Cremona label '27a1'::547548sage: x,y,z=PolynomialRing(QQ,3,'xyz').gens() # optional - magma549sage: C=Curve(x^3+y^3+z^3) # optional - magma550sage: P=C(1,-1,0) # optional - magma551sage: E=EllipticCurve_from_plane_curve(C,P) # optional - magma552sage: E # optional - magma553Elliptic Curve defined by y^2 + y = x^3 - 7 over Rational Field554sage: E.label() # optional - magma555'27a1'556557Now we try a quartic example::558559sage: u,v,w=PolynomialRing(QQ,3,'uvw').gens() # optional - magma560sage: C=Curve(u^4+u^2*v^2-w^4) # optional - magma561sage: P=C(1,0,1) # optional - magma562sage: E=EllipticCurve_from_plane_curve(C,P) # optional - magma563sage: E # optional - magma564Elliptic Curve defined by y^2 = x^3 + 4*x over Rational Field565sage: E.label() # optional - magma566'32a1'567568"""569from sage.interfaces.all import magma570if C.genus()!=1:571raise TypeError, "The curve C must have genus 1"572elif P.parent()!=C.point_set(C.base_ring()):573raise TypeError, "The point P must be on the curve C"574dp=C.defining_polynomial()575x,y,z = dp.parent().variable_names()576cmd = "PR<%s,%s,%s>:=ProjectivePlane(RationalField());"%(x,y,z)577magma.eval(cmd)578cmd = 'CC:=Curve(PR, %s);'%(dp)579magma.eval(cmd)580cmd='aInvariants(MinimalModel(EllipticCurve(CC,CC!%s)));'%([P[0],P[1],P[2]])581s=magma.eval(cmd)582return EllipticCurve(rings.RationalField(), eval(s))583584def EllipticCurves_with_good_reduction_outside_S(S=[], proof=None, verbose=False):585r"""586Returns a sorted list of all elliptic curves defined over `Q`587with good reduction outside the set `S` of primes.588589INPUT:590591- ``S`` - list of primes (default: empty list).592593- ``proof`` - True/False (default True): the MW basis for594auxiliary curves will be computed with this proof flag.595596- ``verbose`` - True/False (default False): if True, some597details of the computation will be output.598599.. note::600601Proof flag: The algorithm used requires determining all602S-integral points on several auxiliary curves, which in turn603requires the computation of their generators. This is not604always possible (even in theory) using current knowledge.605606The value of this flag is passed to the function which607computes generators of various auxiliary elliptic curves, in608order to find their S-integral points. Set to False if the609default (True) causes warning messages, but note that you can610then not rely on the set of curves returned being611complete.612613EXAMPLES::614615sage: EllipticCurves_with_good_reduction_outside_S([])616[]617sage: elist = EllipticCurves_with_good_reduction_outside_S([2])618sage: elist619[Elliptic Curve defined by y^2 = x^3 + 4*x over Rational Field,620Elliptic Curve defined by y^2 = x^3 - x over Rational Field,621...622Elliptic Curve defined by y^2 = x^3 - x^2 - 13*x + 21 over Rational Field]623sage: len(elist)62424625sage: ', '.join([e.label() for e in elist])626'32a1, 32a2, 32a3, 32a4, 64a1, 64a2, 64a3, 64a4, 128a1, 128a2, 128b1, 128b2, 128c1, 128c2, 128d1, 128d2, 256a1, 256a2, 256b1, 256b2, 256c1, 256c2, 256d1, 256d2'627628Without ``Proof=False``, this example gives two warnings::629630sage: elist = EllipticCurves_with_good_reduction_outside_S([11],proof=False) # long time (14s on sage.math, 2011)631sage: len(elist) # long time63212633sage: ', '.join([e.label() for e in elist]) # long time634'11a1, 11a2, 11a3, 121a1, 121a2, 121b1, 121b2, 121c1, 121c2, 121d1, 121d2, 121d3'635636sage: elist = EllipticCurves_with_good_reduction_outside_S([2,3]) # long time (26s on sage.math, 2011)637sage: len(elist) # long time638752639sage: max([e.conductor() for e in elist]) # long time64062208641sage: [N.factor() for N in Set([e.conductor() for e in elist])] # long time642[2^7,6432^8,6442^3 * 3^4,6452^2 * 3^3,6462^8 * 3^4,6472^4 * 3^4,6482^3 * 3,6492^7 * 3,6502^3 * 3^5,6513^3,6522^8 * 3,6532^5 * 3^4,6542^4 * 3,6552 * 3^4,6562^2 * 3^2,6572^6 * 3^4,6582^6,6592^7 * 3^2,6602^4 * 3^5,6612^4 * 3^3,6622 * 3^3,6632^6 * 3^3,6642^6 * 3,6652^5,6662^2 * 3^4,6672^3 * 3^2,6682^5 * 3,6692^7 * 3^4,6702^2 * 3^5,6712^8 * 3^2,6722^5 * 3^2,6732^7 * 3^5,6742^8 * 3^5,6752^3 * 3^3,6762^8 * 3^3,6772^5 * 3^5,6782^4 * 3^2,6792 * 3^5,6802^5 * 3^3,6812^6 * 3^5,6822^7 * 3^3,6833^5,6842^6 * 3^2]685"""686from ell_egros import (egros_from_jlist, egros_get_j)687return egros_from_jlist(egros_get_j(S, proof=proof, verbose=verbose), S)688689690