// Magma code (for each group separately) for the Theorem 3.11 and Table 1 // each portion of the code goes through all quadratic fields, for 0:=PolynomialRing(Rationals()); E:=EllipticCurve([0,-1,-1,0,0]); RankBounds(E); for d in S do printf "d=%o\n", d; E1:=QuadraticTwist(E,d); r1,r2:=RankBounds(E1); r1; r2; if r2 eq 0 then E2:=BaseChange(E,QuadraticField(d)); TorsionSubgroup(E2); end if; end for; // Z/14Z S:=[n : n in [2..100] | SquareFree(n) eq n]; _:=PolynomialRing(Rationals()); E:=EllipticCurve([1,0,1,-1,0]); RankBounds(E); for d in S do printf "d=%o\n", d; E1:=QuadraticTwist(E,d); r1,r2:=RankBounds(E1); r1; r2; if r2 eq 0 then E2:=BaseChange(E,QuadraticField(d)); TorsionSubgroup(E2); end if; end for; // Z/15Z S:=[n : n in [2..100] | SquareFree(n) eq n]; _:=PolynomialRing(Rationals()); E:=EllipticCurve([1,1,1,0,0]); RankBounds(E); for d in S do printf "d=%o\n", d; E1:=QuadraticTwist(E,d); r1,r2:=RankBounds(E1); r1; r2; if r2 eq 0 then E2:=BaseChange(E,QuadraticField(d)); TorsionSubgroup(E2); end if; end for; // Z/2Z x Z/10Z S:=[n : n in [2..100] | SquareFree(n) eq n]; _:=PolynomialRing(Rationals()); E:=EllipticCurve([0,1,0,-1,0]); RankBounds(E); for d in S do printf "d=%o\n", d; E1:=QuadraticTwist(E,d); r1,r2:=RankBounds(E1); r1; r2; if r2 eq 0 then E2:=BaseChange(E,QuadraticField(d)); TorsionSubgroup(E2); end if; end for; // Z/2Z x Z/12Z S:=[n : n in [2..100] | SquareFree(n) eq n]; _:=PolynomialRing(Rationals()); E:=EllipticCurve([0,-1,0,1,0]); RankBounds(E); for d in S do printf "d=%o\n", d; E1:=QuadraticTwist(E,d); r1,r2:=RankBounds(E1); r1; r2; if r2 eq 0 then E2:=BaseChange(E,QuadraticField(d)); TorsionSubgroup(E2); end if; end for; // Z/13Z // In the set S we put only d such that d≡1(mod 8) (see Theorem 3.6) S:=[17,33,41,57,65,73,89,97]; _:=PolynomialRing(Rationals()); C:=HyperellipticCurve(x^6-2*x^5+x^4-2*x^3+6*x^2-4*x+1); J:=Jacobian(C); RankBounds(J); TorsionSubgroup(J); Points(J:Bound:=100); for d in S do printf "d=%o\n", d; C1:=QuadraticTwist(C,d); J1:=Jacobian(C1); r1,r2:=RankBounds(J1); r1; r2; TorsionSubgroup(J1); if r2 ne 0 then C2:=ChangeRing(C,QuadraticField(d)); Points(C2:Bound:=200); end if; end for; //Z/16Z S:=[n : n in [2..100] | SquareFree(n) eq n]; _:=PolynomialRing(Rationals()); J:=JOne(16); L:=LSeries(J); IsZeroAt(L,1); // this is false iff rank(J_1(16)(Q))=0 tr, p:=NewModularHyperellipticCurve(ModularSymbols(J)); C1:=HyperellipticCurve(p); C:=HyperellipticCurve(x*(x^2+1)*(x^2+2*x-1)); J1:=Jacobian(C); TorsionSubgroup(J1); Points(J1:Bound:=100); for d in S do printf "d=%o\n", d; C2:=QuadraticTwist(C1,d); J2:=Jacobian(C2); r1, r2:=RankBounds(J2); r1; r2; if r2 eq 0 then // if the rank of the Jacobian is 0 then we compute the torsion subgroup (as in Proposition 3.9) C2:=QuadraticTwist(C,d); J2:=Jacobian(C2); TorsionSubgroup(J2); Points(J2:Bound:=100); J3:=BaseChange(J1,QuadraticField(d)); TwoTorsionSubgroup(J3); else // if the rank of the Jacobian is not 0, then we cannot use the methods described in Proposition 3.9, so we are searching for the points on the curve C3:=ChangeRing(C,QuadraticField(d)); Points(C3:Bound:=1000); // we can put whichever bound we want end if; end for; // Z/18Z // In the set S we put only d such that d≡1(mod 8) and d≠2(mod 3) (see Theorem 3.7) S:=[33,57,73,97]; _:=PolynomialRing(Rationals()); C:=HyperellipticCurve(x^6+2*x^5+5*x^4+10*x^3+10*x^2+4*x+1); J:=Jacobian(C); RankBounds(J); TorsionSubgroup(J); Points(J:Bound:=100); for d in S do printf "d=%o\n", d; C1:=QuadraticTwist(C,d); J1:=Jacobian(C1); r1,r2:=RankBounds(J1); r1; r2; TorsionSubgroup(J1); if r2 ne 0 then C2:=ChangeRing(C,QuadraticField(d)); Points(C2:Bound:=200); end if; end for;