trace of Heegner point

Skip to first unread message

Ahmed Matar

Feb 15, 2020, 1:37:16 AM2/15/20
to sage-nt
Sage has the ability to compute the Heegner points over ring class fields. I would like to compute the trace of the Heegner point defined over the Hilbert class field down to K. Apparently this is not implemented in sage, but coding it should be easy. However I'm having an issue with the code below

# Note that K=Q(sqrt(-56)) has class number 4
P_conj=P.conjugates_over_K()  #These are the 4 conjugates of the Heegner point P

P_trace should be the desired trace of P down to K. When one prints P_trace we see that it is a point in projective space whose 3rd coordinate is 1 so the 1st and second coordinates should be in K. However if we try P_trace[0].minpoly('x'), we get a polynomial of degree 4. What am I doing wrong?


kevin lui

Feb 16, 2020, 4:07:27 AM2/16/20
to sage-nt
I think this has to do with the fact that when you call `point_exact`, Sage is mapping sending all the conjugates to the same point in the Hilbert class field.

# As expected, only one conjugate is equal to the original.
[Q == P for Q in P_cong]
# Output: [True, False, False, False]

# Annoyingly, these are all equal.
[Q.point_exact() == P.point_exact() for Q in P_cong]
# Output: [True, True, True, True]

We can get around this by working numerically.

P_cong_lambda = [Q.map_to_complex_numbers() for Q in P_cong]
= sum(P_cong_lambda)
= E.period_lattice().elliptic_exponential(P_trace_lambda)
, Y, Z = P_trace_E_CC; P_trace_E_CC
# Output: (3.35714285714284 + 2.94598962112462e-14*I : -0.500000000000106 - 2.65352233041626*I : 1.00000000000000)

Now we can use `algdep` to get a point on in an imaginary quadratic field.

fX = algdep(X ,2); fX
# Output: 14*x - 47
= algdep(Y, 2); fY.disc().squarefree_part()
# Output: (2744*x^2 + 2744*x + 20007, -14)
-14 is also the squarefree part of -56 so that's a good sign! Now put this point on an elliptic curve.

L.<b> = NumberField(fY)
= E.change_ring(L)
([47/14, b, 1])

No errors so I think that's an actual point on E. I think there's a smart way to identify Y as a point on K=QQ(sqrt(-56)) but it's late and I'm blanking on it so I just left it in L.

John Cremona

Feb 16, 2020, 9:59:22 AM2/16/20
to sage-nt
How about this:

sage: E=EllipticCurve('75a1')
sage: P=E.heegner_point(-56)
sage: P1 = P.point_exact()
sage: K = P1[0].parent()
sage: E = P1.curve()
sage: G = K.automorphisms()
sage: def apply(sigma, pt):
....:     E = pt.curve()
....:     return E([sigma(c) for c in pt])

sage: sum([apply(sigma,P1) for sigma in G], 0)
(0 : 1 : 0)
sage: r56 = K(-56).sqrt()
sage: sum([apply(sigma,P1) for sigma in G if sigma(r56)==r56], 0)
(47/14 : 363763/587699796992*a^7 + 363763/41978556928*a^6 + 2404005/2998468352*a^5 + 80502545/10494639232*a^4 + 49062308611/146924949248*a^3 + 138252123705/73462474624*a^2 + 31053597881/18365618656*a - 9514261313/4591404664 : 1)

That last point is defined over Q(sqRT-56)):

sage: tP = sum([apply(sigma,P1) for sigma in G if sigma(r56)==r56], 0)
sage: tP[1].minpoly()
x^2 + x + 20007/2744

You received this message because you are subscribed to the Google Groups "sage-nt" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
To view this discussion on the web visit

Ahmed Matar

Feb 17, 2020, 11:47:49 AM2/17/20
to sage-nt
Thanks Kevin and John for your responses! Both codes work well
Reply all
Reply to author
0 new messages