// IsogenyClasses.magma // Version 0.998 // 14 December 2011 // Everett W. Howe and Kristin E. Lauter: // New methods for bounding the number of points on curves over finite fields, // in preparation. /* ============================================================================== This collection of Magma routines is designed to compute upper bounds on the maximal number of rational points on a genus-g curve over a finite field. The main function, isogeny_classes(q,g,N), returns a list of isogeny classes of g-dimensional abelian varieties over GF(q) that might possibly correspond to isogeny classes containing the Jacobian of a genus-g curve with N points. The Weil polynomial of a Jacobian determines the number of degree-d places on the corresponding curve. The isogeny classes returned by isogeny_classes() all have the property that they predict a non-negative number of degree-d places, for d = 1, ..., g. Each isogeny class is tagged by a flag that determines whether we can prove that it does not contain a Jacobian, using one of several arguments. First, we check to make sure that the isogeny class really is an isogeny class; that is, that the Weil polynomial satisfies the conditions of the Honda-Tate theorem. (So calling them "isogeny classes" before we do this check is an abuse of nomenclature...) Second, if the dimension on the isogeny class is 2, we see whether it meets the conditions of the Howe/Nart/Ritzenthaler classification of 2-dimensional isogeny classes that contain Jacobians. Third, we check to see whether the Weil polynomial predicts a non-negative number of degree-d places, for d up to the genus. (The isogeny classes returned by isogeny_classes() have this property, but for isogeny classes that arise in certain analyses we will have to check this condition.) Fourth, if the isogeny class is maximal (that is, N is equal to the Weil bound for genus-g curves over GF(q)), we check whether the results of Korchmaros and Torres forbid the existence of a curve with Jacobian in the isogeny class. Fifth, we check to see whether the isogeny class factors as an ordinary isogeny class times a power of a supersingular elliptic curve with all endomorphisms defined. If so, we check a generalization of Corollary 12 from the Howe/Lauter paper cited below. Sixth, we check to see whether the isogeny class consists entirely of ordinary varieties that can be defined over a subfield. If so, we recurse, and check to see whether a curve (or possibly the twist of a curve) can lie in the isogeny class over the subfield. Seventh, we check to see whether the real Weil polynomial can be split into two factors whose resultant is 1. A result of Serre says that no Jacobian can lie in such a class. Eighth, we check to see whether the real Weil polynomial can be split into two factors whose "modified reduced resultant" is 2. (The modified reduced resultant is related to the resultant of the two factors, and will be described in a forthcoming paper.) In this case, any curve whose Jacobian lies in the isogeny class must have an involution, and if we can deduce a contradiction from this, we can eliminate the isogeny class from consideration. This step also involves recursion, because we can compute the possible isogeny classes of the Jacobian of the curve modulo the involution. Ninth, we check to see whether we can deduce the existence of a map of known degree from a curve in the isogeny class to an elliptic curve. Sometimes we can use this to arrive at a contradiction. Early versions of many of these tests are described more fully in [Howe and Lauter 2003]. The versions we use here will be described in [Howe and Lauter 2012]. Other items of general interest: * The procedure best_bounds(q,g). This procedure will try to find the largest integer N such that the output of isogeny_classes(q,g,N) does not include an uneliminated isogeny class. * The function double_covers(I). Given an isogeny class I, this function will return a list of isogeny classes J such that we can find no contradictions to the possibility of there being a double cover C --> D with Jac C in I and Jac D in J. The comments to isogeny_classes, best_bounds(), and double_covers() give more information about other options. This Magma code is written in a style reminiscent of Sage code. That is because it was orginally drafted in Sage, and may be translated back into that language one day if I can find out why it was running so slowly. ============================================================================== VERSION HISTORY: ------------------------------------------------------------------------------ Version 0.9, 22 March 2009. First prerelease version. ------------------------------------------------------------------------------ Version 0.94, 9 April 2009 0. Renamed "quotient characteristic" the "modified reduced resultant". 1. Corrected unsightly indentation in modifed_reduced_resultant. 2. Fixed error in modified_reduced_resultant: When computing the GCD of the coefficients of a polynomial, I forgot to coerce them into the integers. 3. Removed incorrect description of the quotient characteristic. 4. Added routine to check whether a Galois descent argument will work. 5. Added a check of place counts to process_isogeny_class, to accomodate recursion. 6. Added routine to check whether a generalized Corollary 12 will work. 7. Changed initial comment to reflect these changes above. ------------------------------------------------------------------------------ Version 0.96, 4 May 2009 1. pullback_bound_parameters was swapping det and dim. Fixed this. 2. pullback_bound_parameters was saying that Delta = -12 was OK, when Delta = -11 is real minimum. 3. is_eliminated_by_elliptic_factor was allowing the pullback to E^n of the principal polarization on Jac C to have degree 1. This can only happen when Jac C is isogenous to E^n. So we added this condition to the test. Interestingly, this makes a difference for Delta = -11; degree-1 polarizations on E^2 need not have short vectors of length 1, but degree-4 polarizations do. 4. Changed is_eliminated_by_resultant_2 so that it adds a comment to the comment field saying what has been learned about degree-2 maps, if the isogeny class is not eliminated. 5. modified_reduced_resultant sometimes returned a rational, not an integer. Fixed by replacing a / with a div. 6. isogeny_classes failed ungracefully when N1 greater than Serre bound. Fixed this, and added initial checks of Serre, Ihara, and Oesterle bounds. 7. In add_real_WP, changed an = into an := ------------------------------------------------------------------------------ Version 0.97, 11 March 2010 1. Fixed typos in comments, fleshed out some comments. 2. Added Ford/Pauli/Roblot reference. ------------------------------------------------------------------------------ Version 0.98, 17 March 2010 1. Added p_rank field to IsogenyClass records. 2. Added add_p_rank() procedure. 3. Modified is_problem_with_double_cover. Now we compute the exact number of ramification points: In char 2 by using the Deuring-Shafarevich formula, in odd characteristic by Riemann-Hurwitz. Then we can compare to upper and lower bounds obtained in other ways. 4. Fixed problem with "illegal null sequence" in add_WP. ------------------------------------------------------------------------------ Version 0.99, 7 April 2010 1. Added error check in is_isogeny_class. Checks to see whether the real Weil polynomial has the right degree. In previous versions, is_isogeny_class would just hang if it was in this situation. 2. Uniformized the error messages throughout the code. 3. Changed the comment on the very first line to reflect the current name of the file. (D'oh!) ------------------------------------------------------------------------------ Version 0.995, 2 June 2010 1. Added utility function double_covers. 2. Added the Howe/Nart/Ritzenthaler classification of isogeny classes of abelian surfaces that contain Jacobians. 3. Modified initial comments to reflect the addition of double_covers(). 4. Added boolean "is_isogeny_class" field to the IsogenyClass record. Changed the "is_isogeny_class" procedure so that it sets this field. 5. Added a reference section to make it easier to give full citations of papers mentioned in comments. ------------------------------------------------------------------------------ Version 0.996, 18 October 2010 1. Modified the way we treat polarizations on E^n, where E is ordinary with CM by the maximal order of a quadratic fields of class number 1. a. Added function NaiveBound. b. Changed pullback_bound_parameters so that it returns the set of allowable discriminants and an upper bound on the dimension. c. Changed pullback_bound so that it returns the naive bound in cases where a sharp bound has not been computed. d. Updated the sharp bounds with new values, computed using HermitianForms.magma ------------------------------------------------------------------------------ Version 0.997, 12 November 2011 1. Modified is_eliminated_by_elliptic_factor. In the case where we have a factor of E^n in the decomposition of the isogeny class, we have to obtain a bound on the degree of the pullback of a principal polarization to E^n. In earlier versions, we used a complicated formula. Now, we use a simpler and strictly more powerful bound explained in our paper. If the real Weil polynomial is (x - r)^n * f for some real Weil polynomial f, then the degree of the pullback polarization divides f(r)^2. 2. Modified is_problem_with_double_cover to more closer match the paper. ------------------------------------------------------------------------------ Version 0.998, 14 December 2011 1. Modified is_eliminated_by_elliptic_factor and pullback_bound. Lemma 4.2 of [Howe and Lauter 2012] gives an upper bound on the smallest degree polarization obtainable on an elliptic curve E by pulling back a polarization (of some given degree) on an abelian variety isogenous to E^n. Originally, this bound was only proven for a very small set of E's, but now it is more general, and is_eliminated_by_elliptic_factor and pullback_bound have been modified to reflect the change. 2. Modified NaiveBound so it gives an answer for all dimensions. 3. With the preceding changes, we no longer need the function pullback_bound_parameters. ------------------------------------------------------------------------------ To do: A. Add Zaytsev's conditions? ============================================================================== */ /* ============================================================================== REFERENCES: [Blichfeldt 1914] H. F. Blichfeldt: A new principle in the geometry of numbers, with some applications, Trans. Amer. Math. Soc. 15 (1914) 227--235. [Ford, Paul, and Roblot 2002] David Ford, Sebastian Pauli, Xavier-Francois Roblot: A fast algorithm for polynomial factorization over Q_p, J. Theor. Nombres Bordeaux 14 (2002) 151--169. [Howe and Lauter 2003] Everett W. Howe and Kristin E. Lauter: Improved upper bounds for the number of points on curves over finite fields, Ann. Inst. Fourier (Grenoble) 53 (2003) 1677--1737. Corrigendum, Ann. Inst. Fourier (Grenoble) 57 (2007) 1019--1021. [Howe and Lauter 2012] Everett W. Howe and Kristin E. Lauter: New methods for bounding the number of points on curves over finite fields, submitted for publication. [Howe, Nart, and Ritzenthaler 2009] Everett W. Howe, Enric Nart, and Christophe Ritzenthaler: Jacobians in isogeny classed of abelian surfaces over finite fields, Ann. Inst. Fourier (Grenoble) 59 (2009) 239--289. [Korchmaros and Torres 2002] G\'abor Korchm\'aros and Fernando Torres: On the genus of a maximal curve, Math. Ann. 323 (2002) 589--608. [Robinson 1964a] Raphael M. Robinson: On the spans of derivatives of polynomials, Amer. Math. Monthly 71 (1964) 504--508. [Robinson 1964b] Raphael M. Robinson: Algebraic equations with span less than 4, Math. Comp. 18 (1964) 547--559. [Smyth 1984] Christopher Smyth: Totally positive algebraic integers of small trace, Ann. Inst. Fourier (Grenoble) 33 (1984) 1--28. ============================================================================== */ /* ============================================================================== Forward definitions. ============================================================================== */ forward add_WP; forward add_real_WP; forward add_places; forward add_points; forward add_modified_reduced_resultants; forward modified_reduced_resultant; forward is_problem_with_double_cover; forward real_WP_from_WP; forward process_isogeny_class; /* ============================================================================== Isogeny classes. We will represent isogeny classes using a Magma record. The fields q and dim always have to be populated. To make any sense, we also need to specify either the WP, the real WP, the vector of places, or the vector of points. Variables --- q: Size of base field dim: Dimension WP: Weil polynomial, degree=2*dim, living in Z[] or Q[] real_WP: Real Weil polynomial, degree=dim, in Z[] or Q[] is_isogeny_class: Does the WP meet the conditions of the Honda-Tate theorem? places: Sequence of place counts, from degree 1 to degree g. points: Point counts over GF(q^i), for i = 1 to g. real_WP_factors: The factorization of real_WP p_rank: The p-rank of the isogeny class. modified_reduced_resultants: For every subset of prime factors of the real WP, the modified reduced resultant of that subset against the remaining prime factors. pairwise_modified_reduced_resultants: The matrix giving the modified reduced resultant of every prime factor of the real WP with every other prime factor. eliminated: Boolean variable, set to true if we find an argument that shows there is no Jacobian in the isogeny class. reason: If the isogeny class is eliminated, this text field explains (briefly) why. comment: Miscellaneous comments that might be useful for someone analyzing the isogeny class. Functions on isogeny classes: add_WP add_real_WP add_places add_points add_p_rank add_modified_reduced_resultants is_isogeny_class ============================================================================== */ IsogenyClass := recformat< q : Integers(), dim : Integers(), WP : PolynomialRing(Rationals()), real_WP : PolynomialRing(Rationals()), is_isogeny_class : BoolElt, places : SeqEnum, points : SeqEnum, real_WP_factors : SeqEnum, p_rank : Integers(), modified_reduced_resultants : SeqEnum, pairwise_modified_reduced_resultants : Mtrx, eliminated : BoolElt, reason : MonStgElt, comment : MonStgElt>; procedure add_WP(~self) // Compute the Weil polynomials of an isogeny class from other // information. if assigned self`WP then return; end if; if assigned self`real_WP then x := Parent(self`real_WP).1; self`WP := Numerator(x^self`dim * Evaluate(self`real_WP,x + self`q/x)); return; end if; if assigned self`points then powersums := [1 + self`q^i - self`points[i] : i in [1..self`dim]]; // Compute the signed symmetric polynomials from the power sums // using the Newton relations. signedsymmetric := [-powersums[1]]; for n in [2..self`dim] do new := (-1/n)* (powersums[n] + &+[signedsymmetric[i]*powersums[n-i] : i in [1..n-1]]); signedsymmetric cat:= [new]; end for; R:=PolynomialRing(Rationals()); self`WP := x^(2*self`dim) + self`q^self`dim + &+[signedsymmetric[i]* (x^(2*self`dim-i) + self`q^(self`dim-i)*x^i) : i in [1..self`dim-1]] + signedsymmetric[self`dim]*x^self`dim; return; end if; if assigned self`places then add_points(~self); add_WP(~self); return; end if; error "ERROR: Not enough information in isogeny class"; end procedure; procedure add_real_WP(~self) // Compute the real Weil polynomial from other information. if assigned self`real_WP then return; end if; if assigned self`WP then self`real_WP := real_WP_from_WP(self`WP); return; end if; if assigned self`points then add_WP(~self); add_real_WP(~self); return; end if; if assigned self`places then add_WP(~self); add_real_WP(~self); return; end if; error "ERROR: Not enough information in isogeny class"; end procedure; procedure add_places(~self) // Compute the number of places of degree 1, ..., dim on a curve // with Jacobian in the isogeny class. if assigned self`places then return; end if; if assigned self`points then self`places := [Integers()!( (1/n)*&+[MoebiusMu(n div d)*self`points[d] : d in Divisors(n)]) : n in [1..self`dim]]; return; end if; if assigned self`WP then add_points(~self); add_places(~self); return; end if; if assigned self`real_WP then add_WP(~self); add_places(~self); return; end if; error "ERROR: Not enough information in isogeny class"; end procedure; procedure add_points(~self) // Compute the #C(GF(q^d)) for d = 1, ..., dim for a curve C // with Jacobian in the isogeny class. if assigned self`points then return; end if; if assigned self`places then self`points := [ &+[i*self`places[i] : i in Divisors(n)] : n in [1..self`dim] ]; return; end if; if assigned self`WP then signedsymmetric := [Coefficient(self`WP, 2*self`dim-i) : i in [1..self`dim] ]; powersums := [-signedsymmetric[1]]; for n in [2..self`dim] do new := -signedsymmetric[n]*n -&+[signedsymmetric[i]*powersums[n-i] : i in [1..n-1]]; powersums cat:= [new]; end for; self`points := [1+self`q^i-powersums[i] : i in [1..self`dim]]; return; end if; if assigned self`real_WP then add_WP(~self); add_points(~self); return; end if; error "ERROR: Not enough information in isogeny class"; end procedure; procedure add_p_rank(~self) // Compute the p-rank of the abelian varieties in the isogeny class. if assigned self`p_rank then return; end if; add_real_WP(~self); rk := self`dim + 1; repeat rk-:=1; until GCD(self`q, Integers()!Coefficient(self`real_WP,self`dim-rk)) eq 1; self`p_rank := rk; end procedure; procedure add_modified_reduced_resultants(~self) // Compute the factorization of the real Weil polynomial, the matrix of // pairwise modified reduced resultants, and the list of modified // reduced resultants for all possible splittings of the real Weil // polynomial. // Here is how we enumerate the possible splittings, if there are n prime // divisors: // For every integer i from 0 to 2^(n-1)-2, consider the binary // representation of 2^(n-1) + i. This will be a string containing // exactly n bits, with the first one equal to 1, and with at least one 0. // This sequence determines the choice of factors. // Note: The integer corresponding to splitting the first factor off from // the rest is 0. The integer corresponding to splitting the i-th factor // off from the rest, with i > 1, is 2^(n-1) - 1 - 2^(n-i). if assigned self`modified_reduced_resultants then return; end if; add_real_WP(~self); self`real_WP_factors := Factorization(self`real_WP); n := #self`real_WP_factors; self`pairwise_modified_reduced_resultants := Matrix(n,[modified_reduced_resultant(a[1],b[1],self`q) : a,b in self`real_WP_factors ]); self`modified_reduced_resultants := []; for i in [0..2^(n-1)-2] do h0 := 1; h1 := 1; b := IntegerToString(2^(n-1) + i,2); for j in [1..n] do if b[j] eq "0" then h0 *:= self`real_WP_factors[j][1]; else h1 *:= self`real_WP_factors[j][1]; end if; end for; self`modified_reduced_resultants cat:= [modified_reduced_resultant(h0,h1,self`q)]; end for; return; end procedure; function real_WP_from_WP(f); // Given a Weil polynomial f, compute the corresponding real Weil // polynomial. n := Degree(f) div 2; if n eq 1 then return Parent(f)![Coefficient(f,1),1]; end if; q := Round(Coefficient(f,0)^(1/n)); if not q^n eq Coefficient(f,0) then error "ERROR: Rounding error, or incorrect Weil polynomial"; end if; h := Parent(f) ! [Coefficient(f,n + i) + &+ [(-q)^j*(i+2*j)/(i+j) *Binomial(i+j,j) *Coefficient(f, n+i+2*j) : j in [1..Floor((n+i)/2)] ] : i in [0..n] ]; return h; end function; /* ============================================================================== Reduced resultants. The *reduced resultant* of two polynomials f and g in Z[x] is the characteristic of the quotient ring Z[x] / (f,g). If f and g have a common factor, this will be 0. Otherwise, it is the smallest positive integer that lies in the ideal (f,g). Suppose h1 and h2 are real Weil q-polynomials (assumed to be coprime to one another), with associated Frobenius elements pi1 and pi2 in the centers of their associated endomorphism rings R1 and R2. Let pi be the element (pi1, pi2) of R1 x R2, and let pibar = q/pi. The *modified reducued resultant* of h1 and h2 is the smallest positive integer n such that (0, n) lies in the subring Z[pi,pibar] of R1 x R2. Usually, this n is simply the reduced resultant of h1 and h2, but if the product h1*h2 is divisible by x^2 - 4*q, we can sometimes divide the reduced resultant by 2. ============================================================================== */ function reduced_resultant(f,g) // Compute the reduced resultant of two polynomials in Z[x]. hcf, a, b := XGCD(f, g); if Degree(hcf) gt 0 then return 0; end if; return LCM([Denominator(c) : c in Coefficients(a)]); end function; function modified_reduced_resultant(h1,h2,q) // Compute the modified reduced resultant of two real Weil q-polynomials // h1 and h2. // See above for the definition. x := Parent(h1).1; hcf, a1, a2 := XGCD(h1, h2); if Degree(hcf) gt 0 then return 0; end if; n := LCM([Denominator(c) : c in Coefficients(a1)]); h := h1*h2; H, rem := Quotrem(h, x^2-4*q); if 0 eq rem then splitelt := n*a1*h1; // 0 mod h1, n mod h2 otherelt := splitelt + x*H; g := Integers()!GCD([Integers()!c : c in Coefficients(otherelt)]); if 0 eq g mod 2 then return n div 2; end if; end if; return n; end function; /* ============================================================================== Sturm sequences. We will implement Sturm sequences using a Magma record. The point of doing this is that we will often be counting roots of the same polynomial in several different intervals, so we want to amortize the cost of computing the sequence of derived polynomials. Variables --- pol : The initial polynomial in Q[x] degree : The degree of the polynomial sequence : The sequence of polynomials from Sturm's theorem infinity_plus : The number of sign changes of the sequence at a large positive number infinity_minus : The number of sign changes of the sequence at a large negative number Functions on Sturm sequences: init_Sturm_sequence add_infinity roots_to_right roots_to_left roots_between_inclusive ============================================================================== */ SturmSequence := recformat< pol : PolynomialRing(Rationals()), degree : Integers(), sequence : SeqEnum, infinity_plus : Integers(), infinity_minus : Integers()>; procedure init_Sturm_sequence(~self) self`degree := Degree(self`pol); sequence := [self`pol]; i := 1; rem := Derivative(self`pol); while rem ne 0 do sequence cat:= [rem]; rem := - sequence[i] mod sequence[i+1]; i +:= 1; end while; self`sequence := sequence; end procedure; procedure add_infinity(~self) leading := [LeadingCoefficient(s) : s in self`sequence]; positive := [c gt 0 : c in leading]; self`infinity_plus := #[i : i in [2..#positive] | positive[i] ne positive[i-1]]; leading := [LeadingCoefficient(s) * (-1)^Degree(s) : s in self`sequence]; positive := [c gt 0 : c in leading]; self`infinity_minus := #[i : i in [2..#positive] | positive[i] ne positive[i-1]]; end procedure; function roots_to_right(self,x) // Compute the number of roots greater than x. if not assigned self`infinity_plus then add_infinity(~self); end if; evaluated := [Evaluate(s,x) : s in self`sequence]; eval_nonzero := [v : v in evaluated | v ne 0]; positive := [c gt 0 : c in eval_nonzero]; return #[i : i in [2..#positive] | positive[i] ne positive[i-1]] - self`infinity_plus; end function; function roots_to_left(self,x) // Compute the number of roots less than x. if not assigned self`infinity_minus then add_infinity(~self); end if; evaluated := [Evaluate(s,x) : s in self`sequence]; eval_nonzero := [v : v in evaluated | v ne 0]; positive := [c gt 0 : c in eval_nonzero]; at_most_x := self`infinity_minus - #[i : i in [2..#positive] | positive[i] ne positive[i-1]]; if Evaluate(self`pol,x) eq 0 then return at_most_x - 1; else return at_most_x; end if; end function; function roots_between_inclusive(self,x,y) // Compute the number of roots in the closed interval [x,y] evaluated := [Evaluate(s,y) : s in self`sequence]; eval_nonzero := [v : v in evaluated | v ne 0]; positive_y := [c gt 0 : c in eval_nonzero]; evaluated := [Evaluate(s,x) : s in self`sequence]; eval_nonzero := [v : v in evaluated | v ne 0]; positive_x := [c gt 0 : c in eval_nonzero]; almost_done := #[i : i in [2..#positive_x] | positive_x[i] ne positive_x[i-1]] - #[i : i in [2..#positive_y] | positive_y[i] ne positive_y[i-1]]; if Evaluate(self`pol,x) eq 0 then return almost_done + 1; else return almost_done; end if; end function; /* ============================================================================== The Serre bound, the Ihara bound, and the Oesterle bound. Functions for computing various bounds on the number of points on a genus-g curve over GF(q). The most unusual thing here is our method of computing the Oesterle bound without using any transcendental functions, or indeed anything othere than arithmetic with integer polynomials. ============================================================================== */ function floor_root(n) // The floor of the square root of the rational number n. answer := Floor(Sqrt(n)); while answer*answer le n do answer +:= 1; end while; while answer*answer gt n do answer -:= 1; end while; return answer; end function; function Serre_bound(q,g) return q + 1 + g*floor_root(4*q); end function; function Ihara_bound(q,g) return q + 1 + Floor((floor_root((8*q+1)*g^2 + 4*(q^2-q)*g) - g) / 2); end function; function modified_Chebyshev(n,q,x) // This function computes the modified Chebyshev polynomial T_n defined // by the property that Trace(z^n) = T_n(Trace(z)) for all complex // numbers of magnitude sqrt(q). if n eq 0 then return Parent(x)!2; end if; return n*&+[(-q)^r / (n-r) * Binomial(n-r,r)*x^(n-2*r) : r in [0..Floor(n/2)]]; end function; function satisfies_Oesterle_condition(q,g,N) // Check to see whether a genus-g curve over GF(q) with N points is // allowed by Oesterle's optimized version of Serre's explicit formulae // method. We rephrase the Oesterle bound in terms of roots of // polynomials in Z[x]. R:=PolynomialRing(Rationals()); m := Floor(2*Log(q,N-1)); repeat m+:=1; until (N-1)^2 lt q^m; repeat m-:=1; until q^m le (N-1)^2; if IsOdd(m) then // The easy case. v := ( q^((m+1) div 2) - (N-1)) / (N-1 - q^((m-1) div 2)); f := modified_Chebyshev((m+1) div 2, q, x) + v*modified_Chebyshev((m-1) div 2, q, x); // Remove multiple roots so we can use Sturm sequences. f := f div GCD(f,Derivative(f)); bound := (2*N + 2*(g-1)*(q+1)) / (N + 2*(g-1)); sturm := rec; init_Sturm_sequence(~sturm); add_infinity(~sturm); return 0 eq roots_to_right(sturm,bound); else // The harder case. a := (q^(m div 2) + N - 1) * modified_Chebyshev(m div 2, q, x); b := q^(m div 2 - 1) * modified_Chebyshev(m div 2 + 1, q, x) + (N - 1) * modified_Chebyshev(m div 2 - 1, q, x); c := q^(m div 2 + 1) * modified_Chebyshev(m div 2 - 1, q, x) + (N - 1) * modified_Chebyshev(m div 2 + 1, q, x); f := (q*(a - b)^2 - (a - c)^2) div (x^2 - 4*q); // Remove multiple roots. f := f div GCD(f,Derivative(f)); bound := (2*N + 2*(g-1)*(q+1)) / (N + 2*(g-1)); sturm := rec; init_Sturm_sequence(~sturm); add_infinity(~sturm); return 0 eq roots_to_right(sturm,bound); end if; end function; function Oesterle_bound(q,g); // Compute the Oesterle bound on the number of rational points on a // genus-g curve over GF(q). // Don't go through all this trouble if the Serre bound will be best. if q le (q - 2*g)^2 and q gt 2*g then return Serre_bound(q,g); end if; // Oesterle gives a bound on g for a given q and N. We change N until // our given g meets the criterion. hi := Serre_bound(q,g) + 1; lo := q + 1; while (hi - lo) gt 1 do med := Round((hi+lo)/2); if satisfies_Oesterle_condition(q,g,med) then lo := med; else hi := med; end if; end while; return lo; end function; /* ============================================================================== The Honda-Tate theorem. Functions related to the problem of determining whether a polynomial with all complex roots on the circle of magnitude sqrt(q) satisfies the conditions of the Honda-Tate theorem. ============================================================================== */ function are_all_roots_in_closed_interval(h,a,b) // Determine whether all of the complex roots of a polynomial h lie in // the closed real interval [a,b]. // Remove multiple roots. (Sturm sequences work with separable polys.) hh := h div GCD(h,Derivative(h)); hhh := rec; init_Sturm_sequence(~hhh); return roots_between_inclusive(hhh,a,b) eq Degree(hh); end function; function are_all_roots_in_Weil_interval(h,q : root_q_plus := 0,root_q_minus := 0) // Determine whether all of the complex roots of a polynomial h lie in // the closed real Weil interval [-2*sqrt(q),2*sqrt(q)]. // The optional argument root_q_plus should be a rational number equal to // or slightly larger than sqrt(q). This is used (when q is not a square) // in a simple first test to see whether all the roots lie in the Weil // interval. // Likewise, root_q_minus should be a rational number equal to or slightly // less than the square root of q. // Remove multiple roots. hh := h div GCD(h,Derivative(h)); // First the easy case, when q is a square: bool, sq := IsSquare(q); if bool then return are_all_roots_in_closed_interval(hh,-2*sq,2*sq); end if; // Next the harder case. First, check to see whether the roots lie in the // superinterval determined by root_q_plus, if that is nonzero. if root_q_plus ne 0 then hhh := rec; init_Sturm_sequence(~hhh); if roots_between_inclusive(hhh,-2*root_q_plus, 2*root_q_plus) lt Degree(hh) then return false; end if; if roots_between_inclusive(hhh,-2*root_q_minus, 2*root_q_minus) eq Degree(hh) then return true; end if; end if; // Otherwise, do the real test. // Create the polynomial whose roots are the squares of the roots of hh. n := Degree(hh); x := Parent(hh).1; heven := &+[Coefficient(hh,i)*x^(i div 2) : i in [0..n by 2]]; hodd := &+[Coefficient(hh,i)*x^((i-1) div 2): i in [1..n by 2]]; h2 := heven^2 - x*hodd^2; return are_all_roots_in_closed_interval(h2,0,4*q); end function; procedure is_isogeny_class(~I) // Given what looks like an isogeny class, verify that the Weil polynomial // satisfies the conditions of the Honda-Tate theorem. // Modify the fields is_isogeny_class, eliminated, and reason // as necessary. add_WP(~I); add_real_WP(~I); if Degree(I`real_WP) ne I`dim then error "ERROR: Real Weil Polynomial has the wrong degree"; end if; // First check that all roots of the real Weil polynomial lie in the // real Weil interval. if not are_all_roots_in_Weil_interval(I`real_WP,I`q) then I`is_isogeny_class := false; I`eliminated := true; I`reason := "Not isogeny class: real"; return; end if; // Next check the p-adic conditions. fq := Factorization(I`q); p := fq[1][1]; e := fq[1][2]; for WPfande in Factorization(I`WP) do WP_factor := WPfande[1]; WP_exp := WPfande[2]; // We will need to know the p-adic valuations of the constant terms // of the p-adic factors of WP_factor. Carrying precision to one more // than twice the valuation of the discriminant will guarantee that we // have the correct factorization, but we may need higher precision in // order to know the valuation of the constant terms. // [Should we write up the discriminant statement? Use the version of // Hensel found in Appendix B of [Ford, Pauli, and Roblot 2002].] D := Discriminant(WP_factor); prec := Max(e,1 + 2*Valuation(D,p))-1; repeat prec +:=1; T := PolynomialRing(pAdicRing(p,prec)); localWPvals := [Valuation(Coefficient(f[1],0)) : f in Factorization(T!WP_factor)]; until Max(localWPvals) lt prec; HTexponent := LCM([Denominator(v/e) : v in localWPvals]); if WP_exp mod HTexponent ne 0 then I`is_isogeny_class := false; I`eliminated := true; I`reason := "Not isogeny class: p-adic"; return; end if; end for; I`is_isogeny_class := true; return; end procedure; /* ============================================================================== Bounds on pullbacks of polarizations. Let E be an elliptic curve with CM by Delta. Suppose we have a polarization of degree det^2 on an abelian variety A, isogenous to E^n, also with CM by Delta. Return a bound B such that there exists a map E ---> A such that the pullback polarization has degree at most B^2. Such a bound is given by Lemma 4.2 of [Howe and Lauter 2012]. For certain values of Delta, det, and n, we can get better bounds than the general ones. These bounds were computed by using the Magm routines found in the file HermitianForms.magma, available by going to http://alumnus.caltech.edu/~however/biblio.html and following the links related to the paper [Howe and Lauter 2012]. ============================================================================== */ function NaiveBound(Delta,det,dim) // Return the pullback bound obtained from viewing a Hermitian // O-lattice of rank n as a Z-lattice of rank 2n. // First, give the value of (or an upper bound for) // the gamma_{2n}^{2n}, where gamma_{2n} is the // Hermite constant for dimension 2n. case dim: when 1: hermite := 4/3; when 2: hermite := 4; when 3: hermite := 64/3; when 4: hermite := 256; else // In this case, 2*dim > 8. pi := 4272943/1360120; // A rational lower bound for pi. hermite := Ceiling( (2/pi)^(2*dim) * (Factorial(dim+1))^2); // An upper bound obtained from [Blichfeldt 1914, Theorem II]. end case; prodbound := hermite * det^2 * (-Delta/4)^dim; naivebound := Floor(prodbound^(1/2/dim)); repeat naivebound -:= 1; until naivebound^(2*dim) lt prodbound; repeat naivebound +:= 1; until naivebound^(2*dim) gt prodbound; naivebound -:= 1; return naivebound; end function; function pullback_bound(Delta, det, dim) // Let E be an elliptic curve with CM by Delta. Suppose we have a // polarization of degree det^2 on a variety A isogenous to E^dim // and also with CM by Delta. Return a bound B such that there // exists a map E ---> A such that the pullback polarization has // degree at most B^2. // For most input values, we'll return the naive bound. But for // some, we know better bounds, as computed by the programs in the // file HermitianForms.magma. if dim gt 5 or not Delta in {-3,-4,-7,-8,-11} or det gt 30 then return NaiveBound(Delta,det,dim); end if; boundmatrix3 := Matrix(30,5,[ 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 3, 2, 2, 2, 2, 4, 2, 2, 2, 2, 5, 2, 1, 2, 0, 6, 3, 2, 2, 0, 7, 2, 2, 2, 2, 8, 3, 2, 2, 0, 9, 3, 3, 3, 2, 10, 2, 2, 2, 0, 11, 3, 2, 2, 0, 12, 4, 3, 2, 2, 13, 4, 2, 2, 2, 14, 3, 2, 2, 0, 15, 4, 3, 2, 0, 16, 4, 3, 3, 3, 17, 4, 3, 2, 0, 18, 5, 3, 3, 0, 19, 4, 3, 2, 2, 20, 4, 3, 2, 0, 21, 5, 3, 3, 2, 22, 5, 2, 3, 0, 23, 5, 3, 2, 0, 24, 6, 4, 3, 0, 25, 5, 3, 3, 2, 26, 5, 3, 2, 0, 27, 6, 3, 3, 3, 28, 5, 3, 3, 3, 29, 6, 3, 3, 0, 30, 6, 4, 3, 0 ]); boundmatrix4 := Matrix(30,5,[ 1, 1, 1, 2, 1, 2, 2, 2, 2, 2, 3, 2, 1, 2, 0, 4, 2, 2, 2, 2, 5, 2, 2, 2, 2, 6, 2, 2, 2, 0, 7, 3, 2, 2, 0, 8, 4, 2, 2, 2, 9, 3, 2, 2, 2, 10, 3, 2, 2, 2, 11, 4, 2, 2, 0, 12, 4, 3, 2, 0, 13, 3, 3, 2, 2, 14, 4, 2, 0, 0, 15, 4, 3, 0, 0, 16, 4, 4, 4, 3, 17, 5, 3, 3, 2, 18, 6, 3, 3, 2, 19, 4, 3, 0, 0, 20, 5, 4, 3, 3, 21, 5, 3, 0, 0, 22, 5, 3, 0, 0, 23, 6, 3, 0, 0, 24, 6, 4, 0, 0, 25, 5, 3, 4, 3, 26, 6, 4, 3, 3, 27, 6, 4, 0, 0, 28, 6, 4, 0, 0, 29, 6, 3, 3, 0, 30, 6, 4, 0, 0 ]); boundmatrix7 := Matrix(30,5,[ 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 0, 0, 4, 2, 2, 2, 2, 5, 3, 2, 0, 0, 6, 2, 2, 0, 0, 7, 3, 3, 3, 3, 8, 4, 4, 2, 2, 9, 4, 3, 3, 3, 10, 3, 2, 0, 0, 11, 3, 3, 3, 3, 12, 4, 3, 0, 0, 13, 4, 4, 0, 0, 14, 5, 3, 3, 3, 15, 4, 3, 0, 0, 16, 4, 4, 4, 4, 17, 5, 3, 0, 0, 18, 6, 4, 4, 3, 19, 5, 3, 0, 0, 20, 6, 4, 0, 0, 21, 7, 4, 0, 0, 22, 5, 4, 3, 3, 23, 5, 4, 4, 3, 24, 6, 4, 0, 0, 25, 6, 4, 4, 3, 26, 6, 4, 0, 0, 27, 7, 6, 0, 0, 28, 7, 5, 4, 4, 29, 6, 5, 4, 0, 30, 6, 5, 0, 0 ]); boundmatrix8 := Matrix(30,5,[ 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 4, 4, 2, 4, 2, 5, 2, 2, 0, 0, 6, 3, 2, 2, 2, 7, 4, 2, 0, 0, 8, 4, 4, 4, 4, 9, 6, 3, 4, 3, 10, 4, 3, 0, 0, 11, 4, 3, 3, 3, 12, 4, 4, 4, 4, 13, 5, 3, 0, 0, 14, 6, 3, 0, 0, 15, 6, 3, 0, 0, 16, 8, 4, 4, 4, 17, 6, 4, 4, 3, 18, 6, 4, 4, 4, 19, 6, 4, 4, 3, 20, 6, 4, 0, 0, 21, 6, 4, 0, 0, 22, 7, 4, 4, 4, 23, 8, 4, 0, 0, 24, 8, 4, 4, 4, 25, 10, 4, 4, 4, 26, 6, 4, 0, 0, 27, 7, 5, 4, 4, 28, 8, 4, 0, 0, 29, 7, 4, 0, 0, 30, 8, 5, 0, 0 ]); boundmatrix11 := Matrix(30,5,[ 1, 2, 1, 2, 3, 2, 1, 2, 0, 0, 3, 2, 2, 3, 3, 4, 4, 3, 3, 3, 5, 4, 2, 4, 3, 6, 3, 3, 0, 0, 7, 3, 3, 0, 0, 8, 4, 4, 0, 0, 9, 6, 4, 4, 4, 10, 5, 4, 0, 0, 11, 6, 4, 4, 5, 12, 7, 4, 4, 4, 13, 5, 4, 0, 0, 14, 5, 4, 0, 0, 15, 6, 4, 4, 4, 16, 8, 4, 5, 4, 17, 6, 5, 0, 0, 18, 7, 5, 0, 0, 19, 8, 5, 0, 0, 20, 8, 5, 4, 4, 21, 9, 5, 0, 0, 22, 11, 5, 0, 0, 23, 6, 5, 4, 4, 24, 8, 5, 0, 0, 25, 10, 5, 5, 5, 26, 7, 5, 0, 0, 27, 8, 6, 5, 5, 28, 9, 5, 0, 0, 29, 10, 5, 0, 0, 30, 9, 5, 0, 0 ]); if Delta eq -3 then bound := boundmatrix3[det,dim]; end if; if Delta eq -4 then bound := boundmatrix4[det,dim]; end if; if Delta eq -7 then bound := boundmatrix7[det,dim]; end if; if Delta eq -8 then bound := boundmatrix8[det,dim]; end if; if Delta eq -11 then bound := boundmatrix11[det,dim]; end if; if bound ne 0 then return bound; else return NaiveBound(Delta,det,dim); end if; end function; /* ============================================================================== Eliminating isogeny classes. Here we include a number of functions that tell us whether various arguments can show that an isogeny class does not contain a Jacobian. ============================================================================== */ procedure is_eliminated_by_genus_2_classification(~I) // If the isogeny class has dimension 2, check to see whether it // meets the necessary and sufficient conditions for containing // a Jacobian. These conditions are spelled out in // [Howe, Nart, and Ritzenthaler 2009]. if I`dim ne 2 then return; end if; add_real_WP(~I); add_p_rank(~I); q := I`q; p := Factorization(q)[1][1]; // We'll default to the case that the isogeny class passes the tests, // and modify this flag as necessary. passes := true; // Are we in the split case or the simple case? split := false; f1 := Factorization(I`real_WP)[1][1]; if Degree(f1) eq 1 then J := rec; is_isogeny_class(~J); if J`is_isogeny_class then f2 := I`real_WP div f1; split := true; end if; end if; if split then s := Integers()!-Coefficient(f1,0); t := Integers()!-Coefficient(f2,0); // The conditions assume that |s| is no smaller than |t|, // so switch values around if necessary. if s^2 lt t^2 then u := s; s := t; t := u; end if; if (s-t)^2 eq 1 then passes := false; end if; case I`p_rank: when 2: if s eq t and t^2 - 4*q in {-3,-4,-7} then passes := false; end if; if q eq 2 and {s^2,t^2} eq {1} and s ne t then passes := false; end if; when 1: if s^2 eq 4*q and IsSquarefree(s-t) then passes := false; end if; when 0: if p gt 3 and s^2 ne t^2 then passes := false; end if; if p eq 3 and #{s^2,t^2,3*q} eq 1 then passes := false; end if; if p eq 3 and IsSquare(q) and not 0 eq (s-t)^2 mod (9*q) then passes := false; end if; if p eq 2 and not 0 eq (s^2-t^2) mod (2*q) then passes := false; end if; if (q eq 2 or q eq 3) and s eq t then passes := false; end if; if (q eq 4 or q eq 9) and #{s^2,t^2,4*q} eq 1 then passes := false; end if; end case; else // The non-split case. add_WP(~I); a := Integers()!Coefficient(I`WP,3); b := Integers()!Coefficient(I`WP,2); if a^2 - b eq q and b lt 0 and {1} eq ({1} join {f[1] mod 3 : f in Factorization(b)}) then passes := false; end if; case I`p_rank: when 2: if a eq 0 and b eq 1 - 2*q then passes := false; end if; if p gt 2 and a eq 0 and b eq 2 - 2*q then passes := false; end if; when 0: if 11 eq p mod 12 and IsSquare(q) and a eq 0 and b eq -q then passes := false; end if; if p eq 3 and IsSquare(q) and a eq 0 and b eq -q then passes := false; end if; if p eq 2 and not IsSquare(q) and a eq 0 and b eq -q then passes := false; end if; if (q eq 2 or q eq 3) and a eq 0 and b eq -2*q then passes := false; end if; end case; end if; if not passes then I`eliminated := true; I`reason := "Genus 2 classification"; else I`eliminated := false; I`comment := "Known to exist by genus 2 classification"; end if; return; end procedure; procedure is_eliminated_by_place_counts(~I) // Check to see whether the number of degree-d places is non-negative, // for all d up to the dimension of the isogeny class. // For the isogeny classes produced by the main portion of the // program, the place counts will always be non-negative by construction. // But for isogeny classes that arise in the analyses of these // "first-level" isogeny classes, we might have to check this. add_places(~I); if &or[ c lt 0 : c in I`places] then I`eliminated := true; I`reason := "Place counts"; end if; return; end procedure; procedure is_eliminated_by_Korchmaros_Torres(~I) // If an isogeny class is maximal, we can check to see whether the // conditions of [Korchmaros and Torres 2002] are satisfied. q := Integers()!I`q; bool, Q := IsSquare(q); if not bool then return; end if; g := I`dim; m := 2*Q; add_real_WP(~I); real_WP := I`real_WP; if real_WP ne (Parent(real_WP).1 + m)^g then return; end if; if g gt Floor((Q^2 - Q + 4)/6) and g ne Floor((Q - 1)^2 / 4) and g ne Q*(Q-1)/2 then I`eliminated := true; I`reason := "Korchmaros-Torres"; return; end if; if Q mod 3 eq 1 and Q ge 13 and g eq Q*(Q-1)/2 then I`eliminated := true; I`reason := "Korchmaros-Torres"; return; end if; return; end procedure; function minimal_endomorphism_discriminant(h,q) // Given the real Weil polynomial of an ordinary isogeny class, return // the discriminant of Z[pi,pibar]. // Make sure we're in the ordinary case. if not GCD(q,Integers()!Coefficient(h,0)) eq 1 then error "ERROR: minimal_endomorphism_discriminant called with non-ordinary h."; end if; // Replace h with its radical. hrad := h div GCD(h,Derivative(h)); // Compute the Weil polynomial. x := Parent(hrad).1; f := Numerator(Evaluate(hrad,x+q/x)); // Apply the formula from Prop. 9.4 of Howe, Trans. Amer. Math. Soc 347 // (1995) 2361--2401. n := Degree(hrad); disc_R_plus := Discriminant(hrad); norm_F_minus_V := ( (&+[Coefficient(f,2*i )*q^i : i in [0..n ]])^2 - q * (&+[Coefficient(f,2*i+1)*q^i : i in [0..n-1]])^2 ) / q^n; disc_R := (-1)^n * norm_F_minus_V * disc_R_plus^2; return Integers()!disc_R; end function; procedure is_eliminated_by_Galois_descent(~I) // Suppose I is ordinary, // q = q0^e0, // pi = pi0^e0, and // Z[pi,pibar] = Z[pi0,pi0bar]. // Then the isogeny class I0 corresponding to pi0 gives an equivalent // category to that of the isogeny class I. In particular, a PPAV in I // comes from a PPAV in I0 by Galois descent. If e0 is odd, a Jacobian // in I comes from a Jacobian in I0. If e0 is even then a Jacobian in I // comes from a PPAV in I0 that is either a Jacobian or the standard // quadratic twist of a Jacobian. // In this procedure, we check to see whether there exists an I0 of this // type for some value of e0. If there is, we check to see whether we can // find a problem with the existence of a Jacobian in I0 (and with the // existence of a twist of a Jacobian in I0, if e0 is even). q := I`q; fq := Factorization(q); p := fq[1][1]; e := fq[1][2]; add_real_WP(~I); h := I`real_WP; // If the isogeny class is not ordinary, this argument doesn't apply. if 0 eq (Integers()!Coefficient(h,0)) mod p then return; end if; fac_h := Factorization(h); factors_of_h := [hh[1] : hh in fac_h]; exponents_of_h := [hh[2] : hh in fac_h]; x := Parent(h).1; end_disc_h := minimal_endomorphism_discriminant(h,q); for e0 in Divisors(e) do if e0 gt 1 then q0 := p^(e div e0); possible_h0_factors := []; for g in factors_of_h do disc_g := minimal_endomorphism_discriminant(g,q); wp := Numerator(Evaluate(g,x + q/x)); gg := Evaluate(wp, x^e0); possibles := [f[1] : f in Factorization(gg) | Degree(f[1]) eq Degree(wp)]; possibles := [real_WP_from_WP(f) : f in possibles]; possibles := [pf : pf in possibles | minimal_endomorphism_discriminant(pf,q0) eq disc_g]; if #possibles eq 0 then break g; end if; possible_h0_factors cat:= [possibles]; end for; if #possible_h0_factors eq #factors_of_h then // Construct the Weil polynomials of the possible I0s. for factors in CartesianProduct(possible_h0_factors) do h0 := &*[factors[i]^exponents_of_h[i] : i in [1..#factors_of_h]]; end_disc_h0 := minimal_endomorphism_discriminant(h0,q0); if end_disc_h0 eq end_disc_h then I0 := rec; add_places(~I0); if &or [n lt 0 : n in I0`places] then I0`eliminated := true; I0`reason := "Negative number of places."; else process_isogeny_class(~I0 : verbose := 0); end if; if IsEven(e0) then h1 := (-1)^Degree(h0) * Evaluate(h0,-x); I1 := rec; add_places(~I1); if &or [n lt 0 : n in I1`places] then I1`eliminated := true; I1`reason := "Negative number of places."; else process_isogeny_class(~I1 : verbose := 0); end if; if I0`eliminated and I1`eliminated then I`eliminated := true; I`reason := "Galois descent to " cat Sprint(h0) cat " over GF(" cat Sprint(q0) cat "): " cat I0`reason cat " // Galois descent to " cat Sprint(h1) cat " over GF(" cat Sprint(q0) cat "): " cat I1`reason; return; end if; if not assigned I`comment then I`comment := ""; end if; I`comment cat:= "Galois descent to " cat Sprint(h0) cat " over GF(" cat Sprint(q0) cat ") // Galois descent to " cat Sprint(h1) cat " over GF(" cat Sprint(q0) cat ")\n"; else if I0`eliminated then I`eliminated := true; I`reason := "Galois descent to " cat Sprint(h0) cat " over GF(" cat Sprint(q0) cat "): " cat I0`reason; return; end if; if not assigned I`comment then I`comment := ""; end if; I`comment cat:= "Galois descent to " cat Sprint(h0) cat " over GF(" cat Sprint(q0) cat ")\n"; end if; end if; end for; end if; end if; end for; return; end procedure; procedure is_eliminated_by_supersingular_factor(~I) // Suppose q is a square, say q = s^2 with s positive or negative, // and we can write the real Weil polynomial as (x - 2*s)^n * h0 for // some ordinary h0 (!= 1). If h0(2*s) is squarefree, then there is no // nontrivial self-dual group scheme that can be embedded in both // a variety with real Weil polynomial h0 and a variety with real // Weil polynomial (x - 2*s)^n. // // This generalizes Corollary 12 of [Howe and Lauter 2003]. q := I`q; add_real_WP(~I); h := I`real_WP; x := Parent(h).1; ss_factor := GCD(h,x^2 - 4*q); if Degree(ss_factor) ne 1 then return; end if; s := Integers()!(-Coefficient(ss_factor,0)/2); // So the supersingular factor is a power of (x - 2*s). h0 := h; repeat h0 := h0 div (x - 2*s); until Evaluate(h0,2*s) ne 0; // The whole variety can't consist of the supersingular part... if Degree(h0) eq 0 then return; end if; critical_value := Integers()!Evaluate(h0,2*s); if GCD(critical_value,q) ne 1 or not IsSquarefree(critical_value) then return; end if; I`eliminated := true; I`reason := "Supersingular factor"; return; end procedure; procedure is_eliminated_by_resultant_1(~I) // Check to see whether an isogeny class is eliminated by the // `resultant = 1' argument. If so, give the splitting that produces // resultant 1. add_modified_reduced_resultants(~I); if not 1 in I`modified_reduced_resultants then return; end if; n := #I`real_WP_factors; i := [i : i in [1..#I`modified_reduced_resultants] | I`modified_reduced_resultants[i] eq 1][1] - 1; I`eliminated := true; I`reason := "Resultant 1: " cat IntegerToString(2^(n-1) + i,2); return; end procedure; procedure is_eliminated_by_resultant_2(~I) // Can we split the real Weil polynomial of an isogeny class into two // parts with modified reduced resultant 2, such that there are problems // with both possible degree-2 maps? If so, return true and a short // description of the problems. add_modified_reduced_resultants(~I); n := #I`real_WP_factors; for i in [1..#I`modified_reduced_resultants] do qc := I`modified_reduced_resultants[i]; if qc eq 2 then // Reconstruct the splitting of the Weil polynomial that gave us // the modified reduced resultant of 2. h0 := Parent(I`real_WP)!1; h1 := Parent(I`real_WP)!1; b := IntegerToString(i-1+2^(n-1),2); for j in [1..#b] do bit := b[j]; f := I`real_WP_factors[j]; if bit eq "0" then h0 *:= f[1]^f[2]; else h1 *:= f[1]^f[2]; end if; end for; // Make the isogeny classes corresponding to the two factors. J0 := rec; J1 := rec; // Is there a problem with double covers to each of these // factors? bool0, reason0 := is_problem_with_double_cover(I,J0); bool1, reason1 := is_problem_with_double_cover(I,J1); if bool0 and bool1 then I`eliminated := true; I`reason := "Resultant 2, splitting " cat b cat ": " cat reason0 cat "; " cat reason1; return; end if; if not assigned I`comment then I`comment := ""; end if; if bool0 or bool1 then if bool0 then imagecurve := "the 1-part"; else imagecurve := "the 0-part"; end if; else imagecurve := "one of the parts"; end if; I`comment cat:= "Degree-2 map to " cat imagecurve cat " of this splitting: " cat b cat "\n"; end if; end for; return; end procedure; function is_problem_with_double_cover(I,J) // Can we show that it is impossible for a curve with Jacobian in // isogeny class I to be a double cover a curve with Jacobian in isogeny // class J? If so, return true, together with a brief description of the // problem. Otherwise, return false. add_real_WP(~I); add_real_WP(~J); add_points(~I); add_points(~J); add_places(~I); add_places(~J); realWP_top := I`real_WP; realWP_bot := J`real_WP; genus_top := I`dim; genus_bot := J`dim; places_top := I`places; places_bot := J`places; q := I`q; // First, an obvious recursive check: Can we eliminate the possibility // of a curve in the bottom isogeny class? process_isogeny_class(~J : verbose := 0); if J`eliminated then return true, "No curve in lower isogeny class: " cat J`reason; end if; // Now check to see whether the number of rational points on the top // curve is at most twice the number on the bottom curve. if places_top[1] gt 2*places_bot[1] then return true, "degree-1 place counts"; end if; // Next, we'll look at conditions involving the number of ramification // points. First let's get upper and lower bounds on the number // of rational ramification points. If s is the number of splitting // places of degree 1, and i is the number of inert places of degree 1, // and r the number of ramifiying places of degree 1, then // places_bot[1] = r + s + i // places_top[1] = r + 2*s // places_top[2] >= i. // From this we see that // r <= 2*places_bot[1] - places_top[1] // r >= 2*places_bot[1] - places_top[1] - 2*places_top[2] // r = places_top[1] modulo 2. ram_upper_bound_degree_1 := 2*places_bot[1] - places_top[1]; ram_lower_bound_degree_1 := 2*places_bot[1] - places_top[1] - 2*places_top[2]; // If the lower bound is negative, replace it with the smallest // non-negative number in the same congruence class modulo 2. if ram_lower_bound_degree_1 lt 0 then ram_lower_bound_degree_1 := places_top[1] mod 2; end if; // Now let's get a lower bound on the total number of geometric // ramification points. The main point here is that if d is odd // and the d-th place count of the top curve is odd, then a // place of degree d on the bottom curve must ramify. ram_lower_bound := ram_lower_bound_degree_1 + &+([0] cat [d : d in [3..genus_top by 2] | 1 eq places_top[d] mod 2]); // Now split into cases, based on whether or not the characteristic // is equal to 2. We will compute the exact amount of ramification, // plus an extra upper bound if the characteristic is 2. if 0 eq q mod 2 then // Compute the number of ramification points by using // the Deuring-Shafarevich formula. add_p_rank(~I); add_p_rank(~J); rank_top := I`p_rank; rank_bot := J`p_rank; // D-S formula for double covers: // rank_top - 1 = 2*(rank_bot - 1) + #{ramification points} ram_exact := rank_top - 2*rank_bot + 1; // Now get an upper bound on the ramification using // Riemann-Hurwitz: ram_upper_bound := genus_top - 2*genus_bot + 1; // Any contradictions? if ram_exact gt ram_upper_bound then return true, "contradictory ramification bounds from R-H and D-S"; end if; // If there's no ramification, then ram_upper_bound should be 0. if ram_exact eq 0 and ram_upper_bound ne 0 then return true, "contradictory ramification bounds from R-H and D-S"; end if; if ram_exact lt ram_lower_bound then return true, "contradictory ramification bounds from D-S and point counts"; end if; else // In this case, q is odd. We compute the genus using // Riemann-Hurwitz. ram_exact := 2*genus_top - 4*genus_bot + 2; if ram_exact lt ram_lower_bound then return true, "contradictory ramification bounds from R-H and point counts"; end if; end if; return false, ""; end function; function is_problem_with_map_to_E(I, E, n) // Determine whether there are any obvious objections to the existence of // a degree-n map from a curve with Jacobian in the isogeny class I to an // elliptic curve in the 1-dimensional isogeny class E. If there are, // return true, together with a short description of one problem. If not, // return false. add_real_WP(~E); add_real_WP(~I); if 0 ne I`real_WP mod E`real_WP then return false, "E doesn't occur in Jacobian of C"; // Really, we should never be in this case. end if; if n eq 1 then if I`dim eq 1 then return false, ""; else return true, "can't have a degree-1 map"; end if; end if; if n eq 2 then return is_problem_with_double_cover(I,E); end if; // For larger n, the only condition that seems widely applicable is to // test whether the curve has more than n times the number of rational // points that E has. add_points(~E); add_points(~I); if I`points[1] gt n*E`points[1] then return true, "too many rational points"; end if; return false, ""; end function; function poly_val_mod_p(f,g,p) // Given polynomials f and g in QQ[x], with g monic linear, and with all // coefficients in ZZ, and given a prime p, return the valuation of // (f mod p) with respect to (g mod p). T := PolynomialRing(GF(p)); return -Valuation(1/T!f, T!g); end function; procedure is_eliminated_by_elliptic_factor(~I) // If there is a Jacobian of a curve C in the isogeny class I, can we // deduce the existence of a map from C to an elliptic factor of I that // will give a contradiction? If so, return true and a description of the // problem. If not, return false. // There are really two arguments: If there is a factor (x - t)^1 in the // real Weil polynomial, we immediately deduce a degree-n map to E, for // some divisor n of the modifed reduced resultant of E with the other // factor of I. But if there is a factor (x - t)^e, we can sometimes // deduce decent bounds on a corresponding map to E. // The whole method depends on the genus being greater than 1. // In recursive calls, we might have genus 1. If so, return // immediately. if I`dim eq 1 then return; end if; // Now check the easy case: An elliptic curve to the first power. add_modified_reduced_resultants(~I); n := #I`real_WP_factors; for i in [1..n] do f := I`real_WP_factors[i]; WP_fact := f[1]; WP_exp := f[2]; if Degree(WP_fact) eq 1 and WP_exp eq 1 then // In this case, we have found an elliptic curve // to the first power as an isogeny factor. // Get the corresponding modified reduced resultant. if i eq 1 then modredres := I`modified_reduced_resultants[1]; else modredres := I`modified_reduced_resultants[2^(n - 1) - 2^(n - i)]; end if; // There will be a map to E of degree dividing the // modifed reduced resultant. degs := Divisors(modredres); problems := [is_problem_with_map_to_E( I, rec, r) : r in degs]; if &and problems then I`eliminated := true; I`reason := "Elliptic factor: map of degree dividing " cat Sprint(modredres) cat " to " cat Sprint(WP_fact); return; else if not assigned I`comment then I`comment := ""; end if; I`comment cat:= "Map to " cat Sprint(WP_fact) cat " of one of these degrees: " cat Sprint([degs[i]: i in [1..#degs] | not problems[i]]) cat "\n"; end if; end if; end for; // OK, so there were no problems coming from single factors. // Do the harder case. for i in [1..n] do f := I`real_WP_factors[i]; WP_fact := f[1]; WP_exp := f[2]; if WP_exp gt 1 and Degree(WP_fact) eq 1 and GCD(Numerator(Coefficient(WP_fact,0)) ,I`q) eq 1 then // We have a power of an ordinary elliptic curve. delta := Coefficient(WP_fact,0)^2 - 4*I`q; // Get the modified reduced resultant if we have more // than one factor. if n gt 1 then if i eq 1 then modredres := I`modified_reduced_resultants[1]; else modredres := I`modified_reduced_resultants[2^(n - 1) - 2^(n - i)]; end if; else // The isogeny class itself is a power of an elliptic // curve. So we check whether there's a problem with // a degree-1 polarization on this power. modredres := 1; end if; otherRWP := Numerator(I`real_WP / WP_fact^WP_exp); // OK. At this point we know that the kernel of the // polarization lives in the modredres-torsion of E^WP_exp. // For each prime divisor p of modredres, we need to // figure out how much of the p-power torsion of E^WP_exp // can be isomorphic to some of the p-power torsion // of the other isogeny factor. // Doing this properly would require a fairly detailed // analysis of the group-scheme structure of the p-torsion // of the varieties in question, and that is more than // we can build into this program. So instead we will // make an easy, but more crude, estimate. // Our real Weil polynomial is // WP_fact^WP_exp * otherRWP. // Say the root of WP_fact is r. Then Frob+Ver-r = 0 // on the kernel of the polarization, so if we could // determine the degree of Frob+Ver-r on the abelian // varieties with real Weil polynomial equal to // otherRWP, we would get another bound on the size // of the kernel. But since otherRWP^2 is the // characteristic polynomial of Frob+Ver, the constant // term of the characteristic polynomial of // Frob+Ver-r is equal to otherRWP(r)^2 --- and this // constant term is the degree of the isogeny. // So we bound the size of the kernel by // modredres^(2*WP_exp) // and by // otherRWP(r)^2, // so we bound the size of the determinant of the // matrix by // GCD(otherRWP(r), modredres^WP_exp). // (This is the argument used in the proof of Prop. 4.1 // of the paper to which this program is attached.) polarization_bound1 := Integers()!(modredres^WP_exp); polarization_bound2 := Integers()! AbsoluteValue( Evaluate(otherRWP, Roots(WP_fact)[1][1])); polarization_bound := GCD(polarization_bound1, polarization_bound2); // For every possible polarization degree, compute the // pullback bound. bound := 0; // An initial value for the bound. for det in Divisors(polarization_bound) do // We can only have polarization degree equal to 1 // in the case where I is a power of an elliptic // curve. if det gt 1 or Degree(otherRWP) eq 0 then pbb := pullback_bound(delta, det, WP_exp); bound := Max(bound,pbb); end if; end for; degs := [1..bound]; problems := [is_problem_with_map_to_E( I, rec, r) : r in degs]; if &and problems then I`eliminated := true; I`reason := "Elliptic factor: map of degree at" cat " most " cat Sprint(bound) cat " to " cat Sprint(WP_fact); return; else if not assigned I`comment then I`comment := ""; end if; I`comment cat:= "Map to " cat Sprint(WP_fact) cat " of one of these degrees: " cat Sprint([degs[i]: i in [1..#degs] | not problems[i]]) cat "\n"; end if; end if; end for; return; end procedure; /* ============================================================================== Deficient polynomials. A function that returns the totally positive irreducible polynomials with small deficiency. The polynomials were computed as in [Smyth 1984]. ============================================================================== */ max_defect := 6; function deficient_polynomial_list(x,n) if n gt max_defect then error "ERROR: Requested polynomials of too high deficieny"; end if; case n: when 1: return [ x - 2, x^2 - 3*x + 1 ]; when 2: return [ x - 3, x^2 - 4*x + 1, x^2 - 4*x + 2, x^3 - 5*x^2 + 6*x - 1 ]; when 3: return [ x - 4, x^2 - 5*x + 1, x^2 - 5*x + 2, x^2 - 5*x + 3, x^2 - 5*x + 5, x^3 - 6*x^2 + 5*x - 1, x^3 - 6*x^2 + 7*x - 1, x^3 - 6*x^2 + 8*x - 2, x^3 - 6*x^2 + 8*x - 1, x^3 - 6*x^2 + 9*x - 3, x^3 - 6*x^2 + 9*x - 1, x^4 - 7*x^3 + 13*x^2 - 7*x + 1, x^4 - 7*x^3 + 14*x^2 - 8*x + 1 ]; when 4: return [ x - 5, x^2 - 6*x + 1, x^2 - 6*x + 2, x^2 - 6*x + 3, x^2 - 6*x + 4, x^2 - 6*x + 6, x^2 - 6*x + 7, x^3 - 7*x^2 + 6*x - 1, x^3 - 7*x^2 + 8*x - 1, x^3 - 7*x^2 + 9*x - 2, x^3 - 7*x^2 + 9*x - 1, x^3 - 7*x^2 + 10*x - 3, x^3 - 7*x^2 + 10*x - 2, x^3 - 7*x^2 + 10*x - 1, x^3 - 7*x^2 + 11*x - 4, x^3 - 7*x^2 + 11*x - 3, x^3 - 7*x^2 + 11*x - 1, x^3 - 7*x^2 + 12*x - 5, x^3 - 7*x^2 + 12*x - 3, x^3 - 7*x^2 + 12*x - 2, x^3 - 7*x^2 + 12*x - 1, x^3 - 7*x^2 + 13*x - 5, x^3 - 7*x^2 + 14*x - 7, x^4 - 8*x^3 + 14*x^2 - 7*x + 1, x^4 - 8*x^3 + 15*x^2 - 8*x + 1, x^4 - 8*x^3 + 16*x^2 - 9*x + 1, x^4 - 8*x^3 + 16*x^2 - 8*x + 1, x^4 - 8*x^3 + 17*x^2 - 10*x + 1, x^4 - 8*x^3 + 17*x^2 - 9*x + 1, x^4 - 8*x^3 + 18*x^2 - 13*x + 1, x^4 - 8*x^3 + 18*x^2 - 12*x + 2, x^4 - 8*x^3 + 18*x^2 - 11*x + 1, x^4 - 8*x^3 + 18*x^2 - 10*x + 1, x^4 - 8*x^3 + 18*x^2 - 9*x + 1, x^4 - 8*x^3 + 19*x^2 - 14*x + 1, x^4 - 8*x^3 + 19*x^2 - 13*x + 2, x^4 - 8*x^3 + 19*x^2 - 12*x + 1, x^4 - 8*x^3 + 20*x^2 - 17*x + 3, x^4 - 8*x^3 + 20*x^2 - 16*x + 1, x^4 - 8*x^3 + 20*x^2 - 16*x + 2, x^5 - 9*x^4 + 26*x^3 - 29*x^2 + 11*x - 1, x^5 - 9*x^4 + 27*x^3 - 32*x^2 + 13*x - 1, x^5 - 9*x^4 + 27*x^3 - 31*x^2 + 12*x - 1, x^5 - 9*x^4 + 28*x^3 - 35*x^2 + 15*x - 1 ]; when 5: return [ x - 6, x^2 - 7*x + 1, x^2 - 7*x + 2, x^2 - 7*x + 3, x^2 - 7*x + 4, x^2 - 7*x + 5, x^2 - 7*x + 7, x^2 - 7*x + 8, x^2 - 7*x + 9, x^2 - 7*x + 11, x^3 - 8*x^2 + 6*x - 1, x^3 - 8*x^2 + 7*x - 1, x^3 - 8*x^2 + 8*x - 2, x^3 - 8*x^2 + 9*x - 1, x^3 - 8*x^2 + 10*x - 2, x^3 - 8*x^2 + 10*x - 1, x^3 - 8*x^2 + 11*x - 3, x^3 - 8*x^2 + 11*x - 2, x^3 - 8*x^2 + 11*x - 1, x^3 - 8*x^2 + 12*x - 4, x^3 - 8*x^2 + 12*x - 3, x^3 - 8*x^2 + 12*x - 2, x^3 - 8*x^2 + 12*x - 1, x^3 - 8*x^2 + 13*x - 5, x^3 - 8*x^2 + 13*x - 4, x^3 - 8*x^2 + 13*x - 3, x^3 - 8*x^2 + 13*x - 1, x^3 - 8*x^2 + 14*x - 6, x^3 - 8*x^2 + 14*x - 5, x^3 - 8*x^2 + 14*x - 3, x^3 - 8*x^2 + 14*x - 2, x^3 - 8*x^2 + 14*x - 1, x^3 - 8*x^2 + 15*x - 7, x^3 - 8*x^2 + 15*x - 5, x^3 - 8*x^2 + 15*x - 4, x^3 - 8*x^2 + 15*x - 3, x^3 - 8*x^2 + 15*x - 2, x^3 - 8*x^2 + 15*x - 1, x^3 - 8*x^2 + 16*x - 7, x^3 - 8*x^2 + 16*x - 6, x^3 - 8*x^2 + 16*x - 4, x^3 - 8*x^2 + 16*x - 2, x^3 - 8*x^2 + 16*x - 1, x^3 - 8*x^2 + 17*x - 9, x^3 - 8*x^2 + 17*x - 8, x^3 - 8*x^2 + 17*x - 7, x^3 - 8*x^2 + 17*x - 5, x^3 - 8*x^2 + 18*x - 10, x^3 - 8*x^2 + 19*x - 13, x^4 - 9*x^3 + 16*x^2 - 8*x + 1, x^4 - 9*x^3 + 17*x^2 - 9*x + 1, x^4 - 9*x^3 + 17*x^2 - 8*x + 1, x^4 - 9*x^3 + 18*x^2 - 11*x + 2, x^4 - 9*x^3 + 18*x^2 - 10*x + 1, x^4 - 9*x^3 + 18*x^2 - 9*x + 1, x^4 - 9*x^3 + 18*x^2 - 8*x + 1, x^4 - 9*x^3 + 19*x^2 - 12*x + 2, x^4 - 9*x^3 + 19*x^2 - 11*x + 1, x^4 - 9*x^3 + 19*x^2 - 10*x + 1, x^4 - 9*x^3 + 19*x^2 - 9*x + 1, x^4 - 9*x^3 + 20*x^2 - 14*x + 3, x^4 - 9*x^3 + 20*x^2 - 12*x + 1, x^4 - 9*x^3 + 20*x^2 - 12*x + 2, x^4 - 9*x^3 + 20*x^2 - 11*x + 1, x^4 - 9*x^3 + 20*x^2 - 10*x + 1, x^4 - 9*x^3 + 21*x^2 - 15*x + 1, x^4 - 9*x^3 + 21*x^2 - 15*x + 3, x^4 - 9*x^3 + 21*x^2 - 14*x + 2, x^4 - 9*x^3 + 21*x^2 - 13*x + 1, x^4 - 9*x^3 + 21*x^2 - 13*x + 2, x^4 - 9*x^3 + 21*x^2 - 12*x + 1, x^4 - 9*x^3 + 21*x^2 - 11*x + 1, x^4 - 9*x^3 + 21*x^2 - 10*x + 1, x^4 - 9*x^3 + 21*x^2 - 9*x + 1, x^4 - 9*x^3 + 22*x^2 - 18*x + 3, x^4 - 9*x^3 + 22*x^2 - 17*x + 4, x^4 - 9*x^3 + 22*x^2 - 16*x + 1, x^4 - 9*x^3 + 22*x^2 - 16*x + 3, x^4 - 9*x^3 + 22*x^2 - 15*x + 2, x^4 - 9*x^3 + 22*x^2 - 14*x + 1, x^4 - 9*x^3 + 22*x^2 - 14*x + 2, x^4 - 9*x^3 + 22*x^2 - 13*x + 1, x^4 - 9*x^3 + 22*x^2 - 13*x + 2, x^4 - 9*x^3 + 22*x^2 - 12*x + 1, x^4 - 9*x^3 + 22*x^2 - 11*x + 1, x^4 - 9*x^3 + 22*x^2 - 10*x + 1, x^4 - 9*x^3 + 23*x^2 - 19*x + 3, x^4 - 9*x^3 + 23*x^2 - 18*x + 1, x^4 - 9*x^3 + 23*x^2 - 18*x + 2, x^4 - 9*x^3 + 23*x^2 - 17*x + 1, x^4 - 9*x^3 + 23*x^2 - 17*x + 3, x^4 - 9*x^3 + 23*x^2 - 16*x + 2, x^4 - 9*x^3 + 23*x^2 - 15*x + 1, x^4 - 9*x^3 + 23*x^2 - 15*x + 2, x^4 - 9*x^3 + 23*x^2 - 14*x + 1, x^4 - 9*x^3 + 23*x^2 - 13*x + 1, x^4 - 9*x^3 + 24*x^2 - 22*x + 5, x^4 - 9*x^3 + 24*x^2 - 21*x + 3, x^4 - 9*x^3 + 24*x^2 - 21*x + 4, x^4 - 9*x^3 + 24*x^2 - 20*x + 1, x^4 - 9*x^3 + 24*x^2 - 20*x + 2, x^4 - 9*x^3 + 24*x^2 - 20*x + 3, x^4 - 9*x^3 + 24*x^2 - 20*x + 5, x^4 - 9*x^3 + 24*x^2 - 19*x + 1, x^4 - 9*x^3 + 24*x^2 - 19*x + 2, x^4 - 9*x^3 + 24*x^2 - 19*x + 4, x^4 - 9*x^3 + 24*x^2 - 18*x + 1, x^4 - 9*x^3 + 24*x^2 - 18*x + 3, x^4 - 9*x^3 + 24*x^2 - 17*x + 2, x^4 - 9*x^3 + 25*x^2 - 25*x + 7, x^4 - 9*x^3 + 25*x^2 - 24*x + 5, x^4 - 9*x^3 + 25*x^2 - 23*x + 3, x^4 - 9*x^3 + 25*x^2 - 23*x + 4, x^4 - 9*x^3 + 25*x^2 - 23*x + 5, x^4 - 9*x^3 + 25*x^2 - 22*x + 1, x^4 - 9*x^3 + 25*x^2 - 22*x + 2, x^4 - 9*x^3 + 25*x^2 - 22*x + 4, x^4 - 9*x^3 + 25*x^2 - 21*x + 1, x^4 - 9*x^3 + 25*x^2 - 21*x + 2, x^4 - 9*x^3 + 25*x^2 - 21*x + 3, x^4 - 9*x^3 + 26*x^2 - 28*x + 9, x^4 - 9*x^3 + 26*x^2 - 27*x + 8, x^4 - 9*x^3 + 26*x^2 - 26*x + 5, x^4 - 9*x^3 + 26*x^2 - 26*x + 7, x^4 - 9*x^3 + 26*x^2 - 24*x + 1, x^4 - 9*x^3 + 27*x^2 - 31*x + 11, x^5 - 10*x^4 + 28*x^3 - 29*x^2 + 10*x - 1, x^5 - 10*x^4 + 29*x^3 - 32*x^2 + 12*x - 1, x^5 - 10*x^4 + 29*x^3 - 31*x^2 + 11*x - 1, x^5 - 10*x^4 + 29*x^3 - 30*x^2 + 10*x - 1, x^5 - 10*x^4 + 29*x^3 - 28*x^2 + 10*x - 1, x^5 - 10*x^4 + 30*x^3 - 34*x^2 + 13*x - 1, x^5 - 10*x^4 + 30*x^3 - 33*x^2 + 11*x - 1, x^5 - 10*x^4 + 30*x^3 - 33*x^2 + 12*x - 1, x^5 - 10*x^4 + 30*x^3 - 29*x^2 + 10*x - 1, x^5 - 10*x^4 + 31*x^3 - 37*x^2 + 15*x - 1, x^5 - 10*x^4 + 31*x^3 - 37*x^2 + 16*x - 2, x^5 - 10*x^4 + 31*x^3 - 36*x^2 + 13*x - 1, x^5 - 10*x^4 + 31*x^3 - 36*x^2 + 14*x - 1, x^5 - 10*x^4 + 31*x^3 - 35*x^2 + 11*x - 1, x^5 - 10*x^4 + 31*x^3 - 35*x^2 + 13*x - 1, x^5 - 10*x^4 + 31*x^3 - 34*x^2 + 11*x - 1, x^5 - 10*x^4 + 31*x^3 - 34*x^2 + 12*x - 1, x^5 - 10*x^4 + 31*x^3 - 33*x^2 + 11*x - 1, x^5 - 10*x^4 + 31*x^3 - 31*x^2 + 11*x - 1, x^5 - 10*x^4 + 32*x^3 - 41*x^2 + 20*x - 3, x^5 - 10*x^4 + 32*x^3 - 40*x^2 + 17*x - 1, x^5 - 10*x^4 + 32*x^3 - 40*x^2 + 18*x - 2, x^5 - 10*x^4 + 32*x^3 - 39*x^2 + 15*x - 1, x^5 - 10*x^4 + 32*x^3 - 39*x^2 + 16*x - 1, x^5 - 10*x^4 + 32*x^3 - 39*x^2 + 17*x - 2, x^5 - 10*x^4 + 32*x^3 - 38*x^2 + 14*x - 1, x^5 - 10*x^4 + 32*x^3 - 38*x^2 + 15*x - 1, x^5 - 10*x^4 + 32*x^3 - 38*x^2 + 16*x - 2, x^5 - 10*x^4 + 32*x^3 - 37*x^2 + 12*x - 1, x^5 - 10*x^4 + 32*x^3 - 37*x^2 + 13*x - 1, x^5 - 10*x^4 + 32*x^3 - 37*x^2 + 14*x - 1, x^5 - 10*x^4 + 32*x^3 - 36*x^2 + 12*x - 1, x^5 - 10*x^4 + 32*x^3 - 36*x^2 + 13*x - 1, x^5 - 10*x^4 + 32*x^3 - 35*x^2 + 12*x - 1, x^5 - 10*x^4 + 33*x^3 - 44*x^2 + 22*x - 3, x^5 - 10*x^4 + 33*x^3 - 43*x^2 + 19*x - 1, x^5 - 10*x^4 + 33*x^3 - 43*x^2 + 20*x - 2, x^5 - 10*x^4 + 33*x^3 - 43*x^2 + 21*x - 3, x^5 - 10*x^4 + 33*x^3 - 42*x^2 + 17*x - 1, x^5 - 10*x^4 + 33*x^3 - 42*x^2 + 18*x - 2, x^5 - 10*x^4 + 33*x^3 - 42*x^2 + 18*x - 1, x^5 - 10*x^4 + 33*x^3 - 42*x^2 + 19*x - 2, x^5 - 10*x^4 + 33*x^3 - 42*x^2 + 20*x - 3, x^5 - 10*x^4 + 33*x^3 - 41*x^2 + 15*x - 1, x^5 - 10*x^4 + 33*x^3 - 41*x^2 + 16*x - 1, x^5 - 10*x^4 + 33*x^3 - 41*x^2 + 17*x - 1, x^5 - 10*x^4 + 33*x^3 - 40*x^2 + 12*x - 1, x^5 - 10*x^4 + 33*x^3 - 40*x^2 + 13*x - 1, x^5 - 10*x^4 + 33*x^3 - 40*x^2 + 14*x - 1, x^5 - 10*x^4 + 33*x^3 - 40*x^2 + 15*x - 1, x^5 - 10*x^4 + 33*x^3 - 40*x^2 + 16*x - 1, x^5 - 10*x^4 + 34*x^3 - 47*x^2 + 24*x - 3, x^5 - 10*x^4 + 34*x^3 - 47*x^2 + 25*x - 4, x^5 - 10*x^4 + 34*x^3 - 46*x^2 + 21*x - 1, x^5 - 10*x^4 + 34*x^3 - 46*x^2 + 22*x - 2, x^5 - 10*x^4 + 34*x^3 - 45*x^2 + 18*x - 1, x^5 - 10*x^4 + 34*x^3 - 45*x^2 + 19*x - 1, x^5 - 10*x^4 + 34*x^3 - 45*x^2 + 20*x - 1, x^5 - 10*x^4 + 34*x^3 - 44*x^2 + 16*x - 1, x^5 - 10*x^4 + 35*x^3 - 51*x^2 + 27*x - 1, x^5 - 10*x^4 + 35*x^3 - 51*x^2 + 29*x - 5, x^5 - 10*x^4 + 35*x^3 - 50*x^2 + 24*x - 1, x^6 - 11*x^5 + 42*x^4 - 68*x^3 + 46*x^2 - 12*x + 1, x^6 - 11*x^5 + 42*x^4 - 68*x^3 + 47*x^2 - 13*x + 1, x^6 - 11*x^5 + 42*x^4 - 67*x^3 + 45*x^2 - 12*x + 1, x^6 - 11*x^5 + 43*x^4 - 74*x^3 + 55*x^2 - 14*x + 1, x^6 - 11*x^5 + 43*x^4 - 73*x^3 + 53*x^2 - 15*x + 1, x^6 - 11*x^5 + 43*x^4 - 72*x^3 + 50*x^2 - 13*x + 1, x^6 - 11*x^5 + 43*x^4 - 72*x^3 + 51*x^2 - 14*x + 1, x^6 - 11*x^5 + 44*x^4 - 79*x^3 + 63*x^2 - 18*x + 1, x^6 - 11*x^5 + 44*x^4 - 78*x^3 + 59*x^2 - 15*x + 1, x^6 - 11*x^5 + 44*x^4 - 78*x^3 + 60*x^2 - 16*x + 1, x^6 - 11*x^5 + 45*x^4 - 84*x^3 + 70*x^2 - 21*x + 1 ]; when 6: return [ x - 7, x^2 - 8*x + 1, x^2 - 8*x + 2, x^2 - 8*x + 3, x^2 - 8*x + 4, x^2 - 8*x + 5, x^2 - 8*x + 6, x^2 - 8*x + 8, x^2 - 8*x + 9, x^2 - 8*x + 10, x^2 - 8*x + 11, x^2 - 8*x + 13, x^2 - 8*x + 14, x^3 - 9*x^2 + 6*x - 1, x^3 - 9*x^2 + 7*x - 1, x^3 - 9*x^2 + 8*x - 1, x^3 - 9*x^2 + 9*x - 2, x^3 - 9*x^2 + 10*x - 1, x^3 - 9*x^2 + 11*x - 2, x^3 - 9*x^2 + 11*x - 1, x^3 - 9*x^2 + 12*x - 3, x^3 - 9*x^2 + 12*x - 2, x^3 - 9*x^2 + 12*x - 1, x^3 - 9*x^2 + 13*x - 4, x^3 - 9*x^2 + 13*x - 3, x^3 - 9*x^2 + 13*x - 2, x^3 - 9*x^2 + 13*x - 1, x^3 - 9*x^2 + 14*x - 5, x^3 - 9*x^2 + 14*x - 4, x^3 - 9*x^2 + 14*x - 3, x^3 - 9*x^2 + 14*x - 2, x^3 - 9*x^2 + 14*x - 1, x^3 - 9*x^2 + 15*x - 6, x^3 - 9*x^2 + 15*x - 5, x^3 - 9*x^2 + 15*x - 4, x^3 - 9*x^2 + 15*x - 3, x^3 - 9*x^2 + 15*x - 1, x^3 - 9*x^2 + 16*x - 7, x^3 - 9*x^2 + 16*x - 6, x^3 - 9*x^2 + 16*x - 5, x^3 - 9*x^2 + 16*x - 3, x^3 - 9*x^2 + 16*x - 2, x^3 - 9*x^2 + 16*x - 1, x^3 - 9*x^2 + 17*x - 8, x^3 - 9*x^2 + 17*x - 7, x^3 - 9*x^2 + 17*x - 5, x^3 - 9*x^2 + 17*x - 4, x^3 - 9*x^2 + 17*x - 3, x^3 - 9*x^2 + 17*x - 2, x^3 - 9*x^2 + 17*x - 1, x^3 - 9*x^2 + 18*x - 9, x^3 - 9*x^2 + 18*x - 7, x^3 - 9*x^2 + 18*x - 6, x^3 - 9*x^2 + 18*x - 5, x^3 - 9*x^2 + 18*x - 4, x^3 - 9*x^2 + 18*x - 3, x^3 - 9*x^2 + 18*x - 2, x^3 - 9*x^2 + 18*x - 1, x^3 - 9*x^2 + 19*x - 9, x^3 - 9*x^2 + 19*x - 8, x^3 - 9*x^2 + 19*x - 7, x^3 - 9*x^2 + 19*x - 5, x^3 - 9*x^2 + 19*x - 4, x^3 - 9*x^2 + 19*x - 2, x^3 - 9*x^2 + 19*x - 1, x^3 - 9*x^2 + 20*x - 13, x^3 - 9*x^2 + 20*x - 11, x^3 - 9*x^2 + 20*x - 10, x^3 - 9*x^2 + 20*x - 9, x^3 - 9*x^2 + 20*x - 8, x^3 - 9*x^2 + 20*x - 7, x^3 - 9*x^2 + 20*x - 5, x^3 - 9*x^2 + 20*x - 4, x^3 - 9*x^2 + 20*x - 3, x^3 - 9*x^2 + 20*x - 2, x^3 - 9*x^2 + 20*x - 1, x^3 - 9*x^2 + 21*x - 12, x^3 - 9*x^2 + 21*x - 11, x^3 - 9*x^2 + 21*x - 10, x^3 - 9*x^2 + 21*x - 8, x^3 - 9*x^2 + 21*x - 7, x^3 - 9*x^2 + 21*x - 6, x^3 - 9*x^2 + 22*x - 15, x^3 - 9*x^2 + 22*x - 13, x^3 - 9*x^2 + 22*x - 11, x^3 - 9*x^2 + 22*x - 9, x^3 - 9*x^2 + 23*x - 17, x^3 - 9*x^2 + 23*x - 16, x^3 - 9*x^2 + 23*x - 14, x^3 - 9*x^2 + 23*x - 13, x^3 - 9*x^2 + 24*x - 19, x^3 - 9*x^2 + 24*x - 17, x^4 - 10*x^3 + 17*x^2 - 8*x + 1, x^4 - 10*x^3 + 18*x^2 - 9*x + 1, x^4 - 10*x^3 + 18*x^2 - 8*x + 1, x^4 - 10*x^3 + 19*x^2 - 10*x + 1, x^4 - 10*x^3 + 19*x^2 - 9*x + 1, x^4 - 10*x^3 + 20*x^2 - 12*x + 2, x^4 - 10*x^3 + 20*x^2 - 11*x + 1, x^4 - 10*x^3 + 20*x^2 - 10*x + 1, x^4 - 10*x^3 + 20*x^2 - 9*x + 1, x^4 - 10*x^3 + 21*x^2 - 13*x + 2, x^4 - 10*x^3 + 21*x^2 - 12*x + 1, x^4 - 10*x^3 + 21*x^2 - 12*x + 2, x^4 - 10*x^3 + 21*x^2 - 11*x + 1, x^4 - 10*x^3 + 21*x^2 - 10*x + 1, x^4 - 10*x^3 + 21*x^2 - 9*x + 1, x^4 - 10*x^3 + 22*x^2 - 15*x + 3, x^4 - 10*x^3 + 22*x^2 - 14*x + 2, x^4 - 10*x^3 + 22*x^2 - 13*x + 1, x^4 - 10*x^3 + 22*x^2 - 12*x + 1, x^4 - 10*x^3 + 22*x^2 - 11*x + 1, x^4 - 10*x^3 + 22*x^2 - 10*x + 1, x^4 - 10*x^3 + 22*x^2 - 9*x + 1, x^4 - 10*x^3 + 23*x^2 - 16*x + 1, x^4 - 10*x^3 + 23*x^2 - 16*x + 3, x^4 - 10*x^3 + 23*x^2 - 14*x + 1, x^4 - 10*x^3 + 23*x^2 - 14*x + 2, x^4 - 10*x^3 + 23*x^2 - 13*x + 1, x^4 - 10*x^3 + 23*x^2 - 13*x + 2, x^4 - 10*x^3 + 23*x^2 - 12*x + 1, x^4 - 10*x^3 + 23*x^2 - 11*x + 1, x^4 - 10*x^3 + 24*x^2 - 18*x + 2, x^4 - 10*x^3 + 24*x^2 - 17*x + 1, x^4 - 10*x^3 + 24*x^2 - 17*x + 3, x^4 - 10*x^3 + 24*x^2 - 16*x + 2, x^4 - 10*x^3 + 24*x^2 - 16*x + 3, x^4 - 10*x^3 + 24*x^2 - 15*x + 1, x^4 - 10*x^3 + 24*x^2 - 15*x + 2, x^4 - 10*x^3 + 24*x^2 - 14*x + 1, x^4 - 10*x^3 + 24*x^2 - 14*x + 2, x^4 - 10*x^3 + 24*x^2 - 13*x + 1, x^4 - 10*x^3 + 24*x^2 - 12*x + 1, x^4 - 10*x^3 + 24*x^2 - 11*x + 1, x^4 - 10*x^3 + 24*x^2 - 10*x + 1, x^4 - 10*x^3 + 25*x^2 - 21*x + 4, x^4 - 10*x^3 + 25*x^2 - 20*x + 3, x^4 - 10*x^3 + 25*x^2 - 20*x + 5, x^4 - 10*x^3 + 25*x^2 - 19*x + 1, x^4 - 10*x^3 + 25*x^2 - 19*x + 4, x^4 - 10*x^3 + 25*x^2 - 18*x + 1, x^4 - 10*x^3 + 25*x^2 - 18*x + 3, x^4 - 10*x^3 + 25*x^2 - 17*x + 2, x^4 - 10*x^3 + 25*x^2 - 17*x + 3, x^4 - 10*x^3 + 25*x^2 - 16*x + 1, x^4 - 10*x^3 + 25*x^2 - 16*x + 2, x^4 - 10*x^3 + 25*x^2 - 15*x + 1, x^4 - 10*x^3 + 25*x^2 - 15*x + 2, x^4 - 10*x^3 + 25*x^2 - 14*x + 1, x^4 - 10*x^3 + 25*x^2 - 14*x + 2, x^4 - 10*x^3 + 25*x^2 - 13*x + 1, x^4 - 10*x^3 + 25*x^2 - 12*x + 1, x^4 - 10*x^3 + 25*x^2 - 11*x + 1, x^4 - 10*x^3 + 25*x^2 - 10*x + 1, x^4 - 10*x^3 + 26*x^2 - 23*x + 5, x^4 - 10*x^3 + 26*x^2 - 21*x + 3, x^4 - 10*x^3 + 26*x^2 - 21*x + 5, x^4 - 10*x^3 + 26*x^2 - 20*x + 1, x^4 - 10*x^3 + 26*x^2 - 20*x + 2, x^4 - 10*x^3 + 26*x^2 - 20*x + 4, x^4 - 10*x^3 + 26*x^2 - 19*x + 1, x^4 - 10*x^3 + 26*x^2 - 19*x + 3, x^4 - 10*x^3 + 26*x^2 - 18*x + 2, x^4 - 10*x^3 + 26*x^2 - 18*x + 3, x^4 - 10*x^3 + 26*x^2 - 17*x + 1, x^4 - 10*x^3 + 26*x^2 - 17*x + 2, x^4 - 10*x^3 + 26*x^2 - 17*x + 3, x^4 - 10*x^3 + 26*x^2 - 16*x + 1, x^4 - 10*x^3 + 26*x^2 - 16*x + 2, x^4 - 10*x^3 + 26*x^2 - 15*x + 1, x^4 - 10*x^3 + 26*x^2 - 15*x + 2, x^4 - 10*x^3 + 26*x^2 - 14*x + 1, x^4 - 10*x^3 + 26*x^2 - 14*x + 2, x^4 - 10*x^3 + 26*x^2 - 13*x + 1, x^4 - 10*x^3 + 26*x^2 - 12*x + 1, x^4 - 10*x^3 + 26*x^2 - 11*x + 1, x^4 - 10*x^3 + 27*x^2 - 26*x + 7, x^4 - 10*x^3 + 27*x^2 - 24*x + 5, x^4 - 10*x^3 + 27*x^2 - 23*x + 3, x^4 - 10*x^3 + 27*x^2 - 23*x + 4, x^4 - 10*x^3 + 27*x^2 - 23*x + 6, x^4 - 10*x^3 + 27*x^2 - 22*x + 1, x^4 - 10*x^3 + 27*x^2 - 22*x + 2, x^4 - 10*x^3 + 27*x^2 - 22*x + 3, x^4 - 10*x^3 + 27*x^2 - 21*x + 1, x^4 - 10*x^3 + 27*x^2 - 21*x + 2, x^4 - 10*x^3 + 27*x^2 - 21*x + 4, x^4 - 10*x^3 + 27*x^2 - 20*x + 1, x^4 - 10*x^3 + 27*x^2 - 20*x + 3, x^4 - 10*x^3 + 27*x^2 - 20*x + 4, x^4 - 10*x^3 + 27*x^2 - 19*x + 2, x^4 - 10*x^3 + 27*x^2 - 18*x + 1, x^4 - 10*x^3 + 27*x^2 - 18*x + 2, x^4 - 10*x^3 + 27*x^2 - 18*x + 3, x^4 - 10*x^3 + 27*x^2 - 17*x + 1, x^4 - 10*x^3 + 27*x^2 - 17*x + 2, x^4 - 10*x^3 + 27*x^2 - 17*x + 3, x^4 - 10*x^3 + 27*x^2 - 16*x + 1, x^4 - 10*x^3 + 27*x^2 - 15*x + 1, x^4 - 10*x^3 + 27*x^2 - 15*x + 2, x^4 - 10*x^3 + 27*x^2 - 14*x + 1, x^4 - 10*x^3 + 27*x^2 - 13*x + 1, x^4 - 10*x^3 + 27*x^2 - 12*x + 1, x^4 - 10*x^3 + 27*x^2 - 11*x + 1, x^4 - 10*x^3 + 28*x^2 - 27*x + 7, x^4 - 10*x^3 + 28*x^2 - 26*x + 5, x^4 - 10*x^3 + 28*x^2 - 26*x + 6, x^4 - 10*x^3 + 28*x^2 - 25*x + 3, x^4 - 10*x^3 + 28*x^2 - 25*x + 4, x^4 - 10*x^3 + 28*x^2 - 25*x + 5, x^4 - 10*x^3 + 28*x^2 - 24*x + 1, x^4 - 10*x^3 + 28*x^2 - 24*x + 2, x^4 - 10*x^3 + 28*x^2 - 24*x + 3, x^4 - 10*x^3 + 28*x^2 - 24*x + 4, x^4 - 10*x^3 + 28*x^2 - 24*x + 6, x^4 - 10*x^3 + 28*x^2 - 23*x + 1, x^4 - 10*x^3 + 28*x^2 - 23*x + 2, x^4 - 10*x^3 + 28*x^2 - 23*x + 3, x^4 - 10*x^3 + 28*x^2 - 23*x + 5, x^4 - 10*x^3 + 28*x^2 - 22*x + 1, x^4 - 10*x^3 + 28*x^2 - 22*x + 2, x^4 - 10*x^3 + 28*x^2 - 22*x + 4, x^4 - 10*x^3 + 28*x^2 - 22*x + 5, x^4 - 10*x^3 + 28*x^2 - 21*x + 1, x^4 - 10*x^3 + 28*x^2 - 21*x + 3, x^4 - 10*x^3 + 28*x^2 - 21*x + 4, x^4 - 10*x^3 + 28*x^2 - 20*x + 2, x^4 - 10*x^3 + 28*x^2 - 20*x + 3, x^4 - 10*x^3 + 28*x^2 - 19*x + 1, x^4 - 10*x^3 + 28*x^2 - 19*x + 2, x^4 - 10*x^3 + 28*x^2 - 19*x + 3, x^4 - 10*x^3 + 28*x^2 - 18*x + 1, x^4 - 10*x^3 + 28*x^2 - 18*x + 2, x^4 - 10*x^3 + 28*x^2 - 17*x + 1, x^4 - 10*x^3 + 28*x^2 - 17*x + 2, x^4 - 10*x^3 + 28*x^2 - 16*x + 1, x^4 - 10*x^3 + 28*x^2 - 16*x + 2, x^4 - 10*x^3 + 28*x^2 - 15*x + 1, x^4 - 10*x^3 + 29*x^2 - 30*x + 9, x^4 - 10*x^3 + 29*x^2 - 29*x + 7, x^4 - 10*x^3 + 29*x^2 - 29*x + 8, x^4 - 10*x^3 + 29*x^2 - 28*x + 5, x^4 - 10*x^3 + 29*x^2 - 28*x + 6, x^4 - 10*x^3 + 29*x^2 - 27*x + 3, x^4 - 10*x^3 + 29*x^2 - 27*x + 4, x^4 - 10*x^3 + 29*x^2 - 27*x + 5, x^4 - 10*x^3 + 29*x^2 - 27*x + 6, x^4 - 10*x^3 + 29*x^2 - 26*x + 1, x^4 - 10*x^3 + 29*x^2 - 26*x + 2, x^4 - 10*x^3 + 29*x^2 - 26*x + 3, x^4 - 10*x^3 + 29*x^2 - 26*x + 4, x^4 - 10*x^3 + 29*x^2 - 26*x + 5, x^4 - 10*x^3 + 29*x^2 - 26*x + 7, x^4 - 10*x^3 + 29*x^2 - 25*x + 1, x^4 - 10*x^3 + 29*x^2 - 25*x + 2, x^4 - 10*x^3 + 29*x^2 - 25*x + 4, x^4 - 10*x^3 + 29*x^2 - 25*x + 6, x^4 - 10*x^3 + 29*x^2 - 24*x + 1, x^4 - 10*x^3 + 29*x^2 - 24*x + 2, x^4 - 10*x^3 + 29*x^2 - 24*x + 3, x^4 - 10*x^3 + 29*x^2 - 24*x + 5, x^4 - 10*x^3 + 29*x^2 - 23*x + 1, x^4 - 10*x^3 + 29*x^2 - 23*x + 2, x^4 - 10*x^3 + 29*x^2 - 23*x + 4, x^4 - 10*x^3 + 29*x^2 - 23*x + 5, x^4 - 10*x^3 + 29*x^2 - 22*x + 1, x^4 - 10*x^3 + 29*x^2 - 22*x + 3, x^4 - 10*x^3 + 29*x^2 - 21*x + 2, x^4 - 10*x^3 + 29*x^2 - 21*x + 3, x^4 - 10*x^3 + 29*x^2 - 20*x + 1, x^4 - 10*x^3 + 29*x^2 - 20*x + 2, x^4 - 10*x^3 + 30*x^2 - 33*x + 11, x^4 - 10*x^3 + 30*x^2 - 32*x + 9, x^4 - 10*x^3 + 30*x^2 - 32*x + 10, x^4 - 10*x^3 + 30*x^2 - 31*x + 7, x^4 - 10*x^3 + 30*x^2 - 31*x + 9, x^4 - 10*x^3 + 30*x^2 - 30*x + 5, x^4 - 10*x^3 + 30*x^2 - 30*x + 6, x^4 - 10*x^3 + 30*x^2 - 30*x + 7, x^4 - 10*x^3 + 30*x^2 - 30*x + 8, x^4 - 10*x^3 + 30*x^2 - 29*x + 3, x^4 - 10*x^3 + 30*x^2 - 29*x + 4, x^4 - 10*x^3 + 30*x^2 - 29*x + 5, x^4 - 10*x^3 + 30*x^2 - 29*x + 7, x^4 - 10*x^3 + 30*x^2 - 28*x + 1, x^4 - 10*x^3 + 30*x^2 - 28*x + 2, x^4 - 10*x^3 + 30*x^2 - 28*x + 4, x^4 - 10*x^3 + 30*x^2 - 28*x + 5, x^4 - 10*x^3 + 30*x^2 - 28*x + 6, x^4 - 10*x^3 + 30*x^2 - 27*x + 1, x^4 - 10*x^3 + 30*x^2 - 27*x + 2, x^4 - 10*x^3 + 30*x^2 - 27*x + 3, x^4 - 10*x^3 + 30*x^2 - 27*x + 4, x^4 - 10*x^3 + 30*x^2 - 27*x + 5, x^4 - 10*x^3 + 30*x^2 - 27*x + 7, x^4 - 10*x^3 + 30*x^2 - 26*x + 1, x^4 - 10*x^3 + 30*x^2 - 26*x + 2, x^4 - 10*x^3 + 30*x^2 - 26*x + 3, x^4 - 10*x^3 + 30*x^2 - 26*x + 4, x^4 - 10*x^3 + 30*x^2 - 26*x + 6, x^4 - 10*x^3 + 30*x^2 - 25*x + 1, x^4 - 10*x^3 + 30*x^2 - 25*x + 2, x^4 - 10*x^3 + 30*x^2 - 25*x + 3, x^4 - 10*x^3 + 30*x^2 - 25*x + 5, x^4 - 10*x^3 + 30*x^2 - 24*x + 1, x^4 - 10*x^3 + 31*x^2 - 36*x + 13, x^4 - 10*x^3 + 31*x^2 - 35*x + 11, x^4 - 10*x^3 + 31*x^2 - 35*x + 12, x^4 - 10*x^3 + 31*x^2 - 34*x + 10, x^4 - 10*x^3 + 31*x^2 - 34*x + 11, x^4 - 10*x^3 + 31*x^2 - 33*x + 7, x^4 - 10*x^3 + 31*x^2 - 33*x + 8, x^4 - 10*x^3 + 31*x^2 - 33*x + 10, x^4 - 10*x^3 + 31*x^2 - 32*x + 5, x^4 - 10*x^3 + 31*x^2 - 32*x + 7, x^4 - 10*x^3 + 31*x^2 - 32*x + 8, x^4 - 10*x^3 + 31*x^2 - 32*x + 9, x^4 - 10*x^3 + 31*x^2 - 31*x + 1, x^4 - 10*x^3 + 31*x^2 - 31*x + 4, x^4 - 10*x^3 + 31*x^2 - 31*x + 6, x^4 - 10*x^3 + 31*x^2 - 31*x + 7, x^4 - 10*x^3 + 31*x^2 - 31*x + 8, x^4 - 10*x^3 + 31*x^2 - 30*x + 1, x^4 - 10*x^3 + 31*x^2 - 30*x + 2, x^4 - 10*x^3 + 31*x^2 - 30*x + 3, x^4 - 10*x^3 + 31*x^2 - 30*x + 4, x^4 - 10*x^3 + 31*x^2 - 30*x + 7, x^4 - 10*x^3 + 31*x^2 - 29*x + 1, x^4 - 10*x^3 + 31*x^2 - 29*x + 2, x^4 - 10*x^3 + 31*x^2 - 29*x + 3, x^4 - 10*x^3 + 32*x^2 - 39*x + 15, x^4 - 10*x^3 + 32*x^2 - 38*x + 13, x^4 - 10*x^3 + 32*x^2 - 38*x + 14, x^4 - 10*x^3 + 32*x^2 - 37*x + 11, x^4 - 10*x^3 + 32*x^2 - 37*x + 13, x^4 - 10*x^3 + 32*x^2 - 36*x + 10, x^4 - 10*x^3 + 32*x^2 - 36*x + 11, x^4 - 10*x^3 + 32*x^2 - 35*x + 5, x^4 - 10*x^3 + 32*x^2 - 35*x + 7, x^4 - 10*x^3 + 32*x^2 - 35*x + 8, x^4 - 10*x^3 + 32*x^2 - 35*x + 9, x^4 - 10*x^3 + 32*x^2 - 35*x + 11, x^4 - 10*x^3 + 32*x^2 - 34*x + 5, x^4 - 10*x^3 + 32*x^2 - 34*x + 6, x^4 - 10*x^3 + 32*x^2 - 33*x + 1, x^4 - 10*x^3 + 32*x^2 - 33*x + 3, x^4 - 10*x^3 + 33*x^2 - 42*x + 17, x^4 - 10*x^3 + 33*x^2 - 41*x + 16, x^4 - 10*x^3 + 33*x^2 - 40*x + 13, x^4 - 10*x^3 + 33*x^2 - 39*x + 11, x^4 - 10*x^3 + 33*x^2 - 38*x + 7, x^4 - 10*x^3 + 34*x^2 - 45*x + 19, x^5 - 11*x^4 + 29*x^3 - 26*x^2 + 9*x - 1, x^5 - 11*x^4 + 31*x^3 - 32*x^2 + 11*x - 1, x^5 - 11*x^4 + 31*x^3 - 31*x^2 + 10*x - 1, x^5 - 11*x^4 + 31*x^3 - 29*x^2 + 10*x - 1, x^5 - 11*x^4 + 32*x^3 - 34*x^2 + 12*x - 1, x^5 - 11*x^4 + 32*x^3 - 33*x^2 + 11*x - 1, x^5 - 11*x^4 + 32*x^3 - 31*x^2 + 11*x - 1, x^5 - 11*x^4 + 33*x^3 - 37*x^2 + 14*x - 1, x^5 - 11*x^4 + 33*x^3 - 36*x^2 + 13*x - 1, x^5 - 11*x^4 + 33*x^3 - 35*x^2 + 11*x - 1, x^5 - 11*x^4 + 33*x^3 - 35*x^2 + 12*x - 1, x^5 - 11*x^4 + 33*x^3 - 34*x^2 + 11*x - 1, x^5 - 11*x^4 + 33*x^3 - 32*x^2 + 11*x - 1, x^5 - 11*x^4 + 33*x^3 - 31*x^2 + 10*x - 1, x^5 - 11*x^4 + 33*x^3 - 30*x^2 + 10*x - 1, x^5 - 11*x^4 + 34*x^3 - 39*x^2 + 15*x - 1, x^5 - 11*x^4 + 34*x^3 - 39*x^2 + 16*x - 2, x^5 - 11*x^4 + 34*x^3 - 38*x^2 + 13*x - 1, x^5 - 11*x^4 + 34*x^3 - 38*x^2 + 14*x - 1, x^5 - 11*x^4 + 34*x^3 - 37*x^2 + 12*x - 1, x^5 - 11*x^4 + 34*x^3 - 37*x^2 + 13*x - 1, x^5 - 11*x^4 + 34*x^3 - 36*x^2 + 11*x - 1, x^5 - 11*x^4 + 34*x^3 - 35*x^2 + 11*x - 1, x^5 - 11*x^4 + 34*x^3 - 34*x^2 + 12*x - 1, x^5 - 11*x^4 + 34*x^3 - 33*x^2 + 11*x - 1, x^5 - 11*x^4 + 34*x^3 - 31*x^2 + 10*x - 1, x^5 - 11*x^4 + 35*x^3 - 43*x^2 + 20*x - 3, x^5 - 11*x^4 + 35*x^3 - 42*x^2 + 17*x - 1, x^5 - 11*x^4 + 35*x^3 - 42*x^2 + 18*x - 2, x^5 - 11*x^4 + 35*x^3 - 41*x^2 + 15*x - 1, x^5 - 11*x^4 + 35*x^3 - 41*x^2 + 16*x - 1, x^5 - 11*x^4 + 35*x^3 - 41*x^2 + 17*x - 2, x^5 - 11*x^4 + 35*x^3 - 40*x^2 + 13*x - 1, x^5 - 11*x^4 + 35*x^3 - 40*x^2 + 14*x - 1, x^5 - 11*x^4 + 35*x^3 - 40*x^2 + 15*x - 1, x^5 - 11*x^4 + 35*x^3 - 39*x^2 + 12*x - 1, x^5 - 11*x^4 + 35*x^3 - 39*x^2 + 14*x - 1, x^5 - 11*x^4 + 35*x^3 - 38*x^2 + 12*x - 1, x^5 - 11*x^4 + 35*x^3 - 38*x^2 + 13*x - 1, x^5 - 11*x^4 + 35*x^3 - 37*x^2 + 12*x - 1, x^5 - 11*x^4 + 35*x^3 - 37*x^2 + 15*x - 2, x^5 - 11*x^4 + 35*x^3 - 36*x^2 + 11*x - 1, x^5 - 11*x^4 + 35*x^3 - 36*x^2 + 13*x - 1, x^5 - 11*x^4 + 35*x^3 - 35*x^2 + 12*x - 1, x^5 - 11*x^4 + 35*x^3 - 34*x^2 + 11*x - 1, x^5 - 11*x^4 + 35*x^3 - 33*x^2 + 11*x - 1, x^5 - 11*x^4 + 35*x^3 - 31*x^2 + 10*x - 1, x^5 - 11*x^4 + 36*x^3 - 46*x^2 + 22*x - 3, x^5 - 11*x^4 + 36*x^3 - 45*x^2 + 19*x - 1, x^5 - 11*x^4 + 36*x^3 - 45*x^2 + 20*x - 2, x^5 - 11*x^4 + 36*x^3 - 45*x^2 + 21*x - 3, x^5 - 11*x^4 + 36*x^3 - 44*x^2 + 17*x - 1, x^5 - 11*x^4 + 36*x^3 - 44*x^2 + 18*x - 2, x^5 - 11*x^4 + 36*x^3 - 44*x^2 + 18*x - 1, x^5 - 11*x^4 + 36*x^3 - 44*x^2 + 19*x - 2, x^5 - 11*x^4 + 36*x^3 - 43*x^2 + 15*x - 1, x^5 - 11*x^4 + 36*x^3 - 43*x^2 + 16*x - 1, x^5 - 11*x^4 + 36*x^3 - 43*x^2 + 17*x - 1, x^5 - 11*x^4 + 36*x^3 - 43*x^2 + 18*x - 2, x^5 - 11*x^4 + 36*x^3 - 42*x^2 + 13*x - 1, x^5 - 11*x^4 + 36*x^3 - 42*x^2 + 15*x - 1, x^5 - 11*x^4 + 36*x^3 - 42*x^2 + 16*x - 1, x^5 - 11*x^4 + 36*x^3 - 42*x^2 + 17*x - 2, x^5 - 11*x^4 + 36*x^3 - 41*x^2 + 12*x - 1, x^5 - 11*x^4 + 36*x^3 - 41*x^2 + 13*x - 1, x^5 - 11*x^4 + 36*x^3 - 41*x^2 + 14*x - 1, x^5 - 11*x^4 + 36*x^3 - 41*x^2 + 15*x - 1, x^5 - 11*x^4 + 36*x^3 - 40*x^2 + 12*x - 1, x^5 - 11*x^4 + 36*x^3 - 40*x^2 + 13*x - 1, x^5 - 11*x^4 + 36*x^3 - 40*x^2 + 14*x - 1, x^5 - 11*x^4 + 36*x^3 - 39*x^2 + 12*x - 1, x^5 - 11*x^4 + 36*x^3 - 39*x^2 + 13*x - 1, x^5 - 11*x^4 + 36*x^3 - 38*x^2 + 12*x - 1, x^5 - 11*x^4 + 36*x^3 - 37*x^2 + 13*x - 1, x^5 - 11*x^4 + 36*x^3 - 36*x^2 + 12*x - 1, x^5 - 11*x^4 + 36*x^3 - 35*x^2 + 11*x - 1, x^5 - 11*x^4 + 36*x^3 - 34*x^2 + 11*x - 1, x^5 - 11*x^4 + 37*x^3 - 49*x^2 + 24*x - 3, x^5 - 11*x^4 + 37*x^3 - 49*x^2 + 25*x - 4, x^5 - 11*x^4 + 37*x^3 - 48*x^2 + 21*x - 1, x^5 - 11*x^4 + 37*x^3 - 48*x^2 + 22*x - 3, x^5 - 11*x^4 + 37*x^3 - 48*x^2 + 22*x - 2, x^5 - 11*x^4 + 37*x^3 - 48*x^2 + 23*x - 3, x^5 - 11*x^4 + 37*x^3 - 47*x^2 + 19*x - 1, x^5 - 11*x^4 + 37*x^3 - 47*x^2 + 20*x - 2, x^5 - 11*x^4 + 37*x^3 - 47*x^2 + 20*x - 1, x^5 - 11*x^4 + 37*x^3 - 47*x^2 + 21*x - 2, x^5 - 11*x^4 + 37*x^3 - 47*x^2 + 22*x - 3, x^5 - 11*x^4 + 37*x^3 - 46*x^2 + 17*x - 1, x^5 - 11*x^4 + 37*x^3 - 46*x^2 + 18*x - 1, x^5 - 11*x^4 + 37*x^3 - 46*x^2 + 19*x - 2, x^5 - 11*x^4 + 37*x^3 - 46*x^2 + 19*x - 1, x^5 - 11*x^4 + 37*x^3 - 46*x^2 + 20*x - 2, x^5 - 11*x^4 + 37*x^3 - 46*x^2 + 21*x - 3, x^5 - 11*x^4 + 37*x^3 - 45*x^2 + 16*x - 1, x^5 - 11*x^4 + 37*x^3 - 45*x^2 + 17*x - 1, x^5 - 11*x^4 + 37*x^3 - 45*x^2 + 18*x - 2, x^5 - 11*x^4 + 37*x^3 - 45*x^2 + 18*x - 1, x^5 - 11*x^4 + 37*x^3 - 45*x^2 + 19*x - 2, x^5 - 11*x^4 + 37*x^3 - 44*x^2 + 13*x - 1, x^5 - 11*x^4 + 37*x^3 - 44*x^2 + 14*x - 1, x^5 - 11*x^4 + 37*x^3 - 44*x^2 + 15*x - 1, x^5 - 11*x^4 + 37*x^3 - 44*x^2 + 16*x - 1, x^5 - 11*x^4 + 37*x^3 - 44*x^2 + 17*x - 2, x^5 - 11*x^4 + 37*x^3 - 44*x^2 + 17*x - 1, x^5 - 11*x^4 + 37*x^3 - 44*x^2 + 18*x - 2, x^5 - 11*x^4 + 37*x^3 - 43*x^2 + 13*x - 1, x^5 - 11*x^4 + 37*x^3 - 43*x^2 + 14*x - 1, x^5 - 11*x^4 + 37*x^3 - 43*x^2 + 15*x - 1, x^5 - 11*x^4 + 37*x^3 - 43*x^2 + 16*x - 1, x^5 - 11*x^4 + 37*x^3 - 43*x^2 + 17*x - 2, x^5 - 11*x^4 + 37*x^3 - 42*x^2 + 13*x - 1, x^5 - 11*x^4 + 37*x^3 - 42*x^2 + 14*x - 1, x^5 - 11*x^4 + 37*x^3 - 42*x^2 + 15*x - 1, x^5 - 11*x^4 + 37*x^3 - 41*x^2 + 12*x - 1, x^5 - 11*x^4 + 37*x^3 - 41*x^2 + 13*x - 1, x^5 - 11*x^4 + 37*x^3 - 41*x^2 + 14*x - 1, x^5 - 11*x^4 + 37*x^3 - 40*x^2 + 13*x - 1, x^5 - 11*x^4 + 37*x^3 - 40*x^2 + 16*x - 2, x^5 - 11*x^4 + 37*x^3 - 39*x^2 + 12*x - 1, x^5 - 11*x^4 + 37*x^3 - 39*x^2 + 14*x - 1, x^5 - 11*x^4 + 37*x^3 - 38*x^2 + 13*x - 1, x^5 - 11*x^4 + 38*x^3 - 53*x^2 + 29*x - 5, x^5 - 11*x^4 + 38*x^3 - 52*x^2 + 26*x - 3, x^5 - 11*x^4 + 38*x^3 - 52*x^2 + 27*x - 4, x^5 - 11*x^4 + 38*x^3 - 51*x^2 + 23*x - 1, x^5 - 11*x^4 + 38*x^3 - 51*x^2 + 24*x - 3, x^5 - 11*x^4 + 38*x^3 - 51*x^2 + 24*x - 2, x^5 - 11*x^4 + 38*x^3 - 51*x^2 + 25*x - 3, x^5 - 11*x^4 + 38*x^3 - 51*x^2 + 26*x - 4, x^5 - 11*x^4 + 38*x^3 - 50*x^2 + 21*x - 1, x^5 - 11*x^4 + 38*x^3 - 50*x^2 + 22*x - 2, x^5 - 11*x^4 + 38*x^3 - 50*x^2 + 22*x - 1, x^5 - 11*x^4 + 38*x^3 - 50*x^2 + 23*x - 3, x^5 - 11*x^4 + 38*x^3 - 50*x^2 + 23*x - 2, x^5 - 11*x^4 + 38*x^3 - 50*x^2 + 24*x - 3, x^5 - 11*x^4 + 38*x^3 - 50*x^2 + 25*x - 4, x^5 - 11*x^4 + 38*x^3 - 49*x^2 + 18*x - 1, x^5 - 11*x^4 + 38*x^3 - 49*x^2 + 19*x - 1, x^5 - 11*x^4 + 38*x^3 - 49*x^2 + 20*x - 2, x^5 - 11*x^4 + 38*x^3 - 49*x^2 + 20*x - 1, x^5 - 11*x^4 + 38*x^3 - 49*x^2 + 21*x - 2, x^5 - 11*x^4 + 38*x^3 - 49*x^2 + 21*x - 1, x^5 - 11*x^4 + 38*x^3 - 49*x^2 + 22*x - 2, x^5 - 11*x^4 + 38*x^3 - 49*x^2 + 23*x - 3, x^5 - 11*x^4 + 38*x^3 - 48*x^2 + 17*x - 1, x^5 - 11*x^4 + 38*x^3 - 48*x^2 + 18*x - 2, x^5 - 11*x^4 + 38*x^3 - 48*x^2 + 18*x - 1, x^5 - 11*x^4 + 38*x^3 - 48*x^2 + 19*x - 2, x^5 - 11*x^4 + 38*x^3 - 48*x^2 + 19*x - 1, x^5 - 11*x^4 + 38*x^3 - 48*x^2 + 20*x - 2, x^5 - 11*x^4 + 38*x^3 - 48*x^2 + 20*x - 1, x^5 - 11*x^4 + 38*x^3 - 48*x^2 + 21*x - 2, x^5 - 11*x^4 + 38*x^3 - 48*x^2 + 22*x - 3, x^5 - 11*x^4 + 38*x^3 - 47*x^2 + 14*x - 1, x^5 - 11*x^4 + 38*x^3 - 47*x^2 + 15*x - 1, x^5 - 11*x^4 + 38*x^3 - 47*x^2 + 16*x - 1, x^5 - 11*x^4 + 38*x^3 - 47*x^2 + 17*x - 1, x^5 - 11*x^4 + 38*x^3 - 47*x^2 + 18*x - 1, x^5 - 11*x^4 + 38*x^3 - 47*x^2 + 19*x - 2, x^5 - 11*x^4 + 38*x^3 - 47*x^2 + 19*x - 1, x^5 - 11*x^4 + 38*x^3 - 47*x^2 + 21*x - 3, x^5 - 11*x^4 + 38*x^3 - 46*x^2 + 13*x - 1, x^5 - 11*x^4 + 38*x^3 - 46*x^2 + 14*x - 1, x^5 - 11*x^4 + 38*x^3 - 46*x^2 + 15*x - 1, x^5 - 11*x^4 + 38*x^3 - 46*x^2 + 16*x - 1, x^5 - 11*x^4 + 38*x^3 - 46*x^2 + 17*x - 1, x^5 - 11*x^4 + 38*x^3 - 46*x^2 + 18*x - 2, x^5 - 11*x^4 + 38*x^3 - 46*x^2 + 18*x - 1, x^5 - 11*x^4 + 38*x^3 - 46*x^2 + 19*x - 2, x^5 - 11*x^4 + 38*x^3 - 45*x^2 + 13*x - 1, x^5 - 11*x^4 + 38*x^3 - 45*x^2 + 14*x - 1, x^5 - 11*x^4 + 38*x^3 - 45*x^2 + 15*x - 1, x^5 - 11*x^4 + 38*x^3 - 45*x^2 + 16*x - 1, x^5 - 11*x^4 + 38*x^3 - 45*x^2 + 17*x - 1, x^5 - 11*x^4 + 38*x^3 - 45*x^2 + 18*x - 2, x^5 - 11*x^4 + 38*x^3 - 44*x^2 + 14*x - 1, x^5 - 11*x^4 + 38*x^3 - 44*x^2 + 15*x - 1, x^5 - 11*x^4 + 38*x^3 - 44*x^2 + 16*x - 1, x^5 - 11*x^4 + 38*x^3 - 44*x^2 + 17*x - 2, x^5 - 11*x^4 + 38*x^3 - 43*x^2 + 13*x - 1, x^5 - 11*x^4 + 38*x^3 - 43*x^2 + 14*x - 1, x^5 - 11*x^4 + 38*x^3 - 43*x^2 + 15*x - 1, x^5 - 11*x^4 + 39*x^3 - 56*x^2 + 29*x - 1, x^5 - 11*x^4 + 39*x^3 - 56*x^2 + 31*x - 5, x^5 - 11*x^4 + 39*x^3 - 55*x^2 + 28*x - 3, x^5 - 11*x^4 + 39*x^3 - 55*x^2 + 29*x - 4, x^5 - 11*x^4 + 39*x^3 - 55*x^2 + 30*x - 5, x^5 - 11*x^4 + 39*x^3 - 54*x^2 + 25*x - 1, x^5 - 11*x^4 + 39*x^3 - 54*x^2 + 26*x - 3, x^5 - 11*x^4 + 39*x^3 - 54*x^2 + 26*x - 2, x^5 - 11*x^4 + 39*x^3 - 54*x^2 + 27*x - 4, x^5 - 11*x^4 + 39*x^3 - 54*x^2 + 27*x - 3, x^5 - 11*x^4 + 39*x^3 - 54*x^2 + 28*x - 4, x^5 - 11*x^4 + 39*x^3 - 54*x^2 + 29*x - 5, x^5 - 11*x^4 + 39*x^3 - 53*x^2 + 22*x - 1, x^5 - 11*x^4 + 39*x^3 - 53*x^2 + 23*x - 1, x^5 - 11*x^4 + 39*x^3 - 53*x^2 + 24*x - 3, x^5 - 11*x^4 + 39*x^3 - 53*x^2 + 24*x - 2, x^5 - 11*x^4 + 39*x^3 - 53*x^2 + 24*x - 1, x^5 - 11*x^4 + 39*x^3 - 53*x^2 + 25*x - 2, x^5 - 11*x^4 + 39*x^3 - 53*x^2 + 26*x - 4, x^5 - 11*x^4 + 39*x^3 - 53*x^2 + 26*x - 3, x^5 - 11*x^4 + 39*x^3 - 53*x^2 + 27*x - 4, x^5 - 11*x^4 + 39*x^3 - 52*x^2 + 20*x - 1, x^5 - 11*x^4 + 39*x^3 - 52*x^2 + 21*x - 1, x^5 - 11*x^4 + 39*x^3 - 52*x^2 + 22*x - 2, x^5 - 11*x^4 + 39*x^3 - 52*x^2 + 22*x - 1, x^5 - 11*x^4 + 39*x^3 - 52*x^2 + 23*x - 3, x^5 - 11*x^4 + 39*x^3 - 52*x^2 + 23*x - 2, x^5 - 11*x^4 + 39*x^3 - 52*x^2 + 23*x - 1, x^5 - 11*x^4 + 39*x^3 - 52*x^2 + 24*x - 2, x^5 - 11*x^4 + 39*x^3 - 52*x^2 + 25*x - 3, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 18*x - 1, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 19*x - 1, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 20*x - 2, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 20*x - 1, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 21*x - 2, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 21*x - 1, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 22*x - 1, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 23*x - 3, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 23*x - 2, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 24*x - 3, x^5 - 11*x^4 + 39*x^3 - 51*x^2 + 25*x - 4, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 15*x - 1, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 16*x - 1, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 17*x - 1, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 18*x - 1, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 19*x - 2, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 19*x - 1, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 20*x - 2, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 20*x - 1, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 21*x - 2, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 21*x - 1, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 22*x - 2, x^5 - 11*x^4 + 39*x^3 - 50*x^2 + 23*x - 3, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 14*x - 1, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 15*x - 1, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 16*x - 1, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 17*x - 1, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 18*x - 1, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 19*x - 2, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 19*x - 1, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 20*x - 2, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 20*x - 1, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 21*x - 2, x^5 - 11*x^4 + 39*x^3 - 49*x^2 + 22*x - 3, x^5 - 11*x^4 + 39*x^3 - 48*x^2 + 13*x - 1, x^5 - 11*x^4 + 39*x^3 - 48*x^2 + 15*x - 1, x^5 - 11*x^4 + 39*x^3 - 48*x^2 + 16*x - 1, x^5 - 11*x^4 + 39*x^3 - 48*x^2 + 17*x - 1, x^5 - 11*x^4 + 39*x^3 - 48*x^2 + 18*x - 1, x^5 - 11*x^4 + 39*x^3 - 47*x^2 + 14*x - 1, x^5 - 11*x^4 + 40*x^3 - 60*x^2 + 34*x - 3, x^5 - 11*x^4 + 40*x^3 - 59*x^2 + 31*x - 1, x^5 - 11*x^4 + 40*x^3 - 59*x^2 + 33*x - 5, x^5 - 11*x^4 + 40*x^3 - 59*x^2 + 34*x - 6, x^5 - 11*x^4 + 40*x^3 - 59*x^2 + 35*x - 7, x^5 - 11*x^4 + 40*x^3 - 58*x^2 + 29*x - 3, x^5 - 11*x^4 + 40*x^3 - 58*x^2 + 30*x - 3, x^5 - 11*x^4 + 40*x^3 - 58*x^2 + 31*x - 5, x^5 - 11*x^4 + 40*x^3 - 58*x^2 + 31*x - 4, x^5 - 11*x^4 + 40*x^3 - 58*x^2 + 32*x - 5, x^5 - 11*x^4 + 40*x^3 - 58*x^2 + 33*x - 6, x^5 - 11*x^4 + 40*x^3 - 57*x^2 + 26*x - 1, x^5 - 11*x^4 + 40*x^3 - 57*x^2 + 27*x - 3, x^5 - 11*x^4 + 40*x^3 - 57*x^2 + 27*x - 1, x^5 - 11*x^4 + 40*x^3 - 57*x^2 + 28*x - 2, x^5 - 11*x^4 + 40*x^3 - 57*x^2 + 29*x - 4, x^5 - 11*x^4 + 40*x^3 - 57*x^2 + 29*x - 3, x^5 - 11*x^4 + 40*x^3 - 57*x^2 + 30*x - 5, x^5 - 11*x^4 + 40*x^3 - 57*x^2 + 31*x - 5, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 24*x - 2, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 24*x - 1, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 25*x - 1, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 26*x - 3, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 26*x - 2, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 26*x - 1, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 27*x - 4, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 27*x - 3, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 27*x - 2, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 28*x - 3, x^5 - 11*x^4 + 40*x^3 - 56*x^2 + 29*x - 4, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 21*x - 1, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 22*x - 2, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 22*x - 1, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 23*x - 1, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 24*x - 3, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 24*x - 1, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 25*x - 3, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 25*x - 2, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 25*x - 1, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 26*x - 3, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 26*x - 2, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 27*x - 3, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 28*x - 4, x^5 - 11*x^4 + 40*x^3 - 55*x^2 + 29*x - 5, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 19*x - 1, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 20*x - 2, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 20*x - 1, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 21*x - 1, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 22*x - 2, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 22*x - 1, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 23*x - 2, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 23*x - 1, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 24*x - 2, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 24*x - 1, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 25*x - 3, x^5 - 11*x^4 + 40*x^3 - 54*x^2 + 25*x - 2, x^5 - 11*x^4 + 40*x^3 - 53*x^2 + 16*x - 1, x^5 - 11*x^4 + 40*x^3 - 53*x^2 + 17*x - 1, x^5 - 11*x^4 + 40*x^3 - 53*x^2 + 18*x - 1, x^5 - 11*x^4 + 40*x^3 - 53*x^2 + 19*x - 1, x^5 - 11*x^4 + 40*x^3 - 53*x^2 + 20*x - 2, x^5 - 11*x^4 + 40*x^3 - 53*x^2 + 20*x - 1, x^5 - 11*x^4 + 40*x^3 - 53*x^2 + 21*x - 1, x^5 - 11*x^4 + 40*x^3 - 52*x^2 + 16*x - 1, x^5 - 11*x^4 + 41*x^3 - 64*x^2 + 39*x - 5, x^5 - 11*x^4 + 41*x^3 - 64*x^2 + 41*x - 9, x^5 - 11*x^4 + 41*x^3 - 63*x^2 + 36*x - 3, x^5 - 11*x^4 + 41*x^3 - 63*x^2 + 37*x - 4, x^5 - 11*x^4 + 41*x^3 - 63*x^2 + 38*x - 7, x^5 - 11*x^4 + 41*x^3 - 63*x^2 + 39*x - 8, x^5 - 11*x^4 + 41*x^3 - 62*x^2 + 33*x - 3, x^5 - 11*x^4 + 41*x^3 - 62*x^2 + 33*x - 1, x^5 - 11*x^4 + 41*x^3 - 62*x^2 + 34*x - 5, x^5 - 11*x^4 + 41*x^3 - 62*x^2 + 34*x - 2, x^5 - 11*x^4 + 41*x^3 - 62*x^2 + 35*x - 5, x^5 - 11*x^4 + 41*x^3 - 62*x^2 + 36*x - 6, x^5 - 11*x^4 + 41*x^3 - 62*x^2 + 37*x - 7, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 30*x - 2, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 30*x - 1, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 31*x - 4, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 32*x - 5, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 32*x - 3, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 32*x - 1, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 33*x - 5, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 33*x - 4, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 34*x - 5, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 35*x - 6, x^5 - 11*x^4 + 41*x^3 - 61*x^2 + 36*x - 7, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 27*x - 1, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 28*x - 2, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 28*x - 1, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 29*x - 4, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 29*x - 3, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 29*x - 1, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 30*x - 3, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 30*x - 2, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 31*x - 5, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 31*x - 4, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 31*x - 3, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 32*x - 4, x^5 - 11*x^4 + 41*x^3 - 60*x^2 + 33*x - 5, x^5 - 11*x^4 + 41*x^3 - 59*x^2 + 25*x - 2, x^5 - 11*x^4 + 41*x^3 - 59*x^2 + 25*x - 1, x^5 - 11*x^4 + 41*x^3 - 59*x^2 + 26*x - 3, x^5 - 11*x^4 + 41*x^3 - 59*x^2 + 26*x - 1, x^5 - 11*x^4 + 41*x^3 - 59*x^2 + 27*x - 3, x^5 - 11*x^4 + 41*x^3 - 59*x^2 + 27*x - 1, x^5 - 11*x^4 + 41*x^3 - 59*x^2 + 28*x - 3, x^5 - 11*x^4 + 41*x^3 - 59*x^2 + 28*x - 2, x^5 - 11*x^4 + 41*x^3 - 59*x^2 + 28*x - 1, x^5 - 11*x^4 + 41*x^3 - 58*x^2 + 22*x - 1, x^5 - 11*x^4 + 41*x^3 - 58*x^2 + 23*x - 1, x^5 - 11*x^4 + 41*x^3 - 58*x^2 + 24*x - 2, x^5 - 11*x^4 + 41*x^3 - 58*x^2 + 24*x - 1, x^5 - 11*x^4 + 41*x^3 - 57*x^2 + 20*x - 1, x^5 - 11*x^4 + 42*x^3 - 69*x^2 + 47*x - 9, x^5 - 11*x^4 + 42*x^3 - 68*x^2 + 44*x - 7, x^5 - 11*x^4 + 42*x^3 - 67*x^2 + 41*x - 7, x^5 - 11*x^4 + 42*x^3 - 67*x^2 + 41*x - 5, x^5 - 11*x^4 + 42*x^3 - 67*x^2 + 43*x - 9, x^5 - 11*x^4 + 42*x^3 - 66*x^2 + 36*x - 1, x^5 - 11*x^4 + 42*x^3 - 66*x^2 + 37*x - 4, x^5 - 11*x^4 + 42*x^3 - 66*x^2 + 37*x - 1, x^5 - 11*x^4 + 42*x^3 - 66*x^2 + 38*x - 5, x^5 - 11*x^4 + 42*x^3 - 66*x^2 + 38*x - 3, x^5 - 11*x^4 + 42*x^3 - 66*x^2 + 39*x - 7, x^5 - 11*x^4 + 42*x^3 - 66*x^2 + 39*x - 4, x^5 - 11*x^4 + 42*x^3 - 66*x^2 + 40*x - 7, x^5 - 11*x^4 + 42*x^3 - 66*x^2 + 41*x - 8, x^5 - 11*x^4 + 42*x^3 - 65*x^2 + 34*x - 2, x^5 - 11*x^4 + 42*x^3 - 65*x^2 + 35*x - 5, x^5 - 11*x^4 + 42*x^3 - 65*x^2 + 35*x - 4, x^5 - 11*x^4 + 42*x^3 - 65*x^2 + 35*x - 3, x^5 - 11*x^4 + 42*x^3 - 65*x^2 + 35*x - 1, x^5 - 11*x^4 + 42*x^3 - 65*x^2 + 36*x - 5, x^5 - 11*x^4 + 42*x^3 - 65*x^2 + 36*x - 2, x^5 - 11*x^4 + 42*x^3 - 65*x^2 + 37*x - 5, x^5 - 11*x^4 + 42*x^3 - 64*x^2 + 31*x - 2, x^5 - 11*x^4 + 42*x^3 - 64*x^2 + 31*x - 1, x^5 - 11*x^4 + 42*x^3 - 64*x^2 + 32*x - 2, x^5 - 11*x^4 + 42*x^3 - 64*x^2 + 32*x - 1, x^5 - 11*x^4 + 42*x^3 - 63*x^2 + 28*x - 1, x^5 - 11*x^4 + 43*x^3 - 73*x^2 + 52*x - 11, x^5 - 11*x^4 + 43*x^3 - 72*x^2 + 47*x - 7, x^5 - 11*x^4 + 43*x^3 - 72*x^2 + 49*x - 11, x^5 - 11*x^4 + 43*x^3 - 72*x^2 + 49*x - 9, x^5 - 11*x^4 + 43*x^3 - 71*x^2 + 42*x - 1, x^5 - 11*x^4 + 43*x^3 - 71*x^2 + 44*x - 5, x^5 - 11*x^4 + 43*x^3 - 71*x^2 + 45*x - 8, x^5 - 11*x^4 + 43*x^3 - 71*x^2 + 46*x - 9, x^5 - 11*x^4 + 43*x^3 - 70*x^2 + 40*x - 2, x^5 - 11*x^4 + 43*x^3 - 70*x^2 + 40*x - 1, x^5 - 11*x^4 + 43*x^3 - 70*x^2 + 41*x - 5, x^5 - 11*x^4 + 44*x^3 - 77*x^2 + 55*x - 11, x^6 - 12*x^5 + 44*x^4 - 67*x^3 + 44*x^2 - 12*x + 1, x^6 - 12*x^5 + 45*x^4 - 70*x^3 + 46*x^2 - 12*x + 1, x^6 - 12*x^5 + 45*x^4 - 67*x^3 + 42*x^2 - 11*x + 1, x^6 - 12*x^5 + 46*x^4 - 74*x^3 + 51*x^2 - 14*x + 1, x^6 - 12*x^5 + 46*x^4 - 72*x^3 + 47*x^2 - 12*x + 1, x^6 - 12*x^5 + 46*x^4 - 72*x^3 + 48*x^2 - 13*x + 1, x^6 - 12*x^5 + 46*x^4 - 71*x^3 + 46*x^2 - 12*x + 1, x^6 - 12*x^5 + 46*x^4 - 70*x^3 + 45*x^2 - 12*x + 1, x^6 - 12*x^5 + 46*x^4 - 68*x^3 + 42*x^2 - 11*x + 1, x^6 - 12*x^5 + 47*x^4 - 79*x^3 + 57*x^2 - 14*x + 1, x^6 - 12*x^5 + 47*x^4 - 77*x^3 + 52*x^2 - 13*x + 1, x^6 - 12*x^5 + 47*x^4 - 77*x^3 + 54*x^2 - 15*x + 1, x^6 - 12*x^5 + 47*x^4 - 76*x^3 + 51*x^2 - 13*x + 1, x^6 - 12*x^5 + 47*x^4 - 76*x^3 + 52*x^2 - 14*x + 1, x^6 - 12*x^5 + 47*x^4 - 75*x^3 + 48*x^2 - 12*x + 1, x^6 - 12*x^5 + 47*x^4 - 75*x^3 + 50*x^2 - 13*x + 1, x^6 - 12*x^5 + 47*x^4 - 74*x^3 + 47*x^2 - 12*x + 1, x^6 - 12*x^5 + 47*x^4 - 74*x^3 + 49*x^2 - 13*x + 1, x^6 - 12*x^5 + 47*x^4 - 73*x^3 + 47*x^2 - 12*x + 1, x^6 - 12*x^5 + 47*x^4 - 72*x^3 + 46*x^2 - 12*x + 1, x^6 - 12*x^5 + 48*x^4 - 83*x^3 + 62*x^2 - 16*x + 1, x^6 - 12*x^5 + 48*x^4 - 82*x^3 + 59*x^2 - 14*x + 1, x^6 - 12*x^5 + 48*x^4 - 82*x^3 + 60*x^2 - 17*x + 1, x^6 - 12*x^5 + 48*x^4 - 82*x^3 + 60*x^2 - 15*x + 1, x^6 - 12*x^5 + 48*x^4 - 81*x^3 + 58*x^2 - 16*x + 1, x^6 - 12*x^5 + 48*x^4 - 81*x^3 + 60*x^2 - 19*x + 2, x^6 - 12*x^5 + 48*x^4 - 80*x^3 + 54*x^2 - 13*x + 1, x^6 - 12*x^5 + 48*x^4 - 80*x^3 + 55*x^2 - 14*x + 1, x^6 - 12*x^5 + 48*x^4 - 80*x^3 + 56*x^2 - 15*x + 1, x^6 - 12*x^5 + 48*x^4 - 79*x^3 + 52*x^2 - 13*x + 1, x^6 - 12*x^5 + 48*x^4 - 79*x^3 + 53*x^2 - 14*x + 1, x^6 - 12*x^5 + 48*x^4 - 79*x^3 + 53*x^2 - 13*x + 1, x^6 - 12*x^5 + 48*x^4 - 79*x^3 + 54*x^2 - 14*x + 1, x^6 - 12*x^5 + 48*x^4 - 79*x^3 + 55*x^2 - 15*x + 1, x^6 - 12*x^5 + 48*x^4 - 78*x^3 + 51*x^2 - 13*x + 1, x^6 - 12*x^5 + 48*x^4 - 78*x^3 + 52*x^2 - 13*x + 1, x^6 - 12*x^5 + 48*x^4 - 78*x^3 + 53*x^2 - 14*x + 1, x^6 - 12*x^5 + 48*x^4 - 77*x^3 + 48*x^2 - 12*x + 1, x^6 - 12*x^5 + 48*x^4 - 77*x^3 + 50*x^2 - 13*x + 1, x^6 - 12*x^5 + 48*x^4 - 77*x^3 + 51*x^2 - 13*x + 1, x^6 - 12*x^5 + 48*x^4 - 77*x^3 + 52*x^2 - 14*x + 1, x^6 - 12*x^5 + 48*x^4 - 76*x^3 + 50*x^2 - 13*x + 1, x^6 - 12*x^5 + 48*x^4 - 75*x^3 + 47*x^2 - 12*x + 1, x^6 - 12*x^5 + 48*x^4 - 75*x^3 + 48*x^2 - 12*x + 1, x^6 - 12*x^5 + 48*x^4 - 75*x^3 + 49*x^2 - 13*x + 1, x^6 - 12*x^5 + 49*x^4 - 88*x^3 + 70*x^2 - 20*x + 1, x^6 - 12*x^5 + 49*x^4 - 86*x^3 + 63*x^2 - 15*x + 1, x^6 - 12*x^5 + 49*x^4 - 86*x^3 + 64*x^2 - 16*x + 1, x^6 - 12*x^5 + 49*x^4 - 86*x^3 + 65*x^2 - 17*x + 1, x^6 - 12*x^5 + 49*x^4 - 85*x^3 + 62*x^2 - 17*x + 1, x^6 - 12*x^5 + 49*x^4 - 85*x^3 + 62*x^2 - 15*x + 1, x^6 - 12*x^5 + 49*x^4 - 85*x^3 + 63*x^2 - 18*x + 1, x^6 - 12*x^5 + 49*x^4 - 85*x^3 + 64*x^2 - 20*x + 2, x^6 - 12*x^5 + 49*x^4 - 84*x^3 + 58*x^2 - 14*x + 1, x^6 - 12*x^5 + 49*x^4 - 84*x^3 + 59*x^2 - 15*x + 1, x^6 - 12*x^5 + 49*x^4 - 84*x^3 + 60*x^2 - 16*x + 1, x^6 - 12*x^5 + 49*x^4 - 84*x^3 + 61*x^2 - 17*x + 1, x^6 - 12*x^5 + 49*x^4 - 84*x^3 + 62*x^2 - 19*x + 2, x^6 - 12*x^5 + 49*x^4 - 83*x^3 + 56*x^2 - 14*x + 1, x^6 - 12*x^5 + 49*x^4 - 83*x^3 + 57*x^2 - 15*x + 1, x^6 - 12*x^5 + 49*x^4 - 83*x^3 + 57*x^2 - 14*x + 1, x^6 - 12*x^5 + 49*x^4 - 83*x^3 + 58*x^2 - 15*x + 1, x^6 - 12*x^5 + 49*x^4 - 83*x^3 + 59*x^2 - 16*x + 1, x^6 - 12*x^5 + 49*x^4 - 83*x^3 + 61*x^2 - 19*x + 2, x^6 - 12*x^5 + 49*x^4 - 82*x^3 + 53*x^2 - 13*x + 1, x^6 - 12*x^5 + 49*x^4 - 82*x^3 + 54*x^2 - 13*x + 1, x^6 - 12*x^5 + 49*x^4 - 82*x^3 + 55*x^2 - 14*x + 1, x^6 - 12*x^5 + 49*x^4 - 82*x^3 + 56*x^2 - 14*x + 1, x^6 - 12*x^5 + 49*x^4 - 82*x^3 + 57*x^2 - 15*x + 1, x^6 - 12*x^5 + 49*x^4 - 82*x^3 + 58*x^2 - 16*x + 1, x^6 - 12*x^5 + 49*x^4 - 81*x^3 + 52*x^2 - 13*x + 1, x^6 - 12*x^5 + 49*x^4 - 81*x^3 + 54*x^2 - 14*x + 1, x^6 - 12*x^5 + 49*x^4 - 81*x^3 + 54*x^2 - 13*x + 1, x^6 - 12*x^5 + 49*x^4 - 81*x^3 + 55*x^2 - 14*x + 1, x^6 - 12*x^5 + 49*x^4 - 81*x^3 + 56*x^2 - 15*x + 1, x^6 - 12*x^5 + 49*x^4 - 80*x^3 + 53*x^2 - 13*x + 1, x^6 - 12*x^5 + 49*x^4 - 80*x^3 + 54*x^2 - 14*x + 1, x^6 - 12*x^5 + 50*x^4 - 93*x^3 + 78*x^2 - 24*x + 1, x^6 - 12*x^5 + 50*x^4 - 92*x^3 + 75*x^2 - 22*x + 1, x^6 - 12*x^5 + 50*x^4 - 92*x^3 + 76*x^2 - 24*x + 2, x^6 - 12*x^5 + 50*x^4 - 91*x^3 + 71*x^2 - 18*x + 1, x^6 - 12*x^5 + 50*x^4 - 91*x^3 + 72*x^2 - 20*x + 1, x^6 - 12*x^5 + 50*x^4 - 91*x^3 + 73*x^2 - 22*x + 2, x^6 - 12*x^5 + 50*x^4 - 90*x^3 + 67*x^2 - 15*x + 1, x^6 - 12*x^5 + 50*x^4 - 90*x^3 + 68*x^2 - 17*x + 1, x^6 - 12*x^5 + 50*x^4 - 90*x^3 + 68*x^2 - 16*x + 1, x^6 - 12*x^5 + 50*x^4 - 90*x^3 + 69*x^2 - 20*x + 1, x^6 - 12*x^5 + 50*x^4 - 90*x^3 + 69*x^2 - 18*x + 1, x^6 - 12*x^5 + 50*x^4 - 90*x^3 + 70*x^2 - 22*x + 2, x^6 - 12*x^5 + 50*x^4 - 90*x^3 + 70*x^2 - 19*x + 1, x^6 - 12*x^5 + 50*x^4 - 90*x^3 + 72*x^2 - 25*x + 3, x^6 - 12*x^5 + 50*x^4 - 89*x^3 + 65*x^2 - 15*x + 1, x^6 - 12*x^5 + 50*x^4 - 89*x^3 + 66*x^2 - 18*x + 1, x^6 - 12*x^5 + 50*x^4 - 89*x^3 + 66*x^2 - 16*x + 1, x^6 - 12*x^5 + 50*x^4 - 89*x^3 + 67*x^2 - 20*x + 2, x^6 - 12*x^5 + 50*x^4 - 89*x^3 + 67*x^2 - 19*x + 1, x^6 - 12*x^5 + 50*x^4 - 89*x^3 + 67*x^2 - 17*x + 1, x^6 - 12*x^5 + 50*x^4 - 89*x^3 + 68*x^2 - 18*x + 1, x^6 - 12*x^5 + 50*x^4 - 88*x^3 + 62*x^2 - 15*x + 1, x^6 - 12*x^5 + 50*x^4 - 88*x^3 + 63*x^2 - 17*x + 1, x^6 - 12*x^5 + 50*x^4 - 88*x^3 + 63*x^2 - 16*x + 1, x^6 - 12*x^5 + 50*x^4 - 88*x^3 + 64*x^2 - 17*x + 1, x^6 - 12*x^5 + 50*x^4 - 88*x^3 + 64*x^2 - 15*x + 1, x^6 - 12*x^5 + 50*x^4 - 88*x^3 + 65*x^2 - 18*x + 1, x^6 - 12*x^5 + 50*x^4 - 88*x^3 + 65*x^2 - 16*x + 1, x^6 - 12*x^5 + 50*x^4 - 88*x^3 + 66*x^2 - 20*x + 2, x^6 - 12*x^5 + 50*x^4 - 88*x^3 + 67*x^2 - 21*x + 2, x^6 - 12*x^5 + 50*x^4 - 87*x^3 + 59*x^2 - 14*x + 1, x^6 - 12*x^5 + 50*x^4 - 87*x^3 + 60*x^2 - 15*x + 1, x^6 - 12*x^5 + 50*x^4 - 87*x^3 + 60*x^2 - 14*x + 1, x^6 - 12*x^5 + 50*x^4 - 87*x^3 + 61*x^2 - 16*x + 1, x^6 - 12*x^5 + 50*x^4 - 87*x^3 + 61*x^2 - 15*x + 1, x^6 - 12*x^5 + 50*x^4 - 87*x^3 + 62*x^2 - 16*x + 1, x^6 - 12*x^5 + 50*x^4 - 87*x^3 + 63*x^2 - 17*x + 1, x^6 - 12*x^5 + 50*x^4 - 87*x^3 + 63*x^2 - 15*x + 1, x^6 - 12*x^5 + 50*x^4 - 87*x^3 + 64*x^2 - 18*x + 1, x^6 - 12*x^5 + 50*x^4 - 87*x^3 + 65*x^2 - 20*x + 2, x^6 - 12*x^5 + 50*x^4 - 86*x^3 + 58*x^2 - 15*x + 1, x^6 - 12*x^5 + 50*x^4 - 86*x^3 + 59*x^2 - 15*x + 1, x^6 - 12*x^5 + 50*x^4 - 86*x^3 + 59*x^2 - 14*x + 1, x^6 - 12*x^5 + 50*x^4 - 86*x^3 + 60*x^2 - 16*x + 1, x^6 - 12*x^5 + 50*x^4 - 86*x^3 + 60*x^2 - 15*x + 1, x^6 - 12*x^5 + 50*x^4 - 86*x^3 + 61*x^2 - 16*x + 1, x^6 - 12*x^5 + 50*x^4 - 85*x^3 + 56*x^2 - 14*x + 1, x^6 - 12*x^5 + 51*x^4 - 98*x^3 + 87*x^2 - 31*x + 3, x^6 - 12*x^5 + 51*x^4 - 97*x^3 + 82*x^2 - 25*x + 1, x^6 - 12*x^5 + 51*x^4 - 97*x^3 + 83*x^2 - 26*x + 1, x^6 - 12*x^5 + 51*x^4 - 97*x^3 + 84*x^2 - 29*x + 3, x^6 - 12*x^5 + 51*x^4 - 96*x^3 + 79*x^2 - 23*x + 1, x^6 - 12*x^5 + 51*x^4 - 96*x^3 + 79*x^2 - 22*x + 1, x^6 - 12*x^5 + 51*x^4 - 96*x^3 + 80*x^2 - 24*x + 1, x^6 - 12*x^5 + 51*x^4 - 96*x^3 + 81*x^2 - 27*x + 3, x^6 - 12*x^5 + 51*x^4 - 96*x^3 + 81*x^2 - 26*x + 2, x^6 - 12*x^5 + 51*x^4 - 95*x^3 + 74*x^2 - 17*x + 1, x^6 - 12*x^5 + 51*x^4 - 95*x^3 + 75*x^2 - 19*x + 1, x^6 - 12*x^5 + 51*x^4 - 95*x^3 + 76*x^2 - 22*x + 2, x^6 - 12*x^5 + 51*x^4 - 95*x^3 + 76*x^2 - 21*x + 1, x^6 - 12*x^5 + 51*x^4 - 95*x^3 + 76*x^2 - 20*x + 1, x^6 - 12*x^5 + 51*x^4 - 95*x^3 + 77*x^2 - 22*x + 1, x^6 - 12*x^5 + 51*x^4 - 95*x^3 + 78*x^2 - 27*x + 3, x^6 - 12*x^5 + 51*x^4 - 95*x^3 + 78*x^2 - 24*x + 2, x^6 - 12*x^5 + 51*x^4 - 95*x^3 + 78*x^2 - 23*x + 1, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 71*x^2 - 16*x + 1, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 72*x^2 - 18*x + 1, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 72*x^2 - 17*x + 1, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 73*x^2 - 21*x + 1, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 73*x^2 - 19*x + 1, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 73*x^2 - 18*x + 1, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 74*x^2 - 23*x + 2, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 74*x^2 - 20*x + 1, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 75*x^2 - 22*x + 2, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 75*x^2 - 21*x + 1, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 76*x^2 - 26*x + 3, x^6 - 12*x^5 + 51*x^4 - 94*x^3 + 76*x^2 - 23*x + 2, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 68*x^2 - 15*x + 1, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 69*x^2 - 16*x + 1, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 70*x^2 - 19*x + 1, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 70*x^2 - 17*x + 1, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 70*x^2 - 16*x + 1, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 71*x^2 - 21*x + 2, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 71*x^2 - 20*x + 1, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 71*x^2 - 18*x + 1, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 72*x^2 - 22*x + 2, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 72*x^2 - 21*x + 1, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 72*x^2 - 19*x + 1, x^6 - 12*x^5 + 51*x^4 - 93*x^3 + 73*x^2 - 20*x + 1, x^6 - 12*x^5 + 51*x^4 - 92*x^3 + 65*x^2 - 15*x + 1, x^6 - 12*x^5 + 51*x^4 - 92*x^3 + 66*x^2 - 16*x + 1, x^6 - 12*x^5 + 51*x^4 - 92*x^3 + 67*x^2 - 18*x + 1, x^6 - 12*x^5 + 51*x^4 - 92*x^3 + 67*x^2 - 17*x + 1, x^6 - 12*x^5 + 51*x^4 - 92*x^3 + 67*x^2 - 15*x + 1, x^6 - 12*x^5 + 51*x^4 - 92*x^3 + 68*x^2 - 18*x + 1, x^6 - 12*x^5 + 51*x^4 - 92*x^3 + 68*x^2 - 16*x + 1, x^6 - 12*x^5 + 51*x^4 - 92*x^3 + 69*x^2 - 19*x + 1, x^6 - 12*x^5 + 51*x^4 - 91*x^3 + 62*x^2 - 15*x + 1, x^6 - 12*x^5 + 51*x^4 - 91*x^3 + 64*x^2 - 16*x + 1, x^6 - 12*x^5 + 52*x^4 - 103*x^3 + 96*x^2 - 38*x + 5, x^6 - 12*x^5 + 52*x^4 - 102*x^3 + 90*x^2 - 29*x + 1, x^6 - 12*x^5 + 52*x^4 - 102*x^3 + 91*x^2 - 32*x + 3, x^6 - 12*x^5 + 52*x^4 - 102*x^3 + 91*x^2 - 30*x + 1, x^6 - 12*x^5 + 52*x^4 - 102*x^3 + 92*x^2 - 33*x + 3, x^6 - 12*x^5 + 52*x^4 - 101*x^3 + 86*x^2 - 25*x + 1, x^6 - 12*x^5 + 52*x^4 - 101*x^3 + 87*x^2 - 28*x + 2, x^6 - 12*x^5 + 52*x^4 - 101*x^3 + 87*x^2 - 27*x + 1, x^6 - 12*x^5 + 52*x^4 - 101*x^3 + 88*x^2 - 30*x + 3, x^6 - 12*x^5 + 52*x^4 - 101*x^3 + 88*x^2 - 28*x + 1, x^6 - 12*x^5 + 52*x^4 - 101*x^3 + 89*x^2 - 31*x + 3, x^6 - 12*x^5 + 52*x^4 - 101*x^3 + 90*x^2 - 33*x + 4, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 81*x^2 - 19*x + 1, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 82*x^2 - 21*x + 1, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 83*x^2 - 24*x + 1, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 83*x^2 - 24*x + 2, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 83*x^2 - 23*x + 1, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 84*x^2 - 26*x + 2, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 84*x^2 - 25*x + 1, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 84*x^2 - 24*x + 1, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 85*x^2 - 28*x + 3, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 85*x^2 - 26*x + 1, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 86*x^2 - 29*x + 3, x^6 - 12*x^5 + 52*x^4 - 100*x^3 + 86*x^2 - 28*x + 2, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 78*x^2 - 18*x + 1, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 79*x^2 - 20*x + 1, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 79*x^2 - 19*x + 1, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 80*x^2 - 24*x + 1, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 80*x^2 - 23*x + 2, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 80*x^2 - 22*x + 1, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 80*x^2 - 21*x + 1, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 80*x^2 - 20*x + 1, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 81*x^2 - 24*x + 2, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 81*x^2 - 23*x + 1, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 81*x^2 - 22*x + 1, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 82*x^2 - 28*x + 3, x^6 - 12*x^5 + 52*x^4 - 99*x^3 + 82*x^2 - 24*x + 1, x^6 - 12*x^5 + 52*x^4 - 98*x^3 + 75*x^2 - 18*x + 1, x^6 - 12*x^5 + 52*x^4 - 98*x^3 + 75*x^2 - 17*x + 1, x^6 - 12*x^5 + 52*x^4 - 98*x^3 + 76*x^2 - 21*x + 1, x^6 - 12*x^5 + 52*x^4 - 98*x^3 + 76*x^2 - 19*x + 1, x^6 - 12*x^5 + 52*x^4 - 98*x^3 + 76*x^2 - 17*x + 1, x^6 - 12*x^5 + 52*x^4 - 98*x^3 + 77*x^2 - 22*x + 1, x^6 - 12*x^5 + 52*x^4 - 97*x^3 + 72*x^2 - 18*x + 1, x^6 - 12*x^5 + 53*x^4 - 108*x^3 + 102*x^2 - 38*x + 3, x^6 - 12*x^5 + 53*x^4 - 108*x^3 + 103*x^2 - 41*x + 5, x^6 - 12*x^5 + 53*x^4 - 107*x^3 + 97*x^2 - 31*x + 1, x^6 - 12*x^5 + 53*x^4 - 107*x^3 + 98*x^2 - 34*x + 2, x^6 - 12*x^5 + 53*x^4 - 107*x^3 + 98*x^2 - 33*x + 1, x^6 - 12*x^5 + 53*x^4 - 107*x^3 + 99*x^2 - 37*x + 4, x^6 - 12*x^5 + 53*x^4 - 107*x^3 + 99*x^2 - 36*x + 3, x^6 - 12*x^5 + 53*x^4 - 107*x^3 + 100*x^2 - 39*x + 5, x^6 - 12*x^5 + 53*x^4 - 107*x^3 + 100*x^2 - 37*x + 3, x^6 - 12*x^5 + 53*x^4 - 106*x^3 + 93*x^2 - 27*x + 1, x^6 - 12*x^5 + 53*x^4 - 106*x^3 + 94*x^2 - 30*x + 1, x^6 - 12*x^5 + 53*x^4 - 106*x^3 + 94*x^2 - 30*x + 2, x^6 - 12*x^5 + 53*x^4 - 106*x^3 + 94*x^2 - 29*x + 1, x^6 - 12*x^5 + 53*x^4 - 106*x^3 + 95*x^2 - 33*x + 3, x^6 - 12*x^5 + 53*x^4 - 106*x^3 + 95*x^2 - 32*x + 3, x^6 - 12*x^5 + 53*x^4 - 106*x^3 + 95*x^2 - 31*x + 1, x^6 - 12*x^5 + 53*x^4 - 106*x^3 + 96*x^2 - 35*x + 4, x^6 - 12*x^5 + 53*x^4 - 106*x^3 + 96*x^2 - 34*x + 3, x^6 - 12*x^5 + 53*x^4 - 105*x^3 + 88*x^2 - 21*x + 1, x^6 - 12*x^5 + 53*x^4 - 105*x^3 + 89*x^2 - 23*x + 1, x^6 - 12*x^5 + 53*x^4 - 105*x^3 + 90*x^2 - 27*x + 1, x^6 - 12*x^5 + 53*x^4 - 105*x^3 + 90*x^2 - 26*x + 1, x^6 - 12*x^5 + 53*x^4 - 105*x^3 + 90*x^2 - 25*x + 1, x^6 - 12*x^5 + 53*x^4 - 105*x^3 + 91*x^2 - 29*x + 2, x^6 - 12*x^5 + 53*x^4 - 104*x^3 + 85*x^2 - 21*x + 1, x^6 - 12*x^5 + 53*x^4 - 104*x^3 + 86*x^2 - 24*x + 1, x^6 - 12*x^5 + 54*x^4 - 114*x^3 + 114*x^2 - 47*x + 5, x^6 - 12*x^5 + 54*x^4 - 114*x^3 + 115*x^2 - 50*x + 7, x^6 - 12*x^5 + 54*x^4 - 113*x^3 + 109*x^2 - 39*x + 1, x^6 - 12*x^5 + 54*x^4 - 113*x^3 + 110*x^2 - 43*x + 4, x^6 - 12*x^5 + 54*x^4 - 113*x^3 + 110*x^2 - 42*x + 3, x^6 - 12*x^5 + 54*x^4 - 112*x^3 + 104*x^2 - 33*x + 1, x^6 - 12*x^5 + 54*x^4 - 112*x^3 + 105*x^2 - 36*x + 1, x^7 - 13*x^6 + 61*x^5 - 133*x^4 + 142*x^3 - 71*x^2 + 15*x - 1, x^7 - 13*x^6 + 61*x^5 - 132*x^4 + 138*x^3 - 67*x^2 + 14*x - 1, x^7 - 13*x^6 + 61*x^5 - 131*x^4 + 136*x^3 - 66*x^2 + 14*x - 1, x^7 - 13*x^6 + 62*x^5 - 139*x^4 + 153*x^3 - 78*x^2 + 16*x - 1, x^7 - 13*x^6 + 62*x^5 - 139*x^4 + 154*x^3 - 80*x^2 + 17*x - 1, x^7 - 13*x^6 + 62*x^5 - 138*x^4 + 149*x^3 - 74*x^2 + 15*x - 1, x^7 - 13*x^6 + 62*x^5 - 138*x^4 + 150*x^3 - 76*x^2 + 16*x - 1, x^7 - 13*x^6 + 62*x^5 - 138*x^4 + 151*x^3 - 78*x^2 + 17*x - 1, x^7 - 13*x^6 + 62*x^5 - 137*x^4 + 146*x^3 - 72*x^2 + 15*x - 1, x^7 - 13*x^6 + 62*x^5 - 137*x^4 + 147*x^3 - 73*x^2 + 15*x - 1, x^7 - 13*x^6 + 62*x^5 - 137*x^4 + 148*x^3 - 75*x^2 + 16*x - 1, x^7 - 13*x^6 + 62*x^5 - 136*x^4 + 142*x^3 - 68*x^2 + 14*x - 1, x^7 - 13*x^6 + 62*x^5 - 136*x^4 + 144*x^3 - 71*x^2 + 15*x - 1, x^7 - 13*x^6 + 62*x^5 - 135*x^4 + 140*x^3 - 67*x^2 + 14*x - 1, x^7 - 13*x^6 + 63*x^5 - 145*x^4 + 165*x^3 - 87*x^2 + 18*x - 1, x^7 - 13*x^6 + 63*x^5 - 145*x^4 + 166*x^3 - 90*x^2 + 20*x - 1, x^7 - 13*x^6 + 63*x^5 - 144*x^4 + 160*x^3 - 80*x^2 + 16*x - 1, x^7 - 13*x^6 + 63*x^5 - 144*x^4 + 161*x^3 - 83*x^2 + 17*x - 1, x^7 - 13*x^6 + 63*x^5 - 144*x^4 + 162*x^3 - 85*x^2 + 18*x - 1, x^7 - 13*x^6 + 63*x^5 - 144*x^4 + 163*x^3 - 87*x^2 + 19*x - 1, x^7 - 13*x^6 + 63*x^5 - 143*x^4 + 157*x^3 - 79*x^2 + 16*x - 1, x^7 - 13*x^6 + 63*x^5 - 143*x^4 + 157*x^3 - 78*x^2 + 16*x - 1, x^7 - 13*x^6 + 63*x^5 - 143*x^4 + 158*x^3 - 81*x^2 + 17*x - 1, x^7 - 13*x^6 + 63*x^5 - 143*x^4 + 158*x^3 - 80*x^2 + 16*x - 1, x^7 - 13*x^6 + 63*x^5 - 143*x^4 + 159*x^3 - 83*x^2 + 18*x - 1, x^7 - 13*x^6 + 63*x^5 - 143*x^4 + 159*x^3 - 82*x^2 + 17*x - 1, x^7 - 13*x^6 + 63*x^5 - 142*x^4 + 153*x^3 - 75*x^2 + 15*x - 1, x^7 - 13*x^6 + 63*x^5 - 142*x^4 + 154*x^3 - 77*x^2 + 16*x - 1, x^7 - 13*x^6 + 64*x^5 - 152*x^4 + 182*x^3 - 104*x^2 + 24*x - 1, x^7 - 13*x^6 + 64*x^5 - 151*x^4 + 176*x^3 - 93*x^2 + 18*x - 1, x^7 - 13*x^6 + 64*x^5 - 151*x^4 + 177*x^3 - 96*x^2 + 20*x - 1, x^7 - 13*x^6 + 64*x^5 - 151*x^4 + 178*x^3 - 99*x^2 + 22*x - 1, x^7 - 13*x^6 + 64*x^5 - 150*x^4 + 172*x^3 - 89*x^2 + 18*x - 1, x^7 - 13*x^6 + 64*x^5 - 150*x^4 + 173*x^3 - 92*x^2 + 19*x - 1, x^7 - 13*x^6 + 64*x^5 - 150*x^4 + 173*x^3 - 91*x^2 + 18*x - 1, x^7 - 13*x^6 + 64*x^5 - 150*x^4 + 174*x^3 - 95*x^2 + 21*x - 1, x^7 - 13*x^6 + 64*x^5 - 150*x^4 + 174*x^3 - 94*x^2 + 20*x - 1, x^7 - 13*x^6 + 64*x^5 - 149*x^4 + 168*x^3 - 86*x^2 + 17*x - 1, x^7 - 13*x^6 + 65*x^5 - 158*x^4 + 194*x^3 - 113*x^2 + 26*x - 1, x^7 - 13*x^6 + 65*x^5 - 157*x^4 + 188*x^3 - 102*x^2 + 20*x - 1 ]; end case; end function; /* ============================================================================== The main portion of the program. The function isogeny_classes(q,g,N) enumerates all of the possible real Weil q-polynomials of degree g with trace q + 1 - N, and then checks to see whether any of our arguments can eliminate the corresponding isogeny classes from consideration. The function best_bound(q,g) tries to find the largest value of N such that isogeny_classes(q,g,N) does not return any uneliminated polynomials. ============================================================================== */ // Note: Using the bounds in the following function seems to make only a small // difference in many isogeny_classes() calculations. But it can't hurt. function derivative_spans(n) // Compute the maximal spans of the derivatives of a degree-n polynomial. // The *span* of a polynomial is the difference between the largest // and the smallest of its real roots. // Suppose f is a degree-n polynomial with real coefficients with all // roots real and lying in the interval [-1,1]. Return a vector of // rational numbers s such that s[i] is an upper bound on the span of // the (n-i)-th derivative of f. s[1] is set to 0 by fiat. // We compute the maximal spans by using a result of Raphael // Robinson [Robinson 1964a], which says that the maximum values // come from polynomials of the form (x-1)^a * (x + 1)^(n - a). R:=PolynomialRing(Rationals()); s := [Rationals() | 0 : i in [1..Floor((n+1)/2)] ]; s cat:= [2 : i in [1..n+1-#s] ]; for a in [1..Floor(n/2)] do f := (x + 1)^a * (x - 1)^(n - a); for k in [1..n-2] do f := Derivative(f); if 2*k ge n - 1 then rts := [r[1] : r in Roots(f,RealField())]; maxr := Max(rts); minr := Min(rts); span := maxr-minr; approx := BestApproximation(span,10^5); while approx lt span do approx +:= 1/Denominator(approx); end while; s[n-k] := Max(s[n-k],approx); end if; end for; end for; return s; end function; procedure process_isogeny_class(~I : verbose := 1) // Given an isogeny class, run through the possible arguments that // might eliminate it, and set the value of I`eliminated appropriately. is_isogeny_class(~I); add_points(~I); add_places(~I); if not assigned I`eliminated then is_eliminated_by_genus_2_classification(~I); end if; if not assigned I`eliminated then is_eliminated_by_place_counts(~I); end if; if not assigned I`eliminated then is_eliminated_by_Korchmaros_Torres(~I); end if; if not assigned I`eliminated then is_eliminated_by_supersingular_factor(~I); end if; if not assigned I`eliminated then is_eliminated_by_Galois_descent(~I); end if; if not assigned I`eliminated then is_eliminated_by_resultant_1(~I); end if; if not assigned I`eliminated then is_eliminated_by_resultant_2(~I); end if; if not assigned I`eliminated then is_eliminated_by_elliptic_factor(~I); end if; // We've tried all the tests we know if not assigned I`eliminated then I`eliminated := false; end if; if verbose gt 1 or (verbose eq 1 and not I`eliminated) then print "=================================================="; print "Eliminated? " cat Sprint(I`eliminated); if I`eliminated then print I`reason; end if; add_places(~I); print "Place counts: ", I`places; add_modified_reduced_resultants(~I); print I`real_WP_factors; print "Matrix of pairwise modified reduced resultants:"; print I`pairwise_modified_reduced_resultants; print "List of modified reduced resultants: ", I`modified_reduced_resultants; if assigned I`comment then print "Possibly useful information:"; print I`comment; end if; end if; return; end procedure; // Now the main function. Here is the notation we will use. It is pretty // much the same as in the program used in [Howe and Lauter 2003]. // // * a[i] will denote the number of degree-i places on C. // // * N[i] will denote the number of GF(q^i)-rational points on C. // // Let alpha[i] (for i = 1, ..., 2*g) be the eigenvalues of the Frobenius // endomorphism of the Jacobian of C, with alpha[i] and alpha[i+g] being // complex conjugates of one another. // // * p[i] will denote the i-th powersum of the alpha's. // // * c[i] will denote the coefficient of x^(2*g-i) in the // characteristic polynomial of Frobenius of Jac C. // // Let f(x) be the Weil polynomial of C, and h the real Weil polynomial, // so that f(x) = x^g * h(x + q/x). The roots of h are all real, and have // absolute value at most 2*sqrt(q). // // * b[i] will denote the coefficient of x^(g-i) in h. // // Here are the relations among these quantities: // // * N[d] is the sum, over the divisors e of d, of e * a[e]. // // * p[d] = q^d + 1 - N[d]. // // * The c's and the p's satisfy the Newton relations: // n*c[n] + p[n] + sum_{0 < j < n} c[j]*p[n-j] = 0. // // * The b's and the c's are related by the fact that // f(x) = x^g * h(x + q/x). function isogeny_classes(q, g, N1: verbose := 1, abort := false, check_defect := true, double_check := true) // Compute possible real Weil polynomials for a genus-g curve over GF(q) // with N1 rational points. // The verbosity levels: // 0: Print nothing // 1: Print the isogeny classes not excluded by our arguments. // 2: Print every isogeny class. // If 'abort' is set to true, the function will return as soon as it // finds a Weil polynomial that cannot be eliminated. // If 'check_defect' is true and the "defect" is small, we will compute // the possible Weil polynomials by looking at precomputed lists of // deficient polynomials. // If 'double_check' is true, verify that the rational approximations // we get to the roots of various polynomials are actually as close // to the roots as we think they are. This is only necessary for // worrywarts (like the programmer) who are concerned with computations // involving real numbers. // This will slow things down, but not too unreasonably. For example, // on my laptop it increased the time for isogeny_classes(2,12,15) by 20 // percent. R := PolynomialRing(Rationals()); // Check to see whether N1 is greater than any of the proven // upper bounds. ob := Oesterle_bound(q,g); ib := Ihara_bound(q,g); sb := Serre_bound(q,g); if N1 gt sb then if verbose gt 0 then printf "Number of points greater than the Serre bound of %o.\n", sb; end if; return []; end if; if N1 gt ib then if verbose gt 0 then printf "Number of points greater than the Ihara bound of %o.\n", ib; end if; return []; end if; if N1 gt ob then if verbose gt 0 then printf "Number of points greater than the Oesterle bound of %o.\n", ob; end if; return []; end if; // Initialize the list of isogeny classes that the // function will return. classes := []; m := floor_root(4*q); defect := q + 1 + g*m - N1; if defect lt 0 then return []; end if; if check_defect and defect le max_defect then // Instead of computing all possible real Weil polynomials from // scratch, we use precomputed lists of irreducible polynomials // of small deficiency. if defect eq 0 then // There's only one possible Weil polynomial. I := rec; process_isogeny_class(~I : verbose := verbose); classes cat:= [I]; return classes; end if; def_list := [deficient_polynomial_list(x,i) : i in [1..defect]]; shifted_list := [[Evaluate(p,x+m+1): p in dl] : dl in def_list]; irreducible_list := [[p : p in sl | are_all_roots_in_Weil_interval(p,q)] : sl in shifted_list]; reducible_list := irreducible_list; for i in [2..defect] do for j in [1.. (i div 2)] do for p1 in reducible_list[j], p2 in reducible_list[i-j] do p := p1*p2; if not p in reducible_list[i] then reducible_list[i] cat:= [p]; end if; end for; end for; end for; for i in [1..defect] do Sort(~reducible_list[i]); end for; for p in reducible_list[defect] do if Degree(p) le g then h := p * (x + m)^(g - Degree(p)); I := rec; add_places(~I); if &and [pl ge 0 : pl in I`places] then process_isogeny_class(~I : verbose := verbose); classes cat:= [I]; if abort and not I`eliminated then return classes; end if; end if; end if; end for; return classes; end if; // Get rational approximations to sqrt(q). root_q_high := BestApproximation(Sqrt(q),10^5); while root_q_high^2 lt q do root_q_high +:= 1/Denominator(root_q_high); end while; root_q_low := root_q_high; while root_q_low^2 gt q do root_q_low -:= 1/Denominator(root_q_low); end while; // Compute the maximum spans of the derivatives of a real Weil // polynomial of degree g. max_spans := [2*root_q_high*a : a in derivative_spans(g)]; // Create real fields with sufficient precision. // At the n-th level of our algorithm, we will be computing // roots of derivatives of Weil polynomials, and we will need // a certain level of precision to the right of the decimal // point. The variable 'digits' will keep track of that number. // But some precision must be devoted to the left of the decimal // point as well, and since the roots will all lie in the Weil // interval we have an upper bound on that. digits_to_left := 3 + Ceiling(Log(10,2*Sqrt(q))); // Now get our collection of real fields. digits := 10; tendigits := [10^-digits]; reals := [RealField(digits)]; for number in [1..g-1] do coef := Factorial(g-number-1); errorfactor := (1/2) * (Factorial(g)/Factorial(g-number+1)) * (4*root_q_high + 10.0^-digits)^(number-1); // We will want 10^(-2*digits)*errorfactor < coef. See the // comments below to find out why this should be enough // precision. newdigits := Ceiling(Log(errorfactor/coef)/Log(10)/2); newdigits := Max(digits,newdigits + 1); tendigits cat:= [10^-newdigits]; reals cat:= [RealField(newdigits + digits_to_left)]; end for; // Get the usual upper bounds on the number of points. point_bound := [Oesterle_bound(q^n,g) : n in [1..g]]; // Initialize several vectors: // // a[i] : The number of degree-i places on C. // N[i] : The number of points on C over GF(q^i). // p[i] : The i-th power sum of the Frobenius eigenvalues. // c[i] : The i-th signed symmetric function of the Frobenius eigenvalues, // so also the coefficient of x^(2g-i) in the Weil polynomial. // b[i] : The coefficient of x^(g-i) in the real Weil polynomial. // h[i] : The (g-i)-th derivative of the real Weil polynomial. // b_bound[i] : Our current upper bound on b[i]. // fact[i] : (g-i)! a := Vector([0 : i in [1..g]]); N := Vector([0 : i in [1..g]]); p := Vector([0 : i in [1..g]]); c := Vector([0 : i in [1..g]]); b := Vector([0 : i in [1..g]]); h := Vector([R!0 : i in [1..g]]); b_bound := Vector([0 : i in [1..g]]); fact := Vector([Factorial(g-i) : i in [1..g]]); fact0 := Factorial(g); // To compute the vector of c's from the vector of b's, // we take the inner product with the vector b_to_c created // here, plus the constant b_to_c_const. b_to_c := [Vector([0 : i in [1..g]]) : j in [1..g]]; for n in [1..g] do for j in [1..g] do if IsEven(n-j) then i := (n-j) div 2; if i ge 0 then b_to_c[n][j] := Binomial(g-n+2*i,g-n+i)*q^i ; end if; end if; end for; end for; b_to_c_const := Vector([0 : i in [1..g]]); for n in [1..g] do if IsEven(n) then b_to_c_const[n] := Binomial(g,g-(n div 2))*q^(n div 2); end if; end for; stage_count := [0 : i in [1..g+1]]; // This is to keep track how how many times we are at various levels // of the computation. This should help determine whether various // modifications to the algorithm actually help. // Start a[1] and N[1] one less than the actual values, // with the others following suit. a[1] := N1 - 1; N[1] := N1 - 1; p[1] := q + 2 - N1; c[1] := N1 - q - 2; b[1] := N1 - q - 2; h[1] := Factorial(g) * x + Factorial(g-1)*b[1]; b_bound[1] := N1 - q - 1; // The variable n will be an index to the element of b that we are // adjusting. n := 1; // Keep a flag to indicate whether we have just incremented // or decremented the index n. Start by saying we decremented. decrement_flag := true; while n gt 0 do stage_count[n] +:= 1; if decrement_flag then // We've just decremented n, so it's time to increment b[n]. if b[n] eq b_bound[n] then // Oops, we're already at the upper limit. // Go back down to the preceding entry of b. n -:= 1; decrement_flag := true; else // We can still increment b[n], so do so. This causes // changes in the values of the other variables. b[n] +:= 1; h[n] +:= fact[n]; c[n] +:= 1; p[n] -:= n; N[n] +:= n; a[n] +:= 1; n +:= 1; decrement_flag := false; end if; else // We've just incremented n, so compute the allowable range // of values for b[n]. if n le g then // Compute the range of coefficients [b_min..b_max] that // b[n] can run through. These coefficients will end up // being reflected in the constant term of h[n]; the // constant term is b[n] times fact[n] ( = (g-n)! ). coef := fact[n]; // Our range computation differs depending on whether // the current value of h[n-1] has multiple roots. // (If the derivative of h[n] has multiple roots, there // is at most one allowable value for b[n].) if n gt 2 then multiple_roots := GCD(h[n-1],h[n-2]); else multiple_roots := R!1; end if; if Degree(multiple_roots) gt 0 then // It's likely we won't be able to lift h[n-1], // so let's be pessimistic and start by saying // there will be a problem. b_max := -1; b_min := 1; new_h := Integral(h[n-1]); shift := new_h mod multiple_roots; // This had better be a constant... if Degree(shift) lt 1 then shift := Rationals()!Coefficient(shift,0); // And it had better be an integer... if Denominator(shift) eq 1 then // And it had better be divisible by coef... shift := Integers()!shift; if shift mod coef eq 0 then value := -shift/coef; // And we'd better have all roots in the // Weil interval. if are_all_roots_in_Weil_interval( new_h+coef*value,q : root_q_plus := root_q_high, root_q_minus := root_q_low) then // Mirabile dictu! There is no problem // at this level! b_max := value; b_min := value; end if; end if; end if; end if; else // There are no multiple roots, and we will use the // method of Robinson [Robinson 1964b] to find the // range of constant terms. new_h := Integral(h[n-1]); // First we compute the extrema of new_h by computing // the roots of its derivative, h[n-1]. We compute // roots in the real numbers, then replace the real // values with rational numbers, and verify that the // rational numbers are indeed as close to the roots // of h[n-1] as we require. extrema := [r[1] : r in Roots(h[n-1],reals[n])]; rational_extrema :=[ Round(ex/tendigits[n])*tendigits[n] : ex in extrema]; Sort(~rational_extrema); // Have we computed to enough precision to separate the // roots? if &or [ extrema[i+1]-extrema[i] lt 2*tendigits[n] : i in [1..#extrema-1] ] then error "ERROR: Insufficient precision in root finding"; end if; // Make certain that we've actually pinned down the roots // as accurately as we think. if double_check and &or[Sign(Evaluate(h[n-1],ex+tendigits[n])) eq Sign(Evaluate(h[n-1],ex-tendigits[n])) : ex in rational_extrema] then error "ERROR: Insufficient accuracy in root finding"; end if; // Now that we have the real roots of h[n-1], let's make // sure they satisfy the required conditions. First we // check that there are n-1 of them. Then we see whether // the span of the roots is allowed by [Robinson 1964a]. // And we check that they all lie in the Weil interval. roots_are_OK := true; // We'll say the roots are OK until we discover // otherwise. if #extrema lt n-1 then // If h[n-1] has non-real roots, we can stop // looking at it. But we want to make sure that // the problem lies with h[n-1], and not with Magma's // root-finding algorithm! So let's make certain // that h[n-1] does not have all real roots. sturm := rec; init_Sturm_sequence(~sturm); add_infinity(~sturm); if sturm`infinity_minus - sturm`infinity_plus ne #extrema then error "ERROR: Problem with real root finding"; end if; roots_are_OK := false; end if; if roots_are_OK then // Do the roots lie in the Weil interval, as best as // we can tell? if extrema[1] lt -2*root_q_high - tendigits[n] or extrema[n-1] gt 2*root_q_high + tendigits[n] then roots_are_OK := false; end if; // Is the span of the roots allowed by Robinson's // theorem? if n gt 2 and extrema[n-1]- extrema[1] gt max_spans[n-1] + 2*tendigits[n] then roots_are_OK := false; end if; end if; if roots_are_OK then // The roots seem OK. We can continue. // We would like an upper bound on the minimum value // of new_h at its maxima, and a lower bound on the // maximum value of new_h at its minima. Then we // could take b_min to be the negative of the upper // bound (divided by coef), and b_max to be the // negative of the lower bound (divided by coef). // // The strategy: We already have the roots of h[n-1] // with accuracy 10^-digits, given as a list of // rational numbers r[0], ..., r[k]. We will // calculate the values new_h(r[i]). For each // approximate root r = r[i] let s be the // corresponding true root of h[n-1]. We can compute // an upper bound for the difference between new_h(r) // and new_h(s) by using the formula // new_h(r) = new_h(s) + (r-s)*h[n-1](s) // + (1/2)*(r-s)^2*h[n-2](t) // for some t lying between r and s. Note that // h[n-1](s) = 0 by definition, and that (r-s)^2 is // at most 10^(-2*digits) in absolute value. The // absolute value of t is at most // 2*root_q_high + 10^-digits // so we must bound the value of h[n-2] on numbers of // this size. But h[n-2] is (by assumption) a // polynomial all of whose roots are lie in the // interval [-2*sqrtq..2*sqrtq], so h[n-2](t) is // bounded by // (leading term of h[n-2]) * // (4*root_q_high + 10^-digits)^deg // where deg = degree(h[n-2]). // Finally, we should adjust our upper and lower // bounds to take account of the fact that the roots // of h[n] must lie in the Weil interval. This means // that we must have // const_min >= -new_h(2*root_q_high). // If n is even, we also have // const_min >= -new_h(-2*root_q_high) // while if n is odd then // const_max <= -new_h(-2*root_q_high) // Now, h[n-2] is the (g-n+2)-th derivative of a // monic polynomial of degree g, so... deg := n - 2; if n gt 2 then leadingterm := fact0 / fact[n-2]; else leadingterm := 1; end if; error_bound := (1/2) * tendigits[n]^2 * leadingterm * (4*root_q_high + tendigits[n])^deg; // List the extrema in decreasing order. ordered_extrema := [rational_extrema[n-i] : i in [1..n-1]]; odd_extrema := [ordered_extrema[i] : i in [1..n-1 by 2]]; even_extrema := [ordered_extrema[i] : i in [2..n-1 by 2]]; // Now calculate bounds on the constant term of h[n], // and then translate these into bounds on b[n]. // First work on lower bounds. // We have to get a positive answer when we // evaluate h[n] at 2*rootq, so... const_min := Evaluate(-new_h,2*root_q_high); // Likewise for -2*rootq, if n is even... if n mod 2 eq 0 then const_min := Max(const_min, Evaluate(-new_h,-2*root_q_high)); end if; // And likewise at the even-numbered extrema. if n gt 2 then ee_bound := Max([Evaluate(-new_h,ex) : ex in even_extrema]) - error_bound; const_min := Max(const_min, ee_bound); end if; b_min := Ceiling(const_min/coef); // Now work on the upper bounds. const_max := Min([Evaluate(-new_h,ex) : ex in odd_extrema]) + error_bound; if n mod 2 eq 1 then const_max := Min(const_max, Evaluate(-new_h,-2*root_q_high)); end if; b_max := Floor(const_max/coef); else // The roots of h[n-1] are not OK. Give bad values // for the next range of b's, so that we stop // recursing. b_max := -1; b_min := 1; end if; end if; // Now we have a range of values of b[n] that give polynomials // with all roots in the Weil interval. We have to compute // the corresponding range of values of a[n], and then // restrict the range of b[n] so that the a[n] values are // non-negative and within the bounds we know from Oesterle. if b_min le b_max then b[n] := b_min; c[n] := InnerProduct(b, b_to_c[n]) + b_to_c_const[n]; p[n] := -n*c[n] - &+[c[i]*p[n-i] : i in [1..n-1]]; N[n] := q^n + 1 - p[n]; a[n] := (N[n] - &+[d*a[d] : d in Divisors(n) | d lt n])/n; h[n] := new_h + coef*b[n]; if a[n] lt 0 then b_min -:= a[n]; b[n] -:= a[n]; h[n] -:= coef*a[n]; c[n] -:= a[n]; p[n] +:= n*a[n]; N[n] -:= n*a[n]; a[n] := 0; end if; a_max := Floor((point_bound[n] - &+[d*a[d] : d in Divisors(n) | d lt n])/n); interval_max := a_max - a[n]; b_max := Min(b_max, b_min + interval_max); end if; if b_min le b_max then b_bound[n] := b_max; n +:= 1; decrement_flag := false; else n -:= 1; decrement_flag := true; end if; else // We are in the case where n > g. // This means that we have found a degree-g polynomial with // all of its roots in the Weil interval. // Now we have to process it, and add it to the list of // output. I := rec; process_isogeny_class(~I : verbose := verbose); classes cat:= [I]; if abort and not I`eliminated then return classes; end if; n -:= 1; decrement_flag := true; end if; end if; end while; // print stage_count; return classes; end function; procedure best_bound(q,g : killtime := 0, high_n:=0) // Given a prime power q and a genus g, set n to 1 more than the Oesterle // bound (or to 1 + high_n, if high_n is set to a nonzero value). Then // repeatedly decrement n until isogeny_classes(q,g,n) produces an isogeny // class that is not eliminated by our arguments. // Setting killtime to a positive value will kill the entire Magma // session after that many seconds. if killtime gt 0 then Alarm(killtime); end if; ob := Oesterle_bound(q,g); ib := Ihara_bound(q,g); sb := Serre_bound(q,g); if high_n ne 0 then n := 1 + high_n; else n := 1 + ob; end if; stop := false; repeat n := n - 1; printf "%o %o %o ", q, g, n; if n eq sb then printf "Weil-Serre "; elif n eq ib then printf "Ihara "; elif n eq ob then printf "Oesterle "; end if; z := isogeny_classes(q,g,n: abort:=true, verbose:=0); bad_ones := [I : I in z | not I`eliminated]; if #bad_ones eq 0 then print "Eliminated"; else I := bad_ones[1]; rwp := I`real_WP; fwp := Factorization(rwp); for i in [1..#fwp] do if i gt 1 then printf " * "; end if; g := fwp[i]; if g[1] eq Parent(g[1]).1 then printf "%o", g[1]; else printf "(%o)", g[1]; end if; if g[2] gt 1 then printf "^%o", g[2]; end if; end for; printf "\n"; stop := true; end if; until stop; end procedure; procedure factored_print(fac) // Utility function for printing out the factored form of // a polynomial on a single line. // The input is supposed to be a factored polynomial. for f in fac do if f[1] eq Parent(f[1]).1 then printf "%o", f[1]; else printf "(%o)", f[1]; end if; if f[2] gt 1 then printf "^%o", f[2]; end if; if f ne fac[#fac] then printf " * "; end if; end for; return; end procedure; function polynomial_divisors(f) // Given a polynomial f, return the list of its (monic) divisors. ff := Factorization(f); divisors := [Parent(f)!1]; for d in ff do p := d[1]; divisors cat:= [dd*p^i : dd in divisors, i in [1..d[2]]]; end for; return divisors; end function; function double_covers(I: verbose := false) // Given an isogeny class I, find all isogeny classes J such that // we can find no problem with the possibility of their being // a double cover C --> D of curves with Jac C in I and Jac D in J. // Return the possible J, together with the number of ramification // points of the double cover, the degree of the different, and the // number of rational points on D. If verbose is set to true, print // out the real Weil polynomial of J, the number of ramification points, // the degree of the different, and the number of rational points on D. // This function is intended to help guide searches for curves with // a given number of points. If one takes the isogeny classes that // come from isogeny_classes(q,g,N) and runs them through // double_covers(), the output will give suggestions for where // to search for double covers that give curves with N points. answer := []; II := I; // Make a copy that we can modify. divisors := polynomial_divisors(II`real_WP); q := Integers()!II`q; if IsEven(q) then // We are in characteristic 2. add_p_rank(~II); for h in divisors do if Degree(h) gt 0 and Degree(h) lt II`dim then J := rec; rest := Parent(h)!(II`real_WP / h); rr := Integers()!reduced_resultant(h,rest); if IsEven(rr) then // We might have a double cover. bool, reason := is_problem_with_double_cover(II,J); if not bool then add_p_rank(~J); add_places(~J); r1 := II`p_rank; r2 := J`p_rank; d1 := II`dim; d2 := J`dim; ram := (r1-1) - 2*(r2-1); degdiff := (2*d1-2) - 2*(2*d2-2); answer cat:= []; if verbose then factored_print(Factorization(J`real_WP)); printf " %o ram points, deg diff = %o, #points = %o\n", ram, degdiff, J`places[1]; end if; end if; end if; end if; end for; else // We are in odd characteristic. for h in divisors do if Degree(h) gt 0 and Degree(h) lt II`dim then J := rec; rest := Parent(h)!(II`real_WP / h); rr := Integers()!reduced_resultant(h,rest); if IsEven(rr) then // We might have a double cover. bool, reason := is_problem_with_double_cover(II,J); if not bool then add_places(~J); d1 := II`dim; d2 := J`dim; degdiff := (2*d1-2) - 2*(2*d2-2); ram := degdiff / 2; answer cat:= []; if verbose then factored_print(Factorization(J`real_WP)); printf " %o ram points, deg diff = %o, #points = %o\n", ram, degdiff, J`places[1]; end if; end if; end if; end if; end for; end if; return answer; end function;