Line data Source code
1 : /* Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : /********************************************************************/
16 : /** **/
17 : /** L-functions: Applications **/
18 : /** **/
19 : /********************************************************************/
20 :
21 : #include "pari.h"
22 : #include "paripriv.h"
23 :
24 : #define DEBUGLEVEL DEBUGLEVEL_lfun
25 :
26 : static GEN
27 14140 : tag(GEN x, long t) { return mkvec2(mkvecsmall(t), x); }
28 :
29 : /* v a t_VEC of length > 1 */
30 : static int
31 59997 : is_tagged(GEN v)
32 : {
33 59997 : GEN T = gel(v,1);
34 59997 : return (typ(T)==t_VEC && lg(T)==3 && typ(gel(T,1))==t_VECSMALL);
35 : }
36 : /* rough check */
37 : static long
38 69825 : is_ldata(GEN L)
39 : {
40 69825 : long l = lg(L);
41 69825 : return typ(L) == t_VEC && (l == 7 || l == 8);
42 : }
43 : /* thorough check */
44 : static void
45 59885 : checkldata(GEN ldata)
46 : {
47 : GEN vga, w, N;
48 : #if 0 /* assumed already checked and true */
49 : if (!is_ldata(ldata) || !is_tagged(ldata)) pari_err_TYPE("checkldata", ldata);
50 : #endif
51 59885 : vga = ldata_get_gammavec(ldata);
52 59885 : if (typ(vga) != t_VEC) pari_err_TYPE("checkldata [gammavec]",vga);
53 59885 : w = gel(ldata, 4); /* FIXME */
54 59885 : switch(typ(w))
55 : {
56 58058 : case t_INT: case t_FRAC: break;
57 1827 : case t_VEC: if (lg(w) == 3 && is_rational_t(typ(gel(w,1)))) break;
58 0 : default: pari_err_TYPE("checkldata [weight]",w);
59 : }
60 59885 : N = ldata_get_conductor(ldata);
61 59885 : if (typ(N) != t_INT) pari_err_TYPE("checkldata [conductor]",N);
62 59885 : }
63 :
64 : /* tag as t_LFUN_GENERIC */
65 : static void
66 609 : lfuncreate_tag(GEN L)
67 : {
68 609 : if (is_tagged(L)) return;
69 448 : gel(L,1) = tag(gel(L,1), t_LFUN_GENERIC);
70 448 : if (typ(gel(L,2)) != t_INT) gel(L,2) = tag(gel(L,2), t_LFUN_GENERIC);
71 : }
72 :
73 : /* shallow */
74 : static GEN
75 168 : closure2ldata(GEN C, long prec)
76 : {
77 168 : GEN L = closure_callgen0prec(C, prec);
78 168 : if (is_ldata(L)) { checkldata(L); lfuncreate_tag(L); }
79 56 : else L = lfunmisc_to_ldata_shallow(L);
80 168 : return L;
81 : }
82 :
83 : /* data may be either an object (polynomial, elliptic curve, etc...)
84 : * or a description vector [an,sd,Vga,k,conductor,rootno,{poles}]. */
85 : GEN
86 1869 : lfuncreate(GEN data)
87 : {
88 1869 : if (is_ldata(data))
89 : {
90 497 : GEN L = gcopy(data);
91 497 : lfuncreate_tag(L); checkldata(L); return L;
92 : }
93 1372 : if (typ(data) == t_CLOSURE && closure_arity(data)==0)
94 : {
95 14 : pari_sp av = avma;
96 14 : GEN L = closure2ldata(data, DEFAULTPREC);
97 14 : gel(L,1) = tag(data, t_LFUN_CLOSURE0); return gerepilecopy(av, L);
98 : }
99 1358 : return lfunmisc_to_ldata(data);
100 : }
101 :
102 : GEN
103 133 : lfunparams(GEN L, long prec)
104 : {
105 133 : pari_sp av = avma;
106 : GEN k, N, v;
107 : long p;
108 :
109 133 : if (!is_ldata(L) || !is_tagged(L)) L = lfunmisc_to_ldata_shallow(L);
110 133 : N = ldata_get_conductor(L);
111 133 : k = ldata_get_k(L);
112 133 : v = ldata_get_gammavec(L);
113 133 : p = gprecision(v);
114 133 : if (p > prec) v = gprec_wtrunc(v, prec);
115 133 : else if (p < prec)
116 : {
117 133 : GEN van = ldata_get_an(L), an = gel(van,2);
118 133 : long t = mael(van,1,1);
119 133 : if (t == t_LFUN_CLOSURE0) L = closure2ldata(an, prec);
120 : }
121 133 : return gerepilecopy(av, mkvec3(N, k, v));
122 : }
123 :
124 : /********************************************************************/
125 : /** Simple constructors **/
126 : /********************************************************************/
127 : static GEN ldata_eulerf(GEN van, GEN p, long prec);
128 :
129 : static GEN
130 126 : vecan_conj(GEN an, long n, long prec)
131 : {
132 126 : GEN p1 = ldata_vecan(gel(an,1), n, prec);
133 126 : return typ(p1) == t_VEC? conj_i(p1): p1;
134 : }
135 :
136 : static GEN
137 0 : eulerf_conj(GEN an, GEN p, long prec)
138 : {
139 0 : GEN p1 = ldata_eulerf(gel(an,1), p, prec);
140 0 : return conj_i(p1);
141 : }
142 :
143 : static GEN
144 308 : vecan_mul(GEN an, long n, long prec)
145 : {
146 308 : GEN p1 = ldata_vecan(gel(an,1), n, prec);
147 308 : GEN p2 = ldata_vecan(gel(an,2), n, prec);
148 308 : if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1);
149 308 : if (typ(p2) == t_VECSMALL) p2 = vecsmall_to_vec(p2);
150 308 : return dirmul(p1, p2);
151 : }
152 :
153 : static GEN
154 28 : eulerf_mul(GEN an, GEN p, long prec)
155 : {
156 28 : GEN p1 = ldata_eulerf(gel(an,1), p, prec);
157 28 : GEN p2 = ldata_eulerf(gel(an,2), p, prec);
158 28 : return gmul(p1, p2);
159 : }
160 :
161 : static GEN
162 77 : lfunconvol(GEN a1, GEN a2)
163 77 : { return tag(mkvec2(a1, a2), t_LFUN_MUL); }
164 :
165 : static GEN
166 616 : vecan_div(GEN an, long n, long prec)
167 : {
168 616 : GEN p1 = ldata_vecan(gel(an,1), n, prec);
169 616 : GEN p2 = ldata_vecan(gel(an,2), n, prec);
170 616 : if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1);
171 616 : if (typ(p2) == t_VECSMALL) p2 = vecsmall_to_vec(p2);
172 616 : return dirdiv(p1, p2);
173 : }
174 :
175 : static GEN
176 14 : eulerf_div(GEN an, GEN p, long prec)
177 : {
178 14 : GEN p1 = ldata_eulerf(gel(an,1), p, prec);
179 14 : GEN p2 = ldata_eulerf(gel(an,2), p, prec);
180 14 : return gdiv(p1, p2);
181 : }
182 :
183 : static GEN
184 56 : lfunconvolinv(GEN a1, GEN a2)
185 56 : { return tag(mkvec2(a1,a2), t_LFUN_DIV); }
186 :
187 : static GEN
188 84 : lfunconj(GEN a1)
189 84 : { return tag(mkvec(a1), t_LFUN_CONJ); }
190 :
191 : static GEN
192 133 : lfuncombdual(GEN (*fun)(GEN, GEN), GEN ldata1, GEN ldata2)
193 : {
194 133 : GEN a1 = ldata_get_an(ldata1), a2 = ldata_get_an(ldata2);
195 133 : GEN b1 = ldata_get_dual(ldata1), b2 = ldata_get_dual(ldata2);
196 133 : if (typ(b1)==t_INT && typ(b2)==t_INT)
197 133 : return utoi(signe(b1) || signe(b2));
198 : else
199 : {
200 0 : if (typ(b1)==t_INT) b1 = signe(b1) ? lfunconj(a1): a1;
201 0 : if (typ(b2)==t_INT) b2 = signe(b2) ? lfunconj(a2): a2;
202 0 : return fun(b1, b2);
203 : }
204 : }
205 :
206 : static GEN
207 581 : vecan_twist(GEN an, long n, long prec)
208 : {
209 581 : GEN p1 = ldata_vecan(gel(an,1), n, prec);
210 581 : GEN p2 = ldata_vecan(gel(an,2), n, prec);
211 : long i;
212 : GEN V;
213 581 : if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1);
214 581 : if (typ(p2) == t_VECSMALL) p2 = vecsmall_to_vec(p2);
215 581 : V = cgetg(n+1, t_VEC);
216 415695 : for(i = 1; i <= n ; i++)
217 415114 : gel(V, i) = gmul(gel(p1, i), gel(p2, i));
218 581 : return V;
219 : }
220 :
221 : static GEN
222 14 : eulerf_twist(GEN an, GEN p, long prec)
223 : {
224 14 : GEN p1 = ldata_eulerf(gel(an,1), p, prec);
225 14 : GEN p2 = ginv(ldata_eulerf(gel(an,2), p, prec));
226 14 : if (typ(p2)!=t_POL || degpol(p2)==0)
227 0 : return poleval(p1,pol_0(0));
228 14 : if (degpol(p2)!=1) pari_err_IMPL("lfuneuler");
229 14 : return poleval(p1,monomial(gneg(gel(p2,3)),1,0));
230 : }
231 :
232 : static GEN
233 637 : vecan_shift(GEN an, long n, long prec)
234 : {
235 637 : GEN p1 = ldata_vecan(gel(an,1), n, prec);
236 637 : GEN s = gel(an,2);
237 : long i;
238 : GEN V;
239 637 : if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1);
240 637 : V = cgetg(n+1, t_VEC);
241 637 : if (typ(s)==t_INT)
242 : {
243 448 : if (equali1(s))
244 31850 : for(i = 1; i <= n ; i++)
245 : {
246 31500 : GEN gi = gel(p1, i);
247 31500 : gel(V, i) = gequal0(gi)? gi: gmulgu(gi, i);
248 : }
249 : else
250 1848 : for(i = 1; i <= n ; i++)
251 : {
252 1750 : GEN gi = gel(p1, i);
253 1750 : gel(V, i) = gequal0(gi)? gi: gmul(gi, powgi(utoi(i), s));
254 : }
255 : }
256 : else
257 : {
258 189 : GEN D = dirpowers(n, s, prec);
259 7049 : for(i = 1; i <= n ; i++)
260 6860 : gel(V, i) = gmul(gel(p1,i), gel(D,i));
261 : }
262 637 : return V;
263 : }
264 :
265 : static GEN
266 42 : eulerf_shift(GEN an, GEN p, long prec)
267 : {
268 42 : GEN p1 = ldata_eulerf(gel(an,1), p, prec);
269 42 : GEN s = gel(an,2);
270 42 : return gsubst(p1, 0, monomial(gpow(p, s, prec), 1, 0));
271 : }
272 :
273 : static GEN
274 84 : eulerf_hgm(GEN an, GEN p)
275 : {
276 84 : GEN H = gel(an,1), t = gel(an,2);
277 84 : if (typ(t)==t_VEC && lg(t)==3)
278 : {
279 28 : GEN L = gel(t,2);
280 28 : long i, l = lg(L);
281 28 : t = gel(t,1);
282 49 : for (i = 1; i < l; i++) /* wild primes */
283 35 : if (equalii(p, gmael(L, i, 1))) break;
284 28 : if (i<l) return gmael(L,i,2);
285 : }
286 70 : return ginv(hgmeulerfactor(H, t, itos(p), NULL));
287 : }
288 :
289 : static GEN
290 315 : deg1ser_shallow(GEN a1, GEN a0, long e)
291 315 : { return RgX_to_ser(deg1pol_shallow(a1, a0, 0), e+2); }
292 : /* lfunrtopoles without sort */
293 : static GEN
294 168 : rtopoles(GEN r)
295 : {
296 168 : long j, l = lg(r);
297 168 : GEN v = cgetg(l, t_VEC);
298 350 : for (j = 1; j < l; j++)
299 : {
300 182 : GEN rj = gel(r,j), a = gel(rj,1);
301 182 : gel(v,j) = a;
302 : }
303 168 : return v;
304 : }
305 : /* re = polar part; overestimate when re = gen_0 (unknown) */
306 : static long
307 266 : orderpole(GEN re) { return typ(re) == t_SER? -valser(re): 1; }
308 : static GEN
309 77 : lfunmulpoles(GEN ldata1, GEN ldata2, long bitprec)
310 : {
311 77 : GEN r, k = ldata_get_k(ldata1), b1 = NULL, b2 = NULL;
312 77 : GEN r1 = ldata_get_residue(ldata1);
313 77 : GEN r2 = ldata_get_residue(ldata2);
314 77 : long i, j, l, L = 0;
315 :
316 77 : if (!r1 && !r2) return NULL;
317 70 : if (r1 && !is_vec_t(typ(r1))) r1 = mkvec(mkvec2(k, r1));
318 70 : if (r2 && !is_vec_t(typ(r2))) r2 = mkvec(mkvec2(k, r2));
319 70 : if (r1) { b1 = rtopoles(r1); L += lg(b1); }
320 70 : if (r2) { b2 = rtopoles(r2); L += lg(b2); }
321 70 : r = cgetg(L, t_VEC); j = 1;
322 70 : if (b1)
323 : {
324 63 : l = lg(b1);
325 133 : for (i = 1; i < l; i++)
326 : {
327 70 : GEN z, z1, z2, be = gmael(r1,i,1);
328 70 : long n, v = orderpole(gmael(r1,i,2));
329 70 : if (b2 && (n = RgV_isin(b2, be))) v += orderpole(gmael(r2,n,2));
330 70 : z = deg1ser_shallow(gen_1, be, 2 + v);
331 70 : z1 = lfun(ldata1,z,bitprec);
332 70 : z2 = lfun(ldata2,z,bitprec);
333 70 : gel(r,j++) = mkvec2(be, gmul(z1, z2));
334 : }
335 : }
336 70 : if (b2)
337 : {
338 63 : long l = lg(b2);
339 133 : for (i = 1; i < l; i++)
340 : {
341 70 : GEN z, z1, z2, be = gmael(r2,i,1);
342 70 : long n, v = orderpole(gmael(r2,i,2));
343 70 : if (b1 && (n = RgV_isin(b1, be))) continue; /* done already */
344 28 : z = deg1ser_shallow(gen_1, be, 2 + v);
345 28 : z1 = lfun(ldata1,z,bitprec);
346 28 : z2 = lfun(ldata2,z,bitprec);
347 28 : gel(r,j++) = mkvec2(be, gmul(z1, z2));
348 : }
349 : }
350 70 : setlg(r, j); return r;
351 : }
352 :
353 : static GEN
354 77 : lfunmul_k(GEN ldata1, GEN ldata2, GEN k, long bitprec)
355 : {
356 : GEN r, N, Vga, eno, a1a2, b1b2;
357 77 : r = lfunmulpoles(ldata1, ldata2, bitprec);
358 77 : N = gmul(ldata_get_conductor(ldata1), ldata_get_conductor(ldata2));
359 77 : Vga = shallowconcat(ldata_get_gammavec(ldata1), ldata_get_gammavec(ldata2));
360 77 : Vga = sort(Vga);
361 77 : eno = gmul(ldata_get_rootno(ldata1), ldata_get_rootno(ldata2));
362 77 : a1a2 = lfunconvol(ldata_get_an(ldata1), ldata_get_an(ldata2));
363 77 : b1b2 = lfuncombdual(lfunconvol, ldata1, ldata2);
364 77 : return mkvecn(r? 7: 6, a1a2, b1b2, Vga, k, N, eno, r);
365 : }
366 :
367 : GEN
368 63 : lfunmul(GEN ldata1, GEN ldata2, long bitprec)
369 : {
370 63 : pari_sp ltop = avma;
371 : GEN k;
372 63 : long prec = nbits2prec(bitprec);
373 63 : ldata1 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata1), prec);
374 63 : ldata2 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata2), prec);
375 63 : k = ldata_get_k(ldata1);
376 63 : if (!gequal(ldata_get_k(ldata2),k))
377 0 : pari_err_OP("lfunmul [weight]",ldata1, ldata2);
378 63 : return gerepilecopy(ltop, lfunmul_k(ldata1, ldata2, k, bitprec));
379 : }
380 :
381 : static GEN
382 56 : lfundivpoles(GEN ldata1, GEN ldata2, long bitprec)
383 : {
384 : long i, j, l;
385 56 : GEN be2, k = ldata_get_k(ldata1);
386 56 : GEN r1 = ldata_get_residue(ldata1);
387 56 : GEN r2 = ldata_get_residue(ldata2), r;
388 :
389 56 : if (r1 && !is_vec_t(typ(r1))) r1 = mkvec(mkvec2(k, r1));
390 56 : if (r2 && !is_vec_t(typ(r2))) r2 = mkvec(mkvec2(k, r2));
391 56 : if (!r1) return NULL;
392 56 : l = lg(r1); r = cgetg(l, t_VEC);
393 56 : be2 = r2? rtopoles(r2): NULL;
394 112 : for (i = j = 1; j < l; j++)
395 : {
396 56 : GEN z, v = gel(r1,j), be = gel(v,1), s1 = gel(v,2);
397 : long n;
398 56 : if (be2 && (n = RgV_isin(be2, be)))
399 : {
400 42 : GEN s2 = gmael(r2,n,2); /* s1,s2: polar parts */
401 42 : if (orderpole(s1) == orderpole(s2)) continue;
402 : }
403 14 : z = gdiv(lfun(ldata1,be,bitprec), lfun(ldata2,be,bitprec));
404 14 : if (valser(z) < 0) gel(r,i++) = mkvec2(be, z);
405 : }
406 56 : if (i == 1) return NULL;
407 14 : setlg(r, i); return r;
408 : }
409 :
410 : static GEN
411 56 : lfunvgasub(GEN v01, GEN v2)
412 : {
413 56 : GEN v1 = shallowcopy(v01), v;
414 56 : long l1 = lg(v1), l2 = lg(v2), j1, j2, j;
415 119 : for (j2 = 1; j2 < l2; j2++)
416 : {
417 91 : for (j1 = 1; j1 < l1; j1++)
418 91 : if (gel(v1,j1) && gequal(gel(v1,j1), gel(v2,j2)))
419 : {
420 63 : gel(v1,j1) = NULL; break;
421 : }
422 63 : if (j1 == l1) pari_err_OP("lfunvgasub", v1, v2);
423 : }
424 56 : v = cgetg(l1-l2+1, t_VEC);
425 259 : for (j1 = j = 1; j1 < l1; j1++)
426 203 : if (gel(v1, j1)) gel(v,j++) = gel(v1,j1);
427 56 : return v;
428 : }
429 :
430 : GEN
431 56 : lfundiv(GEN ldata1, GEN ldata2, long bitprec)
432 : {
433 56 : pari_sp ltop = avma;
434 : GEN k, r, N, v, eno, a1a2, b1b2, eno2;
435 56 : long prec = nbits2prec(bitprec);
436 56 : ldata1 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata1), prec);
437 56 : ldata2 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata2), prec);
438 56 : k = ldata_get_k(ldata1);
439 56 : if (!gequal(ldata_get_k(ldata2),k))
440 0 : pari_err_OP("lfundiv [weight]",ldata1, ldata2);
441 56 : N = gdiv(ldata_get_conductor(ldata1), ldata_get_conductor(ldata2));
442 56 : if (typ(N) != t_INT) pari_err_OP("lfundiv [conductor]",ldata1, ldata2);
443 56 : r = lfundivpoles(ldata1, ldata2, bitprec);
444 56 : a1a2 = lfunconvolinv(ldata_get_an(ldata1), ldata_get_an(ldata2));
445 56 : b1b2 = lfuncombdual(lfunconvolinv, ldata1, ldata2);
446 56 : eno2 = ldata_get_rootno(ldata2);
447 56 : eno = isintzero(eno2)? gen_0: gdiv(ldata_get_rootno(ldata1), eno2);
448 56 : v = lfunvgasub(ldata_get_gammavec(ldata1), ldata_get_gammavec(ldata2));
449 56 : return gerepilecopy(ltop, mkvecn(r? 7: 6, a1a2, b1b2, v, k, N, eno, r));
450 : }
451 :
452 : static GEN
453 245 : gamma_imagchi(GEN gam, GEN w)
454 : {
455 245 : long i, j, k=1, l;
456 245 : GEN g = cgetg_copy(gam, &l);
457 245 : gam = shallowcopy(gam);
458 735 : for (i = l-1; i>=1; i--)
459 : {
460 490 : GEN al = gel(gam, i);
461 490 : if (al)
462 : {
463 252 : GEN N = gadd(w,gmul2n(real_i(al),1));
464 252 : if (gcmpgs(N,2) > 0)
465 : {
466 238 : GEN bl = gsubgs(al, 1);
467 238 : for (j=1; j < i; j++)
468 238 : if (gel(gam,j) && gequal(gel(gam,j), bl))
469 238 : { gel(gam,j) = NULL; break; }
470 238 : if (j==i) return NULL;
471 238 : gel(g, k++) = al;
472 238 : gel(g, k++) = bl;
473 14 : } else if (gequal0(N))
474 14 : gel(g, k++) = gaddgs(al, 1);
475 0 : else if (gequal1(N))
476 0 : gel(g, k++) = gsubgs(al, 1);
477 0 : else return NULL;
478 : }
479 : }
480 245 : return sort(g);
481 : }
482 :
483 : GEN
484 889 : lfuntwist(GEN ldata1, GEN chi, long bitprec)
485 : {
486 889 : pari_sp ltop = avma;
487 : GEN k, L, N, N1, N2, a, a1, a2, b, b1, b2, gam, gam1, gam2;
488 : GEN ldata2;
489 : long d1, t;
490 889 : long prec = nbits2prec(bitprec);
491 889 : ldata1 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata1), prec);
492 889 : ldata2 = lfunmisc_to_ldata_shallow(chi);
493 889 : t = ldata_get_type(ldata2);
494 889 : a1 = ldata_get_an(ldata1);
495 889 : a2 = ldata_get_an(ldata2);
496 889 : if (t == t_LFUN_ZETA)
497 427 : return gerepilecopy(ltop, ldata1);
498 462 : if (t != t_LFUN_CHIZ && t != t_LFUN_KRONECKER &&
499 7 : ( t != t_LFUN_CHIGEN || nf_get_degree(bnr_get_nf(gmael(a2,2,1))) != 1))
500 0 : pari_err_TYPE("lfuntwist", chi);
501 462 : N1 = ldata_get_conductor(ldata1);
502 462 : N2 = ldata_get_conductor(ldata2);
503 462 : if (!gequal1(gcdii(N1, N2)))
504 0 : pari_err_IMPL("lfuntwist (conductors not coprime)");
505 462 : k = ldata_get_k(ldata1);
506 462 : d1 = ldata_get_degree(ldata1);
507 462 : N = gmul(N1, gpowgs(N2, d1));
508 462 : gam1 = ldata_get_gammavec(ldata1);
509 462 : gam2 = ldata_get_gammavec(ldata2);
510 462 : if (gequal0(gel(gam2, 1)))
511 217 : gam = gam1;
512 : else
513 245 : gam = gamma_imagchi(ldata_get_gammavec(ldata1), gaddgs(k,-1));
514 462 : if (!gam) pari_err_IMPL("lfuntwist (gammafactors)");
515 462 : b1 = ldata_get_dual(ldata1);
516 462 : b2 = ldata_get_dual(ldata2);
517 462 : a = tag(mkvec2(a1, a2), t_LFUN_TWIST);
518 462 : if (typ(b1)==t_INT)
519 462 : b = signe(b1) && signe(b2) ? gen_0: gen_1;
520 : else
521 0 : b = tag(mkvec2(b1,lfunconj(a2)), t_LFUN_TWIST);
522 462 : L = mkvecn(6, a, b, gam, k, N, gen_0);
523 462 : return gerepilecopy(ltop, L);
524 : }
525 :
526 : static GEN
527 252 : lfundualpoles(GEN ldata, GEN reno)
528 : {
529 : long l, j;
530 252 : GEN k = ldata_get_k(ldata);
531 252 : GEN r = gel(reno,2), eno = gel(reno,3), R;
532 252 : R = cgetg_copy(r, &l);
533 770 : for (j = 1; j < l; j++)
534 : {
535 518 : GEN b = gmael(r,j,1), e = gmael(r,j,2);
536 518 : long v = varn(e);
537 518 : GEN E = gsubst(gdiv(e, eno), v, gneg(pol_x(v)));
538 518 : gel(R,l-j) = mkvec2(gsub(k,b), E);
539 : }
540 252 : return R;
541 : }
542 :
543 : static GEN
544 539 : ginvvec(GEN x)
545 : {
546 539 : if (is_vec_t(typ(x)))
547 42 : pari_APPLY_same(ginv(gel(x,i)))
548 : else
549 525 : return ginv(x);
550 : }
551 :
552 : GEN
553 602 : lfundual(GEN L, long bitprec)
554 : {
555 602 : pari_sp av = avma;
556 602 : long prec = nbits2prec(bitprec);
557 602 : GEN ldata = ldata_newprec(lfunmisc_to_ldata_shallow(L), prec);
558 602 : GEN a = ldata_get_an(ldata), b = ldata_get_dual(ldata);
559 602 : GEN e = ldata_get_rootno(ldata);
560 602 : GEN ldual, ad, bd, ed, Rd = NULL;
561 602 : if (typ(b) == t_INT)
562 : {
563 574 : ad = equali1(b) ? lfunconj(a): a;
564 574 : bd = b;
565 : }
566 28 : else { ad = b; bd = a; }
567 602 : if (lg(ldata)==8)
568 : {
569 252 : GEN reno = lfunrootres(ldata, bitprec);
570 252 : e = gel(reno,3);
571 252 : Rd = lfundualpoles(ldata, reno);
572 : }
573 602 : ed = isintzero(e) ? e: ginvvec(e);
574 602 : ldual = mkvecn(Rd ? 7:6, ad, bd, gel(ldata,3), gel(ldata,4), gel(ldata,5), ed, Rd);
575 602 : return gerepilecopy(av, ldual);
576 : }
577 :
578 : static GEN
579 98 : RgV_Rg_translate(GEN x, GEN s)
580 259 : { pari_APPLY_same(gadd(gel(x,i),s)) }
581 :
582 : static GEN
583 28 : pole_translate(GEN x, GEN s, GEN Ns)
584 : {
585 28 : x = shallowcopy(x);
586 28 : gel(x,1) = gadd(gel(x,1), s);
587 28 : if (Ns)
588 28 : gel(x,2) = gmul(gel(x,2), Ns);
589 28 : return x;
590 : }
591 :
592 : static GEN
593 14 : poles_translate(GEN x, GEN s, GEN Ns)
594 42 : { pari_APPLY_same(pole_translate(gel(x,i), s, Ns)) }
595 :
596 : /* r / x + O(1) */
597 : static GEN
598 266 : simple_pole(GEN r)
599 : {
600 : GEN S;
601 266 : if (isintzero(r)) return gen_0;
602 217 : S = deg1ser_shallow(gen_0, r, 1);
603 217 : setvalser(S, -1); return S;
604 : }
605 :
606 : GEN
607 98 : lfunshift(GEN ldata, GEN s, long flag, long bitprec)
608 : {
609 98 : pari_sp ltop = avma;
610 : GEN k, k1, L, N, a, b, gam, eps, res;
611 98 : long prec = nbits2prec(bitprec);
612 98 : if (!is_rational_t(typ(s))) pari_err_TYPE("lfunshift",s);
613 98 : ldata = ldata_newprec(lfunmisc_to_ldata_shallow(ldata), prec);
614 98 : a = ldata_get_an(ldata);
615 98 : b = ldata_get_dual(ldata);
616 98 : gam = RgV_Rg_translate(ldata_get_gammavec(ldata), gneg(s));
617 98 : k = gadd(ldata_get_k(ldata), gmul2n(s, 1));
618 98 : k1 = gadd(ldata_get_k1(ldata), s);
619 98 : N = ldata_get_conductor(ldata);
620 98 : eps = ldata_get_rootno(ldata);
621 98 : res = ldata_get_residue(ldata);
622 98 : a = tag(mkvec2(a, s), t_LFUN_SHIFT);
623 98 : if (typ(b) != t_INT)
624 0 : b = tag(mkvec2(b, s), t_LFUN_SHIFT);
625 98 : if (res)
626 98 : switch(typ(res))
627 : {
628 0 : case t_VEC:
629 0 : res = poles_translate(res, s, NULL);
630 0 : break;
631 14 : case t_COL:
632 14 : res = poles_translate(res, s, gpow(N, gmul2n(s, -1), prec));
633 14 : break;
634 84 : default:
635 84 : res = mkvec(mkvec2(gsub(k, s), simple_pole(res)));
636 : }
637 98 : L = mkvecn(res ? 7: 6, a, b, gam, mkvec2(k, k1), N, eps, res);
638 98 : if (flag) L = lfunmul_k(ldata, L, gsub(k, s), bitprec);
639 98 : return gerepilecopy(ltop, L);
640 : }
641 :
642 : /*****************************************************************/
643 : /* L-series from closure */
644 : /*****************************************************************/
645 : static GEN
646 58954 : localfactor(void *E, GEN p, long n)
647 : {
648 58954 : GEN s = closure_callgen2((GEN)E, p, utoi(n));
649 58954 : return direuler_factor(s, n);
650 : }
651 : static GEN
652 1925 : vecan_closure(GEN a, long L, long prec)
653 : {
654 1925 : long ta = typ(a);
655 1925 : GEN gL, Sbad = NULL;
656 :
657 1925 : if (!L) return cgetg(1,t_VEC);
658 1925 : if (ta == t_VEC)
659 : {
660 1008 : long l = lg(a);
661 1008 : if (l == 1) pari_err_TYPE("vecan_closure", a);
662 1008 : ta = typ(gel(a,1));
663 : /* regular vector, return it */
664 1008 : if (ta != t_CLOSURE) return vecslice(a, 1, minss(L,l-1));
665 119 : if (l != 3) pari_err_TYPE("vecan_closure", a);
666 119 : Sbad = gel(a,2);
667 119 : if (typ(Sbad) != t_VEC) pari_err_TYPE("vecan_closure", a);
668 112 : a = gel(a,1);
669 : }
670 917 : else if (ta != t_CLOSURE) pari_err_TYPE("vecan_closure", a);
671 1015 : push_localprec(prec);
672 1015 : gL = stoi(L);
673 1015 : switch(closure_arity(a))
674 : {
675 371 : case 2:
676 371 : a = direuler_bad((void*)a, localfactor, gen_2, gL,gL, Sbad);
677 336 : break;
678 637 : case 1:
679 637 : a = closure_callgen1(a, gL);
680 637 : if (typ(a) != t_VEC) pari_err_TYPE("vecan_closure", a);
681 630 : break;
682 7 : default: pari_err_TYPE("vecan_closure [wrong arity]", a);
683 : a = NULL; /*LCOV_EXCL_LINE*/
684 : }
685 966 : pop_localprec(); return a;
686 : }
687 :
688 : static GEN
689 70 : eulerf_closure(GEN a, GEN p, long prec)
690 : {
691 70 : long ta = typ(a);
692 70 : GEN Sbad = NULL, f;
693 :
694 70 : if (ta == t_VEC)
695 : {
696 0 : long l = lg(a);
697 0 : if (l == 1) pari_err_TYPE("vecan_closure", a);
698 0 : ta = typ(gel(a,1));
699 : /* regular vector, return it */
700 0 : if (ta != t_CLOSURE) return NULL;
701 0 : if (l != 3) pari_err_TYPE("vecan_closure", a);
702 0 : Sbad = gel(a,2);
703 0 : if (typ(Sbad) != t_VEC) pari_err_TYPE("vecan_closure", a);
704 0 : a = gel(a,1);
705 : }
706 70 : else if (ta != t_CLOSURE) pari_err_TYPE("vecan_closure", a);
707 70 : push_localprec(prec);
708 70 : switch(closure_arity(a))
709 : {
710 14 : case 2:
711 14 : f = closure_callgen2(a, p, mkoo()); break;
712 56 : case 1:
713 56 : f = NULL; break;
714 0 : default:
715 0 : f = NULL; pari_err_TYPE("vecan_closure", a);
716 : }
717 70 : pop_localprec(); return f;
718 : }
719 :
720 : /*****************************************************************/
721 : /* L-series of Dirichlet characters. */
722 : /*****************************************************************/
723 :
724 : static GEN
725 1757 : lfunzeta(void)
726 : {
727 1757 : GEN zet = mkvecn(7, NULL, gen_0, NULL, gen_1, gen_1, gen_1, gen_1);
728 1757 : gel(zet,1) = tag(gen_1, t_LFUN_ZETA);
729 1757 : gel(zet,3) = mkvec(gen_0);
730 1757 : return zet;
731 : }
732 :
733 : static GEN
734 1295 : vecan_Kronecker(GEN D, long n)
735 : {
736 1295 : GEN v = cgetg(n+1, t_VECSMALL);
737 1295 : ulong Du = itou_or_0(D);
738 1295 : long i, id, d = Du ? minuu(Du, n): n;
739 31913 : for (i = 1; i <= d; i++) v[i] = krois(D,i);
740 171024 : for (id = i; i <= n; i++,id++) /* periodic mod d */
741 : {
742 169729 : if (id > d) id = 1;
743 169729 : gel(v, i) = gel(v, id);
744 : }
745 1295 : return v;
746 : }
747 :
748 : static GEN
749 4172 : lfunchiquad(GEN D)
750 : {
751 : GEN r;
752 4172 : D = coredisc(D);
753 4172 : if (equali1(D)) return lfunzeta();
754 3647 : if (!isfundamental(D)) pari_err_TYPE("lfunchiquad [not primitive]", D);
755 3647 : r = mkvecn(6, NULL, gen_0, NULL, gen_1, NULL, gen_1);
756 3647 : gel(r,1) = tag(icopy(D), t_LFUN_KRONECKER);
757 3647 : gel(r,3) = mkvec(signe(D) < 0? gen_1: gen_0);
758 3647 : gel(r,5) = mpabs(D);
759 3647 : return r;
760 : }
761 :
762 : /* Begin Hecke characters. Here a character is assumed to be given by a
763 : vector on the generators of the ray class group clgp of CL_m(K).
764 : If clgp = [h,[d1,...,dk],[g1,...,gk]] with dk|...|d2|d1, a character chi
765 : is given by [a1,a2,...,ak] such that chi(gi)=\zeta_di^ai. */
766 :
767 : /* Value of CHI on x, coprime to bnr.mod */
768 : static GEN
769 96516 : chigeneval_i(GEN logx, GEN d, GEN nchi, GEN z, long prec)
770 : {
771 96516 : pari_sp av = avma;
772 96516 : GEN e = FpV_dotproduct(nchi, logx, d);
773 96516 : if (!is_vec_t(typ(z)))
774 1225 : return gerepileupto(av, gpow(z, e, prec));
775 : else
776 : {
777 95291 : ulong i = itou(e);
778 95291 : set_avma(av); return gel(z, i+1);
779 : }
780 : }
781 :
782 : static GEN
783 84343 : chigenevalvec(GEN logx, GEN nchi, GEN z, long prec, long multi)
784 : {
785 84343 : GEN d = gel(nchi,1), x = gel(nchi, 2);
786 84343 : if (multi)
787 35301 : pari_APPLY_same(chigeneval_i(logx, d, gel(x,i), z, prec))
788 : else
789 72779 : return chigeneval_i(logx, d, x, z, prec);
790 : }
791 :
792 : /* return x + yz; y != 0; z = 0,1 "often"; x = 0 "often" */
793 : static GEN
794 1886304 : gaddmul(GEN x, GEN y, GEN z)
795 : {
796 : pari_sp av;
797 1886304 : if (typ(z) == t_INT)
798 : {
799 1683759 : if (!signe(z)) return x;
800 28322 : if (equali1(z)) return gadd(x,y);
801 : }
802 222495 : if (isintzero(x)) return gmul(y,z);
803 119931 : av = avma;
804 119931 : return gerepileupto(av, gadd(x, gmul(y,z)));
805 : }
806 :
807 : static GEN
808 1805328 : gaddmulvec(GEN x, GEN y, GEN z, long multi)
809 : {
810 1805328 : if (multi)
811 244538 : pari_APPLY_same(gaddmul(gel(x,i),gel(y,i),gel(z,i)))
812 : else
813 1723547 : return gaddmul(x,y,z);
814 : }
815 :
816 : static GEN
817 1925 : mkvchi(GEN chi, long n)
818 : {
819 : GEN v;
820 1925 : if (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))))
821 469 : {
822 469 : long d = lg(chi)-1;
823 469 : v = const_vec(n, zerovec(d));
824 469 : gel(v,1) = const_vec(d, gen_1);
825 : }
826 : else
827 1456 : v = vec_ei(n, 1);
828 1925 : return v;
829 : }
830 :
831 : static GEN
832 980 : vecan_chiZ(GEN an, long n, long prec)
833 : {
834 : forprime_t iter;
835 980 : GEN G = gel(an,1);
836 980 : GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2), z;
837 980 : GEN gp = cgetipos(3), v = mkvchi(chi, n);
838 980 : GEN N = znstar_get_N(G);
839 980 : long ord = itos_or_0(gord);
840 980 : ulong Nu = itou_or_0(N);
841 980 : long i, id, d = Nu ? minuu(Nu, n): n;
842 980 : long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))));
843 : ulong p;
844 980 : if (!multichi && ord && n > (ord>>4))
845 854 : {
846 854 : GEN w = ncharvecexpo(G, nchi);
847 854 : z = grootsof1(ord, prec);
848 14735 : for (i = 1; i <= d; i++)
849 13881 : if (w[i] >= 0) gel(v, i) = gel(z, w[i]+1);
850 : }
851 : else
852 : {
853 126 : z = rootsof1_cx(gord, prec);
854 126 : u_forprime_init(&iter, 2, d);
855 805 : while ((p = u_forprime_next(&iter)))
856 : {
857 : GEN ch;
858 : ulong k;
859 679 : if (!umodiu(N,p)) continue;
860 560 : gp[2] = p;
861 560 : ch = chigenevalvec(znconreylog(G, gp), nchi, z, prec, multichi);
862 560 : gel(v, p) = ch;
863 1582 : for (k = 2*p; k <= (ulong)d; k += p)
864 1022 : gel(v, k) = gaddmulvec(gel(v, k), ch, gel(v, k/p), multichi);
865 : }
866 : }
867 271054 : for (id = i = d+1; i <= n; i++,id++) /* periodic mod d */
868 : {
869 270074 : if (id > d) id = 1;
870 270074 : gel(v, i) = gel(v, id);
871 : }
872 980 : return v;
873 : }
874 :
875 : static GEN
876 42 : eulerf_chiZ(GEN an, GEN p, long prec)
877 : {
878 42 : GEN G = gel(an,1);
879 42 : GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2);
880 42 : long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))));
881 42 : GEN z = rootsof1_cx(gord, prec);
882 42 : GEN N = znstar_get_N(G);
883 42 : GEN ch = dvdii(N,p) ? gen_0: chigenevalvec(znconreylog(G, p), nchi, z, prec, multichi);
884 42 : return mkrfrac(gen_1, deg1pol_shallow(gneg(ch), gen_1,0));
885 : }
886 :
887 : static GEN
888 945 : vecan_chigen(GEN an, long n, long prec)
889 : {
890 : forprime_t iter;
891 945 : GEN bnr = gel(an,1), nf = bnr_get_nf(bnr);
892 945 : GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2), z;
893 945 : GEN gp = cgetipos(3), v = mkvchi(chi, n);
894 945 : GEN N = gel(bnr_get_mod(bnr), 1), NZ = gcoeff(N,1,1);
895 945 : long ord = itos_or_0(gord);
896 945 : long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))));
897 : ulong p;
898 :
899 945 : if (ord && n > (ord>>4))
900 945 : z = grootsof1(ord, prec);
901 : else
902 0 : z = rootsof1_cx(gord, prec);
903 :
904 945 : if (nf_get_degree(nf) == 1)
905 : {
906 546 : ulong Nu = itou_or_0(NZ);
907 546 : long i, id, d = Nu ? minuu(Nu, n): n;
908 546 : u_forprime_init(&iter, 2, d);
909 3206 : while ((p = u_forprime_next(&iter)))
910 : {
911 : GEN ch;
912 : ulong k;
913 2660 : if (!umodiu(NZ,p)) continue;
914 2093 : gp[2] = p;
915 2093 : ch = chigenevalvec(isprincipalray(bnr,gp), nchi, z, prec, multichi);
916 2093 : gel(v, p) = ch;
917 6692 : for (k = 2*p; k <= (ulong)d; k += p)
918 4599 : gel(v, k) = gaddmulvec(gel(v, k), ch, gel(v, k/p), multichi);
919 : }
920 7000 : for (id = i = d+1; i <= n; i++,id++) /* periodic mod d */
921 : {
922 6454 : if (id > d) id = 1;
923 6454 : gel(v, i) = gel(v, id);
924 : }
925 : }
926 : else
927 : {
928 399 : GEN BOUND = stoi(n);
929 399 : u_forprime_init(&iter, 2, n);
930 82369 : while ((p = u_forprime_next(&iter)))
931 : {
932 : GEN L;
933 : long j;
934 81970 : int check = !umodiu(NZ,p);
935 81970 : gp[2] = p;
936 81970 : L = idealprimedec_limit_norm(nf, gp, BOUND);
937 163828 : for (j = 1; j < lg(L); j++)
938 : {
939 81858 : GEN pr = gel(L, j), ch;
940 : ulong k, q;
941 81858 : if (check && idealval(nf, N, pr)) continue;
942 81613 : ch = chigenevalvec(isprincipalray(bnr,pr), nchi, z, prec, multichi);
943 81613 : q = upr_norm(pr);
944 81613 : gel(v, q) = gadd(gel(v, q), ch);
945 1881320 : for (k = 2*q; k <= (ulong)n; k += q)
946 1799707 : gel(v, k) = gaddmulvec(gel(v, k), ch, gel(v, k/q), multichi);
947 : }
948 : }
949 : }
950 945 : return v;
951 : }
952 :
953 : static GEN
954 28 : eulerf_chigen(GEN an, GEN p, long prec)
955 : {
956 28 : GEN bnr = gel(an,1), nf = bnr_get_nf(bnr);
957 28 : GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2), z;
958 28 : GEN N = gel(bnr_get_mod(bnr), 1), NZ = gcoeff(N,1,1), f;
959 28 : long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))));
960 :
961 28 : z = rootsof1_cx(gord, prec);
962 28 : if (nf_get_degree(nf) == 1)
963 : {
964 : GEN ch;
965 0 : if (dvdii(NZ,p)) ch = gen_0;
966 : else
967 : {
968 0 : ch = chigenevalvec(isprincipalray(bnr,p), nchi, z, prec, multichi);
969 0 : if (typ(ch)==t_VEC) return NULL;
970 : }
971 0 : f = deg1pol_shallow(gneg(ch), gen_1, 0);
972 : }
973 : else
974 : {
975 28 : int check = dvdii(NZ,p);
976 28 : GEN L = idealprimedec(nf, p);
977 28 : long j, lL = lg(L);
978 28 : f = pol_1(0);
979 49 : for (j = 1; j < lL; j++)
980 : {
981 35 : GEN pr = gel(L, j), ch;
982 35 : if (check && idealval(nf, N, pr)) ch = gen_0;
983 : else
984 35 : ch = chigenevalvec(isprincipalray(bnr,pr), nchi, z, prec, multichi);
985 35 : if (typ(ch)==t_VEC) return NULL;
986 21 : f = gmul(f, gsub(gen_1, monomial(ch, pr_get_f(pr), 0)));
987 : }
988 : }
989 14 : return mkrfrac(gen_1,f);
990 : }
991 :
992 : static GEN
993 4221 : vec01(long r1, long r2)
994 : {
995 4221 : long d = r1+r2, i;
996 4221 : GEN v = cgetg(d+1,t_VEC);
997 11851 : for (i = 1; i <= r1; i++) gel(v,i) = gen_0;
998 6671 : for ( ; i <= d; i++) gel(v,i) = gen_1;
999 4221 : return v;
1000 : }
1001 :
1002 : /* true nf or t_POL */
1003 : static GEN
1004 1127 : lfunzetak_i(GEN T)
1005 : {
1006 : GEN Vga, N;
1007 : long r1, r2;
1008 1127 : if (typ(T) == t_POL)
1009 : {
1010 560 : T = nfinit0(T, nf_NOLLL, DEFAULTPREC);
1011 560 : if (lg(T) == 3) T = gel(T,1); /* [nf,change of var] */
1012 : }
1013 1127 : nf_get_sign(T,&r1,&r2); Vga = vec01(r1+r2,r2);
1014 1127 : N = absi_shallow(nf_get_disc(T));
1015 1127 : return mkvecn(7, tag(T,t_LFUN_NF), gen_0, Vga, gen_1, N, gen_1, gen_0);
1016 : }
1017 : /* truen nf or t_POL */
1018 : static GEN
1019 714 : lfunzetak(GEN T)
1020 714 : { pari_sp av = avma; return gerepilecopy(av, lfunzetak_i(T)); }
1021 :
1022 : /* v = vector of normalized characters of order dividing o; renormalize
1023 : * so that all have same apparent order o */
1024 : static GEN
1025 203 : char_renormalize(GEN v, GEN o)
1026 : {
1027 : long i, l;
1028 203 : GEN w = cgetg_copy(v, &l);
1029 770 : for (i = 1; i < l; i++)
1030 : {
1031 567 : GEN C = gel(v,i), oc = gel(C,1), c = gel(C,2);
1032 567 : if (!equalii(o, oc)) c = gmul(c, diviiexact(o, oc));
1033 567 : gel(w,i) = c;
1034 : }
1035 203 : return w;
1036 : }
1037 : /* G is a bid of nftyp typ_BIDZ */
1038 : static GEN
1039 1750 : lfunchiZ(GEN G, GEN CHI)
1040 : {
1041 1750 : pari_sp av = avma;
1042 1750 : GEN sig = NULL, N = bid_get_ideal(G), nchi, r;
1043 : int real;
1044 : long s;
1045 :
1046 1750 : if (typ(N) != t_INT) pari_err_TYPE("lfunchiZ", G);
1047 1750 : if (typ(CHI) == t_VEC && !RgV_is_ZV(CHI))
1048 14 : {
1049 35 : GEN C, G0 = G, o = gen_1;
1050 35 : long i, l = lg(CHI);
1051 35 : nchi = cgetg(l, t_VEC);
1052 35 : N = znconreyconductor(G, gel(CHI,1), &C);
1053 28 : if (typ(N) != t_INT) G = znstar0(N, 1);
1054 28 : s = zncharisodd(G, C);
1055 70 : for (i = 1; i < l; i++)
1056 : {
1057 56 : if (i > 1)
1058 : {
1059 28 : if (!gequal(N, znconreyconductor(G0, gel(CHI,i), &C))
1060 21 : || zncharisodd(G, C) != s)
1061 14 : pari_err_TYPE("lfuncreate [different conductors]", CHI);
1062 : }
1063 42 : C = znconreylog_normalize(G, C);
1064 42 : o = lcmii(o, gel(C,1)); /* lcm with charorder */
1065 42 : gel(nchi,i) = C;
1066 : }
1067 14 : nchi = mkvec2(o, char_renormalize(nchi, o));
1068 14 : if (typ(N) != t_INT) N = gel(N,1);
1069 : }
1070 : else
1071 : {
1072 1715 : N = znconreyconductor(G, CHI, &CHI);
1073 1715 : if (typ(N) != t_INT)
1074 : {
1075 7 : if (equali1(gel(N,1))) { set_avma(av); return lfunzeta(); }
1076 0 : G = znstar0(N, 1);
1077 0 : N = gel(N,1);
1078 : }
1079 : /* CHI now primitive on G */
1080 1708 : switch(itou_or_0(zncharorder(G, CHI)))
1081 : {
1082 427 : case 1: set_avma(av); return lfunzeta();
1083 665 : case 2: if (zncharisodd(G,CHI)) N = negi(N);
1084 665 : return gerepileupto(av, lfunchiquad(N));
1085 : }
1086 616 : nchi = znconreylog_normalize(G, CHI);
1087 616 : s = zncharisodd(G, CHI);
1088 : }
1089 630 : sig = mkvec(s? gen_1: gen_0);
1090 630 : real = abscmpiu(gel(nchi,1), 2) <= 0;
1091 630 : r = mkvecn(6, tag(mkvec2(G,nchi), t_LFUN_CHIZ),
1092 : real? gen_0: gen_1, sig, gen_1, N, gen_0);
1093 630 : return gerepilecopy(av, r);
1094 : }
1095 :
1096 : static GEN
1097 1197 : lfunchigen(GEN bnr, GEN CHI)
1098 : {
1099 1197 : pari_sp av = avma;
1100 : GEN N, sig, Ldchi, nf, nchi, NN;
1101 : long r1, r2, n1;
1102 : int real;
1103 :
1104 1197 : if (typ(CHI) == t_VEC && !RgV_is_ZV(CHI))
1105 189 : {
1106 196 : long map, i, l = lg(CHI);
1107 196 : GEN bnr0 = bnr, D, chi = gel(CHI,1), o = gen_1;
1108 196 : nchi = cgetg(l, t_VEC);
1109 196 : bnr_char_sanitize(&bnr, &chi);
1110 196 : D = cyc_normalize(bnr_get_cyc(bnr));
1111 196 : N = bnr_get_mod(bnr);
1112 196 : map = (bnr != bnr0);
1113 742 : for (i = 1; i < l; i++)
1114 : {
1115 553 : if (i > 1)
1116 : {
1117 357 : chi = gel(CHI,i);
1118 357 : if (!map)
1119 : {
1120 343 : if (!bnrisconductor(bnr, chi))
1121 7 : pari_err_TYPE("lfuncreate [different conductors]", CHI);
1122 : }
1123 : else
1124 : {
1125 14 : if (!gequal(bnrconductor_raw(bnr0, chi), N))
1126 0 : pari_err_TYPE("lfuncreate [different conductors]", CHI);
1127 14 : chi = bnrchar_primitive_raw(bnr0, bnr, chi);
1128 : }
1129 : }
1130 546 : chi = char_normalize(chi, D);
1131 546 : o = lcmii(o, gel(chi,1)); /* lcm with charorder */
1132 546 : gel(nchi,i) = chi;
1133 : }
1134 189 : nchi = mkvec2(o, char_renormalize(nchi, o));
1135 : }
1136 : else
1137 : {
1138 1001 : bnr_char_sanitize(&bnr, &CHI);
1139 1001 : nchi = NULL; /* now CHI is primitive wrt bnr */
1140 : }
1141 :
1142 1190 : N = bnr_get_mod(bnr);
1143 1190 : nf = bnr_get_nf(bnr);
1144 1190 : n1 = lg(vec01_to_indices(gel(N,2))) - 1; /* vecsum(N[2]) */
1145 1190 : N = gel(N,1);
1146 1190 : NN = mulii(idealnorm(nf, N), absi_shallow(nf_get_disc(nf)));
1147 1190 : if (!nchi)
1148 : {
1149 1001 : if (equali1(NN)) { set_avma(av); return lfunzeta(); }
1150 581 : if (ZV_equal0(CHI)) return gerepilecopy(av, lfunzetak_i(bnr_get_nf(bnr)));
1151 504 : nchi = char_normalize(CHI, cyc_normalize(bnr_get_cyc(bnr)));
1152 : }
1153 693 : real = abscmpiu(gel(nchi,1), 2) <= 0;
1154 693 : nf_get_sign(nf, &r1, &r2);
1155 693 : sig = vec01(r1+r2-n1, r2+n1);
1156 693 : Ldchi = mkvecn(6, tag(mkvec2(bnr, nchi), t_LFUN_CHIGEN),
1157 : real? gen_0: gen_1, sig, gen_1, NN, gen_0);
1158 693 : return gerepilecopy(av, Ldchi);
1159 : }
1160 :
1161 : /* Find all characters of clgp whose kernel contain group given by HNF H.
1162 : * Set *pcnj[i] to the conductor */
1163 : static GEN
1164 497 : chigenkerfind(GEN bnr, GEN H, GEN *pcnj)
1165 : {
1166 497 : GEN res, cnj, L = bnrchar(bnr, H, NULL);
1167 497 : long i, k, l = lg(L);
1168 :
1169 497 : res = cgetg(l, t_VEC);
1170 497 : *pcnj = cnj = cgetg(l, t_VEC);
1171 1841 : for (i = k = 1; i < l; i++)
1172 : {
1173 1344 : GEN chi = gel(L,i);
1174 1344 : gel(res, k) = chi;
1175 1344 : gel(cnj, k) = ZV_equal0(chi)? gen_0: bnrconductorofchar(bnr, chi);
1176 1344 : k++;
1177 : }
1178 497 : setlg(cnj, k);
1179 497 : setlg(res, k); return res;
1180 : }
1181 :
1182 : static GEN
1183 497 : vec_classes(GEN A, GEN F)
1184 : {
1185 497 : GEN w = vec_equiv(F);
1186 497 : long i, l = lg(w);
1187 497 : GEN V = cgetg(l, t_VEC);
1188 1512 : for (i = 1; i < l; i++) gel(V,i) = vecpermute(A,gel(w,i));
1189 497 : return V;
1190 : }
1191 :
1192 : static GEN
1193 989961 : abelrel_pfactor(GEN bnr, GEN pr, GEN U, GEN D, GEN h)
1194 : {
1195 989961 : GEN v = bnrisprincipalmod(bnr, pr, h, 0);
1196 989961 : GEN E = ZV_ZV_mod(ZM_ZC_mul(U, v), D);
1197 989961 : ulong o = itou(charorder(D, E)), f = pr_get_f(pr);
1198 989961 : return gpowgs(gsub(gen_1, monomial(gen_1, f * o, 0)), itou(h) / o);
1199 : }
1200 :
1201 : static GEN
1202 687435 : abelrel_factor(GEN bnr, GEN C, GEN p, GEN mod, GEN U, GEN D, GEN h)
1203 : {
1204 687435 : GEN nf = bnr_get_nf(bnr), F = pol_1(0), prid = idealprimedec(nf,p);
1205 687435 : GEN mod2 = shallowcopy(mod);
1206 687435 : long i, l = lg(prid);
1207 1677396 : for (i = 1; i < l; i++)
1208 : {
1209 989961 : GEN pr = gel(prid, i), Fpr;
1210 989961 : long v = idealval(nf,mod,pr);
1211 989961 : if (v > 0)
1212 : {
1213 : GEN bnr2, C2, U2, D2, h2;
1214 112 : gel(mod2, 1) = idealdivpowprime(nf, gel(mod, 1), pr, utoi(v));
1215 112 : bnr2 = bnrinitmod(bnr, mod2, 0, h);
1216 112 : C2 = bnrmap(bnrmap(bnr, bnr2), C);
1217 112 : D2 = ZM_snfall_i(C2, &U2, NULL, 1);
1218 112 : h2 = ZV_prod(D2);
1219 112 : Fpr = abelrel_pfactor(bnr2, pr, U2, D2, h2);
1220 : }
1221 : else
1222 989849 : Fpr = abelrel_pfactor(bnr, pr, U, D, h);
1223 989961 : F = ZX_mul(F, Fpr);
1224 : }
1225 687435 : return gcopy(mkrfrac(gen_1, F));
1226 : }
1227 :
1228 : static GEN
1229 28 : eulerf_abelrel(GEN an, GEN p)
1230 : {
1231 28 : GEN bnr = gel(an,1), C = gel(an,2), mod = gel(an,3);
1232 28 : GEN U, D = ZM_snfall_i(C, &U, NULL, 1), h = ZV_prod(D);
1233 28 : return abelrel_factor(bnr, C, p, mod, U, D, h);
1234 : }
1235 :
1236 : struct direuler_abelrel
1237 : {
1238 : GEN bnr, C, mod, U, D, h;
1239 : };
1240 :
1241 : static GEN
1242 687407 : _direuler_abelrel(void *E, GEN p)
1243 : {
1244 687407 : struct direuler_abelrel *s = (struct direuler_abelrel*) E;
1245 687407 : return abelrel_factor(s->bnr, s->C, p, s->mod, s->U, s->D, s->h);
1246 : }
1247 :
1248 : static GEN
1249 119 : vecan_abelrel(GEN an, long N)
1250 : {
1251 : struct direuler_abelrel s;
1252 119 : s.bnr = gel(an,1);
1253 119 : s.C = gel(an,2);
1254 119 : s.mod = gel(an,3);
1255 119 : s.D = ZM_snfall_i(s.C, &s.U, NULL, 1);
1256 119 : s.h = ZV_prod(s.D);
1257 119 : return direuler((void*)&s, _direuler_abelrel, gen_1, stoi(N), NULL);
1258 : }
1259 :
1260 : static GEN
1261 518 : lfunabelrel_i(GEN bnr, GEN H, GEN mod)
1262 : {
1263 518 : GEN NrD = bnrdisc(bnr, H, 0), N = absi_shallow(gel(NrD,3));
1264 518 : long n = itos(gel(NrD,1)), r1 = itos(gel(NrD,2)), r2 = (n-r1)>>1;
1265 518 : if (!mod) mod = bnrconductor(bnr, H, 0);
1266 518 : return mkvecn(7, tag(mkvec3(bnr,H,mod),t_LFUN_ABELREL),
1267 : gen_0, vec01(r1+r2, r2), gen_1, N, gen_1, gen_0);
1268 : }
1269 : static GEN
1270 21 : lfunabelrel(GEN bnr, GEN H, GEN mod)
1271 21 : { pari_sp av = avma; return gerepilecopy(av, lfunabelrel_i(bnr, H, mod)); }
1272 :
1273 : GEN
1274 497 : lfunabelianrelinit(GEN bnr, GEN H, GEN dom, long der, long bitprec)
1275 : {
1276 : GEN X, cnj, M, D,C ;
1277 : long l, i;
1278 497 : C = chigenkerfind(bnr, H, &cnj);
1279 497 : C = vec_classes (C, cnj);
1280 497 : X = cgetg_copy(C,&l);
1281 1512 : for (i = 1; i < l; ++i)
1282 : {
1283 1015 : GEN chi = gel(C,i);
1284 1015 : GEN L = lfunchigen(bnr, lg(chi)==2 ? gel(chi,1): chi);
1285 1015 : gel(X,i) = lfuninit(L, dom, der, bitprec);
1286 : }
1287 497 : M = mkvec3(X, const_vecsmall(l-1, 1), const_vecsmall(l-1, 0));
1288 497 : D = mkvec2(dom, mkvecsmall2(der, bitprec));
1289 497 : return lfuninit_make(t_LDESC_PRODUCT, lfunabelrel_i(bnr, H, NULL), M, D);
1290 : }
1291 :
1292 : /*****************************************************************/
1293 : /* Dedekind zeta functions */
1294 : /*****************************************************************/
1295 : /* true nf */
1296 : static GEN
1297 2079 : dirzetak0(GEN nf, ulong N)
1298 : {
1299 2079 : GEN vect, c, c2, T = nf_get_pol(nf), index = nf_get_index(nf);
1300 2079 : pari_sp av = avma, av2;
1301 2079 : const ulong SQRTN = usqrt(N);
1302 : ulong i, p, lx;
1303 2079 : long court[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0};
1304 : forprime_t S;
1305 :
1306 2079 : c = cgetalloc(N+1, t_VECSMALL);
1307 2079 : c2 = cgetalloc(N+1, t_VECSMALL);
1308 2568503 : c2[1] = c[1] = 1; for (i=2; i<=N; i++) c[i] = 0;
1309 2079 : u_forprime_init(&S, 2, N); av2 = avma;
1310 334327 : while ( (p = u_forprime_next(&S)) )
1311 : {
1312 332248 : set_avma(av2);
1313 332248 : if (umodiu(index, p)) /* p does not divide index */
1314 331891 : vect = gel(Flx_degfact(ZX_to_Flx(T,p), p),1);
1315 : else
1316 : {
1317 357 : court[2] = p;
1318 357 : vect = idealprimedec_degrees(nf,court);
1319 : }
1320 332248 : lx = lg(vect);
1321 332248 : if (p <= SQRTN)
1322 34160 : for (i=1; i<lx; i++)
1323 : {
1324 22743 : ulong qn, q = upowuu(p, vect[i]); /* Norm P[i] */
1325 22743 : if (!q || q > N) break;
1326 20188 : memcpy(c2 + 2, c + 2, (N-1)*sizeof(long));
1327 : /* c2[i] <- c[i] + sum_{k = 1}^{v_q(i)} c[i/q^k] for all i <= N */
1328 41559 : for (qn = q; qn <= N; qn *= q)
1329 : {
1330 41559 : ulong k0 = N/qn, k, k2; /* k2 = k*qn */
1331 3600261 : for (k = k0, k2 = k*qn; k > 0; k--, k2 -=qn) c2[k2] += c[k];
1332 41559 : if (q > k0) break; /* <=> q*qn > N */
1333 : }
1334 20188 : swap(c, c2);
1335 : }
1336 : else /* p > sqrt(N): simpler */
1337 628817 : for (i=1; i<lx; i++)
1338 : {
1339 : ulong k, k2; /* k2 = k*p */
1340 556500 : if (vect[i] > 1) break;
1341 : /* c2[i] <- c[i] + sum_{k = 1}^{v_q(i)} c[i/q^k] for all i <= N */
1342 1828477 : for (k = N/p, k2 = k*p; k > 0; k--, k2 -= p) c[k2] += c[k];
1343 : }
1344 : }
1345 2079 : set_avma(av);
1346 2079 : pari_free(c2); return c;
1347 : }
1348 :
1349 : static GEN
1350 168 : eulerf_zetak(GEN nf, GEN p)
1351 : {
1352 168 : GEN v, f = pol_1(0);
1353 : long i, l;
1354 168 : if (dvdii(nf_get_index(nf), p)) /* p does not divide index */
1355 7 : v = idealprimedec_degrees(nf,p);
1356 : else
1357 161 : v = gel(FpX_degfact(nf_get_pol(nf), p), 1);
1358 168 : l = lg(v);
1359 406 : for (i = 1; i < l; i++) f = ZX_sub(f, RgX_shift_shallow(f, v[i]));
1360 168 : retmkrfrac(gen_1, ZX_copy(f));
1361 : }
1362 :
1363 : GEN
1364 2079 : dirzetak(GEN nf, GEN b)
1365 : {
1366 : GEN z, c;
1367 : long n;
1368 :
1369 2079 : if (typ(b) != t_INT) pari_err_TYPE("dirzetak",b);
1370 2079 : if (signe(b) <= 0) return cgetg(1,t_VEC);
1371 2079 : nf = checknf(nf);
1372 2079 : n = itou_or_0(b); if (!n) pari_err_OVERFLOW("dirzetak");
1373 2079 : c = dirzetak0(nf, n);
1374 2079 : z = vecsmall_to_vec(c); pari_free(c); return z;
1375 : }
1376 :
1377 : static GEN
1378 630 : linit_get_mat(GEN linit)
1379 : {
1380 630 : if (linit_get_type(linit)==t_LDESC_PRODUCT)
1381 154 : return lfunprod_get_fact(linit_get_tech(linit));
1382 : else
1383 476 : return mkvec3(mkvec(linit), mkvecsmall(1), mkvecsmall(0));
1384 : }
1385 :
1386 : static GEN
1387 315 : lfunproduct(GEN ldata, GEN linit1, GEN linit2, GEN domain)
1388 : {
1389 315 : GEN M1 = linit_get_mat(linit1);
1390 315 : GEN M2 = linit_get_mat(linit2);
1391 315 : GEN M3 = mkvec3(shallowconcat(gel(M1, 1), gel(M2, 1)),
1392 315 : vecsmall_concat(gel(M1, 2), gel(M2, 2)),
1393 315 : vecsmall_concat(gel(M1, 3), gel(M2, 3)));
1394 315 : return lfuninit_make(t_LDESC_PRODUCT, ldata, M3, domain);
1395 : }
1396 : static GEN lfunzetakinit_artin(GEN nf, GEN gal, GEN dom, long der, long bit);
1397 : /* true nf */
1398 : static GEN
1399 315 : lfunzetakinit_quotient(GEN nf, GEN polk, GEN dom, long der, long bitprec)
1400 : {
1401 : GEN ak, an, nfk, Vga, ldata, N, Lk, LKk, domain;
1402 : long r1k, r2k, r1, r2;
1403 :
1404 315 : nf_get_sign(nf,&r1,&r2);
1405 315 : nfk = nfinit(polk, nbits2prec(bitprec));
1406 315 : Lk = lfunzetakinit(nfk, dom, der, bitprec); /* zeta_k */
1407 315 : nf_get_sign(nfk,&r1k,&r2k);
1408 315 : Vga = vec01((r1+r2) - (r1k+r2k), r2-r2k);
1409 315 : N = absi_shallow(diviiexact(nf_get_disc(nf), nf_get_disc(nfk)));
1410 315 : ak = nf_get_degree(nf)==1 ? tag(gen_1, t_LFUN_ZETA): tag(nfk, t_LFUN_NF);
1411 315 : an = tag(mkvec2(tag(nf,t_LFUN_NF), ak), t_LFUN_DIV);
1412 315 : ldata = mkvecn(6, an, gen_0, Vga, gen_1, N, gen_1);
1413 315 : LKk = lfuninit(ldata, dom, der, bitprec); /* zeta_K/zeta_k */
1414 315 : domain = mkvec2(dom, mkvecsmall2(der, bitprec));
1415 315 : return lfunproduct(lfunzetak_i(nf), Lk, LKk, domain);
1416 : }
1417 : /* true nf */
1418 : GEN
1419 910 : lfunzetakinit(GEN nf, GEN dom, long der, long bitprec)
1420 : {
1421 910 : long n, d = nf_get_degree(nf);
1422 910 : GEN L, Q, R, G, T = nf_get_pol(nf);
1423 910 : if (d == 1) return lfuninit(lfunzeta(), dom, der, bitprec);
1424 749 : G = galoisinit(nf, NULL);
1425 749 : if (isintzero(G))
1426 : {
1427 315 : GEN S = nfsubfields(nf, 0); n = lg(S)-1;
1428 315 : return lfunzetakinit_quotient(nf, gmael(S,n-1,1), dom, der, bitprec);
1429 : }
1430 434 : if (!group_isabelian(galois_group(G)))
1431 21 : return lfunzetakinit_artin(nf, G, dom, der, bitprec);
1432 413 : Q = Buchall(pol_x(1), 0, nbits2prec(bitprec));
1433 413 : T = shallowcopy(T); setvarn(T,0);
1434 413 : R = rnfconductor0(Q, T, 1);
1435 413 : L = lfunabelianrelinit(gel(R,2), gel(R,3), dom, der, bitprec);
1436 413 : delete_var(); return L;
1437 : }
1438 :
1439 : /***************************************************************/
1440 : /* Elliptic Curves and Modular Forms */
1441 : /***************************************************************/
1442 :
1443 : static GEN
1444 189 : lfunellnf(GEN e)
1445 : {
1446 189 : pari_sp av = avma;
1447 189 : GEN ldata = cgetg(7, t_VEC), nf = ellnf_get_nf(e);
1448 189 : GEN N = gel(ellglobalred(e), 1);
1449 189 : long n = nf_get_degree(nf);
1450 189 : gel(ldata, 1) = tag(e, t_LFUN_ELL);
1451 189 : gel(ldata, 2) = gen_0;
1452 189 : gel(ldata, 3) = vec01(n, n);
1453 189 : gel(ldata, 4) = gen_2;
1454 189 : gel(ldata, 5) = mulii(idealnorm(nf,N), sqri(nf_get_disc(nf)));
1455 189 : gel(ldata, 6) = stoi(ellrootno_global(e));
1456 189 : return gerepilecopy(av, ldata);
1457 : }
1458 :
1459 : static GEN
1460 1617 : lfunellQ(GEN e)
1461 : {
1462 1617 : pari_sp av = avma;
1463 1617 : GEN ldata = cgetg(7, t_VEC);
1464 1617 : gel(ldata, 1) = tag(ellanal_globalred(e, NULL), t_LFUN_ELL);
1465 1617 : gel(ldata, 2) = gen_0;
1466 1617 : gel(ldata, 3) = mkvec2(gen_0, gen_1);
1467 1617 : gel(ldata, 4) = gen_2;
1468 1617 : gel(ldata, 5) = ellQ_get_N(e);
1469 1617 : gel(ldata, 6) = stoi(ellrootno_global(e));
1470 1617 : return gerepilecopy(av, ldata); /* ellanal_globalred not gerepile-safe */
1471 : }
1472 :
1473 : static GEN
1474 1806 : lfunell(GEN e)
1475 : {
1476 1806 : long t = ell_get_type(e);
1477 1806 : switch(t)
1478 : {
1479 1617 : case t_ELL_Q: return lfunellQ(e);
1480 189 : case t_ELL_NF:return lfunellnf(e);
1481 : }
1482 0 : pari_err_TYPE("lfun",e);
1483 : return NULL; /*LCOV_EXCL_LINE*/
1484 : }
1485 :
1486 : static GEN
1487 140 : ellsympow_gamma(long m)
1488 : {
1489 140 : GEN V = cgetg(m+2, t_VEC);
1490 140 : long i = 1, j;
1491 140 : if (!odd(m)) gel(V, i++) = stoi(-2*(m>>2));
1492 364 : for (j = (m+1)>>1; j > 0; i+=2, j--)
1493 : {
1494 224 : gel(V,i) = stoi(1-j);
1495 224 : gel(V,i+1) = stoi(1-j+1);
1496 : }
1497 140 : return V;
1498 : }
1499 :
1500 : static GEN
1501 86785 : ellsympow_trace(GEN p, GEN t, long m)
1502 : {
1503 86785 : long k, n = m >> 1;
1504 86785 : GEN tp = gpowers0(sqri(t), n, odd(m)? t: NULL);
1505 86839 : GEN pp = gen_1, b = gen_1, r = gel(tp,n+1);
1506 246139 : for(k=1; k<=n; k++)
1507 : {
1508 : GEN s;
1509 159564 : pp = mulii(pp, p);
1510 158448 : b = diviuexact(muliu(b, (m-(2*k-1))*(m-(2*k-2))), k*(m-(k-1)));
1511 158159 : s = mulii(mulii(b, gel(tp,1+n-k)), pp);
1512 159009 : r = odd(k) ? subii(r, s): addii(r, s);
1513 : }
1514 86575 : return r;
1515 : }
1516 :
1517 : static GEN
1518 3129 : ellsympow_abelian(GEN p, GEN ap, long m, long o)
1519 : {
1520 3129 : pari_sp av = avma;
1521 3129 : long i, M, n = (m+1)>>1;
1522 : GEN pk, tv, pn, pm, F, v;
1523 3129 : if (!odd(o))
1524 : {
1525 0 : if (odd(m)) return pol_1(0);
1526 0 : M = m >> 1; o >>= 1;
1527 : }
1528 : else
1529 3129 : M = m * ((o+1) >> 1);
1530 3129 : pk = gpowers(p,n); pn = gel(pk,n+1);
1531 3129 : tv = cgetg(m+2,t_VEC);
1532 3129 : gel(tv, 1) = gen_2;
1533 3129 : gel(tv, 2) = ap;
1534 10668 : for (i = 3; i <= m+1; i++)
1535 7539 : gel(tv,i) = subii(mulii(ap,gel(tv,i-1)), mulii(p,gel(tv,i-2)));
1536 3129 : pm = odd(m)? mulii(gel(pk,n), pn): sqri(pn); /* cheap p^m */
1537 3129 : F = deg2pol_shallow(pm, gen_0, gen_1, 0);
1538 3129 : v = odd(m) ? pol_1(0): deg1pol_shallow(negi(pn), gen_1, 0);
1539 9450 : for (i = M % o; i < n; i += o) /* o | m-2*i */
1540 : {
1541 6321 : gel(F,3) = negi(mulii(gel(tv,m-2*i+1), gel(pk,i+1)));
1542 6321 : v = ZX_mul(v, F);
1543 : }
1544 3129 : return gerepilecopy(av, v);
1545 : }
1546 :
1547 : static GEN
1548 89911 : ellsympow(GEN E, ulong m, GEN p, long n)
1549 : {
1550 89911 : pari_sp av = avma;
1551 89911 : GEN ap = ellap(E, p);
1552 89874 : if (n <= 2)
1553 : {
1554 86774 : GEN t = ellsympow_trace(p, ap, m);
1555 86587 : return deg1pol_shallow(t, gen_1, 0);
1556 : }
1557 : else
1558 3100 : return gerepileupto(av, RgXn_inv_i(ellsympow_abelian(p, ap, m, 1), n));
1559 : }
1560 :
1561 : GEN
1562 5656 : direllsympow_worker(GEN P, ulong X, GEN E, ulong m)
1563 : {
1564 5656 : pari_sp av = avma;
1565 5656 : long i, l = lg(P);
1566 5656 : GEN W = cgetg(l, t_VEC);
1567 95552 : for(i = 1; i < l; i++)
1568 : {
1569 89897 : ulong p = uel(P,i);
1570 89897 : long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */
1571 89909 : gel(W,i) = ellsympow(E, m, utoi(uel(P,i)), d);
1572 : }
1573 5655 : return gerepilecopy(av, mkvec2(P,W));
1574 : }
1575 :
1576 : static GEN
1577 56 : eulerf_bad(GEN bad, GEN p)
1578 : {
1579 56 : long i, l = lg(bad);
1580 112 : for (i = 1; i < l; i++)
1581 56 : if (equalii(gmael(bad,i,1), p))
1582 0 : return gmael(bad,i,2);
1583 56 : return NULL;
1584 : }
1585 :
1586 : static GEN
1587 343 : vecan_ellsympow(GEN an, long n)
1588 : {
1589 343 : GEN nn = utoi(n), crvm = gel(an,1), bad = gel(an,2);
1590 343 : GEN worker = snm_closure(is_entry("_direllsympow_worker"), crvm);
1591 343 : return pardireuler(worker, gen_2, nn, nn, bad);
1592 : }
1593 :
1594 : static GEN
1595 28 : eulerf_ellsympow(GEN an, GEN p)
1596 : {
1597 28 : GEN crvm = gel(an,1), bad = gel(an,2), E = gel(crvm,1);
1598 28 : GEN f = eulerf_bad(bad, p);
1599 28 : if (f) return f;
1600 28 : retmkrfrac(gen_1,ellsympow_abelian(p, ellap(E, p), itos(gel(crvm,2)), 1));
1601 : }
1602 :
1603 : static long
1604 196 : ellsympow_betam(long o, long m)
1605 : {
1606 196 : const long c3[]={3, -1, 1};
1607 196 : const long c12[]={6, -2, 2, 0, 4, -4};
1608 196 : const long c24[]={12, -2, -4, 6, 4, -10};
1609 196 : if (!odd(o) && odd(m)) return 0;
1610 161 : switch(o)
1611 : {
1612 0 : case 1: return m+1;
1613 14 : case 2: return m+1;
1614 84 : case 3: case 6: return (m+c3[m%3])/3;
1615 0 : case 4: return m%4 == 0 ? (m+2)/2: m/2;
1616 21 : case 8: return m%4 == 0 ? (m+4)/4: (m-2)/4;
1617 35 : case 12: return (m+c12[(m%12)/2])/6;
1618 7 : case 24: return (m+c24[(m%12)/2])/12;
1619 : }
1620 0 : return 0;
1621 : }
1622 :
1623 : static long
1624 98 : ellsympow_epsm(long o, long m) { return m + 1 - ellsympow_betam(o, m); }
1625 :
1626 : static GEN
1627 98 : ellsympow_multred(GEN E, GEN p, long m, long vN, long *cnd, long *w)
1628 : {
1629 98 : if (vN == 1 || !odd(m))
1630 : {
1631 98 : GEN s = (odd(m) && signe(ellap(E,p)) < 0)? gen_1: gen_m1;
1632 98 : *cnd = m;
1633 98 : *w = odd(m)? ellrootno(E, p): 1;
1634 98 : return deg1pol_shallow(s, gen_1, 0);
1635 : }
1636 : else
1637 : {
1638 0 : *cnd = equaliu(p,2)? ((m+1)>>1) * vN: m+1;
1639 0 : *w = (m & 3) == 1? ellrootno(E, p): 1;
1640 0 : return pol_1(0);
1641 : }
1642 : }
1643 :
1644 : static GEN
1645 98 : ellsympow_nonabelian(GEN p, long m, long bet)
1646 : {
1647 98 : GEN q = powiu(p, m >> 1), q2 = sqri(q), F;
1648 98 : if (odd(m))
1649 : {
1650 35 : q2 = mulii(q2, p); /* p^m */
1651 35 : return gpowgs(deg2pol_shallow(q2, gen_0, gen_1, 0), bet>>1);
1652 : }
1653 63 : togglesign_safe(&q2);
1654 63 : F = gpowgs(deg2pol_shallow(q2, gen_0, gen_1, 0), bet>>1);
1655 63 : if (!odd(bet)) return F;
1656 28 : if (m%4 != 2) togglesign_safe(&q);
1657 28 : return gmul(F, deg1pol_shallow(q, gen_1, 0));
1658 : }
1659 :
1660 : static long
1661 0 : safe_Z_pvalrem(GEN n, GEN p, GEN *pr)
1662 0 : { return signe(n)==0? -1: Z_pvalrem(n, p, pr); }
1663 :
1664 : static GEN
1665 0 : c4c6_ap(GEN c4, GEN c6, GEN p)
1666 : {
1667 0 : GEN N = Fp_ellcard(Fp_muls(c4, -27, p), Fp_muls(c6, -54, p), p);
1668 0 : return subii(addiu(p, 1), N);
1669 : }
1670 :
1671 : static GEN
1672 0 : ellsympow_abelian_twist(GEN E, GEN p, long m, long o)
1673 : {
1674 0 : GEN ap, c4t, c6t, c4 = ell_get_c4(E), c6 = ell_get_c6(E);
1675 0 : long v4 = safe_Z_pvalrem(c4, p, &c4t);
1676 0 : long v6 = safe_Z_pvalrem(c6, p, &c6t);
1677 0 : if (v6>=0 && (v4==-1 || 3*v4>=2*v6)) c6 = c6t;
1678 0 : if (v4>=0 && (v6==-1 || 3*v4<=2*v6)) c4 = c4t;
1679 0 : ap = c4c6_ap(c4, c6, p);
1680 0 : return ellsympow_abelian(p, ap, m, o);
1681 : }
1682 :
1683 : static GEN
1684 0 : ellsympow_goodred(GEN E, GEN p, long m, long *cnd, long *w)
1685 : {
1686 0 : long o = 12/cgcd(12, Z_pval(ell_get_disc(E), p));
1687 0 : long bet = ellsympow_betam(o, m);
1688 0 : long eps = m + 1 - bet;
1689 0 : *w = odd(m) && odd(eps>>1) ? ellrootno(E,p): 1;
1690 0 : *cnd = eps;
1691 0 : if (umodiu(p, o) == 1)
1692 0 : return ellsympow_abelian_twist(E, p, m, o);
1693 : else
1694 0 : return ellsympow_nonabelian(p, m, bet);
1695 : }
1696 :
1697 : static long
1698 70 : ellsympow_inertia3(GEN E, long vN)
1699 : {
1700 70 : long vD = Z_lval(ell_get_disc(E), 3);
1701 70 : if (vN==2) return vD%2==0 ? 2: 4;
1702 70 : if (vN==4) return vD%4==0 ? 3: 6;
1703 70 : if (vN==3 || vN==5) return 12;
1704 0 : return 0;
1705 : }
1706 :
1707 : static long
1708 70 : ellsympow_deltam3(long o, long m, long vN)
1709 : {
1710 70 : if (o==3 || o==6) return ellsympow_epsm(3, m);
1711 70 : if (o==12 && vN ==3) return (ellsympow_epsm(3, m))/2;
1712 0 : if (o==12 && vN ==5) return (ellsympow_epsm(3, m))*3/2;
1713 0 : return 0;
1714 : }
1715 :
1716 : static long
1717 0 : ellsympow_isabelian3(GEN E)
1718 : {
1719 0 : ulong c4 = umodiu(ell_get_c4(E),81), c6 = umodiu(ell_get_c6(E), 243);
1720 0 : return (c4 == 27 || (c4%27==9 && (c6==108 || c6==135)));
1721 : }
1722 :
1723 : static long
1724 35 : ellsympow_rootno3(GEN E, GEN p, long o, long m)
1725 : {
1726 35 : const long w6p[]={1,-1,-1,-1,1,1};
1727 35 : const long w6n[]={-1,1,-1,1,-1,1};
1728 35 : const long w12p[]={1,1,-1,1,1,1};
1729 35 : const long w12n[]={-1,-1,-1,-1,-1,1};
1730 35 : long w = ellrootno(E, p), mm = (m%12)>>1;
1731 35 : switch(o)
1732 : {
1733 0 : case 2: return m%4== 1 ? -1: 1;
1734 0 : case 6: return w == 1 ? w6p[mm]: w6n[mm];
1735 35 : case 12: return w == 1 ? w12p[mm]: w12n[mm];
1736 0 : default: return 1;
1737 : }
1738 : }
1739 :
1740 : static GEN
1741 70 : ellsympow_goodred3(GEN E, GEN F, GEN p, long m, long vN, long *cnd, long *w)
1742 : {
1743 70 : long o = ellsympow_inertia3(E, vN);
1744 70 : long bet = ellsympow_betam(o, m);
1745 70 : *cnd = m + 1 - bet + ellsympow_deltam3(o, m, vN);
1746 70 : *w = odd(m)? ellsympow_rootno3(E, p, o, m): 1;
1747 70 : if (o==1 || o==2)
1748 0 : return ellsympow_abelian(p, ellap(F, p), m, o);
1749 70 : if ((o==3 || o==6) && ellsympow_isabelian3(F))
1750 0 : return ellsympow_abelian(p, p, m, o);
1751 : else
1752 70 : return ellsympow_nonabelian(p, m, bet);
1753 : }
1754 :
1755 : static long
1756 28 : ellsympow_inertia2(GEN F, long vN)
1757 : {
1758 28 : long vM = itos(gel(elllocalred(F, gen_2),1));
1759 28 : GEN c6 = ell_get_c6(F);
1760 28 : long v6 = signe(c6) ? vali(c6): 24;
1761 28 : if (vM==0) return vN==0 ? 1: 2;
1762 28 : if (vM==2) return vN==2 ? 3: 6;
1763 14 : if (vM==5) return 8;
1764 7 : if (vM==8) return v6>=9? 8: 4;
1765 7 : if (vM==3 || vN==7) return 24;
1766 0 : return 0;
1767 : }
1768 :
1769 : static long
1770 28 : ellsympow_deltam2(long o, long m, long vN)
1771 : {
1772 28 : if ((o==2 || o==6) && vN==4) return ellsympow_epsm(2, m);
1773 28 : if ((o==2 || o==6) && vN==6) return 2*ellsympow_epsm(2, m);
1774 28 : if (o==4) return 2*ellsympow_epsm(4, m)+ellsympow_epsm(2, m);
1775 28 : if (o==8 && vN==5) return ellsympow_epsm(8, m)+ellsympow_epsm(2, m)/2;
1776 21 : if (o==8 && vN==6) return ellsympow_epsm(8, m)+ellsympow_epsm(2, m);
1777 21 : if (o==8 && vN==8) return ellsympow_epsm(8, m)+ellsympow_epsm(4, m)+ellsympow_epsm(2, m);
1778 21 : if (o==24 && vN==3) return (2*ellsympow_epsm(8, m)+ellsympow_epsm(2, m))/6;
1779 14 : if (o==24 && vN==4) return (ellsympow_epsm(8, m)+ellsympow_epsm(2, m)*2)/3;
1780 14 : if (o==24 && vN==6) return (ellsympow_epsm(8, m)+ellsympow_epsm(2, m)*5)/3;
1781 14 : if (o==24 && vN==7) return (ellsympow_epsm(8, m)*10+ellsympow_epsm(2, m)*5)/6;
1782 14 : return 0;
1783 : }
1784 :
1785 : static long
1786 0 : ellsympow_isabelian2(GEN F)
1787 0 : { return umodi2n(ell_get_c4(F),7) == 96; }
1788 :
1789 : static long
1790 0 : ellsympow_rootno2(GEN E, long vN, long m, long bet)
1791 : {
1792 0 : long eps2 = (m + 1 - bet)>>1;
1793 0 : long eta = odd(vN) && m%8==3 ? -1 : 1;
1794 0 : long w2 = odd(eps2) ? ellrootno(E, gen_2): 1;
1795 0 : return eta == w2 ? 1 : -1;
1796 : }
1797 :
1798 : static GEN
1799 28 : ellsympow_goodred2(GEN E, GEN F, GEN p, long m, long vN, long *cnd, long *w)
1800 : {
1801 28 : long o = ellsympow_inertia2(F, vN);
1802 28 : long bet = ellsympow_betam(o, m);
1803 28 : *cnd = m + 1 - bet + ellsympow_deltam2(o, m, vN);
1804 28 : *w = odd(m) ? ellsympow_rootno2(E, vN, m, bet): 1;
1805 28 : if (o==1 || o==2)
1806 0 : return ellsympow_abelian(p, ellap(F, p), m, o);
1807 28 : if (o==4 && ellsympow_isabelian2(F))
1808 0 : return ellsympow_abelian(p, p, m, o);
1809 : else
1810 28 : return ellsympow_nonabelian(p, m, bet);
1811 : }
1812 :
1813 : static GEN
1814 189 : ellminimaldotwist(GEN E, GEN *pD)
1815 : {
1816 189 : GEN D = ellminimaltwistcond(E), Et = elltwist(E, D), Etmin;
1817 189 : if (pD) *pD = D;
1818 189 : Etmin = ellminimalmodel(Et, NULL);
1819 189 : obj_free(Et); return Etmin;
1820 : }
1821 :
1822 : /* Based on
1823 : Symmetric powers of elliptic curve L-functions,
1824 : Phil Martin and Mark Watkins, ANTS VII
1825 : <http://magma.maths.usyd.edu.au/users/watkins/papers/antsVII.pdf>
1826 : with thanks to Mark Watkins. BA20180402
1827 : */
1828 : static GEN
1829 140 : lfunellsympow(GEN e, ulong m)
1830 : {
1831 140 : pari_sp av = avma;
1832 : GEN B, N, Nfa, pr, ex, ld, bad, ejd, et, pole;
1833 140 : long i, l, mero, w = (m&7)==1 || (m&7)==3 ? -1: 1;
1834 140 : checkell_Q(e);
1835 140 : e = ellminimalmodel(e, NULL);
1836 140 : ejd = Q_denom(ell_get_j(e));
1837 140 : mero = m==0 || (m%4==0 && ellQ_get_CM(e)<0);
1838 140 : ellQ_get_Nfa(e, &N, &Nfa);
1839 140 : pr = gel(Nfa,1);
1840 140 : ex = gel(Nfa,2); l = lg(pr);
1841 140 : if (ugcd(umodiu(N,6), 6) == 1)
1842 21 : et = NULL;
1843 : else
1844 119 : et = ellminimaldotwist(e, NULL);
1845 140 : B = gen_1;
1846 140 : bad = cgetg(l, t_VEC);
1847 336 : for (i=1; i<l; i++)
1848 : {
1849 196 : long vN = itos(gel(ex,i));
1850 196 : GEN p = gel(pr,i), eul;
1851 : long cnd, wp;
1852 196 : if (dvdii(ejd, p))
1853 98 : eul = ellsympow_multred(e, p, m, vN, &cnd, &wp);
1854 98 : else if (equaliu(p, 2))
1855 28 : eul = ellsympow_goodred2(e, et, p, m, vN, &cnd, &wp);
1856 70 : else if (equaliu(p, 3))
1857 70 : eul = ellsympow_goodred3(e, et, p, m, vN, &cnd, &wp);
1858 : else
1859 0 : eul = ellsympow_goodred(e, p, m, &cnd, &wp);
1860 196 : gel(bad, i) = mkvec2(p, ginv(eul));
1861 196 : B = mulii(B, powiu(p,cnd));
1862 196 : w *= wp;
1863 : }
1864 140 : pole = mero ? mkvec(mkvec2(stoi(1+(m>>1)),gen_0)): NULL;
1865 280 : ld = mkvecn(mero? 7: 6, tag(mkvec2(mkvec2(e,utoi(m)),bad), t_LFUN_SYMPOW_ELL),
1866 140 : gen_0, ellsympow_gamma(m), stoi(m+1), B, stoi(w), pole);
1867 140 : if (et) obj_free(et);
1868 140 : return gerepilecopy(av, ld);
1869 : }
1870 :
1871 : GEN
1872 70 : lfunsympow(GEN ldata, ulong m)
1873 : {
1874 70 : ldata = lfunmisc_to_ldata_shallow(ldata);
1875 70 : if (ldata_get_type(ldata) != t_LFUN_ELL)
1876 0 : pari_err_IMPL("lfunsympow");
1877 70 : return lfunellsympow(gel(ldata_get_an(ldata), 2), m);
1878 : }
1879 :
1880 : static GEN
1881 28 : lfunmfspec_i(GEN lmisc, long bit)
1882 : {
1883 : GEN linit, ldataf, v, ve, vo, om, op, B, dom;
1884 : long k, k2, j;
1885 :
1886 28 : ldataf = lfunmisc_to_ldata_shallow(lmisc);
1887 28 : if (!gequal(ldata_get_gammavec(ldataf), mkvec2(gen_0,gen_1)))
1888 0 : pari_err_TYPE("lfunmfspec", lmisc);
1889 28 : k = gtos(ldata_get_k(ldataf));
1890 28 : if (k == 1) return mkvec2(cgetg(1, t_VEC), gen_1);
1891 21 : dom = mkvec3(dbltor(k/2.), dbltor((k-2)/2.), gen_0);
1892 21 : if (is_linit(lmisc) && linit_get_type(lmisc) == t_LDESC_INIT
1893 0 : && sdomain_isincl((double)k, dom, lfun_get_dom(linit_get_tech(lmisc))))
1894 0 : linit = lmisc;
1895 : else
1896 21 : linit = lfuninit(ldataf, dom, 0, bit);
1897 21 : B = int2n(bit/4);
1898 21 : v = cgetg(k, t_VEC);
1899 168 : for (j = 1; j < k; j++) gel(v,j) = lfunlambda(linit, utoi(j), bit);
1900 21 : om = gel(v,1);
1901 21 : if (odd(k)) return mkvec2(bestappr(gdiv(v, om), B), om);
1902 :
1903 7 : k2 = k/2;
1904 7 : ve = cgetg(k2, t_VEC);
1905 7 : vo = cgetg(k2+1, t_VEC);
1906 7 : gel(vo,1) = om;
1907 42 : for (j = 1; j < k2; j++)
1908 : {
1909 35 : gel(ve,j) = gel(v,2*j);
1910 35 : gel(vo,j+1) = gel(v,2*j+1);
1911 : }
1912 7 : if (k2 == 1) { om = gen_1; op = gel(v,1); }
1913 7 : else { om = gel(v,2); op = gel(v,3); }
1914 7 : if (maxss(gexpo(imag_i(om)), gexpo(imag_i(op))) > -bit/2)
1915 0 : pari_err_TYPE("lfunmfspec", lmisc);
1916 7 : ve = gdiv(ve, om);
1917 7 : vo = gdiv(vo, op);
1918 7 : return mkvec4(bestappr(ve,B), bestappr(vo,B), om, op);
1919 : }
1920 : GEN
1921 28 : lfunmfspec(GEN lmisc, long bit)
1922 : {
1923 28 : pari_sp av = avma;
1924 28 : return gerepilecopy(av, lfunmfspec_i(lmisc, bit));
1925 : }
1926 :
1927 : static long
1928 28 : ellsymsq_bad2(GEN c4, GEN c6, long e)
1929 : {
1930 28 : switch (e)
1931 : {
1932 14 : case 2: return 1;
1933 7 : case 3: return 0;
1934 7 : case 5: return 0;
1935 0 : case 7: return 0;
1936 0 : case 8:
1937 0 : if (!umodi2n(c6,9)) return 0;
1938 0 : return umodi2n(c4,7)==32 ? 1 : -1;
1939 0 : default: return 0;
1940 : }
1941 : }
1942 : static long
1943 14 : ellsymsq_bad3(GEN c4, GEN c6, long e)
1944 : {
1945 : long c6_243, c4_81;
1946 14 : switch (e)
1947 : {
1948 0 : case 2: return 1;
1949 14 : case 3: return 0;
1950 0 : case 5: return 0;
1951 0 : case 4:
1952 0 : c4_81 = umodiu(c4,81);
1953 0 : if (c4_81 == 27) return -1;
1954 0 : if (c4_81%27 != 9) return 1;
1955 0 : c6_243 = umodiu(c6,243);
1956 0 : return (c6_243==108 || c6_243==135)? -1: 1;
1957 0 : default: return 0;
1958 : }
1959 : }
1960 : static int
1961 0 : c4c6_testp(GEN c4, GEN c6, GEN p)
1962 0 : { GEN p2 = sqri(p); return (dvdii(c6,p2) && !dvdii(c4,p2)); }
1963 : /* assume e = v_p(N) >= 2 */
1964 : static long
1965 42 : ellsymsq_badp(GEN c4, GEN c6, GEN p, long e)
1966 : {
1967 42 : if (absequaliu(p, 2)) return ellsymsq_bad2(c4, c6, e);
1968 14 : if (absequaliu(p, 3)) return ellsymsq_bad3(c4, c6, e);
1969 0 : switch(umodiu(p, 12UL))
1970 : {
1971 0 : case 1: return -1;
1972 0 : case 5: return c4c6_testp(c4,c6,p)? -1: 1;
1973 0 : case 7: return c4c6_testp(c4,c6,p)? 1:-1;
1974 0 : default:return 1; /* p%12 = 11 */
1975 : }
1976 : }
1977 : static GEN
1978 70 : lfunellsymsqmintwist(GEN e)
1979 : {
1980 70 : pari_sp av = avma;
1981 : GEN N, Nfa, P, E, V, c4, c6, ld;
1982 : long i, l, k;
1983 70 : checkell_Q(e);
1984 70 : e = ellminimalmodel(e, NULL);
1985 70 : ellQ_get_Nfa(e, &N, &Nfa);
1986 70 : c4 = ell_get_c4(e);
1987 70 : c6 = ell_get_c6(e);
1988 70 : P = gel(Nfa,1); l = lg(P);
1989 70 : E = gel(Nfa,2);
1990 70 : V = cgetg(l, t_VEC);
1991 196 : for (i=k=1; i<l; i++)
1992 : {
1993 126 : GEN p = gel(P,i);
1994 126 : long a, e = itos(gel(E,i));
1995 126 : if (e == 1) continue;
1996 42 : a = ellsymsq_badp(c4, c6, p, e);
1997 42 : gel(V,k++) = mkvec2(p, stoi(a));
1998 : }
1999 70 : setlg(V, k);
2000 70 : ld = lfunellsympow(e, 2);
2001 70 : return gerepilecopy(av, mkvec2(ld, V));
2002 : }
2003 :
2004 : static GEN
2005 70 : mfpeters(GEN ldata2, GEN fudge, GEN N, long k, long bitprec)
2006 : {
2007 70 : GEN t, L = real_i(lfun(ldata2, stoi(k), bitprec));
2008 70 : long prec = nbits2prec(bitprec);
2009 70 : t = powrs(mppi(prec), k+1); shiftr_inplace(t, 2*k-1); /* Pi/2 * (4Pi)^k */
2010 70 : return gmul(gdiv(gmul(mulii(N,mpfact(k-1)), fudge), t), L);
2011 : }
2012 :
2013 : /* Assume E to be twist-minimal */
2014 : static GEN
2015 70 : lfunellmfpetersmintwist(GEN E, long bitprec)
2016 : {
2017 70 : pari_sp av = avma;
2018 70 : GEN symsq, veceuler, N = ellQ_get_N(E), fudge = gen_1;
2019 70 : long j, k = 2;
2020 70 : symsq = lfunellsymsqmintwist(E);
2021 70 : veceuler = gel(symsq,2);
2022 112 : for (j = 1; j < lg(veceuler); j++)
2023 : {
2024 42 : GEN v = gel(veceuler,j), p = gel(v,1), q = powis(p,1-k);
2025 42 : long s = signe(gel(v,2));
2026 42 : if (s) fudge = gmul(fudge, s==1 ? gaddsg(1, q): gsubsg(1, q));
2027 : }
2028 70 : return gerepileupto(av, mfpeters(gel(symsq,1),fudge,N,k,bitprec));
2029 : }
2030 :
2031 : /* From Christophe Delaunay, http://delaunay.perso.math.cnrs.fr/these.pdf */
2032 : static GEN
2033 70 : elldiscfix(GEN E, GEN Et, GEN D)
2034 : {
2035 70 : GEN N = ellQ_get_N(E), Nt = ellQ_get_N(Et);
2036 70 : GEN P = gel(absZ_factor(D), 1);
2037 70 : GEN f = gen_1;
2038 70 : long i, l = lg(P);
2039 133 : for (i=1; i < l; i++)
2040 : {
2041 63 : GEN r, p = gel(P,i);
2042 63 : long v = Z_pval(N, p), vt = Z_pval(Nt, p);
2043 63 : if (v <= vt) continue;
2044 : /* v > vt */
2045 49 : if (absequaliu(p, 2))
2046 : {
2047 28 : if (vt == 0 && v >= 4)
2048 0 : r = shifti(subsi(9, sqri(ellap(Et, p))), v-3); /* 9=(2+1)^2 */
2049 28 : else if (vt == 1)
2050 7 : r = gmul2n(utoipos(3), v-3); /* not in Z if v=2 */
2051 21 : else if (vt >= 2)
2052 21 : r = int2n(v-vt);
2053 : else
2054 0 : r = gen_1; /* vt = 0, 1 <= v <= 3 */
2055 : }
2056 21 : else if (vt >= 1)
2057 14 : r = gdiv(subiu(sqri(p), 1), p);
2058 : else
2059 7 : r = gdiv(mulii(subiu(p, 1), subii(sqri(addiu(p, 1)), sqri(ellap(Et, p)))), p);
2060 49 : f = gmul(f, r);
2061 : }
2062 70 : return f;
2063 : }
2064 :
2065 : GEN
2066 70 : lfunellmfpeters(GEN E, long bitprec)
2067 : {
2068 70 : pari_sp ltop = avma;
2069 70 : GEN D, Et = ellminimaldotwist(E, &D);
2070 70 : GEN nor = lfunellmfpetersmintwist(Et, bitprec);
2071 70 : GEN nor2 = gmul(nor, elldiscfix(E, Et, D));
2072 70 : obj_free(Et); return gerepileupto(ltop, nor2);
2073 : }
2074 :
2075 : /*************************************************************/
2076 : /* Genus 2 curves */
2077 : /*************************************************************/
2078 :
2079 : static void
2080 233611 : Flv_diffnext(GEN d, ulong p)
2081 : {
2082 233611 : long j, n = lg(d)-1;
2083 1635277 : for(j = n; j>=2; j--)
2084 1401666 : uel(d,j) = Fl_add(uel(d,j), uel(d,j-1), p);
2085 233611 : }
2086 :
2087 : static GEN
2088 1995 : Flx_difftable(GEN P, ulong p)
2089 : {
2090 1995 : long i, n = degpol(P);
2091 1995 : GEN V = cgetg(n+2, t_VECSMALL);
2092 1995 : uel(V, n+1) = Flx_constant(P);
2093 13965 : for(i = n; i >= 1; i--)
2094 : {
2095 11970 : P = Flx_diff1(P, p);
2096 11970 : uel(V, i) = Flx_constant(P);
2097 : }
2098 1995 : return V;
2099 : }
2100 :
2101 : static long
2102 1995 : Flx_genus2trace_naive(GEN H, ulong p)
2103 : {
2104 1995 : pari_sp av = avma;
2105 : ulong i, j;
2106 1995 : long a, n = degpol(H);
2107 1995 : GEN k = const_vecsmall(p, -1), d;
2108 1995 : k[1] = 0;
2109 117803 : for (i=1, j=1; i < p; i += 2, j = Fl_add(j, i, p))
2110 115808 : k[j+1] = 1;
2111 1995 : a = n == 5 ? 0: k[1+Flx_lead(H)];
2112 1995 : d = Flx_difftable(H, p);
2113 235606 : for (i=0; i < p; i++)
2114 : {
2115 233611 : a += k[1+uel(d,n+1)];
2116 233611 : Flv_diffnext(d, p);
2117 : }
2118 1995 : set_avma(av);
2119 1995 : return a;
2120 : }
2121 :
2122 : static GEN
2123 2156 : dirgenus2(GEN Q, GEN p, long n)
2124 : {
2125 2156 : pari_sp av = avma;
2126 : GEN f;
2127 2156 : if (n > 2)
2128 161 : f = RgX_recip(hyperellcharpoly(gmul(Q,gmodulo(gen_1, p))));
2129 : else
2130 : {
2131 1995 : ulong pp = itou(p);
2132 1995 : GEN Qp = ZX_to_Flx(Q, pp);
2133 1995 : long t = Flx_genus2trace_naive(Qp, pp);
2134 1995 : f = deg1pol_shallow(stoi(t), gen_1, 0);
2135 : }
2136 2156 : return gerepileupto(av, RgXn_inv_i(f, n));
2137 : }
2138 :
2139 : GEN
2140 875 : dirgenus2_worker(GEN P, ulong X, GEN Q)
2141 : {
2142 875 : pari_sp av = avma;
2143 875 : long i, l = lg(P);
2144 875 : GEN V = cgetg(l, t_VEC);
2145 3031 : for(i = 1; i < l; i++)
2146 : {
2147 2156 : ulong p = uel(P,i);
2148 2156 : long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */
2149 2156 : gel(V,i) = dirgenus2(Q, utoi(uel(P,i)), d);
2150 : }
2151 875 : return gerepilecopy(av, mkvec2(P,V));
2152 : }
2153 :
2154 : static GEN
2155 196 : vecan_genus2(GEN an, long L)
2156 : {
2157 196 : GEN Q = gel(an,1), bad = gel(an, 2);
2158 196 : GEN worker = snm_closure(is_entry("_dirgenus2_worker"), mkvec(Q));
2159 196 : return pardireuler(worker, gen_2, stoi(L), NULL, bad);
2160 : }
2161 :
2162 : static GEN
2163 0 : eulerf_genus2(GEN an, GEN p)
2164 : {
2165 0 : GEN Q = gel(an,1), bad = gel(an, 2);
2166 0 : GEN f = eulerf_bad(bad, p);
2167 0 : if (f) return f;
2168 0 : f = RgX_recip(hyperellcharpoly(gmul(Q,gmodulo(gen_1, p))));
2169 0 : return mkrfrac(gen_1,f);
2170 : }
2171 :
2172 : static GEN
2173 49 : genus2_redmodel(GEN P, GEN p)
2174 : {
2175 49 : GEN M = FpX_factor(P, p);
2176 49 : GEN F = gel(M,1), E = gel(M,2);
2177 49 : long i, k, r = lg(F);
2178 49 : GEN U = scalarpol(leading_coeff(P), varn(P));
2179 49 : GEN G = cgetg(r, t_COL);
2180 161 : for (i=1, k=0; i<r; i++)
2181 : {
2182 112 : if (E[i]>1)
2183 56 : gel(G,++k) = gel(F,i);
2184 112 : if (odd(E[i]))
2185 77 : U = FpX_mul(U, gel(F,i), p);
2186 : }
2187 49 : setlg(G,++k);
2188 49 : return mkvec2(G,U);
2189 : }
2190 :
2191 : static GEN
2192 308 : oneminusxd(long d)
2193 : {
2194 308 : return gsub(gen_1, pol_xn(d, 0));
2195 : }
2196 :
2197 : static GEN
2198 21 : ellfromeqncharpoly(GEN P, GEN Q, GEN p)
2199 : {
2200 : long v;
2201 : GEN E, F, t, y;
2202 21 : v = fetch_var();
2203 21 : y = pol_x(v);
2204 21 : F = gsub(gadd(ZX_sqr(y), gmul(y, Q)), P);
2205 21 : E = ellinit(ellfromeqn(F), p, DEFAULTPREC);
2206 21 : delete_var();
2207 21 : t = ellap(E, p);
2208 21 : obj_free(E);
2209 21 : return mkpoln(3, gen_1, negi(t), p);
2210 : }
2211 :
2212 : static GEN
2213 49 : genus2_eulerfact(GEN P, GEN p)
2214 : {
2215 49 : GEN Pp = FpX_red(P, p);
2216 49 : GEN GU = genus2_redmodel(Pp, p);
2217 49 : long d = 6-degpol(Pp), v = d/2, w = odd(d);
2218 : GEN abe, tor;
2219 49 : GEN ki, kp = pol_1(0), kq = pol_1(0);
2220 49 : GEN F = gel(GU,1), Q = gel(GU,2);
2221 49 : long dQ = degpol(Q), lF = lg(F)-1;
2222 :
2223 0 : abe = dQ >= 5 ? RgX_recip(hyperellcharpoly(gmul(Q,gmodulo(gen_1,p))))
2224 98 : : dQ >= 3 ? RgX_recip(ellfromeqncharpoly(Q,gen_0,p))
2225 49 : : pol_1(0);
2226 42 : ki = dQ != 0 ? oneminusxd(1)
2227 56 : : Fp_issquare(gel(Q,2),p) ? ZX_sqr(oneminusxd(1))
2228 7 : : oneminusxd(2);
2229 49 : if (lF)
2230 : {
2231 : long i;
2232 98 : for(i=1; i <= lF; i++)
2233 : {
2234 56 : GEN Fi = gel(F, i);
2235 56 : long d = degpol(Fi);
2236 56 : GEN e = FpX_rem(Q, Fi, p);
2237 91 : GEN kqf = lgpol(e)==0 ? oneminusxd(d):
2238 70 : FpXQ_issquare(e, Fi, p) ? ZX_sqr(oneminusxd(d))
2239 35 : : oneminusxd(2*d);
2240 56 : kp = gmul(kp, oneminusxd(d));
2241 56 : kq = gmul(kq, kqf);
2242 : }
2243 : }
2244 49 : if (v)
2245 : {
2246 7 : GEN kqoo = w==1 ? oneminusxd(1):
2247 0 : Fp_issquare(leading_coeff(Q), p)? ZX_sqr(oneminusxd(1))
2248 0 : : oneminusxd(2);
2249 7 : kp = gmul(kp, oneminusxd(1));
2250 7 : kq = gmul(kq, kqoo);
2251 : }
2252 49 : tor = RgX_div(ZX_mul(oneminusxd(1), kq), ZX_mul(ki, kp));
2253 49 : return ginv( ZX_mul(abe, tor) );
2254 : }
2255 :
2256 : static GEN
2257 28 : F2x_genus2_find_trans(GEN P, GEN Q, GEN F)
2258 : {
2259 28 : pari_sp av = avma;
2260 28 : long i, d = F2x_degree(F), v = P[1];
2261 : GEN M, C, V;
2262 28 : M = cgetg(d+1, t_MAT);
2263 84 : for (i=1; i<=d; i++)
2264 : {
2265 56 : GEN Mi = F2x_rem(F2x_add(F2x_shift(Q,i-1), monomial_F2x(2*i-2,v)), F);
2266 56 : gel(M,i) = F2x_to_F2v(Mi, d);
2267 : }
2268 28 : C = F2x_to_F2v(F2x_rem(P, F), d);
2269 28 : V = F2m_F2c_invimage(M, C);
2270 28 : return gerepileuptoleaf(av, F2v_to_F2x(V, v));
2271 : }
2272 :
2273 : static GEN
2274 35 : F2x_genus2_trans(GEN P, GEN Q, GEN H)
2275 : {
2276 35 : return F2x_add(P,F2x_add(F2x_mul(H,Q), F2x_sqr(H)));
2277 : }
2278 :
2279 : static GEN
2280 42 : F2x_genus_redoo(GEN P, GEN Q, long k)
2281 : {
2282 42 : if (F2x_degree(P)==2*k)
2283 : {
2284 14 : long c = F2x_coeff(P,2*k-1), dQ = F2x_degree(Q);
2285 14 : if ((dQ==k-1 && c==1) || (dQ<k-1 && c==0))
2286 7 : return F2x_genus2_trans(P, Q, monomial_F2x(k, P[1]));
2287 : }
2288 35 : return P;
2289 : }
2290 :
2291 : static GEN
2292 35 : F2x_pseudodisc(GEN P, GEN Q)
2293 : {
2294 35 : GEN dP = F2x_deriv(P), dQ = F2x_deriv(Q);
2295 35 : return F2x_gcd(Q, F2x_add(F2x_mul(P, F2x_sqr(dQ)), F2x_sqr(dP)));
2296 : }
2297 :
2298 : static GEN
2299 14 : F2x_genus_red(GEN P, GEN Q)
2300 : {
2301 : long dP, dQ;
2302 : GEN F, FF;
2303 14 : P = F2x_genus_redoo(P, Q, 3);
2304 14 : P = F2x_genus_redoo(P, Q, 2);
2305 14 : P = F2x_genus_redoo(P, Q, 1);
2306 14 : dP = F2x_degree(P);
2307 14 : dQ = F2x_degree(Q);
2308 14 : FF = F = F2x_pseudodisc(P,Q);
2309 35 : while(F2x_degree(F)>0)
2310 : {
2311 21 : GEN M = gel(F2x_factor(F),1);
2312 21 : long i, l = lg(M);
2313 49 : for(i=1; i<l; i++)
2314 : {
2315 28 : GEN R = F2x_sqr(gel(M,i));
2316 28 : GEN H = F2x_genus2_find_trans(P, Q, R);
2317 28 : P = F2x_div(F2x_genus2_trans(P, Q, H), R);
2318 28 : Q = F2x_div(Q, gel(M,i));
2319 : }
2320 21 : F = F2x_pseudodisc(P, Q);
2321 : }
2322 14 : return mkvec4(P,Q,FF,mkvecsmall2(dP,dQ));
2323 : }
2324 :
2325 : /* Number of solutions of x^2+b*x+c */
2326 : static long
2327 21 : F2xqX_quad_nbroots(GEN b, GEN c, GEN T)
2328 : {
2329 21 : if (lgpol(b) > 0)
2330 : {
2331 14 : GEN d = F2xq_div(c, F2xq_sqr(b, T), T);
2332 14 : return F2xq_trace(d, T)? 0: 2;
2333 : }
2334 : else
2335 7 : return 1;
2336 : }
2337 :
2338 : static GEN
2339 14 : genus2_eulerfact2(GEN PQ)
2340 : {
2341 14 : GEN V = F2x_genus_red(ZX_to_F2x(gel(PQ, 1)), ZX_to_F2x(gel(PQ, 2)));
2342 14 : GEN P = gel(V, 1), Q = gel(V, 2);
2343 14 : GEN F = gel(V, 3), v = gel(V, 4);
2344 : GEN abe, tor;
2345 14 : GEN ki, kp = pol_1(0), kq = pol_1(0);
2346 14 : long dP = F2x_degree(P), dQ = F2x_degree(Q), d = maxss(dP, 2*dQ);
2347 14 : if (!lgpol(F)) return pol_1(0);
2348 21 : ki = dQ!=0 || dP>0 ? oneminusxd(1):
2349 7 : dP==-1 ? ZX_sqr(oneminusxd(1)): oneminusxd(2);
2350 28 : abe = d>=5? RgX_recip(hyperellcharpoly(gmul(PQ,gmodulss(1,2)))):
2351 14 : d>=3? RgX_recip(ellfromeqncharpoly(F2x_to_ZX(P), F2x_to_ZX(Q), gen_2)):
2352 14 : pol_1(0);
2353 14 : if (lgpol(F))
2354 : {
2355 14 : GEN M = gel(F2x_factor(F), 1);
2356 14 : long i, lF = lg(M)-1;
2357 35 : for(i=1; i <= lF; i++)
2358 : {
2359 21 : GEN Fi = gel(M, i);
2360 21 : long d = F2x_degree(Fi);
2361 21 : long nb = F2xqX_quad_nbroots(F2x_rem(Q, Fi), F2x_rem(P, Fi), Fi);
2362 35 : GEN kqf = nb==1 ? oneminusxd(d):
2363 0 : nb==2 ? ZX_sqr(oneminusxd(d))
2364 14 : : oneminusxd(2*d);
2365 21 : kp = gmul(kp, oneminusxd(d));
2366 21 : kq = gmul(kq, kqf);
2367 : }
2368 : }
2369 14 : if (maxss(v[1],2*v[2])<5)
2370 : {
2371 14 : GEN kqoo = v[1]>2*v[2] ? oneminusxd(1):
2372 0 : v[1]<2*v[2] ? ZX_sqr(oneminusxd(1))
2373 7 : : oneminusxd(2);
2374 7 : kp = gmul(kp, oneminusxd(1));
2375 7 : kq = gmul(kq, kqoo);
2376 : }
2377 14 : tor = RgX_div(ZX_mul(oneminusxd(1),kq), ZX_mul(ki, kp));
2378 14 : return ginv( ZX_mul(abe, tor) );
2379 : }
2380 :
2381 : GEN
2382 35 : lfungenus2(GEN G)
2383 : {
2384 35 : pari_sp ltop = avma;
2385 : GEN Ldata;
2386 35 : GEN gr = genus2red(G, NULL);
2387 35 : GEN N = gel(gr, 1), M = gel(gr, 2), PQ = gel(gr, 3), L = gel(gr, 4);
2388 35 : GEN e, F = gadd(gsqr(gel(PQ, 2)), gmul2n(gel(PQ, 1), 2));
2389 35 : long i, lL = lg(L), ram2;
2390 35 : ram2 = absequaliu(gmael(M,1,1),2);
2391 35 : if (ram2 && equalis(gmael(M,2,1),-1))
2392 14 : pari_warn(warner,"unknown valuation of conductor at 2");
2393 35 : e = cgetg(lL+(ram2?0:1), t_VEC);
2394 56 : gel(e,1) = mkvec2(gen_2, ram2 ? genus2_eulerfact2(PQ)
2395 21 : : ginv( RgX_recip(hyperellcharpoly(gmul(PQ,gmodulss(1,2))))) );
2396 84 : for(i = ram2? 2: 1; i < lL; i++)
2397 : {
2398 49 : GEN Li = gel(L, i);
2399 49 : GEN p = gel(Li, 1);
2400 49 : gel(e, ram2 ? i: i+1) = mkvec2(p, genus2_eulerfact(F,p));
2401 : }
2402 35 : Ldata = mkvecn(6, tag(mkvec2(F,e), t_LFUN_GENUS2),
2403 : gen_0, mkvec4(gen_0, gen_0, gen_1, gen_1), gen_2, N, gen_0);
2404 35 : return gerepilecopy(ltop, Ldata);
2405 : }
2406 :
2407 : /*************************************************************/
2408 : /* ETA QUOTIENTS */
2409 : /* An eta quotient is a matrix with 2 columns [m, r_m] with */
2410 : /* m >= 1 representing f(\tau)=\prod_m\eta(m\tau)^{r_m}. */
2411 : /*************************************************************/
2412 :
2413 : /* eta(x^v) + O(x^L) */
2414 : GEN
2415 1222 : eta_ZXn(long v, long L)
2416 : {
2417 1222 : long n, k = 0, v2 = 2*v, bn = v, cn = 0;
2418 : GEN P;
2419 1222 : if (!L) return zeropol(0);
2420 1222 : P = cgetg(L+2,t_POL); P[1] = evalsigne(1);
2421 72543 : for(n = 0; n < L; n++) gel(P,n+2) = gen_0;
2422 1222 : for(n = 0;; n++, bn += v2, cn += v)
2423 3000 : { /* k = v * (3*n-1) * n / 2; bn = v * (2*n+1); cn = v * n */
2424 : long k2;
2425 4222 : gel(P, k+2) = odd(n)? gen_m1: gen_1;
2426 4222 : k2 = k+cn; if (k2 >= L) break;
2427 3770 : k = k2;
2428 : /* k = v * (3*n+1) * n / 2 */;
2429 3770 : gel(P, k+2) = odd(n)? gen_m1: gen_1;
2430 3770 : k2 = k+bn; if (k2 >= L) break;
2431 3000 : k = k2;
2432 : }
2433 1222 : setlg(P, k+3); return P;
2434 : }
2435 : GEN
2436 322 : eta_product_ZXn(GEN eta, long L)
2437 : {
2438 322 : pari_sp av = avma;
2439 322 : GEN P = NULL, D = gel(eta,1), R = gel(eta,2);
2440 322 : long i, l = lg(D);
2441 1148 : for (i = 1; i < l; ++i)
2442 : {
2443 826 : GEN Q = eta_ZXn(D[i], L);
2444 826 : long r = R[i];
2445 826 : if (r < 0) { Q = RgXn_inv_i(Q, L); r = -r; }
2446 826 : if (r != 1) Q = RgXn_powu_i(Q, r, L);
2447 826 : P = P? ZXn_mul(P, Q, L): Q;
2448 826 : if (gc_needed(av,1) && i > 1)
2449 : {
2450 0 : if (DEBUGMEM>1) pari_warn(warnmem,"eta_product_ZXn");
2451 0 : P = gerepilecopy(av, P);
2452 : }
2453 : }
2454 322 : return P;
2455 : }
2456 : static GEN
2457 147 : vecan_eta(GEN an, long L)
2458 : {
2459 147 : long v = itos(gel(an, 3));
2460 : GEN t;
2461 147 : if (v > L) return zerovec(L);
2462 140 : t = eta_product_ZXn(an, L - v);
2463 140 : if (v) t = RgX_shift_shallow(t, v);
2464 140 : return RgX_to_RgV(t, L);
2465 : }
2466 : /* return 1 if cuspidal, 0 if holomorphic, -1 otherwise */
2467 : static int
2468 231 : etacuspidal(GEN N, GEN k, GEN B, GEN R, GEN NB)
2469 : {
2470 231 : long i, j, lD, l, cusp = 1;
2471 231 : pari_sp av = avma;
2472 : GEN D;
2473 231 : if (gsigne(k) < 0) return -1;
2474 224 : D = divisors(N); lD = lg(D); l = lg(B);
2475 1505 : for (i = 1; i < lD; i++)
2476 : {
2477 1281 : GEN t = gen_0, d = gel(D,i);
2478 : long s;
2479 3997 : for (j = 1; j < l; j++)
2480 2716 : t = addii(t, mulii(gel(NB,j), mulii(gel(R,j), sqri(gcdii(d, gel(B,j))))));
2481 1281 : s = signe(t);
2482 1281 : if (s < 0) return -1;
2483 1281 : if (!s) cusp = 0;
2484 : }
2485 224 : return gc_bool(av, cusp);
2486 : }
2487 : /* u | 24, level N = u*N0, N0 = lcm(B), NB[i] = N0/B[i] */
2488 : static int
2489 49 : etaselfdual(GEN B, GEN R, GEN NB, ulong u)
2490 : {
2491 49 : pari_sp av = avma;
2492 49 : long i, l = lg(B);
2493 161 : for (i = 1; i < l; i++)
2494 : {
2495 112 : long j = ZV_search(B, muliu(gel(NB,i), u)); /* search for N / B[i] */
2496 112 : set_avma(av); if (!j || !equalii(gel(R,i),gel(R,j))) return 0;
2497 : }
2498 49 : return 1;
2499 : }
2500 : /* return Nebentypus of eta quotient, k2 = 2*k integral */
2501 : static GEN
2502 203 : etachar(GEN B, GEN R, GEN k2)
2503 : {
2504 203 : long i, l = lg(B);
2505 203 : GEN P = gen_1;
2506 546 : for (i = 1; i < l; ++i) if (mpodd(gel(R,i))) P = mulii(P, gel(B,i));
2507 203 : switch(Mod4(k2))
2508 : {
2509 133 : case 0: break;
2510 42 : case 2: P = negi(P); break;
2511 28 : default: P = shifti(P, 1); break;
2512 : }
2513 203 : return coredisc(P);
2514 : }
2515 : /* Return 0 if not on gamma_0(N). Sets conductor, modular weight, character,
2516 : * canonical matrix, v_q(eta), sd = 1 iff self-dual, cusp = 1 iff cuspidal
2517 : * [0 if holomorphic at all cusps, else -1] */
2518 : long
2519 259 : etaquotype(GEN *peta, GEN *pN, GEN *pk, GEN *CHI, long *pv, long *sd,
2520 : long *cusp)
2521 : {
2522 259 : GEN B, R, S, T, N, NB, eta = *peta;
2523 : long l, i, u, S24;
2524 :
2525 259 : if (lg(eta) != 3) pari_err_TYPE("lfunetaquo", eta);
2526 259 : switch(typ(eta))
2527 : {
2528 77 : case t_VEC: eta = mkmat2(mkcol(gel(eta,1)), mkcol(gel(eta,2))); break;
2529 182 : case t_MAT: break;
2530 0 : default: pari_err_TYPE("lfunetaquo", eta);
2531 : }
2532 259 : if (!RgV_is_ZVpos(gel(eta,1)) || !RgV_is_ZV(gel(eta,2)))
2533 0 : pari_err_TYPE("lfunetaquo", eta);
2534 259 : *peta = eta = famat_reduce(eta);
2535 259 : B = gel(eta,1); l = lg(B); /* sorted in increasing order */
2536 259 : R = gel(eta,2);
2537 259 : N = ZV_lcm(B); NB = cgetg(l, t_VEC);
2538 721 : for (i = 1; i < l; i++) gel(NB,i) = diviiexact(N, gel(B,i));
2539 259 : S = gen_0; T = gen_0; u = 0;
2540 721 : for (i = 1; i < l; ++i)
2541 : {
2542 462 : GEN b = gel(B,i), r = gel(R,i);
2543 462 : S = addii(S, mulii(b, r));
2544 462 : T = addii(T, r);
2545 462 : u += umodiu(r,24) * umodiu(gel(NB,i), 24);
2546 : }
2547 259 : S = divis_rem(S, 24, &S24);
2548 259 : if (S24) return 0; /* nonintegral valuation at oo */
2549 252 : u = 24 / ugcd(24, u % 24);
2550 252 : *pN = muliu(N, u); /* level */
2551 252 : *pk = gmul2n(T,-1); /* weight */
2552 252 : *pv = itos(S); /* valuation */
2553 252 : if (cusp) *cusp = etacuspidal(*pN, *pk, B, R, NB);
2554 252 : if (sd) *sd = etaselfdual(B, R, NB, u);
2555 252 : if (CHI) *CHI = etachar(B, R, T);
2556 252 : return 1;
2557 : }
2558 :
2559 : GEN
2560 49 : lfunetaquo(GEN eta0)
2561 : {
2562 49 : pari_sp ltop = avma;
2563 49 : GEN Ldata, N, BR, k, eta = eta0;
2564 : long v, sd, cusp;
2565 49 : if (!etaquotype(&eta, &N, &k, NULL, &v, &sd, &cusp))
2566 0 : pari_err_TYPE("lfunetaquo", eta0);
2567 49 : if (!cusp) pari_err_IMPL("noncuspidal eta quotient");
2568 49 : if (!sd) pari_err_IMPL("non self-dual eta quotient");
2569 49 : if (typ(k) != t_INT) pari_err_TYPE("lfunetaquo [nonintegral weight]", eta0);
2570 49 : BR = mkvec3(ZV_to_zv(gel(eta,1)), ZV_to_zv(gel(eta,2)), stoi(v - 1));
2571 49 : Ldata = mkvecn(6, tag(BR,t_LFUN_ETA), gen_0, mkvec2(gen_0,gen_1), k,N, gen_1);
2572 49 : return gerepilecopy(ltop, Ldata);
2573 : }
2574 :
2575 : static GEN
2576 399 : vecan_qf(GEN Q, long L)
2577 : {
2578 399 : GEN v, w = qfrep0(Q, utoi(L), 1);
2579 : long i;
2580 399 : v = cgetg(L+1, t_VEC);
2581 26698 : for (i = 1; i <= L; i++) gel(v,i) = utoi(2 * w[i]);
2582 399 : return v;
2583 : }
2584 :
2585 : long
2586 336 : qfiseven(GEN M)
2587 : {
2588 336 : long i, l = lg(M);
2589 784 : for (i=1; i<l; i++)
2590 679 : if (mpodd(gcoeff(M,i,i))) return 0;
2591 105 : return 1;
2592 : }
2593 :
2594 : GEN
2595 91 : lfunqf(GEN M, long prec)
2596 : {
2597 91 : pari_sp ltop = avma;
2598 : long n;
2599 : GEN k, D, d, Mi, Ldata, poles, eno, dual;
2600 :
2601 91 : if (typ(M) != t_MAT) pari_err_TYPE("lfunqf", M);
2602 91 : if (!RgM_is_ZM(M)) pari_err_TYPE("lfunqf [not integral]", M);
2603 91 : n = lg(M)-1;
2604 91 : k = uutoQ(n,2);
2605 91 : M = Q_primpart(M);
2606 91 : Mi = ZM_inv(M, &d); /* d M^(-1) */
2607 91 : if (!qfiseven(M)) { M = gmul2n(M, 1); d = shifti(d,1); }
2608 91 : if (!qfiseven(Mi)){ Mi= gmul2n(Mi,1); d = shifti(d,1); }
2609 : /* det(Mi) = d^n/det(M), D^2 = det(Mi)/det(M) */
2610 91 : D = gdiv(gpow(d,k,prec), ZM_det(M));
2611 91 : if (!issquareall(D, &eno)) eno = gsqrt(D, prec);
2612 91 : dual = gequal1(D) ? gen_0: tag(Mi, t_LFUN_QF);
2613 91 : poles = mkcol2(mkvec2(k, simple_pole(gmul2n(eno,1))),
2614 : mkvec2(gen_0, simple_pole(gen_m2)));
2615 91 : Ldata = mkvecn(7, tag(M, t_LFUN_QF), dual,
2616 : mkvec2(gen_0, gen_1), k, d, eno, poles);
2617 91 : return gerepilecopy(ltop, Ldata);
2618 : }
2619 :
2620 : /********************************************************************/
2621 : /** Artin L function, based on a GP script by Charlotte Euvrard **/
2622 : /********************************************************************/
2623 :
2624 : static GEN
2625 119 : artin_charfromgens(GEN G, GEN M)
2626 : {
2627 119 : GEN R, V, ord = gal_get_orders(G), grp = gal_get_group(G);
2628 119 : long i, j, k, n = lg(ord)-1, m = lg(grp)-1;
2629 :
2630 119 : if (lg(M)-1 != n) pari_err_DIM("lfunartin");
2631 119 : R = cgetg(m+1, t_VEC);
2632 119 : gel(R, 1) = matid(lg(gel(M, 1))-1);
2633 357 : for (i = 1, k = 1; i <= n; ++i)
2634 : {
2635 238 : long c = k*(ord[i] - 1);
2636 238 : gel(R, ++k) = gel(M, i);
2637 1043 : for (j = 2; j <= c; ++j) gel(R, ++k) = gmul(gel(R,j), gel(M,i));
2638 : }
2639 119 : V = cgetg(m+1, t_VEC);
2640 1281 : for (i = 1; i <= m; i++) gel(V, gel(grp,i)[1]) = gtrace(gel(R,i));
2641 119 : return V;
2642 : }
2643 :
2644 : /* TODO move somewhere else? */
2645 : GEN
2646 280 : galois_get_conj(GEN G)
2647 : {
2648 280 : GEN grp = gal_get_group(G);
2649 280 : long i, k, r = lg(grp)-1;
2650 280 : GEN b = zero_F2v(r);
2651 959 : for (k = 2; k <= r; ++k)
2652 : {
2653 959 : GEN g = gel(grp,k);
2654 959 : if (!F2v_coeff(b,g[1]) && g[g[1]]==1)
2655 : {
2656 392 : pari_sp av = avma;
2657 392 : GEN F = galoisfixedfield(G, g, 1, -1);
2658 392 : if (ZX_sturmpart(F, NULL) > 0) { set_avma(av); return g; }
2659 1456 : for (i = 1; i<=r; i++)
2660 : {
2661 1344 : GEN h = gel(grp, i);
2662 1344 : long t = h[1];
2663 5264 : while (h[t]!=1) t = h[t];
2664 1344 : F2v_set(b, h[g[t]]);
2665 : }
2666 112 : set_avma(av);
2667 : }
2668 : }
2669 0 : pari_err_BUG("galois_get_conj");
2670 : return NULL;/*LCOV_EXCL_LINE*/
2671 : }
2672 :
2673 7700 : static GEN cyclotoi(GEN v) { return simplify_shallow(lift_shallow(v)); }
2674 2891 : static long cyclotos(GEN v) { return gtos(cyclotoi(v)); }
2675 2821 : static long char_dim(GEN ch) { return cyclotos(gel(ch,1)); }
2676 :
2677 : static GEN
2678 1379 : artin_gamma(GEN N, GEN G, GEN ch)
2679 : {
2680 1379 : long a, t, d = char_dim(ch);
2681 1379 : if (nf_get_r2(N) == 0) return vec01(d, 0);
2682 70 : a = galois_get_conj(G)[1];
2683 70 : t = cyclotos(gel(ch,a));
2684 70 : return vec01((d+t) / 2, (d-t) / 2);
2685 : }
2686 :
2687 : static long
2688 3213 : artin_dim(GEN ind, GEN ch)
2689 : {
2690 3213 : long n = lg(ch)-1;
2691 3213 : GEN elts = group_elts(ind, n);
2692 3213 : long i, d = lg(elts)-1;
2693 3213 : GEN s = gen_0;
2694 18123 : for(i=1; i<=d; i++)
2695 14910 : s = gadd(s, gel(ch, gel(elts,i)[1]));
2696 3213 : return gtos(gdivgu(cyclotoi(s), d));
2697 : }
2698 :
2699 : static GEN
2700 623 : artin_ind(GEN elts, GEN ch, GEN p)
2701 : {
2702 623 : long i, d = lg(elts)-1;
2703 623 : GEN s = gen_0;
2704 2149 : for(i=1; i<=d; i++)
2705 1526 : s = gadd(s, gel(ch, gmul(gel(elts,i),p)[1]));
2706 623 : return gdivgu(s, d);
2707 : }
2708 :
2709 : static GEN
2710 2282 : artin_ram(GEN nf, GEN gal, GEN aut, GEN pr, GEN ramg, GEN ch, long d)
2711 : {
2712 2282 : pari_sp av = avma;
2713 : long i, v, n;
2714 : GEN p, q, V, elts;
2715 2282 : if (d==0) return pol_1(0);
2716 616 : n = degpol(gal_get_pol(gal));
2717 616 : q = p = idealramfrobenius_aut(nf, gal, pr, ramg, aut);
2718 616 : elts = group_elts(gel(ramg,2), n);
2719 616 : v = fetch_var_higher();
2720 616 : V = cgetg(d+2, t_POL);
2721 616 : V[1] = evalsigne(1)|evalvarn(v);
2722 1239 : for(i=1; i<=d; i++)
2723 : {
2724 623 : gel(V,i+1) = artin_ind(elts, ch, q);
2725 623 : q = gmul(q, p);
2726 : }
2727 616 : delete_var();
2728 616 : V = RgXn_expint(RgX_neg(V),d+1);
2729 616 : setvarn(V,0); return gerepileupto(av, ginv(V));
2730 : }
2731 :
2732 : /* N true nf; [Artin conductor, vec of [p, Lp]] */
2733 : static GEN
2734 1379 : artin_badprimes(GEN N, GEN G, GEN aut, GEN ch)
2735 : {
2736 1379 : pari_sp av = avma;
2737 1379 : long i, d = char_dim(ch);
2738 1379 : GEN P = gel(absZ_factor(nf_get_disc(N)), 1);
2739 1379 : long lP = lg(P);
2740 1379 : GEN B = cgetg(lP, t_VEC), C = cgetg(lP, t_VEC);
2741 :
2742 3661 : for (i = 1; i < lP; ++i)
2743 : {
2744 2282 : GEN p = gel(P, i), pr = idealprimedec_galois(N, p);
2745 2282 : GEN J = idealramgroups_aut(N, G, pr, aut);
2746 2282 : GEN G0 = gel(J,2); /* inertia group */
2747 2282 : long lJ = lg(J);
2748 2282 : long sdec = artin_dim(G0, ch);
2749 2282 : long ndec = group_order(G0);
2750 2282 : long j, v = ndec * (d - sdec);
2751 3213 : for (j = 3; j < lJ; ++j)
2752 : {
2753 931 : GEN Jj = gel(J, j);
2754 931 : long s = artin_dim(Jj, ch);
2755 931 : v += group_order(Jj) * (d - s);
2756 : }
2757 2282 : gel(C, i) = powiu(p, v/ndec);
2758 2282 : gel(B, i) = mkvec2(p, artin_ram(N, G, aut, pr, J, ch, sdec));
2759 : }
2760 1379 : return gerepilecopy(av, mkvec2(ZV_prod(C), B));
2761 : }
2762 :
2763 : /* p does not divide nf.index */
2764 : static GEN
2765 52400 : idealfrobenius_easy(GEN nf, GEN gal, GEN aut, GEN T, GEN p)
2766 : {
2767 52400 : long i, l = lg(aut), f = degpol(T);
2768 52400 : GEN D, Dzk, DzkT, DXp, grp = gal_get_group(gal);
2769 52400 : pari_sp av = avma;
2770 52400 : if (f==1) return gel(grp,1);
2771 50594 : Dzk = nf_get_zkprimpart(nf);
2772 50594 : D = modii(nf_get_zkden(nf), p);
2773 50591 : DzkT = RgV_to_RgM(FqV_red(Dzk, T, p), f);
2774 50595 : DXp = RgX_to_RgC(FpX_Frobenius(T, p), f);
2775 50587 : if (!equali1(D)) DXp = FpC_Fp_mul(DXp, D, p);
2776 332144 : for(i=1; i < l; i++)
2777 : {
2778 332133 : GEN g = gel(grp,i);
2779 332133 : if (perm_orderu(g) == (ulong)f)
2780 : {
2781 170273 : GEN A = FpM_FpC_mul(DzkT, gel(aut,g[1]), p);
2782 170253 : if (ZV_equal(A, DXp)) {set_avma(av); return g; }
2783 : }
2784 : }
2785 : return NULL; /* LCOV_EXCL_LINE */
2786 : }
2787 : /* true nf; p divides nf.index, pr/p unramified */
2788 : static GEN
2789 1596 : idealfrobenius_hard(GEN nf, GEN gal, GEN aut, GEN pr)
2790 : {
2791 1596 : long i, l = lg(aut), f = pr_get_f(pr);
2792 1596 : GEN modpr, p, T, X, Xp, pi, grp = gal_get_group(gal);
2793 1596 : pari_sp av = avma;
2794 1596 : if (f==1) return gel(grp,1);
2795 1344 : pi = pr_get_gen(pr);
2796 1344 : modpr = zkmodprinit(nf, pr);
2797 1344 : p = modpr_get_p(modpr);
2798 1344 : T = modpr_get_T(modpr);
2799 1344 : X = modpr_genFq(modpr);
2800 1344 : Xp = FpX_Frobenius(T, p);
2801 9188 : for (i = 1; i < l; i++)
2802 : {
2803 9188 : GEN g = gel(grp,i);
2804 9188 : if (perm_orderu(g) == (ulong)f)
2805 : {
2806 4372 : GEN S = gel(aut,g[1]);
2807 4372 : GEN A = nf_to_Fq(nf, zk_galoisapplymod(nf,X,S,p), modpr);
2808 : /* sigma(X) = X^p (mod pr) and sigma(pi) in pr */
2809 5828 : if (ZX_equal(A, Xp) && (f == nf_get_degree(nf) ||
2810 2800 : ZC_prdvd(zk_galoisapplymod(nf,pi,S,p),pr))) { set_avma(av); return g; }
2811 : }
2812 : }
2813 : return NULL; /* LCOV_EXCL_LINE */
2814 : }
2815 :
2816 : /* true nf */
2817 : static GEN
2818 53991 : dirartin(GEN nf, GEN G, GEN V, GEN aut, GEN p, long n)
2819 : {
2820 53991 : pari_sp av = avma;
2821 : GEN pr, frob;
2822 : /* pick one maximal ideal in the conjugacy class above p */
2823 53991 : GEN T = nf_get_pol(nf);
2824 53993 : if (!dvdii(nf_get_index(nf), p))
2825 : { /* simple case */
2826 52392 : GEN F = FpX_factor(T, p), P = gmael(F,1,1);
2827 52400 : frob = idealfrobenius_easy(nf, G, aut, P, p);
2828 : }
2829 : else
2830 : {
2831 1596 : pr = idealprimedec_galois(nf,p);
2832 1596 : frob = idealfrobenius_hard(nf, G, aut, pr);
2833 : }
2834 53996 : set_avma(av); return n ? RgXn_inv(gel(V, frob[1]), n): gel(V, frob[1]);
2835 : }
2836 :
2837 : GEN
2838 15666 : dirartin_worker(GEN P, ulong X, GEN nf, GEN G, GEN V, GEN aut)
2839 : {
2840 15666 : pari_sp av = avma;
2841 15666 : long i, l = lg(P);
2842 15666 : GEN W = cgetg(l, t_VEC);
2843 69633 : for(i = 1; i < l; i++)
2844 : {
2845 53967 : ulong p = uel(P,i);
2846 53967 : long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */
2847 53966 : gel(W,i) = dirartin(nf, G, V, aut, utoi(uel(P,i)), d);
2848 : }
2849 15666 : return gerepilecopy(av, mkvec2(P,W));
2850 : }
2851 :
2852 : static GEN
2853 2947 : vecan_artin(GEN an, long L, long prec)
2854 : {
2855 2947 : GEN A, Sbad = gel(an,5);
2856 2947 : long n = itos(gel(an,6)), isreal = lg(an)<8 ? 0: !itos(gel(an,7));
2857 2947 : GEN worker = snm_closure(is_entry("_dirartin_worker"), vecslice(an,1,4));
2858 2947 : A = lift_shallow(pardireuler(worker, gen_2, stoi(L), NULL, Sbad));
2859 2947 : A = RgXV_RgV_eval(A, grootsof1(n, prec));
2860 2947 : if (isreal) A = real_i(A);
2861 2947 : return A;
2862 : }
2863 :
2864 : static GEN
2865 28 : eulerf_artin(GEN an, GEN p, long prec)
2866 : {
2867 28 : GEN nf = gel(an,1), G = gel(an,2), V = gel(an,3), aut = gel(an,4);
2868 28 : GEN Sbad = gel(an,5);
2869 28 : long n = itos(gel(an,6)), isreal = lg(an)<8 ? 0: !itos(gel(an,7));
2870 28 : GEN f = eulerf_bad(Sbad, p);
2871 28 : if (!f) f = mkrfrac(gen_1,dirartin(nf, G, V, aut, p, 0));
2872 28 : f = gsubst(liftpol(f),1, rootsof1u_cx(n, prec));
2873 28 : if (isreal) f = real_i(f);
2874 28 : return f;
2875 : }
2876 :
2877 : static GEN
2878 2856 : char_expand(GEN conj, GEN ch)
2879 : {
2880 2856 : long i, l = lg(conj);
2881 2856 : GEN V = cgetg(l, t_COL);
2882 31409 : for (i=1; i<l; i++) gel(V,i) = gel(ch, conj[i]);
2883 2856 : return V;
2884 : }
2885 :
2886 : static GEN
2887 1596 : handle_zeta(long n, GEN ch, long *m)
2888 : {
2889 : GEN c;
2890 1596 : long t, i, l = lg(ch);
2891 1596 : GEN dim = cyclotoi(vecsum(ch));
2892 1596 : if (typ(dim) != t_INT)
2893 0 : pari_err_DOMAIN("lfunartin","chi","is not a", strtoGENstr("character"), ch);
2894 1596 : t = itos(dim);
2895 1596 : if (t < 0 || t % n)
2896 0 : pari_err_DOMAIN("lfunartin","chi","is not a", strtoGENstr("character"), ch);
2897 1596 : if (t == 0) { *m = 0; return ch; }
2898 224 : *m = t / n;
2899 224 : c = cgetg(l, t_COL);
2900 2065 : for (i=1; i<l; i++)
2901 1841 : gel(c,i) = gsubgs(gel(ch,i), *m);
2902 224 : return c;
2903 : }
2904 :
2905 : static int
2906 6496 : cyclo_is_real(GEN v, GEN ix)
2907 : {
2908 6496 : pari_sp av = avma;
2909 6496 : GEN w = poleval(lift_shallow(v), ix);
2910 6496 : return gc_bool(av, gequal(w, v));
2911 : }
2912 :
2913 : static int
2914 1379 : char_is_real(GEN ch, GEN mod)
2915 : {
2916 1379 : long i, l = lg(ch);
2917 1379 : GEN ix = QXQ_inv(pol_x(varn(mod)), mod);
2918 7014 : for (i=1; i<l; i++)
2919 6496 : if (!cyclo_is_real(gel(ch,i), ix)) return 0;
2920 518 : return 1;
2921 : }
2922 :
2923 : GEN
2924 1610 : lfunartin(GEN nf, GEN gal, GEN ch, long o, long bitprec)
2925 : {
2926 1610 : pari_sp av = avma;
2927 1610 : GEN bc, V, aut, mod, Ldata = NULL, chx, cc, conj, repr;
2928 : long tmult, var;
2929 1610 : nf = checknf(nf);
2930 1610 : checkgal(gal);
2931 1610 : var = gvar(ch);
2932 1610 : if (var == 0) pari_err_PRIORITY("lfunartin",ch,"=",0);
2933 1610 : if (var < 0) var = 1;
2934 1610 : if (!is_vec_t(typ(ch))) pari_err_TYPE("lfunartin", ch);
2935 1610 : cc = group_to_cc(gal);
2936 1610 : conj = gel(cc,2);
2937 1610 : repr = gel(cc,3);
2938 1610 : mod = mkpolmod(gen_1, polcyclo(o, var));
2939 1610 : if (lg(ch)>1 && typ(gel(ch,1))==t_MAT)
2940 119 : chx = artin_charfromgens(gal, gmul(ch,mod));
2941 : else
2942 : {
2943 1491 : if (lg(repr) != lg(ch)) pari_err_DIM("lfunartin");
2944 1477 : chx = char_expand(conj, gmul(ch,mod));
2945 : }
2946 1596 : chx = handle_zeta(nf_get_degree(nf), chx, &tmult);
2947 1596 : ch = shallowextract(chx, repr);
2948 1596 : if (!gequal0(chx))
2949 : {
2950 1379 : GEN real = char_is_real(chx, gel(mod,1))? gen_0: gen_1;
2951 1379 : aut = nfgaloispermtobasis(nf, gal);
2952 1379 : V = gmul(char_expand(conj, galoischarpoly(gal, ch, o)), mod);
2953 1379 : bc = artin_badprimes(nf, gal, aut, chx);
2954 2758 : Ldata = mkvecn(6,
2955 1379 : tag(mkcoln(7, nf, gal, V, aut, gel(bc, 2), stoi(o), real), t_LFUN_ARTIN),
2956 1379 : real, artin_gamma(nf, gal, chx), gen_1, gel(bc,1), gen_0);
2957 : }
2958 1596 : if (tmult==0 && Ldata==NULL) pari_err_TYPE("lfunartin",ch);
2959 1596 : if (tmult)
2960 : {
2961 : long i;
2962 224 : if (Ldata==NULL) { Ldata = lfunzeta(); tmult--; }
2963 231 : for(i=1; i<=tmult; i++)
2964 7 : Ldata = lfunmul(Ldata, gen_1, bitprec);
2965 : }
2966 1596 : return gerepilecopy(av, Ldata);
2967 : }
2968 :
2969 : /* true nf */
2970 : static GEN
2971 21 : lfunzetakinit_artin(GEN nf, GEN gal, GEN dom, long der, long bitprec)
2972 : {
2973 21 : GEN F, E, M, domain, To = galoischartable(gal), T = gel(To, 1);
2974 21 : long i, o = itos(gel(To, 2)), l = lg(T);
2975 21 : F = cgetg(l, t_VEC);
2976 21 : E = cgetg(l, t_VECSMALL);
2977 84 : for (i = 1; i < l; ++i)
2978 : {
2979 63 : GEN L = lfunartin(nf, gal, gel(T,i), o, bitprec);
2980 63 : gel(F, i) = lfuninit(L, dom, der, bitprec);
2981 63 : E[i] = char_dim(gel(T,i));
2982 : }
2983 21 : domain = mkvec2(dom, mkvecsmall2(der, bitprec));
2984 21 : M = mkvec3(F, E, zero_zv(l-1));
2985 21 : return lfuninit_make(t_LDESC_PRODUCT, lfunzetak_i(nf), M, domain);
2986 : }
2987 :
2988 : /********************************************************************/
2989 : /** High-level Constructors **/
2990 : /********************************************************************/
2991 : enum { t_LFUNMISC_POL, t_LFUNMISC_CHIQUAD, t_LFUNMISC_CHICONREY,
2992 : t_LFUNMISC_CHIGEN, t_LFUNMISC_ELLINIT, t_LFUNMISC_ETAQUO,
2993 : t_LFUNMISC_GCHAR, t_LFUNMISC_ABELREL };
2994 : static long
2995 8225 : lfundatatype(GEN data)
2996 : {
2997 8225 : switch(typ(data))
2998 : {
2999 3507 : case t_INT: return t_LFUNMISC_CHIQUAD;
3000 147 : case t_INTMOD: return t_LFUNMISC_CHICONREY;
3001 560 : case t_POL: return t_LFUNMISC_POL;
3002 4011 : case t_VEC:
3003 4011 : switch(lg(data))
3004 : {
3005 1806 : case 17: return t_LFUNMISC_ELLINIT;
3006 0 : case 10: return t_LFUNMISC_POL;
3007 2205 : case 3:
3008 2205 : if (typ(gel(data,1)) != t_VEC) break;
3009 2205 : return is_gchar_group(gel(data,1)) ? t_LFUNMISC_GCHAR
3010 2205 : : typ(gel(data,2))==t_MAT ? t_LFUNMISC_ABELREL
3011 : : t_LFUNMISC_CHIGEN;
3012 : }
3013 0 : break;
3014 : }
3015 0 : return -1;
3016 : }
3017 : static GEN
3018 67655 : lfunmisc_to_ldata_i(GEN ldata, long shallow)
3019 : {
3020 : GEN x;
3021 67655 : if (is_linit(ldata)) ldata = linit_get_ldata(ldata);
3022 67655 : if (is_ldata(ldata) && is_tagged(ldata))
3023 : {
3024 59276 : if (!shallow) ldata = gcopy(ldata);
3025 59276 : checkldata(ldata); return ldata;
3026 : }
3027 8379 : x = checknf_i(ldata); if (x) return lfunzetak(x);
3028 8225 : switch (lfundatatype(ldata))
3029 : {
3030 560 : case t_LFUNMISC_POL: return lfunzetak(ldata);
3031 3507 : case t_LFUNMISC_CHIQUAD: return lfunchiquad(ldata);
3032 147 : case t_LFUNMISC_CHICONREY:
3033 : {
3034 147 : GEN G = znstar0(gel(ldata,1), 1);
3035 147 : return lfunchiZ(G, gel(ldata,2));
3036 : }
3037 1792 : case t_LFUNMISC_CHIGEN:
3038 : {
3039 1792 : GEN G = gel(ldata,1), chi = gel(ldata,2);
3040 1792 : switch(nftyp(G))
3041 : {
3042 1603 : case typ_BIDZ: return lfunchiZ(G, chi);
3043 182 : case typ_BNR: return lfunchigen(G, chi);
3044 : }
3045 : }
3046 7 : break;
3047 392 : case t_LFUNMISC_GCHAR: return lfungchar(gel(ldata,1), gel(ldata,2));
3048 21 : case t_LFUNMISC_ABELREL:
3049 21 : return lfunabelrel(gel(ldata,1), gel(ldata,2),
3050 21 : lg(ldata)==3? NULL: gel(ldata,3));
3051 1806 : case t_LFUNMISC_ELLINIT: return lfunell(ldata);
3052 : }
3053 7 : if (shallow != 2) pari_err_TYPE("lfunmisc_to_ldata",ldata);
3054 0 : return NULL;
3055 : }
3056 :
3057 : GEN
3058 1358 : lfunmisc_to_ldata(GEN ldata)
3059 1358 : { return lfunmisc_to_ldata_i(ldata, 0); }
3060 :
3061 : GEN
3062 52815 : lfunmisc_to_ldata_shallow(GEN ldata)
3063 52815 : { return lfunmisc_to_ldata_i(ldata, 1); }
3064 :
3065 : GEN
3066 13482 : lfunmisc_to_ldata_shallow_i(GEN ldata)
3067 13482 : { return lfunmisc_to_ldata_i(ldata, 2); }
3068 :
3069 : /********************************************************************/
3070 : /** High-level an expansion **/
3071 : /********************************************************************/
3072 : /* van is the output of ldata_get_an: return a_1,...a_L at precision prec */
3073 : GEN
3074 18767 : ldata_vecan(GEN van, long L, long prec)
3075 : {
3076 18767 : GEN an = gel(van, 2);
3077 18767 : long t = mael(van,1,1);
3078 : pari_timer ti;
3079 18767 : if (DEBUGLEVEL >= 1)
3080 0 : err_printf("Lfun: computing %ld coeffs, prec %ld, type %ld\n", L, prec, t);
3081 18767 : if (DEBUGLEVEL >= 2) timer_start(&ti);
3082 18767 : switch (t)
3083 : {
3084 : long n;
3085 1925 : case t_LFUN_GENERIC:
3086 1925 : an = vecan_closure(an, L, prec);
3087 1855 : n = lg(an)-1;
3088 1855 : if (n < L)
3089 : {
3090 14 : pari_warn(warner, "#an = %ld < %ld, results may be imprecise", n, L);
3091 14 : an = shallowconcat(an, zerovec(L-n));
3092 : }
3093 1855 : break;
3094 0 : case t_LFUN_CLOSURE0:
3095 : pari_err_BUG("ldata_vecan: please call ldata_newprec");/*LCOV_EXCL_LINE*/
3096 1890 : case t_LFUN_ZETA: an = const_vecsmall(L, 1); break;
3097 2072 : case t_LFUN_NF: an = dirzetak(an, stoi(L)); break;
3098 1974 : case t_LFUN_ELL:
3099 1974 : an = (ell_get_type(an) == t_ELL_Q) ? ellanQ_zv(an, L): ellan(an, L);
3100 1974 : break;
3101 1295 : case t_LFUN_KRONECKER: an = vecan_Kronecker(an, L); break;
3102 119 : case t_LFUN_ABELREL: an = vecan_abelrel(an, L); break;
3103 980 : case t_LFUN_CHIZ: an = vecan_chiZ(an, L, prec); break;
3104 945 : case t_LFUN_CHIGEN: an = vecan_chigen(an, L, prec); break;
3105 693 : case t_LFUN_HECKE: an = vecan_gchar(an, L, prec); break;
3106 2947 : case t_LFUN_ARTIN: an = vecan_artin(an, L, prec); break;
3107 147 : case t_LFUN_ETA: an = vecan_eta(an, L); break;
3108 399 : case t_LFUN_QF: an = vecan_qf(an, L); break;
3109 616 : case t_LFUN_DIV: an = vecan_div(an, L, prec); break;
3110 308 : case t_LFUN_MUL: an = vecan_mul(an, L, prec); break;
3111 126 : case t_LFUN_CONJ: an = vecan_conj(an, L, prec); break;
3112 343 : case t_LFUN_SYMPOW_ELL: an = vecan_ellsympow(an, L); break;
3113 196 : case t_LFUN_GENUS2: an = vecan_genus2(an, L); break;
3114 168 : case t_LFUN_HGM:
3115 168 : an = hgmcoefs(gel(an,1), gel(an,2), L); break;
3116 406 : case t_LFUN_MFCLOS:
3117 : {
3118 406 : GEN F = gel(an,1), E = gel(an,2), c = gel(an,3);
3119 406 : an = mfcoefs(F,L,1) + 1; /* skip a_0 */
3120 406 : an[0] = evaltyp(t_VEC)|evallg(L+1);
3121 406 : an = mfvecembed(E, an);
3122 406 : if (!isint1(c)) an = RgV_Rg_mul(an,c);
3123 406 : break;
3124 : }
3125 581 : case t_LFUN_TWIST: an = vecan_twist(an, L, prec); break;
3126 637 : case t_LFUN_SHIFT: an = vecan_shift(an, L, prec); break;
3127 0 : default: pari_err_TYPE("ldata_vecan", van);
3128 : }
3129 18697 : if (DEBUGLEVEL >= 2) timer_printf(&ti, "ldata_vecan");
3130 18697 : return an;
3131 : }
3132 :
3133 : /* shallow */
3134 : GEN
3135 19768 : ldata_newprec(GEN ldata, long prec)
3136 : {
3137 19768 : GEN van = ldata_get_an(ldata), an = gel(van, 2);
3138 19768 : long t = mael(van,1,1);
3139 19768 : switch (t)
3140 : {
3141 154 : case t_LFUN_CLOSURE0: return closure2ldata(an, prec);
3142 994 : case t_LFUN_HECKE:
3143 : {
3144 994 : GEN gc = gel(an, 1), chiw = gel(an, 2);
3145 994 : gc = gcharnewprec(gc, prec);
3146 994 : return gchari_lfun(gc, chiw, gen_0); /* chi in internal format */
3147 : }
3148 329 : case t_LFUN_QF:
3149 : {
3150 329 : GEN eno = ldata_get_rootno(ldata);
3151 329 : if (typ(eno)==t_REAL && realprec(eno) < prec) return lfunqf(an, prec);
3152 273 : break;
3153 : }
3154 : }
3155 18564 : return ldata;
3156 : }
3157 :
3158 : GEN
3159 826 : ldata_eulerf(GEN van, GEN p, long prec)
3160 : {
3161 826 : GEN an = gel(van, 2), f = gen_0;
3162 826 : long t = mael(van,1,1);
3163 826 : switch (t)
3164 : {
3165 70 : case t_LFUN_GENERIC:
3166 70 : f = eulerf_closure(an, p, prec); break;
3167 0 : case t_LFUN_CLOSURE0:
3168 : pari_err_BUG("ldata_vecan: please call ldata_newprec");/*LCOV_EXCL_LINE*/
3169 56 : case t_LFUN_ZETA: f = mkrfrac(gen_1,deg1pol(gen_m1, gen_1,0)); break;
3170 168 : case t_LFUN_NF: f = eulerf_zetak(an, p); break;
3171 70 : case t_LFUN_ELL: f = elleulerf(an, p); break;
3172 70 : case t_LFUN_KRONECKER:
3173 70 : f = mkrfrac(gen_1, deg1pol_shallow(stoi(-kronecker(an, p)), gen_1, 0)); break;
3174 28 : case t_LFUN_ABELREL: f = eulerf_abelrel(an, p); break;
3175 42 : case t_LFUN_CHIZ: f = eulerf_chiZ(an, p, prec); break;
3176 28 : case t_LFUN_CHIGEN: f = eulerf_chigen(an, p, prec); break;
3177 14 : case t_LFUN_HECKE: f = eulerf_gchar(an, p, prec); break;
3178 28 : case t_LFUN_ARTIN: f = eulerf_artin(an, p, prec); break;
3179 14 : case t_LFUN_DIV: f = eulerf_div(an, p, prec); break;
3180 28 : case t_LFUN_MUL: f = eulerf_mul(an, p, prec); break;
3181 0 : case t_LFUN_CONJ: f = eulerf_conj(an, p, prec); break;
3182 28 : case t_LFUN_SYMPOW_ELL: f = eulerf_ellsympow(an, p); break;
3183 0 : case t_LFUN_GENUS2: f = eulerf_genus2(an, p); break;
3184 14 : case t_LFUN_TWIST: f = eulerf_twist(an, p, prec); break;
3185 42 : case t_LFUN_SHIFT: f = eulerf_shift(an, p, prec); break;
3186 84 : case t_LFUN_HGM: f = eulerf_hgm(an, p); break;
3187 42 : default: f = NULL; break;
3188 : }
3189 826 : if (!f) pari_err_DOMAIN("lfuneuler", "L", "Euler product", strtoGENstr("unknown"), an);
3190 714 : return f;
3191 : }
3192 :
3193 : GEN
3194 679 : lfuneuler(GEN ldata, GEN p, long prec)
3195 : {
3196 679 : pari_sp av = avma;
3197 679 : if (typ(p)!=t_INT || signe(p)<=0) pari_err_TYPE("lfuneuler", p);
3198 672 : ldata = ldata_newprec(lfunmisc_to_ldata_shallow(ldata), prec);
3199 672 : return gerepilecopy(av, ldata_eulerf(ldata_get_an(ldata), p, prec));
3200 : }
|