Attachment 'intptsanf.m'

Download

   1 ///////////////////////////////////////////////////////////////////////////////
   2 // Computing all integral points on elliptic curves over number fields
   3 // Based on Smart & Stephens' paper (Math. Proc. Camb. Phil. Soc. 122 (1997),
   4 // pp. 9-16) with some modification
   5 //
   6 // Written by Thotsaphon Thongjunthug, BSc(Hons)
   7 // Last update: 14 May 2009
   8 //
   9 // This package requires some functions on Silverman's bound implemented in
  10 // John Cremona's "nfhtbound.m", available freely on his webpage
  11 // http://www.warwick.ac.uk/~masgaj/ftp/progs/magma/index.html
  12 ///////////////////////////////////////////////////////////////////////////////
  13 
  14 
  15 ///////////////////////////////////////////////////////////////////////////////
  16 // Commands:
  17 // IntegralPoints() : Find all integral points on elliptic curves over
  18 //                    number fields
  19 ///////////////////////////////////////////////////////////////////////////////
  20 
  21 
  22 // Declare printing verbose
  23 // 0 = return result only, no detail will be printed
  24 // 1 = minimal amount of details shown
  25 // 2 = all details (e.g. values of all constants) shown (for debugging only) 
  26 declare verbose Detail, 2;
  27 
  28 
  29 ///////////////////////////////////////////////////////////////////////////////
  30 // Constants for an upper bound on linear form in logarithm
  31 // The indices of c are as in Smart & Stephens' paper
  32 ///////////////////////////////////////////////////////////////////////////////
  33 
  34 // Compute constant c3
  35 // Input: L = a sequence of points on elliptic curves over number field
  36 function c3(L)
  37   M := Eigenvalues(HeightPairingMatrix(L));
  38   M := SetToSequence(M);
  39   M := [m[1] : m in M]; // ignore multiplicity
  40   M := Minimum(M); // least eigenvalue
  41   return M;
  42 end function;
  43 
  44 // Compute constant c6
  45 // Input: E = elliptic curve over real/complex numbers
  46 function c6(E)
  47   P<x> := PolynomialRing(ComplexField());
  48   C4, C6 := Explode(cInvariants(E));
  49   f := x^3 - (P! C4/48)*x - (P! C6/864);
  50   R := Roots(f);
  51   R := [r[1] : r in R]; // ignore multiplicity
  52   R := [Abs(r) : r in R];
  53   R := 2 * Maximum(R);
  54   return R;
  55 end function;
  56 
  57 // Compute constant c8, and the periods of the lattice L where E(C) = C/L
  58 // This requires complex periods of elliptic curves over C
  59 // Require: complexell.m
  60 // Input: E = elliptic curve over real/complex numbers
  61 function c8(E)
  62   org_w1, org_w2 := Explode(ComplexPeriods(E));
  63   // Apply transformation by SL(2,Z) so that tau = w2/w1 is in the
  64   // fundamental domain
  65   _, A := ReducedTau(org_w2 / org_w1); // require "complexell.m"
  66   w2 := A[1,1]*org_w2 + A[1,2]*org_w1;
  67   w1 := A[2,1]*org_w2 + A[2,2]*org_w1;
  68   L := [Abs(w) : w in [w1, w2, w1+w2]];
  69   L := Maximum(L);
  70   return L, [w1, w2];
  71 end function;
  72 
  73 // Compute absolute logarithmic height of an element in n-projective space
  74 // over a number field K
  75 // Input: X = a sequence of elements in a number field K  
  76 function AbsLogHeight(X)
  77   // X cannot be zero vector
  78   if #X eq #[x : x in X | x eq 0] then
  79     error "AbsLogHeightExt: X cannot be zero vector";
  80   end if;
  81   
  82   // Find all prime ideal that divides some denominators of x_i
  83   I := {};
  84   K := Parent(X[1]); // assume each x_i is in the same field
  85   O := RingOfIntegers(K);
  86   for x in X do
  87     den := O ! Denominator(x);
  88     L := Decomposition(den);
  89     L := {l[1] : l in L}; // ignore multiplicity
  90     I := I join L;
  91   end for;
  92   
  93   h := 0;
  94   // Non-archimedean contributions
  95   for p in I do
  96     M := [Rationals()| ];
  97     for x in X do
  98       if x eq 0 then
  99         Append(~M, 0);
 100       else
 101         Append(~M, Norm(p)^(-Valuation(x, p)));
 102       end if;
 103     end for;
 104     M := Maximum(M);
 105     M := Log(M);
 106     h +:= M;
 107   end for;
 108   
 109   // Archimedean contributions
 110   s1, s2 := Signature(K);
 111   // M = [log max(|x_1|_v,..., |x_n|_v) : v in M_K]
 112   M := [];
 113   for x in X do
 114     C := Conjugates(x);
 115     newC := [];
 116     // Real embedding contributions
 117     for i := 1 to s1 do
 118       Append(~newC, Abs(C[i]));
 119     end for;
 120     // Complex embedding contributions
 121     for i := 1 to s2 do
 122       Append(~newC, Abs(C[s1+(2*i-1)])^2);
 123     end for;
 124 
 125     if #M eq 0 then
 126       M := newC;
 127     else
 128       for i := 1 to (s1+s2) do
 129         if newC[i] gt M[i] then
 130           M[i] := newC[i];
 131         end if;
 132       end for;
 133     end if;
 134   end for;
 135   M := [Log(m) : m in M];
 136   
 137   // Overall absolute logarithmic height
 138   h +:= (&+M);
 139   h /:= Degree(K);
 140   return h;
 141 end function;
 142 
 143 
 144 ///////////////////////////////////////////////////////////////////////////////
 145 // Constants for David's lower bound on linear form in logarithm
 146 // Notation used as in Appendix A of Smart's book
 147 // "The Algorithmic Resolution of Diophantine Equations", with c's being
 148 // replaced by d's
 149 ///////////////////////////////////////////////////////////////////////////////
 150 
 151 // Compute the "height" of elliptic curve
 152 // Input: E = elliptic curve over number field
 153 function h_E(E)
 154   j := jInvariant(E);
 155   C4, C6 := Explode(cInvariants(E));
 156   g2 := C4/12;
 157   g3 := C6/216;
 158   m := Maximum([1, AbsLogHeight([1, g2, g3]), AbsLogHeight([1, j])]);
 159   return m;
 160 end function;
 161 
 162 // Compute the list of modified height of a point P in E(K)
 163 // according to embeddings
 164 // Input: E = elliptic curve over a number field K
 165 //        P = a point in E(K)
 166 //        ElogEmbedP = elliptic logarithm of P when embedded in some
 167 //                     embedding
 168 //        D7 = constant d7 (depending on embedding)
 169 function h_m(E, P, ElogEmbedP, D7)
 170   K := BaseRing(E);
 171   L := [Height(P), h_E(E), D7/Degree(K)*Abs(ElogEmbedP)^2];
 172   L := Maximum(L);
 173   return L;
 174 end function;
 175 
 176 // Compute two extra h_m's based on the two periods
 177 // Similar to h_m, but now ElogEmbedP becomes a period of the fundamental
 178 // parallelogram of E(C) for some embedding
 179 // Input: E = elliptic curve over a number field
 180 //        Periods = a sequence of two periods of the fundamental
 181 //                  parallelogram of E(C) for some embbeding
 182 //        D7 = constant d7 (depending on embedding)
 183 function Extra_h_m(E, Periods, D7)
 184   D := Degree(BaseRing(E));
 185   h := h_E(E);
 186   tmp1 := Maximum([0, h, D7/D*Abs(Periods[1])^2]);
 187   tmp2 := Maximum([0, h, D7/D*Abs(Periods[2])^2]);
 188   return [tmp1, tmp2];
 189 end function;
 190 
 191 // Compute constant d8
 192 // Input: E = elliptic curve over a number field K
 193 //        L = a sequence of points in E(K) (e.g. Mordell-Weil basis)
 194 //        Elog = a sequence of (pre-computed) elliptic logarithm of
 195 //               each point in L at a fixed embedding
 196 //        Periods = a sequence of two periods of the fundamental
 197 //                  parallelogram of E(C) for some embbeding
 198 //        D7 = constant d7 (depending on embedding)
 199 function d8(E, L, Elog, Periods, D7)
 200   C := [Exp(1) * h_E(E)];
 201   D := Degree(BaseRing(E));
 202   for i := 1 to #L do
 203     Append(~C, h_m(E, L[i], Elog[i], D7) / D);
 204   end for;
 205   C := C cat [t / D : t in Extra_h_m(E, Periods, D7)];
 206   C := Maximum(C);
 207   return C;
 208 end function;
 209 
 210 // Compute constant d9
 211 // Input: E = elliptic curve over a number field
 212 //        L = a sequence of points in E(K) (e.g. Mordell-Weil basis)
 213 //        Elog = a sequence of (pre-computed) elliptic logarithm of
 214 //               each point in L at a fixed embedding
 215 //        Periods = a sequence of two periods of the fundamental
 216 //                  parallelogram of E(C) for some embbeding
 217 //        D7 = constant d7 (depending on embedding)
 218 function d9(E, L, Elog, Periods, D7)
 219   D := Degree(BaseRing(E));
 220   C := [];
 221   for i := 1 to #L do
 222     tmp := Exp(1) * Sqrt(D * h_m(E, L[i], Elog[i], D7) / D7);
 223     tmp /:= Abs(Elog[i]);
 224     C[i] := tmp;
 225   end for;
 226 
 227   // Take minimum among extra_h_m
 228   Ehm := Extra_h_m(E, Periods, D7);
 229   tmp1 := Exp(1) * Sqrt(D*Ehm[1]/D7) / Abs(Periods[1]);
 230   tmp2 := Exp(1) * Sqrt(D*Ehm[2]/D7) / Abs(Periods[2]);
 231   C := C cat [tmp1, tmp2];
 232   C := Minimum(C);
 233   return C;
 234 end function;
 235 
 236 // Compute constant d10
 237 // Input: E = elliptic curve over a number field
 238 //        L = a sequence of points in E(K) (e.g. Mordell-Weil basis)
 239 //        Elog = a sequence of (pre-computed) elliptic logarithm of
 240 //               each point in L at a fixed embedding
 241 //        Periods = a sequence of two periods of the fundamental
 242 //                  parallelogram of E(C) for some embbeding
 243 //        D7 = constant d7 (depending on embedding)
 244 function d10(E, L, Elog, Periods, D7)
 245   D := Degree(BaseRing(E));
 246   n := #L+2;
 247   scalar := 2 * 10^(8 + 7*n) * (2/Exp(1))^(2*n^2);
 248   scalar *:= (n+1)^(4*n^2 + 10*n) * D^(2*n + 2);
 249   scalar *:= (Log(d9(E, L, Elog, Periods, D7)))^(-2*n-1);
 250   for i := 1 to #L do
 251     scalar *:= h_m(E, L[i], Elog[i], D7);
 252   end for;
 253   scalar *:= &*(Extra_h_m(E, Periods, D7));   
 254   return scalar;
 255 end function;
 256 
 257 // Compute the right-hand side of the Principal Inequality
 258 // Input: D   = Degree(K), K = number field
 259 //        r   = rank(E(K))
 260 //        C9  = constant c9
 261 //        C10 = constant c10
 262 //        D9  = constant d9
 263 //        D10 = constant d10
 264 //        h   = h_E(E), E = elliptic curve over K
 265 //        Q   = initial bound for the coefficients of P_i's, where
 266 //              P_i's are in the Mordell-Weil basis
 267 function RHS(D, r, C9, C10, D9, D10, h, Q, expTors)
 268   bound := (Log(Log(Q*r*expTors)) + h + Log(D*D9))^(r+3);
 269   bound *:= D10*(Log(Q*r*expTors) + Log(D*D9));
 270   bound +:= Log(C9*expTors);
 271   bound /:= C10;
 272   return bound;
 273 end function;
 274 
 275 // Approximate initial bound on Q = max_{1\le i\le r}{|q_i|}
 276 // Input: D   = Degree(K), where K = number field
 277 //        r   = rank of E(K)
 278 //        Q0  = constant Q0 (in S&S paper, this is called K0)
 279 //        C9  = constant c9
 280 //        C10 = constant c10
 281 //        D8  = constant d8 (from function d8())
 282 //        D9  = constant d9 (from function d9())
 283 //        D10 = constant d10 (from function d10())
 284 //        h   = h_E(E)
 285 //        expTors = exponent of the torsion subgroup of E(K)
 286 // Revised: 5 May 2009
 287 function InitialQ(D, r, Q0, C9, C10, D8, D9, D10, h, expTors)
 288   minQ := Maximum(Q0, Exp(D8));
 289   
 290   // Try to approximate Q such that Q^2 = RHS(Q) (i.e. Q makes both sides
 291   // of the Principal Inequality equal)
 292   // Firstly, set a guess for Q, say minQ + 1 (so that Q > minQ)
 293   // For simplicity, let's round Q up to the nearest power of 10
 294   Q := minQ + 1;
 295   x := Ceiling(Log(10, Q)); // x = log_10(Q)
 296 
 297   // Check if Q satisfies the Principal Inequality, i.e. if Q^2 < RHS(Q)
 298   // If so, repeat with the larger Q until we find the first Q that
 299   // violates the P.I.
 300   // N.B. This loop will eventually terminate 
 301   exp_OK := 0;   // the exponent that satisfies P.I.
 302   exp_fail := 0; // the exponent that fails P.I.
 303   while 10^(2*x) lt RHS(D, r, C9, C10, D9, D10, h, 10^x, expTors) do
 304     exp_OK := x; // Principal Inequality satisfied
 305     x *:= 2;     // double x, and retry
 306   end while;
 307   exp_fail := x; // x that fails the Principal Inequality
 308   
 309   // So now x = log_10(Q) must lie between exp_OK and exp_fail
 310   // Refine x further using "binary search"
 311   repeat
 312     x := Floor((exp_OK + exp_fail)/2);
 313     if 10^(2*x) ge RHS(D, r, C9, C10, D9, D10, h, 10^x, expTors) then
 314       exp_fail := x;
 315     else
 316       exp_OK := x;
 317     end if;
 318   until (exp_fail - exp_OK) le 1;
 319   return exp_fail; // over-estimate
 320 end function;
 321 
 322 // Reduce the bound Q by LLL reduction until no further improvement
 323 // is possible. This function initially requires high precision to
 324 // proceed, although this should be done automatically by now
 325 // Require: complexell.m
 326 // Input: EmbedE  = model of E embedded in some (complex) embedding
 327 //        EmbedL  = a sequence of points on EmbedE (e.g. points in the
 328 //                  Mordell-Weil basis when embedded into EmbedE)
 329 //        Elog    = a sequence of (pre-computed) elliptic logarithm of
 330 //                  each point in EmbedL
 331 //        C9      = constant c9
 332 //        C10     = constant c10
 333 //        Periods = sequence of the double periods of the fundamental
 334 //                  parallelogram associated to EmbedE
 335 //        expTors = exponent of the torsion subgroup of E(K), K = number field
 336 //        initQ   = initial guess for Q to be reduced by LLL
 337 function ReducedQ(EmbedE, EmbedL, Elog, C9, C10, Periods, expTors, initQ)
 338   w1, w2 := Explode(Periods);
 339   r := #EmbedL;  
 340   newQ := initQ;
 341 
 342   // Repeat LLL reduction until no further reduction is possible
 343   repeat
 344     Q := newQ;
 345     S := r*(Q^2)*(expTors^2);
 346     T := 3*r*Q*expTors/Sqrt(2);
 347 
 348     // Create the basis matrix
 349     C := 1;
 350     repeat
 351       C *:= Q^Ceiling((r+2)/2);  
 352       L := ZeroMatrix(Integers(), r+2, r+2);
 353       
 354       // Elliptic logarithm should have precision "suitable to" C
 355       // e.g. If C = 10^100, then Re(Elog[i]) should be computed
 356       // correctly to at least 100 decimal places
 357       pow10_C := Ceiling(Log(10, C));
 358       if pow10_C gt Precision(Elog[1]) then
 359 	vprint Detail, 2: 
 360 	  "Need higher precision, recompute elliptic logarithm ...";
 361         // Re-compute elliptic logarithm to the right precision
 362         Elog := [ComplexEllLog(EmbedE, P : Prec := pow10_C+10) : P in EmbedL];
 363         vprint Detail, 2: "Elliptic logarithm recomputed";
 364       end if;
 365       // Assign all non-zero entries
 366       for i := 1 to r do
 367         L[i,i] := 1;
 368         L[r+1, i] := Truncate(C*Re(Elog[i]));
 369         L[r+2, i] := Truncate(C*Im(Elog[i]));
 370       end for;
 371       L[r+1, r+1] := Truncate(C*Re(w1));
 372       L[r+1, r+2] := Truncate(C*Re(w2));
 373       L[r+2, r+1] := Truncate(C*Im(w1));
 374       L[r+2, r+2] := Truncate(C*Im(w2));
 375       L := Transpose(L); // In Magma, basis is spanned by row vector!
 376           
 377       // LLL reduction and constants
 378       L := LLL(L);
 379       b1 := L[1]; // 1st row of reduced basis
 380       // Norm(b1) = square of Euclidean norm
 381       lhs := 2^(-r-1)*Norm(b1) - S;
 382     until (lhs ge 0) and (Sqrt(lhs) gt T);
 383     
 384     newQ := ( Log(C*C9*expTors) - Log(Sqrt(lhs) - T) ) / C10;
 385     newQ := Floor(Sqrt(newQ));
 386     pow10 := Floor(Log(10, C));
 387     vprintf Detail, 2: "Choose C = %.4o x 10^%o. ", 1.*C/10^pow10, pow10;  
 388     vprintf Detail, 2: "After reduction, Q <= %o\n", newQ;
 389   until ((Q - newQ) le 1) or (newQ le 1);
 390   return newQ;
 391 end function;
 392 
 393 
 394 ///////////////////////////////////////////////////////////////////////////////
 395 // Main intrinsic functions
 396 ///////////////////////////////////////////////////////////////////////////////
 397 
 398 // Search for all integral points on elliptic curves over number fields
 399 // within a given bound
 400 // Input:    E = elliptic curve over a number field K
 401 //           L = a sequence of points in the Mordell-Weil basis for E(K)
 402 //           Q = a maximum for the absolute bound on all coefficients
 403 //               in the linear combination of points in L
 404 // Output:  S1 = sequence of all integral points on E(K) modulo [-1]
 405 //          S2 = sequence of tuples representing the points as a
 406 //               linear combination of points in L
 407 // Option: tol = tolerance used for checking integrality of points.
 408 //               (Default = 0 - only exact arithmetic will be performed)
 409 intrinsic IntegralPoints(E::CrvEll, L::[PtEll], Q::RngIntElt : tol := 0) ->
 410   SeqEnum, SeqEnum
 411 {Given an elliptic curve E over a number field, its Mordell-Weil basis L, and a positive integer Q, return the sequence of all integral points modulo [-1] of the form P = q_1*L[1] + ... + q_r*L[r] + T with some torsion point T and |q_i| <= Q, followed by a sequence of tuple sequences representing the points as a linear combination of points. An optional tolerance may be given to speed up the computation when checking integrality of points.}
 412 
 413   // Check input validity
 414   require IsNumberField(BaseRing(E)):
 415     "Elliptic curve must be defined over a number field";
 416   require tol ge 0: "Tolerance must be non-negative";
 417 
 418   // Find the generators of the torsion subgroup of E(K)
 419   Tors, map := TorsionSubgroup(E);
 420   expTors := Exponent(Tors);
 421   G := Generators(Tors);
 422   Tors := [map(g) : g in G];   // each generator of E(K)_tors
 423   OrdG := [Order(g) : g in G]; // order of each generator
 424 
 425   if (#L eq 0) and (#Tors eq 0) then
 426     return [], [];
 427   end if;
 428 
 429   // Create all possible r+#Tors-tuples
 430   r := #L; // r = rank of E(K)
 431   C := [0 : i in [1..(r + #Tors)]];
 432   ListC := [];
 433   for i := 0 to Q do
 434     C[1] := i;
 435     Append(~ListC, C);
 436   end for;
 437 
 438   for i := 2 to r do
 439     tmp := [];
 440     for j := 1 to Q do
 441       for l in ListC do
 442         tup := l;
 443         tup[i] := j;
 444         Append(~tmp, tup);
 445 
 446         // Avoid having its negative in the list
 447         // Only use when all previous entries in tuple are zero
 448         for k := 1 to i-1 do
 449           if tup[k] ne 0 then
 450             tup[i] := -j;
 451             Append(~tmp, tup);
 452             break;
 453           end if;
 454         end for;
 455 
 456       end for;
 457     end for;
 458     ListC := ListC cat tmp;
 459   end for;
 460 
 461   // Add torsion point, if any
 462   if #Tors ne 0 then
 463     for i := 1 to #Tors do
 464       tmp := [];
 465       for j := 1 to (OrdG[i]-1) do
 466         for l in ListC do
 467           tup := l;
 468           tup[r+i] := j;
 469           Append(~tmp, tup);
 470         end for;
 471       end for;
 472       ListC := ListC cat tmp;
 473     end for;
 474   end if;
 475   Remove(~ListC, 1); // remove point at infinity
 476 
 477   L := L cat Tors;
 478   vprint Detail, 2: "Generators = ", L;
 479   PtsList := [];
 480   CoeffList := [];
 481   
 482   // Skip the complex arithmetic and only perform exact arithmetic if tol = 0
 483   if tol eq 0 then
 484     vprint Detail : "Exact arithmetic";
 485     for l in ListC do
 486       P := &+[l[i]*L[i] : i in [1..#L]];
 487       if IsIntegral(P[1]) and IsIntegral(P[2]) then
 488         vprintf Detail: "%o ---> %o\n", l, P;
 489         Append(~PtsList, P);
 490         TupList := [ <L[i], l[i]> : i in [1..#L] | l[i] ne 0 ];
 491         Append(~CoeffList, TupList);
 492       end if;
 493     end for;
 494     vprint Detail: "*"^45;
 495     return PtsList, CoeffList;
 496   end if;
 497 
 498   // Suggested by John Cremona
 499   // Point search. This is done via arithmetic on complex points on each
 500   // embedding of E. Exact arithmetic will be carried if the resulting
 501   // complex points are "close" to being integral, subject to some tolerance
 502   
 503   // Embed each generator of the torsion subgroup
 504   X := [Conjugates(P[1]) : P in (L cat Tors)];
 505   Y := [Conjugates(P[2]) : P in (L cat Tors)];
 506   // Create all embeddings of E
 507   K := BaseRing(E);
 508   s1, s2 := Signature(K);
 509   a1, a2, a3, a4, a6 := Explode(aInvariants(E));
 510   a1 := Conjugates(a1);
 511   a2 := Conjugates(a2);
 512   a3 := Conjugates(a3);
 513   a4 := Conjugates(a4);
 514   a6 := Conjugates(a6);
 515   EmbedEList := [EllipticCurve([a1[j], a2[j], a3[j], a4[j], a6[j]]): j in 
 516     [1..(s1+2*s2)]];
 517 
 518   // Set tolerance - This should be larger than 10^(-current precision) to
 519   // avoid missing any integral points. Too large tolerance will slow the
 520   // computation, too small tolerance may lead to missing some integral points.
 521   // This is now made as an option.
 522   vprint Detail: "Tolerance = ", tol * 1.;
 523   
 524   // Create the matrix containing all embeddings of the integral basis of K
 525   // as its columns
 526   IntBasis := IntegralBasis(K); 
 527   B := Matrix([Conjugates(a) : a in IntBasis]);
 528   // Note that B is always invertible, so we can take its inverse
 529   B := B^(-1);
 530   
 531   // Embeddings of each point in L
 532   // Format: [[P1 ... P1], [P2 ... P2], ...]
 533   EmbedLList := [];
 534   for i := 1 to (r+#Tors) do
 535     EmbedLi := [];
 536     for j := 1 to (s1+2*s2) do
 537       P_i := Points(EmbedEList[j], X[i][j])[1];
 538       // Choose the right sign for the y-coordinate
 539       if (Y[i][j] ne 0) and (Re(P_i[2]/Y[i][j]) lt 0) then
 540         P_i := -P_i;
 541       end if;
 542       Append(~EmbedLi, P_i);
 543     end for;
 544     Append(~EmbedLList, EmbedLi);
 545   end for;
 546 
 547   // Point search
 548   for l in ListC do
 549     // Compute P by complex arithmetic for every embedding
 550     EmbedPList := [E![0,1,0] : E in EmbedEList];
 551     for j := 1 to (s1+2*s2) do
 552       EmbedPList[j] := &+[l[i]*EmbedLList[i][j] : i in [1..(r + #Tors)]];
 553     end for;
 554 
 555     // Check if the x-coordinate of P is "close to" being integral
 556     // If so, compute P exactly and check if it is integral; skip P otherwise
 557     XofP := Matrix([[P[1] : P in EmbedPList]]);
 558     // Write x(P) w.r.t. the integral basis of (K)
 559     // Due to the floating arithmetic, some entries in LX may have very tiny
 560     // imaginary part, which can be thought as zero
 561     LX := XofP * B;
 562     LX := [Abs( Re(LX[1,i]) - Round(Re(LX[1,i])) ): i in [1..#IntBasis]];
 563     LX := &and[dx lt tol : dx in LX];
 564     if not LX then
 565       // x-coordinate of P is not integral, skip P
 566       continue;
 567     end if;
 568 
 569     // Now check P by exact arithmetic
 570     // Add P and the list of tuples representing P into the list
 571     // if P is integral
 572     P := &+[l[i]*L[i] : i in [1..#L]];
 573     if IsIntegral(P[1]) and IsIntegral(P[2]) then
 574       vprintf Detail: "%o ---> %o\n", l, P;
 575       Append(~PtsList, P);
 576       TupList := [ <L[i], l[i]> : i in [1..#L] | l[i] ne 0 ];
 577       Append(~CoeffList, TupList);
 578     end if;
 579   end for;
 580   vprint Detail: "*"^45;
 581   return PtsList, CoeffList;
 582 end intrinsic;
 583 
 584 // Compute all integral points on elliptic curve over a number field
 585 // This function simply computes a suitable bound Q, and return
 586 // IntegralPoints(E, L, Q : tol := ...). 
 587 // Input :   E = elliptic curve over a number field K
 588 //           L = a sequence of points in the Mordell-Weil basis for E(K)
 589 // Output:  S1 = sequence of all integral points on E(K) modulo [-1]
 590 //          S2 = sequence of tuples representing the points as a
 591 //               linear combination of points in L
 592 // Option: tol = tolerance used for checking integrality of points.
 593 //               (Default = 0 - only exact arithmetic will be performed) 
 594 intrinsic IntegralPoints(E::CrvEll, L::[PtEll] : tol := 0) -> SeqEnum, SeqEnum
 595 {Given an elliptic curve over a number field and its Mordell-Weil basis, return the sequence of all integral points modulo [-1], followed by a sequence of tuple sequences representing the points as a linear combination of points. An optional tolerance may be given to speed up the computation when checking integrality of points. (This function simply computes a suitable Q and call IntegralPoints(E, L, Q: tol := ...)}
 596 
 597   // Check input validity
 598   require IsNumberField(BaseRing(E)):
 599     "Elliptic curve must be defined over a number field";
 600   require tol ge 0:
 601     "Tolerance must be non-negative";
 602 
 603   if #L eq 0 then
 604     return IntegralPoints(E, [], 0 : tol := tol);
 605   end if;
 606 
 607   a1, a2, a3, a4, a6 := Explode(aInvariants(E));
 608 
 609   // Embed E into various (real/complex) embeddings
 610   a1 := Conjugates(a1);
 611   a2 := Conjugates(a2);
 612   a3 := Conjugates(a3);
 613   a4 := Conjugates(a4);
 614   a6 := Conjugates(a6);
 615   K := BaseRing(E);
 616   s1, s2 := Signature(K);
 617   b2 := Conjugates(bInvariants(E)[1]);
 618   pi := Pi(RealField());
 619 
 620   // Embed generators in the Mordell-Weil basis
 621   X := [Conjugates(P[1]) : P in L];
 622   Y := [Conjugates(P[2]) : P in L];
 623   
 624   // Find the generators of the torsion subgroup of E(K)
 625   Tors, map := TorsionSubgroup(E);
 626   expTors := Exponent(Tors);
 627   G := Generators(Tors);
 628   Tors := []; OrdG := [];
 629   for g in G do
 630     Append(~Tors, map(g));   // torsion point
 631     Append(~OrdG, Order(g)); // order of torsion point
 632   end for;
 633   
 634   // Global constants (independent to the embedding of E)
 635   C2 := -SilvermanLowerHeightBound(E); // require "nfhtbound.m"
 636   C3 := c3(L);
 637   h := h_E(E);
 638   vprint Detail, 2: "Global constants";
 639   vprintf Detail, 2: "c2 = %.4o\n", C2;
 640   vprintf Detail, 2: "c3 = %.4o\n", C3;
 641   vprintf Detail, 2: "h_E = %.4o\n", h;
 642   vprint Detail, 2: "-"^45;
 643   
 644   Q := [];
 645   // Find the most reduced bound on each embedding of E
 646   // But first let's adjust the index
 647   for i := 1 to (s1+s2) do
 648     if i le s1 then
 649       j := i;
 650       nv := 1;
 651       vprintf Detail, 2: "Real embedding #%o\n", j; 
 652     else
 653       j := s1 + (2*(i-s1)-1);
 654       nv := 2;
 655       vprintf Detail, 2: "Complex embedding #%o\n", i-s1; 
 656     end if;
 657     
 658     // Create complex embedding of E
 659     ee := EllipticCurve([a1[j], a2[j], a3[j], a4[j], a6[j]]);
 660 
 661     // Embedding of all points in Mordell-Weil basis
 662     // Find complex elliptic logarithm of each embedded point
 663     // Let's set precision initially to, say, 1000
 664     EmbedL := [[X[i][j], Y[i][j]] : i in [1..#L]];
 665     Elog := [ComplexEllLog(ee, P: Prec := 1000) : P in EmbedL];
 666     // Local constants (depending on embedding)
 667     // C9, C10 are used for the upper bound on the linear form in logarithm
 668     C4 := C3 * Degree(K) / (nv*(s1+s2));
 669     vprintf Detail, 2: "c4 =  %.4o\n", C4;
 670     C5 := C2 * Degree(K) / (nv*(s1+s2));
 671     vprintf Detail, 2: "c5 = %.4o\n", C5;
 672     C6 := c6(ee);
 673     vprintf Detail, 2: "c6 = %.4o\n", C6;
 674     delta := 1 + (nv-1)*pi;
 675     C8, Periods := c8(ee);
 676     vprintf Detail, 2: "c8 = %.4o\n", C8;
 677     C7 := 8*(delta^2) + (C8^2)*Abs(b2[j])/12;
 678     vprintf Detail, 2: "c7 = %.4o\n", C7;
 679     C9 := C7*Exp(C5/2);
 680     vprintf Detail, 2: "c9 = %.4o\n", C9;
 681     C10 := C4/2;
 682     vprintf Detail, 2: "c10 = %.4o\n", C10;
 683     Q0 := Sqrt( ( Log(C6+Abs(b2[j])/12) + C5) / C4 );
 684     vprintf Detail, 2: "Q0 = %.4o\n", Q0;
 685 
 686     // Constants for David's lower bound on the linear form in logarithm
 687     w1, w2 := Explode(Periods); // N.B. periods are already in "standard" form
 688     D7 := 3*pi / ((Abs(w2)^2) * Im(w2/w1));
 689     D8 := d8(E, L, Elog, Periods, D7);
 690     D9 := d9(E, L, Elog, Periods, D7);
 691     D10 := d10(E, L, Elog, Periods, D7);
 692     vprintf Detail, 2: "d7 =  %.4o\n", D7;
 693     vprintf Detail, 2: "d8 = %.4o\n", D8;
 694     vprintf Detail, 2: "d9 = %.4o\n", D9;
 695     vprintf Detail, 2: "d10 = %.4o\n", D10;
 696     
 697     // Find the reduced bound for the coefficients in the linear
 698     // logarithmic form
 699     initQ := InitialQ(Degree(K), #L, Q0, C9, C10, D8, D9, D10, h, expTors);
 700     vprintf Detail, 2: "Initial Q <= 10^%o\n", initQ;
 701     initQ := 10^initQ;
 702     Append(~Q, ReducedQ(ee, EmbedL, Elog, C9, C10, Periods, expTors, initQ));
 703     vprint Detail, 2: "-"^45;
 704   end for;
 705   Q := Maximum(Q);
 706   vprintf Detail: "Maximum absolute bound on coefficients = %o\n", Q;  
 707   return IntegralPoints(E, L, Q : tol := tol);
 708 end intrinsic;

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.