@@ -524,6 +524,107 @@ def create_object(self, version, key, *, names=None, **kwds):
524
524
from .ell_generic import EllipticCurve_generic
525
525
return EllipticCurve_generic (R , x )
526
526
527
+ @staticmethod
528
+ def _eisenstein_series_e_eval (weight , tau , prec ):
529
+ r"""
530
+ Private method to evaluate `E_{2k}`. To be merged with modular form code later.
531
+
532
+ INPUT:
533
+
534
+ - prec -- precision in bits
535
+
536
+ OUTPUT:
537
+
538
+ Element of ``ComplexField(prec)`` equal to `E_{2k}(\tau)` where ``2k == weight``.
539
+
540
+ TESTS:
541
+
542
+ Example values::
543
+
544
+ sage: tau = CC(2/3*I+4/5)
545
+ sage: weight = 6
546
+
547
+ Evaluating using our method::
548
+
549
+ sage: EllipticCurve._eisenstein_series_e_eval(weight, tau, 53) # abs tol 1e-10
550
+ 2.06948373064822 + 9.23822630732235*I
551
+
552
+ Approximately evaluate using convergent sum::
553
+
554
+ sage: sum((a+b*tau)^-weight for a in (-50..50) for b in (-50..50) if gcd(a, b)==1)/2 # abs tol 1e-10
555
+ 2.06948373572619 + 9.23822632418512*I
556
+
557
+ Approximately evaluate using `q`-expansion::
558
+
559
+ sage: M4 = EisensteinForms(Gamma0(1), weight=weight)
560
+ sage: e4 = M4.0
561
+ sage: e4.qexp(prec=50).polynomial()(exp(2*pi*I * tau).n(200)) # abs tol 1e-60
562
+ 2.0694837306482189422343628966349567015465461257928410093613 + 9.2382263073223530637169893909058439360384065238856673719976*I
563
+
564
+ Higher precision::
565
+
566
+ sage: EllipticCurve._eisenstein_series_e_eval(weight, tau, 200) # abs tol 1e-60
567
+ 2.0694837306482189422343628966349567015465461257928410093613 + 9.2382263073223530637169893909058439360384065238856673719976*I
568
+ """
569
+ from sage .libs .pari .all import pari
570
+ from sage .rings .complex_mpfr import ComplexField
571
+ mf = pari .mfinit ([1 ,weight ],3 )
572
+ [f ] = pari .mfbasis (mf )
573
+ old_prec = pari .get_real_precision_bits ()
574
+ pari .set_real_precision_bits (prec )
575
+ F = ComplexField (prec )
576
+ result = pari .mfeval (mf , f , F (tau ), precision = prec )/ pari .mfcoef (f , 0 )
577
+ # for some reason precision=prec passed above doesn't work, thus need pari.set_real_precision_bits(prec)
578
+ pari .set_real_precision_bits (old_prec )
579
+ return F (result )
580
+
581
+ @staticmethod
582
+ def _eisenstein_series_g_eval (weight , tau , prec ):
583
+ r"""
584
+ Similar to :meth:`_eisenstein_series_e_eval`, but evaluates `G_{2k}`.
585
+
586
+ TESTS::
587
+
588
+ sage: tau = CC(2/3*I+4/5)
589
+ sage: weight = 6
590
+ sage: EllipticCurve._eisenstein_series_g_eval(weight, tau, 53) # abs tol 1e-10
591
+ 4.21074983052932 + 18.7968908775932*I
592
+ """
593
+ from sage .functions .transcendental import zeta
594
+ e = EllipticCurve ._eisenstein_series_e_eval (weight , tau , prec )
595
+ return e .parent ()(zeta (weight ) * 2 * e )
596
+
597
+ @staticmethod
598
+ def from_period_lattice_basis (w1 , w2 ):
599
+ r"""
600
+ Construct an elliptic curve from a period lattice basis.
601
+
602
+ INPUT:
603
+
604
+ - ``w1``, ``w2`` -- basis elements, must be element of ``ComplexField(prec)`` for some ``prec``
605
+
606
+ OUTPUT:
607
+
608
+ ``EllipticCurve`` instance with base ring ``ComplexField(prec)``
609
+
610
+ EXAMPLES::
611
+
612
+ sage: F = ComplexField(53)
613
+ sage: w1 = F(1)
614
+ sage: w2 = F(I * sqrt(7))
615
+ sage: E = EllipticCurve.from_period_lattice_basis(w1, w2)
616
+ sage: E.period_lattice().basis() # abs tol 1e-10
617
+ (-2.64575131106483*I, -1.00000000000000)
618
+ """
619
+ F = w1 .parent ()
620
+ if F != w2 .parent ():
621
+ raise ValueError ("basis elements must have the same parent" )
622
+ prec = F .precision ()
623
+ tau = w2 / w1
624
+ g2 = - 60 * EllipticCurve ._eisenstein_series_g_eval (4 , tau , prec )/ w1 ** 4
625
+ g3 = - 140 * EllipticCurve ._eisenstein_series_g_eval (6 , tau , prec )/ w1 ** 6
626
+ return EllipticCurve (F , [(g2 / 4 ).real (), (g3 / 4 ).real ()])
627
+
527
628
528
629
EllipticCurve = EllipticCurveFactory ('sage.schemes.elliptic_curves.constructor.EllipticCurve' )
529
630
0 commit comments