1 | initial version |
I think the following is needed, notations slightly changed, but in the same spirit:
p = 13
r = 5
F1 = GF(p)
R1.<X> = F1[]
F4.<c> = GF( p** 4 , modulus = X^4 - 2 )
R4.<Y> = F4[]
F16.<v> = F4.extension( X^4 - c )
b = 1/c
print "2b^4 = %s" % ( 2*b^4 )
print "v^4 = %s" % ( v^4 )
E1 = EllipticCurve( F1, [1,0] )
E4 = EllipticCurve( F4, [1,0] ) # E1.change_ring( F4 )
EE4 = EllipticCurve( F4, [c,0] ) # the twist
D = E4.is_quartic_twist( EE4 )
# print E4 == E1.change_ring( F4 )
print "E4.is_quartic_twist( EE4 ) --> use %s" % D
# Possible twists with conjugates of c
for d in ( X^4-2 ).roots( ring=F, multiplicities=False ):
print "Twisting with d = %s" % d
Tw = E.quartic_twist( d )
print Tw
if EE.is_isomorphic( Tw ):
print "--> isomorphic to EE"
if E.is_isomorphic( Tw ):
print "--> isomorphic to E"
print
# Find the "exact value" for the twisting element
d = None
for u in F1:
if not u:
continue
Eu4 = E4.quartic_twist( u*c )
if Eu4 == EE4:
d = u*c
print "More exactly: Use quartic twist via d = %s" % ( u*c )
print
P = E1.gens()[0]
Q = k*P
Qx, Qy = Q.xy()
print "Consider the point Q = ", Q
print "E4( Q ) =", E4( Q )
E16 = E4.change_ring( F16 )
EE16 = EE4.change_ring( F16 )
print "EE16.point( ( Qx * v^2, Qy * v^3 ) ) =", EE16.point( ( Qx * v^2, Qy * v^3 ) )
Results:
2b^4 = 1
v^4 = c
E4.is_quartic_twist( EE4 ) --> use c
Twisting with d = 12*c
Elliptic Curve defined by y^2 = x^3 + 4*c*x over Finite Field in c of size 13^4
--> isomorphic to EE
Twisting with d = 8*c
Elliptic Curve defined by y^2 = x^3 + 7*c*x over Finite Field in c of size 13^4
--> isomorphic to EE
Twisting with d = 5*c
Elliptic Curve defined by y^2 = x^3 + 6*c*x over Finite Field in c of size 13^4
--> isomorphic to EE
Twisting with d = c
Elliptic Curve defined by y^2 = x^3 + 9*c*x over Finite Field in c of size 13^4
--> isomorphic to EE
More exactly: Use quartic twist via d = 3*c
Consider the point Q = (9 : 7 : 1)
E4( Q ) = (9 : 7 : 1)
EE16.point( ( Qx * v^2, Qy * v^3 ) ) = (9*v^2 : 7*v^3 : 1)
The for
loop done w.r.t. roots of two is not relevant for the question, but may support the answer.
Note that the twist is done programatically using the c_invariants
twist for c4
, as in the following lines delivered by E.quartic_twist??
c4,c6=self.c_invariants()
# E is isomorphic to [0,0,0,-27*c4,0]
assert c6==0
return EllipticCurve(K,[0,0,0,-27*c4*D,0])