/* VERSION: 18 February 2004 ======================================================================== This Magma program finds all pointless genus-3 curves over K = F_25. In the paper Everett W. Howe, Kristen E. Lauter, and Jaap Top: Pointless curves of genus three and four, preprint, 2004 it is shown that the real Weil polynomial of such a curve must be one of these four polynomials: f1 := (x - 10)^2*(x - 6) f2 := (x - 10)*(x^2 - 16*x + 62) f3 := (x - 10)*(x - 9)*(x - 7) f4 := (x - 10)*(x - 8)^2 We will first show that the latter three do not occur; then we will show that the first polynomial does occur, and that the curve giving rise to it is unique. Suppose C is a curve with real Weil polynomial equal to f2, f3, or f4. We show in our paper that then C is a double cover of an elliptic curve E over K having either 16 or 17 rational points. There is exactly one elliptic curve over K of each of these orders. For each of these E's, we must consider rational points Q that represent the classes of E(K) modulo 2*E(K). For the elliptic curve with 17 points, we need only consider Q = {the identity}. The elliptic curve with 16 points has an automorphism of order 6, and the group E(K)/2*E(K) breaks into 2 orbits under the action of this group. Thus for this curve we need only consider 2 values of Q, one of them the identity. Suppose we are given E and Q. If Q is the identity, we list the degree-4 functions f on E that are regular outside the identity. If Q is not the identity, we list the degree-6 functions f that are regular outside the identity and that have a double zero at Q. The covers we must consider are obtained by adjoining a root of z^2 = f to the function field of E. The two E's we consider are y^2 = x^3 + a^9 y^2 = x^3 + x + a^8 where a^2 - a + 2 = 0. Suppose we write Q = (x0,y0) with y0 nonzero, and let f0 be a linear polynomial defining the tangent to E at Q. Then the degree-6 functions on E that we must consider are all of the form f = (x - x0)^2 * (a degree-1 polynomial in x) + (x - x0) * (y - y0) * (constant) + f0 * (constant). Let c be the (nonzero) coefficient of x in the degree-1 polynomial of x appearing above, and let t be a uniformizing parameter of E at infinity (so we may take t = y/x, for example). The Laurent expansion of f at infinity is c*t^-6 + (higher-order terms), so the function f is a square locally at infinity if and only if c is a square. Since we are searching for double covers of E with no rational points, we may assume that c is not a square, and by multiplying f by a constant square (which doesn't change the cover), we may assume that c is a. For each (E, Q, f) we then check to see whether there is a rational point P on E, different from Q and infinity, for which f(P) is a square. Such a point would give a rational point on the double cover associated to f. If there is no such point P, we then check to see whether the intersection divisor of f with the equation for E has exactly one double point (namely Q) and four simple points. If so, we compute an overestimate of the number of points on this double cover of E over the quadratic extension of L. A curve with real Weil polynomial equal to f2, f3, or f4 would have 544, 546, or 548 points over the quadratic extension of K. We check that the only functions give rise to curves having at most 540 points. This shows that f2, f3, and f4 do not occur as the real Weil polynomial of a pointless genus-3 curve over K. Next we turn to f1. If C is a curve over K with real Weil polynomial equal to f1, then (as we show in the paper) C must be a double cover of an elliptic curve over K with exactly 20 rational points and with 4 rational 2-torsion points. There are two such curves to consider, and for each curve we must consider auxiliary points Q that represent the classes of E(K) modulo 2*E(K). Given E and Q, we enumerate the possibile functions as above. We find that there is exactly on (E,Q,f) triple, namely E : y^2 = x^3 + 2x, with Q = {the identity element} and f = a*(x^2-2). ======================================================================== */ /* VERSION: 18 February 2004. First public version. */ print "You should see a message to investigate one cover:"; print "the double cover of the elliptic curve y^2 = x^3 + 2*x"; print "given by setting z^2 = a*x^2 + a^19."; print ""; K:=GF(25); assert a^2 - a + 2 eq 0; R:=PolynomialRing(K,2); S := PolynomialRing(K,3); P2 := ProjectiveSpace(K,2); T:=PolynomialRing(K); function firstcheck(f, E, Q) // Here we check whether f(P) is a nonzero square for any point // P on E (other than Q or infinity). // Return false if we find such a point, true if not. for P in E do if not P in {Q,Identity(E)} then if IsSquare(Evaluate(f,[P[1],P[2]])) then return false; end if; end if; end for; return true; end function; function secondcheck(f, eqn, Q) // Given a polynomial f in K[x,y] and an equation for E in K[x,y], // we check to see that f, viewed as a function on E, has a double // root at Q and four simple roots elsewhere. Return false if we // know that our f does not have this shape. Return true if we have // to look more closely at f to decide. // // We assume that the degree of f is equal to 6 and that it is // regular outside infinity. // // Instead of using Magma's curve facilities, we will consider // various projections of the intersection divisor (in P^2) of // f and the equation for E onto the x-line. Generically, the // projection will have the same shape as the original intersection // divisor --- the only way it can change is if we project at // a slope that happens to be the slope of the line between two of // the intersection points. // // Since there are at most 6 intersection points, there are at // most (6 choose 2) = 15 slopes to avoid. // // So our strategy will be to compute the projection of the // intersection divisor to the x-line via all 25 slopes. The form of // the generic intersection divisor is then easy to spot: If we list // the divisors as // [{# of simple intersections}, {# of double intersections}, etc.] // then the generic form will be the lexicographically greatest. formlist := []; for slope in K do newf := Evaluate(f,[x+slope*y,y]); neweqn := Evaluate(eqn,[x+slope*y,y]); pol := UnivariatePolynomial(Resultant(newf, neweqn, y)); polfac := Factorization(pol); n1 := 0; n2 := 0; for fac in polfac do case fac[2]: when 1: n1 +:= Degree(fac[1]); when 2: n2 +:= Degree(fac[1]); end case; end for; formlist cat:= [ [n1,n2] ]; end for; Sort(~formlist); // default order is lexicographic. realform := formlist[#formlist]; return realform eq [4,1] and 0 eq Evaluate(f,[Q[1],Q[2]]); end function; function secondcheckzero(f, eqn) // Same as above, only we assume f has degree 4 and we want // no double zero. formlist := []; for slope in K do newf := Evaluate(f,[x+slope*y,y]); neweqn := Evaluate(eqn,[x+slope*y,y]); pol := UnivariatePolynomial(Resultant(newf, neweqn, y)); polfac := Factorization(pol); n1 := 0; for fac in polfac do case fac[2]: when 1: n1 +:= Degree(fac[1]); end case; end for; formlist cat:= [ [n1] ]; end for; Sort(~formlist); // default order is lexicographic. realform := formlist[#formlist]; return realform eq [4]; end function; function finalcheck(f, E, Q) // Here we get an upper bound on the number of F_625-ration // points there are on the curve C over E defined by z^2 = f. // Count two points on C for every point P on E with f(P) a // nonzero square, count two points on C for the point Q, // two for infinity, and one for every simple zero. L := ext; F := BaseExtend(E,L); QQ := F!Q; count := 4; // 2 each for Q and for infinity. for P in F do if not P in {QQ,Identity(F)} then v := Evaluate(f,[P[1],P[2]]); if IsSquare(v) then count+:=2; end if; if v eq 0 then count-:=1; end if; end if; end for; return count; end function; function allchecks(E,Q) // E is the elliptic curve. // Q is the Q to try. // List the appropriate f's, and apply tests to (E,Q,f) triples. // Print the triples that pass both tests. // Return true if no triples pass, false if not. bool := true; elist := Eltseq(E); eqn := y^2 + elist[1]*x*y + elist[3]*y - (x^3 + elist[2]*x^2 + elist[4]*x + elist[5]); x0 := Q[1]; y0 := Q[2]; for m in K do b := y0 - m*x0; pol := UnivariatePolynomial(Evaluate(eqn,[x,m*x+b])); if pol mod UnivariatePolynomial(x-x0)^2 eq 0 then m0 := m; b0 := b; break; end if; end for; f0 := y - m0*x - b0; // f0 is the tangent line to E at Q. for c1, c2 in K do f1 := (x - x0)^2 * (x + c1) + (x - x0) * (y - y0) * c2; for c0 in K do f := a*(f1 + c0*f0); if firstcheck(f,E,Q) then if secondcheck(f,eqn,Q) then upperbound := finalcheck(f,E,Q); if #E eq 20 or upperbound ge 544 then bool := false; print "This one needs further analysis: "; print E,Q,f; print ""; end if; end if; end if; end for; end for; return bool; end function; function allcheckszero(E) // Same as above, with Q = identity. // The appropriate f's are the functions, regular at infinity, // of degree 4. // List the appropriate f's, and apply tests to (E,f) pairs. // Print the pairs that pass both tests. // Return true if no pairs pass, false if not. bool := true; elist := Eltseq(E); eqn := y^2 + elist[1]*x*y + elist[3]*y - (x^3 + elist[2]*x^2 + elist[4]*x + elist[5]); for c0, c2, c3 in K do f := a*(x^2 + c3*y + c2*x + c0); if firstcheck(f,E,Identity(E)) then if secondcheckzero(f,eqn) then bool := false; print "This one needs further analysis: "; print E,f; print ""; end if; end if; end for; return bool; end function; // The two curves we must examine for f2, f3 and f4: E1 := EllipticCurve([0,0,0,0,a^9]); // 16 points assert #E1 eq 16; Q1 := E1![2,a^22]; E2 := EllipticCurve([0,0,0,1,a^3]); // 17 points assert #E2 eq 17; // Check that the identity and images of Q1 under automorphisms // of E1 represent E1(K) mod 2*E1(K): zeta := a^8; R1a := E1![Q1[1]*zeta,Q1[2]]; R1b:= E1![Q1[1]*zeta^2,Q1[2]]; assert #E1 eq #({2*P : P in E1} join {2*P+Q1 : P in E1} join {2*P+R1a : P in E1} join {2*P+R1b : P in E1}); // Clearly E2(K) = 2*E1(K). // Now do the checks: check1 := allcheckszero(E1); check2 := allchecks(E1,Q1); check3 := allcheckszero(E2); if not &and[check1, check2, check3] then print "There were unexpected choices that require further analysis."; end if; // Now the two curves with 20 points: E3 := EllipticCurve([K|0,0,0,2,0]); // 20 points, End E = Z[i] Q3a := E3![1,a^9]; Q3b := E3![a,a]; E4 := EllipticCurve([K|0,0,0,-1,1]); // 20 points, End E = Z[2i] Q4a := E4![0,1]; Q4b := E4![a,a^10]; Q4c := E4![a^4,a^8]; // Check that the identity, Q3a, Q3b, and [i]Q3b represent E3(K) // mod 2*E3(K): i := K!2; R3 := E3![-Q3b[1],i*Q3b[2]]; assert #E3 eq #({2*P : P in E3} join {2*P+Q3a : P in E3} join {2*P+Q3b : P in E3} join {2*P+R3 : P in E3}); // Check that the identity, Q4a, Q4b, and Q4c represent E4(K) // mod 2*E4(K): assert #E4 eq #({2*P : P in E4} join {2*P+Q4a : P in E4} join {2*P+Q4b : P in E4} join {2*P+Q4c : P in E4}); check4 := allcheckszero(E3); // This one gives our example. check5 := allchecks(E3,Q3a); check6 := allchecks(E3,Q3b); check7 := allcheckszero(E4); check8 := allchecks(E4,Q4a); check9 := allchecks(E4,Q4b); checka := allchecks(E4,Q4c); if not &and[check5,check6,check7,check8,check9,checka] then print "There were unexpected choices that require further analysis."; end if;