# Revision history [back]

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])