Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jack4818
GitHub Repository: jack4818/Castryck-Decru-SageMath
Path: blob/main/Magma-Reference/richelot_aux.m
323 views
1
/*
2
This code was downloaded from https://homes.esat.kuleuven.be/~wcastryc/ on 3 August 2022
3
*/
4
5
function FromProdToJac(C, E, P_c, Q_c, P, Q, a)
6
Fp2 := BaseField(C);
7
R<x> := PolynomialRing(Fp2);
8
9
P_c2 := 2^(a-1)*P_c;
10
Q_c2 := 2^(a-1)*Q_c;
11
P2 := 2^(a-1)*P;
12
Q2 := 2^(a-1)*Q;
13
14
alp1 := P_c2[1];
15
alp2 := Q_c2[1];
16
alp3 := (P_c2 + Q_c2)[1];
17
bet1 := P2[1];
18
bet2 := Q2[1];
19
bet3 := (P2 + Q2)[1];
20
a1 := (alp3 - alp2)^2/(bet3 - bet2) + (alp2 - alp1)^2/(bet2 - bet1) + (alp1 - alp3)^2/(bet1 - bet3);
21
b1 := (bet3 - bet2)^2/(alp3 - alp2) + (bet2 - bet1)^2/(alp2 - alp1) + (bet1 - bet3)^2/(alp1 - alp3);
22
a2 := alp1*(bet3 - bet2) + alp2*(bet1 - bet3) + alp3*(bet2 - bet1);
23
b2 := bet1*(alp3 - alp2) + bet2*(alp1 - alp3) + bet3*(alp2 - alp1);
24
Deltalp := (alp1 - alp2)^2*(alp1 - alp3)^2*(alp2 - alp3)^2;
25
Deltbet := (bet1 - bet2)^2*(bet1 - bet3)^2*(bet2 - bet3)^2;
26
A := Deltbet*a1/a2;
27
B := Deltalp*b1/b2;
28
29
h := - (A*(alp2 - alp1)*(alp1 - alp3)*x^2 + B*(bet2 - bet1)*(bet1 - bet3)) *
30
(A*(alp3 - alp2)*(alp2 - alp1)*x^2 + B*(bet3 - bet2)*(bet2 - bet1)) *
31
(A*(alp1 - alp3)*(alp3 - alp2)*x^2 + B*(bet1 - bet3)*(bet3 - bet2));
32
33
t1 := -(A/B)*b2/b1;
34
t2 := (bet1*(bet3 - bet2)^2/(alp3 - alp2) + bet2*(bet1 - bet3)^2/(alp1 - alp3) + bet3*(bet2 - bet1)^2/(alp2 - alp1))/b1;
35
s1 := -(B/A)*a2/a1;
36
s2 := (alp1*(alp3 - alp2)^2/(bet3 - bet2) + alp2*(alp1 - alp3)^2/(bet1 - bet3) + alp3*(alp2 - alp1)^2/(bet2 - bet1))/a1;
37
38
Uff<u0, u1, v0, v1> := FunctionField(Fp2, 4);
39
A4<U0, U1, V0, V1> := AffineSpace(Fp2, 4); U := Parent(U0);
40
41
u0tilde := 1/u0;
42
u1tilde := u1/u0;
43
v0tilde := (u1*v0 - u0*v1)/u0^2;
44
v1tilde := (u1^2*v0 - u0*v0 - u0*u1*v1)/u0^2;
45
46
lamb1 := - (Deltbet/A^3)*v1tilde/(s1*u1tilde);
47
lamb2 := - (Deltalp/B^3)*v1/(t1*u1);
48
49
x1 := lamb1^2 + alp1 + alp2 + alp3 - s1*(u1tilde^2 - 2*u0tilde) - 2*s2;
50
y1 := -lamb1*(x1 - s2 + (u0tilde*v1tilde - u1tilde*v0tilde)*s1/v1tilde);
51
52
x2 := lamb2^2 + bet1 + bet2 + bet3 - t1*(u1^2 - 2*u0) - 2*t2;
53
y2 := -lamb2*(x2 - t2 + (u0*v1 - u1*v0)*t1/v1);
54
55
eq1 := U ! Numerator(x1 - P_c[1]);
56
eq2 := U ! Numerator(y1 - P_c[2]);
57
eq3 := U ! Numerator(x2 - P[1]);
58
eq4 := U ! Numerator(y2 - P[2]);
59
eq5 := 2*V0^2 - 2*V0*V1*U1 + V1^2*(U1^2 - 2*U0)
60
- 2*Coefficient(h, 0)
61
- (-U1)*Coefficient(h, 1)
62
- (U1^2 - 2*U0)*Coefficient(h, 2)
63
- (-U1^3 + 3*U0*U1)*Coefficient(h, 3)
64
- (U1^4 - 4*U1^2*U0 + 2*U0^2)*Coefficient(h, 4)
65
- (-U1^5 + 5*U1^3*U0 - 5*U1*U0^2)*Coefficient(h, 5)
66
- (U1^6 - 6*U1^4*U0 + 9*U1^2*U0^2 - 2*U0^3)*Coefficient(h, 6);
67
68
V := Scheme(A4, [eq1, eq2, eq3, eq4, eq5]);
69
70
// point with zero coordinates probably correspond to "extra" solutions, we should be left with 4 sols
71
// (code may fail over small fields)
72
73
realsols := [];
74
for D in Points(V) do
75
Dseq := Eltseq(D);
76
if not 0 in Dseq then
77
realsols cat:= [Dseq];
78
end if;
79
end for;
80
81
// print "Number of inverse images found:", #realsols, "(hopefully 4)";
82
83
J := Jacobian(HyperellipticCurve(h));
84
sol := Random(realsols);
85
D := elt<J | x^2 + sol[2]*x + sol[1], sol[4]*x + sol[3]>;
86
imPcP := 2*D;
87
88
// now for (Q_c, Q)
89
90
eq1 := U ! Numerator(x1 - Q_c[1]);
91
eq2 := U ! Numerator(y1 - Q_c[2]);
92
eq3 := U ! Numerator(x2 - Q[1]);
93
eq4 := U ! Numerator(y2 - Q[2]);
94
V := Scheme(A4, [eq1, eq2, eq3, eq4, eq5]);
95
realsols := [];
96
for D in Points(V) do
97
Dseq := Eltseq(D);
98
if not 0 in Dseq then
99
realsols cat:= [Dseq];
100
end if;
101
end for;
102
// print "Number of inverse images found:", #realsols, "(hopefully 4)";
103
sol := Random(realsols);
104
D := elt<J | x^2 + sol[2]*x + sol[1], sol[4]*x + sol[3]>;
105
imQcQ := 2*D;
106
107
return h, imPcP[1], imPcP[2], imQcQ[1], imQcQ[2];
108
end function;
109
110
function FromJacToJac(h, D11, D12, D21, D22, a)
111
R<x> := Parent(h);
112
Fp2 := BaseRing(R);
113
114
J := Jacobian(HyperellipticCurve(h));
115
D1 := elt<J | D11, D12>;
116
D2 := elt<J | D21, D22>;
117
118
G1 := (2^(a-1)*D1)[1];
119
G2 := (2^(a-1)*D2)[1];
120
G3 := h div (G1*G2);
121
122
delta := Matrix(Fp2, 3, 3, [Coefficient(G1, 0), Coefficient(G1, 1), Coefficient(G1, 2),
123
Coefficient(G2, 0), Coefficient(G2, 1), Coefficient(G2, 2),
124
Coefficient(G3, 0), Coefficient(G3, 1), Coefficient(G3, 2)]);
125
delta := Determinant(delta)^(-1);
126
127
H1 := delta*(Derivative(G2)*G3 - G2*Derivative(G3));
128
H2 := delta*(Derivative(G3)*G1 - G3*Derivative(G1));
129
H3 := delta*(Derivative(G1)*G2 - G1*Derivative(G2));
130
131
hnew := H1*H2*H3;
132
Jnew := Jacobian(HyperellipticCurve(hnew));
133
134
// now compute image points
135
// first the point [D11, D12]:
136
137
u0 := Coefficient(D11, 0);
138
u1 := Coefficient(D11, 1);
139
v0 := Coefficient(D12, 0);
140
v1 := Coefficient(D12, 1);
141
S<x1,y1,y2,x2> := PolynomialRing(Fp2, 4);
142
pr := hom<S -> R | 0, 0, 0, x>;
143
144
eq1 := x1^2 + u1*x1 + u0;
145
eq2 := v1*x1 + v0 - y1;
146
eq3 := Evaluate(G1, x1)*Evaluate(H1, x2) + Evaluate(G2, x1)*Evaluate(H2, x2);
147
eq4 := y1*y2 - Evaluate(G1, x1)*Evaluate(H1, x2)*(x1 - x2);
148
eq5 := y1^2 - Evaluate(h, x1);
149
I := Ideal([eq1, eq2, eq3, eq4, eq5]);
150
G := GroebnerBasis(I); // last two are in non-reduced Mumford form: y2 + cubic(x2), quartic(x2)
151
unew := pr(G[#G]);
152
vnew := -pr(G[#G-1]);
153
// sanity check: (vnew^2 - hnew) mod unew;
154
imD1 := elt<Jnew | pr(G[#G]), -pr(G[#G-1])>;
155
156
// now same for the point [D21, D22]:
157
158
u0 := Coefficient(D21, 0);
159
u1 := Coefficient(D21, 1);
160
v0 := Coefficient(D22, 0);
161
v1 := Coefficient(D22, 1);
162
eq1 := x1^2 + u1*x1 + u0;
163
eq2 := v1*x1 + v0 - y1;
164
I := Ideal([eq1, eq2, eq3, eq4, eq5]);
165
G := GroebnerBasis(I);
166
unew := pr(G[#G]);
167
vnew := -pr(G[#G-1]);
168
imD2 := elt<Jnew | pr(G[#G]), -pr(G[#G-1])>;
169
170
return hnew, imD1[1], imD1[2], imD2[1], imD2[2];
171
end function;
172
173
function Does22ChainSplit(C, E, P_c, Q_c, P, Q, a)
174
Fp2 := BaseField(C);
175
// gluing step
176
h, D11, D12, D21, D22 := FromProdToJac(C, E, P_c, Q_c, P, Q, a);
177
// print "order 2^", a-1, "on hyp curve", h;
178
for i in [1..a-2] do
179
h, D11, D12, D21, D22 := FromJacToJac(h, D11, D12, D21, D22, a-i);
180
// print "order 2^", a - i - 1, "on hyp curve", h;
181
end for;
182
// now we are left with a quadratic splitting: is it singular?
183
G1 := D11;
184
G2 := D21;
185
G3 := h div (G1*G2);
186
// print G1, G2, G3;
187
delta := Matrix(Fp2, 3, 3, [Coefficient(G1, 0), Coefficient(G1, 1), Coefficient(G1, 2),
188
Coefficient(G2, 0), Coefficient(G2, 1), Coefficient(G2, 2),
189
Coefficient(G3, 0), Coefficient(G3, 1), Coefficient(G3, 2)]);
190
delta := Determinant(delta);
191
return delta eq 0;
192
end function;
193
194
function OddCyclicSumOfSquares(n, factexpl, provide_own_fac)
195
if provide_own_fac then
196
fac := factexpl;
197
else
198
fac := Factorization(n);
199
end if;
200
if {f[1] mod 4 : f in fac} ne {1} then
201
return false, 0, 0;
202
else
203
Z<I> := GaussianIntegers();
204
prod := 1;
205
for f in fac do
206
p := f[1];
207
repeat
208
z := Random(GF(p));
209
until z^((p-1) div 2) eq -1;
210
z := Integers() ! (z^((p-1) div 4)); // square root of -1
211
prod *:= GCD(Z ! p, Z ! z + I)^f[2];
212
end for;
213
u := [Integers() ! e : e in Eltseq(prod)];
214
if IsOdd(u[1]) then u1 := u[1]; u2 := u[2] div 2; else u1 := u[2]; u2 := u[1] div 2; end if;
215
return true, Abs(u1), Abs(u2);
216
end if;
217
end function;
218
219
220
function Pushing3Chain(E, P, i) // compute chain of isogenies quotienting out a point P of order 3^i
221
Fp2 := BaseField(E);
222
R<x> := PolynomialRing(Fp2);
223
chain := [];
224
C := E;
225
remainingker := P;
226
for j in [1..i] do
227
kerpol := x - (3^(i-j)*remainingker)[1];
228
C, comp := IsogenyFromKernel(C, kerpol);
229
remainingker := comp(remainingker);
230
chain cat:=[comp];
231
end for;
232
return C, chain;
233
end function;
234
235
236
function Pushing9Chain(E, P, i) // compute chain of isogenies quotienting out a point P of order 9^i (obsolete)
237
Fp2 := BaseField(E);
238
R<x> := PolynomialRing(Fp2);
239
chain := [];
240
C := E;
241
remainingker := P;
242
for j in [1..i] do
243
kerpol := &*[x - (k*9^(i-j)*remainingker)[1] : k in [1..4]];
244
C, comp := IsogenyFromKernel(C, kerpol);
245
remainingker := comp(remainingker);
246
chain cat:=[comp];
247
end for;
248
return C, chain;
249
end function;
250
251