Line data Source code
1 : /* Copyright (C) 2000 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
14 : #include "pari.h"
15 : #include "paripriv.h"
16 :
17 : #define DEBUGLEVEL DEBUGLEVEL_genus2red
18 :
19 : /********************************************************************/
20 : /** **/
21 : /** IGUSA INVARIANTS **/
22 : /** (GP2C-generated) **/
23 : /** **/
24 : /********************************************************************/
25 : /*
26 : j2(a0,a1,a2,a3,a4,a5,a6) = (-120*a0*a6+20*a1*a5-8*a2*a4+3*a3^2) / 4;
27 : */
28 : static GEN
29 1393 : igusaj2(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6)
30 : {
31 1393 : pari_sp av = avma;
32 1393 : return gerepileupto(av, gmul2n(gadd(gsub(gadd(gmul(gmulsg(-120, a0), a6), gmul(gmulsg(20, a1), a5)), gmul(gmulsg(8, a2), a4)), gmulsg(3, gsqr(a3))), -2));
33 : }
34 :
35 : /*
36 : j4(a0,a1,a2,a3,a4,a5,a6) = (240*(a0*a3*a4*a5+a1*a2*a3*a6)-400*(a0*a2*a5^2+a1^2*a4*a6)-64*(a0*a4^3+a2^3*a6)+16*(a1*a3*a4^2+a2^2*a3*a5)-672*a0*a3^2*a6+240*a1^2*a5^2-112*a1*a2*a4*a5-8*a1*a3^2*a5+16*a2^2*a4^2-16*a2*a3^2*a4+3*a3^4+2640*a0^2*a6^2-880*a0*a1*a5*a6+1312*a0*a2*a4*a6) / 2^7
37 : */
38 : static GEN
39 1393 : igusaj4(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6)
40 : {
41 1393 : pari_sp av = avma;
42 1393 : return gerepileupto(av,
43 : gmul2n(gadd(gsub(gadd(gadd(gsub(gadd(gsub(gsub(gadd(gsub(gadd(gsub(gsub(gmulsg(240,
44 : gadd(gmul(gmul(gmul(a0, a3), a4), a5), gmul(gmul(gmul(a1, a2), a3), a6))),
45 : gmulsg(400, gadd(gmul(gmul(a0, a2), gsqr(a5)), gmul(gmul(gsqr(a1), a4), a6)))),
46 : gmulsg(64, gadd(gmul(a0, gpowgs(a4, 3)), gmul(gpowgs(a2, 3), a6)))), gmulsg(16,
47 : gadd(gmul(gmul(a1, a3), gsqr(a4)), gmul(gmul(gsqr(a2), a3), a5)))),
48 : gmul(gmul(gmulsg(672, a0), gsqr(a3)), a6)), gmul(gmulsg(240, gsqr(a1)),
49 : gsqr(a5))), gmul(gmul(gmul(gmulsg(112, a1), a2), a4), a5)), gmul(gmul(gmulsg(8,
50 : a1), gsqr(a3)), a5)), gmul(gmulsg(16, gsqr(a2)), gsqr(a4))),
51 : gmul(gmul(gmulsg(16, a2), gsqr(a3)), a4)), gmulsg(3, gpowgs(a3, 4))),
52 : gmul(gmulsg(2640, gsqr(a0)), gsqr(a6))), gmul(gmul(gmul(gmulsg(880, a0), a1),
53 : a5), a6)), gmul(gmul(gmul(gmulsg(1312, a0), a2), a4), a6)), -7));
54 : }
55 :
56 : /*
57 : j6(a0,a1,a2,a3,a4,a5,a6) = (1600*(a0^2*a4^2*a5^2+a1^2*a2^2*a6^2)+1600*(a0*a1*a2*a5^3+a1^3*a4*a5*a6)+640*(a0*a1*a3*a4*a5^2+a1^2*a2*a3*a5*a6)-4000*(a0^2*a3*a5^3+a1^3*a3*a6^2)-384*(a0*a1*a4^3*a5+a1*a2^3*a5*a6)-640*(a0*a2^2*a4*a5^2+a1^2*a2*a4^2*a6)+80*(a0*a2*a3^2*a5^2+a1^2*a3^2*a4*a6)+192*(a0*a2*a3*a4^2*a5+a1*a2^2*a3*a4*a6)-48*(a0*a3^3*a4*a5+a1*a2*a3^3*a6)-224*(a1^2*a3*a4^2*a5+a1*a2^2*a3*a5^2)+64*(a1^2*a4^4+a2^4*a5^2)-64*(a1*a2*a3*a4^3+a2^3*a3*a4*a5)+16*(a1*a3^3*a4^2+a2^2*a3^3*a5)-4096*(a0^2*a4^3*a6+a0*a2^3*a6^2)+6400*(a0^2*a2*a5^2*a6+a0*a1^2*a4*a6^2)+10560*(a0^2*a3*a4*a5*a6+a0*a1*a2*a3*a6^2)+2624*(a0*a1*a3*a4^2*a6+a0*a2^2*a3*a5*a6)-4432*a0*a1*a3^2*a5*a6-8*a2*a3^4*a4+a3^6-320*a1^3*a5^3+64*a1^2*a2*a4*a5^2+176*a1^2*a3^2*a5^2+128*a1*a2^2*a4^2*a5+112*a1*a2*a3^2*a4*a5-28*a1*a3^4*a5+16*a2^2*a3^2*a4^2+5120*a0^3*a6^3-2544*a0^2*a3^2*a6^2+312*a0*a3^4*a6-14336*a0^2*a2*a4*a6^2+1024*a0*a2^2*a4^2*a6-2560*a0^2*a1*a5*a6^2-2240*a0*a1^2*a5^2*a6-6528*a0*a1*a2*a4*a5*a6-1568*a0*a2*a3^2*a4*a6) / 2^10
58 : */
59 : static GEN
60 1393 : igusaj6(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6)
61 : {
62 1393 : pari_sp av = avma;
63 1393 : return gerepileupto(av,
64 : gmul2n(gsub(gsub(gsub(gsub(gadd(gsub(gadd(gsub(gadd(gadd(gsub(gadd(gadd(gadd(gadd(gsub(gadd(gsub(gsub(gadd(gadd(gadd(gsub(gadd(gsub(gadd(gsub(gsub(gadd(gadd(gsub(gsub(gsub(gadd(gadd(gmulsg(1600,
65 : gadd(gmul(gmul(gsqr(a0), gsqr(a4)), gsqr(a5)), gmul(gmul(gsqr(a1), gsqr(a2)),
66 : gsqr(a6)))), gmulsg(1600, gadd(gmul(gmul(gmul(a0, a1), a2), gpowgs(a5, 3)),
67 : gmul(gmul(gmul(gpowgs(a1, 3), a4), a5), a6)))), gmulsg(640,
68 : gadd(gmul(gmul(gmul(gmul(a0, a1), a3), a4), gsqr(a5)),
69 : gmul(gmul(gmul(gmul(gsqr(a1), a2), a3), a5), a6)))), gmulsg(4000,
70 : gadd(gmul(gmul(gsqr(a0), a3), gpowgs(a5, 3)), gmul(gmul(gpowgs(a1, 3), a3),
71 : gsqr(a6))))), gmulsg(384, gadd(gmul(gmul(gmul(a0, a1), gpowgs(a4, 3)), a5),
72 : gmul(gmul(gmul(a1, gpowgs(a2, 3)), a5), a6)))), gmulsg(640,
73 : gadd(gmul(gmul(gmul(a0, gsqr(a2)), a4), gsqr(a5)), gmul(gmul(gmul(gsqr(a1),
74 : a2), gsqr(a4)), a6)))), gmulsg(80, gadd(gmul(gmul(gmul(a0, a2), gsqr(a3)),
75 : gsqr(a5)), gmul(gmul(gmul(gsqr(a1), gsqr(a3)), a4), a6)))), gmulsg(192,
76 : gadd(gmul(gmul(gmul(gmul(a0, a2), a3), gsqr(a4)), a5), gmul(gmul(gmul(gmul(a1,
77 : gsqr(a2)), a3), a4), a6)))), gmulsg(48, gadd(gmul(gmul(gmul(a0, gpowgs(a3, 3)),
78 : a4), a5), gmul(gmul(gmul(a1, a2), gpowgs(a3, 3)), a6)))), gmulsg(224,
79 : gadd(gmul(gmul(gmul(gsqr(a1), a3), gsqr(a4)), a5), gmul(gmul(gmul(a1,
80 : gsqr(a2)), a3), gsqr(a5))))), gmulsg(64, gadd(gmul(gsqr(a1), gpowgs(a4, 4)),
81 : gmul(gpowgs(a2, 4), gsqr(a5))))), gmulsg(64, gadd(gmul(gmul(gmul(a1, a2), a3),
82 : gpowgs(a4, 3)), gmul(gmul(gmul(gpowgs(a2, 3), a3), a4), a5)))), gmulsg(16,
83 : gadd(gmul(gmul(a1, gpowgs(a3, 3)), gsqr(a4)), gmul(gmul(gsqr(a2), gpowgs(a3,
84 : 3)), a5)))), gmulsg(4096, gadd(gmul(gmul(gsqr(a0), gpowgs(a4, 3)), a6),
85 : gmul(gmul(a0, gpowgs(a2, 3)), gsqr(a6))))), gmulsg(6400,
86 : gadd(gmul(gmul(gmul(gsqr(a0), a2), gsqr(a5)), a6), gmul(gmul(gmul(a0,
87 : gsqr(a1)), a4), gsqr(a6))))), gmulsg(10560, gadd(gmul(gmul(gmul(gmul(gsqr(a0),
88 : a3), a4), a5), a6), gmul(gmul(gmul(gmul(a0, a1), a2), a3), gsqr(a6))))),
89 : gmulsg(2624, gadd(gmul(gmul(gmul(gmul(a0, a1), a3), gsqr(a4)), a6),
90 : gmul(gmul(gmul(gmul(a0, gsqr(a2)), a3), a5), a6)))),
91 : gmul(gmul(gmul(gmul(gmulsg(4432, a0), a1), gsqr(a3)), a5), a6)),
92 : gmul(gmul(gmulsg(8, a2), gpowgs(a3, 4)), a4)), gpowgs(a3, 6)), gmul(gmulsg(320,
93 : gpowgs(a1, 3)), gpowgs(a5, 3))), gmul(gmul(gmul(gmulsg(64, gsqr(a1)), a2), a4),
94 : gsqr(a5))), gmul(gmul(gmulsg(176, gsqr(a1)), gsqr(a3)), gsqr(a5))),
95 : gmul(gmul(gmul(gmulsg(128, a1), gsqr(a2)), gsqr(a4)), a5)),
96 : gmul(gmul(gmul(gmul(gmulsg(112, a1), a2), gsqr(a3)), a4), a5)),
97 : gmul(gmul(gmulsg(28, a1), gpowgs(a3, 4)), a5)), gmul(gmul(gmulsg(16, gsqr(a2)),
98 : gsqr(a3)), gsqr(a4))), gmul(gmulsg(5120, gpowgs(a0, 3)), gpowgs(a6, 3))),
99 : gmul(gmul(gmulsg(2544, gsqr(a0)), gsqr(a3)), gsqr(a6))), gmul(gmul(gmulsg(312,
100 : a0), gpowgs(a3, 4)), a6)), gmul(gmul(gmul(gmulsg(14336, gsqr(a0)), a2), a4),
101 : gsqr(a6))), gmul(gmul(gmul(gmulsg(1024, a0), gsqr(a2)), gsqr(a4)), a6)),
102 : gmul(gmul(gmul(gmulsg(2560, gsqr(a0)), a1), a5), gsqr(a6))),
103 : gmul(gmul(gmul(gmulsg(2240, a0), gsqr(a1)), gsqr(a5)), a6)),
104 : gmul(gmul(gmul(gmul(gmul(gmulsg(6528, a0), a1), a2), a4), a5), a6)),
105 : gmul(gmul(gmul(gmul(gmulsg(1568, a0), a2), gsqr(a3)), a4), a6)), -10));
106 : }
107 :
108 : /********************************************************************/
109 : /** **/
110 : /** A REDUCTION ALGORITHM "A LA TATE" FOR CURVES OF GENUS 2 **/
111 : /** **/
112 : /********************************************************************/
113 : /* Based on genus2reduction-0.3, http://www.math.u-bordeaux.fr/~liu/G2R/
114 : * by Qing Liu <liu@math.u-bordeaux.fr>
115 : * and Henri Cohen <cohen@math.u-bordeaux.fr>
116 :
117 : * Qing Liu: Modeles minimaux des courbes de genre deux
118 : * J. fuer die Reine und Angew. Math., 453 (1994), 137-164.
119 : * http://www.math.u-bordeaux.fr/~liu/articles/modregE.ps */
120 :
121 : /* some auxiliary polynomials, gp2c-generated */
122 :
123 : /*
124 : apol2(a0,a1,a2) = -5*a1^2+12*a0*a2;
125 : */
126 : static GEN
127 1393 : apol2(GEN a0, GEN a1, GEN a2)
128 : {
129 1393 : return gadd(gmulsg(-5, gsqr(a1)), gmul(gmulsg(12, a0), a2));
130 : }
131 :
132 : /*
133 : apol3(a0,a1,a2,a3) = 5*a1^3+9*a0*(-2*a1*a2+3*a0*a3);
134 : */
135 : static GEN
136 1393 : apol3(GEN a0, GEN a1, GEN a2, GEN a3)
137 : {
138 1393 : return gadd(gmulsg(5, gpowgs(a1, 3)), gmul(gmulsg(9, a0), gadd(gmul(gmulsg(-2, a1), a2), gmul(gmulsg(3, a0), a3))));
139 : }
140 :
141 : /*
142 : apol5(a0,a1,a2,a3,a4,a5) = a1^5+3*a0*(-2*a1^3*a2+9*a0*a1^2*a3-36*a0^2*a1*a4+108*a0^3*a5);
143 : */
144 : static GEN
145 1393 : apol5(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5)
146 : {
147 1393 : return gadd(gpowgs(a1, 5), gmul(gmulsg(3, a0), gadd(gsub(gadd(gmul(gmulsg(-2, gpowgs(a1, 3)), a2), gmul(gmul(gmulsg(9, a0), gsqr(a1)), a3)), gmul(gmul(gmulsg(36, gsqr(a0)), a1), a4)), gmul(gmulsg(108, gpowgs(a0, 3)), a5))));
148 : }
149 :
150 : /*
151 : bpol2(a0,a1,a2,a3,a4) = 2*a2^2-5*a1*a3+10*a0*a4;
152 : */
153 : static GEN
154 1393 : bpol2(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4)
155 : {
156 1393 : return gadd(gsub(gmulsg(2, gsqr(a2)), gmul(gmulsg(5, a1), a3)), gmul(gmulsg(10, a0), a4));
157 : }
158 :
159 : static const long VERYBIG = (1L<<20);
160 : static long
161 23583 : myval(GEN x, GEN p) { return signe(x)? Z_pval(x,p): VERYBIG; }
162 : static long
163 2982 : my3val(GEN x) { return signe(x)? Z_lval(x,3): VERYBIG; }
164 : /* b in Z[i], return v_3(b) */
165 : static long
166 1491 : myval_zi(GEN b) { return minss(my3val(real_i(b)), my3val(imag_i(b))); }
167 : /* b in Z[i, Y]/(Y^2-3), return v_Y(b) */
168 : static long
169 672 : myval_zi2(GEN b)
170 : {
171 : long v0, v1;
172 672 : b = lift_shallow(b);
173 672 : v0 = myval_zi(RgX_coeff(b,0));
174 672 : v1 = myval_zi(RgX_coeff(b,1));
175 672 : return minss(2*v0, 2*v1+1);
176 : }
177 :
178 : /* min(a,b,c) */
179 : static long
180 1925 : min3(long a, long b, long c)
181 : {
182 1925 : long m = a;
183 1925 : if (b < m) m = b;
184 1925 : if (c < m) m = c;
185 1925 : return m;
186 : }
187 :
188 : /* Vector of p-adic factors (over Q_p) to accuracy r of pol. */
189 : static GEN
190 119 : padicfactors(GEN pol, GEN p, long r) { return gel(factorpadic(pol,p,r),1); }
191 :
192 : /* x(1/t)*t^6, deg x <= 6 */
193 : static GEN
194 322 : RgX_recip6(GEN x)
195 : {
196 322 : long lx = lg(x), i, j;
197 322 : GEN y = cgetg(9, t_POL);
198 322 : y[1] = x[1];
199 2429 : for (i=8,j=2; j < lx; i--,j++) gel(y,i) = gel(x,j);
200 469 : for ( ; j < 9; i--,j++) gel(y,i) = gen_0;
201 322 : return normalizepol_lg(y, 9);
202 : }
203 : /* extract coefficients of a polynomial a0 X^6 + ... + a6, of degree <= 6 */
204 : static void
205 1617 : RgX_to_06(GEN q, GEN *a0, GEN *a1, GEN *a2, GEN *a3, GEN *a4, GEN *a5, GEN *a6)
206 : {
207 1617 : *a0 = gen_0;
208 1617 : *a1 = gen_0;
209 1617 : *a2 = gen_0;
210 1617 : *a3 = gen_0;
211 1617 : *a4 = gen_0;
212 1617 : *a5 = gen_0;
213 1617 : *a6 = gen_0;
214 1617 : switch(degpol(q))
215 : {
216 1183 : case 6: *a0 = gel(q,8); /*fall through*/
217 1617 : case 5: *a1 = gel(q,7); /*fall through*/
218 1617 : case 4: *a2 = gel(q,6); /*fall through*/
219 1617 : case 3: *a3 = gel(q,5); /*fall through*/
220 1617 : case 2: *a4 = gel(q,4); /*fall through*/
221 1617 : case 1: *a5 = gel(q,3); /*fall through*/
222 1617 : case 0: *a6 = gel(q,2); /*fall through*/
223 : }
224 1617 : }
225 : /* extract coefficients a0,...a3 of a polynomial a0 X^6 + ... + a6 */
226 : static void
227 1393 : RgX_to_03(GEN q, GEN *a0, GEN *a1, GEN *a2, GEN *a3)
228 : {
229 1393 : *a0 = gen_0;
230 1393 : *a1 = gen_0;
231 1393 : *a2 = gen_0;
232 1393 : *a3 = gen_0;
233 1393 : switch(degpol(q))
234 : {
235 931 : case 6: *a0 = gel(q,8); /*fall through*/
236 1393 : case 5: *a1 = gel(q,7); /*fall through*/
237 1393 : case 4: *a2 = gel(q,6); /*fall through*/
238 1393 : case 3: *a3 = gel(q,5); /*fall through*/
239 : }
240 1393 : }
241 :
242 : /* deg(H mod p) = 3, return v_p( disc(corresponding p-adic factor) ) */
243 : static long
244 14 : discpart(GEN H, GEN p, long prec)
245 : {
246 : GEN list, prod, dis;
247 : long i, j;
248 :
249 14 : if (degpol(FpX_red(H,p)) != 3)
250 : pari_err_BUG("discpart [must not reach]"); /* LCOV_EXCL_LINE */
251 14 : list = padicfactors(H,p,prec);
252 14 : prod = pol_1(varn(H));
253 56 : for(i = 1; i < lg(list); i++)
254 : {
255 42 : GEN t = gel(list,i);
256 84 : for(j = 3; j < lg(t); j++) /* include if nonconstant mod p */
257 70 : if (!valp(gel(t,j))) { prod = RgX_mul(prod,t); break; }
258 : }
259 14 : if (degpol(prod) != 3) pari_err_BUG("discpart [prod degree]");
260 14 : dis = RgX_disc(prod);
261 14 : return gequal0(dis)? prec+1: valp(dis);
262 : }
263 :
264 : /* B = b0 X^6 + ... + b6 a ZX, 0 <= j <= 3.
265 : * Let theta_j(H) := min { v_p(b_i) / (i - j), j < i <= 6 } >= 0.
266 : * Return 60 theta \in Z */
267 : static long
268 1918 : theta_j(GEN B, GEN p, long j)
269 : {
270 1918 : long i, t = VERYBIG;
271 9240 : for(i = 1+j; i <= 6; i++)
272 7322 : t = minss(t, myval(RgX_coeff(B,6-i), p) * (60 / (i-j)));
273 1918 : return t;
274 : }
275 : /* compute 6 * theta_3 for B in Z[i][X], p = 3 */
276 : static long
277 28 : theta_3_zi(GEN B)
278 : {
279 28 : long v2 = myval_zi(RgX_coeff(B,2));
280 28 : long v1 = myval_zi(RgX_coeff(B,1));
281 28 : long v0 = myval_zi(RgX_coeff(B,0));
282 28 : return min3(6*v2, 3*v1, 2*v0);
283 : }
284 : /* compute 6 * theta_3 for B in (Z[i,Y]/(Y^2-3))[X], p = 3 */
285 : static long
286 84 : theta_3_zi2(GEN B)
287 : {
288 84 : long v2 = myval_zi2(RgX_coeff(B,2));
289 84 : long v1 = myval_zi2(RgX_coeff(B,1));
290 84 : long v0 = myval_zi2(RgX_coeff(B,0));
291 84 : return min3(6*v2, 3*v1, 2*v0);
292 : }
293 :
294 : /* Set maxord to the maximal multiplicity of a factor. If there is at least
295 : * a triple root (=> maxord >= 3) return it, else return NULL */
296 : static GEN
297 805 : factmz(GEN Q, GEN p, long *maxord)
298 : {
299 805 : GEN z = FpX_factor_squarefree(Q, p);
300 805 : long m = lg(z)-1; /* maximal multiplicity */
301 805 : *maxord = m;
302 805 : return (m >= 3)? FpX_oneroot(gel(z,m), p): NULL;
303 : }
304 : static long
305 1736 : get_lambda(GEN H, GEN p)
306 : {
307 1736 : if (!dvdii(RgX_coeff(H,3), p)) return 3;
308 735 : if (!dvdii(RgX_coeff(H,4), p)) return 2;
309 560 : if (!dvdii(RgX_coeff(H,5), p)) return 1;
310 441 : if (!dvdii(RgX_coeff(H,6), p)) return 0;
311 63 : return -1;
312 : }
313 :
314 : /* H integral ZX of degree 5 or 6, p > 2. Modify until
315 : * y^2 = p^alpha H is minimal over Z_p, alpha = 0,1
316 : * Return [H,lambda,60*theta,alpha,quad,beta], where
317 : * - quad = 1 if H has a root of order 3 in F_p^2 \ F_p, 0 otherwise
318 : * - 0 <= lambda <= 3, index of a coefficient with valuation 0
319 : * - theta = theta_j(H(x + r), p, lambda), 60*theta in Z, where r is a root
320 : * of H mod p
321 : * - beta >= -1 s.t. H = p^n H0(r + p^beta * X) for some n, r in Z, where
322 : * H0 is the initial H or polrecip(H) */
323 : static GEN
324 1673 : polymini(GEN H, GEN p)
325 : {
326 1673 : long t60, alpha, lambda, quad = 0, beta = 0;
327 : GEN Hp;
328 :
329 1673 : alpha = ZX_pvalrem(H, p, &H) & 1;
330 1673 : lambda = get_lambda(H, p);
331 1673 : if (lambda < 0) { H = RgX_recip6(H); lambda = get_lambda(H, p); }
332 0 : for(;;)
333 : {
334 : for(;;)
335 245 : { /* lambda <= 3, t60 = 60*theta */
336 : GEN rac;
337 : long e, maxord;
338 1918 : t60 = theta_j(H,p,lambda); e = t60 / 60;
339 1918 : if (e)
340 : {
341 903 : GEN pe = powiu(p,e);
342 : /* H <- H(p^e X) / p^(e(6-lambda)) */
343 903 : H = ZX_unscale_divpow(H, pe, 6-lambda);
344 903 : alpha = (alpha + lambda*e)&1;
345 903 : beta += e;
346 903 : t60 -= 60*e;
347 : }
348 : /* 0 <= t < 60 */
349 1918 : Hp = FpX_red(H, p); if (t60) break;
350 :
351 798 : rac = factmz(Hp,p, &maxord);
352 798 : if (maxord <= 2)
353 : {
354 532 : if (degpol(Hp) <= 3) break;
355 119 : goto end;
356 : }
357 : /* maxord >= 3 */
358 266 : if (!rac) { quad = 1; goto end; }
359 245 : if (signe(rac)) H = ZX_translate(H, rac);
360 245 : lambda = 6 - maxord;
361 : }
362 1554 : if (lambda <= 2)
363 : {
364 623 : if (myval(RgX_coeff(H,2),p) > 1-alpha &&
365 518 : myval(RgX_coeff(H,1),p) > 2-alpha &&
366 413 : myval(RgX_coeff(H,0),p) > 3-alpha)
367 : {
368 0 : H = ZX_unscale(H, p);
369 0 : if (alpha) H = ZX_Z_mul(H, p);
370 0 : return polymini(H, p);
371 : }
372 623 : break;
373 : }
374 : /* lambda = 3 */
375 931 : if (alpha == 0) break;
376 399 : if (degpol(Hp) == 3)
377 : {
378 721 : if (myval(RgX_coeff(H,6),p) >= 3 &&
379 357 : myval(RgX_coeff(H,5),p) >= 2)
380 : { /* too close to root [Kodaira symbol for y^2 = p^alpha*H not
381 : implemented when alpha = 1]: go back one step */
382 357 : H = ZX_rescale(H, p); /* H(x/p)p^(deg H) */
383 357 : H = ZX_Z_divexact(H, powiu(p, degpol(H)-3)); /* H(x/p)p^3 */
384 357 : t60 += 60; alpha = 0; beta--;
385 : }
386 364 : break;
387 : }
388 35 : if (degpol(Hp) != 6) break;
389 7 : if (t60)
390 : {
391 : long m, maxord;
392 7 : GEN v, T, rac = factmz(RgX_mulXn(Hp, -3), p, &maxord);
393 14 : if (maxord <= 2) break;
394 7 : T = ZX_affine(H, p, rac); /* H(rac + px) */
395 7 : if (ZX_pval(T,p) < 3) break;
396 :
397 0 : H = ZX_Z_divexact(T, powiu(p,3));
398 0 : alpha = 0; beta++;
399 0 : v = FpX_factor_squarefree(FpX_red(H,p), p);
400 0 : m = lg(v)-1; /* maximal multiplicity */
401 0 : if (m > 1)
402 : {
403 0 : rac = FpX_oneroot(gel(v,m), p); /* v[m] is linear */
404 0 : H = ZX_translate(H,rac);
405 0 : t60 = theta_j(H,p,3);
406 0 : if (t60 < 60) break;
407 : }
408 : }
409 : }
410 1673 : end:
411 1673 : return mkvec2(H, mkvecsmall5(lambda,t60,alpha,quad,beta));
412 : }
413 :
414 : /* a in Q[i], return a^3 mod 3 */
415 : static GEN
416 14 : zi_pow3mod(GEN a)
417 : {
418 : GEN x, y;
419 14 : if (typ(a) != t_COMPLEX) return gmodgs(a,3);
420 7 : x = gmodgs(gel(a,1), 3);
421 7 : y = gmodgs(gel(a,2), 3);
422 7 : return mkcomplex(x, negi(y));
423 : }
424 : static GEN
425 21 : polymini_zi(GEN pol) /* polynome minimal dans Z[i] */
426 : {
427 21 : GEN polh, rac, a0, a1, a2, a3, a4, a5, a6, p = utoipos(3);
428 21 : long alpha, beta = 0, t6;
429 :
430 21 : alpha = ZX_pval(pol,p) & 1;
431 21 : polh = alpha? RgX_Rg_div(pol, p): pol;
432 21 : rac = mkcomplex(Fp_div(RgX_coeff(polh,3), RgX_coeff(polh,6), p), gen_1);
433 : for(;;)
434 7 : {
435 : long e;
436 28 : polh = RgX_translate(polh, rac);
437 28 : t6 = theta_3_zi(polh); e = t6 / 6;
438 28 : if (e)
439 : {
440 14 : GEN pe = powiu(p,e);
441 14 : polh = RgX_Rg_div(RgX_unscale(polh,pe), powiu(pe,3));
442 14 : alpha = (alpha+e)&1;
443 14 : t6 -= e * 6; beta += e;
444 : }
445 28 : RgX_to_06(polh, &a0,&a1,&a2,&a3,&a4,&a5,&a6);
446 28 : if (t6 || !myval_zi(a4) || !myval_zi(a5)) break;
447 7 : rac = zi_pow3mod(gdiv(a6, gneg(a3)));
448 : }
449 21 : if (alpha && myval_zi(a0) >= 3 && myval_zi(a1) >= 2 && myval_zi(a2) >= 1)
450 : {
451 14 : t6 += 6; beta--; alpha = 0;
452 : }
453 21 : if (alpha && beta >= 1) pari_err_BUG("quadratic");
454 21 : return mkvecsmall3(t6, alpha, beta);
455 : }
456 :
457 : /* pol is a ZX, minimal polynomial over Z_3[i,Y]/(Y^2-3) */
458 : static GEN
459 84 : polymini_zi2(GEN pol)
460 : {
461 : long alpha, beta, t6;
462 : GEN a0, a1, a2, a3, a4, a5, a6;
463 84 : GEN polh, rac, y = pol_x(fetch_var()), p = utoipos(3);
464 :
465 84 : if (ZX_pval(pol,p)) pari_err_BUG("polymini_zi2 [polynomial not minimal]");
466 84 : y = mkpolmod(y, gsubgs(gsqr(y), 3)); /* mod(y,y^2-3) */
467 84 : polh = gdivgs(RgX_unscale(pol, y),27); /* H(y*x) / 27 */
468 161 : if (myval_zi2(RgX_coeff(polh,4)) <= 0 ||
469 77 : myval_zi2(RgX_coeff(polh,2)) <= 0)
470 : {
471 7 : (void)delete_var();
472 7 : return mkvecsmall2(0,0);
473 : }
474 :
475 77 : if (myval_zi2(gsub(RgX_coeff(polh,6), RgX_coeff(polh,0))) > 0)
476 7 : rac = gen_I();
477 : else
478 70 : rac = gen_1;
479 77 : alpha = 0;
480 77 : beta = 0;
481 : for(;;)
482 7 : {
483 : long e;
484 84 : polh = RgX_translate(polh, rac);
485 84 : t6 = theta_3_zi2(polh); e = t6 / 6;
486 84 : if (e)
487 : {
488 77 : GEN pent = gpowgs(y, e);
489 77 : polh = RgX_Rg_div(RgX_unscale(polh, pent), gpowgs(pent,3));
490 77 : alpha = (alpha+e)&1;
491 77 : t6 -= 6*e; beta += e;
492 : }
493 84 : RgX_to_06(polh, &a0,&a1,&a2,&a3,&a4,&a5,&a6);
494 84 : if (t6 || !myval_zi2(a4) || !myval_zi2(a5)) break;
495 7 : a3 = liftpol_shallow(a3); if (typ(a3)==t_POL) a3 = RgX_coeff(a3,0);
496 7 : a6 = liftpol_shallow(a6); if (typ(a6)==t_POL) a6 = RgX_coeff(a6,0);
497 7 : rac = zi_pow3mod(gdiv(a6,gneg(a3)));
498 : }
499 77 : if (alpha)
500 : {
501 42 : if (myval_zi2(a0) < 3 || myval_zi2(a1) < 2 || myval_zi2(a2) < 1)
502 0 : pari_err_BUG("polymini_zi2 [alpha]");
503 42 : t6 += 6; beta--;
504 : }
505 77 : (void)delete_var();
506 77 : if (odd(beta)) pari_err_BUG("quartic [type over Z[i] must be [K-K-(2*m)]]");
507 77 : return mkvecsmall2(t6, beta);
508 : }
509 :
510 : struct igusa {
511 : GEN j2, i4, j4, j6, j8, j10, i12;
512 : GEN a0, A2, A3, A5, B2;
513 : };
514 : struct igusa_p {
515 : long eps, tt, r1, r2, tame;
516 : GEN p, stable, val, neron;
517 : const char *type;
518 : };
519 :
520 : /* initialize Ip */
521 : static void
522 1435 : stable_reduction(struct igusa *I, struct igusa_p *Ip, GEN p)
523 : {
524 : static const long d[9] = { 0,60,30,30,20,15,12,10 }; /* 120 / deg(X) */
525 1435 : GEN j2 = I->j2, i4 = I->i4, j4 = I->j4, j6 = I->j6, j8 = I->j8;
526 1435 : GEN val, J, v, Ieps, j10 = I->j10, i12 = I->i12;
527 : long s, r1, r2, r3, r4, i, eps;
528 :
529 1435 : Ip->tame = 0;
530 1435 : Ip->neron = NULL;
531 1435 : Ip->type = NULL;
532 1435 : Ip->p = p;
533 1435 : Ip->val = val = cgetg(9, t_VECSMALL);
534 1435 : val[1] = myval(j2,p);
535 1435 : val[2] = myval(j4,p);
536 1435 : val[3] = myval(i4,p);
537 1435 : val[4] = myval(j6,p);
538 1435 : val[5] = myval(j8,p);
539 1435 : val[6] = myval(j10,p);
540 1435 : val[7] = myval(i12,p);
541 1435 : switch(itos_or_0(p))
542 : {
543 21 : case 2: eps = 4; val[8] = val[5]; Ieps = j8; break;
544 476 : case 3: eps = 3; val[8] = val[4]; Ieps = j6; break;
545 938 : default: eps = 1; val[8] = val[1]; Ieps = gdivgs(j2,12); break;
546 : }
547 :
548 1435 : v = cgetg(8,t_VECSMALL);
549 11480 : for(i = 1; i <= 7; i++) v[i] = val[i] * d[i];
550 1435 : s = vecsmall_min(v);
551 1435 : Ip->eps = eps;
552 :
553 1435 : r1 = 3*eps*val[3];
554 1435 : r3 = eps*val[6] + val[8];
555 1435 : r2 = eps*val[7];
556 1435 : r4 = min3(r1, r2, r3);
557 :
558 : /* s = max(v_p(X) / deg(X)) */
559 1435 : J = cgetg(1, t_VEC);
560 1435 : if (s == v[6])
561 154 : Ip->tt = 1;
562 1281 : else if (s == v[7])
563 : {
564 119 : J = mkvec( Fp_to_mod(gmod(gdiv(gpowgs(i4,3),i12), p), p) );
565 119 : Ip->tt = 2;
566 : }
567 1162 : else if (s == v[3])
568 210 : Ip->tt = (val[2] == val[3] || 2*val[4] == 3*val[3])? 3: 4;
569 952 : else if (r3 == r4)
570 : {
571 560 : GEN a,b, P, sj, pj, t = gmul(gpowgs(j10,eps),Ieps);
572 560 : sj = gaddsg(1728, gdiv(gpowgs(i12,eps), t));
573 560 : pj = gdiv(gpowgs(i4,3*eps), t);
574 560 : a = gmod(sj, p);
575 560 : b = gmod(pj, p);
576 560 : P = mkpoln(3, gen_1, Fp_neg(a,p), b, 0); /* X^2 - SX + P: roots j1,j2 */
577 560 : J = FpX_roots(P, p);
578 560 : switch(lg(J)-1)
579 : {
580 0 : case 0:
581 0 : P = FpX_to_mod(P, p);
582 0 : a = FpX_to_mod(pol_x(0), p);
583 0 : b = FpX_to_mod(deg1pol_shallow(b, gen_m1,0), p);
584 0 : J = mkvec2(mkpolmod(a,P), mkpolmod(b,P)); break;
585 378 : case 1:
586 378 : a = Fp_to_mod(gel(J,1), p);
587 378 : J = mkvec2(a, a); break;
588 182 : case 2:
589 182 : settyp(J, t_VEC);
590 182 : J = FpV_to_mod(J, p); break;
591 : }
592 560 : Ip->tt = 5;
593 : }
594 392 : else if (r2 == r4)
595 : {
596 280 : J = mkvec( Fp_to_mod(gmod(gdiv(gpowgs(i4,3),i12), p), p) );
597 280 : Ip->tt = 6;
598 : }
599 : else
600 112 : Ip->tt = 7; /* r1 == r4 */
601 1435 : Ip->stable = mkvec2(stoi(Ip->tt), J);
602 1435 : }
603 :
604 : struct red {
605 : const char *t, *pages;
606 : double tnum;
607 : GEN g;
608 : };
609 :
610 : /* destroy v */
611 : static GEN
612 1414 : zv_snf(GEN v)
613 : {
614 1414 : long i, l = lg(v);
615 3129 : for (i = 1; i < l; i++)
616 : {
617 1715 : long j, a = v[i];
618 2478 : for (j = i+1; j < l; j++)
619 : {
620 763 : long b = v[j], d = ugcd(a,b);
621 763 : v[i] = a = a*(b/d);
622 763 : v[j] = d;
623 : }
624 : }
625 1498 : for (i = l-1; i > 0; i--)
626 1197 : if (v[i] != 1) { setlg(v, i+1); break; }
627 1414 : return zv_to_ZV(v);
628 : }
629 :
630 : static GEN
631 1337 : cyclic(long n)
632 1337 : { return (n <= 1)? cgetg(1, t_VECSMALL): mkvecsmall(n); }
633 : static GEN
634 336 : dicyclic(long a, long b)
635 : {
636 : long d;
637 336 : if (!a) a = 1;
638 336 : if (!b) b = 1;
639 336 : if (a < b) lswap(a,b);
640 336 : d = ugcd(a,b);
641 336 : if (d == 1) return cyclic(a*b);
642 280 : return mkvecsmall2(a*b/d, d);
643 : }
644 : /* Z/2xZ/2, resp Z/4 for n even, resp. odd */
645 : static GEN
646 280 : groupH(long n) { return odd(n)? cyclic(4): dicyclic(2,2); }
647 :
648 : static long
649 252 : get_red(struct red *S, struct igusa_p *Ip, GEN polh, GEN p, long alpha, long r)
650 : {
651 252 : GEN val = Ip->val;
652 : long indice;
653 252 : switch(r)
654 : {
655 42 : case 0:
656 42 : indice = FpX_is_squarefree(FpX_red(polh,p), p)
657 : ? 0
658 42 : : val[6] - val[7] + val[8]/Ip->eps;
659 42 : S->t = stack_sprintf("I{%ld}", indice);
660 42 : S->tnum = 1;
661 42 : S->pages = "159-177";
662 42 : S->g = cyclic(indice);
663 42 : return indice ? indice: 1;
664 35 : case 6:
665 35 : if (alpha == 0) polh = ZX_unscale_divpow(polh, p, 3); /* H(px) /p^3 */
666 35 : indice = FpX_is_squarefree(FpX_red(polh,p), p)
667 : ? 0
668 35 : : val[6] - val[7] + val[8]/Ip->eps;
669 35 : S->t = stack_sprintf("I*{%ld}", indice);
670 35 : S->tnum = 1.5;
671 35 : S->pages = "159-177";
672 35 : S->g = groupH(indice);
673 35 : return indice + 5;
674 21 : case 3:
675 21 : S->t = "III";
676 21 : S->tnum = 3;
677 21 : S->pages = "161-177";
678 21 : S->g = cyclic(2);
679 21 : return 2;
680 35 : case 9:
681 35 : S->t = "III*";
682 35 : S->tnum = 3.5;
683 35 : S->pages = "162-177";
684 35 : S->g = cyclic(2);
685 35 : return 8;
686 28 : case 2:
687 28 : S->t = "II";
688 28 : S->tnum = 2;
689 28 : S->pages = "159-174";
690 28 : S->g = cyclic(1);
691 28 : return 1;
692 56 : case 8:
693 56 : S->t = "IV*";
694 56 : S->tnum = 4.5;
695 56 : S->pages = "160-175";
696 56 : S->g = cyclic(3);
697 56 : return 7;
698 21 : case 4:
699 21 : S->t = "IV";
700 21 : S->tnum = 4;
701 21 : S->pages = "160-174";
702 21 : S->g = cyclic(3);
703 21 : return 3;
704 14 : case 10:
705 14 : S->t = "II*";
706 14 : S->tnum = 2.5;
707 14 : S->pages = "160-174";
708 14 : S->g = cyclic(1);
709 14 : return 9;
710 0 : default: pari_err_BUG("get_red [type]");
711 0 : S->t = "";
712 0 : S->tnum = 0;
713 0 : S->pages = ""; /* gcc -Wall */
714 0 : S->g = NULL;
715 : return -1; /*LCOV_EXCL_LINE*/
716 : }
717 : }
718 :
719 : /* reduce a/b; assume b > 0 */
720 : static void
721 1330 : ssQ_red(long a, long b, long *n, long *d)
722 : {
723 1330 : long g = ugcd(labs(a), b);
724 1330 : if (g > 1) { a /= g; b /= g; }
725 1330 : *n = a; *d = b;
726 1330 : }
727 : /* denom(a/b); assume b > 0 */
728 : static long
729 28 : ssQ_denom(long a, long b)
730 : {
731 28 : long g = ugcd(labs(a), b);
732 28 : return g == 1? b: b / g;
733 : }
734 : /* n = lcm(d, denom(a/b)); r = (a/b * n mod n); assume b > 0 and d > 0 */
735 : static void
736 455 : get_nr(long d, long a, long b, long *n, long *r)
737 : {
738 : long c, A, B;
739 455 : ssQ_red(a, b, &A,&B);
740 455 : c = d / ugcd(d, B);
741 455 : *n = B * c;
742 455 : *r = umodsu(A * c, *n);
743 455 : }
744 : /* n = lcm(denom(a/b), denom(c/d)); r = (a/b * n mod n); q = (c/d * n mod n);
745 : * assume b > 0 and d > 0 */
746 : static void
747 154 : get_nrq(long a, long b, long c, long d, long *n, long *r, long *q)
748 : {
749 : long g, A, B, C, D;
750 154 : ssQ_red(a, b, &A,&B);
751 154 : ssQ_red(c, d, &C,&D);
752 154 : g = ugcd(B,D);
753 154 : *n = B * (D/g);
754 154 : *r = umodsu(A * (D/g), *n);
755 154 : *q = umodsu(C * (B/g), *n);
756 154 : }
757 :
758 : /* Ip->tt = 1 */
759 : static long
760 28 : tame_1(struct igusa *I, struct igusa_p *Ip)
761 : {
762 28 : GEN p = Ip->p, val = Ip->val;
763 28 : long condp = -1, va0, va5, r, n;
764 28 : va0 = myval(I->a0,p);
765 28 : va5 = myval(I->A5,p);
766 28 : if (!gequal0(I->A5) && 20*va0+val[6] > 6*va5)
767 21 : get_nr(ssQ_denom(5*val[6]-6*va5, 40), val[6]-2*va5, 20, &n,&r);
768 : else
769 7 : get_nr(ssQ_denom(5*va0-val[6], 10), 10*va0-val[6], 30, &n,&r);
770 28 : switch(n)
771 : {
772 0 : case 1:
773 0 : condp = 0;
774 0 : Ip->type = "[I{0-0-0}] page 155";
775 0 : Ip->neron = cyclic(1); break;
776 21 : case 2:
777 21 : switch(r)
778 : {
779 14 : case 0:
780 14 : condp = 4;
781 14 : Ip->type = "[I*{0-0-0}] page 155";
782 14 : Ip->neron = mkvecsmall4(2,2,2,2); break;
783 7 : case 1:
784 7 : condp = 2;
785 7 : Ip->type = "[II] page 155";
786 7 : Ip->neron = cyclic(1); break;
787 0 : default: pari_err_BUG("tame_1 [bug1]");
788 : }
789 21 : break;
790 7 : case 4:
791 7 : condp = 4;
792 7 : Ip->type = "[VI] page 156";
793 7 : Ip->neron = dicyclic(2,2); break;
794 0 : default: pari_err_BUG("tame_1 [bug8]");
795 : }
796 28 : return condp;
797 : }
798 :
799 : /* (4.2) */
800 : static long
801 203 : tame_234_init(struct igusa *I, struct igusa_p *Ip, long *n, long *q, long *r)
802 : {
803 203 : long va0, va5, vb2, v12 = -1, flc = 1;
804 203 : GEN p = Ip->p;
805 203 : switch(Ip->tt)
806 : {
807 91 : case 2: v12 = myval(I->i12, Ip->p); break;
808 56 : case 3: v12 = 3*myval(I->i4, Ip->p); break;
809 56 : case 4: v12 = 6*myval(I->j2, Ip->p); break;
810 : }
811 203 : va0 = myval(I->a0,p);
812 203 : va5 = myval(I->A5,p);
813 203 : vb2 = myval(I->B2,p);
814 203 : if (9*vb2 >= 6*va0+v12 && 36*va5 >= 120*va0+5*v12)
815 : {
816 42 : get_nrq(12*va0-v12,36, 6*va0-v12,12, n, r, q);
817 : }
818 161 : else if (120*va0+5*v12 > 36*va5 && 60*vb2 >= 12*va5+5*v12)
819 : {
820 49 : ssQ_red(36*va5-25*v12,240, q,n);
821 49 : *r = umodsu(-2* *q, *n);
822 : }
823 : else /* 6*va0+v12 > 9*vb2 && 12*va5+5*v12 > 60*vb2 */
824 : {
825 112 : get_nrq(v12-6*vb2,12, v12-9*vb2,12, n,r,q);
826 112 : flc = 0;
827 : }
828 203 : return flc;
829 : }
830 :
831 : /* Ip->tt = 2 */
832 : static long
833 91 : tame_2(struct igusa *I, struct igusa_p *Ip)
834 : {
835 91 : long condp = -1, d, n, q, r;
836 91 : GEN val = Ip->val;
837 91 : (void)tame_234_init(I, Ip, &n, &q, &r);
838 91 : d = n * (6*val[6]-5*val[7]) / 6;
839 91 : switch(n)
840 : {
841 7 : case 1: condp = 1;
842 7 : Ip->type = stack_sprintf("[I{%ld-0-0}] page 170", d);
843 7 : Ip->neron = cyclic(d); break;
844 21 : case 2:
845 21 : switch(r)
846 : {
847 7 : case 0: condp = 4;
848 7 : Ip->type = stack_sprintf("[I*{%ld-0-0}] page 171",d/2);
849 7 : Ip->neron = shallowconcat(dicyclic(2,2),groupH(d/2)); break;
850 14 : case 1:
851 14 : switch(q)
852 : {
853 7 : case 0: condp = 2;
854 7 : Ip->type = stack_sprintf("[II*{%ld-0}] page 172",d/2);
855 7 : Ip->neron = cyclic(1); break;
856 7 : case 1: condp = 3;
857 7 : Ip->type = stack_sprintf("[II{%ld-0}] page 171",d/2);
858 7 : Ip->neron = cyclic(2*d); break;
859 0 : default: pari_err_BUG("tame2 [bug10]");
860 : }
861 14 : break;
862 0 : default: pari_err_BUG("tame2 [bug11]");
863 : }
864 21 : break;
865 14 : case 3: condp = 3;
866 14 : Ip->neron = cyclic(d);
867 14 : switch(r)
868 : {
869 7 : case 1:
870 7 : Ip->type = stack_sprintf("[II{%ld}-IV] page 175", (d-2)/3);
871 7 : break;
872 7 : case 2:
873 7 : Ip->type = stack_sprintf("[II{%ld}-IV*] page 175", (d-1)/3);
874 7 : break;
875 0 : default: pari_err_BUG("tame2 [bug12]");
876 : }
877 14 : break;
878 42 : case 4:
879 42 : switch(r)
880 : {
881 21 : case 1:
882 21 : switch(q)
883 : {
884 14 : case 1: condp = 3;
885 14 : Ip->type = stack_sprintf("[II{%ld}-III] page 177",(d-2)/4);
886 14 : Ip->neron = cyclic(d/2); break;
887 7 : case 3: condp = 4;
888 7 : Ip->type = stack_sprintf("[II*{%ld}-III*] page 178",(d-2)/4);
889 7 : Ip->neron = cyclic(8); break;
890 0 : default: pari_err_BUG("tame2 [bug13]");
891 : }
892 21 : break;
893 21 : case 3:
894 21 : switch(q)
895 : {
896 7 : case 1: condp = 4;
897 7 : Ip->type = stack_sprintf("[II*{%ld}-III] page 178",(d-2)/4);
898 7 : Ip->neron = cyclic(8); break;
899 14 : case 3: condp = 3;
900 14 : Ip->type = stack_sprintf("[II{%ld}-III*] page 178",(d-2)/4);
901 14 : Ip->neron = cyclic(d/2); break;
902 0 : default: pari_err_BUG("tame2 [bug14]");
903 : }
904 21 : break;
905 0 : default: pari_err_BUG("tame2 [bug15]");
906 : }
907 42 : break;
908 7 : case 6:
909 7 : switch(r)
910 : {
911 7 : case 2: condp = 4;
912 7 : Ip->type = stack_sprintf("[II*-II*{%ld}] page 176", (d-4)/6);
913 7 : Ip->neron = groupH((d+2)/6); break;
914 0 : case 4: condp = 4;
915 0 : Ip->type = stack_sprintf("[II-II*{%ld}] page 176", (d-2)/6);
916 0 : Ip->neron = groupH((d+4)/6); break;
917 0 : default: pari_err_BUG("tame2 [bug16]");
918 : }
919 7 : break;
920 0 : default: pari_err_BUG("tame2 [bug17]");
921 : }
922 91 : return condp;
923 : }
924 :
925 : /* Ip->tt = 3 */
926 : static long
927 56 : tame_3(struct igusa *I, struct igusa_p *Ip)
928 : {
929 56 : long condp = -1, n, q, r, va5, d1, d2;
930 56 : long flc = tame_234_init(I, Ip, &n, &q, &r);
931 56 : GEN val = Ip->val;
932 :
933 56 : va5 = 2*val[6]-5*val[3];
934 56 : d1 = minss(n * (val[7]-3*val[3]), n * va5 / 4);
935 56 : d2 = n * va5 / 2 - d1;
936 56 : switch(n)
937 : {
938 14 : case 1: condp = 2;
939 14 : Ip->type = stack_sprintf("[I{%ld-%ld-0}] page 179", d1,d2);
940 14 : Ip->neron = dicyclic(d1,d2); break;
941 28 : case 2:
942 28 : switch(r)
943 : {
944 14 : case 0: condp = 4;
945 14 : Ip->type = stack_sprintf("[I*{%ld-%ld-0}] page 180", d1/2,d2/2);
946 14 : Ip->neron = shallowconcat(groupH(d1/2),groupH(d2/2)); break;
947 14 : case 1: condp = 3;
948 14 : if (flc)
949 : {
950 14 : Ip->type = stack_sprintf("[2I{%ld}-0] page 181", d1);
951 14 : Ip->neron = cyclic(d1);
952 : }
953 : else
954 : { /* FIXME: "or" same with d1<->d2 */
955 0 : Ip->type = stack_sprintf("[II{%ld-%ld}] page 182",d1/2,d2/2);
956 0 : Ip->neron = ((d1*d2-4)&7)? cyclic(2*d1): dicyclic(d1,2);
957 : }
958 14 : break;
959 0 : default: pari_err_BUG("tame3 [bug20]");
960 : }
961 28 : break;
962 14 : case 4: condp = 4;
963 14 : Ip->type = stack_sprintf("[III{%ld}] page 182", d1/2);
964 14 : Ip->neron = groupH(d1/2); break;
965 0 : default: pari_err_BUG("tame3 [bug21]");
966 : }
967 56 : return condp;
968 : }
969 :
970 : /* Ip->tt = 4 */
971 : static long
972 56 : tame_4(struct igusa *I, struct igusa_p *Ip)
973 : {
974 56 : long condp = -1, d1,d2,d3, f1,f2, g, h, n, q, r, vl,vn,vm, e1,e2,e3;
975 56 : GEN val = Ip->val;
976 56 : (void)tame_234_init(I, Ip, &n, &q, &r);
977 56 : vl = val[6]-5*val[1];
978 56 : vn = val[7]-6*val[1];
979 56 : vm = val[2]-2*val[1]; /* all >= 0 */
980 56 : e1 = min3(2*vl, 3*vn, 6*vm);
981 56 : e2 = minss(6*vl - e1, 12*vn - 2*e1); /* >= 0 */
982 56 : e3 = 12*vl - (2*e1+e2); /* >= 0 */
983 56 : d1 = e1*n / 6;
984 56 : d2 = e2*n / 12;
985 56 : d3 = e3*n / 12;
986 56 : g = d1*d2 + d1*d3 + d2*d3;
987 56 : h = ugcd(ugcd(d1,d2),d3);
988 56 : switch(n)
989 : {
990 7 : case 1: condp = 2;
991 7 : Ip->type = stack_sprintf("[I{%ld-%ld-%ld}] page 182",d1,d2,d3);
992 7 : Ip->neron = dicyclic(h,g/h); break;
993 49 : case 2:
994 49 : switch(r)
995 : {
996 7 : case 0: condp = 4;
997 7 : Ip->type = stack_sprintf("[I*{%ld-%ld-%ld}] page 183",d1/2,d2/2,d3/2);
998 7 : Ip->neron = shallowconcat(groupH(g/4), groupH(2-((h&2)>>1))); break;
999 42 : case 1:
1000 42 : if (d1 == d2 || d1 == d3) f2 = d1;
1001 0 : else if (d2 == d3) f2 = d2;
1002 : else {
1003 0 : pari_err_BUG("tame4 [bug23]");
1004 : return -1; /*LCOV_EXCL_LINE*/
1005 : }
1006 42 : f1 = d1+d2+d3-2*f2;
1007 42 : switch(q)
1008 : {
1009 14 : case 0: condp = 3;
1010 14 : Ip->type = stack_sprintf("[II*{%ld-%ld}] page 184", f1/2,f2);
1011 14 : Ip->neron = cyclic(f2); break;
1012 28 : case 1: condp = 3;
1013 28 : Ip->type = stack_sprintf("[II{%ld-%ld}] page 183", f1/2,f2);
1014 28 : Ip->neron = cyclic(2*f1+f2); break;
1015 0 : default: pari_err_BUG("tame4 [bug24]");
1016 : }
1017 42 : break;
1018 0 : default: pari_err_BUG("tame4 [bug25]");
1019 : }
1020 49 : break;
1021 0 : case 3: condp = 4;
1022 0 : Ip->type = stack_sprintf("[III{%ld}] page 184",d1);
1023 0 : Ip->neron = (d1%3)? cyclic(9): dicyclic(3,3); break;
1024 0 : case 6: condp = 4;
1025 0 : Ip->type = stack_sprintf("[III*{%ld}] page 184",d1/2);
1026 0 : Ip->neron = cyclic(1); break;
1027 0 : default: pari_err_BUG("tame4 [bug26]");
1028 : }
1029 56 : return condp;
1030 : }
1031 :
1032 : /* p = 3 */
1033 : static void
1034 91 : tame_567_init_3(struct igusa_p *Ip, long dk,
1035 : long *pd, long *pn, long *pdm, long *pr)
1036 : {
1037 91 : long n = 1 + Ip->r1/6;
1038 91 : *pd = n * dk / 36; /* / (12*Ip->eps) */
1039 91 : *pn = n;
1040 91 : *pr = -1; /* unused */
1041 91 : *pdm = 0;
1042 91 : }
1043 :
1044 : /* (4.3) */
1045 : static void
1046 609 : tame_567_init(struct igusa *I, struct igusa_p *Ip, long dk,
1047 : long *pd, long *pn, long *pdm, long *pr)
1048 : {
1049 : long ndk, ddk;
1050 609 : GEN p = Ip->p, val = Ip->val;
1051 :
1052 609 : if (equaliu(p,3)) { tame_567_init_3(Ip, dk, pd, pn, pdm, pr); return; }
1053 : /* assume p > 3, Ip->eps = 1 */
1054 518 : ssQ_red(dk, 12, &ndk, &ddk);
1055 518 : if (! odd(val[8]))
1056 : {
1057 427 : long va0 = myval(I->a0,p), va2 = myval(I->A2,p), va3 = myval(I->A3,p);
1058 427 : long va5 = myval(I->A5,p), vb2 = myval(I->B2,p);
1059 427 : long v1 = 2*va3-4*va0-val[1], v2 = 6*va5-20*va0-5*val[1];
1060 427 : long v3 = 3*vb2-2*va0-2*val[1], v4 = 10*vb2-2*va5-5*val[1];
1061 427 : if (v3 >= 0 && v2 >= 0 && v1 >= 0)
1062 : {
1063 476 : if (v1==0 || v2==0) get_nr(ddk, va0+val[1], 6,pn,pr); /* Prop 4.3.1 (a) */
1064 : else
1065 : { /* Prop 4.3.1 (d) */
1066 231 : long v5 = myval(subii(mulii(I->A2,I->A3),mului(3,I->A5)),p);
1067 231 : if (gequal0(I->A2)) pari_err_BUG("tame567 [bug27]");
1068 231 : get_nr(ddk, 12*va0 + min3(dk, 6*va3-9*va2, 4*v5 - 10*va2), 24, pn,pr);
1069 : }
1070 : }
1071 182 : else if (v2 < 0 && v4 >= 0)
1072 182 : get_nr(ddk, 2*va5+val[1], 8, pn,pr); /* Prop 4.3.1 (b) */
1073 : else /* (v3 < 0 && v4 < 0) */
1074 0 : get_nr(ddk, vb2, 4, pn,pr); /* Prop 4.3.1 (c) */
1075 427 : *pd = (*pn/ddk) * ndk;
1076 : }
1077 : else
1078 : {
1079 91 : *pr = ndk;
1080 91 : *pn = 2*ddk;
1081 91 : *pd = 2*ndk;
1082 : }
1083 518 : *pdm = umodsu(*pd, *pn);
1084 : }
1085 :
1086 : static long
1087 329 : tame_5(struct igusa *I, struct igusa_p *Ip)
1088 : {
1089 329 : long condp = -1, d, n, dm, r, dk;
1090 329 : GEN val = Ip->val;
1091 :
1092 329 : dk = Ip->eps*val[6]-5*val[8];
1093 329 : tame_567_init(I, Ip, dk, &d, &n, &dm, &r);
1094 329 : if (! odd(val[8]))
1095 : {
1096 266 : switch(n)
1097 : {
1098 7 : case 1: condp = 0;
1099 7 : Ip->type = stack_sprintf("[I{0}-I{0}-%ld] page 158", d);
1100 7 : Ip->neron = cyclic(1); break;
1101 14 : case 2:
1102 14 : switch(dm)
1103 : {
1104 7 : case 0: condp = 4;
1105 7 : Ip->type = stack_sprintf("[I*{0}-I*{0}-%ld] page 158",(d-2)/2);
1106 7 : Ip->neron = mkvecsmall4(2,2,2,2); break;
1107 7 : case 1: condp = 2;
1108 7 : Ip->type = stack_sprintf("[I{0}-I*{0}-%ld] page 159",(d-1)/2);
1109 7 : Ip->neron = dicyclic(2,2); break;
1110 : }
1111 14 : break;
1112 35 : case 3:
1113 35 : switch(dm)
1114 : {
1115 7 : case 0: condp = 4;
1116 7 : Ip->type = stack_sprintf("[IV-IV*-%ld] page 165",(d-3)/3);
1117 7 : Ip->neron = dicyclic(3,3); break;
1118 14 : case 1:
1119 14 : switch(r)
1120 : {
1121 7 : case 0: case 1: condp = 2;
1122 7 : Ip->type = stack_sprintf("[I{0}-IV-%ld] page 160",(d-1)/3);
1123 7 : Ip->neron = cyclic(3); break;
1124 7 : case 2: condp = 4;
1125 7 : Ip->type = stack_sprintf("[IV*-IV*-%ld] page 166",(d-4)/3);
1126 7 : Ip->neron = dicyclic(3,3); break;
1127 : }
1128 14 : break;
1129 14 : case 2:
1130 14 : switch(r)
1131 : {
1132 7 : case 0: case 2: condp = 2;
1133 7 : Ip->type = stack_sprintf("[I{0}-IV*-%ld] page 160",(d-2)/3);
1134 7 : Ip->neron = cyclic(3); break;
1135 7 : case 1: condp = 4;
1136 7 : Ip->type = stack_sprintf("[IV-IV-%ld] page 165",(d-2)/3);
1137 7 : Ip->neron = dicyclic(3,3); break;
1138 : }
1139 14 : break;
1140 : }
1141 35 : break;
1142 49 : case 4:
1143 49 : switch(dm)
1144 : {
1145 7 : case 0: condp = 4;
1146 7 : Ip->type = stack_sprintf("[III-III*-%ld] page 169",(d-4)/4);
1147 7 : Ip->neron = dicyclic(2,2); break;
1148 14 : case 1:
1149 14 : switch(r)
1150 : {
1151 7 : case 0: case 1: condp = 2;
1152 7 : Ip->type = stack_sprintf("[I{0}-III-%ld] page 161",(d-1)/4);
1153 7 : Ip->neron = cyclic(2); break;
1154 7 : case 2: case 3: condp = 4;
1155 7 : Ip->type = stack_sprintf("[I*{0}-III*-%ld] page 162",(d-5)/4);
1156 7 : Ip->neron = mkvecsmall3(2,2,2); break;
1157 : }
1158 14 : break;
1159 14 : case 2: condp = 4;
1160 14 : Ip->neron = dicyclic(2,2);
1161 14 : switch(r)
1162 : {
1163 7 : case 1:
1164 7 : Ip->type = stack_sprintf("[III-III-%ld] page 169",(d-2)/4);
1165 7 : break;
1166 7 : case 3:
1167 7 : Ip->type = stack_sprintf("[III*-III*-%ld] page 169",(d-6)/4);
1168 7 : break;
1169 0 : default: pari_err_BUG("tame5 [bug29]");
1170 : }
1171 14 : break;
1172 14 : case 3:
1173 14 : switch(r)
1174 : {
1175 7 : case 0: case 3: condp = 2;
1176 7 : Ip->type = stack_sprintf("[I{0}-III*-%ld] page 162",(d-3)/4);
1177 7 : Ip->neron = cyclic(2); break;
1178 7 : case 1: case 2: condp = 4;
1179 7 : Ip->type = stack_sprintf("[I*{0}-III-%ld] page 162",(d-3)/4);
1180 7 : Ip->neron = mkvecsmall3(2,2,2); break;
1181 : }
1182 14 : break;
1183 : }
1184 49 : break;
1185 105 : case 6:
1186 105 : switch(dm)
1187 : {
1188 7 : case 0: condp = 4;
1189 7 : Ip->type = stack_sprintf("[II-II*-%ld] page 163",(d-6)/6);
1190 7 : Ip->neron = cyclic(1); break;
1191 21 : case 1:
1192 21 : switch(r)
1193 : {
1194 7 : case 0: case 1: condp = 2;
1195 7 : Ip->type = stack_sprintf("[I{0}-II-%ld] page 159",(d-1)/6);
1196 7 : Ip->neron = cyclic(1); break;
1197 7 : case 2: case 5: condp = 4;
1198 7 : Ip->type = stack_sprintf("[II*-IV-%ld] page 164",(d-7)/6);
1199 7 : Ip->neron = cyclic(3); break;
1200 7 : case 3: case 4: condp = 4;
1201 7 : Ip->type = stack_sprintf("[I*{0}-IV*-%ld] page 161",(d-7)/6);
1202 7 : Ip->neron = mkvecsmall2(6,2); break;
1203 : }
1204 21 : break;
1205 21 : case 2:
1206 21 : switch(r)
1207 : {
1208 14 : case 1: condp = 4;
1209 14 : Ip->type = stack_sprintf("[II-II-%ld] page 163",(d-2)/6);
1210 14 : Ip->neron = cyclic(1); break;
1211 7 : case 3: case 5: condp = 4;
1212 7 : Ip->type = stack_sprintf("[I*{0}-II*-%ld] page 160",(d-8)/6);
1213 7 : Ip->neron = dicyclic(2,2); break;
1214 0 : default: pari_err_BUG("tame5 [bug30]");
1215 : }
1216 21 : break;
1217 14 : case 3:
1218 14 : Ip->neron = cyclic(3);
1219 14 : switch(r)
1220 : {
1221 7 : case 1: case 2: condp = 4;
1222 7 : Ip->type = stack_sprintf("[II-IV-%ld] page 164",(d-3)/6);
1223 7 : break;
1224 7 : case 4: case 5: condp = 4;
1225 7 : Ip->type = stack_sprintf("[II*-IV*-%ld] page 164",(d-9)/6);
1226 7 : break;
1227 0 : default: pari_err_BUG("tame5 [bug31]");
1228 : }
1229 14 : break;
1230 21 : case 4:
1231 21 : switch(r)
1232 : {
1233 7 : case 1: case 3: condp = 4;
1234 7 : Ip->type = stack_sprintf("[I*{0}-II-%ld] page 160",(d-4)/6);
1235 7 : Ip->neron = dicyclic(2,2); break;
1236 14 : case 5: condp = 4;
1237 14 : Ip->type = stack_sprintf("[II*-II*-%ld] page 163",(d-10)/6);
1238 14 : Ip->neron = cyclic(1); break;
1239 0 : default: pari_err_BUG("tame5 [bug32]");
1240 : }
1241 21 : break;
1242 21 : case 5:
1243 21 : switch(r)
1244 : {
1245 7 : case 0: case 5: condp = 2;
1246 7 : Ip->type = stack_sprintf("[I{0}-II*-%ld] page 160",(d-5)/6);
1247 7 : Ip->neron = cyclic(1); break;
1248 7 : case 1: case 4: condp = 4;
1249 7 : Ip->type = stack_sprintf("[II-IV*-%ld] page 164",(d-5)/6);
1250 7 : Ip->neron = cyclic(3); break;
1251 7 : case 2: case 3: condp = 4;
1252 7 : Ip->type = stack_sprintf("[I*{0}-IV-%ld] page 161",(d-5)/6);
1253 7 : Ip->neron = mkvecsmall2(6,2); break;
1254 : }
1255 21 : break;
1256 0 : default: pari_err_BUG("tame5 [bug33]");
1257 : }
1258 105 : break;
1259 56 : case 12:
1260 56 : condp = 4;
1261 56 : switch(dm)
1262 : {
1263 14 : case 1:
1264 14 : switch(r)
1265 : {
1266 7 : case 3: case 10:
1267 7 : Ip->type = stack_sprintf("[II*-III-%ld] page 166",(d-13)/12);
1268 7 : Ip->neron = cyclic(2); break;
1269 7 : case 4: case 9:
1270 7 : Ip->type = stack_sprintf("[III*-IV-%ld] page 167",(d-13)/12);
1271 7 : Ip->neron = cyclic(6); break;
1272 0 : default: pari_err_BUG("tame5 [bug34]");
1273 : }
1274 14 : break;
1275 14 : case 5:
1276 14 : switch(r)
1277 : {
1278 7 : case 2: case 3:
1279 7 : Ip->type = stack_sprintf("[II-III-%ld] page 166",(d-5)/12);
1280 7 : Ip->neron = cyclic(2); break;
1281 7 : case 8: case 9:
1282 7 : Ip->type = stack_sprintf("[III*-IV*-%ld] page 168",(d-17)/12);
1283 7 : Ip->neron = cyclic(6); break;
1284 0 : default: pari_err_BUG("tame5 [bug35]");
1285 : }
1286 14 : break;
1287 14 : case 7:
1288 14 : switch(r)
1289 : {
1290 7 : case 3: case 4:
1291 7 : Ip->type = stack_sprintf("[III-IV-%ld] page 167",(d-7)/12);
1292 7 : Ip->neron = cyclic(6); break;
1293 7 : case 9: case 10:
1294 7 : Ip->type = stack_sprintf("[II*-III*-%ld] page 167",(d-19)/12);
1295 7 : Ip->neron = cyclic(2); break;
1296 0 : default: pari_err_BUG("tame5 [bug36]");
1297 : }
1298 14 : break;
1299 14 : case 11:
1300 14 : switch(r)
1301 : {
1302 7 : case 3: case 8:
1303 7 : Ip->type = stack_sprintf("[III-IV*-%ld] page 168",(d-11)/12);
1304 7 : Ip->neron = cyclic(6); break;
1305 7 : case 2: case 9:
1306 7 : Ip->type = stack_sprintf("[II-III*-%ld] page 166",(d-11)/12);
1307 7 : Ip->neron = cyclic(2); break;
1308 0 : default: pari_err_BUG("tame5 [bug37]");
1309 : }
1310 14 : break;
1311 0 : default: pari_err_BUG("tame5 [bug38]");
1312 : }
1313 56 : break;
1314 0 : default: pari_err_BUG("tame5 [bug39]");
1315 : }
1316 : }
1317 : else
1318 : {
1319 63 : r %= (n >> 1);
1320 63 : switch(n)
1321 : {
1322 7 : case 2: condp = 2;
1323 7 : Ip->type = stack_sprintf("[2I{0}-%ld] page 159",(d/2));
1324 7 : Ip->neron = cyclic(1); break;
1325 14 : case 4: condp = 4;
1326 14 : Ip->type = stack_sprintf("[2I*{0}-%ld] page 159",(d/2-1)/2);
1327 14 : Ip->neron = dicyclic(2,2); break;
1328 14 : case 6: condp = 4;
1329 14 : Ip->neron = cyclic(3);
1330 14 : switch(r)
1331 : {
1332 7 : case 1:
1333 7 : Ip->type = stack_sprintf("[2IV-%ld] page 165",(d/2-1)/3);
1334 7 : break;
1335 7 : case 2:
1336 7 : Ip->type = stack_sprintf("[2IV*-%ld] page 165",(d/2-2)/3);
1337 7 : break;
1338 0 : default: pari_err_BUG("tame5 [bug40]");
1339 : }
1340 14 : break;
1341 14 : case 8: condp = 4;
1342 14 : Ip->neron = cyclic(2);
1343 14 : switch(r)
1344 : {
1345 7 : case 1:
1346 7 : Ip->type = stack_sprintf("[2III-%ld] page 168",(d/2-1)/4);
1347 7 : break;
1348 7 : case 3:
1349 7 : Ip->type = stack_sprintf("[2III*-%ld] page 168",(d/2-3)/4);
1350 7 : break;
1351 0 : default: pari_err_BUG("tame5 [bug41]");
1352 : }
1353 14 : break;
1354 14 : case 12: condp = 4;
1355 14 : Ip->neron = cyclic(1);
1356 14 : switch(r)
1357 : {
1358 7 : case 1:
1359 7 : Ip->type = stack_sprintf("[2II-%ld] page 162",(d/2-1)/6);
1360 7 : break;
1361 7 : case 5:
1362 7 : Ip->type = stack_sprintf("[2II*-%ld] page 163",(d/2-5)/6);
1363 7 : break;
1364 0 : default: pari_err_BUG("tame5 [bug42]");
1365 : }
1366 14 : break;
1367 0 : default: pari_err_BUG("tame5 [bug43]");
1368 : }
1369 : }
1370 329 : return condp;
1371 : }
1372 :
1373 : static long
1374 189 : tame_6(struct igusa *I, struct igusa_p *Ip)
1375 : {
1376 189 : long condp = -1, d, d1, n, dm, r, dk;
1377 189 : GEN val = Ip->val;
1378 :
1379 189 : dk = Ip->eps*val[7]-6*val[8];
1380 189 : tame_567_init(I, Ip, dk, &d, &n, &dm, &r);
1381 189 : d1 = n * (Ip->eps*(val[6]-val[7])+val[8]) / Ip->eps;
1382 189 : switch(n)
1383 : {
1384 56 : case 1: condp = 1;
1385 56 : Ip->type = stack_sprintf("[I{0}-I{%ld}-%ld] page 170",d1,d);
1386 56 : Ip->neron = cyclic(d1); break;
1387 28 : case 2:
1388 28 : switch(dm)
1389 : {
1390 7 : case 0: condp = 4;
1391 7 : Ip->type=stack_sprintf("[I*{0}-I*{%ld}-%ld] page 171", d1/2,(d-2)/2);
1392 7 : Ip->neron = shallowconcat(groupH(d1/2), dicyclic(2,2)); break;
1393 21 : case 1: return -1;
1394 0 : default: pari_err_BUG("tame6 [bug44]");
1395 : }
1396 7 : break;
1397 14 : case 3: condp = 3;
1398 14 : Ip->neron = dicyclic(3,d1/3);
1399 14 : switch(dm)
1400 : {
1401 7 : case 1:
1402 7 : Ip->type = stack_sprintf("[I{%ld}-IV-%ld] page 173",d1/3,(d-1)/3);
1403 7 : break;
1404 7 : case 2:
1405 7 : Ip->type = stack_sprintf("[I{%ld}-IV*-%ld] page 173",d1/3,(d-2)/3);
1406 7 : break;
1407 0 : default: pari_err_BUG("tame6 [bug45]");
1408 : }
1409 14 : break;
1410 35 : case 4:
1411 35 : switch(dm)
1412 : {
1413 21 : case 1:
1414 21 : switch(r)
1415 : {
1416 7 : case 0: case 1: condp = 3;
1417 7 : Ip->type=stack_sprintf("[I{%ld}-III-%ld] page 176",d1/4,(d-1)/4);
1418 7 : Ip->neron = dicyclic(2,d1/4); break;
1419 14 : case 2: case 3: condp = 4;
1420 14 : Ip->type=stack_sprintf("[I*{%ld}-III*-%ld] page 177",d1/4,(d-5)/4);
1421 14 : Ip->neron = shallowconcat(groupH(d1/4), cyclic(2)); break;
1422 0 : default: pari_err_BUG("tame6 [bug46]");
1423 : }
1424 21 : break;
1425 14 : case 3:
1426 14 : switch(r)
1427 : {
1428 7 : case 0: case 3: condp = 3;
1429 7 : Ip->type=stack_sprintf("[I{%ld}-III*-%ld] page 176",d1/4,(d-3)/4);
1430 7 : Ip->neron = dicyclic(2,d1/4); break;
1431 7 : case 1: case 2: condp = 4;
1432 7 : Ip->type=stack_sprintf("[I*{%ld}-III-%ld] page 177",d1/4,(d-3)/4);
1433 7 : Ip->neron = shallowconcat(groupH(d1/4), cyclic(2)); break;
1434 0 : default: pari_err_BUG("tame6 [bug47]");
1435 : }
1436 14 : break;
1437 0 : default: pari_err_BUG("tame6 [bug48]");
1438 : }
1439 35 : break;
1440 56 : case 6:
1441 56 : switch(dm)
1442 : {
1443 21 : case 1:
1444 21 : switch(r)
1445 : {
1446 7 : case 0: case 1: condp = 3;
1447 7 : Ip->type = stack_sprintf("[I{%ld}-II-%ld] page 172",d1/6,(d-1)/6);
1448 7 : Ip->neron = cyclic(d1/6); break;
1449 14 : case 3: case 4: condp = 4;
1450 14 : Ip->type=stack_sprintf("[I*{%ld}-IV*-%ld] page 174",d1/6,(d-7)/6);
1451 14 : Ip->neron = shallowconcat(groupH(d1/6), cyclic(3)); break;
1452 0 : default: pari_err_BUG("tame6 [bug49]");
1453 : }
1454 21 : break;
1455 14 : case 2: condp = 4;
1456 14 : Ip->type = stack_sprintf("[I*{%ld}-II*-%ld] page 174",d1/6,(d-8)/6);
1457 14 : Ip->neron = groupH(d1/6); break;
1458 7 : case 4: condp = 4;
1459 7 : Ip->type = stack_sprintf("[I*{%ld}-II-%ld] page 173",d1/6,(d-4)/6);
1460 7 : Ip->neron = groupH(d1/6); break;
1461 14 : case 5:
1462 14 : switch(r)
1463 : {
1464 7 : case 0: case 5: condp = 3;
1465 7 : Ip->type=stack_sprintf("[I{%ld}-II*-%ld] page 172",d1/6,(d-5)/6);
1466 7 : Ip->neron = cyclic(d1/6); break;
1467 7 : case 2: case 3: condp = 4;
1468 7 : Ip->type=stack_sprintf("[I*{%ld}-IV-%ld] page 174",d1/6,(d-5)/6);
1469 7 : Ip->neron = shallowconcat(groupH(d1/6), cyclic(3)); break;
1470 0 : default: pari_err_BUG("tame6 [bug50]");
1471 : }
1472 14 : break;
1473 0 : default: pari_err_BUG("tame6 [bug51]");
1474 : }
1475 56 : break;
1476 0 : default: pari_err_BUG("tame6 [bug52]");
1477 : }
1478 168 : return condp;
1479 : }
1480 :
1481 : static long
1482 91 : tame_7(struct igusa *I, struct igusa_p *Ip)
1483 : {
1484 91 : long condp = -1, d, D, d1, d2, n, dm, r, dk;
1485 91 : GEN val = Ip->val;
1486 :
1487 91 : dk = 3*(Ip->eps*val[3]-2*val[8]);
1488 91 : tame_567_init(I, Ip, dk, &d, &n, &dm, &r);
1489 91 : D = n * (Ip->eps*(val[6]-3*val[3])+val[8]) / Ip->eps;
1490 91 : d1 = minss(n * (val[7]-3*val[3]), D/2);
1491 91 : d2 = D - d1;
1492 : /* d1 <= d2 */
1493 91 : switch(n)
1494 : {
1495 42 : case 1: condp = 2;
1496 42 : Ip->type = stack_sprintf("[I{%ld}-I{%ld}-%ld] page 179",d1,d2,d);
1497 42 : Ip->neron = dicyclic(d1,d2); break;
1498 35 : case 2:
1499 35 : if (odd(val[8]))
1500 : {
1501 14 : condp = 3;
1502 14 : Ip->type = stack_sprintf("[2I{%ld}-%ld] page 181",d1,d/2);
1503 14 : Ip->neron = cyclic(d1);
1504 : }
1505 21 : else if (dm == 0)
1506 : {
1507 14 : condp = 4;
1508 14 : Ip->type = stack_sprintf("[I*{%ld}-I*{%ld}-%ld] page 180", d1/2,d2/2,(d-2)/2);
1509 14 : Ip->neron = shallowconcat(groupH(d1/2),groupH(d2/2));
1510 : }
1511 : else
1512 : {
1513 : GEN H;
1514 7 : if (d1 != d2) return -1;
1515 0 : condp = 3; H = groupH(d1/2);
1516 0 : Ip->type = stack_sprintf("[I{%ld}-I*{%ld}-%ld] page 180", d1/2,d1/2,(d-1)/2);
1517 0 : Ip->neron = shallowconcat(H, H);
1518 : }
1519 28 : break;
1520 14 : case 4: condp = 4;
1521 14 : Ip->type = stack_sprintf("[2I*{%ld}-%ld] page 181",d1/2,(d-2)/4);
1522 14 : Ip->neron = groupH(d1/2); break;
1523 0 : default: pari_err_BUG("tame7 [bug55]");
1524 : }
1525 84 : return condp;
1526 : }
1527 :
1528 : static long labelm3(GEN polh, long t60, long alpha, long Dmin, struct igusa *I, struct igusa_p *Ip);
1529 : static long
1530 840 : tame(GEN polh, long t60, long alpha, long Dmin, struct igusa *I, struct igusa_p *Ip)
1531 : {
1532 : long d;
1533 840 : Ip->tame = 1;
1534 840 : switch(Ip->tt)
1535 : {
1536 28 : case 1: return tame_1(I,Ip);
1537 91 : case 2: return tame_2(I,Ip);
1538 56 : case 3: return tame_3(I,Ip);
1539 56 : case 4: return tame_4(I,Ip);
1540 329 : case 5: return tame_5(I,Ip);
1541 189 : case 6: d = tame_6(I,Ip); break;
1542 91 : default:d = tame_7(I,Ip); break;
1543 : }
1544 280 : if (d < 0) d = labelm3(polh,t60,alpha,Dmin,I,Ip); /* => tt=6 or 7 */
1545 280 : return d;
1546 : }
1547 :
1548 : /* maxc = maximum conductor valuation at p */
1549 : static long
1550 497 : get_maxc(GEN p)
1551 : {
1552 497 : switch (itos_or_0(p))
1553 : {
1554 0 : case 2: return 20; break;
1555 301 : case 3: return 10; break;
1556 14 : case 5: return 9; break;
1557 182 : default: return 4; break; /* p > 5 */
1558 : }
1559 : }
1560 :
1561 : /* p = 3 */
1562 : static long
1563 84 : quartic(GEN polh, long alpha, long Dmin, struct igusa_p *Ip)
1564 : {
1565 84 : GEN val = Ip->val, p = Ip->p;
1566 84 : GEN polf = polymini_zi2(ZX_Z_mul(polh, powiu(p, alpha)));
1567 84 : long condp = -1, d, R, r1, beta;
1568 84 : r1 = polf[1];
1569 84 : beta = polf[2];
1570 84 : R = beta/2;
1571 84 : switch(Ip->tt)
1572 : {
1573 70 : case 1: case 5: d = 0;break;
1574 0 : case 3: d = val[6] - 5*val[3]/2;break;
1575 14 : case 7: d = val[6] - 3*val[3] + val[8]/Ip->eps;break;
1576 0 : default: pari_err_BUG("quartic [type choices]");
1577 : d = 0; /*LCOV_EXCL_LINE*/
1578 : }
1579 84 : switch(r1)
1580 : {
1581 21 : case 0:
1582 21 : if (d)
1583 : {
1584 7 : condp = 3;
1585 7 : Ip->type = stack_sprintf("[2I{%ld}-%ld] page 181",d,R);
1586 7 : Ip->neron = cyclic(d);
1587 : }
1588 : else
1589 : {
1590 14 : condp = 2;
1591 14 : Ip->neron = cyclic(1);
1592 14 : if (R) Ip->type = stack_sprintf("[2I{0}-%ld] page 159",R);
1593 7 : else Ip->type = "[II] page 155";
1594 : }
1595 21 : break;
1596 14 : case 6: condp = 4;
1597 14 : Ip->type = stack_sprintf("[2I*{%ld}-%ld] pages 159, 181",d,R);
1598 14 : Ip->neron = dicyclic(2,2); break;
1599 7 : case 3: condp = 4;
1600 7 : Ip->type = stack_sprintf("[2III-%ld] page 168",R);
1601 7 : Ip->neron = cyclic(2); break;
1602 7 : case 9: condp = 4;
1603 7 : Ip->type = stack_sprintf("[2III*-%ld] page 168",R);
1604 7 : Ip->neron = cyclic(2); break;
1605 7 : case 2: condp = Dmin-12*R-13;
1606 7 : Ip->type = stack_sprintf("[2II-%ld] page 162",R);
1607 7 : Ip->neron = cyclic(1); break;
1608 14 : case 8: condp = Dmin-12*R-19;
1609 14 : Ip->type = stack_sprintf("[2IV*-%ld] page 165",R);
1610 14 : Ip->neron = cyclic(3); break;
1611 7 : case 4: condp = Dmin-12*R-15;
1612 7 : Ip->type = stack_sprintf("[2IV-%ld] page 165",R);
1613 7 : Ip->neron = cyclic(3); break;
1614 7 : case 10: condp = Dmin-12*R-21;
1615 7 : Ip->type = stack_sprintf("[2II*-%ld] page 163",R);
1616 7 : Ip->neron = cyclic(1); break;
1617 0 : default: pari_err_BUG("quartic [type1]");
1618 : }
1619 84 : if (condp > get_maxc(p) || condp < 0) pari_err_BUG("quartic [conductor]");
1620 84 : return condp;
1621 : }
1622 :
1623 : static long
1624 280 : litredtp(long alpha, long alpha1, long t60, long t60_1, GEN polh, GEN polh1,
1625 : long Dmin, long R, struct igusa *I, struct igusa_p *Ip)
1626 : {
1627 280 : GEN val = Ip->val, p = Ip->p;
1628 280 : long condp = -1, indice, d;
1629 :
1630 280 : if ((Ip->r1 == 0||Ip->r1 == 6) && (Ip->r2 == 0||Ip->r2 == 6))
1631 : { /* (r1,r2) = (0,0), (0,6), (6,0) or (6,6) */
1632 154 : if (Ip->tt == 5)
1633 : {
1634 21 : switch(Ip->r1 + Ip->r2)
1635 : {
1636 7 : case 0: /* (0,0) */
1637 7 : condp = 0;
1638 7 : Ip->type = stack_sprintf("[I{0}-I{0}-%ld] page 158",R);
1639 7 : Ip->neron = cyclic(1); break;
1640 7 : case 6: /* (0,6) or (6,0) */
1641 7 : condp = 2;
1642 7 : Ip->type = stack_sprintf("[I{0}-I*{0}-%ld] page 159",R);
1643 7 : Ip->neron = dicyclic(2,2); break;
1644 7 : case 12: /* (6,6) */
1645 7 : condp = 4;
1646 7 : Ip->type = stack_sprintf("[I*{0}-I*{0}-%ld] page 158",R);
1647 7 : Ip->neron = mkvecsmall4(2,2,2,2); break;
1648 : }
1649 21 : return condp;
1650 : }
1651 133 : if (Ip->r1 == Ip->r2) return tame(polh, t60, alpha, Dmin, I, Ip);
1652 42 : if (Ip->tt == 6)
1653 : {
1654 28 : d = val[6] - val[7] + val[8]/Ip->eps;
1655 28 : if (Ip->r1 && alpha1 == 0) polh1 = ZX_unscale_divpow(polh1, p, 3);
1656 28 : if (FpX_is_squarefree(FpX_red(polh1,p),p))
1657 7 : { indice = 0; condp = 3-Ip->r2/6; }
1658 : else
1659 21 : { indice = d; condp = 3-Ip->r1/6; }
1660 : }
1661 : else
1662 : { /* Ip->tt == 7 */
1663 : long d1;
1664 14 : d = val[6] - 3*val[3] + val[8]/Ip->eps;
1665 14 : if (t60_1 == 60) polh1 = ZX_unscale_divpow(polh1, p, 3);
1666 14 : d1 = minss(val[7]-3*val[3],d/2);
1667 14 : if (d == 2*d1) indice = d1;
1668 : else
1669 : {
1670 14 : indice = discpart(polh1,p,d1+1);
1671 14 : if (indice>= d1+1) indice = d-d1; else indice = d1;
1672 : }
1673 14 : condp = 3;
1674 : }
1675 42 : if (Ip->r1) indice = d - indice; /* (r1,r2) = (6,0) */
1676 42 : Ip->neron = shallowconcat(cyclic(indice),groupH(d-indice));
1677 42 : Ip->type = stack_sprintf("[I{%ld}-I*{%ld}-%ld] page %ld",
1678 42 : indice,d-indice,R, (Ip->tt==6)? 170L: 180L);
1679 42 : return condp;
1680 : }
1681 126 : if (Ip->tt == 7) pari_err_BUG("litredtp [switch ri]");
1682 : {
1683 126 : struct red __S1, __S2, *S1 = &__S1, *S2 = &__S2;
1684 126 : long f1 = get_red(S1, Ip, polh1, p, alpha1, Ip->r1);
1685 126 : long f2 = get_red(S2, Ip, polh, p, alpha, Ip->r2);
1686 : /* reorder to normalize representation */
1687 126 : if (S1->tnum > S2->tnum || (S1->tnum == S2->tnum && f1 > f2))
1688 56 : { struct red *S = S1; S1 = S2; S2 = S; }
1689 126 : Ip->type = stack_sprintf("[%s-%s-%ld] pages %s", S1->t,S2->t, R, S1->pages);
1690 126 : Ip->neron = shallowconcat(S1->g, S2->g);
1691 126 : condp = Dmin - (f1 + f2) + ((R >= 0)? 2-12*R: 4);
1692 : }
1693 126 : if (condp > get_maxc(p)) pari_err_BUG("litredtp [conductor]");
1694 126 : return condp;
1695 : }
1696 :
1697 : static long
1698 259 : labelm3(GEN h1, long t60_1, long alpha1, long Dmin, struct igusa *I, struct igusa_p *Ip)
1699 : {
1700 259 : GEN h, pm, vs, val = Ip->val, p = Ip->p;
1701 : long alpha, t60, lambda, beta, R;
1702 :
1703 259 : pm = polymini(ZX_Z_mul(RgX_recip6(h1), powiu(p,alpha1)), p);
1704 259 : h = gel(pm,1); vs = gel(pm,2);
1705 259 : lambda= vs[1];
1706 259 : t60 = vs[2];
1707 259 : alpha = vs[3];
1708 259 : beta = vs[5];
1709 259 : if (lambda != 3) pari_err_BUG("labelm3 [lambda != 3]");
1710 259 : R = beta-(alpha1+alpha);
1711 259 : if (odd(R)) pari_err_BUG("labelm3 [R odd]");
1712 259 : R /= 2;
1713 259 : if (R <= -2) pari_err_BUG("labelm3 [R <= -2]");
1714 259 : if (val[8] % (2*Ip->eps)) pari_err_BUG("labelm3 [val(eps2)]");
1715 259 : if (R >= 0 && (alpha+alpha1) >= 1) pari_err_BUG("labelm3 [minimal equation]");
1716 259 : Ip->r1 = t60_1 / 10 + 6*alpha1;
1717 259 : Ip->r2 = t60 / 10 + 6*alpha;
1718 259 : return litredtp(alpha, alpha1, t60, t60_1, h, h1, Dmin, R, I, Ip);
1719 : }
1720 :
1721 : /* p = 3 */
1722 : static long
1723 21 : quadratic(GEN polh, long alpha, long Dmin, struct igusa *I, struct igusa_p *Ip)
1724 : {
1725 21 : long alpha1 = alpha, beta, t6, R;
1726 21 : GEN vs = polymini_zi(ZX_Z_mul(polh, powiu(Ip->p,alpha)));
1727 21 : t6 = vs[1];
1728 21 : alpha = vs[2];
1729 21 : beta = vs[3];
1730 21 : R = beta-alpha;
1731 21 : if (R >= 0 && alpha1)
1732 : {
1733 0 : Dmin -= 10;
1734 0 : if (DEBUGLEVEL)
1735 0 : err_printf("(Care: minimal discriminant over Z[i] smaller than over Z)\n");
1736 : }
1737 21 : Ip->r2 = Ip->r1 = t6 + 6*alpha;
1738 21 : return litredtp(alpha, alpha, t6*10, t6*10, polh, polh, Dmin, R, I, Ip);
1739 : }
1740 :
1741 : static long
1742 1435 : genus2localred(struct igusa *I, struct igusa_p *Ip, GEN p, GEN polmini)
1743 : {
1744 : GEN val, vs, polh, list, c1, c2, c3, c4, c5, c6, prod;
1745 : long i, vb5, vb6, d, Dmin, alpha, lambda, t60;
1746 1435 : long condp = -1, indice, vc6, mm, nb, dism;
1747 :
1748 1435 : stable_reduction(I, Ip, p);
1749 1435 : val = Ip->val; Dmin = val[6];
1750 1435 : if (Dmin == 0)
1751 : {
1752 7 : Ip->tame = 1;
1753 7 : Ip->type = "[I{0-0-0}] page 155";
1754 7 : Ip->neron = cyclic(1); return 0;
1755 : }
1756 1428 : if (Dmin == 1)
1757 : {
1758 14 : Ip->type = "[I{1-0-0}] page 170";
1759 14 : Ip->neron = cyclic(1); return 1;
1760 : }
1761 1414 : if (Dmin == 2) switch(Ip->tt)
1762 : {
1763 0 : case 2:
1764 0 : Ip->type = "[I{2-0-0}] page 170";
1765 0 : Ip->neron = cyclic(2); return 1;
1766 0 : case 3:
1767 0 : Ip->type = "[I{1-1-0}] page 179";
1768 0 : Ip->neron = cyclic(1); return 2;
1769 14 : case 5:
1770 14 : if (cmpis(p,3) <= 0) pari_err_BUG("genus2localred [tt 1]");
1771 14 : Ip->type = "[I{0}-II-0] page 159";
1772 14 : Ip->neron = cyclic(1); return 2;
1773 0 : default: pari_err_BUG("genus2localred [tt 2]");
1774 : }
1775 1400 : if (absequaliu(p,2)) return -1;
1776 1379 : polh = gel(polmini,1); vs = gel(polmini,2);
1777 1379 : lambda = vs[1];
1778 1379 : t60 = vs[2];
1779 1379 : alpha = vs[3];
1780 1379 : if (vs[4]) return equaliu(p,3)? quadratic(polh, alpha, Dmin, I, Ip):
1781 0 : tame(polh, t60, alpha, Dmin, I, Ip);
1782 1358 : if (!t60 && lambda<= 2)
1783 : {
1784 7 : if (Ip->tt >= 5) pari_err_BUG("genus2localred [tt 3]");
1785 7 : return tame(polh, t60, alpha, Dmin, I, Ip);
1786 : }
1787 1351 : if (Dmin == 3)
1788 : {
1789 7 : switch(Ip->tt)
1790 : {
1791 0 : case 2: return tame(polh, t60, alpha, Dmin, I, Ip);
1792 0 : case 3: Ip->type = "[I{2-1-0}] page 179"; Ip->neron = cyclic(2); return 2;
1793 7 : case 4: Ip->type = "[I{1-1-1}] page 182"; Ip->neron = cyclic(3); return 2;
1794 0 : case 5:
1795 0 : if (equaliu(p,3) && t60 != 30)
1796 0 : return labelm3(polh,t60,alpha,Dmin,I,Ip);
1797 0 : Ip->type = "[I{0}-III-0] page 161"; Ip->neron = cyclic(2); return 2;
1798 0 : case 6:
1799 0 : if (equaliu(p,3)) pari_err_BUG("genus2localred [conductor]");
1800 0 : Ip->type = "[I{1}-II-0] page 172"; Ip->neron = cyclic(1); return 3;
1801 : }
1802 0 : pari_err_BUG("genus2localred [switch tt 4]");
1803 : return -1; /* LCOV_EXCL_LINE */
1804 : }
1805 1344 : switch(lambda)
1806 : {
1807 364 : case 0:
1808 364 : switch(t60+alpha)
1809 : {
1810 7 : case 10:
1811 7 : condp = Dmin-1;
1812 7 : Ip->type = "[V] page 156";
1813 7 : Ip->neron = cyclic(3); break;
1814 7 : case 11:
1815 7 : condp = Dmin-11;
1816 7 : Ip->type = "[V*] page 156";
1817 7 : Ip->neron = cyclic(3); break;
1818 7 : case 12:
1819 7 : condp = Dmin-2;
1820 7 : Ip->type = "[IX-2] page 157";
1821 7 : Ip->neron = cyclic(5); break;
1822 14 : case 13:
1823 14 : condp = Dmin-12;
1824 14 : Ip->type = "[VIII-4] page 157";
1825 14 : Ip->neron = cyclic(1); break;
1826 7 : case 24:
1827 7 : condp = Dmin-8;
1828 7 : Ip->type = "[IX-4] page 158";
1829 7 : Ip->neron = cyclic(5);
1830 7 : break;
1831 14 : case 15: case 16:
1832 14 : if (Ip->tt>= 5) pari_err_BUG("genus2localred [tt 6]");
1833 14 : return tame(polh, t60, alpha, Dmin, I, Ip);
1834 112 : case 20: case 21:
1835 : {
1836 : GEN b0, b1, b2, b3, b4, b5, b6, b02, b03, b04, b05;
1837 112 : RgX_to_06(polh, &b0,&b1,&b2,&b3,&b4,&b5,&b6);
1838 112 : vb5 = myval(b5,p);
1839 112 : vb6 = myval(b6,p);
1840 112 : if (vb6 >= 3)
1841 : {
1842 14 : if (vb5 < 2) pari_err_BUG("genus2localred [red1]");
1843 14 : if (vb5 >= 3)
1844 : {
1845 7 : condp = Dmin-8;
1846 7 : Ip->type = "[II*-IV-(-1)] page 164";
1847 7 : Ip->neron = cyclic(3);
1848 : }
1849 : else
1850 : {
1851 7 : condp = Dmin-7;
1852 7 : Ip->type = "[IV-III*-(-1)] page 167";
1853 7 : Ip->neron = cyclic(6);
1854 : }
1855 14 : break;
1856 : }
1857 98 : if (dvdii(b0,p)) pari_err_BUG("genus2localred [b0]");
1858 98 : b02 = gsqr(b0);
1859 98 : b03 = gmul(b02, b0);
1860 98 : b04 = gmul(b03, b0);
1861 98 : b05 = gmul(b04, b0);
1862 98 : c1 = gmul2n(b1,-1);
1863 98 : c2 = gmul2n(gsub(gmul(b0,b2), gsqr(c1)),-1);
1864 98 : c3 = gmul2n(gsub(gmul(b02,b3), gmul2n(gmul(c1,c2),1)),-1);
1865 98 : c4 = gsub(gmul(b03,b4), gadd(gmul2n(gmul(c1,c3),1),gsqr(c2)));
1866 98 : c5 = gsub(gmul(b04,b5), gmul2n(gmul(c2,c3),1));
1867 98 : c6 = gsub(gmul(b05,b6), gsqr(c3));
1868 : /* b0^5*H(x/b0) = (x^3+c1*x^2+c2*x+c3)^2+c4*x^2+c5*x+c6 */
1869 98 : vc6 = myval(c6,p);
1870 98 : if (vc6 == 2)
1871 : {
1872 7 : if (alpha)
1873 : {
1874 0 : condp = Dmin-16;
1875 0 : Ip->type = "[IV] page 155";
1876 0 : Ip->neron = cyclic(1);
1877 : }
1878 : else
1879 : {
1880 7 : condp = Dmin-6;
1881 7 : Ip->type = "[III] page 155";
1882 7 : Ip->neron = dicyclic(3,3);
1883 : }
1884 : }
1885 : else
1886 : {
1887 91 : if (myval(c3,p) > 1) pari_err_BUG("genus2localred [c3]");
1888 91 : mm = min3(3*myval(c4,p)-4, 3*myval(c5,p)-5, 3*vc6-6);
1889 91 : if (alpha)
1890 : {
1891 35 : condp = Dmin-mm-16;
1892 35 : Ip->type = stack_sprintf("[III*{%ld}] page 184", mm);
1893 35 : Ip->neron = cyclic(1);
1894 : }
1895 : else
1896 : {
1897 56 : condp = Dmin-mm-6;
1898 56 : Ip->type = stack_sprintf("[III{%ld}] page 184", mm);
1899 56 : Ip->neron = (mm%3)? cyclic(9): dicyclic(3,3);
1900 : }
1901 : }
1902 : }
1903 98 : break;
1904 196 : case 30:
1905 280 : return equaliu(p,3)? quartic(polh, alpha, Dmin, Ip)
1906 280 : : tame(polh, t60, alpha, Dmin, I, Ip);
1907 0 : default: pari_err_BUG("genus2localred [red2]");
1908 : }
1909 154 : break;
1910 112 : case 1:
1911 112 : switch(t60+alpha)
1912 : {
1913 7 : case 12:
1914 7 : condp = Dmin;
1915 7 : Ip->type = "[VIII-1] page 156";
1916 7 : Ip->neron = cyclic(1); break;
1917 7 : case 13:
1918 7 : condp = Dmin-10;
1919 7 : Ip->type = "[IX-3] page 157";
1920 7 : Ip->neron = cyclic(5); break;
1921 7 : case 24:
1922 7 : condp = Dmin-4;
1923 7 : Ip->type = "[IX-1] page 157";
1924 7 : Ip->neron = cyclic(5); break;
1925 7 : case 25:
1926 7 : condp = Dmin-14;
1927 7 : Ip->type = "[VIII-3] page 157";
1928 7 : Ip->neron = cyclic(1); break;
1929 7 : case 36:
1930 7 : condp = Dmin-8;
1931 7 : Ip->type = "[VIII-2] page 157";
1932 7 : Ip->neron = cyclic(1); break;
1933 14 : case 15:
1934 14 : condp = Dmin-1;
1935 14 : Ip->type = "[VII] page 156";
1936 14 : Ip->neron = cyclic(2); break;
1937 7 : case 16:
1938 7 : condp = Dmin-11;
1939 7 : Ip->type = "[VII*] page 156";
1940 7 : Ip->neron = cyclic(2); break;
1941 14 : case 20:
1942 14 : if (cmpis(p,3))
1943 : {
1944 7 : d = 6*val[6]-5*val[7]-2;
1945 7 : if (d%6) pari_err_BUG("genus2localred [index]");
1946 7 : dism = (d/6);
1947 : }
1948 : else
1949 : {
1950 7 : list = padicfactors(polh,p,Dmin-5);
1951 7 : nb = lg(list);
1952 7 : prod = pol_1(varn(polh));
1953 21 : for(i = 1;i<nb;i++)
1954 : {
1955 14 : GEN c = gel(list,i);
1956 14 : if (valp(gel(c,2)) && degpol(c)<= 2) prod = RgX_mul(prod,c);
1957 : }
1958 7 : if (degpol(prod) > 2) pari_err_BUG("genus2localred [padicfactors]");
1959 7 : dism = valp(RgX_disc(prod)) - 1;
1960 : }
1961 14 : condp = Dmin-dism-3;
1962 14 : Ip->type = stack_sprintf("[II-II*{%ld}] page 176", dism);
1963 14 : Ip->neron = groupH(dism+1); break;
1964 14 : case 21:
1965 14 : vb6 = myval(RgX_coeff(polh,0),p);
1966 14 : if (vb6<2) pari_err_BUG("genus2localred [red3]");
1967 14 : condp = Dmin-14;
1968 14 : Ip->type = "[IV*-II{0}] page 175";
1969 14 : Ip->neron = cyclic(1); break;
1970 28 : case 30:
1971 28 : vb5 = myval(RgX_coeff(polh,1),p);
1972 28 : if (vb5 == 2)
1973 : {
1974 21 : if (Ip->tt >= 5) pari_err_BUG("genus2localred [tt 6]");
1975 21 : return tame(polh, t60, alpha, Dmin, I, Ip);
1976 : }
1977 7 : condp = Dmin-7;
1978 7 : Ip->type = "[II*-III-(-1)] page 167";
1979 7 : Ip->neron = cyclic(2); break;
1980 : }
1981 91 : break;
1982 147 : case 2:
1983 147 : if (ugcd(t60, 60) == 15) /* denom(theta) = 4 */
1984 : {
1985 28 : if (Ip->tt>4) pari_err_BUG("genus2localred [tt 5]");
1986 28 : return tame(polh, t60, alpha, Dmin, I, Ip);
1987 : }
1988 119 : if (!equaliu(p,3) && ugcd(t60, 60) == 20) /* denom(theta) = 3 */
1989 21 : return tame(polh, t60, alpha, Dmin, I, Ip);
1990 98 : list = padicfactors(polh,p,Dmin-10*alpha);
1991 98 : nb = lg(list); prod = pol_1(varn(polh));
1992 336 : for(i = 1;i<nb;i++)
1993 : {
1994 238 : GEN c = gel(list,i);
1995 238 : if (!valp(gel(c,2))) prod = RgX_mul(prod,c);
1996 : }
1997 98 : switch(degpol(prod))
1998 : {
1999 : GEN e0, e1, e2;
2000 0 : case 0:
2001 0 : dism = 0; break;
2002 7 : case 1:
2003 7 : e1 = gel(prod,3);
2004 7 : dism = 2*valp(e1); break;
2005 91 : case 2:
2006 91 : e0 = gel(prod,2);
2007 91 : e1 = gel(prod,3);
2008 91 : e2 = gel(prod,4);
2009 91 : dism = valp(gsub(gsqr(e1),gmul2n(gmul(e0,e2),2))); break;
2010 0 : default:
2011 0 : pari_err_BUG("genus2localred [padicfactors 2]");
2012 0 : dism = 0;
2013 : }
2014 98 : switch(t60/5+alpha-4)
2015 : {
2016 14 : case 0:
2017 14 : condp = Dmin-dism-1;
2018 14 : Ip->type = stack_sprintf("[IV-II{%ld}] page 175", dism);
2019 14 : Ip->neron = cyclic(3*dism+2); break;
2020 7 : case 1:
2021 7 : condp = Dmin-dism-10;
2022 7 : Ip->type = stack_sprintf("[II*-II*{%ld}] page 176",dism);
2023 7 : Ip->neron = groupH(dism+1); break;
2024 70 : case 2: case 3:
2025 70 : if (myval(RgX_coeff(polh,0),p) == 2)
2026 : {
2027 56 : if (Ip->tt>4) pari_err_BUG("genus2localred [tt 5]");
2028 56 : return tame(polh, t60, alpha, Dmin, I, Ip);
2029 : }
2030 14 : dism++;
2031 14 : indice = val[6]-(5*val[3]/2)-dism;
2032 14 : condp = Dmin-dism-indice-2;
2033 14 : Ip->type = stack_sprintf("[II{%ld-%ld}] page 182", dism,indice);
2034 14 : Ip->neron = both_odd(dism,indice)? dicyclic(2,2*dism): cyclic(4*dism);
2035 14 : break;
2036 7 : case 4:
2037 7 : condp = Dmin-dism-5;
2038 7 : Ip->type = stack_sprintf("[IV*-II{%ld}] page 175",dism+1);
2039 7 : Ip->neron = cyclic(3*dism+4); break;
2040 : }
2041 42 : break;
2042 721 : case 3:
2043 721 : if (!equaliu(p,3) || Ip->tt <= 4)
2044 490 : return tame(polh, t60, alpha, Dmin, I, Ip);
2045 231 : return labelm3(polh,t60,alpha,Dmin,I,Ip); /* p = 3 */
2046 0 : default: pari_err_BUG("genus2localred [switch lambda]");
2047 : }
2048 287 : if (condp < 2 || condp > get_maxc(p))
2049 0 : pari_err_BUG("genus2localred [conductor]");
2050 287 : return condp;
2051 : }
2052 :
2053 : static GEN
2054 1393 : hyperellintegralmodel(GEN PQ)
2055 : {
2056 : GEN D;
2057 1393 : PQ = Q_remove_denom(PQ, &D);
2058 1393 : if (!D) return PQ;
2059 14 : if (typ(PQ)==t_POL) return gmul(PQ,D);
2060 0 : if (typ(PQ) == t_VEC && lg(PQ) == 3)
2061 0 : return mkvec2(gmul(gel(PQ,1),D), gel(PQ,2));
2062 0 : pari_err_TYPE("hyperellintegralmodel",PQ);
2063 : return NULL; /* LCOV_EXCL_LINE */
2064 : }
2065 :
2066 : /* P,Q are ZX, study Y^2 + Q(X) Y = P(X) */
2067 : GEN
2068 1393 : genus2red(GEN PQ, GEN p)
2069 : {
2070 1393 : pari_sp av = avma;
2071 : struct igusa I;
2072 : GEN P, Q;
2073 : GEN j22, j42, j2j6, a0,a1,a2,a3,a4,a5,a6, V,polr,facto,factp, vecmini, cond;
2074 : long i, l, dd;
2075 1393 : PQ = hyperellminimalmodel(hyperellintegralmodel(PQ), NULL, p ? mkvec(p): p);
2076 1393 : P = gel(PQ,1);
2077 1393 : Q = gel(PQ,2);
2078 1393 : if (p && typ(p) != t_INT) pari_err_TYPE("genus2red", p);
2079 :
2080 1393 : polr = ZX_add(ZX_sqr(Q), gmul2n(P,2)); /* ZX */
2081 1393 : switch(degpol(polr))
2082 : {
2083 1393 : case 5: case 6: break;
2084 0 : default: pari_err_DOMAIN("genus2red","genus","!=", gen_2,mkvec2(P,Q));
2085 : }
2086 :
2087 1393 : RgX_to_03(polr, &a0,&a1,&a2,&a3);
2088 1393 : I.j10 = !signe(a0)? mulii(sqri(a1), ZX_disc(polr)): ZX_disc(polr);
2089 1393 : if (!signe(I.j10))
2090 0 : pari_err_DOMAIN("genus2red","genus","<",gen_2,mkvec2(P,Q));
2091 1393 : I.j10 = gmul2n(I.j10, -12); /* t_INT */
2092 :
2093 1393 : if (p == NULL)
2094 : {
2095 42 : facto = absZ_factor(I.j10);
2096 42 : factp = gel(facto,1);
2097 : }
2098 : else
2099 : {
2100 1351 : factp = mkcol(p);
2101 1351 : facto = mkmat2(factp, mkcol(gen_1));
2102 : }
2103 1393 : l = lg(factp);
2104 1393 : vecmini = cgetg(l, t_COL);
2105 2828 : for(i = 1; i<l; i++)
2106 : {
2107 1435 : GEN l = gel(factp,i), pm;
2108 1435 : if (i == 1 && absequaliu(l, 2)) { gel(vecmini,1) = gen_0; continue; }
2109 1414 : gel(vecmini,i) = pm = polymini(polr, l);
2110 1414 : polr = ZX_Q_mul(gel(pm,1), powiu(l, gel(pm,2)[3]));
2111 : }
2112 1393 : RgX_to_06(polr, &a0,&a1,&a2,&a3,&a4,&a5,&a6);
2113 1393 : I.j10 = !signe(a0)? mulii(sqri(a1), ZX_disc(polr)): ZX_disc(polr);
2114 1393 : I.j10 = gmul2n(I.j10,-12);
2115 :
2116 1393 : I.a0 = a0;
2117 1393 : I.A2 = apol2(a0,a1,a2);
2118 1393 : I.A3 = apol3(a0,a1,a2,a3);
2119 1393 : I.A5 = apol5(a0,a1,a2,a3,a4,a5);
2120 1393 : I.B2 = bpol2(a0,a1,a2,a3,a4);
2121 :
2122 1393 : I.j2 = igusaj2(a0,a1,a2,a3,a4,a5,a6);
2123 1393 : I.j4 = igusaj4(a0,a1,a2,a3,a4,a5,a6);
2124 1393 : I.i4 = gsub(gsqr(I.j2), gmulsg(24,I.j4));
2125 1393 : I.j6 = igusaj6(a0,a1,a2,a3,a4,a5,a6);
2126 1393 : j42 = gsqr(I.j4);
2127 1393 : j22 = gsqr(I.j2);
2128 1393 : j2j6 = gmul(I.j2,I.j6);
2129 1393 : I.j8 = gmul2n(gsub(j2j6,j42), -2);
2130 1393 : I.i12= gmul2n(gsub(gadd(gmul(j22,j42),gmulsg(36,gmul(j2j6,I.j4))),
2131 : gadd(gadd(gmulsg(32,gmul(j42,I.j4)),gmul(j2j6,j22)),gmulsg(108,gsqr(I.j6)))),-2);
2132 :
2133 2828 : for(i = 1; i < l; i++)
2134 1435 : gcoeff(facto,i,2) = stoi(Q_pval(I.j10, gel(factp,i)));
2135 1393 : dd = ZX_pval(polr,gen_2) & (~1); /* = 2 floor(val/2) */
2136 1393 : polr = gmul2n(polr, -dd);
2137 :
2138 1393 : V = cgetg(l, t_VEC);
2139 2828 : for (i = 1; i < l; i++)
2140 : {
2141 1435 : GEN q = gel(factp,i), red, N = NULL;
2142 : struct igusa_p Ip;
2143 1435 : long f = genus2localred(&I, &Ip, q, gel(vecmini,i));
2144 1435 : gcoeff(facto,i,2) = stoi(f);
2145 1435 : if (Ip.tame) Ip.type = stack_strcat("(tame) ", Ip.type);
2146 1435 : if (f >= 0)
2147 1414 : N = zv_snf(Ip.neron);
2148 1435 : if (DEBUGLEVEL)
2149 : {
2150 0 : if (!p) err_printf("p = %Ps\n", q);
2151 0 : err_printf("(potential) stable reduction: %Ps\n", Ip.stable);
2152 0 : if (f >= 0) {
2153 0 : err_printf("reduction at p: %s, %Ps", Ip.type, N);
2154 0 : err_printf(", f = %ld\n", f);
2155 : }
2156 : }
2157 1435 : red = f >= 0? mkvec2(strtoGENstr(Ip.type), N): cgetg(1, t_VEC);
2158 1435 : gel(V, i) = mkvec3(q, Ip.stable, red);
2159 : }
2160 1393 : if (p) V = gel(V,1);
2161 1393 : cond = factorback(facto);
2162 : /* remove denominator 2 coming from f = -1 in genuslocalred(, p = 2) */
2163 1393 : if (typ(cond) != t_INT) cond = gel(cond,1);
2164 1393 : return gerepilecopy(av, mkvec4(cond, facto, PQ, V));
2165 : }
|