Line data Source code
1 : /* Copyright (C) 2016 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 : /* Modular forms package based on trace formulas */
18 : /* */
19 : /*************************************************************************/
20 : #include "pari.h"
21 : #include "paripriv.h"
22 :
23 : #define DEBUGLEVEL DEBUGLEVEL_mf
24 :
25 : enum {
26 : MF_SPLIT = 1,
27 : MF_EISENSPACE,
28 : MF_FRICKE,
29 : MF_MF2INIT,
30 : MF_SPLITN
31 : };
32 :
33 : typedef struct {
34 : GEN vnew, vfull, DATA, VCHIP;
35 : long n, newHIT, newTOTAL, cuspHIT, cuspTOTAL;
36 : } cachenew_t;
37 :
38 : static void init_cachenew(cachenew_t *c, long n, long N, GEN f);
39 : static long mf1cuspdim_i(long N, GEN CHI, GEN TMP, GEN vSP, long *dih);
40 : static GEN mfinit_i(GEN NK, long space);
41 : static GEN mfinit_Nkchi(long N, long k, GEN CHI, long space, long flraw);
42 : static GEN mf2init_Nkchi(long N, long k, GEN CHI, long space, long flraw);
43 : static GEN mf2basis(long N, long r, GEN CHI, GEN *pCHI1, long space);
44 : static GEN mfeisensteinbasis(long N, long k, GEN CHI);
45 : static GEN mfeisensteindec(GEN mf, GEN F);
46 : static GEN initwt1newtrace(GEN mf);
47 : static GEN initwt1trace(GEN mf);
48 : static GEN myfactoru(long N);
49 : static GEN mydivisorsu(long N);
50 : static GEN Qab_Czeta(long k, long ord, GEN C, long vt);
51 : static GEN mfcoefs_i(GEN F, long n, long d);
52 : static GEN bhnmat_extend(GEN M, long m,long l, GEN S, cachenew_t *cache);
53 : static GEN initnewtrace(long N, GEN CHI);
54 : static void dbg_cachenew(cachenew_t *C);
55 : static GEN hecke_i(long m, long l, GEN V, GEN F, GEN DATA);
56 : static GEN c_Ek(long n, long d, GEN F);
57 : static GEN RgV_heckef2(long n, long d, GEN V, GEN F, GEN DATA);
58 : static GEN mfcusptrace_i(long N, long k, long n, GEN Dn, GEN TDATA);
59 : static GEN mfnewtracecache(long N, long k, long n, cachenew_t *cache);
60 : static GEN colnewtrace(long n0, long n, long d, long N, long k, cachenew_t *c);
61 : static GEN dihan(GEN bnr, GEN w, GEN k0j, long m, ulong n);
62 : static GEN sigchi(long k, GEN CHI, long n);
63 : static GEN sigchi2(long k, GEN CHI1, GEN CHI2, long n, long ord);
64 : static GEN mflineardivtomat(long N, GEN vF, long n);
65 : static GEN mfdihedralcusp(long N, GEN CHI, GEN vSP);
66 : static long mfdihedralcuspdim(long N, GEN CHI, GEN vSP);
67 : static GEN mfdihedralnew(long N, GEN CHI, GEN SP);
68 : static GEN mfdihedral(long N);
69 : static GEN mfdihedralall(long N);
70 : static long mf1cuspdim(long N, GEN CHI, GEN vSP);
71 : static long mf2dim_Nkchi(long N, long k, GEN CHI, ulong space);
72 : static long mfdim_Nkchi(long N, long k, GEN CHI, long space);
73 : static GEN charLFwtk(long N, long k, GEN CHI, long ord, long t);
74 : static GEN mfeisensteingacx(GEN E,long w,GEN ga,long n,long prec);
75 : static GEN mfgaexpansion(GEN mf, GEN F, GEN gamma, long n, long prec);
76 : static GEN mfEHmat(long n, long r);
77 : static GEN mfEHcoef(long r, long N);
78 : static GEN mftobasis_i(GEN mf, GEN F);
79 :
80 : static GEN
81 37863 : mkgNK(GEN N, GEN k, GEN CHI, GEN P) { return mkvec4(N, k, CHI, P); }
82 : static GEN
83 15267 : mkNK(long N, long k, GEN CHI) { return mkgNK(stoi(N), stoi(k), CHI, pol_x(1)); }
84 : GEN
85 8848 : MF_get_CHI(GEN mf) { return gmael(mf,1,3); }
86 : GEN
87 21273 : MF_get_gN(GEN mf) { return gmael(mf,1,1); }
88 : long
89 20069 : MF_get_N(GEN mf) { return itou(MF_get_gN(mf)); }
90 : GEN
91 15526 : MF_get_gk(GEN mf) { return gmael(mf,1,2); }
92 : long
93 7238 : MF_get_k(GEN mf)
94 : {
95 7238 : GEN gk = MF_get_gk(mf);
96 7238 : if (typ(gk)!=t_INT) pari_err_IMPL("half-integral weight");
97 7238 : return itou(gk);
98 : }
99 : long
100 280 : MF_get_r(GEN mf)
101 : {
102 280 : GEN gk = MF_get_gk(mf);
103 280 : if (typ(gk) == t_INT) pari_err_IMPL("integral weight");
104 280 : return itou(gel(gk, 1)) >> 1;
105 : }
106 : long
107 15393 : MF_get_space(GEN mf) { return itos(gmael(mf,1,4)); }
108 : GEN
109 4487 : MF_get_E(GEN mf) { return gel(mf,2); }
110 : GEN
111 21553 : MF_get_S(GEN mf) { return gel(mf,3); }
112 : GEN
113 1911 : MF_get_basis(GEN mf) { return shallowconcat(gel(mf,2), gel(mf,3)); }
114 : long
115 5642 : MF_get_dim(GEN mf)
116 : {
117 5642 : switch(MF_get_space(mf))
118 : {
119 721 : case mf_FULL:
120 721 : return lg(MF_get_S(mf)) - 1 + lg(MF_get_E(mf))-1;
121 140 : case mf_EISEN:
122 140 : return lg(MF_get_E(mf))-1;
123 4781 : default: /* mf_NEW, mf_CUSP, mf_OLD */
124 4781 : return lg(MF_get_S(mf)) - 1;
125 : }
126 : }
127 : GEN
128 7343 : MFnew_get_vj(GEN mf) { return gel(mf,4); }
129 : GEN
130 686 : MFcusp_get_vMjd(GEN mf) { return gel(mf,4); }
131 : GEN
132 6916 : MF_get_M(GEN mf) { return gmael(mf,5,3); }
133 : GEN
134 4872 : MF_get_Minv(GEN mf) { return gmael(mf,5,2); }
135 : GEN
136 10640 : MF_get_Mindex(GEN mf) { return gmael(mf,5,1); }
137 :
138 : /* ordinary gtocol forgets about initial 0s */
139 : GEN
140 2583 : sertocol(GEN S) { return gtocol0(S, -(lg(S) - 2 + valser(S))); }
141 : /*******************************************************************/
142 : /* Linear algebra in cyclotomic fields (TODO: export this) */
143 : /*******************************************************************/
144 : /* return r and split prime p giving projection Q(zeta_n) -> Fp, zeta -> r */
145 : static ulong
146 1246 : QabM_init(long n, ulong *p)
147 : {
148 1246 : ulong pinit = 1000000007;
149 : forprime_t T;
150 1246 : if (n <= 1) { *p = pinit; return 0; }
151 1225 : u_forprime_arith_init(&T, pinit, ULONG_MAX, 1, n);
152 1225 : *p = u_forprime_next(&T);
153 1225 : return Flx_oneroot(ZX_to_Flx(polcyclo(n, 0), *p), *p);
154 : }
155 : static ulong
156 8534960 : Qab_to_Fl(GEN P, ulong r, ulong p)
157 : {
158 : ulong t;
159 : GEN den;
160 8534960 : P = Q_remove_denom(liftpol_shallow(P), &den);
161 8534960 : if (typ(P) == t_POL) { GEN Pp = ZX_to_Flx(P, p); t = Flx_eval(Pp, r, p); }
162 8399335 : else t = umodiu(P, p);
163 8534960 : if (den) t = Fl_div(t, umodiu(den, p), p);
164 8534960 : return t;
165 : }
166 : static GEN
167 38164 : QabC_to_Flc(GEN x, ulong r, ulong p)
168 8341333 : { pari_APPLY_long( Qab_to_Fl(gel(x,i), r, p)); }
169 : static GEN
170 595 : QabM_to_Flm(GEN x, ulong r, ulong p)
171 38759 : { pari_APPLY_same(QabC_to_Flc(gel(x, i), r, p);) }
172 : /* A a t_POL */
173 : static GEN
174 1484 : QabX_to_Flx(GEN A, ulong r, ulong p)
175 : {
176 1484 : long i, l = lg(A);
177 1484 : GEN a = cgetg(l, t_VECSMALL);
178 1484 : a[1] = ((ulong)A[1])&VARNBITS;
179 233023 : for (i = 2; i < l; i++) uel(a,i) = Qab_to_Fl(gel(A,i), r, p);
180 1484 : return Flx_renormalize(a, l);
181 : }
182 :
183 : /* FIXME: remove */
184 : static GEN
185 1106 : ZabM_pseudoinv_i(GEN M, GEN P, long n, GEN *pv, GEN *den, int ratlift)
186 : {
187 1106 : GEN v = ZabM_indexrank(M, P, n);
188 1106 : if (pv) *pv = v;
189 1106 : M = shallowmatextract(M,gel(v,1),gel(v,2));
190 1106 : return ratlift? ZabM_inv_ratlift(M, P, n, den): ZabM_inv(M, P, n, den);
191 : }
192 :
193 : /* M matrix with coeff in Q(\chi)), where Q(\chi) = Q(X)/(P) for
194 : * P = cyclotomic Phi_n. Assume M rational if n <= 2 */
195 : static GEN
196 1652 : QabM_ker(GEN M, GEN P, long n)
197 : {
198 1652 : if (n <= 2) return QM_ker(M);
199 420 : return ZabM_ker(row_Q_primpart(liftpol_shallow(M)), P, n);
200 : }
201 : /* pseudo-inverse of M. FIXME: should replace QabM_pseudoinv */
202 : static GEN
203 1358 : QabM_pseudoinv_i(GEN M, GEN P, long n, GEN *pv, GEN *pden)
204 : {
205 : GEN cM, Mi;
206 1358 : if (n <= 2)
207 : {
208 1176 : M = Q_primitive_part(M, &cM);
209 1176 : Mi = ZM_pseudoinv(M, pv, pden); /* M^(-1) = Mi / (cM * den) */
210 : }
211 : else
212 : {
213 182 : M = Q_primitive_part(liftpol_shallow(M), &cM);
214 182 : Mi = ZabM_pseudoinv(M, P, n, pv, pden);
215 : }
216 1358 : *pden = mul_content(*pden, cM);
217 1358 : return Mi;
218 : }
219 : /* FIXME: delete */
220 : static GEN
221 1092 : QabM_pseudoinv(GEN M, GEN P, long n, GEN *pv, GEN *pden)
222 : {
223 1092 : GEN Mi = QabM_pseudoinv_i(M, P, n, pv, pden);
224 1092 : return P? gmodulo(Mi, P): Mi;
225 : }
226 :
227 : static GEN
228 10563 : QabM_indexrank(GEN M, GEN P, long n)
229 : {
230 : GEN z;
231 10563 : if (n <= 2)
232 : {
233 9366 : M = vec_Q_primpart(M);
234 9366 : z = ZM_indexrank(M); /* M^(-1) = Mi / (cM * den) */
235 : }
236 : else
237 : {
238 1197 : M = vec_Q_primpart(liftpol_shallow(M));
239 1197 : z = ZabM_indexrank(M, P, n);
240 : }
241 10563 : return z;
242 : }
243 :
244 : /*********************************************************************/
245 : /* Simple arithmetic functions */
246 : /*********************************************************************/
247 : /* TODO: most of these should be exported and used in ifactor1.c */
248 : /* phi(n) */
249 : static ulong
250 110726 : myeulerphiu(ulong n)
251 : {
252 : pari_sp av;
253 110726 : if (n == 1) return 1;
254 91140 : av = avma; return gc_ulong(av, eulerphiu_fact(myfactoru(n)));
255 : }
256 : static long
257 65709 : mymoebiusu(ulong n)
258 : {
259 : pari_sp av;
260 65709 : if (n == 1) return 1;
261 54194 : av = avma; return gc_long(av, moebiusu_fact(myfactoru(n)));
262 : }
263 :
264 : static long
265 3031 : mynumdivu(long N)
266 : {
267 : pari_sp av;
268 3031 : if (N == 1) return 1;
269 2898 : av = avma; return gc_long(av, numdivu_fact(myfactoru(N)));
270 : }
271 :
272 : /* N\prod_{p|N} (1+1/p) */
273 : static long
274 401541 : mypsiu(ulong N)
275 : {
276 : pari_sp av;
277 : GEN P;
278 : long j, l, a;
279 401541 : if (N == 1) return 1;
280 315532 : av = avma; P = gel(myfactoru(N), 1); l = lg(P);
281 751247 : for (a = N, j = 1; j < l; j++) a += a / P[j];
282 315532 : return gc_long(av, a);
283 : }
284 : /* write n = mf^2. Return m, set f. */
285 : static ulong
286 71 : mycore(ulong n, long *pf)
287 : {
288 71 : pari_sp av = avma;
289 71 : GEN fa = myfactoru(n), P = gel(fa,1), E = gel(fa,2);
290 71 : long i, l = lg(P), m = 1, f = 1;
291 268 : for (i = 1; i < l; i++)
292 : {
293 197 : long j, p = P[i], e = E[i];
294 197 : if (e & 1) m *= p;
295 456 : for (j = 2; j <= e; j+=2) f *= p;
296 : }
297 71 : *pf = f; return gc_long(av,m);
298 : }
299 :
300 : /* fa = factorization of -D > 0, return -D0 > 0 (where D0 is fundamental) */
301 : static long
302 12427786 : corediscs_fact(GEN fa)
303 : {
304 12427786 : GEN P = gel(fa,1), E = gel(fa,2);
305 12427786 : long i, l = lg(P), m = 1;
306 41412492 : for (i = 1; i < l; i++)
307 : {
308 28984706 : long p = P[i], e = E[i];
309 28984706 : if (e & 1) m *= p;
310 : }
311 12427786 : if ((m&3L) != 3) m <<= 2;
312 12427786 : return m;
313 : }
314 : static long
315 7098 : mubeta(long n)
316 : {
317 7098 : pari_sp av = avma;
318 7098 : GEN E = gel(myfactoru(n), 2);
319 7098 : long i, s = 1, l = lg(E);
320 14735 : for (i = 1; i < l; i++)
321 : {
322 7637 : long e = E[i];
323 7637 : if (e >= 3) return gc_long(av,0);
324 7637 : if (e == 1) s *= -2;
325 : }
326 7098 : return gc_long(av,s);
327 : }
328 :
329 : /* n = n1*n2, n1 = ppo(n, m); return mubeta(n1)*moebiusu(n2).
330 : * N.B. If n from newt_params we, in fact, never return 0 */
331 : static long
332 7850904 : mubeta2(long n, long m)
333 : {
334 7850904 : pari_sp av = avma;
335 7850904 : GEN fa = myfactoru(n), P = gel(fa,1), E = gel(fa,2);
336 7850904 : long i, s = 1, l = lg(P);
337 15734522 : for (i = 1; i < l; i++)
338 : {
339 7883618 : long p = P[i], e = E[i];
340 7883618 : if (m % p)
341 : { /* p^e in n1 */
342 6669223 : if (e >= 3) return gc_long(av,0);
343 6669223 : if (e == 1) s *= -2;
344 : }
345 : else
346 : { /* in n2 */
347 1214395 : if (e >= 2) return gc_long(av,0);
348 1214395 : s = -s;
349 : }
350 : }
351 7850904 : return gc_long(av,s);
352 : }
353 :
354 : /* write N = prod p^{ep} and n = df^2, d squarefree.
355 : * set g = ppo(gcd(sqfpart(N), f), FC)
356 : * N2 = prod p^if(e==1 || p|n, ep-1, ep-2) */
357 : static void
358 1941594 : newt_params(long N, long n, long FC, long *pg, long *pN2)
359 : {
360 1941594 : GEN fa = myfactoru(N), P = gel(fa,1), E = gel(fa,2);
361 1941594 : long i, g = 1, N2 = 1, l = lg(P);
362 5163782 : for (i = 1; i < l; i++)
363 : {
364 3222188 : long p = P[i], e = E[i];
365 3222188 : if (e == 1)
366 2825389 : { if (FC % p && n % (p*p) == 0) g *= p; }
367 : else
368 396799 : N2 *= upowuu(p,(n % p)? e-2: e-1);
369 : }
370 1941594 : *pg = g; *pN2 = N2;
371 1941594 : }
372 : /* simplified version of newt_params for n = 1 (newdim) */
373 : static void
374 42525 : newd_params(long N, long *pN2)
375 : {
376 42525 : GEN fa = myfactoru(N), P = gel(fa,1), E = gel(fa,2);
377 42525 : long i, N2 = 1, l = lg(P);
378 106092 : for (i = 1; i < l; i++)
379 : {
380 63567 : long p = P[i], e = E[i];
381 63567 : if (e > 2) N2 *= upowuu(p, e-2);
382 : }
383 42525 : *pN2 = N2;
384 42525 : }
385 :
386 : static long
387 21 : newd_params2(long N)
388 : {
389 21 : GEN fa = myfactoru(N), P = gel(fa,1), E = gel(fa,2);
390 21 : long i, N2 = 1, l = lg(P);
391 56 : for (i = 1; i < l; i++)
392 : {
393 35 : long p = P[i], e = E[i];
394 35 : if (e >= 2) N2 *= upowuu(p, e);
395 : }
396 21 : return N2;
397 : }
398 :
399 : /*******************************************************************/
400 : /* Relative trace between cyclotomic fields (TODO: export this) */
401 : /*******************************************************************/
402 : /* g>=1; return g * prod_{p | g, (p,q) = 1} (1-1/p) */
403 : static long
404 36869 : phipart(long g, long q)
405 : {
406 36869 : if (g > 1)
407 : {
408 19670 : GEN P = gel(myfactoru(g), 1);
409 19670 : long i, l = lg(P);
410 40194 : for (i = 1; i < l; i++) { long p = P[i]; if (q % p) g -= g / p; }
411 : }
412 36869 : return g;
413 : }
414 : /* Set s,v s.t. Trace(zeta_N^k) from Q(zeta_N) to Q(\zeta_N) = s * zeta_M^v
415 : * With k > 0, N = M*d and N, M != 2 mod 4 */
416 : static long
417 84756 : tracerelz(long *pv, long d, long M, long k)
418 : {
419 : long s, g, q, muq;
420 84756 : if (d == 1) { *pv = k; return 1; }
421 65618 : *pv = 0; g = ugcd(k, d); q = d / g;
422 65618 : muq = mymoebiusu(q); if (!muq) return 0;
423 47173 : if (M != 1)
424 : {
425 37828 : long v = Fl_invsafe(q % M, M);
426 37828 : if (!v) return 0;
427 27524 : *pv = (v * (k/g)) % M;
428 : }
429 36869 : s = phipart(g, M*q); if (muq < 0) s = -s;
430 36869 : return s;
431 : }
432 : /* Pi = polcyclo(i), i = m or n. Let Ki = Q(zeta_i), initialize Tr_{Kn/Km} */
433 : GEN
434 34062 : Qab_trace_init(long n, long m, GEN Pn, GEN Pm)
435 : {
436 : long a, i, j, N, M, vt, d, D;
437 : GEN T, G;
438 :
439 34062 : if (m == n || n <= 2) return mkvec(Pm);
440 16555 : vt = varn(Pn);
441 16555 : d = degpol(Pn);
442 : /* if (N != n) zeta_N = zeta_n^2 and zeta_n = - zeta_N^{(N+1)/2} */
443 16555 : N = ((n & 3) == 2)? n >> 1: n;
444 16555 : M = ((m & 3) == 2)? m >> 1: m; /* M | N | n */
445 16555 : a = N / M;
446 16555 : T = const_vec(d, NULL);
447 16555 : D = d / degpol(Pm); /* relative degree */
448 16555 : if (D == 1) G = NULL;
449 : else
450 : { /* zeta_M = zeta_n^A; s_j(zeta_M) = zeta_M <=> j = 1 (mod J) */
451 15281 : long lG, A = (N == n)? a: (a << 1), J = n / ugcd(n, A);
452 15281 : G = coprimes_zv(n);
453 150276 : for (j = lG = 1; j < n; j += J)
454 134995 : if (G[j]) G[lG++] = j;
455 15281 : setlg(G, lG); /* Gal(Q(zeta_n) / Q(zeta_m)) */
456 : }
457 16555 : T = const_vec(d, NULL);
458 16555 : gel(T,1) = utoipos(D); /* Tr 1 */
459 140140 : for (i = 1; i < d; i++)
460 : { /* if n = 2N, zeta_n^i = (-1)^i zeta_N^k */
461 : long s, v, k;
462 : GEN t;
463 :
464 123585 : if (gel(T, i+1)) continue;
465 84756 : k = (N == n)? i: ((odd(i)? i + N: i) >> 1);
466 84756 : if ((s = tracerelz(&v, a, M, k)))
467 : {
468 56007 : if (m != M) v *= 2;/* Tr = s * zeta_m^v */
469 56007 : if (n != N && odd(i)) s = -s;
470 56007 : t = Qab_Czeta(v, m, stoi(s), vt);
471 : }
472 : else
473 28749 : t = gen_0;
474 : /* t = Tr_{Kn/Km} zeta_n^i; fill using Galois action */
475 84756 : if (!G)
476 19138 : gel(T, i + 1) = t;
477 : else
478 370874 : for (j = 1; j <= D; j++)
479 : {
480 305256 : long z = Fl_mul(i,G[j], n);
481 305256 : if (z < d) gel(T, z + 1) = t;
482 : }
483 : }
484 16555 : return mkvec3(Pm, Pn, T);
485 : }
486 : /* x a t_POL modulo Phi_n */
487 : static GEN
488 80255 : tracerel_i(GEN T, GEN x)
489 : {
490 80255 : long k, l = lg(x);
491 : GEN S;
492 80255 : if (l == 2) return gen_0;
493 80255 : S = gmul(gel(T,1), gel(x,2));
494 283290 : for (k = 3; k < l; k++) S = gadd(S, gmul(gel(T,k-1), gel(x,k)));
495 80255 : return S;
496 : }
497 : static GEN
498 253855 : tracerel(GEN a, GEN v, GEN z)
499 : {
500 253855 : a = liftpol_shallow(a);
501 253855 : a = simplify_shallow(z? gmul(z,a): a);
502 253855 : if (typ(a) == t_POL)
503 : {
504 80255 : GEN T = gel(v,3);
505 80255 : long degrel = itou(gel(T,1));
506 80255 : a = tracerel_i(T, RgX_rem(a, gel(v,2)));
507 80255 : if (degrel != 1) a = gdivgu(a, degrel);
508 80255 : if (typ(a) == t_POL) a = RgX_rem(a, gel(v,1));
509 : }
510 253855 : return a;
511 : }
512 : static GEN
513 6944 : tracerel_z(GEN v, long t)
514 : {
515 6944 : GEN Pn = gel(v,2);
516 6944 : return t? pol_xn(t, varn(Pn)): NULL;
517 : }
518 : /* v = Qab_trace_init(n,m); x is a t_VEC of polmodulo Phi_n; Kn = Q(zeta_n)
519 : * [Kn:Km]^(-1) Tr_{Kn/Km} (zeta_n^t * x); 0 <= t < [Kn:Km] */
520 : GEN
521 0 : Qab_tracerel(GEN v, long t, GEN a)
522 : {
523 0 : if (lg(v) != 4) return a; /* => t = 0 */
524 0 : return tracerel(a, v, tracerel_z(v, t));
525 : }
526 : GEN
527 16198 : QabV_tracerel(GEN v, long t, GEN x)
528 : {
529 : GEN z;
530 16198 : if (lg(v) != 4) return x; /* => t = 0 */
531 6944 : z = tracerel_z(v, t);
532 260799 : pari_APPLY_same(tracerel(gel(x,i), v, z));
533 : }
534 : GEN
535 154 : QabM_tracerel(GEN v, long t, GEN x)
536 : {
537 154 : if (lg(v) != 4) return x;
538 105 : pari_APPLY_same(QabV_tracerel(v, t, gel(x,i)));
539 : }
540 :
541 : /* C*zeta_o^k mod X^o - 1 */
542 : static GEN
543 2247966 : Qab_Czeta(long k, long o, GEN C, long vt)
544 : {
545 2247966 : if (!k) return C;
546 1485694 : if (!odd(o))
547 : { /* optimization: reduce max degree by a factor 2 for free */
548 1434587 : o >>= 1;
549 1434587 : if (k >= o) { k -= o; C = gneg(C); if (!k) return C; }
550 : }
551 1137486 : return monomial(C, k, vt);
552 : }
553 : /* zeta_o^k */
554 : static GEN
555 200767 : Qab_zeta(long k, long o, long vt) { return Qab_Czeta(k, o, gen_1, vt); }
556 :
557 : /* Operations on Dirichlet characters */
558 :
559 : /* A Dirichlet character can be given in GP in different formats, but in this
560 : * package, it will be a vector CHI=[G,chi,ord,pol], where G is the (Z/MZ)^* to
561 : * which the character belongs, chi is the character in Conrey format, ord is
562 : * the order, and pol is polcyclo(ord,'t). */
563 :
564 : static GEN
565 3876236 : gmfcharorder(GEN CHI) { return gel(CHI, 3); }
566 : long
567 3817786 : mfcharorder(GEN CHI) { return itou(gmfcharorder(CHI)); }
568 : static long
569 2709 : mfcharistrivial(GEN CHI) { return !CHI || mfcharorder(CHI) == 1; }
570 : static GEN
571 1619786 : gmfcharmodulus(GEN CHI) { return gmael3(CHI, 1, 1, 1); }
572 : long
573 1619786 : mfcharmodulus(GEN CHI) { return itou(gmfcharmodulus(CHI)); }
574 : GEN
575 599354 : mfcharpol(GEN CHI) { return gel(CHI,4); }
576 :
577 : /* vz[i+1] = image of (zeta_o)^i in Fp */
578 : static ulong
579 313040 : Qab_Czeta_Fl(long k, GEN vz, ulong C, ulong p)
580 : {
581 : long o;
582 313040 : if (!k) return C;
583 205982 : o = lg(vz)-2;
584 205982 : if ((k << 1) == o) return Fl_neg(C,p);
585 179053 : return Fl_mul(C, vz[k+1], p);
586 : }
587 :
588 : static long
589 2556365 : znchareval_i(GEN CHI, long n, GEN ord)
590 2556365 : { return itos(znchareval(gel(CHI,1), gel(CHI,2), stoi(n), ord)); }
591 :
592 : /* n coprime with the modulus of CHI */
593 : static GEN
594 14553 : mfchareval(GEN CHI, long n)
595 : {
596 14553 : GEN Pn, C, go = gmfcharorder(CHI);
597 14553 : long k, o = go[2];
598 14553 : if (o == 1) return gen_1;
599 7399 : k = znchareval_i(CHI, n, go);
600 7399 : Pn = mfcharpol(CHI);
601 7399 : C = Qab_zeta(k, o, varn(Pn));
602 7399 : if (typ(C) != t_POL) return C;
603 5327 : return gmodulo(C, Pn);
604 : }
605 : /* d a multiple of ord(CHI); n coprime with char modulus;
606 : * return x s.t. CHI(n) = \zeta_d^x] */
607 : static long
608 3675462 : mfcharevalord(GEN CHI, long n, long d)
609 : {
610 3675462 : if (mfcharorder(CHI) == 1) return 0;
611 2545270 : return znchareval_i(CHI, n, utoi(d));
612 : }
613 :
614 : /* G a znstar, L a Conrey log: return a 'mfchar' */
615 : static GEN
616 378812 : mfcharGL(GEN G, GEN L)
617 : {
618 378812 : GEN o = zncharorder(G,L);
619 378812 : long ord = itou(o), vt = fetch_user_var("t");
620 378812 : return mkvec4(G, L, o, polcyclo(ord,vt));
621 : }
622 : static GEN
623 5859 : mfchartrivial()
624 5859 : { return mfcharGL(znstar0(gen_1,1), cgetg(1,t_COL)); }
625 : /* convert a generic character into an 'mfchar' */
626 : static GEN
627 4074 : get_mfchar(GEN CHI)
628 : {
629 : GEN G, L;
630 4074 : if (typ(CHI) != t_VEC) CHI = znchar(CHI);
631 : else
632 : {
633 889 : long l = lg(CHI);
634 889 : if ((l != 3 && l != 5) || !checkznstar_i(gel(CHI,1)))
635 7 : pari_err_TYPE("checkNF [chi]", CHI);
636 882 : if (l == 5) return CHI;
637 : }
638 4004 : G = gel(CHI,1);
639 4004 : L = gel(CHI,2); if (typ(L) != t_COL) L = znconreylog(G,L);
640 4004 : return mfcharGL(G, L);
641 : }
642 :
643 : /* parse [N], [N,k], [N,k,CHI]. If 'joker' is set, allow wildcard for CHI */
644 : static GEN
645 9247 : checkCHI(GEN NK, long N, int joker)
646 : {
647 : GEN CHI;
648 9247 : if (lg(NK) == 3)
649 742 : CHI = mfchartrivial();
650 : else
651 : {
652 : long i, l;
653 8505 : CHI = gel(NK,3); l = lg(CHI);
654 8505 : if (isintzero(CHI) && joker)
655 4116 : CHI = NULL; /* all character orbits */
656 4389 : else if (isintm1(CHI) && joker > 1)
657 2373 : CHI = gen_m1; /* sum over all character orbits */
658 2016 : else if ((typ(CHI) == t_VEC &&
659 217 : (l == 1 || l != 3 || !checkznstar_i(gel(CHI,1)))) && joker)
660 : {
661 133 : CHI = shallowtrans(CHI); /* list of characters */
662 952 : for (i = 1; i < l; i++) gel(CHI,i) = get_mfchar(gel(CHI,i));
663 : }
664 : else
665 : {
666 1883 : CHI = get_mfchar(CHI); /* single char */
667 1883 : if (N % mfcharmodulus(CHI)) pari_err_TYPE("checkNF [chi]", NK);
668 : }
669 : }
670 9233 : return CHI;
671 : }
672 : /* support half-integral weight */
673 : static void
674 9254 : checkNK2(GEN NK, long *N, long *nk, long *dk, GEN *CHI, int joker)
675 : {
676 9254 : long l = lg(NK);
677 : GEN T;
678 9254 : if (typ(NK) != t_VEC || l < 3 || l > 4) pari_err_TYPE("checkNK", NK);
679 9254 : T = gel(NK,1); if (typ(T) != t_INT) pari_err_TYPE("checkNF [N]", NK);
680 9254 : *N = itos(T); if (*N <= 0) pari_err_TYPE("checkNF [N <= 0]", NK);
681 9254 : T = gel(NK,2);
682 9254 : switch(typ(T))
683 : {
684 5866 : case t_INT: *nk = itos(T); *dk = 1; break;
685 3381 : case t_FRAC:
686 3381 : *nk = itos(gel(T,1));
687 3381 : *dk = itou(gel(T,2)); if (*dk == 2) break;
688 7 : default: pari_err_TYPE("checkNF [k]", NK);
689 : }
690 9247 : *CHI = checkCHI(NK, *N, joker);
691 9233 : }
692 : /* don't support half-integral weight */
693 : static void
694 133 : checkNK(GEN NK, long *N, long *k, GEN *CHI, int joker)
695 : {
696 : long d;
697 133 : checkNK2(NK, N, k, &d, CHI, joker);
698 133 : if (d != 1) pari_err_TYPE("checkNF [k]", NK);
699 133 : }
700 :
701 : static GEN
702 4872 : mfchargalois(long N, int odd, GEN flagorder)
703 : {
704 4872 : GEN G = znstar0(utoi(N), 1), L = chargalois(G, flagorder);
705 4872 : long l = lg(L), i, j;
706 113526 : for (i = j = 1; i < l; i++)
707 : {
708 108654 : GEN chi = znconreyfromchar(G, gel(L,i));
709 108654 : if (zncharisodd(G,chi) == odd) gel(L,j++) = mfcharGL(G,chi);
710 : }
711 4872 : setlg(L, j); return L;
712 : }
713 : /* possible characters for nontrivial S_1(N, chi) */
714 : static GEN
715 1729 : mf1chars(long N, GEN vCHI)
716 : {
717 1729 : if (vCHI) return vCHI; /*do not filter, user knows best*/
718 : /* Tate's theorem */
719 1659 : return mfchargalois(N, 1, uisprime(N)? mkvecsmall2(2,4): NULL);
720 : }
721 : static GEN
722 3255 : mfchars(long N, long k, long dk, GEN vCHI)
723 3255 : { return vCHI? vCHI: mfchargalois(N, (dk == 2)? 0: (k & 1), NULL); }
724 :
725 : /* wrappers from mfchar to znchar */
726 : static long
727 68670 : mfcharparity(GEN CHI)
728 : {
729 68670 : if (!CHI) return 1;
730 68670 : return zncharisodd(gel(CHI,1), gel(CHI,2)) ? -1 : 1;
731 : }
732 : /* if CHI is primitive, return CHI itself, not a copy */
733 : static GEN
734 82334 : mfchartoprimitive(GEN CHI, long *pF)
735 : {
736 : pari_sp av;
737 : GEN chi, F;
738 82334 : if (!CHI) { if (pF) *pF = 1; return mfchartrivial(); }
739 82334 : av = avma; F = znconreyconductor(gel(CHI,1), gel(CHI,2), &chi);
740 82334 : if (typ(F) == t_INT) set_avma(av);
741 : else
742 : {
743 7875 : CHI = leafcopy(CHI);
744 7875 : gel(CHI,1) = znstar0(F, 1);
745 7875 : gel(CHI,2) = chi;
746 : }
747 82334 : if (pF) *pF = mfcharmodulus(CHI);
748 82334 : return CHI;
749 : }
750 : static long
751 397950 : mfcharconductor(GEN CHI)
752 : {
753 397950 : pari_sp av = avma;
754 397950 : GEN res = znconreyconductor(gel(CHI,1), gel(CHI,2), NULL);
755 397950 : if (typ(res) == t_VEC) res = gel(res, 1);
756 397950 : return gc_long(av, itos(res));
757 : }
758 :
759 : /* Operations on mf closures */
760 : static GEN
761 64526 : tagparams(long t, GEN NK) { return mkvec2(mkvecsmall(t), NK); }
762 : static GEN
763 1197 : lfuntag(long t, GEN x) { return mkvec2(mkvecsmall(t), x); }
764 : static GEN
765 56 : tag0(long t, GEN NK) { retmkvec(tagparams(t,NK)); }
766 : static GEN
767 10423 : tag(long t, GEN NK, GEN x) { retmkvec2(tagparams(t,NK), x); }
768 : static GEN
769 37499 : tag2(long t, GEN NK, GEN x, GEN y) { retmkvec3(tagparams(t,NK), x,y); }
770 : static GEN
771 16415 : tag3(long t, GEN NK, GEN x,GEN y,GEN z) { retmkvec4(tagparams(t,NK), x,y,z); }
772 : static GEN
773 0 : tag4(long t, GEN NK, GEN x,GEN y,GEN z,GEN a)
774 0 : { retmkvec5(tagparams(t,NK), x,y,z,a); }
775 : /* is F a "modular form" ? */
776 : int
777 19565 : checkmf_i(GEN F)
778 19565 : { return typ(F) == t_VEC
779 18718 : && lg(F) > 1 && typ(gel(F,1)) == t_VEC
780 13902 : && lg(gel(F,1)) == 3
781 13741 : && typ(gmael(F,1,1)) == t_VECSMALL
782 38283 : && typ(gmael(F,1,2)) == t_VEC; }
783 241108 : long mf_get_type(GEN F) { return gmael(F,1,1)[1]; }
784 191968 : GEN mf_get_gN(GEN F) { return gmael3(F,1,2,1); }
785 144627 : GEN mf_get_gk(GEN F) { return gmael3(F,1,2,2); }
786 : /* k - 1/2, assume k in 1/2 + Z */
787 441 : long mf_get_r(GEN F) { return itou(gel(mf_get_gk(F),1)) >> 1; }
788 124019 : long mf_get_N(GEN F) { return itou(mf_get_gN(F)); }
789 : long
790 73731 : mf_get_k(GEN F)
791 : {
792 73731 : GEN gk = mf_get_gk(F);
793 73731 : if (typ(gk)!=t_INT) pari_err_IMPL("half-integral weight");
794 73731 : return itou(gk);
795 : }
796 65527 : GEN mf_get_CHI(GEN F) { return gmael3(F,1,2,3); }
797 25081 : GEN mf_get_field(GEN F) { return gmael3(F,1,2,4); }
798 19691 : GEN mf_get_NK(GEN F) { return gmael(F,1,2); }
799 : static void
800 588 : mf_setfield(GEN f, GEN P)
801 : {
802 588 : gel(f,1) = leafcopy(gel(f,1));
803 588 : gmael(f,1,2) = leafcopy(gmael(f,1,2));
804 588 : gmael3(f,1,2,4) = P;
805 588 : }
806 :
807 : /* UTILITY FUNCTIONS */
808 : GEN
809 9121 : mftocol(GEN F, long lim, long d)
810 9121 : { GEN c = mfcoefs_i(F, lim, d); settyp(c,t_COL); return c; }
811 : GEN
812 2135 : mfvectomat(GEN vF, long lim, long d)
813 : {
814 2135 : long j, l = lg(vF);
815 2135 : GEN M = cgetg(l, t_MAT);
816 10437 : for (j = 1; j < l; j++) gel(M,j) = mftocol(gel(vF,j), lim, d);
817 2135 : return M;
818 : }
819 :
820 : static GEN
821 4893 : RgV_to_ser_full(GEN x) { return RgV_to_ser(x, 0, lg(x)+1); }
822 : /* TODO: delete */
823 : static GEN
824 679 : mfcoefsser(GEN F, long n) { return RgV_to_ser_full(mfcoefs_i(F,n,1)); }
825 : static GEN
826 847 : sertovecslice(GEN S, long n)
827 : {
828 847 : GEN v = gtovec0(S, -(lg(S) - 2 + valser(S)));
829 847 : long l = lg(v), n2 = n + 2;
830 847 : if (l < n2) pari_err_BUG("sertovecslice [n too large]");
831 847 : return (l == n2)? v: vecslice(v, 1, n2-1);
832 : }
833 :
834 : /* a, b two RgV of the same length, multiply as truncated power series */
835 : static GEN
836 8869 : RgV_mul_RgXn(GEN a, GEN b)
837 : {
838 8869 : long n = lg(a)-1;
839 : GEN c;
840 8869 : a = RgV_to_RgX(a,0);
841 8869 : b = RgV_to_RgX(b,0); c = RgXn_mul(a, b, n);
842 8869 : c = RgX_to_RgC(c,n); settyp(c,t_VEC); return c;
843 : }
844 : /* divide as truncated power series */
845 : static GEN
846 399 : RgV_div_RgXn(GEN a, GEN b)
847 : {
848 399 : long n = lg(a)-1;
849 : GEN c;
850 399 : a = RgV_to_RgX(a,0);
851 399 : b = RgV_to_RgX(b,0); c = RgXn_div_i(a, b, n);
852 399 : c = RgX_to_RgC(c,n); settyp(c,t_VEC); return c;
853 : }
854 : /* a^b */
855 : static GEN
856 112 : RgV_pows_RgXn(GEN a, long b)
857 : {
858 112 : long n = lg(a)-1;
859 : GEN c;
860 112 : a = RgV_to_RgX(a,0);
861 112 : if (b < 0) { a = RgXn_inv(a, n); b = -b; }
862 112 : c = RgXn_powu_i(a,b,n);
863 112 : c = RgX_to_RgC(c,n); settyp(c,t_VEC); return c;
864 : }
865 :
866 : /* assume lg(V) >= n*d + 2 */
867 : static GEN
868 8939 : c_deflate(long n, long d, GEN v)
869 : {
870 8939 : long i, id, l = n+2;
871 : GEN w;
872 8939 : if (d == 1) return lg(v) == l ? v: vecslice(v, 1, l-1);
873 581 : w = cgetg(l, typ(v));
874 11249 : for (i = id = 1; i < l; i++, id += d) gel(w, i) = gel(v, id);
875 581 : return w;
876 : }
877 :
878 : static void
879 14 : err_cyclo(void)
880 14 : { pari_err_IMPL("changing cyclotomic fields in mf"); }
881 : /* Q(zeta_a) = Q(zeta_b) ? */
882 : static int
883 616 : same_cyc(long a, long b)
884 616 : { return (a == b) || (odd(a) && b == (a<<1)) || (odd(b) && a == (b<<1)); }
885 : /* need to combine elements in Q(CHI1) and Q(CHI2) with result in Q(CHI),
886 : * CHI = CHI1 * CHI2 or CHI / CHI2 times some character of order 2 */
887 : static GEN
888 2835 : chicompat(GEN CHI, GEN CHI1, GEN CHI2)
889 : {
890 2835 : long o1 = mfcharorder(CHI1);
891 2835 : long o2 = mfcharorder(CHI2), O, o;
892 : GEN T1, T2, P, Po;
893 2835 : if (o1 <= 2 && o2 <= 2) return NULL;
894 623 : o = mfcharorder(CHI);
895 623 : Po = mfcharpol(CHI);
896 623 : P = mfcharpol(CHI1);
897 623 : if (o1 == o2)
898 : {
899 21 : if (o1 == o) return NULL;
900 14 : if (!same_cyc(o1,o)) err_cyclo();
901 0 : return mkvec4(P, gen_1,gen_1, Qab_trace_init(o1, o, P, Po));
902 : }
903 602 : O = ulcm(o1, o2);
904 602 : if (!same_cyc(O,o)) err_cyclo();
905 602 : if (O != o1) P = (O == o2)? mfcharpol(CHI2): polcyclo(O, varn(P));
906 602 : T1 = o1 <= 2? gen_1: utoipos(O / o1);
907 602 : T2 = o2 <= 2? gen_1: utoipos(O / o2);
908 602 : return mkvec4(P, T1, T2, O == o? gen_1: Qab_trace_init(O, o, P, Po));
909 : }
910 : static GEN
911 49 : inflatemod(GEN f, long o, GEN P)
912 : {
913 49 : f = lift_shallow(f);
914 49 : return gmodulo(typ(f)==t_POL? RgX_inflate(f,o): f, P);
915 : }
916 : static GEN
917 7 : RgV_inflatemod(GEN x, long o, GEN P)
918 56 : { pari_APPLY_same(inflatemod(gel(x,i), o, P)); }
919 : /* *F a vector of cyclotomic numbers */
920 : static void
921 651 : chicompatlift(GEN T, GEN *F, GEN *G)
922 : {
923 651 : long o1 = itou(gel(T,2)), o2 = itou(gel(T,3));
924 651 : GEN P = gel(T,1);
925 651 : if (o1 != 1) *F = RgV_inflatemod(*F, o1, P);
926 651 : if (o2 != 1 && G) *G = RgV_inflatemod(*G, o2, P);
927 651 : }
928 : static GEN
929 651 : chicompatfix(GEN T, GEN F)
930 : {
931 651 : GEN V = gel(T,4);
932 651 : if (typ(V) == t_VEC) F = gmodulo(QabV_tracerel(V, 0, F), gel(V,1));
933 651 : return F;
934 : }
935 :
936 : static GEN
937 637 : c_mul(long n, long d, GEN S)
938 : {
939 637 : pari_sp av = avma;
940 637 : long nd = n*d;
941 637 : GEN F = gel(S,2), G = gel(S,3);
942 637 : F = mfcoefs_i(F, nd, 1);
943 637 : G = mfcoefs_i(G, nd, 1);
944 637 : if (lg(S) == 5) chicompatlift(gel(S,4),&F,&G);
945 637 : F = c_deflate(n, d, RgV_mul_RgXn(F,G));
946 637 : if (lg(S) == 5) F = chicompatfix(gel(S,4), F);
947 637 : return gc_GEN(av, F);
948 : }
949 : static GEN
950 112 : c_pow(long n, long d, GEN S)
951 : {
952 112 : pari_sp av = avma;
953 112 : long nd = n*d;
954 112 : GEN F = gel(S,2), a = gel(S,3), f = mfcoefs_i(F,nd,1);
955 112 : if (lg(S) == 5) chicompatlift(gel(S,4),&F, NULL);
956 112 : f = RgV_pows_RgXn(f, itos(a));
957 112 : f = c_deflate(n, d, f);
958 112 : if (lg(S) == 5) f = chicompatfix(gel(S,4), f);
959 112 : return gc_GEN(av, f);
960 : }
961 :
962 : /* F * Theta */
963 : static GEN
964 448 : mfmultheta(GEN F)
965 : {
966 448 : if (typ(mf_get_gk(F)) == t_FRAC && mf_get_type(F) == t_MF_DIV)
967 : {
968 154 : GEN T = gel(F,3); /* hopefully mfTheta() */
969 154 : if (mf_get_type(T) == t_MF_THETA && mf_get_N(T) == 4) return gel(F,2);
970 : }
971 294 : return mfmul(F, mfTheta(NULL));
972 : }
973 :
974 : static GEN
975 42 : c_bracket(long n, long d, GEN S)
976 : {
977 42 : pari_sp av = avma;
978 42 : long i, nd = n*d;
979 42 : GEN F = gel(S,2), G = gel(S,3), tF, tG, C, mpow, res, gk, gl;
980 42 : GEN VF = mfcoefs_i(F, nd, 1);
981 42 : GEN VG = mfcoefs_i(G, nd, 1);
982 42 : ulong j, m = itou(gel(S,4));
983 :
984 42 : if (!n)
985 : {
986 14 : if (m > 0) { set_avma(av); return mkvec(gen_0); }
987 7 : return gc_GEN(av, mkvec(gmul(gel(VF, 1), gel(VG, 1))));
988 : }
989 28 : tF = cgetg(nd+2, t_VEC);
990 28 : tG = cgetg(nd+2, t_VEC);
991 28 : res = NULL; gk = mf_get_gk(F); gl = mf_get_gk(G);
992 : /* pow[i,j+1] = i^j */
993 28 : if (lg(S) == 6) chicompatlift(gel(S,5),&VF,&VG);
994 28 : mpow = cgetg(m+2, t_MAT);
995 28 : gel(mpow,1) = const_col(nd, gen_1);
996 56 : for (j = 1; j <= m; j++)
997 : {
998 28 : GEN c = cgetg(nd+1, t_COL);
999 28 : gel(mpow,j+1) = c;
1000 245 : for (i = 1; i <= nd; i++) gel(c,i) = muliu(gcoeff(mpow,i,j), i);
1001 : }
1002 28 : C = binomial(gaddgs(gk, m-1), m);
1003 28 : if (odd(m)) C = gneg(C);
1004 84 : for (j = 0; j <= m; j++)
1005 : { /* C = (-1)^(m-j) binom(m+l-1, j) binom(m+k-1,m-j) */
1006 : GEN c;
1007 56 : gel(tF,1) = j == 0? gel(VF,1): gen_0;
1008 56 : gel(tG,1) = j == m? gel(VG,1): gen_0;
1009 56 : gel(tF,2) = gel(VF,2); /* assume nd >= 1 */
1010 56 : gel(tG,2) = gel(VG,2);
1011 518 : for (i = 2; i <= nd; i++)
1012 : {
1013 462 : gel(tF, i+1) = gmul(gcoeff(mpow,i,j+1), gel(VF, i+1));
1014 462 : gel(tG, i+1) = gmul(gcoeff(mpow,i,m-j+1), gel(VG, i+1));
1015 : }
1016 56 : c = gmul(C, c_deflate(n, d, RgV_mul_RgXn(tF, tG)));
1017 56 : res = res? gadd(res, c): c;
1018 56 : if (j < m)
1019 56 : C = gdiv(gmul(C, gmulsg(m-j, gaddgs(gl,m-j-1))),
1020 28 : gmulsg(-(j+1), gaddgs(gk,j)));
1021 : }
1022 28 : if (lg(S) == 6) res = chicompatfix(gel(S,5), res);
1023 28 : return gc_upto(av, res);
1024 : }
1025 : /* linear combination \sum L[j] vecF[j] */
1026 : static GEN
1027 3024 : c_linear(long n, long d, GEN F, GEN L, GEN dL)
1028 : {
1029 3024 : pari_sp av = avma;
1030 3024 : long j, l = lg(L);
1031 3024 : GEN S = NULL;
1032 10780 : for (j = 1; j < l; j++)
1033 : {
1034 7756 : GEN c = gel(L,j);
1035 7756 : if (gequal0(c)) continue;
1036 7000 : c = gmul(c, mfcoefs_i(gel(F,j), n, d));
1037 7000 : S = S? gadd(S,c): c;
1038 : }
1039 3024 : if (!S) return zerovec(n+1);
1040 3024 : if (!is_pm1(dL)) S = gdiv(S, dL);
1041 3024 : return gc_upto(av, S);
1042 : }
1043 :
1044 : /* B_d(T_j Trace^new) as t_MF_BD(t_MF_HECKE(t_MF_NEWTRACE)) or
1045 : * t_MF_HECKE(t_MF_NEWTRACE)
1046 : * or t_MF_NEWTRACE in level N. Set d and j, return t_MF_NEWTRACE component*/
1047 : static GEN
1048 84665 : bhn_parse(GEN f, long *d, long *j)
1049 : {
1050 84665 : long t = mf_get_type(f);
1051 84665 : *d = *j = 1;
1052 84665 : if (t == t_MF_BD) { *d = itos(gel(f,3)); f = gel(f,2); t = mf_get_type(f); }
1053 84665 : if (t == t_MF_HECKE) { *j = gel(f,2)[1]; f = gel(f,3); }
1054 84665 : return f;
1055 : }
1056 : /* f as above, return the t_MF_NEWTRACE component */
1057 : static GEN
1058 34993 : bhn_newtrace(GEN f)
1059 : {
1060 34993 : long t = mf_get_type(f);
1061 34993 : if (t == t_MF_BD) { f = gel(f,2); t = mf_get_type(f); }
1062 34993 : if (t == t_MF_HECKE) f = gel(f,3);
1063 34993 : return f;
1064 : }
1065 : static int
1066 4144 : ok_bhn_linear(GEN vf)
1067 : {
1068 4144 : long i, N0 = 0, l = lg(vf);
1069 : GEN CHI, gk;
1070 4144 : if (l == 1) return 1;
1071 4144 : gk = mf_get_gk(gel(vf,1));
1072 4144 : CHI = mf_get_CHI(gel(vf,1));
1073 29792 : for (i = 1; i < l; i++)
1074 : {
1075 28007 : GEN f = bhn_newtrace(gel(vf,i));
1076 28007 : long N = mf_get_N(f);
1077 28007 : if (mf_get_type(f) != t_MF_NEWTRACE) return 0;
1078 25648 : if (N < N0) return 0; /* largest level must come last */
1079 25648 : N0 = N;
1080 25648 : if (!gequal(gk,mf_get_gk(f))) return 0; /* same k */
1081 25648 : if (!gequal(gel(mf_get_CHI(f),2), gel(CHI,2))) return 0; /* same CHI */
1082 : }
1083 1785 : return 1;
1084 : }
1085 :
1086 : /* vF not empty, same hypotheses as bhnmat_extend */
1087 : static GEN
1088 7091 : bhnmat_extend_nocache(GEN M, long N, long n, long d, GEN vF)
1089 : {
1090 : cachenew_t cache;
1091 7091 : long l = lg(vF);
1092 : GEN f;
1093 7091 : if (l == 1) return M? M: cgetg(1, t_MAT);
1094 6986 : f = bhn_newtrace(gel(vF,1)); /* N.B. mf_get_N(f) divides N */
1095 6986 : init_cachenew(&cache, n*d, N, f);
1096 6986 : M = bhnmat_extend(M, n, d, vF, &cache);
1097 6986 : dbg_cachenew(&cache); return M;
1098 : }
1099 : /* c_linear of "bhn" mf closures, same hypotheses as bhnmat_extend */
1100 : static GEN
1101 2331 : c_linear_bhn(long n, long d, GEN F)
1102 : {
1103 : pari_sp av;
1104 2331 : GEN M, v, vF = gel(F,2), L = gel(F,3), dL = gel(F,4);
1105 2331 : if (lg(L) == 1) return zerovec(n+1);
1106 2331 : av = avma;
1107 2331 : M = bhnmat_extend_nocache(NULL, mf_get_N(F), n, d, vF);
1108 2331 : v = RgM_RgC_mul(M,L); settyp(v, t_VEC);
1109 2331 : if (!is_pm1(dL)) v = gdiv(v, dL);
1110 2331 : return gc_upto(av, v);
1111 : }
1112 :
1113 : /* c in K, K := Q[X]/(T) vz = vector of consecutive powers of root z of T
1114 : * attached to an embedding s: K -> C. Return s(c) in C */
1115 : static GEN
1116 84686 : Rg_embed1(GEN c, GEN vz)
1117 : {
1118 84686 : long t = typ(c);
1119 84686 : if (t == t_POLMOD) { c = gel(c,2); t = typ(c); }
1120 84686 : if (t == t_POL) c = RgX_RgV_eval(c, vz);
1121 84686 : return c;
1122 : }
1123 : /* return s(x) in C[X] */
1124 : static GEN
1125 13489 : RgX_embed1(GEN x, GEN vz)
1126 40698 : { pari_APPLY_pol(Rg_embed1(gel(x,i), vz)); }
1127 : /* return s(x) in C^n */
1128 : static GEN
1129 798 : vecembed1(GEN x, GEN vz)
1130 39858 : { pari_APPLY_same(Rg_embed1(gel(x,i), vz)); }
1131 : /* P in L = K[X]/(U), K = Q[t]/T; s an embedding of K -> C attached
1132 : * to a root of T, extended to an embedding of L -> C attached to a root
1133 : * of s(U); vT powers of the root of T, vU powers of the root of s(U).
1134 : * Return s(P) in C^n */
1135 : static GEN
1136 13328 : Rg_embed2(GEN P, long vt, GEN vT, GEN vU)
1137 : {
1138 13328 : P = liftpol_shallow(P);
1139 13328 : if (typ(P) != t_POL) return P;
1140 13272 : if (varn(P) == vt) return Rg_embed1(P, vT);
1141 13265 : return Rg_embed1(RgX_embed1(P, vT), vU); /* varn(P) == vx */
1142 : }
1143 : static GEN
1144 42 : vecembed2(GEN x, long vt, GEN vT, GEN vU)
1145 1050 : { pari_APPLY_same(Rg_embed2(gel(x,i), vt, vT, vU)); }
1146 : static GEN
1147 532 : RgX_embed2(GEN x, long vt, GEN vT, GEN vU)
1148 3724 : { pari_APPLY_pol(Rg_embed2(gel(x,i), vt, vT, vU)); }
1149 : /* embed polynomial f in variable 0 [ may be a scalar ], E from getembed */
1150 : static GEN
1151 1687 : RgX_embed(GEN f, GEN E)
1152 : {
1153 : GEN vT;
1154 1687 : if (typ(f) != t_POL || varn(f) != 0) return mfembed(E, f);
1155 945 : if (lg(E) == 1) return f;
1156 721 : vT = gel(E,2);
1157 721 : if (lg(E) == 3)
1158 189 : f = RgX_embed1(f, vT);
1159 : else
1160 532 : f = RgX_embed2(f, varn(gel(E,1)), vT, gel(E,3));
1161 721 : return f;
1162 : }
1163 : /* embed vector, E from getembed */
1164 : GEN
1165 1743 : mfvecembed(GEN E, GEN v)
1166 : {
1167 : GEN vT;
1168 1743 : if (lg(E) == 1) return v;
1169 840 : vT = gel(E,2);
1170 840 : if (lg(E) == 3)
1171 798 : v = vecembed1(v, vT);
1172 : else
1173 42 : v = vecembed2(v, varn(gel(E,1)), vT, gel(E,3));
1174 840 : return v;
1175 : }
1176 : GEN
1177 70 : mfmatembed(GEN E, GEN x)
1178 : {
1179 70 : if (lg(E) == 1) return x;
1180 168 : pari_APPLY_same(mfvecembed(E, gel(x,i)));
1181 : }
1182 : /* embed vector of polynomials in var 0 */
1183 : static GEN
1184 98 : RgXV_embed(GEN x, GEN E)
1185 : {
1186 98 : if (lg(E) == 1) return x;
1187 1358 : pari_APPLY_same(RgX_embed(gel(x,i), E));
1188 : }
1189 :
1190 : /* embed scalar */
1191 : GEN
1192 101545 : mfembed(GEN E, GEN f)
1193 : {
1194 : GEN vT;
1195 101545 : if (lg(E) == 1) return f;
1196 14273 : vT = gel(E,2);
1197 14273 : if (lg(E) == 3)
1198 5145 : f = Rg_embed1(f, vT);
1199 : else
1200 9128 : f = Rg_embed2(f, varn(gel(E,1)), vT, gel(E,3));
1201 14273 : return f;
1202 : }
1203 : /* vector of the sigma(f), sigma in vE */
1204 : static GEN
1205 364 : RgX_embedall(GEN f, GEN vE)
1206 : {
1207 364 : long i, l = lg(vE);
1208 : GEN v;
1209 364 : if (l == 2) return RgX_embed(f, gel(vE,1));
1210 35 : v = cgetg(l, t_VEC);
1211 105 : for (i = 1; i < l; i++) gel(v,i) = RgX_embed(f, gel(vE,i));
1212 35 : return v;
1213 : }
1214 : /* matrix whose colums are the sigma(v), sigma in vE */
1215 : static GEN
1216 350 : RgC_embedall(GEN v, GEN vE)
1217 : {
1218 350 : long j, l = lg(vE);
1219 350 : GEN M = cgetg(l, t_MAT);
1220 875 : for (j = 1; j < l; j++) gel(M,j) = mfvecembed(gel(vE,j), v);
1221 350 : return M;
1222 : }
1223 : /* vector of the sigma(v), sigma in vE */
1224 : static GEN
1225 4907 : Rg_embedall_i(GEN v, GEN vE)
1226 : {
1227 4907 : long j, l = lg(vE);
1228 4907 : GEN M = cgetg(l, t_VEC);
1229 14735 : for (j = 1; j < l; j++) gel(M,j) = mfembed(gel(vE,j), v);
1230 4907 : return M;
1231 : }
1232 : /* vector of the sigma(v), sigma in vE; if #vE == 1, return v */
1233 : static GEN
1234 95154 : Rg_embedall(GEN v, GEN vE)
1235 95154 : { return (lg(vE) == 2)? mfembed(gel(vE,1), v): Rg_embedall_i(v, vE); }
1236 :
1237 : static GEN
1238 847 : c_div_i(long n, GEN S)
1239 : {
1240 847 : GEN F = gel(S,2), G = gel(S,3);
1241 : GEN a0, a0i, H;
1242 847 : F = mfcoefs_i(F, n, 1);
1243 847 : G = mfcoefs_i(G, n, 1);
1244 847 : if (lg(S) == 5) chicompatlift(gel(S,4),&F,&G);
1245 847 : F = RgV_to_ser_full(F);
1246 847 : G = RgV_to_ser_full(G);
1247 847 : a0 = polcoef_i(G, 0, -1); /* != 0 */
1248 847 : if (gequal1(a0)) a0 = a0i = NULL;
1249 : else
1250 : {
1251 602 : a0i = ginv(a0);
1252 602 : G = gmul(ser_unscale(G,a0), a0i);
1253 602 : F = gmul(ser_unscale(F,a0), a0i);
1254 : }
1255 847 : H = gdiv(F, G);
1256 847 : if (a0) H = ser_unscale(H,a0i);
1257 847 : H = sertovecslice(H, n);
1258 847 : if (lg(S) == 5) H = chicompatfix(gel(S,4), H);
1259 847 : return H;
1260 : }
1261 : static GEN
1262 847 : c_div(long n, long d, GEN S)
1263 : {
1264 847 : pari_sp av = avma;
1265 847 : GEN D = (d==1)? c_div_i(n, S): c_deflate(n, d, c_div_i(n*d, S));
1266 847 : return gc_GEN(av, D);
1267 : }
1268 :
1269 : static GEN
1270 35 : c_shift(long n, long d, GEN F, GEN gsh)
1271 : {
1272 35 : pari_sp av = avma;
1273 : GEN vF;
1274 35 : long sh = itos(gsh), n1 = n*d + sh;
1275 35 : if (n1 < 0) return zerovec(n+1);
1276 35 : vF = mfcoefs_i(F, n1, 1);
1277 35 : if (sh < 0) vF = shallowconcat(zerovec(-sh), vF);
1278 35 : else vF = vecslice(vF, sh+1, n1+1);
1279 35 : return gc_GEN(av, c_deflate(n, d, vF));
1280 : }
1281 :
1282 : static GEN
1283 175 : c_deriv(long n, long d, GEN F, GEN gm)
1284 : {
1285 175 : pari_sp av = avma;
1286 175 : GEN V = mfcoefs_i(F, n, d), res;
1287 175 : long i, m = itos(gm);
1288 175 : if (!m) return V;
1289 175 : res = cgetg(n+2, t_VEC); gel(res,1) = gen_0;
1290 175 : if (m < 0)
1291 49 : { for (i=1; i <= n; i++) gel(res, i+1) = gdiv(gel(V, i+1), powuu(i,-m)); }
1292 : else
1293 2457 : { for (i=1; i <= n; i++) gel(res, i+1) = gmul(gel(V,i+1), powuu(i,m)); }
1294 175 : return gc_upto(av, res);
1295 : }
1296 :
1297 : static GEN
1298 14 : c_derivE2(long n, long d, GEN F, GEN gm)
1299 : {
1300 14 : pari_sp av = avma;
1301 : GEN VF, VE, res, tmp, gk;
1302 14 : long i, m = itos(gm), nd;
1303 14 : if (m == 0) return mfcoefs_i(F, n, d);
1304 14 : nd = n*d;
1305 14 : VF = mfcoefs_i(F, nd, 1); VE = mfcoefs_i(mfEk(2), nd, 1);
1306 14 : gk = mf_get_gk(F);
1307 14 : if (m == 1)
1308 : {
1309 7 : res = cgetg(n+2, t_VEC);
1310 56 : for (i = 0; i <= n; i++) gel(res, i+1) = gmulsg(i, gel(VF, i*d+1));
1311 7 : tmp = c_deflate(n, d, RgV_mul_RgXn(VF, VE));
1312 7 : return gc_upto(av, gsub(res, gmul(gdivgu(gk, 12), tmp)));
1313 : }
1314 : else
1315 : {
1316 : long j;
1317 35 : for (j = 1; j <= m; j++)
1318 : {
1319 28 : tmp = RgV_mul_RgXn(VF, VE);
1320 140 : for (i = 0; i <= nd; i++) gel(VF, i+1) = gmulsg(i, gel(VF, i+1));
1321 28 : VF = gsub(VF, gmul(gdivgu(gaddgs(gk, 2*(j-1)), 12), tmp));
1322 : }
1323 7 : return gc_GEN(av, c_deflate(n, d, VF));
1324 : }
1325 : }
1326 :
1327 : /* Twist by the character (D/.) */
1328 : static GEN
1329 168 : c_twist(long n, long d, GEN F, GEN D)
1330 : {
1331 168 : pari_sp av = avma;
1332 168 : GEN v = mfcoefs_i(F, n, d), z = cgetg(n+2, t_VEC);
1333 : long i;
1334 994 : for (i = 0; i <= n; i++)
1335 : {
1336 : long s;
1337 826 : GEN a = gel(v, i+1);
1338 826 : if (d == 1) s = krois(D, i);
1339 : else
1340 : {
1341 266 : pari_sp av2 = avma;
1342 266 : s = kronecker(D, muluu(i, d)); set_avma(av2);
1343 : }
1344 826 : switch(s)
1345 : {
1346 259 : case 1: a = gcopy(a); break;
1347 252 : case -1: a = gneg(a); break;
1348 315 : default: a = gen_0; break;
1349 : }
1350 826 : gel(z, i+1) = a;
1351 : }
1352 168 : return gc_upto(av, z);
1353 : }
1354 :
1355 : /* form F given by closure, compute T(n)(F) as closure */
1356 : static GEN
1357 1246 : c_hecke(long m, long l, GEN DATA, GEN F)
1358 : {
1359 1246 : pari_sp av = avma;
1360 1246 : return gc_GEN(av, hecke_i(m, l, NULL, F, DATA));
1361 : }
1362 : static GEN
1363 147 : c_const(long n, long d, GEN C)
1364 : {
1365 147 : GEN V = zerovec(n+1);
1366 147 : long i, j, l = lg(C);
1367 147 : if (l > d*n+2) l = d*n+2;
1368 196 : for (i = j = 1; i < l; i+=d, j++) gel(V, j) = gcopy(gel(C,i));
1369 147 : return V;
1370 : }
1371 :
1372 : /* m > 0 */
1373 : static GEN
1374 525 : eta3_ZXn(long m)
1375 : {
1376 525 : long l = m+2, n, k;
1377 525 : GEN P = cgetg(l,t_POL);
1378 525 : P[1] = evalsigne(1)|evalvarn(0);
1379 7245 : for (n = 2; n < l; n++) gel(P,n) = gen_0;
1380 525 : for (n = k = 0;; n++)
1381 : {
1382 2891 : if (k + n >= m) { setlg(P, k+3); return P; }
1383 2366 : k += n;
1384 : /* now k = n(n+1) / 2 */
1385 2366 : gel(P, k+2) = odd(n)? utoineg(2*n+1): utoipos(2*n+1);
1386 : }
1387 : }
1388 :
1389 : static GEN
1390 539 : c_delta(long n, long d)
1391 : {
1392 539 : pari_sp ltop = avma;
1393 539 : long N = n*d;
1394 : GEN e;
1395 539 : if (!N) return mkvec(gen_0);
1396 525 : e = eta3_ZXn(N);
1397 525 : e = ZXn_sqr(e,N);
1398 525 : e = ZXn_sqr(e,N);
1399 525 : e = ZXn_sqr(e,N); /* eta(x)^24 */
1400 525 : settyp(e, t_VEC);
1401 525 : gel(e,1) = gen_0; /* Delta(x) = x*eta(x)^24 as a t_VEC */
1402 525 : return gc_GEN(ltop, c_deflate(n, d, e));
1403 : }
1404 :
1405 : /* return s(d) such that s|f <=> d | f^2 */
1406 : static long
1407 56 : mysqrtu(ulong d)
1408 : {
1409 56 : GEN fa = myfactoru(d), P = gel(fa,1), E = gel(fa,2);
1410 56 : long l = lg(P), i, s = 1;
1411 140 : for (i = 1; i < l; i++) s *= upowuu(P[i], (E[i]+1)>>1);
1412 56 : return s;
1413 : }
1414 : static GEN
1415 1946 : c_theta(long n, long d, GEN psi)
1416 : {
1417 1946 : long lim = usqrt(n*d), F = mfcharmodulus(psi), par = mfcharparity(psi);
1418 1946 : long f, d2 = d == 1? 1: mysqrtu(d);
1419 1946 : GEN V = zerovec(n + 1);
1420 8722 : for (f = d2; f <= lim; f += d2)
1421 6776 : if (ugcd(F, f) == 1)
1422 : {
1423 6769 : pari_sp av = avma;
1424 6769 : GEN c = mfchareval(psi, f);
1425 6769 : gel(V, f*f/d + 1) = gc_upto(av, par < 0? gmulgu(c,2*f): gmul2n(c,1));
1426 : }
1427 1946 : if (F == 1) gel(V, 1) = gen_1;
1428 1946 : return V; /* no GC needed */
1429 : }
1430 :
1431 : static GEN
1432 203 : c_etaquo(long n, long d, GEN eta, GEN gs)
1433 : {
1434 203 : pari_sp av = avma;
1435 203 : long s = itos(gs), nd = n*d, nds = nd - s + 1;
1436 : GEN c;
1437 203 : if (nds <= 0) return zerovec(n+1);
1438 182 : c = RgX_to_RgC(eta_product_ZXn(eta, nds), nds); settyp(c, t_VEC);
1439 182 : if (s > 0) c = shallowconcat(zerovec(s), c);
1440 182 : return gc_GEN(av, c_deflate(n, d, c));
1441 : }
1442 :
1443 : static GEN
1444 77 : c_ell(long n, long d, GEN E)
1445 : {
1446 77 : pari_sp av = avma;
1447 : GEN v;
1448 77 : if (d == 1) return gconcat(gen_0, ellan(E, n));
1449 7 : v = vec_prepend(ellan(E, n*d), gen_0);
1450 7 : return gc_GEN(av, c_deflate(n, d, v));
1451 : }
1452 :
1453 : static GEN
1454 21 : c_cusptrace(long n, long d, GEN F)
1455 : {
1456 21 : pari_sp av = avma;
1457 21 : GEN D = gel(F,2), res = cgetg(n+2, t_VEC);
1458 21 : long i, N = mf_get_N(F), k = mf_get_k(F);
1459 21 : gel(res, 1) = gen_0;
1460 140 : for (i = 1; i <= n; i++)
1461 119 : gel(res, i+1) = mfcusptrace_i(N, k, i*d, mydivisorsu(i*d), D);
1462 21 : return gc_GEN(av, res);
1463 : }
1464 :
1465 : static GEN
1466 1918 : c_newtrace(long n, long d, GEN F)
1467 : {
1468 1918 : pari_sp av = avma;
1469 : cachenew_t cache;
1470 1918 : long N = mf_get_N(F);
1471 : GEN v;
1472 1918 : init_cachenew(&cache, n == 1? 1: n*d, N, F);
1473 1918 : v = colnewtrace(0, n, d, N, mf_get_k(F), &cache);
1474 1918 : settyp(v, t_VEC); return gc_GEN(av, v);
1475 : }
1476 :
1477 : static GEN
1478 7525 : c_Bd(long n, long d, GEN F, GEN A)
1479 : {
1480 7525 : pari_sp av = avma;
1481 7525 : long a = itou(A), ad = ugcd(a,d), aad = a/ad, i, j;
1482 7525 : GEN w, v = mfcoefs_i(F, n/aad, d/ad);
1483 7525 : if (a == 1) return v;
1484 7525 : n++; w = zerovec(n);
1485 213416 : for (i = j = 1; j <= n; i++, j += aad) gel(w,j) = gcopy(gel(v,i));
1486 7525 : return gc_upto(av, w);
1487 : }
1488 :
1489 : static GEN
1490 5579 : c_dihedral(long n, long d, GEN F)
1491 : {
1492 5579 : pari_sp av = avma;
1493 5579 : GEN CHI = mf_get_CHI(F);
1494 5579 : GEN w = gel(F,3), V = dihan(gel(F,2), w, gel(F,4), mfcharorder(CHI), n*d);
1495 5579 : GEN Tinit = gel(w,3), Pm = gel(Tinit,1);
1496 5579 : GEN A = c_deflate(n, d, V);
1497 5579 : if (degpol(Pm) == 1 || RgV_is_ZV(A)) return gc_GEN(av, A);
1498 1043 : return gc_upto(av, gmodulo(A, Pm));
1499 : }
1500 :
1501 : static GEN
1502 343 : c_mfEH(long n, long d, GEN F)
1503 : {
1504 343 : pari_sp av = avma;
1505 : GEN v, M, A;
1506 343 : long i, r = mf_get_r(F);
1507 343 : if (n == 1)
1508 14 : return gc_GEN(av, mkvec2(mfEHcoef(r,0),mfEHcoef(r,d)));
1509 : /* speedup mfcoef */
1510 329 : if (r == 1)
1511 : {
1512 70 : v = cgetg(n+2, t_VEC);
1513 70 : gel(v,1) = sstoQ(-1,12);
1514 83258 : for (i = 1; i <= n; i++)
1515 : {
1516 83188 : long id = i*d, a = id & 3;
1517 83188 : gel(v,i+1) = (a==1 || a==2)? gen_0: uutoQ(hclassno6u(id), 6);
1518 : }
1519 70 : return v; /* no GC needed */
1520 : }
1521 259 : M = mfEHmat(n*d+1,r);
1522 259 : if (d > 1)
1523 : {
1524 35 : long l = lg(M);
1525 119 : for (i = 1; i < l; i++) gel(M,i) = c_deflate(n, d, gel(M,i));
1526 : }
1527 259 : A = gel(F,2); /* [num(B), den(B)] */
1528 259 : v = RgC_Rg_div(RgM_RgC_mul(M, gel(A,1)), gel(A,2));
1529 259 : settyp(v,t_VEC); return gc_upto(av, v);
1530 : }
1531 :
1532 : static GEN
1533 11361 : c_mfeisen(long n, long d, GEN F)
1534 : {
1535 11361 : pari_sp av = avma;
1536 11361 : GEN v, vchi, E0, P, T, CHI, gk = mf_get_gk(F);
1537 : long i, k;
1538 11361 : if (typ(gk) != t_INT) return c_mfEH(n, d, F);
1539 11018 : k = itou(gk);
1540 11018 : vchi = gel(F,2);
1541 11018 : E0 = gel(vchi,1);
1542 11018 : T = gel(vchi,2);
1543 11018 : P = gel(T,1);
1544 11018 : CHI = gel(vchi,3);
1545 11018 : v = cgetg(n+2, t_VEC);
1546 11018 : gel(v, 1) = gcopy(E0); /* E(0) */
1547 11018 : if (lg(vchi) == 5)
1548 : { /* E_k(chi1,chi2) */
1549 8925 : GEN CHI2 = gel(vchi,4), F3 = gel(F,3);
1550 8925 : long ord = F3[1], j = F3[2];
1551 509670 : for (i = 1; i <= n; i++) gel(v, i+1) = sigchi2(k, CHI, CHI2, i*d, ord);
1552 8925 : v = QabV_tracerel(T, j, v);
1553 : }
1554 : else
1555 : { /* E_k(chi) */
1556 26285 : for (i = 1; i <= n; i++) gel(v, i+1) = sigchi(k, CHI, i*d);
1557 : }
1558 11018 : if (degpol(P) != 1 && !RgV_is_QV(v)) return gc_upto(av, gmodulo(v, P));
1559 8085 : return gc_GEN(av, v);
1560 : }
1561 :
1562 : /* N^k * (D * B_k)(x/N), set D = denom(B_k) */
1563 : static GEN
1564 2023 : bern_init(long N, long k, GEN *pD)
1565 2023 : { return ZX_rescale(Q_remove_denom(bernpol(k, 0), pD), utoi(N)); }
1566 :
1567 : /* L(chi_D, 1-k) */
1568 : static GEN
1569 28 : lfunquadneg_naive(long D, long k)
1570 : {
1571 : GEN B, dS, S;
1572 28 : long r, N = labs(D);
1573 : pari_sp av;
1574 28 : if (k == 1 && N == 1) return gneg(ghalf);
1575 28 : B = bern_init(N, k, &dS);
1576 28 : dS = mul_denom(dS, stoi(-N*k));
1577 28 : av = avma;
1578 7175 : for (r = 0, S = gen_0; r < N; r++)
1579 : {
1580 7147 : long c = kross(D, r);
1581 7147 : if (c)
1582 : {
1583 5152 : GEN t = ZX_Z_eval(B, utoi(r));
1584 5152 : S = c > 0 ? addii(S, t) : subii(S, t);
1585 5152 : S = gc_INT(av, S);
1586 : }
1587 : }
1588 28 : return gdiv(S, dS);
1589 : }
1590 :
1591 : /* Returns vector of coeffs from F[0], F[d], ..., F[d*n] */
1592 : static GEN
1593 38563 : mfcoefs_i(GEN F, long n, long d)
1594 : {
1595 38563 : if (n < 0) return gen_0;
1596 38563 : switch(mf_get_type(F))
1597 : {
1598 147 : case t_MF_CONST: return c_const(n, d, gel(F,2));
1599 11361 : case t_MF_EISEN: return c_mfeisen(n, d, F);
1600 882 : case t_MF_Ek: return c_Ek(n, d, F);
1601 539 : case t_MF_DELTA: return c_delta(n, d);
1602 1680 : case t_MF_THETA: return c_theta(n, d, gel(F,2));
1603 203 : case t_MF_ETAQUO: return c_etaquo(n, d, gel(F,2), gel(F,3));
1604 77 : case t_MF_ELL: return c_ell(n, d, gel(F,2));
1605 637 : case t_MF_MUL: return c_mul(n, d, F);
1606 112 : case t_MF_POW: return c_pow(n, d, F);
1607 42 : case t_MF_BRACKET: return c_bracket(n, d, F);
1608 3024 : case t_MF_LINEAR: return c_linear(n, d, gel(F,2), gel(F,3), gel(F,4));
1609 2331 : case t_MF_LINEAR_BHN: return c_linear_bhn(n, d, F);
1610 847 : case t_MF_DIV: return c_div(n, d, F);
1611 35 : case t_MF_SHIFT: return c_shift(n, d, gel(F,2), gel(F,3));
1612 175 : case t_MF_DERIV: return c_deriv(n, d, gel(F,2), gel(F,3));
1613 14 : case t_MF_DERIVE2: return c_derivE2(n, d, gel(F,2), gel(F,3));
1614 168 : case t_MF_TWIST: return c_twist(n, d, gel(F,2), gel(F,3));
1615 1246 : case t_MF_HECKE: return c_hecke(n, d, gel(F,2), gel(F,3));
1616 7525 : case t_MF_BD: return c_Bd(n, d, gel(F,2), gel(F,3));
1617 21 : case t_MF_TRACE: return c_cusptrace(n, d, F);
1618 1918 : case t_MF_NEWTRACE: return c_newtrace(n, d, F);
1619 5579 : case t_MF_DIHEDRAL: return c_dihedral(n, d, F);
1620 : default: pari_err_TYPE("mfcoefs",F); return NULL;/*LCOV_EXCL_LINE*/
1621 : }
1622 : }
1623 :
1624 : static GEN
1625 392 : matdeflate(long n, long d, GEN x)
1626 1680 : { pari_APPLY_same(c_deflate(n,d,gel(x,i))); }
1627 : static int
1628 6104 : space_is_cusp(long space) { return space != mf_FULL && space != mf_EISEN; }
1629 : /* safe with flraw mf */
1630 : static GEN
1631 2632 : mfcoefs_mf(GEN mf, long n, long d)
1632 : {
1633 2632 : GEN MS, ME, E = MF_get_E(mf), S = MF_get_S(mf), M = MF_get_M(mf);
1634 2632 : long lE = lg(E), lS = lg(S), l = lE+lS-1;
1635 :
1636 2632 : if (l == 1) return cgetg(1, t_MAT);
1637 2520 : if (typ(M) == t_MAT && lg(M) != 1 && (n+1)*d < nbrows(M))
1638 21 : return matdeflate(n, d, M); /*cached; lg = 1 is possible from mfinit */
1639 2499 : ME = (lE == 1)? cgetg(1, t_MAT): mfvectomat(E, n, d);
1640 2499 : if (lS == 1)
1641 455 : MS = cgetg(1, t_MAT);
1642 2044 : else if (mf_get_type(gel(S,1)) == t_MF_DIV) /*k 1/2-integer or k=1 (exotic)*/
1643 371 : MS = matdeflate(n,d, mflineardivtomat(MF_get_N(mf), S, n*d));
1644 1673 : else if (MF_get_k(mf) == 1) /* k = 1 (dihedral) */
1645 : {
1646 308 : GEN M = mfvectomat(gmael(S,1,2), n, d);
1647 : long i;
1648 308 : MS = cgetg(lS, t_MAT);
1649 1589 : for (i = 1; i < lS; i++)
1650 : {
1651 1281 : GEN f = gel(S,i), dc = gel(f,4), c = RgM_RgC_mul(M, gel(f,3));
1652 1281 : if (!equali1(dc)) c = RgC_Rg_div(c,dc);
1653 1281 : gel(MS,i) = c;
1654 : }
1655 : }
1656 : else /* k >= 2 integer */
1657 1365 : MS = bhnmat_extend_nocache(NULL, MF_get_N(mf), n, d, S);
1658 2499 : return shallowconcat(ME,MS);
1659 : }
1660 : GEN
1661 4144 : mfcoefs(GEN F, long n, long d)
1662 : {
1663 4144 : if (!checkmf_i(F))
1664 : {
1665 42 : pari_sp av = avma;
1666 42 : GEN mf = checkMF_i(F); if (!mf) pari_err_TYPE("mfcoefs", F);
1667 42 : return gc_GEN(av, mfcoefs_mf(mf,n,d));
1668 : }
1669 4102 : if (d <= 0) pari_err_DOMAIN("mfcoefs", "d", "<=", gen_0, stoi(d));
1670 4102 : if (n < 0) return cgetg(1, t_VEC);
1671 4102 : return mfcoefs_i(F, n, d);
1672 : }
1673 :
1674 : /* assume k >= 0 */
1675 : static GEN
1676 455 : mfak_i(GEN F, long k)
1677 : {
1678 455 : if (!k) return gel(mfcoefs_i(F,0,1), 1);
1679 294 : return gel(mfcoefs_i(F,1,k), 2);
1680 : }
1681 : GEN
1682 301 : mfcoef(GEN F, long n)
1683 : {
1684 301 : pari_sp av = avma;
1685 301 : if (!checkmf_i(F)) pari_err_TYPE("mfcoef",F);
1686 301 : return n < 0? gen_0: gc_GEN(av, mfak_i(F, n));
1687 : }
1688 :
1689 : static GEN
1690 133 : paramconst() { return tagparams(t_MF_CONST, mkNK(1,0,mfchartrivial())); }
1691 : static GEN
1692 91 : mftrivial(void) { retmkvec2(paramconst(), cgetg(1,t_VEC)); }
1693 : static GEN
1694 42 : mf1(void) { retmkvec2(paramconst(), mkvec(gen_1)); }
1695 :
1696 : /* induce mfchar CHI to G */
1697 : static GEN
1698 312179 : induce(GEN G, GEN CHI)
1699 : {
1700 : GEN o, chi;
1701 312179 : if (typ(CHI) == t_INT) /* Kronecker */
1702 : {
1703 300888 : chi = znchar_quad(G, CHI);
1704 300888 : o = ZV_equal0(chi)? gen_1: gen_2;
1705 300888 : CHI = mkvec4(G,chi,o,cgetg(1,t_VEC));
1706 : }
1707 : else
1708 : {
1709 11291 : if (mfcharmodulus(CHI) == itos(znstar_get_N(G))) return CHI;
1710 10640 : CHI = leafcopy(CHI);
1711 10640 : chi = zncharinduce(gel(CHI,1), gel(CHI,2), G);
1712 10640 : gel(CHI,1) = G;
1713 10640 : gel(CHI,2) = chi;
1714 : }
1715 311528 : return CHI;
1716 : }
1717 : /* induce mfchar CHI to znstar(N) */
1718 : static GEN
1719 42476 : induceN(long N, GEN CHI)
1720 : {
1721 42476 : if (mfcharmodulus(CHI) != N) CHI = induce(znstar0(utoipos(N),1), CHI);
1722 42476 : return CHI;
1723 : }
1724 : /* *pCHI1 and *pCHI2 are mfchar, induce to common modulus */
1725 : static void
1726 11305 : char2(GEN *pCHI1, GEN *pCHI2)
1727 : {
1728 11305 : GEN CHI1 = *pCHI1, G1 = gel(CHI1,1), N1 = znstar_get_N(G1);
1729 11305 : GEN CHI2 = *pCHI2, G2 = gel(CHI2,1), N2 = znstar_get_N(G2);
1730 11305 : if (!equalii(N1,N2))
1731 : {
1732 8855 : GEN G, d = gcdii(N1,N2);
1733 8855 : if (equalii(N2,d)) *pCHI2 = induce(G1, CHI2);
1734 1589 : else if (equalii(N1,d)) *pCHI1 = induce(G2, CHI1);
1735 : else
1736 : {
1737 154 : if (!equali1(d)) N2 = diviiexact(N2,d);
1738 154 : G = znstar0(mulii(N1,N2), 1);
1739 154 : *pCHI1 = induce(G, CHI1);
1740 154 : *pCHI2 = induce(G, CHI2);
1741 : }
1742 : }
1743 11305 : }
1744 : /* mfchar or charinit wrt same modulus; outputs a mfchar */
1745 : static GEN
1746 301994 : mfcharmul_i(GEN CHI1, GEN CHI2)
1747 : {
1748 301994 : GEN G = gel(CHI1,1), chi3 = zncharmul(G, gel(CHI1,2), gel(CHI2,2));
1749 301994 : return mfcharGL(G, chi3);
1750 : }
1751 : /* mfchar or charinit; outputs a mfchar */
1752 : static GEN
1753 1127 : mfcharmul(GEN CHI1, GEN CHI2)
1754 : {
1755 1127 : char2(&CHI1, &CHI2); return mfcharmul_i(CHI1,CHI2);
1756 : }
1757 : /* mfchar or charinit; outputs a mfchar */
1758 : static GEN
1759 161 : mfcharpow(GEN CHI, GEN n)
1760 : {
1761 : GEN G, chi;
1762 161 : G = gel(CHI,1); chi = zncharpow(G, gel(CHI,2), n);
1763 161 : return mfchartoprimitive(mfcharGL(G, chi), NULL);
1764 : }
1765 : /* mfchar or charinit wrt same modulus; outputs a mfchar */
1766 : static GEN
1767 10178 : mfchardiv_i(GEN CHI1, GEN CHI2)
1768 : {
1769 10178 : GEN G = gel(CHI1,1), chi3 = znchardiv(G, gel(CHI1,2), gel(CHI2,2));
1770 10178 : return mfcharGL(G, chi3);
1771 : }
1772 : /* mfchar or charinit; outputs a mfchar */
1773 : static GEN
1774 10178 : mfchardiv(GEN CHI1, GEN CHI2)
1775 : {
1776 10178 : char2(&CHI1, &CHI2); return mfchardiv_i(CHI1,CHI2);
1777 : }
1778 : static GEN
1779 56 : mfcharconj(GEN CHI)
1780 : {
1781 56 : CHI = leafcopy(CHI);
1782 56 : gel(CHI,2) = zncharconj(gel(CHI,1), gel(CHI,2));
1783 56 : return CHI;
1784 : }
1785 :
1786 : /* CHI mfchar, assume 4 | N. Multiply CHI by \chi_{-4} */
1787 : static GEN
1788 1092 : mfchilift(GEN CHI, long N)
1789 : {
1790 1092 : CHI = induceN(N, CHI);
1791 1092 : return mfcharmul_i(CHI, induce(gel(CHI,1), stoi(-4)));
1792 : }
1793 : /* CHI defined mod N, N4 = N/4;
1794 : * if CHI is defined mod N4 return CHI;
1795 : * else if CHI' = CHI*(-4,.) is defined mod N4, return CHI' (primitive)
1796 : * else error */
1797 : static GEN
1798 42 : mfcharchiliftprim(GEN CHI, long N4)
1799 : {
1800 42 : long FC = mfcharconductor(CHI);
1801 : GEN CHIP;
1802 42 : if (N4 % FC == 0) return CHI;
1803 14 : CHIP = mfchartoprimitive(mfchilift(CHI, N4 << 2), &FC);
1804 14 : if (N4 % FC) pari_err_TYPE("mfkohnenbasis [incorrect CHI]", CHI);
1805 14 : return CHIP;
1806 : }
1807 : /* ensure CHI(-1) = (-1)^k [k integer] or 1 [half-integer], by multiplying
1808 : * by (-4/.) if needed */
1809 : static GEN
1810 2933 : mfchiadjust(GEN CHI, GEN gk, long N)
1811 : {
1812 2933 : long par = mfcharparity(CHI);
1813 2933 : if (typ(gk) == t_INT && mpodd(gk)) par = -par;
1814 2933 : return par == 1 ? CHI : mfchilift(CHI, N);
1815 : }
1816 :
1817 : static GEN
1818 4270 : mfsamefield(GEN T, GEN P, GEN Q)
1819 : {
1820 4270 : if (degpol(P) == 1) return Q;
1821 721 : if (degpol(Q) == 1) return P;
1822 630 : if (!gequal(P,Q)) pari_err_TYPE("mfsamefield [different fields]",mkvec2(P,Q));
1823 623 : if (T) err_cyclo();
1824 623 : return P;
1825 : }
1826 :
1827 : GEN
1828 455 : mfmul(GEN f, GEN g)
1829 : {
1830 455 : pari_sp av = avma;
1831 : GEN T, N, K, NK, CHI, CHIf, CHIg;
1832 455 : if (!checkmf_i(f)) pari_err_TYPE("mfmul",f);
1833 455 : if (!checkmf_i(g)) pari_err_TYPE("mfmul",g);
1834 455 : N = lcmii(mf_get_gN(f), mf_get_gN(g));
1835 455 : K = gadd(mf_get_gk(f), mf_get_gk(g));
1836 455 : CHIf = mf_get_CHI(f);
1837 455 : CHIg = mf_get_CHI(g);
1838 455 : CHI = mfchiadjust(mfcharmul(CHIf,CHIg), K, itos(N));
1839 455 : T = chicompat(CHI, CHIf, CHIg);
1840 455 : NK = mkgNK(N, K, CHI, mfsamefield(T, mf_get_field(f), mf_get_field(g)));
1841 448 : return gc_GEN(av, T? tag3(t_MF_MUL,NK,f,g,T): tag2(t_MF_MUL,NK,f,g));
1842 : }
1843 : GEN
1844 77 : mfpow(GEN f, long n)
1845 : {
1846 77 : pari_sp av = avma;
1847 : GEN T, KK, NK, gn, CHI, CHIf;
1848 77 : if (!checkmf_i(f)) pari_err_TYPE("mfpow",f);
1849 77 : if (!n) return mf1();
1850 77 : if (n == 1) return gcopy(f);
1851 77 : KK = gmulsg(n,mf_get_gk(f));
1852 77 : gn = stoi(n);
1853 77 : CHIf = mf_get_CHI(f);
1854 77 : CHI = mfchiadjust(mfcharpow(CHIf,gn), KK, mf_get_N(f));
1855 77 : T = chicompat(CHI, CHIf, CHIf);
1856 70 : NK = mkgNK(mf_get_gN(f), KK, CHI, mf_get_field(f));
1857 70 : return gc_GEN(av, T? tag3(t_MF_POW,NK,f,gn,T): tag2(t_MF_POW,NK,f,gn));
1858 : }
1859 : GEN
1860 28 : mfbracket(GEN f, GEN g, long m)
1861 : {
1862 28 : pari_sp av = avma;
1863 : GEN T, N, K, NK, CHI, CHIf, CHIg;
1864 28 : if (!checkmf_i(f)) pari_err_TYPE("mfbracket",f);
1865 28 : if (!checkmf_i(g)) pari_err_TYPE("mfbracket",g);
1866 28 : if (m < 0) pari_err_TYPE("mfbracket [m<0]",stoi(m));
1867 28 : K = gaddgs(gadd(mf_get_gk(f), mf_get_gk(g)), 2*m);
1868 28 : if (gsigne(K) < 0) pari_err_IMPL("mfbracket for this form");
1869 28 : N = lcmii(mf_get_gN(f), mf_get_gN(g));
1870 28 : CHIf = mf_get_CHI(f);
1871 28 : CHIg = mf_get_CHI(g);
1872 28 : CHI = mfcharmul(CHIf, CHIg);
1873 28 : CHI = mfchiadjust(CHI, K, itou(N));
1874 28 : T = chicompat(CHI, CHIf, CHIg);
1875 28 : NK = mkgNK(N, K, CHI, mfsamefield(T, mf_get_field(f), mf_get_field(g)));
1876 56 : return gc_GEN(av, T? tag4(t_MF_BRACKET, NK, f, g, utoi(m), T)
1877 28 : : tag3(t_MF_BRACKET, NK, f, g, utoi(m)));
1878 : }
1879 :
1880 : /* remove 0 entries in L */
1881 : static int
1882 1960 : mflinear_strip(GEN *pF, GEN *pL)
1883 : {
1884 1960 : pari_sp av = avma;
1885 1960 : GEN F = *pF, L = *pL;
1886 1960 : long i, j, l = lg(L);
1887 1960 : GEN F2 = cgetg(l, t_VEC), L2 = cgetg(l, t_VEC);
1888 11753 : for (i = j = 1; i < l; i++)
1889 : {
1890 9793 : if (gequal0(gel(L,i))) continue;
1891 4823 : gel(F2,j) = gel(F,i);
1892 4823 : gel(L2,j) = gel(L,i); j++;
1893 : }
1894 1960 : if (j == l) set_avma(av);
1895 : else
1896 : {
1897 602 : setlg(F2,j); *pF = F2;
1898 602 : setlg(L2,j); *pL = L2;
1899 : }
1900 1960 : return (j > 1);
1901 : }
1902 : static GEN
1903 7070 : taglinear_i(long t, GEN NK, GEN F, GEN L)
1904 : {
1905 : GEN dL;
1906 7070 : L = Q_remove_denom(L, &dL); if (!dL) dL = gen_1;
1907 7070 : return tag3(t, NK, F, L, dL);
1908 : }
1909 : static GEN
1910 2926 : taglinear(GEN NK, GEN F, GEN L)
1911 : {
1912 2926 : long t = ok_bhn_linear(F)? t_MF_LINEAR_BHN: t_MF_LINEAR;
1913 2926 : return taglinear_i(t, NK, F, L);
1914 : }
1915 : /* assume F has parameters NK = [N,K,CHI] */
1916 : static GEN
1917 490 : mflinear_i(GEN NK, GEN F, GEN L)
1918 : {
1919 490 : if (!mflinear_strip(&F,&L)) return mftrivial();
1920 490 : return taglinear(NK, F,L);
1921 : }
1922 : static GEN
1923 770 : mflinear_bhn(GEN mf, GEN L)
1924 : {
1925 : long i, l;
1926 770 : GEN P, NK, F = MF_get_S(mf);
1927 770 : if (!mflinear_strip(&F,&L)) return mftrivial();
1928 763 : l = lg(L); P = pol_x(1);
1929 3465 : for (i = 1; i < l; i++)
1930 : {
1931 2702 : GEN c = gel(L,i);
1932 2702 : if (typ(c) == t_POLMOD && varn(gel(c,1)) == 1)
1933 665 : P = mfsamefield(NULL, P, gel(c,1));
1934 : }
1935 763 : NK = mkgNK(MF_get_gN(mf), MF_get_gk(mf), MF_get_CHI(mf), P);
1936 763 : return taglinear_i(t_MF_LINEAR_BHN, NK, F,L);
1937 : }
1938 :
1939 : /* F vector of forms with same weight and character but varying level, return
1940 : * global [N,k,chi,P] */
1941 : static GEN
1942 3339 : vecmfNK(GEN F)
1943 : {
1944 3339 : long i, l = lg(F);
1945 : GEN N, f;
1946 3339 : if (l == 1) return mkNK(1, 0, mfchartrivial());
1947 3339 : f = gel(F,1); N = mf_get_gN(f);
1948 47474 : for (i = 2; i < l; i++) N = lcmii(N, mf_get_gN(gel(F,i)));
1949 3339 : return mkgNK(N, mf_get_gk(f), mf_get_CHI(f), mf_get_field(f));
1950 : }
1951 : /* do not use mflinear: mflineardivtomat rely on F being constant across the
1952 : * basis where mflinear strips the ones matched by 0 coeffs. Assume k and CHI
1953 : * constant, N is allowed to vary. */
1954 : static GEN
1955 1218 : vecmflinear(GEN F, GEN C)
1956 : {
1957 1218 : long i, t, l = lg(C);
1958 1218 : GEN NK, v = cgetg(l, t_VEC);
1959 1218 : if (l == 1) return v;
1960 1218 : t = ok_bhn_linear(F)? t_MF_LINEAR_BHN: t_MF_LINEAR;
1961 1218 : NK = vecmfNK(F);
1962 4599 : for (i = 1; i < l; i++) gel(v,i) = taglinear_i(t, NK, F, gel(C,i));
1963 1218 : return v;
1964 : }
1965 : /* vecmflinear(F,C), then divide everything by E, which has valuation 0 */
1966 : static GEN
1967 434 : vecmflineardiv0(GEN F, GEN C, GEN E)
1968 : {
1969 434 : GEN v = vecmflinear(F, C);
1970 434 : long i, l = lg(v);
1971 434 : if (l == 1) return v;
1972 434 : gel(v,1) = mfdiv_val(gel(v,1), E, 0);
1973 1729 : for (i = 2; i < l; i++)
1974 : { /* v[i] /= E */
1975 1295 : GEN f = shallowcopy(gel(v,1));
1976 1295 : gel(f,2) = gel(v,i);
1977 1295 : gel(v,i) = f;
1978 : }
1979 434 : return v;
1980 : }
1981 :
1982 : /* Non empty linear combination of linear combinations of same
1983 : * F_j=\sum_i \mu_{i,j}G_i so R = \sum_i (\sum_j(\la_j\mu_{i,j})) G_i */
1984 : static GEN
1985 2121 : mflinear_linear(GEN F, GEN L, int strip)
1986 : {
1987 2121 : long l = lg(F), j;
1988 2121 : GEN vF, M = cgetg(l, t_MAT);
1989 2121 : L = shallowcopy(L);
1990 20097 : for (j = 1; j < l; j++)
1991 : {
1992 17976 : GEN f = gel(F,j), c = gel(f,3), d = gel(f,4);
1993 17976 : if (typ(c) == t_VEC) c = shallowtrans(c);
1994 17976 : if (!isint1(d)) gel(L,j) = gdiv(gel(L,j),d);
1995 17976 : gel(M,j) = c;
1996 : }
1997 2121 : vF = gmael(F,1,2); L = RgM_RgC_mul(M,L);
1998 2121 : if (strip && !mflinear_strip(&vF,&L)) return mftrivial();
1999 2121 : return taglinear(vecmfNK(vF), vF, L);
2000 : }
2001 : /* F nonempty vector of forms of the form mfdiv(mflinear(B,v), E) where E
2002 : * does not vanish at oo, or mflinear(B,v). Apply mflinear(F, L) */
2003 : static GEN
2004 2121 : mflineardiv_linear(GEN F, GEN L, int strip)
2005 : {
2006 2121 : long l = lg(F), j;
2007 : GEN v, E, f;
2008 2121 : if (lg(L) != l) pari_err_DIM("mflineardiv_linear");
2009 2121 : f = gel(F,1); /* l > 1 */
2010 2121 : if (mf_get_type(f) != t_MF_DIV) return mflinear_linear(F,L,strip);
2011 1813 : E = gel(f,3);
2012 1813 : v = cgetg(l, t_VEC);
2013 18634 : for (j = 1; j < l; j++) { GEN f = gel(F,j); gel(v,j) = gel(f,2); }
2014 1813 : return mfdiv_val(mflinear_linear(v,L,strip), E, 0);
2015 : }
2016 : static GEN
2017 483 : vecmflineardiv_linear(GEN F, GEN M)
2018 : {
2019 483 : long i, l = lg(M);
2020 483 : GEN v = cgetg(l, t_VEC);
2021 2023 : for (i = 1; i < l; i++) gel(v,i) = mflineardiv_linear(F, gel(M,i), 0);
2022 483 : return v;
2023 : }
2024 :
2025 : static GEN
2026 1057 : tobasis(GEN mf, GEN F, GEN L)
2027 : {
2028 1057 : if (checkmf_i(L) && mf) return mftobasis(mf, L, 0);
2029 1050 : if (typ(F) != t_VEC) pari_err_TYPE("mflinear",F);
2030 1050 : if (!is_vec_t(typ(L))) pari_err_TYPE("mflinear",L);
2031 1050 : if (lg(L) != lg(F)) pari_err_DIM("mflinear");
2032 1050 : return L;
2033 : }
2034 : GEN
2035 1106 : mflinear(GEN F, GEN L)
2036 : {
2037 1106 : pari_sp av = avma;
2038 1106 : GEN G, NK, P, mf = checkMF_i(F), N = NULL, K = NULL, CHI = NULL;
2039 : long i, l;
2040 1106 : if (mf)
2041 : {
2042 728 : GEN gk = MF_get_gk(mf);
2043 728 : F = MF_get_basis(F);
2044 728 : if (typ(gk) != t_INT)
2045 49 : return gc_GEN(av, mflineardiv_linear(F, L, 1));
2046 679 : if (itou(gk) > 1 && space_is_cusp(MF_get_space(mf)))
2047 : {
2048 455 : L = tobasis(mf, F, L);
2049 455 : return gc_GEN(av, mflinear_bhn(mf, L));
2050 : }
2051 : }
2052 602 : L = tobasis(mf, F, L);
2053 602 : if (!mflinear_strip(&F,&L)) return mftrivial();
2054 :
2055 588 : l = lg(F);
2056 588 : if (l == 2 && gequal1(gel(L,1))) return gc_GEN(av, gel(F,1));
2057 329 : P = pol_x(1);
2058 1057 : for (i = 1; i < l; i++)
2059 : {
2060 735 : GEN f = gel(F,i), c = gel(L,i), Ni, Ki;
2061 735 : if (!checkmf_i(f)) pari_err_TYPE("mflinear", f);
2062 735 : Ni = mf_get_gN(f); N = N? lcmii(N, Ni): Ni;
2063 735 : Ki = mf_get_gk(f);
2064 735 : if (!K) K = Ki;
2065 406 : else if (!gequal(K, Ki))
2066 7 : pari_err_TYPE("mflinear [different weights]", mkvec2(K,Ki));
2067 728 : P = mfsamefield(NULL, P, mf_get_field(f));
2068 728 : if (typ(c) == t_POLMOD && varn(gel(c,1)) == 1)
2069 126 : P = mfsamefield(NULL, P, gel(c,1));
2070 : }
2071 322 : G = znstar0(N,1);
2072 1036 : for (i = 1; i < l; i++)
2073 : {
2074 721 : GEN CHI2 = mf_get_CHI(gel(F,i));
2075 721 : CHI2 = induce(G, CHI2);
2076 721 : if (!CHI) CHI = CHI2;
2077 399 : else if (!gequal(CHI, CHI2))
2078 7 : pari_err_TYPE("mflinear [different characters]", mkvec2(CHI,CHI2));
2079 : }
2080 315 : NK = mkgNK(N, K, CHI, P);
2081 315 : return gc_GEN(av, taglinear(NK,F,L));
2082 : }
2083 :
2084 : GEN
2085 42 : mfshift(GEN F, long sh)
2086 : {
2087 42 : pari_sp av = avma;
2088 42 : if (!checkmf_i(F)) pari_err_TYPE("mfshift",F);
2089 42 : return gc_GEN(av, tag2(t_MF_SHIFT, mf_get_NK(F), F, stoi(sh)));
2090 : }
2091 : static long
2092 49 : mfval(GEN F)
2093 : {
2094 49 : pari_sp av = avma;
2095 49 : long i = 0, n, sb;
2096 : GEN gk, gN;
2097 49 : if (!checkmf_i(F)) pari_err_TYPE("mfval", F);
2098 49 : gN = mf_get_gN(F);
2099 49 : gk = mf_get_gk(F);
2100 49 : sb = mfsturmNgk(itou(gN), gk);
2101 70 : for (n = 1; n <= sb;)
2102 : {
2103 : GEN v;
2104 63 : if (n > 0.5*sb) n = sb+1;
2105 63 : v = mfcoefs_i(F, n, 1);
2106 119 : for (; i <= n; i++)
2107 98 : if (!gequal0(gel(v, i+1))) return gc_long(av,i);
2108 21 : n <<= 1;
2109 : }
2110 7 : return gc_long(av,-1);
2111 : }
2112 :
2113 : GEN
2114 2275 : mfdiv_val(GEN f, GEN g, long vg)
2115 : {
2116 : GEN T, N, K, NK, CHI, CHIf, CHIg;
2117 2275 : if (vg) { f = mfshift(f,vg); g = mfshift(g,vg); }
2118 2275 : N = lcmii(mf_get_gN(f), mf_get_gN(g));
2119 2275 : K = gsub(mf_get_gk(f), mf_get_gk(g));
2120 2275 : CHIf = mf_get_CHI(f);
2121 2275 : CHIg = mf_get_CHI(g);
2122 2275 : CHI = mfchiadjust(mfchardiv(CHIf, CHIg), K, itos(N));
2123 2275 : T = chicompat(CHI, CHIf, CHIg);
2124 2268 : NK = mkgNK(N, K, CHI, mfsamefield(T, mf_get_field(f), mf_get_field(g)));
2125 2268 : return T? tag3(t_MF_DIV, NK, f, g, T): tag2(t_MF_DIV, NK, f, g);
2126 : }
2127 : GEN
2128 49 : mfdiv(GEN F, GEN G)
2129 : {
2130 49 : pari_sp av = avma;
2131 49 : long v = mfval(G);
2132 49 : if (!checkmf_i(F)) pari_err_TYPE("mfdiv", F);
2133 42 : if (v < 0 || (v && !gequal0(mfcoefs(F, v-1, 1))))
2134 14 : pari_err_DOMAIN("mfdiv", "ord(G)", ">", strtoGENstr("ord(F)"),
2135 : mkvec2(F, G));
2136 28 : return gc_GEN(av, mfdiv_val(F, G, v));
2137 : }
2138 : GEN
2139 182 : mfderiv(GEN F, long m)
2140 : {
2141 182 : pari_sp av = avma;
2142 : GEN NK, gk;
2143 182 : if (!checkmf_i(F)) pari_err_TYPE("mfderiv",F);
2144 182 : gk = gaddgs(mf_get_gk(F), 2*m);
2145 182 : NK = mkgNK(mf_get_gN(F), gk, mf_get_CHI(F), mf_get_field(F));
2146 182 : return gc_GEN(av, tag2(t_MF_DERIV, NK, F, stoi(m)));
2147 : }
2148 : GEN
2149 21 : mfderivE2(GEN F, long m)
2150 : {
2151 21 : pari_sp av = avma;
2152 : GEN NK, gk;
2153 21 : if (!checkmf_i(F)) pari_err_TYPE("mfderivE2",F);
2154 21 : if (m < 0) pari_err_DOMAIN("mfderivE2","m","<",gen_0,stoi(m));
2155 21 : gk = gaddgs(mf_get_gk(F), 2*m);
2156 21 : NK = mkgNK(mf_get_gN(F), gk, mf_get_CHI(F), mf_get_field(F));
2157 21 : return gc_GEN(av, tag2(t_MF_DERIVE2, NK, F, stoi(m)));
2158 : }
2159 :
2160 : GEN
2161 28 : mftwist(GEN F, GEN D)
2162 : {
2163 28 : pari_sp av = avma;
2164 : GEN NK, CHI, NT, Da;
2165 : long q;
2166 28 : if (!checkmf_i(F)) pari_err_TYPE("mftwist", F);
2167 28 : if (typ(D) != t_INT) pari_err_TYPE("mftwist", D);
2168 28 : Da = mpabs_shallow(D);
2169 28 : CHI = mf_get_CHI(F); q = mfcharconductor(CHI);
2170 28 : NT = glcm(glcm(mf_get_gN(F), mulsi(q, Da)), sqri(Da));
2171 28 : NK = mkgNK(NT, mf_get_gk(F), CHI, mf_get_field(F));
2172 28 : return gc_GEN(av, tag2(t_MF_TWIST, NK, F, D));
2173 : }
2174 :
2175 : /***************************************************************/
2176 : /* Generic cache handling */
2177 : /***************************************************************/
2178 : enum { cache_FACT, cache_DIV, cache_H, cache_D, cache_DIH };
2179 : typedef struct {
2180 : const char *name;
2181 : GEN cache;
2182 : ulong minself, maxself;
2183 : void (*init)(long);
2184 : ulong miss, maxmiss;
2185 : long compressed;
2186 : } cache;
2187 :
2188 : static void constfact(long lim);
2189 : static void constdiv(long lim);
2190 : static void consttabh(long lim);
2191 : static void consttabdihedral(long lim);
2192 : static void constcoredisc(long lim);
2193 : static THREAD cache caches[] = {
2194 : { "Factors", NULL, 50000, 50000, &constfact, 0, 0, 0 },
2195 : { "Divisors", NULL, 50000, 50000, &constdiv, 0, 0, 0 },
2196 : { "H", NULL, 100000, 10000000, &consttabh, 0, 0, 1 },
2197 : { "CorediscF",NULL, 100000, 10000000, &constcoredisc, 0, 0, 0 },
2198 : { "Dihedral", NULL, 1000, 3000, &consttabdihedral, 0, 0, 0 },
2199 : };
2200 :
2201 : static void
2202 879 : cache_reset(long id) { caches[id].miss = caches[id].maxmiss = 0; }
2203 : static void
2204 9435 : cache_delete(long id) { guncloneNULL(caches[id].cache); }
2205 : static void
2206 885 : cache_set(long id, GEN S)
2207 : {
2208 885 : GEN old = caches[id].cache;
2209 885 : caches[id].cache = gclone(S);
2210 885 : guncloneNULL(old);
2211 885 : }
2212 :
2213 : /* handle a cache miss: store stats, possibly reset table; return value
2214 : * if (now) cached; return NULL on failure. HACK: some caches contain an
2215 : * ulong where the 0 value is impossible, and return it (typecast to GEN) */
2216 : static GEN
2217 456742564 : cache_get(long id, ulong D)
2218 : {
2219 456742564 : cache *S = &caches[id];
2220 456742564 : const ulong d = S->compressed? D>>1: D;
2221 : ulong max, l;
2222 :
2223 456742564 : if (!S->cache)
2224 : {
2225 635 : max = maxuu(minuu(D, S->maxself), S->minself);
2226 635 : S->init(max);
2227 627 : l = lg(S->cache);
2228 : }
2229 : else
2230 : {
2231 456741929 : l = lg(S->cache);
2232 456741929 : if (l <= d)
2233 : {
2234 504 : if (D > S->maxmiss) S->maxmiss = D;
2235 504 : if (DEBUGLEVEL >= 3)
2236 0 : err_printf("miss in cache %s: %lu, max = %lu\n",
2237 : S->name, D, S->maxmiss);
2238 504 : if (S->miss++ >= 5 && D < S->maxself)
2239 : {
2240 31 : max = minuu(S->maxself, (long)(S->maxmiss * 1.2));
2241 31 : if (max <= S->maxself)
2242 : {
2243 31 : if (DEBUGLEVEL >= 3)
2244 0 : err_printf("resetting cache %s to %lu\n", S->name, max);
2245 31 : S->init(max); l = lg(S->cache);
2246 : }
2247 : }
2248 : }
2249 : }
2250 456742556 : return (l <= d)? NULL: gel(S->cache, d);
2251 : }
2252 : static GEN
2253 70 : cache_report(long id)
2254 : {
2255 70 : cache *S = &caches[id];
2256 70 : GEN v = zerocol(5);
2257 70 : gel(v,1) = strtoGENstr(S->name);
2258 70 : if (S->cache)
2259 : {
2260 35 : gel(v,2) = utoi(lg(S->cache)-1);
2261 35 : gel(v,3) = utoi(S->miss);
2262 35 : gel(v,4) = utoi(S->maxmiss);
2263 35 : gel(v,5) = utoi(gsizebyte(S->cache));
2264 : }
2265 70 : return v;
2266 : }
2267 : GEN
2268 14 : getcache(void)
2269 : {
2270 14 : pari_sp av = avma;
2271 14 : GEN M = cgetg(6, t_MAT);
2272 14 : gel(M,1) = cache_report(cache_FACT);
2273 14 : gel(M,2) = cache_report(cache_DIV);
2274 14 : gel(M,3) = cache_report(cache_H);
2275 14 : gel(M,4) = cache_report(cache_D);
2276 14 : gel(M,5) = cache_report(cache_DIH);
2277 14 : return gc_GEN(av, shallowtrans(M));
2278 : }
2279 :
2280 : void
2281 1887 : pari_close_mf(void)
2282 : {
2283 1887 : cache_delete(cache_FACT);
2284 1887 : cache_delete(cache_DIV);
2285 1887 : cache_delete(cache_H);
2286 1887 : cache_delete(cache_D);
2287 1887 : cache_delete(cache_DIH);
2288 1887 : }
2289 :
2290 : /*************************************************************************/
2291 : /* a odd, update local cache (recycle memory) */
2292 : static GEN
2293 5461 : update_factor_cache(long a, long lim, long *pb)
2294 : {
2295 5461 : const long step = 16000; /* even; don't increase this: RAM cache thrashing */
2296 5461 : if (a + 2*step > lim)
2297 354 : *pb = lim; /* fuse last 2 chunks */
2298 : else
2299 5107 : *pb = a + step;
2300 5461 : return vecfactoroddu_i(a, *pb);
2301 : }
2302 : /* assume lim < MAX_LONG/8 */
2303 : static void
2304 82 : constcoredisc(long lim)
2305 : {
2306 82 : pari_sp av2, av = avma;
2307 82 : GEN D = caches[cache_D].cache, CACHE = NULL;
2308 82 : long cachea, cacheb, N, LIM = !D ? 4 : lg(D)-1;
2309 82 : if (lim <= 0) lim = 5;
2310 82 : if (lim <= LIM) return;
2311 82 : cache_reset(cache_D);
2312 82 : D = zero_zv(lim);
2313 82 : av2 = avma;
2314 82 : cachea = cacheb = 0;
2315 12427868 : for (N = 1; N <= lim; N+=2)
2316 : { /* N odd */
2317 : long i, d, d2;
2318 : GEN F;
2319 12427786 : if (N > cacheb)
2320 : {
2321 1521 : set_avma(av2); cachea = N;
2322 1521 : CACHE = update_factor_cache(N, lim, &cacheb);
2323 : }
2324 12427786 : F = gel(CACHE, ((N-cachea)>>1)+1); /* factoru(N) */
2325 12427786 : D[N] = d = corediscs_fact(F); /* = 3 mod 4 or 4 mod 16 */
2326 12427786 : d2 = odd(d)? d<<3: d<<1;
2327 12427786 : for (i = 1;;)
2328 : {
2329 16570354 : if ((N << i) > lim) break;
2330 8285196 : D[N<<i] = d2; i++;
2331 8285196 : if ((N << i) > lim) break;
2332 4142568 : D[N<<i] = d; i++;
2333 : }
2334 : }
2335 82 : cache_set(cache_D, D);
2336 82 : set_avma(av);
2337 : }
2338 :
2339 : static void
2340 294 : constfact(long lim)
2341 : {
2342 : pari_sp av;
2343 294 : GEN VFACT = caches[cache_FACT].cache;
2344 294 : long LIM = VFACT? lg(VFACT)-1: 4;
2345 294 : if (lim <= 0) lim = 5;
2346 294 : if (lim <= LIM) return;
2347 266 : cache_reset(cache_FACT); av = avma;
2348 266 : cache_set(cache_FACT, vecfactoru_i(1,lim)); set_avma(av);
2349 : }
2350 : static void
2351 259 : constdiv(long lim)
2352 : {
2353 : pari_sp av;
2354 259 : GEN VFACT, VDIV = caches[cache_DIV].cache;
2355 259 : long N, LIM = VDIV? lg(VDIV)-1: 4;
2356 259 : if (lim <= 0) lim = 5;
2357 259 : if (lim <= LIM) return;
2358 259 : constfact(lim);
2359 255 : VFACT = caches[cache_FACT].cache;
2360 255 : cache_reset(cache_DIV); av = avma;
2361 255 : VDIV = cgetg(lim+1, t_VEC);
2362 12750255 : for (N = 1; N <= lim; N++) gel(VDIV,N) = divisorsu_fact(gel(VFACT,N));
2363 255 : cache_set(cache_DIV, VDIV); set_avma(av);
2364 : }
2365 :
2366 : /* n > 1, D = divisors(n); sets L = 2*lambda(n), S = sigma(n) */
2367 : static void
2368 38429238 : lamsig(GEN D, long *pL, long *pS)
2369 : {
2370 38429238 : pari_sp av = avma;
2371 38429238 : long i, l = lg(D), L = 1, S = D[l-1]+1;
2372 138200094 : for (i = 2; i < l; i++) /* skip d = 1 */
2373 : {
2374 138200094 : long d = D[i], nd = D[l-i]; /* nd = n/d */
2375 138200094 : if (d < nd) { L += d; S += d + nd; }
2376 : else
2377 : {
2378 38429238 : L <<= 1; if (d == nd) { L += d; S += d; }
2379 38429238 : break;
2380 : }
2381 : }
2382 38429238 : set_avma(av); *pL = L; *pS = S;
2383 38429238 : }
2384 : /* table of 6 * Hurwitz class numbers D <= lim */
2385 : static void
2386 276 : consttabh(long lim)
2387 : {
2388 276 : pari_sp av = avma, av2;
2389 276 : GEN VHDH0, VDIV, CACHE = NULL;
2390 276 : GEN VHDH = caches[cache_H].cache;
2391 276 : long r, N, cachea, cacheb, lim0 = VHDH? lg(VHDH)-1: 2, LIM = lim0 << 1;
2392 :
2393 276 : if (lim <= 0) lim = 5;
2394 276 : if (lim <= LIM) return;
2395 276 : cache_reset(cache_H);
2396 276 : r = lim&3L; if (r) lim += 4-r;
2397 276 : cache_get(cache_DIV, lim);
2398 272 : VDIV = caches[cache_DIV].cache;
2399 272 : VHDH0 = cgetg(lim/2 + 1, t_VECSMALL);
2400 272 : VHDH0[1] = 2;
2401 272 : VHDH0[2] = 3;
2402 3057404 : for (N = 3; N <= lim0; N++) VHDH0[N] = VHDH[N];
2403 272 : av2 = avma;
2404 272 : cachea = cacheb = 0;
2405 19214891 : for (N = LIM + 3; N <= lim; N += 4)
2406 : {
2407 19214619 : long s = 0, limt = usqrt(N>>2), flsq = 0, ind, t, L, S;
2408 : GEN DN, DN2;
2409 19214619 : if (N + 2 >= lg(VDIV))
2410 : { /* use local cache */
2411 : GEN F;
2412 16115115 : if (N + 2 > cacheb)
2413 : {
2414 3940 : set_avma(av2); cachea = N;
2415 3940 : CACHE = update_factor_cache(N, lim+2, &cacheb);
2416 : }
2417 16115115 : F = gel(CACHE, ((N-cachea)>>1)+1); /* factoru(N) */
2418 16115115 : DN = divisorsu_fact(F);
2419 16115115 : F = gel(CACHE, ((N-cachea)>>1)+2); /* factoru(N+2) */
2420 16115115 : DN2 = divisorsu_fact(F);
2421 : }
2422 : else
2423 : { /* use global cache */
2424 3099504 : DN = gel(VDIV,N);
2425 3099504 : DN2 = gel(VDIV,N+2);
2426 : }
2427 19214619 : ind = N >> 1;
2428 4083539486 : for (t = 1; t <= limt; t++)
2429 : {
2430 4064324867 : ind -= (t<<2)-2; /* N/2 - 2t^2 */
2431 4064324867 : if (ind) s += VHDH0[ind]; else flsq = 1;
2432 : }
2433 19214619 : lamsig(DN, &L,&S);
2434 19214619 : VHDH0[N >> 1] = 2*S - 3*L - 2*s + flsq;
2435 19214619 : s = 0; flsq = 0; limt = (usqrt(N+2) - 1) >> 1;
2436 19214619 : ind = (N+1) >> 1;
2437 4074016196 : for (t = 1; t <= limt; t++)
2438 : {
2439 4054801577 : ind -= t<<2; /* (N+1)/2 - 2t(t+1) */
2440 4054801577 : if (ind) s += VHDH0[ind]; else flsq = 1;
2441 : }
2442 19214619 : lamsig(DN2, &L,&S);
2443 19214619 : VHDH0[(N+1) >> 1] = S - 3*(L >> 1) - s - flsq;
2444 : }
2445 272 : cache_set(cache_H, VHDH0); set_avma(av);
2446 : }
2447 :
2448 : /*************************************************************************/
2449 : /* Core functions using factorizations, divisors of class numbers caches */
2450 : /* TODO: myfactoru and factorization cache should be exported */
2451 : static GEN
2452 34098967 : myfactoru(long N)
2453 : {
2454 34098967 : GEN z = cache_get(cache_FACT, N);
2455 34098967 : return z? gcopy(z): factoru(N);
2456 : }
2457 : static GEN
2458 71683095 : mydivisorsu(long N)
2459 : {
2460 71683095 : GEN z = cache_get(cache_DIV, N);
2461 71683095 : return z? leafcopy(z): divisorsu(N);
2462 : }
2463 : /* write -n = Df^2, D < 0 fundamental discriminant. Return D, set f. */
2464 : static long
2465 179330411 : mycoredisc2neg(ulong n, long *pf)
2466 : {
2467 179330411 : ulong m, D = (ulong)cache_get(cache_D, n);
2468 179330411 : if (D) { *pf = usqrt(n/D); return -(long)D; }
2469 57 : m = mycore(n, pf);
2470 57 : if ((m&3) != 3) { m <<= 2; *pf >>= 1; }
2471 57 : return (long)-m;
2472 : }
2473 : /* write n = Df^2, D > 0 fundamental discriminant. Return D, set f. */
2474 : static long
2475 14 : mycoredisc2pos(ulong n, long *pf)
2476 : {
2477 14 : ulong m = mycore(n, pf);
2478 14 : if ((m&3) != 1) { m <<= 2; *pf >>= 1; }
2479 14 : return (long)m;
2480 : }
2481 :
2482 : /* D < 0 fundamental. Return 6*hclassno(-D); faster than quadclassunit up
2483 : * to 5*10^5 or so */
2484 : static ulong
2485 123 : hclassno6_count(long D)
2486 : {
2487 123 : ulong a, b, b2, h = 0, d = -D;
2488 123 : int f = 0;
2489 :
2490 123 : if (d > 500000) return 6 * quadclassnos(D);
2491 : /* this part would work with -d non fundamental */
2492 116 : b = d&1; b2 = (1+d)>>2;
2493 116 : if (!b)
2494 : {
2495 8956 : for (a=1; a*a<b2; a++)
2496 8927 : if (b2%a == 0) h++;
2497 29 : f = (a*a==b2); b=2; b2=(4+d)>>2;
2498 : }
2499 21585 : while (b2*3 < d)
2500 : {
2501 21469 : if (b2%b == 0) h++;
2502 3344544 : for (a=b+1; a*a < b2; a++)
2503 3323075 : if (b2%a == 0) h += 2;
2504 21469 : if (a*a == b2) h++;
2505 21469 : b += 2; b2 = (b*b+d)>>2;
2506 : }
2507 116 : if (b2*3 == d) return 6*h+2;
2508 116 : if (f) return 6*h+3;
2509 116 : return 6*h;
2510 : }
2511 : /* D0 < 0; 6 * hclassno(-D), using D = D0*F^2 */
2512 : static long
2513 201 : hclassno6u_2(long D0, long F)
2514 : {
2515 : long h;
2516 201 : if (F == 1) h = hclassno6_count(D0);
2517 : else
2518 : { /* second chance */
2519 79 : h = (ulong)cache_get(cache_H, -D0);
2520 79 : if (!h) h = hclassno6_count(D0);
2521 79 : h *= uhclassnoF_fact(myfactoru(F), D0);
2522 : }
2523 201 : return h;
2524 : }
2525 : /* D > 0; 6 * hclassno(D) (6*Hurwitz). Beware, cached value for D (=0,3 mod 4)
2526 : * is stored at D>>1 */
2527 : ulong
2528 2522834 : hclassno6u(ulong D)
2529 : {
2530 2522834 : ulong z = (ulong)cache_get(cache_H, D);
2531 : long D0, F;
2532 2522830 : if (z) return z;
2533 201 : D0 = mycoredisc2neg(D, &F);
2534 201 : return hclassno6u_2(D0,F);
2535 : }
2536 : /* same as hclassno6u without creating caches */
2537 : ulong
2538 160911 : hclassno6u_no_cache(ulong D)
2539 : {
2540 160911 : cache *S = &caches[cache_H];
2541 : long D0, F;
2542 160911 : if (S->cache)
2543 : {
2544 136617 : const ulong d = D>>1; /* compressed */
2545 136617 : if ((ulong)lg(S->cache) > d) return S->cache[d];
2546 : }
2547 160611 : S = &caches[cache_D];
2548 160611 : if (!S->cache || (ulong)lg(S->cache) <= D) return 0;
2549 0 : D0 = mycoredisc2neg(D, &F);
2550 0 : return hclassno6u_2(D0,F);
2551 : }
2552 : /* same, where the decomposition D = D0*F^2 is already known */
2553 : static ulong
2554 158346131 : hclassno6u_i(ulong D, long D0, long F)
2555 : {
2556 158346131 : ulong z = (ulong)cache_get(cache_H, D);
2557 158346131 : if (z) return z;
2558 0 : return hclassno6u_2(D0,F);
2559 : }
2560 :
2561 : /* D < -4 fundamental, 6 * h(D), ordinary class number */
2562 : static long
2563 10748416 : hclassno6u_fund(long D)
2564 : {
2565 10748416 : ulong z = (ulong)cache_get(cache_H, -D);
2566 10748416 : return z? z: 6 * quadclassnos(D);
2567 : }
2568 :
2569 : /*************************************************************************/
2570 : /* TRACE FORMULAS */
2571 : /* CHIP primitive, initialize for t_POLMOD output */
2572 : static GEN
2573 33551 : mfcharinit(GEN CHIP)
2574 : {
2575 33551 : long n, o, l, vt, N = mfcharmodulus(CHIP);
2576 : GEN c, v, V, G, Pn;
2577 33551 : if (N == 1) return mkvec2(mkvec(gen_1), pol_x(0));
2578 5831 : G = gel(CHIP,1);
2579 5831 : v = ncharvecexpo(G, znconrey_normalized(G, gel(CHIP,2)));
2580 5831 : l = lg(v); V = cgetg(l, t_VEC);
2581 5831 : o = mfcharorder(CHIP);
2582 5831 : Pn = mfcharpol(CHIP); vt = varn(Pn);
2583 5831 : if (o <= 2)
2584 : {
2585 60620 : for (n = 1; n < l; n++)
2586 : {
2587 55867 : if (v[n] < 0) c = gen_0; else c = v[n]? gen_m1: gen_1;
2588 55867 : gel(V,n) = c;
2589 : }
2590 : }
2591 : else
2592 : {
2593 17591 : for (n = 1; n < l; n++)
2594 : {
2595 16513 : if (v[n] < 0) c = gen_0;
2596 : else
2597 : {
2598 9394 : c = Qab_zeta(v[n], o, vt);
2599 9394 : if (typ(c) == t_POL && lg(c) >= lg(Pn)) c = RgX_rem(c, Pn);
2600 : }
2601 16513 : gel(V,n) = c;
2602 : }
2603 : }
2604 5831 : return mkvec2(V, Pn);
2605 : }
2606 : static GEN
2607 428379 : vchip_lift(GEN VCHI, long x, GEN C)
2608 : {
2609 428379 : GEN V = gel(VCHI,1);
2610 428379 : long F = lg(V)-1;
2611 428379 : if (F == 1) return C;
2612 33005 : x %= F;
2613 33005 : if (!x) return C;
2614 33005 : if (x <= 0) x += F;
2615 33005 : return gmul(C, gel(V, x));
2616 : }
2617 : static long
2618 282559972 : vchip_FC(GEN VCHI) { return lg(gel(VCHI,1))-1; }
2619 : static GEN
2620 6586245 : vchip_mod(GEN VCHI, GEN S)
2621 6586245 : { return (typ(S) == t_POL)? RgX_rem(S, gel(VCHI,2)): S; }
2622 : static GEN
2623 1992428 : vchip_polmod(GEN VCHI, GEN S)
2624 1992428 : { return (typ(S) == t_POL)? mkpolmod(S, gel(VCHI,2)): S; }
2625 :
2626 : /* contribution of scalar matrices in dimension formula */
2627 : static GEN
2628 366373 : A1(long N, long k) { return uutoQ(mypsiu(N)*(k-1), 12); }
2629 : static long
2630 7756 : ceilA1(long N, long k) { return ceildivuu(mypsiu(N) * (k-1), 12); }
2631 :
2632 : /* sturm bound, slightly larger than dimension */
2633 : long
2634 22036 : mfsturmNk(long N, long k) { return (mypsiu(N) * k) / 12; }
2635 : long
2636 3346 : mfsturmNgk(long N, GEN k)
2637 : {
2638 3346 : long n,d; Qtoss(k,&n,&d);
2639 3346 : return 1 + (mypsiu(N)*n)/(d == 1? 12: 24);
2640 : }
2641 : static long
2642 427 : mfsturmmf(GEN F) { return mfsturmNgk(mf_get_N(F), mf_get_gk(F)); }
2643 :
2644 : /* List of all solutions of x^2 + x + 1 = 0 modulo N, x modulo N */
2645 : static GEN
2646 581 : sqrtm3modN(long N)
2647 : {
2648 : pari_sp av;
2649 : GEN fa, P, E, B, mB, A, Q, T, R, v, gen_m3;
2650 581 : long l, i, n, ct, fl3 = 0, Ninit;
2651 581 : if (!odd(N) || (N%9) == 0) return cgetg(1,t_VECSMALL);
2652 553 : Ninit = N;
2653 553 : if ((N%3) == 0) { N /= 3; fl3 = 1; }
2654 553 : fa = myfactoru(N); P = gel(fa, 1); E = gel(fa, 2);
2655 553 : l = lg(P);
2656 749 : for (i = 1; i < l; i++)
2657 560 : if ((P[i]%3) == 2) return cgetg(1,t_VECSMALL);
2658 189 : A = cgetg(l, t_VECSMALL);
2659 189 : B = cgetg(l, t_VECSMALL);
2660 189 : mB= cgetg(l, t_VECSMALL);
2661 189 : Q = cgetg(l, t_VECSMALL); gen_m3 = utoineg(3);
2662 385 : for (i = 1; i < l; i++)
2663 : {
2664 196 : long p = P[i], e = E[i];
2665 196 : Q[i] = upowuu(p,e);
2666 196 : B[i] = itou( Zp_sqrt(gen_m3, utoipos(p), e) );
2667 196 : mB[i]= Q[i] - B[i];
2668 : }
2669 189 : ct = 1 << (l-1);
2670 189 : T = ZV_producttree(Q);
2671 189 : R = ZV_chinesetree(Q,T);
2672 189 : v = cgetg(ct+1, t_VECSMALL);
2673 189 : av = avma;
2674 581 : for (n = 1; n <= ct; n++)
2675 : {
2676 392 : long m = n-1, r;
2677 812 : for (i = 1; i < l; i++)
2678 : {
2679 420 : A[i] = (m&1L)? mB[i]: B[i];
2680 420 : m >>= 1;
2681 : }
2682 392 : r = itou( ZV_chinese_tree(A, Q, T, R) );
2683 462 : if (fl3) while (r%3) r += N;
2684 392 : set_avma(av); v[n] = odd(r) ? (r-1) >> 1 : (r+Ninit-1) >> 1;
2685 : }
2686 189 : return v;
2687 : }
2688 :
2689 : /* number of elliptic points of order 3 in X0(N) */
2690 : static long
2691 10220 : nu3(long N)
2692 : {
2693 : long i, l;
2694 : GEN P;
2695 10220 : if (!odd(N) || (N%9) == 0) return 0;
2696 8995 : if ((N%3) == 0) N /= 3;
2697 8995 : P = gel(myfactoru(N), 1); l = lg(P);
2698 13195 : for (i = 1; i < l; i++) if ((P[i]%3) == 2) return 0;
2699 4018 : return 1L<<(l-1);
2700 : }
2701 : /* number of elliptic points of order 2 in X0(N) */
2702 : static long
2703 17647 : nu2(long N)
2704 : {
2705 : long i, l;
2706 : GEN P;
2707 17647 : if ((N&3L) == 0) return 0;
2708 17647 : if (!odd(N)) N >>= 1;
2709 17647 : P = gel(myfactoru(N), 1); l = lg(P);
2710 22078 : for (i = 1; i < l; i++) if ((P[i]&3L) == 3) return 0;
2711 3969 : return 1L<<(l-1);
2712 : }
2713 :
2714 : /* contribution of elliptic matrices of order 3 in dimension formula
2715 : * Only depends on CHIP the primitive char attached to CHI */
2716 : static GEN
2717 44135 : A21(long N, long k, GEN CHI)
2718 : {
2719 : GEN res, G, chi, o;
2720 : long a21, i, limx, S;
2721 44135 : if ((N&1L) == 0) return gen_0;
2722 21371 : a21 = k%3 - 1;
2723 21371 : if (!a21) return gen_0;
2724 20531 : if (N <= 3) return sstoQ(a21, 3);
2725 10801 : if (!CHI) return sstoQ(nu3(N) * a21, 3);
2726 581 : res = sqrtm3modN(N); limx = (N - 1) >> 1;
2727 581 : G = gel(CHI,1); chi = gel(CHI,2);
2728 581 : o = gmfcharorder(CHI);
2729 973 : for (S = 0, i = 1; i < lg(res); i++)
2730 : { /* (x,N) = 1; S += chi(x) + chi(x^2) */
2731 392 : long x = res[i];
2732 392 : if (x <= limx)
2733 : { /* CHI(x)=e(c/o), 3rd-root of 1 */
2734 196 : GEN c = znchareval(G, chi, utoi(x), o);
2735 196 : if (!signe(c)) S += 2; else S--;
2736 : }
2737 : }
2738 581 : return sstoQ(a21 * S, 3);
2739 : }
2740 :
2741 : /* List of all square roots of -1 modulo N */
2742 : static GEN
2743 595 : sqrtm1modN(long N)
2744 : {
2745 : pari_sp av;
2746 : GEN fa, P, E, B, mB, A, Q, T, R, v;
2747 595 : long l, i, n, ct, fleven = 0;
2748 595 : if ((N&3L) == 0) return cgetg(1,t_VECSMALL);
2749 595 : if ((N&1L) == 0) { N >>= 1; fleven = 1; }
2750 595 : fa = myfactoru(N); P = gel(fa,1); E = gel(fa,2);
2751 595 : l = lg(P);
2752 945 : for (i = 1; i < l; i++)
2753 665 : if ((P[i]&3L) == 3) return cgetg(1,t_VECSMALL);
2754 280 : A = cgetg(l, t_VECSMALL);
2755 280 : B = cgetg(l, t_VECSMALL);
2756 280 : mB= cgetg(l, t_VECSMALL);
2757 280 : Q = cgetg(l, t_VECSMALL);
2758 574 : for (i = 1; i < l; i++)
2759 : {
2760 294 : long p = P[i], e = E[i];
2761 294 : Q[i] = upowuu(p,e);
2762 294 : B[i] = itou( Zp_sqrt(gen_m1, utoipos(p), e) );
2763 294 : mB[i]= Q[i] - B[i];
2764 : }
2765 280 : ct = 1 << (l-1);
2766 280 : T = ZV_producttree(Q);
2767 280 : R = ZV_chinesetree(Q,T);
2768 280 : v = cgetg(ct+1, t_VECSMALL);
2769 280 : av = avma;
2770 868 : for (n = 1; n <= ct; n++)
2771 : {
2772 588 : long m = n-1, r;
2773 1232 : for (i = 1; i < l; i++)
2774 : {
2775 644 : A[i] = (m&1L)? mB[i]: B[i];
2776 644 : m >>= 1;
2777 : }
2778 588 : r = itou( ZV_chinese_tree(A, Q, T, R) );
2779 588 : if (fleven && !odd(r)) r += N;
2780 588 : set_avma(av); v[n] = r;
2781 : }
2782 280 : return v;
2783 : }
2784 :
2785 : /* contribution of elliptic matrices of order 4 in dimension formula.
2786 : * Only depends on CHIP the primitive char attached to CHI */
2787 : static GEN
2788 44135 : A22(long N, long k, GEN CHI)
2789 : {
2790 : GEN G, chi, o, res;
2791 : long S, a22, i, limx, o2;
2792 44135 : if ((N&3L) == 0) return gen_0;
2793 30380 : a22 = (k & 3L) - 1; /* (k % 4) - 1 */
2794 30380 : if (!a22) return gen_0;
2795 30310 : if (N <= 2) return sstoQ(a22, 4);
2796 18452 : if (!CHI) return sstoQ(nu2(N)*a22, 4);
2797 805 : if (mfcharparity(CHI) == -1) return gen_0;
2798 595 : res = sqrtm1modN(N); limx = (N - 1) >> 1;
2799 595 : G = gel(CHI,1); chi = gel(CHI,2);
2800 595 : o = gmfcharorder(CHI);
2801 595 : o2 = itou(o)>>1;
2802 1183 : for (S = 0, i = 1; i < lg(res); i++)
2803 : { /* (x,N) = 1, S += real(chi(x)) */
2804 588 : long x = res[i];
2805 588 : if (x <= limx)
2806 : { /* CHI(x)=e(c/o), 4th-root of 1 */
2807 294 : long c = itou( znchareval(G, chi, utoi(x), o) );
2808 294 : if (!c) S++; else if (c == o2) S--;
2809 : }
2810 : }
2811 595 : return sstoQ(a22 * S, 2);
2812 : }
2813 :
2814 : /* sumdiv(N,d,eulerphi(gcd(d,N/d))) */
2815 : static long
2816 39116 : nuinf(long N)
2817 : {
2818 39116 : GEN fa = myfactoru(N), P = gel(fa,1), E = gel(fa,2);
2819 39116 : long i, t = 1, l = lg(P);
2820 82999 : for (i=1; i<l; i++)
2821 : {
2822 43883 : long p = P[i], e = E[i];
2823 43883 : if (odd(e))
2824 35091 : t *= upowuu(p,e>>1) << 1;
2825 : else
2826 8792 : t *= upowuu(p,(e>>1)-1) * (p+1);
2827 : }
2828 39116 : return t;
2829 : }
2830 :
2831 : /* contribution of hyperbolic matrices in dimension formula */
2832 : static GEN
2833 44583 : A3(long N, long FC)
2834 : {
2835 : long i, S, NF, l;
2836 : GEN D;
2837 44583 : if (FC == 1) return uutoQ(nuinf(N),2);
2838 5467 : D = mydivisorsu(N); l = lg(D);
2839 5467 : S = 0; NF = N/FC;
2840 42840 : for (i = 1; i < l; i++)
2841 : {
2842 37373 : long g = ugcd(D[i], D[l-i]);
2843 37373 : if (NF%g == 0) S += myeulerphiu(g);
2844 : }
2845 5467 : return uutoQ(S, 2);
2846 : }
2847 :
2848 : /* special contribution in weight 2 in dimension formula */
2849 : static long
2850 43666 : A4(long k, long FC)
2851 43666 : { return (k==2 && FC==1)? 1: 0; }
2852 : /* gcd(x,N) */
2853 : static long
2854 288402905 : myugcd(GEN GCD, ulong x)
2855 : {
2856 288402905 : ulong N = lg(GCD)-1;
2857 288402905 : if (x >= N) x %= N;
2858 288402905 : return GCD[x+1];
2859 : }
2860 : /* 1_{gcd(x,N) = 1} * chi(x), return NULL if 0 */
2861 : static GEN
2862 411157547 : mychicgcd(GEN GCD, GEN VCHI, long x)
2863 : {
2864 411157547 : long N = lg(GCD)-1;
2865 411157547 : if (N == 1) return gen_1;
2866 336008349 : x = umodsu(x, N);
2867 336008349 : if (GCD[x+1] != 1) return NULL;
2868 274839143 : x %= vchip_FC(VCHI); if (!x) return gen_1;
2869 6668046 : return gel(gel(VCHI,1), x);
2870 : }
2871 :
2872 : /* contribution of scalar matrices to trace formula */
2873 : static GEN
2874 6564045 : TA1(long N, long k, GEN VCHI, GEN GCD, long n)
2875 : {
2876 : GEN S;
2877 : ulong m;
2878 6564045 : if (!uissquareall(n, &m)) return gen_0;
2879 398979 : if (m == 1) return A1(N,k); /* common */
2880 358113 : S = mychicgcd(GCD, VCHI, m);
2881 358113 : return S? gmul(gmul(powuu(m, k-2), A1(N,k)), S): gen_0;
2882 : }
2883 :
2884 : /* All square roots modulo 4N, x modulo 2N, precomputed to accelerate TA2 */
2885 : static GEN
2886 129171 : mksqr(long N)
2887 : {
2888 129171 : pari_sp av = avma;
2889 129171 : long x, N2 = N << 1, N4 = N << 2;
2890 129171 : GEN v = const_vec(N2, cgetg(1, t_VECSMALL));
2891 129171 : gel(v, N2) = mkvecsmall(0); /* x = 0 */
2892 3523569 : for (x = 1; x <= N; x++)
2893 : {
2894 3394398 : long r = (((x*x - 1)%N4) >> 1) + 1;
2895 3394398 : gel(v,r) = vecsmall_append(gel(v,r), x);
2896 : }
2897 129171 : return gc_GEN(av, v);
2898 : }
2899 :
2900 : static GEN
2901 129171 : mkgcd(long N)
2902 : {
2903 : GEN GCD, d;
2904 : long i, N2;
2905 129171 : if (N == 1) return mkvecsmall(N);
2906 106246 : GCD = cgetg(N + 1, t_VECSMALL);
2907 106246 : d = GCD+1; /* GCD[i+1] = d[i] = gcd(i,N) = gcd(N-i,N), i = 0..N-1 */
2908 106246 : d[0] = N; d[1] = d[N-1] = 1; N2 = N>>1;
2909 1664670 : for (i = 2; i <= N2; i++) d[i] = d[N-i] = ugcd(N, i);
2910 106246 : return GCD;
2911 : }
2912 :
2913 : /* Table of \sum_{x^2-tx+n=0 mod Ng}chi(x) for all g dividing gcd(N,F),
2914 : * F^2 largest such that (t^2-4n)/F^2=0 or 1 mod 4; t >= 0 */
2915 : static GEN
2916 16069092 : mutglistall(long t, long N, long NF, GEN VCHI, long n, GEN MUP, GEN L, GEN GCD)
2917 : {
2918 16069092 : long i, lx = lg(L);
2919 16069092 : GEN DNF = mydivisorsu(NF), v = zerovec(NF);
2920 16069092 : long j, g, lDNF = lg(DNF);
2921 44948705 : for (i = 1; i < lx; i++)
2922 : {
2923 28879613 : long x = (L[i] + t) >> 1, y, lD;
2924 28879613 : GEN D, c = mychicgcd(GCD, VCHI, x);
2925 28879613 : if (L[i] && L[i] != N)
2926 : {
2927 19329393 : GEN c2 = mychicgcd(GCD, VCHI, t - x);
2928 19329393 : if (c2) c = c? gadd(c, c2): c2;
2929 : }
2930 28879613 : if (!c) continue;
2931 22310113 : y = (x*(x - t) + n) / N; /* exact division */
2932 22310113 : D = mydivisorsu(ugcd(labs(y), NF)); lD = lg(D);
2933 60130499 : for (j=1; j < lD; j++) { g = D[j]; gel(v,g) = gadd(gel(v,g), c); }
2934 : }
2935 : /* j = 1 corresponds to g = 1, and MUP[1] = 1 */
2936 37214644 : for (j=2; j < lDNF; j++) { g = DNF[j]; gel(v,g) = gmulsg(MUP[g], gel(v,g)); }
2937 16069092 : return v;
2938 : }
2939 :
2940 : /* special case (N,F) = 1: easier */
2941 : static GEN
2942 163261104 : mutg1(long t, long N, GEN VCHI, GEN L, GEN GCD)
2943 : {
2944 163261104 : GEN S = NULL;
2945 163261104 : long i, lx = lg(L);
2946 342969170 : for (i = 1; i < lx; i++)
2947 : {
2948 179708066 : long x = (L[i] + t) >> 1;
2949 179708066 : GEN c = mychicgcd(GCD, VCHI, x);
2950 179708066 : if (c) S = S? gadd(S, c): c;
2951 179708066 : if (L[i] && L[i] != N)
2952 : {
2953 99891078 : c = mychicgcd(GCD, VCHI, t - x);
2954 99891078 : if (c) S = S? gadd(S, c): c;
2955 : }
2956 179708066 : if (S && !signe(S)) S = NULL; /* strive hard to add gen_0 */
2957 : }
2958 163261104 : return S; /* single value */
2959 : }
2960 :
2961 : /* n > 2, return P_n = \sum_{0<=j<=n/2} (-1)^j binomial(n-j,j) X^j
2962 : * (2x)^n P_n (1 / (4x^2)) = polchebyshev(n, 2) */
2963 : GEN
2964 402734 : mfrhopol(long n)
2965 : {
2966 : #ifdef LONG_IS_64BIT
2967 345246 : const long M = 2642249;
2968 : #else
2969 57488 : const long M = 1629;
2970 : #endif
2971 402734 : long j, d = n >> 1; /* >= 1 */
2972 402734 : GEN P = cgetg(d + 3, t_POL);
2973 :
2974 402734 : if (n > M) pari_err_IMPL("mfrhopol for large weight"); /* avoid overflow */
2975 402734 : P[1] = evalvarn(0)|evalsigne(1);
2976 402734 : gel(P,2) = gen_1;
2977 402734 : gel(P,3) = utoineg(n-1); /* j = 1 */
2978 402734 : if (d > 1) gel(P,4) = utoipos(((n-3)*(n-2)) >> 1); /* j = 2 */
2979 402734 : if (d > 2) gel(P,5) = utoineg(((n-5)*(n-4)*(n-3)) / 6); /* j = 3 */
2980 1608867 : for (j = 4; j <= d; j++)
2981 1206133 : gel(P,j+2) = diviuexact(mulis(gel(P,j+1), -(n-2*j+1)*(n-2*j+2)), (n-j+1)*j);
2982 402734 : return P;
2983 : }
2984 :
2985 : /* polrecip(Q)(x), assume Q(0) = 1 */
2986 : GEN
2987 4102887 : mfrhopol_u_eval(GEN Q, ulong x)
2988 : {
2989 4102887 : GEN T = addiu(gel(Q,3), x);
2990 4102887 : long l = lg(Q), j;
2991 41482944 : for (j = 4; j < l; j++) T = addii(gel(Q,j), mului(x, T));
2992 4102887 : return T;
2993 : }
2994 : GEN
2995 105133 : mfrhopol_eval(GEN Q, GEN x)
2996 : {
2997 : long l, j;
2998 : GEN T;
2999 105133 : if (lgefint(x) == 3) return mfrhopol_u_eval(Q, x[2]);
3000 0 : l = lg(Q); T = addii(gel(Q,3), x);
3001 0 : for (j = 4; j < l; j++) T = addii(gel(Q,j), mulii(x, T));
3002 0 : return T;
3003 : }
3004 : /* t >= 0. If nu odd, let [N, T] = [(nu - 1)/2, t]; else let [N, T] = [nu/2, 1].
3005 : * We have t2 = t^2 and Q(X) = sum_{0<=j<=N} (-1)^j binomial(nu-j,j) n^j X^j
3006 : * U_nu(z) = polchebyshev(nu, 2, z)
3007 : * = sum_{0<=j<=N} (-1)^j binomial(nu-j,j) (2z)^(nu-2*j))
3008 : * Return C n^(nu/2) U_nu(t / (2*sqrt(n)))
3009 : * = C sum_{0<=j<=N} (-1)^j binomial(nu-j,j) n^j t^(nu - 2j)
3010 : * = C T sum_{0<=j<=N} (-1)^j binomial(nu-j,j) n^j (t^2)^(N - j)
3011 : * = C T polrecip(Q)(t^2); note that Q(0) = 1 */
3012 : static GEN
3013 170066746 : mfrhopow(GEN C, GEN Q, long nu, long t, long t2, long n)
3014 : {
3015 : GEN T;
3016 170066746 : switch (nu)
3017 : {
3018 162107834 : case 0: return C;
3019 2168698 : case 1: return gmulsg(t, C);
3020 1664866 : case 2: return gmulsg(t2 - n, C);
3021 51275 : case 3: return gmul(mulss(t, t2 - 2*n), C);
3022 4074073 : default:
3023 4074073 : if (!t) return gmul(gel(Q, lg(Q) - 1), C);
3024 3997754 : T = mfrhopol_u_eval(Q, t2); if (odd(nu)) T = mului(t, T);
3025 3997754 : return gmul(T, C);
3026 : }
3027 : }
3028 :
3029 : static GEN
3030 324085950 : TA2_t(long t, long N, long N4, long n, long n4, long nu, GEN Q,
3031 : GEN VCHI, GEN SQRTS, GEN MUP, GEN GCD)
3032 : {
3033 324085950 : long F, NF, D0, t2 = t*t, D = n4 - t2; /* > 0 */
3034 324085950 : GEN sh, L = gel(SQRTS, (umodsu(-D - 1, N4) >> 1) + 1);
3035 :
3036 324085950 : if (lg(L) == 1) return NULL;
3037 179330196 : D0 = mycoredisc2neg(D, &F);
3038 179330196 : NF = myugcd(GCD, F);
3039 179330196 : if (NF == 1)
3040 : { /* (N,F) = 1 => single value in mutglistall */
3041 163261104 : GEN mut = mutg1(t, N, VCHI, L, GCD);
3042 163261104 : if (!mut) return NULL;
3043 158346131 : sh = gmulgu(mut, hclassno6u_i(D,D0,F));
3044 : }
3045 : else
3046 : {
3047 16069092 : GEN v = mutglistall(t, N, NF, VCHI, n, MUP, L, GCD);
3048 16069092 : GEN DF = mydivisorsu(F);
3049 16069092 : long i, lDF = lg(DF);
3050 16069092 : sh = gen_0;
3051 64474719 : for (i = 1; i < lDF; i++)
3052 : {
3053 48405627 : long Ff, f = DF[i], g = myugcd(GCD, f);
3054 48405627 : GEN mut = gel(v, g);
3055 48405627 : if (gequal0(mut)) continue;
3056 31401426 : Ff = DF[lDF-i]; /* F/f */
3057 31401426 : if (Ff > 1)
3058 : {
3059 22452173 : GEN P = gel(myfactoru(Ff), 1);
3060 22452173 : long j, lP = lg(P);
3061 49502654 : for (j = 1; j < lP; j++) { long p = P[j]; Ff -= kross(D0, p)*Ff/p; }
3062 22452173 : mut = gmulsg(Ff, mut);
3063 : }
3064 31401426 : sh = gadd(sh, mut);
3065 : }
3066 16069092 : if (gequal0(sh)) return NULL;
3067 11720615 : if (D0 == -3) sh = gmul2n(sh, 1);
3068 11225060 : else if (D0 == -4) sh = gmulgu(sh, 3);
3069 10748416 : else sh = gmulgu(sh, hclassno6u_fund(D0));
3070 : }
3071 170066746 : return mfrhopow(sh, Q, nu, t, t2, n);
3072 : }
3073 :
3074 : /* contribution of elliptic matrices to trace formula */
3075 : static GEN
3076 6564045 : TA2(long N, long k, GEN VCHI, long n, GEN SQRTS, GEN MUP, GEN GCD)
3077 : {
3078 6564045 : long N4 = N << 2, n4 = n << 2, nu = k - 2;
3079 6564045 : long st = (!odd(N) && odd(n)) ? 2 : 1;
3080 6564045 : long t, limt = usqrt(n4 - 1);
3081 6564045 : GEN s, S = gen_0, Q = nu > 3 ? ZX_z_unscale(mfrhopol(nu), n) : NULL;
3082 :
3083 : /* actually compute 6*S to ensure integrality */
3084 324390485 : for (t = st; t <= limt; t += st) /* t^2 < 4n */
3085 : {
3086 317826440 : pari_sp av = avma;
3087 317826440 : s = TA2_t(t, N, N4, n, n4, nu, Q, VCHI, SQRTS, MUP, GCD);
3088 317826440 : if (s) S = gc_upto(av, gadd(S, s)); else set_avma(av);
3089 : }
3090 6564045 : if (!odd(k))
3091 : {
3092 6259510 : s = TA2_t(0, N, N4, n, n4, nu, Q, VCHI, SQRTS, MUP, GCD);
3093 : /* s/2 is the only term involving a denominator (= 2) */
3094 6259510 : if (s) S = gadd(S, gmul2n(s, -1));
3095 : }
3096 6564045 : return gdivgu(S, 6);
3097 : }
3098 :
3099 : /* compute global auxiliary data for TA3 */
3100 : static GEN
3101 129171 : mkbez(long N, long FC)
3102 : {
3103 129171 : long ct, i, NF = N/FC;
3104 129171 : GEN w, D = mydivisorsu(N);
3105 129171 : long l = lg(D);
3106 :
3107 129171 : w = cgetg(l, t_VEC);
3108 374556 : for (i = ct = 1; i < l; i++)
3109 : {
3110 351631 : long u, v, h, c = D[i], Nc = D[l-i];
3111 351631 : if (c > Nc) break;
3112 245385 : h = cbezout(c, Nc, &u, &v);
3113 245385 : if (h == 1) /* shortcut */
3114 177051 : gel(w, ct++) = mkvecsmall4(1,u*c,1,i);
3115 68334 : else if (!(NF%h))
3116 57582 : gel(w, ct++) = mkvecsmall4(h,u*(c/h),myeulerphiu(h),i);
3117 : }
3118 129171 : setlg(w,ct); stackdummy((pari_sp)(w+ct),(pari_sp)(w+l));
3119 129171 : return w;
3120 : }
3121 :
3122 : /* contribution of hyperbolic matrices to trace formula, d * nd = n,
3123 : * DN = divisorsu(N) */
3124 : static GEN
3125 34044534 : auxsum(GEN VCHI, GEN GCD, long d, long nd, GEN DN, GEN BEZ)
3126 : {
3127 34044534 : GEN S = gen_0;
3128 34044534 : long ct, g = nd - d, lDN = lg(DN), lBEZ = lg(BEZ);
3129 87676498 : for (ct = 1; ct < lBEZ; ct++)
3130 : {
3131 53631964 : GEN y, B = gel(BEZ, ct);
3132 53631964 : long ic, c, Nc, uch, h = B[1];
3133 53631964 : if (g%h) continue;
3134 52409078 : uch = B[2];
3135 52409078 : ic = B[4];
3136 52409078 : c = DN[ic];
3137 52409078 : Nc= DN[lDN - ic]; /* Nc = N/c */
3138 52409078 : if (ugcd(Nc, nd) == 1)
3139 43984571 : y = mychicgcd(GCD, VCHI, d + uch*g); /* 0 if (c,d) > 1 */
3140 : else
3141 8424507 : y = NULL;
3142 52409078 : if (c != Nc && ugcd(Nc, d) == 1)
3143 : {
3144 39006713 : GEN y2 = mychicgcd(GCD, VCHI, nd - uch*g); /* 0 if (c,nd) > 1 */
3145 39006713 : if (y2) y = y? gadd(y, y2): y2;
3146 : }
3147 52409078 : if (y) S = gadd(S, gmulsg(B[3], y));
3148 : }
3149 34044534 : return S;
3150 : }
3151 :
3152 : static GEN
3153 6564045 : TA3(long N, long k, GEN VCHI, GEN GCD, GEN Dn, GEN BEZ)
3154 : {
3155 6564045 : GEN S = gen_0, DN = mydivisorsu(N);
3156 6564045 : long i, l = lg(Dn);
3157 40608579 : for (i = 1; i < l; i++)
3158 : {
3159 40567713 : long d = Dn[i], nd = Dn[l-i]; /* = n/d */
3160 : GEN t, u;
3161 40567713 : if (d > nd) break;
3162 34044534 : t = auxsum(VCHI, GCD, d, nd, DN, BEZ);
3163 34044534 : if (isintzero(t)) continue;
3164 32683853 : u = powuu(d,k-1); if (d == nd) u = gmul2n(u,-1);
3165 32683853 : S = gadd(S, gmul(u,t));
3166 : }
3167 6564045 : return S;
3168 : }
3169 :
3170 : /* special contribution in weight 2 in trace formula */
3171 : static long
3172 6564045 : TA4(long k, GEN VCHIP, GEN Dn, GEN GCD)
3173 : {
3174 : long i, l, S;
3175 6564045 : if (k != 2 || vchip_FC(VCHIP) != 1) return 0;
3176 5687416 : l = lg(Dn); S = 0;
3177 66354498 : for (i = 1; i < l; i++)
3178 : {
3179 60667082 : long d = Dn[i]; /* gcd(N,n/d) == 1? */
3180 60667082 : if (myugcd(GCD, Dn[l-i]) == 1) S += d;
3181 : }
3182 5687416 : return S;
3183 : }
3184 :
3185 : /* precomputation of products occurring im mutg, again to accelerate TA2 */
3186 : static GEN
3187 129171 : mkmup(long N)
3188 : {
3189 129171 : GEN fa = myfactoru(N), P = gel(fa,1), D = divisorsu_fact(fa);
3190 129171 : long i, lP = lg(P), lD = lg(D);
3191 129171 : GEN MUP = zero_zv(N);
3192 129171 : MUP[1] = 1;
3193 452403 : for (i = 2; i < lD; i++)
3194 : {
3195 323232 : long j, g = D[i], Ng = D[lD-i]; /* N/g */
3196 886011 : for (j = 1; j < lP; j++) { long p = P[j]; if (Ng%p) g += g/p; }
3197 323232 : MUP[D[i]] = g;
3198 : }
3199 129171 : return MUP;
3200 : }
3201 :
3202 : /* quadratic nonresidues mod p; p odd prime, p^2 fits in a long */
3203 : static GEN
3204 2814 : non_residues(long p)
3205 : {
3206 2814 : long i, j, p2 = p >> 1;
3207 2814 : GEN v = cgetg(p2+1, t_VECSMALL), w = const_vecsmall(p-1, 1);
3208 4571 : for (i = 2; i <= p2; i++) w[(i*i) % p] = 0; /* no need to check 1 */
3209 9142 : for (i = 2, j = 1; i < p; i++) if (w[i]) v[j++] = i;
3210 2814 : return v;
3211 : }
3212 :
3213 : /* CHIP primitive. Return t_VECSMALL v of length q such that
3214 : * Tr^new_{N,CHIP}(n) = 0 whenever v[(n%q) + 1] is nonzero */
3215 : static GEN
3216 33649 : mfnewzerodata(long N, GEN CHIP)
3217 : {
3218 33649 : GEN V, M, L, faN = myfactoru(N), PN = gel(faN,1), EN = gel(faN,2);
3219 33649 : GEN G = gel(CHIP,1), chi = gel(CHIP,2);
3220 33649 : GEN fa = znstar_get_faN(G), P = ZV_to_zv(gel(fa,1)), E = gel(fa,2);
3221 33649 : long i, mod, j = 1, l = lg(PN);
3222 :
3223 33649 : M = cgetg(l, t_VECSMALL); M[1] = 0;
3224 33649 : V = cgetg(l, t_VEC);
3225 : /* Tr^new(n) = 0 if (n mod M[i]) in V[i] */
3226 33649 : if ((N & 3) == 0)
3227 : {
3228 13153 : long e = EN[1];
3229 13153 : long c = (lg(P) > 1 && P[1] == 2)? E[1]: 0; /* c = v_2(FC) */
3230 : /* e >= 2 */
3231 13153 : if (c == e-1) return NULL; /* Tr^new = 0 */
3232 13048 : if (c == e)
3233 : {
3234 3941 : if (e == 2)
3235 : { /* sc: -4 */
3236 1946 : gel(V,1) = mkvecsmall(3);
3237 1946 : M[1] = 4;
3238 : }
3239 1995 : else if (e == 3)
3240 : { /* sc: -8 (CHI_2(-1)=-1<=>chi[1]=1) and 8 (CHI_2(-1)=1 <=> chi[1]=0) */
3241 1995 : long t = signe(gel(chi,1))? 7: 3;
3242 1995 : gel(V,1) = mkvecsmall2(5, t);
3243 1995 : M[1] = 8;
3244 : }
3245 : }
3246 9107 : else if (e == 5 && c == 3)
3247 154 : { /* sc: -8 (CHI_2(-1)=-1<=>chi[1]=1) and 8 (CHI_2(-1)=1 <=> chi[1]=0) */
3248 154 : long t = signe(gel(chi,1))? 7: 3;
3249 154 : gel(V,1) = mkvecsmalln(6, 2L,4L,5L,6L,8L,t);
3250 154 : M[1] = 8;
3251 : }
3252 8953 : else if ((e == 4 && c == 2) || (e == 5 && c <= 2) || (e == 6 && c <= 2)
3253 7378 : || (e >= 7 && c == e - 3))
3254 : { /* sc: 4 */
3255 1575 : gel(V,1) = mkvecsmall3(0,2,3);
3256 1575 : M[1] = 4;
3257 : }
3258 7378 : else if ((e <= 4 && c == 0) || (e >= 5 && c == e - 2))
3259 : { /* sc: 2 */
3260 7021 : gel(V,1) = mkvecsmall(0);
3261 7021 : M[1] = 2;
3262 : }
3263 357 : else if ((e == 6 && c == 3) || (e >= 7 && c <= e - 4))
3264 : { /* sc: -2 */
3265 357 : gel(V,1) = mkvecsmalln(7, 0L,2L,3L,4L,5L,6L,7L);
3266 357 : M[1] = 8;
3267 : }
3268 : }
3269 33544 : j = M[1]? 2: 1;
3270 71526 : for (i = odd(N)? 1: 2; i < l; i++) /* skip p=2, done above */
3271 : {
3272 37982 : long p = PN[i], e = EN[i];
3273 37982 : long z = zv_search(P, p), c = z? E[z]: 0; /* c = v_p(FC) */
3274 37982 : if ((e <= 2 && c == 1 && itos(gel(chi,z)) == (p>>1)) /* ord(CHI_p)=2 */
3275 35791 : || (e >= 3 && c <= e - 2))
3276 2814 : { /* sc: -p */
3277 2814 : GEN v = non_residues(p);
3278 2814 : if (e != 1) v = vecsmall_prepend(v, 0);
3279 2814 : gel(V,j) = v;
3280 2814 : M[j] = p; j++;
3281 : }
3282 35168 : else if (e >= 2 && c < e)
3283 : { /* sc: p */
3284 2660 : gel(V,j) = mkvecsmall(0);
3285 2660 : M[j] = p; j++;
3286 : }
3287 : }
3288 33544 : if (j == 1) return cgetg(1, t_VECSMALL);
3289 15603 : setlg(V,j); setlg(M,j); mod = zv_prod(M);
3290 15603 : L = zero_zv(mod);
3291 34125 : for (i = 1; i < j; i++)
3292 : {
3293 18522 : GEN v = gel(V,i);
3294 18522 : long s, m = M[i], lv = lg(v);
3295 48132 : for (s = 1; s < lv; s++)
3296 : {
3297 29610 : long a = v[s] + 1;
3298 56679 : do { L[a] = 1; a += m; } while (a <= mod);
3299 : }
3300 : }
3301 15603 : return L;
3302 : }
3303 : /* v=mfnewzerodata(N,CHI); returns TRUE if newtrace(n) must be zero,
3304 : * (but newtrace(n) may still be zero if we return FALSE) */
3305 : static long
3306 2673683 : mfnewchkzero(GEN v, long n) { long q = lg(v)-1; return q && v[(n%q) + 1]; }
3307 :
3308 : /* if (!VCHIP): from mftraceform_cusp;
3309 : * else from initnewtrace and CHI is known to be primitive */
3310 : static GEN
3311 129171 : inittrace(long N, GEN CHI, GEN VCHIP)
3312 : {
3313 : long FC;
3314 129171 : if (VCHIP)
3315 129164 : FC = mfcharmodulus(CHI);
3316 : else
3317 7 : VCHIP = mfcharinit(mfchartoprimitive(CHI, &FC));
3318 129171 : return mkvecn(5, mksqr(N), mkmup(N), mkgcd(N), VCHIP, mkbez(N, FC));
3319 : }
3320 :
3321 : /* p > 2 prime; return a sorted t_VECSMALL of primes s.t Tr^new(p) = 0 for all
3322 : * weights > 2 */
3323 : static GEN
3324 33544 : inittrconj(long N, long FC)
3325 : {
3326 : GEN fa, P, E, v;
3327 : long i, k, l;
3328 :
3329 33544 : if (FC != 1) return cgetg(1,t_VECSMALL);
3330 :
3331 27713 : fa = myfactoru(N >> vals(N));
3332 27713 : P = gel(fa,1); l = lg(P);
3333 27713 : E = gel(fa,2);
3334 27713 : v = cgetg(l, t_VECSMALL);
3335 60298 : for (i = k = 1; i < l; i++)
3336 : {
3337 32585 : long j, p = P[i]; /* > 2 */
3338 78610 : for (j = 1; j < l; j++)
3339 46025 : if (j != i && E[j] == 1 && kross(-p, P[j]) == 1) v[k++] = p;
3340 : }
3341 27713 : setlg(v,k); return v;
3342 : }
3343 :
3344 : /* assume CHIP primitive, f(CHIP) | N; NZ = mfnewzerodata(N,CHIP) */
3345 : static GEN
3346 33544 : initnewtrace_i(long N, GEN CHIP, GEN NZ)
3347 : {
3348 33544 : GEN T = const_vec(N, cgetg(1,t_VEC)), D, VCHIP;
3349 33544 : long FC = mfcharmodulus(CHIP), N1, N2, i, l;
3350 :
3351 33544 : if (!NZ) NZ = mkvecsmall(1); /*Tr^new = 0; initialize data nevertheless*/
3352 33544 : VCHIP = mfcharinit(CHIP);
3353 33544 : N1 = N/FC; newd_params(N1, &N2);
3354 33544 : D = mydivisorsu(N1/N2); l = lg(D);
3355 33544 : N2 *= FC;
3356 162708 : for (i = 1; i < l; i++)
3357 : {
3358 129164 : long M = D[i]*N2;
3359 129164 : gel(T,M) = inittrace(M, CHIP, VCHIP);
3360 : }
3361 33544 : gel(T,N) = shallowconcat(gel(T,N), mkvec2(NZ, inittrconj(N,FC)));
3362 33544 : return T;
3363 : }
3364 : /* don't initialize if Tr^new = 0, return NULL */
3365 : static GEN
3366 33649 : initnewtrace(long N, GEN CHI)
3367 : {
3368 33649 : GEN CHIP = mfchartoprimitive(CHI, NULL), NZ = mfnewzerodata(N,CHIP);
3369 33649 : return NZ? initnewtrace_i(N, CHIP, NZ): NULL;
3370 : }
3371 :
3372 : /* (-1)^k */
3373 : static long
3374 8295 : m1pk(long k) { return odd(k)? -1 : 1; }
3375 : static long
3376 7931 : badchar(long N, long k, GEN CHI)
3377 7931 : { return mfcharparity(CHI) != m1pk(k) || (CHI && N % mfcharconductor(CHI)); }
3378 :
3379 :
3380 : static long
3381 43743 : mfcuspdim_i(long N, long k, GEN CHI, GEN vSP)
3382 : {
3383 43743 : pari_sp av = avma;
3384 : long FC;
3385 : GEN s;
3386 43743 : if (k <= 0) return 0;
3387 43743 : if (k == 1) return CHI? mf1cuspdim(N, CHI, vSP): 0;
3388 43484 : FC = CHI? mfcharconductor(CHI): 1;
3389 43484 : if (FC == 1) CHI = NULL;
3390 43484 : s = gsub(A1(N, k), gadd(A21(N, k, CHI), A22(N, k, CHI)));
3391 43484 : s = gadd(s, gsubsg(A4(k, FC), A3(N, FC)));
3392 43484 : return gc_long(av, itos(s));
3393 : }
3394 : /* dimension of space of cusp forms S_k(\G_0(N),CHI)
3395 : * Only depends on CHIP the primitive char attached to CHI */
3396 : long
3397 3458 : mfcuspdim(long N, long k, GEN CHI) { return mfcuspdim_i(N, k, CHI, NULL); }
3398 :
3399 : /* dimension of whole space M_k(\G_0(N),CHI)
3400 : * Only depends on CHIP the primitive char attached to CHI; assumes !badchar */
3401 : long
3402 868 : mffulldim(long N, long k, GEN CHI)
3403 : {
3404 868 : pari_sp av = avma;
3405 868 : long FC = CHI? mfcharconductor(CHI): 1;
3406 : GEN s;
3407 868 : if (k <= 0) return (k == 0 && FC == 1)? 1: 0;
3408 868 : if (k == 1) return gc_long(av, itos(A3(N, FC)) + mf1cuspdim(N, CHI, NULL));
3409 651 : if (FC == 1) CHI = NULL;
3410 651 : s = gsub(A1(N, k), gadd(A21(N, k, CHI), A22(N, k, CHI)));
3411 651 : s = gadd(s, A3(N, FC));
3412 651 : return gc_long(av, itos(s));
3413 : }
3414 :
3415 : /* Dimension of the space of Eisenstein series */
3416 : long
3417 231 : mfeisensteindim(long N, long k, GEN CHI)
3418 : {
3419 231 : pari_sp av = avma;
3420 231 : long s, FC = CHI? mfcharconductor(CHI): 1;
3421 231 : if (k <= 0) return (k == 0 && FC == 1)? 1: 0;
3422 231 : s = itos(gmul2n(A3(N, FC), 1));
3423 231 : if (k > 1) s -= A4(k, FC); else s >>= 1;
3424 231 : return gc_long(av,s);
3425 : }
3426 :
3427 : enum { _SQRTS = 1, _MUP, _GCD, _VCHIP, _BEZ, _NEWLZ, _TRCONJ };
3428 : /* Trace of T(n) on space of cuspforms; only depends on CHIP the primitive char
3429 : * attached to CHI */
3430 : static GEN
3431 6564045 : mfcusptrace_i(long N, long k, long n, GEN Dn, GEN S)
3432 : {
3433 6564045 : pari_sp av = avma;
3434 : GEN a, b, VCHIP, GCD;
3435 : long t;
3436 6564045 : if (!n) return gen_0;
3437 6564045 : VCHIP = gel(S,_VCHIP);
3438 6564045 : GCD = gel(S,_GCD);
3439 6564045 : t = TA4(k, VCHIP, Dn, GCD);
3440 6564045 : a = TA1(N, k, VCHIP, GCD, n); if (t) a = gaddgs(a,t);
3441 6564045 : b = TA2(N, k, VCHIP, n, gel(S,_SQRTS), gel(S,_MUP), GCD);
3442 6564045 : b = gadd(b, TA3(N, k, VCHIP, GCD, Dn, gel(S,_BEZ)));
3443 6564045 : b = gsub(a,b);
3444 6564045 : if (typ(b) != t_POL) return gc_upto(av, b);
3445 50834 : return gc_GEN(av, vchip_polmod(VCHIP, b));
3446 : }
3447 :
3448 : static GEN
3449 7850904 : mfcusptracecache(long N, long k, long n, GEN Dn, GEN S, cachenew_t *cache)
3450 : {
3451 7850904 : GEN C = NULL, T = gel(cache->vfull,N);
3452 7850904 : long lcache = lg(T);
3453 7850904 : if (n < lcache) C = gel(T, n);
3454 7850904 : if (C) cache->cuspHIT++; else C = mfcusptrace_i(N, k, n, Dn, S);
3455 7850904 : cache->cuspTOTAL++;
3456 7850904 : if (n < lcache) gel(T,n) = C;
3457 7850904 : return C;
3458 : }
3459 :
3460 : /* return the divisors of n, known to be among the elements of D */
3461 : static GEN
3462 336280 : div_restrict(GEN D, ulong n)
3463 : {
3464 : long i, j, l;
3465 336280 : GEN v, VDIV = caches[cache_DIV].cache;
3466 336280 : if (lg(VDIV) > n) return gel(VDIV,n);
3467 0 : l = lg(D);
3468 0 : v = cgetg(l, t_VECSMALL);
3469 0 : for (i = j = 1; i < l; i++)
3470 : {
3471 0 : ulong d = D[i];
3472 0 : if (n % d == 0) v[j++] = d;
3473 : }
3474 0 : setlg(v,j); return v;
3475 : }
3476 :
3477 : /* for some prime divisors of N, Tr^new(p) = 0 */
3478 : static int
3479 270911 : trconj(GEN T, long N, long n)
3480 270911 : { return (lg(T) > 1 && N % n == 0 && zv_search(T, n)); }
3481 :
3482 : /* n > 0; trace formula on new space */
3483 : static GEN
3484 2673683 : mfnewtrace_i(long N, long k, long n, cachenew_t *cache)
3485 : {
3486 2673683 : GEN VCHIP, s, Dn, DN1, SN, S = cache->DATA;
3487 : long FC, N1, N2, N1N2, g, i, j, lDN1;
3488 :
3489 2673683 : if (!S) return gen_0;
3490 2673683 : SN = gel(S,N);
3491 2673683 : if (mfnewchkzero(gel(SN,_NEWLZ), n)) return gen_0;
3492 1941643 : if (k > 2 && trconj(gel(SN,_TRCONJ), N, n)) return gen_0;
3493 1941594 : VCHIP = gel(SN, _VCHIP); FC = vchip_FC(VCHIP);
3494 1941594 : N1 = N/FC; newt_params(N1, n, FC, &g, &N2);
3495 1941594 : N1N2 = N1/N2;
3496 1941594 : DN1 = mydivisorsu(N1N2); lDN1 = lg(DN1);
3497 1941594 : N2 *= FC;
3498 1941594 : Dn = mydivisorsu(n); /* this one is probably out of cache */
3499 1941594 : s = gmulsg(mubeta2(N1N2,n), mfcusptracecache(N2, k, n, Dn, gel(S,N2), cache));
3500 7514624 : for (i = 2; i < lDN1; i++)
3501 : { /* skip M1 = 1, done above */
3502 5573030 : long M1 = DN1[i], N1M1 = DN1[lDN1-i];
3503 5573030 : GEN Dg = mydivisorsu(ugcd(M1, g));
3504 5573030 : M1 *= N2;
3505 5573030 : s = gadd(s, gmulsg(mubeta2(N1M1,n),
3506 5573030 : mfcusptracecache(M1, k, n, Dn, gel(S,M1), cache)));
3507 5909310 : for (j = 2; j < lg(Dg); j++) /* skip d = 1, done above */
3508 : {
3509 336280 : long d = Dg[j], ndd = n/(d*d), M = M1/d;
3510 336280 : GEN z = mulsi(mubeta2(N1M1,ndd), powuu(d,k-1)), C = vchip_lift(VCHIP,d,z);
3511 336280 : GEN Dndd = div_restrict(Dn, ndd);
3512 336280 : s = gadd(s, gmul(C, mfcusptracecache(M, k, ndd, Dndd, gel(S,M), cache)));
3513 : }
3514 5573030 : s = vchip_mod(VCHIP, s);
3515 : }
3516 1941594 : return vchip_polmod(VCHIP, s);
3517 : }
3518 :
3519 : static GEN
3520 12355 : get_DIH(long N)
3521 : {
3522 12355 : GEN x = cache_get(cache_DIH, N);
3523 12355 : return x? gcopy(x): mfdihedral(N);
3524 : }
3525 : static GEN
3526 2373 : get_vDIH(long N, GEN D)
3527 : {
3528 2373 : GEN x = const_vec(N, NULL);
3529 : long i, l;
3530 2373 : if (!D) D = mydivisorsu(N);
3531 2373 : l = lg(D);
3532 14504 : for (i = 1; i < l; i++) { long d = D[i]; gel(x, d) = get_DIH(d); }
3533 2373 : return x;
3534 : }
3535 :
3536 : /* divisors of N which are multiple of F */
3537 : static GEN
3538 322 : divisorsNF(long N, long F)
3539 : {
3540 322 : GEN D = mydivisorsu(N / F);
3541 322 : long l = lg(D), i;
3542 833 : for (i = 1; i < l; i++) D[i] = N / D[i];
3543 322 : return D;
3544 : }
3545 : /* mfcuspdim(N,k,CHI) - mfnewdim(N,k,CHI); CHIP primitive (for efficiency) */
3546 : static long
3547 8512 : mfolddim_i(long N, long k, GEN CHIP, GEN vSP)
3548 : {
3549 8512 : long S, i, l, F = mfcharmodulus(CHIP), N1 = N / F, N2;
3550 : GEN D;
3551 8512 : newd_params(N1, &N2); /* will ensure mubeta != 0 */
3552 8512 : D = mydivisorsu(N1/N2); l = lg(D); S = 0;
3553 8512 : if (k == 1 && !vSP) vSP = get_vDIH(N, divisorsNF(N, F));
3554 32795 : for (i = 2; i < l; i++)
3555 : {
3556 24283 : long d = mfcuspdim_i(N / D[i], k, CHIP, vSP);
3557 24283 : if (d) S -= mubeta(D[i]) * d;
3558 : }
3559 8512 : return S;
3560 : }
3561 : long
3562 224 : mfolddim(long N, long k, GEN CHI)
3563 : {
3564 224 : pari_sp av = avma;
3565 224 : GEN CHIP = mfchartoprimitive(CHI, NULL);
3566 224 : return gc_long(av, mfolddim_i(N, k, CHIP, NULL));
3567 : }
3568 : /* Only depends on CHIP the primitive char attached to CHI; assumes !badchar */
3569 : long
3570 16002 : mfnewdim(long N, long k, GEN CHI)
3571 : {
3572 : pari_sp av;
3573 : long S, F;
3574 16002 : GEN vSP, CHIP = mfchartoprimitive(CHI, &F);
3575 16002 : vSP = (k == 1)? get_vDIH(N, divisorsNF(N, F)): NULL;
3576 16002 : S = mfcuspdim_i(N, k, CHIP, vSP); if (!S) return 0;
3577 8015 : av = avma; return gc_long(av, S - mfolddim_i(N, k, CHIP, vSP));
3578 : }
3579 :
3580 : /* trace form, given as closure */
3581 : static GEN
3582 980 : mftraceform_new(long N, long k, GEN CHI)
3583 : {
3584 : GEN T;
3585 980 : if (k == 1) return initwt1newtrace(mfinit_Nkchi(N, 1, CHI, mf_CUSP, 0));
3586 959 : T = initnewtrace(N,CHI); if (!T) return mftrivial();
3587 959 : return tag(t_MF_NEWTRACE, mkNK(N,k,CHI), T);
3588 : }
3589 : static GEN
3590 14 : mftraceform_cusp(long N, long k, GEN CHI)
3591 : {
3592 14 : if (k == 1) return initwt1trace(mfinit_Nkchi(N, 1, CHI, mf_CUSP, 0));
3593 7 : return tag(t_MF_TRACE, mkNK(N,k,CHI), inittrace(N,CHI,NULL));
3594 : }
3595 : static GEN
3596 98 : mftraceform_i(GEN NK, long space)
3597 : {
3598 : GEN CHI;
3599 : long N, k;
3600 98 : checkNK(NK, &N, &k, &CHI, 0);
3601 98 : if (!mfdim_Nkchi(N, k, CHI, space)) return mftrivial();
3602 77 : switch(space)
3603 : {
3604 56 : case mf_NEW: return mftraceform_new(N, k, CHI);
3605 14 : case mf_CUSP:return mftraceform_cusp(N, k, CHI);
3606 : }
3607 7 : pari_err_DOMAIN("mftraceform", "space", "=", utoi(space), NK);
3608 : return NULL;/*LCOV_EXCL_LINE*/
3609 : }
3610 : GEN
3611 98 : mftraceform(GEN NK, long space)
3612 98 : { pari_sp av = avma; return gc_GEN(av, mftraceform_i(NK,space)); }
3613 :
3614 : static GEN
3615 18466 : hecke_data(long N, long n)
3616 18466 : { return mkvecsmall3(n, u_ppo(n, N), N); }
3617 : /* 1/2-integral weight */
3618 : static GEN
3619 84 : heckef2_data(long N, long n)
3620 : {
3621 : ulong f, fN, fN2;
3622 84 : if (!uissquareall(n, &f)) return NULL;
3623 77 : fN = u_ppo(f, N); fN2 = fN*fN;
3624 77 : return mkvec2(myfactoru(fN), mkvecsmall4(n, N, fN2, n/fN2));
3625 : }
3626 : /* N = mf_get_N(F) or a multiple */
3627 : static GEN
3628 25704 : mfhecke_i(long n, long N, GEN F)
3629 : {
3630 25704 : if (n == 1) return F;
3631 18081 : return tag2(t_MF_HECKE, mf_get_NK(F), hecke_data(N,n), F);
3632 : }
3633 :
3634 : GEN
3635 119 : mfhecke(GEN mf, GEN F, long n)
3636 : {
3637 119 : pari_sp av = avma;
3638 : GEN NK, CHI, gk, DATA;
3639 : long N, nk, dk;
3640 119 : mf = checkMF(mf);
3641 119 : if (!checkmf_i(F)) pari_err_TYPE("mfhecke",F);
3642 119 : if (n <= 0) pari_err_TYPE("mfhecke [n <= 0]", stoi(n));
3643 119 : if (n == 1) return gcopy(F);
3644 119 : gk = mf_get_gk(F);
3645 119 : Qtoss(gk,&nk,&dk);
3646 119 : CHI = mf_get_CHI(F);
3647 119 : N = MF_get_N(mf);
3648 119 : if (dk == 2)
3649 : {
3650 77 : DATA = heckef2_data(N,n);
3651 77 : if (!DATA) return mftrivial();
3652 : }
3653 : else
3654 42 : DATA = hecke_data(N,n);
3655 112 : NK = mkgNK(lcmii(stoi(N), mf_get_gN(F)), gk, CHI, mf_get_field(F));
3656 112 : return gc_GEN(av, tag2(t_MF_HECKE, NK, DATA, F));
3657 : }
3658 :
3659 : /* form F given by closure, compute B(d)(F) as closure (q -> q^d) */
3660 : static GEN
3661 36981 : mfbd_i(GEN F, long d)
3662 : {
3663 : GEN D, NK, gk, CHI;
3664 36981 : if (d == 1) return F;
3665 13762 : if (d <= 0) pari_err_TYPE("mfbd [d <= 0]", stoi(d));
3666 13762 : if (mf_get_type(F) != t_MF_BD) D = utoi(d);
3667 7 : else { D = mului(d, gel(F,3)); F = gel(F,2); }
3668 13762 : gk = mf_get_gk(F); CHI = mf_get_CHI(F);
3669 13762 : if (typ(gk) != t_INT) CHI = mfcharmul(CHI, get_mfchar(utoi(d << 2)));
3670 13762 : NK = mkgNK(muliu(mf_get_gN(F), d), gk, CHI, mf_get_field(F));
3671 13762 : return tag2(t_MF_BD, NK, F, D);
3672 : }
3673 : GEN
3674 266 : mfbd(GEN F, long d)
3675 : {
3676 266 : pari_sp av = avma;
3677 266 : if (!checkmf_i(F)) pari_err_TYPE("mfbd",F);
3678 266 : return gc_GEN(av, mfbd_i(F, d));
3679 : }
3680 :
3681 : /* A[i+1] = a(t*i^2) */
3682 : static GEN
3683 112 : RgV_shimura(GEN A, long n, long t, long N, long r, GEN CHI)
3684 : {
3685 112 : GEN R, a0, Pn = mfcharpol(CHI);
3686 112 : long m, st, ord = mfcharorder(CHI), vt = varn(Pn), Nt = t == 1? N: ulcm(N,t);
3687 :
3688 112 : R = cgetg(n + 2, t_VEC);
3689 112 : st = odd(r)? -t: t;
3690 112 : a0 = gel(A, 1);
3691 112 : if (!gequal0(a0))
3692 : {
3693 14 : long o = mfcharorder(CHI);
3694 14 : if (st != 1 && odd(o)) o <<= 1;
3695 14 : a0 = gmul(a0, charLFwtk(Nt, r, CHI, o, st));
3696 : }
3697 112 : gel(R, 1) = a0;
3698 672 : for (m = 1; m <= n; m++)
3699 : {
3700 560 : GEN Dm = mydivisorsu(u_ppo(m, Nt)), S = gel(A, m*m + 1);
3701 560 : long i, l = lg(Dm);
3702 833 : for (i = 2; i < l; i++)
3703 : { /* (e,Nt) = 1; skip i = 1: e = 1, done above */
3704 273 : long e = Dm[i], me = m / e, a = mfcharevalord(CHI, e, ord);
3705 273 : GEN c, C = powuu(e, r - 1);
3706 273 : if (kross(st, e) == -1) C = negi(C);
3707 273 : c = Qab_Czeta(a, ord, C, vt);
3708 273 : S = gadd(S, gmul(c, gel(A, me*me + 1)));
3709 : }
3710 560 : gel(R, m+1) = S;
3711 : }
3712 112 : return degpol(Pn) > 1? gmodulo(R, Pn): R;
3713 : }
3714 :
3715 : static long
3716 35 : mfisinkohnen(GEN mf, GEN F)
3717 : {
3718 35 : GEN v, gk = MF_get_gk(mf), CHI = MF_get_CHI(mf);
3719 35 : long i, eps, N4 = MF_get_N(mf) >> 2, sb = mfsturmNgk(N4 << 4, gk) + 1;
3720 35 : eps = N4 % mfcharconductor(CHI)? -1 : 1;
3721 35 : if (odd(MF_get_r(mf))) eps = -eps;
3722 35 : v = mfcoefs(F, sb, 1);
3723 910 : for (i = 2; i <= sb; i+=4) if (!gequal0(gel(v,i+1))) return 0;
3724 462 : for (i = 2+eps; i <= sb; i+=4) if (!gequal0(gel(v,i+1))) return 0;
3725 21 : return 1;
3726 : }
3727 :
3728 : static long
3729 49 : mfshimura_space_cusp(GEN mf)
3730 : {
3731 : long N4;
3732 49 : if (MF_get_r(mf) == 1 && (N4 = MF_get_N(mf) >> 2) >= 4)
3733 : {
3734 21 : GEN E = gel(myfactoru(N4), 2);
3735 21 : long ma = vecsmall_max(E);
3736 21 : if (ma > 2 || (ma == 2 && !mfcharistrivial(MF_get_CHI(mf)))) return 0;
3737 : }
3738 35 : return 1;
3739 : }
3740 :
3741 : static GEN
3742 56 : mfshifin(GEN mf2, GEN G)
3743 : {
3744 56 : GEN res = mftobasis_i(mf2, G);
3745 : /* not mflinear(mf2,): we want lowest possible level */
3746 56 : G = mflinear(MF_get_basis(mf2), res);
3747 56 : return mkvec3(mf2, G, res);
3748 : }
3749 :
3750 : /* t is either a positive squarefree integer or a fundamental
3751 : discriminant of sign (-1)^r. */
3752 : GEN
3753 63 : mfshimura(GEN mf, GEN F, long t)
3754 : {
3755 63 : pari_sp av = avma;
3756 : GEN G, mf2, CHI;
3757 63 : long sb, M, r, N, space = mf_FULL;
3758 :
3759 63 : if (!checkmf_i(F)) pari_err_TYPE("mfshimura",F);
3760 63 : mf = checkMF(mf);
3761 63 : r = MF_get_r(mf);
3762 63 : if (r <= 0) pari_err_DOMAIN("mfshimura", "weight", "<=", ghalf, mf_get_gk(F));
3763 63 : if (t <= 0 || !uissquarefree(t))
3764 : {
3765 14 : GEN gD = stoi(t);
3766 14 : if (!t || !isfundamental(gD) || (t < 0 && !odd(r)) || (t > 0 && odd(r)))
3767 7 : pari_err_TYPE("mfshimura [t]", stoi(t));
3768 7 : if (odd(t)) t = -t;
3769 : else
3770 : {
3771 : GEN SH;
3772 7 : if (t < 0) t = -t;
3773 7 : SH = mfshimura(mf, F, t >> 2); mf2 = gel(SH, 1);
3774 7 : G = mfhecke(mf2, gel(SH, 2), 2);
3775 7 : return gc_GEN(av, mfshifin(mf2, G));
3776 : }
3777 : }
3778 49 : N = MF_get_N(mf); M = N >> 1;
3779 49 : if (mfiscuspidal(mf,F))
3780 : {
3781 35 : if (mfshimura_space_cusp(mf)) space = mf_CUSP;
3782 35 : if (mfisinkohnen(mf,F)) M = N >> 2;
3783 : }
3784 49 : CHI = MF_get_CHI(mf);
3785 49 : mf2 = mfinit_Nkchi(M, r << 1, mfcharpow(CHI, gen_2), space, 0);
3786 49 : sb = mfsturm(mf2);
3787 49 : G = RgV_shimura(mfcoefs_i(F, sb*sb, t), sb, t, N, r, CHI);
3788 49 : return gc_GEN(av, mfshifin(mf2, G));
3789 : }
3790 :
3791 : /* W ZabM (ZM if n = 1), a t_INT or NULL, b t_INT, ZXQ mod P or NULL.
3792 : * Write a/b = A/d with d t_INT and A Zab return [W,d,A,P] */
3793 : static GEN
3794 7819 : mkMinv(GEN W, GEN a, GEN b, GEN P)
3795 : {
3796 7819 : GEN A = (b && typ(b) == t_POL)? Q_remove_denom(QXQ_inv(b,P), &b): NULL;
3797 7819 : if (a && b)
3798 : {
3799 1358 : a = Qdivii(a,b);
3800 1358 : if (typ(a) == t_INT) b = gen_1; else { b = gel(a,2); a = gel(a,1); }
3801 1358 : if (is_pm1(a)) a = NULL;
3802 : }
3803 7819 : if (a) A = A? ZX_Z_mul(A,a): a; else if (!A) A = gen_1;
3804 7819 : if (!b) b = gen_1;
3805 7819 : if (!P) P = gen_0;
3806 7819 : return mkvec4(W,b,A,P);
3807 : }
3808 : /* M square invertible QabM, return [M',d], M*M' = d*Id */
3809 : static GEN
3810 609 : QabM_Minv(GEN M, GEN P, long n)
3811 : {
3812 : GEN dW, W, dM;
3813 609 : M = Q_remove_denom(M, &dM);
3814 609 : W = P? ZabM_inv(liftpol_shallow(M), P, n, &dW): ZM_inv(M, &dW);
3815 609 : return mkMinv(W, dM, dW, P);
3816 : }
3817 : /* Simplified form of mfclean, after a QabM_indexrank: M a ZabM with full
3818 : * column rank and z = indexrank(M) is known */
3819 : static GEN
3820 861 : mfclean2(GEN M, GEN z, GEN P, long n)
3821 : {
3822 861 : GEN d, Minv, y = gel(z,1), W = rowpermute(M, y);
3823 861 : W = P? ZabM_inv(liftpol_shallow(W), P, n, &d): ZM_inv(W, &d);
3824 861 : M = rowslice(M, 1, y[lg(y)-1]);
3825 861 : Minv = mkMinv(W, NULL, d, P);
3826 861 : return mkvec3(y, Minv, M);
3827 : }
3828 : /* M QabM, lg(M)>1 and [y,z] its rank profile. Let Minv be the inverse of the
3829 : * invertible square matrix in mkMinv format. Return [y,Minv, M[..y[#y],]]
3830 : * P cyclotomic polynomial of order n > 2 or NULL */
3831 : static GEN
3832 5047 : mfclean(GEN M, GEN P, long n, int ratlift)
3833 : {
3834 5047 : GEN W, v, y, z, d, Minv, dM, MdM = Q_remove_denom(M, &dM);
3835 5047 : if (n <= 2)
3836 3941 : W = ZM_pseudoinv(MdM, &v, &d);
3837 : else
3838 1106 : W = ZabM_pseudoinv_i(liftpol_shallow(MdM), P, n, &v, &d, ratlift);
3839 5047 : y = gel(v,1);
3840 5047 : z = gel(v,2);
3841 5047 : if (lg(z) != lg(MdM)) M = vecpermute(M,z);
3842 5047 : M = rowslice(M, 1, y[lg(y)-1]);
3843 5047 : Minv = mkMinv(W, dM, d, P);
3844 5047 : return mkvec3(y, Minv, M);
3845 : }
3846 : /* call mfclean using only CHI */
3847 : static GEN
3848 4095 : mfcleanCHI(GEN M, GEN CHI, int ratlift)
3849 : {
3850 4095 : long n = mfcharorder(CHI);
3851 4095 : GEN P = (n <= 2)? NULL: mfcharpol(CHI);
3852 4095 : return mfclean(M, P, n, ratlift);
3853 : }
3854 :
3855 : /* DATA component of a t_MF_NEWTRACE. Was it stripped to save memory ? */
3856 : static int
3857 34601 : newtrace_stripped(GEN DATA)
3858 34601 : { return DATA && (lg(DATA) == 5 && typ(gel(DATA,3)) == t_INT); }
3859 : /* f a t_MF_NEWTRACE */
3860 : static GEN
3861 34601 : newtrace_DATA(long N, GEN f)
3862 : {
3863 34601 : GEN DATA = gel(f,2);
3864 34601 : return newtrace_stripped(DATA)? initnewtrace(N, DATA): DATA;
3865 : }
3866 : /* reset cachenew for new level incorporating new DATA, tf a t_MF_NEWTRACE
3867 : * (+ possibly initialize 'full' for new allowed levels) */
3868 : static void
3869 34601 : reset_cachenew(cachenew_t *cache, long N, GEN tf)
3870 : {
3871 : long i, n, l;
3872 34601 : GEN v, DATA = newtrace_DATA(N,tf);
3873 34601 : cache->DATA = DATA;
3874 34601 : if (!DATA) return;
3875 34496 : n = cache->n;
3876 34496 : v = cache->vfull; l = N+1; /* = lg(DATA) */
3877 2223592 : for (i = 1; i < l; i++)
3878 2189096 : if (typ(gel(v,i)) == t_INT && lg(gel(DATA,i)) != 1)
3879 54551 : gel(v,i) = const_vec(n, NULL);
3880 34496 : cache->VCHIP = gel(gel(DATA,N),_VCHIP);
3881 : }
3882 : /* initialize a cache of newtrace / cusptrace up to index n and level | N;
3883 : * DATA may be NULL (<=> Tr^new = 0). tf a t_MF_NEWTRACE */
3884 : static void
3885 13650 : init_cachenew(cachenew_t *cache, long n, long N, GEN tf)
3886 : {
3887 13650 : long i, l = N+1; /* = lg(tf.DATA) when DATA != NULL */
3888 : GEN v;
3889 13650 : cache->n = n;
3890 13650 : cache->vnew = v = cgetg(l, t_VEC);
3891 957593 : for (i = 1; i < l; i++) gel(v,i) = (N % i)? gen_0: const_vec(n, NULL);
3892 13650 : cache->newHIT = cache->newTOTAL = cache->cuspHIT = cache->cuspTOTAL = 0;
3893 13650 : cache->vfull = v = zerovec(N);
3894 13650 : reset_cachenew(cache, N, tf);
3895 13650 : }
3896 : static void
3897 17780 : dbg_cachenew(cachenew_t *C)
3898 : {
3899 17780 : if (DEBUGLEVEL >= 2 && C)
3900 0 : err_printf("newtrace cache hits: new = %ld/%ld, cusp = %ld/%ld\n",
3901 : C->newHIT, C->newTOTAL, C->cuspHIT, C->cuspTOTAL);
3902 17780 : }
3903 :
3904 : /* newtrace_{N,k}(d*i), i = n0, ..., n */
3905 : static GEN
3906 185598 : colnewtrace(long n0, long n, long d, long N, long k, cachenew_t *cache)
3907 : {
3908 185598 : GEN v = cgetg(n-n0+2, t_COL);
3909 : long i;
3910 4831841 : for (i = n0; i <= n; i++) gel(v, i-n0+1) = mfnewtracecache(N, k, i*d, cache);
3911 185598 : return v;
3912 : }
3913 : /* T_n(l*m0, l*(m0+1), ..., l*m) F, F = t_MF_NEWTRACE [N,k],DATA, cache
3914 : * contains DATA != NULL as well as cached values of F */
3915 : static GEN
3916 91581 : heckenewtrace(long m0, long m, long l, long N, long NBIG, long k, long n, cachenew_t *cache)
3917 : {
3918 91581 : long lD, a, k1, nl = n*l;
3919 91581 : GEN D, V, v = colnewtrace(m0, m, nl, N, k, cache); /* d=1 */
3920 : GEN VCHIP;
3921 91581 : if (n == 1) return v;
3922 63259 : VCHIP = cache->VCHIP;
3923 63259 : D = mydivisorsu(u_ppo(n, NBIG)); lD = lg(D);
3924 63259 : k1 = k - 1;
3925 155358 : for (a = 2; a < lD; a++)
3926 : { /* d > 1, (d,NBIG) = 1 */
3927 92099 : long i, j, d = D[a], c = ugcd(l, d), dl = d/c, m0d = ceildivuu(m0, dl);
3928 92099 : GEN C = vchip_lift(VCHIP, d, powuu(d, k1));
3929 : /* m0=0: i = 1 => skip F(0) = 0 */
3930 92099 : if (!m0) { i = 1; j = dl; } else { i = 0; j = m0d*dl; }
3931 92099 : V = colnewtrace(m0d, m/dl, nl/(d*c), N, k, cache);
3932 : /* C = chi(d) d^(k-1) */
3933 1105314 : for (; j <= m; i++, j += dl)
3934 1013215 : gel(v,j-m0+1) = gadd(gel(v,j-m0+1), vchip_mod(VCHIP, gmul(C,gel(V,i+1))));
3935 : }
3936 63259 : return v;
3937 : }
3938 :
3939 : /* Given v = an[i], return an[d*i], i=0..n */
3940 : static GEN
3941 2646 : anextract(GEN v, long n, long d)
3942 : {
3943 2646 : long i, id, l = n + 2;
3944 2646 : GEN w = cgetg(l, t_VEC);
3945 2646 : if (d == 1)
3946 7322 : for (i = 1; i < l; i++) gel(w, i) = gel(v, i);
3947 : else
3948 22169 : for (i = id = 1; i < l; i++, id += d) gel(w, i) = gel(v, id);
3949 2646 : return w;
3950 : }
3951 : /* T_n(F)(0, l, ..., l*m) */
3952 : static GEN
3953 2723 : hecke_i(long m, long l, GEN V, GEN F, GEN DATA)
3954 : {
3955 : long k, n, nNBIG, NBIG, lD, M, a, t, nl;
3956 : GEN D, v, CHI;
3957 2723 : if (typ(DATA) == t_VEC)
3958 : { /* 1/2-integral k */
3959 98 : if (!V) { GEN S = gel(DATA,2); V = mfcoefs_i(F, m*l*S[3], S[4]); }
3960 98 : return RgV_heckef2(m, l, V, F, DATA);
3961 : }
3962 2625 : k = mf_get_k(F);
3963 2625 : n = DATA[1]; nl = n*l;
3964 2625 : nNBIG = DATA[2];
3965 2625 : NBIG = DATA[3];
3966 2625 : if (nNBIG == 1) return V? V: mfcoefs_i(F,m,nl);
3967 1869 : if (!V && mf_get_type(F) == t_MF_NEWTRACE)
3968 : { /* inline F to allow cache, T_n at level NBIG acting on Tr^new(N,k,CHI) */
3969 : cachenew_t cache;
3970 546 : long N = mf_get_N(F);
3971 546 : init_cachenew(&cache, m*nl, N, F);
3972 546 : v = heckenewtrace(0, m, l, N, NBIG, k, n, &cache);
3973 546 : dbg_cachenew(&cache);
3974 546 : settyp(v, t_VEC); return v;
3975 : }
3976 1323 : CHI = mf_get_CHI(F);
3977 1323 : D = mydivisorsu(nNBIG); lD = lg(D);
3978 1323 : M = m + 1;
3979 1323 : t = nNBIG * ugcd(nNBIG, l);
3980 1323 : if (!V) V = mfcoefs_i(F, m * t, nl / t); /* usually nl = t */
3981 1323 : v = anextract(V, m, t); /* mfcoefs(F, m, nl); d = 1 */
3982 2646 : for (a = 2; a < lD; a++)
3983 : { /* d > 1, (d, NBIG) = 1 */
3984 1323 : long d = D[a], c = ugcd(l, d), dl = d/c, i, idl;
3985 1323 : GEN chi = mfchareval(CHI, d);
3986 1323 : GEN C = k ? gmul(chi, powuu(d, k-1)): chi;
3987 1323 : GEN w = anextract(V, m/dl, t/(d*c)); /* mfcoefs(F, m/dl, nl/(d*c)) */
3988 7322 : for (i = idl = 1; idl <= M; i++, idl += dl)
3989 5999 : gel(v,idl) = gadd(gel(v,idl), gmul(C, gel(w,i)));
3990 : }
3991 1323 : return v;
3992 : }
3993 :
3994 : static GEN
3995 12544 : mkmf(GEN x1, GEN x2, GEN x3, GEN x4, GEN x5)
3996 : {
3997 12544 : GEN MF = obj_init(5, MF_SPLITN);
3998 12544 : gel(MF,1) = x1;
3999 12544 : gel(MF,2) = x2;
4000 12544 : gel(MF,3) = x3;
4001 12544 : gel(MF,4) = x4;
4002 12544 : gel(MF,5) = x5; return MF;
4003 : }
4004 :
4005 : /* return an integer b such that p | b => T_p^k Tr^new = 0, for all k > 0 */
4006 : static long
4007 7756 : get_badj(long N, long FC)
4008 : {
4009 7756 : GEN fa = myfactoru(N), P = gel(fa,1), E = gel(fa,2);
4010 7756 : long i, b = 1, l = lg(P);
4011 20587 : for (i = 1; i < l; i++)
4012 12831 : if (E[i] > 1 && u_lval(FC, P[i]) < E[i]) b *= P[i];
4013 7756 : return b;
4014 : }
4015 : /* in place, assume perm strictly increasing */
4016 : static void
4017 1372 : vecpermute_inplace(GEN v, GEN perm)
4018 : {
4019 1372 : long i, l = lg(perm);
4020 11914 : for (i = 1; i < l; i++) gel(v,i) = gel(v,perm[i]);
4021 1372 : }
4022 :
4023 : /* Find basis of newspace using closures; assume k >= 2 and !badchar.
4024 : * Return NULL if space is empty, else
4025 : * [mf1, list of closures T(j)traceform, list of corresponding j, matrix] */
4026 : static GEN
4027 15757 : mfnewinit(long N, long k, GEN CHI, cachenew_t *cache, long init)
4028 : {
4029 : GEN S, vj, M, CHIP, mf1, listj, P, tf;
4030 : long j, ct, ctlj, dim, jin, SB, sb, two, ord, FC, badj;
4031 :
4032 15757 : dim = mfnewdim(N, k, CHI);
4033 15757 : if (!dim && !init) return NULL;
4034 7756 : sb = mfsturmNk(N, k);
4035 7756 : CHIP = mfchartoprimitive(CHI, &FC);
4036 : /* remove newtrace data from S to save space in output: negligible slowdown */
4037 7756 : tf = tag(t_MF_NEWTRACE, mkNK(N,k,CHIP), CHIP);
4038 7756 : badj = get_badj(N, FC);
4039 : /* try sbsmall first: Sturm bound not sharp for new space */
4040 7756 : SB = ceilA1(N, k);
4041 7756 : listj = cgetg(2*sb + 3, t_VECSMALL);
4042 377461 : for (j = ctlj = 1; ctlj < 2*sb + 3; j++)
4043 369705 : if (ugcd(j, badj) == 1) listj[ctlj++] = j;
4044 7756 : if (init)
4045 : {
4046 4200 : init_cachenew(cache, (SB+1)*listj[dim+1], N, tf);
4047 4200 : if (init == -1 || !dim) return NULL; /* old space or dim = 0 */
4048 : }
4049 : else
4050 3556 : reset_cachenew(cache, N, tf);
4051 : /* cache.DATA is not NULL */
4052 7287 : ord = mfcharorder(CHIP);
4053 7287 : P = ord <= 2? NULL: mfcharpol(CHIP);
4054 7287 : vj = cgetg(dim+1, t_VECSMALL);
4055 7287 : M = cgetg(dim+1, t_MAT);
4056 7294 : for (two = 1, ct = 0, jin = 1; two <= 2; two++)
4057 : {
4058 7294 : long a, jlim = jin + sb;
4059 22876 : for (a = jin; a <= jlim; a++)
4060 : {
4061 : GEN z, vecz;
4062 22869 : ct++; vj[ct] = listj[a];
4063 22869 : gel(M, ct) = heckenewtrace(0, SB, 1, N, N, k, vj[ct], cache);
4064 22869 : if (ct < dim) continue;
4065 :
4066 7973 : z = QabM_indexrank(M, P, ord);
4067 7973 : vecz = gel(z, 2); ct = lg(vecz) - 1;
4068 7973 : if (ct == dim) { M = mkvec3(z, gen_0, M); break; } /*maximal rank, done*/
4069 686 : vecpermute_inplace(M, vecz);
4070 686 : vecpermute_inplace(vj, vecz);
4071 : }
4072 7294 : if (a <= jlim) break;
4073 : /* sbsmall was not sufficient, use Sturm bound: must extend M */
4074 70 : for (j = 1; j <= ct; j++)
4075 : {
4076 63 : GEN t = heckenewtrace(SB + 1, sb, 1, N, N, k, vj[j], cache);
4077 63 : gel(M,j) = shallowconcat(gel(M, j), t);
4078 : }
4079 7 : jin = jlim + 1; SB = sb;
4080 : }
4081 7287 : S = cgetg(dim + 1, t_VEC);
4082 29428 : for (j = 1; j <= dim; j++) gel(S, j) = mfhecke_i(vj[j], N, tf);
4083 7287 : dbg_cachenew(cache);
4084 7287 : mf1 = mkvec4(utoipos(N), utoipos(k), CHI, utoi(mf_NEW));
4085 7287 : return mkmf(mf1, cgetg(1,t_VEC), S, vj, M);
4086 : }
4087 : /* k > 1 integral, mf space is mf_CUSP or mf_FULL */
4088 : static GEN
4089 49 : mfinittonew(GEN mf)
4090 : {
4091 49 : GEN CHI = MF_get_CHI(mf), S = MF_get_S(mf), vMjd = MFcusp_get_vMjd(mf);
4092 49 : GEN M = MF_get_M(mf), vj, mf1;
4093 49 : long i, j, l, l0 = lg(S), N0 = MF_get_N(mf);
4094 252 : for (i = l0-1; i > 0; i--)
4095 : {
4096 238 : long N = gel(vMjd,i)[1];
4097 238 : if (N != N0) break;
4098 : }
4099 49 : if (i == l0-1) return NULL;
4100 42 : S = vecslice(S, i+1, l0-1); /* forms of conductor N0 */
4101 42 : l = lg(S); vj = cgetg(l, t_VECSMALL);
4102 245 : for (j = 1; j < l; j++) vj[j] = gel(vMjd,j+i)[2];
4103 42 : M = vecslice(M, lg(M)-lg(S)+1, lg(M)-1); /* their coefficients */
4104 42 : M = mfcleanCHI(M, CHI, 0);
4105 42 : mf1 = mkvec4(utoipos(N0), MF_get_gk(mf), CHI, utoi(mf_NEW));
4106 42 : return mkmf(mf1, cgetg(1,t_VEC), S, vj, M);
4107 : }
4108 :
4109 : /* Bd(f)[m0..m], v = f[ceil(m0/d)..floor(m/d)], m0d = ceil(m0/d) */
4110 : static GEN
4111 84665 : RgC_Bd_expand(long m0, long m, GEN v, long d, long m0d)
4112 : {
4113 : long i, j;
4114 : GEN w;
4115 84665 : if (d == 1) return v;
4116 24080 : w = zerocol(m-m0+1);
4117 24080 : if (!m0) { i = 1; j = d; } else { i = 0; j = m0d*d; }
4118 477421 : for (; j <= m; i++, j += d) gel(w,j-m0+1) = gel(v,i+1);
4119 24080 : return w;
4120 : }
4121 : /* S a nonempty vector of t_MF_BD(t_MF_HECKE(t_MF_NEWTRACE)); M the matrix
4122 : * of their coefficients r*0, r*1, ..., r*m0 (~ mfvectomat) or NULL (empty),
4123 : * extend it to coeffs up to m > m0. The forms B_d(T_j(tf_N))in S should be
4124 : * sorted by level N, then j, then increasing d. No reordering here. */
4125 : static GEN
4126 9282 : bhnmat_extend(GEN M, long m, long r, GEN S, cachenew_t *cache)
4127 : {
4128 9282 : long i, mr, m0, m0r, Nold = 0, jold = 0, l = lg(S);
4129 9282 : GEN MAT = cgetg(l, t_MAT), v = NULL;
4130 9282 : if (M) { m0 = nbrows(M); m0r = m0 * r; } else m0 = m0r = 0;
4131 9282 : mr = m*r;
4132 93947 : for (i = 1; i < l; i++)
4133 : {
4134 : long d, j, md, N;
4135 84665 : GEN c, f = bhn_parse(gel(S,i), &d,&j); /* t_MF_NEWTRACE */
4136 84665 : N = mf_get_N(f);
4137 84665 : md = ceildivuu(m0r,d);
4138 84665 : if (N != Nold) { reset_cachenew(cache, N, f); Nold = N; jold = 0; }
4139 84665 : if (!cache->DATA) { gel(MAT,i) = zerocol(m+1); continue; }
4140 84665 : if (j != jold || md)
4141 68103 : { v = heckenewtrace(md, mr/d, 1, N, N, mf_get_k(f), j,cache); jold=j; }
4142 84665 : c = RgC_Bd_expand(m0r, mr, v, d, md);
4143 84665 : if (r > 1) c = c_deflate(m-m0, r, c);
4144 84665 : if (M) c = shallowconcat(gel(M,i), c);
4145 84665 : gel(MAT,i) = c;
4146 : }
4147 9282 : return MAT;
4148 : }
4149 :
4150 : /* k > 1 */
4151 : static GEN
4152 3269 : mfinitcusp(long N, long k, GEN CHI, cachenew_t *cache, long space)
4153 : {
4154 : long L, l, lDN1, FC, N1, d1, i, init;
4155 3269 : GEN vS, vMjd, DN1, vmf, CHIP = mfchartoprimitive(CHI, &FC);
4156 :
4157 3269 : d1 = (space == mf_OLD)? mfolddim_i(N, k, CHIP, NULL): mfcuspdim(N, k, CHIP);
4158 3269 : if (!d1) return NULL;
4159 2961 : N1 = N/FC; DN1 = mydivisorsu(N1); lDN1 = lg(DN1);
4160 2961 : init = (space == mf_OLD)? -1: 1;
4161 2961 : vmf = cgetg(lDN1, t_VEC);
4162 17479 : for (i = lDN1 - 1, l = 1; i; i--)
4163 : { /* by decreasing level to allow cache */
4164 14518 : GEN mf = mfnewinit(FC*DN1[i], k, CHIP, cache, init);
4165 14518 : if (mf) gel(vmf, l++) = mf;
4166 14518 : init = 0;
4167 : }
4168 2961 : setlg(vmf,l); vmf = vecreverse(vmf); /* reorder by increasing level */
4169 :
4170 2961 : L = mfsturmNk(N, k)+1;
4171 2961 : vS = vectrunc_init(L);
4172 2961 : vMjd = vectrunc_init(L);
4173 9380 : for (i = 1; i < l; i++)
4174 : {
4175 6419 : GEN DNM, mf = gel(vmf,i), S = MF_get_S(mf), vj = MFnew_get_vj(mf);
4176 6419 : long a, lDNM, lS = lg(S), M = MF_get_N(mf);
4177 6419 : DNM = mydivisorsu(N / M); lDNM = lg(DNM);
4178 26404 : for (a = 1; a < lS; a++)
4179 : {
4180 19985 : GEN tf = gel(S,a);
4181 19985 : long b, j = vj[a];
4182 49553 : for (b = 1; b < lDNM; b++)
4183 : {
4184 29568 : long d = DNM[b];
4185 29568 : vectrunc_append(vS, mfbd_i(tf, d));
4186 29568 : vectrunc_append(vMjd, mkvecsmall3(M, j, d));
4187 : }
4188 : }
4189 : }
4190 2961 : return mkmf(NULL, cgetg(1, t_VEC), vS, vMjd, NULL);
4191 : }
4192 :
4193 : long
4194 4592 : mfsturm_mf(GEN mf)
4195 : {
4196 4592 : GEN Mindex = MF_get_Mindex(mf);
4197 4592 : long n = lg(Mindex)-1;
4198 4592 : return n? Mindex[n]-1: 0;
4199 : }
4200 :
4201 : long
4202 833 : mfsturm(GEN T)
4203 : {
4204 : long N, nk, dk;
4205 833 : GEN CHI, mf = checkMF_i(T);
4206 833 : if (mf) return mfsturm_mf(mf);
4207 7 : checkNK2(T, &N, &nk, &dk, &CHI, 0);
4208 7 : return dk == 1 ? mfsturmNk(N, nk) : mfsturmNk(N, (nk + 1) >> 1);
4209 : }
4210 : long
4211 196 : mfisequal(GEN F, GEN G, long lim)
4212 : {
4213 196 : pari_sp av = avma;
4214 : long b;
4215 196 : if (!checkmf_i(F)) pari_err_TYPE("mfisequal",F);
4216 196 : if (!checkmf_i(G)) pari_err_TYPE("mfisequal",G);
4217 196 : b = lim? lim: maxss(mfsturmmf(F), mfsturmmf(G));
4218 196 : return gc_long(av, gequal(mfcoefs_i(F, b, 1), mfcoefs_i(G, b, 1)));
4219 : }
4220 :
4221 : GEN
4222 35 : mffields(GEN mf)
4223 : {
4224 35 : if (checkmf_i(mf)) return gcopy(mf_get_field(mf));
4225 35 : mf = checkMF(mf); return gcopy(MF_get_fields(mf));
4226 : }
4227 :
4228 : GEN
4229 364 : mfeigenbasis(GEN mf)
4230 : {
4231 364 : pari_sp ltop = avma;
4232 : GEN F, S, v, vP;
4233 : long i, l, k, dS;
4234 :
4235 364 : mf = checkMF(mf);
4236 364 : k = MF_get_k(mf);
4237 364 : S = MF_get_S(mf); dS = lg(S)-1;
4238 364 : if (!dS) return cgetg(1, t_VEC);
4239 357 : F = MF_get_newforms(mf);
4240 357 : vP = MF_get_fields(mf);
4241 357 : if (k == 1)
4242 : {
4243 210 : if (MF_get_space(mf) == mf_FULL)
4244 : {
4245 14 : long dE = lg(MF_get_E(mf)) - 1;
4246 14 : if (dE) F = rowslice(F, dE+1, dE+dS);
4247 : }
4248 210 : v = vecmflineardiv_linear(S, F);
4249 210 : l = lg(v);
4250 : }
4251 : else
4252 : {
4253 147 : GEN (*L)(GEN, GEN) = (MF_get_space(mf) == mf_FULL)? mflinear: mflinear_bhn;
4254 147 : l = lg(F); v = cgetg(l, t_VEC);
4255 511 : for (i = 1; i < l; i++) gel(v,i) = L(mf, gel(F,i));
4256 : }
4257 945 : for (i = 1; i < l; i++) mf_setfield(gel(v,i), gel(vP,i));
4258 357 : return gc_GEN(ltop, v);
4259 : }
4260 :
4261 : /* Minv = [M, d, A], v a t_COL; A a Zab, d a t_INT; return (A/d) * M*v */
4262 : static GEN
4263 7938 : Minv_RgC_mul(GEN Minv, GEN v)
4264 : {
4265 7938 : GEN M = gel(Minv,1), d = gel(Minv,2), A = gel(Minv,3);
4266 7938 : v = RgM_RgC_mul(M, v);
4267 7938 : if (!equali1(A))
4268 : {
4269 2072 : if (typ(A) == t_POL && degpol(A) > 0) A = mkpolmod(A, gel(Minv,4));
4270 2072 : v = RgC_Rg_mul(v, A);
4271 : }
4272 7938 : if (!equali1(d)) v = RgC_Rg_div(v, d);
4273 7938 : return v;
4274 : }
4275 : static GEN
4276 1309 : Minv_RgM_mul(GEN Minv, GEN B)
4277 : {
4278 1309 : long j, l = lg(B);
4279 1309 : GEN M = cgetg(l, t_MAT);
4280 6090 : for (j = 1; j < l; j++) gel(M,j) = Minv_RgC_mul(Minv, gel(B,j));
4281 1309 : return M;
4282 : }
4283 : /* B * Minv; allow B = NULL for Id */
4284 : static GEN
4285 2450 : RgM_Minv_mul(GEN B, GEN Minv)
4286 : {
4287 2450 : GEN M = gel(Minv,1), d = gel(Minv,2), A = gel(Minv,3);
4288 2450 : if (B) M = RgM_mul(B, M);
4289 2450 : if (!equali1(A))
4290 : {
4291 980 : if (typ(A) == t_POL) A = mkpolmod(A, gel(Minv,4));
4292 980 : M = RgM_Rg_mul(M, A);
4293 : }
4294 2450 : if (!equali1(d)) M = RgM_Rg_div(M,d);
4295 2450 : return M;
4296 : }
4297 :
4298 : /* perm vector of strictly increasing indices, v a vector or arbitrary length;
4299 : * the last r entries of perm fall beyond v.
4300 : * Return v o perm[1..(-r)], discarding the last r entries of v */
4301 : static GEN
4302 1610 : vecpermute_partial(GEN v, GEN perm, long *r)
4303 : {
4304 1610 : long i, n = lg(v)-1, l = lg(perm);
4305 : GEN w;
4306 1610 : if (perm[l-1] <= n) { *r = 0; return vecpermute(v,perm); }
4307 63 : for (i = 1; i < l; i++)
4308 63 : if (perm[i] > n) break;
4309 21 : *r = l - i; l = i;
4310 21 : w = cgetg(l, typ(v));
4311 63 : for (i = 1; i < l; i++) gel(w,i) = gel(v,perm[i]);
4312 21 : return w;
4313 : }
4314 :
4315 : /* given form F, find coeffs of F on mfbasis(mf). If power series, not
4316 : * guaranteed correct if precision less than Sturm bound */
4317 : static GEN
4318 1449 : mftobasis_i(GEN mf, GEN F)
4319 : {
4320 : GEN v, Mindex, Minv;
4321 1449 : if (!MF_get_dim(mf)) return cgetg(1, t_COL);
4322 1449 : Mindex = MF_get_Mindex(mf);
4323 1449 : Minv = MF_get_Minv(mf);
4324 1449 : if (checkmf_i(F))
4325 : {
4326 294 : long n = Mindex[lg(Mindex)-1];
4327 294 : v = vecpermute(mfcoefs_i(F, n, 1), Mindex);
4328 294 : return Minv_RgC_mul(Minv, v);
4329 : }
4330 : else
4331 : {
4332 1155 : GEN A = gel(Minv,1), d = gel(Minv,2);
4333 : long r;
4334 1155 : v = F;
4335 1155 : switch(typ(F))
4336 : {
4337 0 : case t_SER: v = sertocol(v);
4338 1155 : case t_VEC: case t_COL: break;
4339 0 : default: pari_err_TYPE("mftobasis", F);
4340 : }
4341 1155 : if (lg(v) == 1) pari_err_TYPE("mftobasis",v);
4342 1155 : v = vecpermute_partial(v, Mindex, &r);
4343 1155 : if (!r) return Minv_RgC_mul(Minv, v); /* single solution */
4344 : /* affine space of dimension r */
4345 21 : v = RgM_RgC_mul(vecslice(A, 1, lg(v)-1), v);
4346 21 : if (!equali1(d)) v = RgC_Rg_div(v,d);
4347 21 : return mkvec2(v, vecslice(A, lg(A)-r, lg(A)-1));
4348 : }
4349 : }
4350 :
4351 : static GEN
4352 910 : const_mat(long n, GEN x)
4353 : {
4354 910 : long j, l = n+1;
4355 910 : GEN A = cgetg(l,t_MAT);
4356 6902 : for (j = 1; j < l; j++) gel(A,j) = const_col(n, x);
4357 910 : return A;
4358 : }
4359 :
4360 : /* L is the mftobasis of a form on CUSP space. We allow mf_FULL or mf_CUSP */
4361 : static GEN
4362 455 : mftonew_i(GEN mf, GEN L, long *plevel)
4363 : {
4364 : GEN S, listMjd, CHI, res, Aclos, Acoef, D, perm;
4365 455 : long N1, LC, lD, i, l, t, level, N = MF_get_N(mf);
4366 :
4367 455 : if (MF_get_k(mf) == 1) pari_err_IMPL("mftonew in weight 1");
4368 455 : listMjd = MFcusp_get_vMjd(mf);
4369 455 : CHI = MF_get_CHI(mf); LC = mfcharconductor(CHI);
4370 455 : S = MF_get_S(mf);
4371 :
4372 455 : N1 = N/LC;
4373 455 : D = mydivisorsu(N1); lD = lg(D);
4374 455 : perm = cgetg(N1+1, t_VECSMALL);
4375 3451 : for (i = 1; i < lD; i++) perm[D[i]] = i;
4376 455 : Aclos = const_mat(lD-1, cgetg(1,t_VEC));
4377 455 : Acoef = const_mat(lD-1, cgetg(1,t_VEC));
4378 455 : l = lg(listMjd);
4379 4669 : for (i = 1; i < l; i++)
4380 : {
4381 : long M, d;
4382 : GEN v;
4383 4214 : if (gequal0(gel(L,i))) continue;
4384 469 : v = gel(listMjd, i);
4385 469 : M = perm[ v[1]/LC ];
4386 469 : d = perm[ v[3] ];
4387 469 : gcoeff(Aclos,M,d) = vec_append(gcoeff(Aclos,M,d), gel(S,i));
4388 469 : gcoeff(Acoef,M,d) = shallowconcat(gcoeff(Acoef,M,d), gel(L,i));
4389 : }
4390 455 : res = cgetg(l, t_VEC); level = 1;
4391 3451 : for (i = t = 1; i < lD; i++)
4392 : {
4393 2996 : long j, M = D[i]*LC;
4394 2996 : GEN gM = utoipos(M);
4395 26530 : for (j = 1; j < lD; j++)
4396 : {
4397 23534 : GEN vf = gcoeff(Aclos,i,j), C, NK;
4398 : long d;
4399 23534 : if (lg(vf) == 1) continue;
4400 427 : d = D[j];
4401 427 : C = gcoeff(Acoef,i,j);
4402 427 : NK = mf_get_NK(gel(vf, 1));
4403 427 : if (d > 1)
4404 : { /* remove mfbd(, d) wrappers */
4405 175 : long h, lf = lg(vf);
4406 357 : for (h = 1; h < lf; h++)
4407 : {
4408 182 : GEN fd = gel(vf, h);
4409 182 : if (mf_get_type(fd) != t_MF_BD || !equaliu(gel(fd,3), d))
4410 0 : pari_err_BUG("mftonew [inconsistent multiplier]");
4411 182 : gel(vf, h) = gel(fd, 2);
4412 : }
4413 : }
4414 427 : level = ulcm(level, M*d);
4415 427 : gel(res,t++) = mkvec3(gM, utoipos(d), mflinear_i(NK,vf,C));
4416 : }
4417 : }
4418 455 : if (plevel) *plevel = level;
4419 455 : setlg(res, t); return res;
4420 : }
4421 : GEN
4422 217 : mftonew(GEN mf, GEN F)
4423 : {
4424 217 : pari_sp av = avma;
4425 : GEN ES;
4426 : long s;
4427 217 : mf = checkMF(mf);
4428 217 : s = MF_get_space(mf);
4429 217 : if (s != mf_FULL && s != mf_CUSP)
4430 7 : pari_err_TYPE("mftonew [not a full or cuspidal space]", mf);
4431 210 : ES = mftobasisES(mf,F);
4432 203 : if (!gequal0(gel(ES,1)))
4433 0 : pari_err_TYPE("mftonew [not a cuspidal form]", F);
4434 203 : F = gel(ES,2);
4435 203 : return gc_GEN(av, mftonew_i(mf,F, NULL));
4436 : }
4437 :
4438 : static GEN mfeisenstein_i(long k, GEN CHI1, GEN CHI2);
4439 :
4440 : /* mfinit(F * Theta) */
4441 : static GEN
4442 98 : mf2init(GEN mf)
4443 : {
4444 98 : GEN CHI = MF_get_CHI(mf), gk = gadd(MF_get_gk(mf), ghalf);
4445 98 : long N = MF_get_N(mf);
4446 98 : return mfinit_Nkchi(N, itou(gk), mfchiadjust(CHI, gk, N), mf_FULL, 0);
4447 : }
4448 :
4449 : static long
4450 637 : mfvec_first_cusp(GEN v)
4451 : {
4452 637 : long i, l = lg(v);
4453 1533 : for (i = 1; i < l; i++)
4454 : {
4455 1428 : GEN F = gel(v,i);
4456 1428 : long t = mf_get_type(F);
4457 1428 : if (t == t_MF_BD) { F = gel(F,2); t = mf_get_type(F); }
4458 1428 : if (t == t_MF_HECKE) { F = gel(F,3); t = mf_get_type(F); }
4459 1428 : if (t == t_MF_NEWTRACE) break;
4460 : }
4461 637 : return i;
4462 : }
4463 : /* vF a vector of mf F of type DIV(LINEAR(BAS,L), f) in (lcm) level N,
4464 : * F[2]=LINEAR(BAS,L), F[2][2]=BAS=fixed basis (Eisenstein or bhn type),
4465 : * F[2][3]=L, F[3]=f; mfvectomat(vF, n) */
4466 : static GEN
4467 644 : mflineardivtomat(long N, GEN vF, long n)
4468 : {
4469 644 : GEN F, M, f, fc, ME, dB, B, a0, V = NULL;
4470 644 : long lM, lF = lg(vF), j;
4471 :
4472 644 : if (lF == 1) return cgetg(1,t_MAT);
4473 637 : F = gel(vF,1);
4474 637 : if (lg(F) == 5)
4475 : { /* chicompat */
4476 273 : V = gmael(F,4,4);
4477 273 : if (typ(V) == t_INT) V = NULL;
4478 : }
4479 637 : M = gmael(F,2,2); /* BAS */
4480 637 : lM = lg(M);
4481 637 : j = mfvec_first_cusp(M);
4482 637 : if (j == 1) ME = NULL;
4483 : else
4484 : { /* BAS starts by Eisenstein */
4485 161 : ME = mfvectomat(vecslice(M,1,j-1), n, 1);
4486 161 : M = vecslice(M, j,lM-1);
4487 : }
4488 637 : M = bhnmat_extend_nocache(NULL, N, n, 1, M);
4489 637 : if (ME) M = shallowconcat(ME,M);
4490 : /* M = mfcoefs of BAS */
4491 637 : B = cgetg(lF, t_MAT);
4492 637 : dB= cgetg(lF, t_VEC);
4493 3157 : for (j = 1; j < lF; j++)
4494 : {
4495 2520 : GEN g = gel(vF, j); /* t_MF_DIV */
4496 2520 : gel(B,j) = RgM_RgC_mul(M, gmael(g,2,3));
4497 2520 : gel(dB,j)= gmael(g,2,4);
4498 : }
4499 637 : f = mfcoefsser(gel(F,3),n);
4500 637 : a0 = polcoef_i(f, 0, -1);
4501 637 : if (gequal0(a0) || gequal1(a0))
4502 336 : a0 = NULL;
4503 : else
4504 301 : f = gdiv(ser_unscale(f, a0), a0);
4505 637 : fc = ginv(f);
4506 3157 : for (j = 1; j < lF; j++)
4507 : {
4508 2520 : pari_sp av = avma;
4509 2520 : GEN LISer = RgV_to_ser_full(gel(B,j)), f;
4510 2520 : if (a0) LISer = gdiv(ser_unscale(LISer, a0), a0);
4511 2520 : f = gmul(LISer, fc);
4512 2520 : if (a0) f = ser_unscale(f, ginv(a0));
4513 2520 : f = sertocol(f); setlg(f, n+2);
4514 2520 : if (!gequal1(gel(dB,j))) f = RgC_Rg_div(f, gel(dB,j));
4515 2520 : gel(B,j) = gc_upto(av,f);
4516 : }
4517 637 : if (V) B = gmodulo(QabM_tracerel(V, 0, B), gel(V,1));
4518 637 : return B;
4519 : }
4520 :
4521 : static GEN
4522 350 : mfheckemat_mfcoefs(GEN mf, GEN B, GEN DATA)
4523 : {
4524 350 : GEN Mindex = MF_get_Mindex(mf), Minv = MF_get_Minv(mf);
4525 350 : long j, l = lg(B), sb = mfsturm_mf(mf);
4526 350 : GEN b = MF_get_basis(mf), Q = cgetg(l, t_VEC);
4527 1827 : for (j = 1; j < l; j++)
4528 : {
4529 1477 : GEN v = hecke_i(sb, 1, gel(B,j), gel(b,j), DATA); /* Tn b[j] */
4530 1477 : settyp(v,t_COL); gel(Q,j) = vecpermute(v, Mindex);
4531 : }
4532 350 : return Minv_RgM_mul(Minv,Q);
4533 : }
4534 : /* T_p^2, p prime, 1/2-integral weight; B = mfcoefs(mf,sb*p^2,1) or (mf,sb,p^2)
4535 : * if p|N */
4536 : static GEN
4537 7 : mfheckemat_mfcoefs_p2(GEN mf, long p, GEN B)
4538 : {
4539 7 : pari_sp av = avma;
4540 7 : GEN DATA = heckef2_data(MF_get_N(mf), p*p);
4541 7 : return gc_upto(av, mfheckemat_mfcoefs(mf, B, DATA));
4542 : }
4543 : /* convert Mindex from row-index to mfcoef indexation: a(n) is stored in
4544 : * mfcoefs()[n+1], so subtract 1 from all indices */
4545 : static GEN
4546 49 : Mindex_as_coef(GEN mf)
4547 : {
4548 49 : GEN v, Mindex = MF_get_Mindex(mf);
4549 49 : long i, l = lg(Mindex);
4550 49 : v = cgetg(l, t_VECSMALL);
4551 210 : for (i = 1; i < l; i++) v[i] = Mindex[i]-1;
4552 49 : return v;
4553 : }
4554 : /* T_p, p prime; B = mfcoefs(mf,sb*p,1) or (mf,sb,p) if p|N; integral weight */
4555 : static GEN
4556 35 : mfheckemat_mfcoefs_p(GEN mf, long p, GEN B)
4557 : {
4558 35 : pari_sp av = avma;
4559 35 : GEN vm, Q, C, Minv = MF_get_Minv(mf);
4560 35 : long lm, k, i, j, l = lg(B), N = MF_get_N(mf);
4561 :
4562 35 : if (N % p == 0) return Minv_RgM_mul(Minv, rowpermute(B, MF_get_Mindex(mf)));
4563 21 : k = MF_get_k(mf);
4564 21 : C = gmul(mfchareval(MF_get_CHI(mf), p), powuu(p, k-1));
4565 21 : vm = Mindex_as_coef(mf); lm = lg(vm);
4566 21 : Q = cgetg(l, t_MAT);
4567 147 : for (j = 1; j < l; j++) gel(Q,j) = cgetg(lm, t_COL);
4568 147 : for (i = 1; i < lm; i++)
4569 : {
4570 126 : long m = vm[i], mp = m*p;
4571 126 : GEN Cm = (m % p) == 0? C : NULL;
4572 1260 : for (j = 1; j < l; j++)
4573 : {
4574 1134 : GEN S = gel(B,j), s = gel(S, mp + 1);
4575 1134 : if (Cm) s = gadd(s, gmul(C, gel(S, m/p + 1)));
4576 1134 : gcoeff(Q, i, j) = s;
4577 : }
4578 : }
4579 21 : return gc_upto(av, Minv_RgM_mul(Minv,Q));
4580 : }
4581 : /* Matrix of T(p), p prime, dim(mf) > 0 and integral weight */
4582 : static GEN
4583 343 : mfheckemat_p(GEN mf, long p)
4584 : {
4585 343 : pari_sp av = avma;
4586 343 : long N = MF_get_N(mf), sb = mfsturm_mf(mf);
4587 343 : GEN B = (N % p)? mfcoefs_mf(mf, sb * p, 1): mfcoefs_mf(mf, sb, p);
4588 343 : return gc_upto(av, mfheckemat_mfcoefs(mf, B, hecke_data(N,p)));
4589 : }
4590 :
4591 : /* mf_NEW != (0), weight > 1, p prime. Use
4592 : * T(p) T(j) = T(j*p) + p^{k-1} \chi(p) 1_{p | j, p \nmid N} T(j/p) */
4593 : static GEN
4594 924 : mfnewmathecke_p(GEN mf, long p)
4595 : {
4596 924 : pari_sp av = avma;
4597 924 : GEN tf, vj = MFnew_get_vj(mf), CHI = MF_get_CHI(mf);
4598 924 : GEN Mindex = MF_get_Mindex(mf), Minv = MF_get_Minv(mf);
4599 924 : long N = MF_get_N(mf), k = MF_get_k(mf);
4600 924 : long i, j, lvj = lg(vj), lim = vj[lvj-1] * p;
4601 924 : GEN M, perm, V, need = zero_zv(lim);
4602 924 : GEN C = (N % p)? gmul(mfchareval(CHI,p), powuu(p,k-1)): NULL;
4603 924 : tf = mftraceform_new(N, k, CHI);
4604 4004 : for (i = 1; i < lvj; i++)
4605 : {
4606 3080 : j = vj[i]; need[j*p] = 1;
4607 3080 : if (N % p && j % p == 0) need[j/p] = 1;
4608 : }
4609 924 : perm = zero_zv(lim);
4610 924 : V = cgetg(lim+1, t_VEC);
4611 12754 : for (i = j = 1; i <= lim; i++)
4612 11830 : if (need[i]) { gel(V,j) = mfhecke_i(i, N, tf); perm[i] = j; j++; }
4613 924 : setlg(V, j);
4614 924 : V = bhnmat_extend_nocache(NULL, N, mfsturm_mf(mf), 1, V);
4615 924 : V = rowpermute(V, Mindex); /* V[perm[i]] = coeffs(T_i newtrace) */
4616 924 : M = cgetg(lvj, t_MAT);
4617 4004 : for (i = 1; i < lvj; i++)
4618 : {
4619 : GEN t;
4620 3080 : j = vj[i]; t = gel(V, perm[j*p]);
4621 3080 : if (C && j % p == 0) t = RgC_add(t, RgC_Rg_mul(gel(V, perm[j/p]),C));
4622 3080 : gel(M,i) = t;
4623 : }
4624 924 : return gc_upto(av, Minv_RgM_mul(Minv, M));
4625 : }
4626 :
4627 : GEN
4628 77 : mfheckemat(GEN mf, GEN vn)
4629 : {
4630 77 : pari_sp av = avma;
4631 77 : long lv, lvP, i, N, dim, nk, dk, p, sb, flint = (typ(vn)==t_INT);
4632 : GEN CHI, res, vT, FA, B, vP;
4633 :
4634 77 : mf = checkMF(mf);
4635 77 : if (typ(vn) != t_VECSMALL) vn = gtovecsmall(vn);
4636 77 : N = MF_get_N(mf); CHI = MF_get_CHI(mf); Qtoss(MF_get_gk(mf), &nk, &dk);
4637 77 : dim = MF_get_dim(mf);
4638 77 : lv = lg(vn);
4639 77 : res = cgetg(lv, t_VEC);
4640 77 : FA = cgetg(lv, t_VEC);
4641 77 : vP = cgetg(lv, t_VEC);
4642 77 : vT = const_vec(vecsmall_max(vn), NULL);
4643 182 : for (i = 1; i < lv; i++)
4644 : {
4645 105 : ulong n = (ulong)labs(vn[i]);
4646 : GEN fa;
4647 105 : if (!n) pari_err_TYPE("mfheckemat", vn);
4648 105 : if (dk == 1 || uissquareall(n, &n)) fa = myfactoru(n);
4649 0 : else { n = 0; fa = myfactoru(1); } /* dummy: T_{vn[i]} = 0 */
4650 105 : vn[i] = n;
4651 105 : gel(FA,i) = fa;
4652 105 : gel(vP,i) = gel(fa,1);
4653 : }
4654 77 : vP = shallowconcat1(vP); vecsmall_sort(vP);
4655 77 : vP = vecsmall_uniq_sorted(vP); /* all primes occurring in vn */
4656 77 : lvP = lg(vP); if (lvP == 1) goto END;
4657 56 : p = vP[lvP-1];
4658 56 : sb = mfsturm_mf(mf);
4659 56 : if (dk == 1 && nk != 1 && MF_get_space(mf) == mf_NEW)
4660 21 : B = NULL; /* special purpose mfnewmathecke_p is faster */
4661 35 : else if (lvP == 2 && N % p == 0)
4662 21 : B = mfcoefs_mf(mf, sb, dk==2? p*p: p); /* single prime | N, can optimize */
4663 : else
4664 14 : B = mfcoefs_mf(mf, sb * (dk==2? p*p: p), 1); /* general initialization */
4665 126 : for (i = 1; i < lvP; i++)
4666 : {
4667 70 : long j, l, q, e = 1;
4668 : GEN C, Tp, u1, u0;
4669 70 : p = vP[i];
4670 189 : for (j = 1; j < lv; j++) e = maxss(e, z_lval(vn[j], p));
4671 70 : if (!B)
4672 28 : Tp = mfnewmathecke_p(mf, p);
4673 42 : else if (dk == 2)
4674 7 : Tp = mfheckemat_mfcoefs_p2(mf,p, (lvP==2||N%p)? B: matdeflate(sb,p*p,B));
4675 : else
4676 35 : Tp = mfheckemat_mfcoefs_p(mf, p, (lvP==2||N%p)? B: matdeflate(sb,p,B));
4677 70 : gel(vT, p) = Tp;
4678 70 : if (e == 1) continue;
4679 14 : u0 = gen_1;
4680 14 : if (dk == 2)
4681 : {
4682 0 : C = N % p? gmul(mfchareval(CHI,p*p), powuu(p, nk-2)): NULL;
4683 0 : if (e == 2) u0 = uutoQ(p+1,p); /* special case T_{p^4} */
4684 : }
4685 : else
4686 14 : C = N % p? gmul(mfchareval(CHI,p), powuu(p, nk-1)): NULL;
4687 28 : for (u1=Tp, q=p, l=2; l <= e; l++)
4688 : { /* u0 = T_{p^{l-2}}, u1 = T_{p^{l-1}} for l > 2 */
4689 14 : GEN v = gmul(Tp, u1);
4690 14 : if (C) v = gsub(v, gmul(C, u0));
4691 : /* q = p^l, vT[q] = T_q for k integer else T_{q^2} */
4692 14 : q *= p; u0 = u1; gel(vT, q) = u1 = v;
4693 : }
4694 : }
4695 56 : END:
4696 : /* vT[p^e] = T_{p^e} for all p^e occurring below */
4697 182 : for (i = 1; i < lv; i++)
4698 : {
4699 105 : long n = vn[i], j, lP;
4700 : GEN fa, P, E, M;
4701 105 : if (n == 0) { gel(res,i) = zeromat(dim,dim); continue; }
4702 105 : if (n == 1) { gel(res,i) = matid(dim); continue; }
4703 77 : fa = gel(FA,i);
4704 77 : P = gel(fa,1); lP = lg(P);
4705 77 : E = gel(fa,2); M = gel(vT, upowuu(P[1], E[1]));
4706 84 : for (j = 2; j < lP; j++) M = RgM_mul(M, gel(vT, upowuu(P[j], E[j])));
4707 77 : gel(res,i) = M;
4708 : }
4709 77 : if (flint) res = gel(res,1);
4710 77 : return gc_GEN(av, res);
4711 : }
4712 :
4713 : /* f = \sum_i v[i] T_listj[i] (Trace Form) attached to v; replace by f/a_1(f) */
4714 : static GEN
4715 1540 : mf_normalize(GEN mf, GEN v)
4716 : {
4717 1540 : GEN c, dc = NULL, M = MF_get_M(mf), Mindex = MF_get_Mindex(mf);
4718 1540 : v = Q_primpart(v);
4719 1540 : c = RgMrow_RgC_mul(M, v, 2); /* a_1(f) */
4720 1540 : if (gequal1(c)) return v;
4721 945 : if (typ(c) == t_POL) c = gmodulo(c, mfcharpol(MF_get_CHI(mf)));
4722 945 : if (typ(c) == t_POLMOD && varn(gel(c,1)) == 1 && degpol(gel(c,1)) >= 40
4723 7 : && Mindex[1] == 2
4724 7 : && mfcharorder(MF_get_CHI(mf)) <= 2)
4725 7 : { /* normalize using expansion at infinity (small coefficients) */
4726 7 : GEN w, P = gel(c,1), a1 = gel(c,2);
4727 7 : long i, l = lg(Mindex);
4728 7 : w = cgetg(l, t_COL);
4729 7 : gel(w,1) = gen_1;
4730 280 : for (i = 2; i < l; i++)
4731 : {
4732 273 : c = liftpol_shallow(RgMrow_RgC_mul(M, v, Mindex[i]));
4733 273 : gel(w,i) = QXQ_div(c, a1, P);
4734 : }
4735 : /* w = expansion at oo of normalized form */
4736 7 : v = Minv_RgC_mul(MF_get_Minv(mf), Q_remove_denom(w, &dc));
4737 7 : v = gmodulo(v, P); /* back to mfbasis coefficients */
4738 : }
4739 : else
4740 : {
4741 938 : c = ginv(c);
4742 938 : if (typ(c) == t_POLMOD) c = Q_remove_denom(c, &dc);
4743 938 : v = RgC_Rg_mul(v, c);
4744 : }
4745 945 : if (dc) v = RgC_Rg_div(v, dc);
4746 945 : return v;
4747 : }
4748 : static void
4749 455 : pol_red(GEN NF, GEN *pP, GEN *pa, long flag)
4750 : {
4751 455 : GEN dP, a, P = *pP;
4752 455 : long d = degpol(P);
4753 :
4754 455 : *pa = a = pol_x(varn(P));
4755 455 : if (d * (NF ? nf_get_degree(NF): 1) > 30) return;
4756 :
4757 448 : dP = RgX_disc(P);
4758 448 : if (typ(dP) != t_INT)
4759 112 : { dP = gnorm(dP); if (typ(dP) != t_INT) pari_err_BUG("mfnewsplit"); }
4760 448 : if (d == 2 || expi(dP) < 62)
4761 : {
4762 413 : if (expi(dP) < 31)
4763 406 : P = NF? rnfpolredabs(NF, P,flag): polredabs0(P,flag);
4764 : else
4765 7 : P = NF? rnfpolredbest(NF,P,flag): polredbest(P,flag);
4766 413 : if (flag)
4767 : {
4768 385 : a = gel(P,2); if (typ(a) == t_POLMOD) a = gel(a,2);
4769 385 : P = gel(P,1);
4770 : }
4771 : }
4772 448 : *pP = P;
4773 448 : *pa = a;
4774 : }
4775 :
4776 : /* Diagonalize and normalize. See mfsplit for meaning of flag. */
4777 : static GEN
4778 1092 : mfspclean(GEN mf, GEN mf0, GEN NF, long ord, GEN simplesp, long flag)
4779 : {
4780 1092 : const long vz = 1;
4781 1092 : long i, l = lg(simplesp), dim = MF_get_dim(mf);
4782 1092 : GEN res = cgetg(l, t_MAT), pols = cgetg(l, t_VEC);
4783 1092 : GEN zeros = (mf == mf0)? NULL: zerocol(dim - MF_get_dim(mf0));
4784 2660 : for (i = 1; i < l; i++)
4785 : {
4786 1568 : GEN ATP = gel(simplesp, i), A = gel(ATP,1), P = gel(ATP,3);
4787 1568 : long d = degpol(P);
4788 1568 : GEN a, v = (flag && d > flag)? NULL: gel(A,1);
4789 1568 : if (d == 1) P = pol_x(vz);
4790 : else
4791 : {
4792 455 : pol_red(NF, &P, &a, !!v);
4793 455 : if (v)
4794 : { /* Mod(a,P) root of charpoly(T), K*gpowers(a) = eigenvector of T */
4795 427 : GEN K, den, M = cgetg(d+1, t_MAT), T = gel(ATP,2);
4796 : long j;
4797 427 : T = shallowtrans(T);
4798 427 : gel(M,1) = vec_ei(d,1); /* basis of cyclic vectors */
4799 1372 : for (j = 2; j <= d; j++) gel(M,j) = RgM_RgC_mul(T, gel(M,j-1));
4800 427 : M = Q_primpart(M);
4801 147 : K = NF? ZabM_inv(liftpol_shallow(M), nf_get_pol(NF), ord, &den)
4802 427 : : ZM_inv(M,&den);
4803 427 : K = shallowtrans(K);
4804 427 : v = gequalX(a)? pol_x_powers(d, vz): RgXQ_powers(a, d-1, P);
4805 427 : v = gmodulo(RgM_RgC_mul(A, RgM_RgC_mul(K,v)), P);
4806 : }
4807 : }
4808 1568 : if (v)
4809 : {
4810 1540 : v = mf_normalize(mf0, v); if (zeros) v = shallowconcat(zeros,v);
4811 1540 : gel(res,i) = v; if (flag) setlg(res,i+1);
4812 : }
4813 : else
4814 28 : gel(res,i) = zerocol(dim);
4815 1568 : gel(pols,i) = P;
4816 : }
4817 1092 : return mkvec2(res, pols);
4818 : }
4819 :
4820 : /* return v = v_{X-r}(P), and set Z = P / (X-r)^v */
4821 : static long
4822 70 : RgX_valrem_root(GEN P, GEN r, GEN *Z)
4823 : {
4824 : long v;
4825 140 : for (v = 0; degpol(P); v++)
4826 : {
4827 140 : GEN t, Q = RgX_div_by_X_x(P, r, &t);
4828 140 : if (!gequal0(t)) break;
4829 70 : P = Q;
4830 : }
4831 70 : *Z = P; return v;
4832 : }
4833 : static GEN
4834 1533 : mynffactor(GEN NF, GEN P, long dimlim)
4835 : {
4836 : long i, l, v;
4837 : GEN R, E;
4838 1533 : if (dimlim != 1)
4839 : {
4840 966 : R = NF? nffactor(NF, P): QX_factor(P);
4841 966 : if (!dimlim) return R;
4842 21 : E = gel(R,2);
4843 21 : R = gel(R,1); l = lg(R);
4844 98 : for (i = 1; i < l; i++)
4845 91 : if (degpol(gel(R,i)) > dimlim) break;
4846 21 : if (i == 1) return NULL;
4847 21 : setlg(E,i);
4848 21 : setlg(R,i); return mkmat2(R, E);
4849 : }
4850 : /* dimlim = 1 */
4851 567 : R = nfroots(NF, P); l = lg(R);
4852 567 : if (l == 1) return NULL;
4853 504 : v = varn(P);
4854 504 : settyp(R, t_COL);
4855 504 : if (degpol(P) == l-1)
4856 448 : E = const_col(l-1, gen_1);
4857 : else
4858 : {
4859 56 : E = cgetg(l, t_COL);
4860 126 : for (i = 1; i < l; i++) gel(E,i) = utoi(RgX_valrem_root(P, gel(R,i), &P));
4861 : }
4862 504 : R = deg1_from_roots(R, v);
4863 504 : return mkmat2(R, E);
4864 : }
4865 :
4866 : /* Let K be a number field attached to NF (Q if NF = NULL). A K-vector
4867 : * space of dimension d > 0 is given by a t_MAT A (n x d, full column rank)
4868 : * giving a K-basis, X a section (d x n: left pseudo-inverse of A). Return a
4869 : * pair (T, fa), where T is an element of the Hecke algebra (a sum of Tp taken
4870 : * from vector vTp) acting on A (a d x d t_MAT) and fa is the factorization of
4871 : * its characteristic polynomial, limited to factors of degree <= dimlim if
4872 : * dimlim != 0 (return NULL if there are no factors of degree <= dimlim) */
4873 : static GEN
4874 1358 : findbestsplit(GEN NF, GEN vTp, GEN A, GEN X, long dimlim, long vz)
4875 : {
4876 1358 : GEN T = NULL, Tkeep = NULL, fakeep = NULL;
4877 1358 : long lmax = 0, i, lT = lg(vTp);
4878 1785 : for (i = 1; i < lT; i++)
4879 : {
4880 1785 : GEN D, P, E, fa, TpA = gel(vTp,i);
4881 : long l;
4882 2828 : if (typ(TpA) == t_INT) break;
4883 1533 : if (lg(TpA) > lg(A)) TpA = RgM_mul(X, RgM_mul(TpA, A)); /* Tp | A */
4884 1533 : T = T ? RgM_add(T, TpA) : TpA;
4885 1533 : if (!NF) { P = QM_charpoly_ZX(T); setvarn(P, vz); }
4886 : else
4887 : {
4888 294 : P = charpoly(Q_remove_denom(T, &D), vz);
4889 294 : if (D) P = gdiv(RgX_unscale(P, D), powiu(D, degpol(P)));
4890 : }
4891 1533 : fa = mynffactor(NF, P, dimlim);
4892 1533 : if (!fa) return NULL;
4893 1470 : E = gel(fa, 2);
4894 : /* characteristic polynomial is separable ? */
4895 1470 : if (isint1(vecmax(E))) { Tkeep = T; fakeep = fa; break; }
4896 427 : l = lg(E);
4897 : /* characteristic polynomial has more factors than before ? */
4898 427 : if (l > lmax) { lmax = l; Tkeep = T; fakeep = fa; }
4899 : }
4900 1295 : return mkvec2(Tkeep, fakeep);
4901 : }
4902 :
4903 : static GEN
4904 294 : nfcontent(GEN nf, GEN v)
4905 : {
4906 294 : long i, l = lg(v);
4907 294 : GEN c = gel(v,1);
4908 1512 : for (i = 2; i < l; i++) c = idealadd(nf, c, gel(v,i));
4909 294 : if (typ(c) == t_MAT && gequal1(gcoeff(c,1,1))) c = gen_1;
4910 294 : return c;
4911 : }
4912 : static GEN
4913 455 : nf_primpart(GEN nf, GEN x)
4914 : {
4915 455 : switch(typ(x))
4916 : {
4917 294 : case t_COL:
4918 : {
4919 294 : GEN A = matalgtobasis(nf, x), c = nfcontent(nf, A);
4920 294 : if (typ(c) == t_INT) return x;
4921 35 : c = idealred_elt(nf,c);
4922 35 : A = Q_primpart( nfC_nf_mul(nf, A, Q_primpart(nfinv(nf,c))) );
4923 35 : A = liftpol_shallow( matbasistoalg(nf, A) );
4924 35 : if (gexpo(A) > gexpo(x)) A = x;
4925 35 : return A;
4926 : }
4927 455 : case t_MAT: pari_APPLY_same(nf_primpart(nf, gel(x,i)));
4928 0 : default:
4929 0 : pari_err_TYPE("nf_primpart", x);
4930 : return NULL; /*LCOV_EXCL_LINE*/
4931 : }
4932 : }
4933 :
4934 : /* rotate entries of v to accomodate new entry 'x' (push out oldest entry) */
4935 : static void
4936 1239 : vecpush(GEN v, GEN x)
4937 : {
4938 : long i;
4939 6195 : for (i = lg(v)-1; i > 1; i--) gel(v,i) = gel(v,i-1);
4940 1239 : gel(v,1) = x;
4941 1239 : }
4942 :
4943 : /* sort t_VEC of vector spaces by increasing dimension */
4944 : static GEN
4945 1092 : sort_by_dim(GEN v)
4946 : {
4947 1092 : long i, l = lg(v);
4948 1092 : GEN D = cgetg(l, t_VECSMALL);
4949 2660 : for (i = 1; i < l; i++) D[i] = lg(gmael(v,i,2));
4950 1092 : return vecpermute(v, vecsmall_indexsort(D));
4951 : }
4952 : static GEN
4953 1092 : split_starting_space(GEN mf)
4954 : {
4955 1092 : long d = MF_get_dim(mf), d2;
4956 1092 : GEN id = matid(d);
4957 1092 : switch(MF_get_space(mf))
4958 : {
4959 1085 : case mf_NEW:
4960 1085 : case mf_CUSP: return mkvec2(id, id);
4961 : }
4962 7 : d2 = lg(MF_get_S(mf))-1;
4963 7 : return mkvec2(vecslice(id, d-d2+1,d),
4964 : shallowconcat(zeromat(d2,d-d2),matid(d2)));
4965 : }
4966 : /* If dimlim > 0, keep only the dimension <= dimlim eigenspaces.
4967 : * See mfsplit for the meaning of flag. */
4968 : static GEN
4969 1491 : split_ii(GEN mf, long dimlim, long flag, GEN vSP, long *pnewd)
4970 : {
4971 : forprime_t iter;
4972 1491 : GEN CHI = MF_get_CHI(mf), empty = cgetg(1, t_VEC), mf0 = mf;
4973 : GEN NF, POLCYC, todosp, Tpbigvec, simplesp;
4974 1491 : long N = MF_get_N(mf), k = MF_get_k(mf);
4975 1491 : long ord, FC, NEWT, dimsimple = 0, newd = -1;
4976 1491 : const long NBH = 5, vz = 1;
4977 : ulong p;
4978 :
4979 1491 : switch(MF_get_space(mf))
4980 : {
4981 1197 : case mf_NEW: break;
4982 287 : case mf_CUSP:
4983 : case mf_FULL:
4984 : {
4985 : GEN CHIP;
4986 287 : if (k > 1) { mf0 = mfinittonew(mf); break; }
4987 259 : CHIP = mfchartoprimitive(CHI, NULL);
4988 259 : newd = lg(MF_get_S(mf))-1 - mfolddim_i(N, k, CHIP, vSP);
4989 259 : break;
4990 : }
4991 7 : default: pari_err_TYPE("mfsplit [space does not contain newspace]", mf);
4992 : return NULL; /*LCOV_EXCL_LINE*/
4993 : }
4994 1484 : if (newd < 0) newd = mf0? MF_get_dim(mf0): 0;
4995 1484 : *pnewd = newd;
4996 1484 : if (!newd) return mkvec2(cgetg(1, t_MAT), empty);
4997 :
4998 1092 : NEWT = (k > 1 && MF_get_space(mf0) == mf_NEW);
4999 1092 : todosp = mkvec( split_starting_space(mf0) );
5000 1092 : simplesp = empty;
5001 1092 : FC = mfcharconductor(CHI);
5002 1092 : ord = mfcharorder(CHI);
5003 1092 : if (ord <= 2) NF = POLCYC = NULL;
5004 : else
5005 : {
5006 210 : POLCYC = mfcharpol(CHI);
5007 210 : NF = nfinit(POLCYC,DEFAULTPREC);
5008 : }
5009 1092 : Tpbigvec = zerovec(NBH);
5010 1092 : u_forprime_init(&iter, 2, ULONG_MAX);
5011 1526 : while (dimsimple < newd && (p = u_forprime_next(&iter)))
5012 : {
5013 : GEN nextsp;
5014 : long ind;
5015 1526 : if (N % (p*p) == 0 && N/p % FC == 0) continue; /* T_p = 0 in this case */
5016 1239 : vecpush(Tpbigvec, NEWT? mfnewmathecke_p(mf0,p): mfheckemat_p(mf0,p));
5017 1239 : nextsp = empty;
5018 1638 : for (ind = 1; ind < lg(todosp); ind++)
5019 : {
5020 1358 : GEN tmp = gel(todosp, ind), fa, P, E, D, Tp, DTp;
5021 1358 : GEN A = gel(tmp, 1);
5022 1358 : GEN X = gel(tmp, 2);
5023 : long lP, i;
5024 1358 : tmp = findbestsplit(NF, Tpbigvec, A, X, dimlim, vz);
5025 1477 : if (!tmp) continue; /* nothing there */
5026 1295 : Tp = gel(tmp, 1);
5027 1295 : fa = gel(tmp, 2);
5028 1295 : P = gel(fa, 1);
5029 1295 : E = gel(fa, 2); lP = lg(P);
5030 : /* lP > 1 */
5031 1295 : if (DEBUGLEVEL) err_printf("Exponents = %Ps\n", E);
5032 1295 : if (lP == 2)
5033 : {
5034 868 : GEN P1 = gel(P,1);
5035 868 : long e1 = itos(gel(E,1)), d1 = degpol(P1);
5036 868 : if (e1 * d1 == lg(Tp)-1)
5037 : {
5038 819 : if (e1 > 1) nextsp = vec_append(nextsp, mkvec2(A,X));
5039 : else
5040 : { /* simple module */
5041 721 : simplesp = vec_append(simplesp, mkvec3(A,Tp,P1));
5042 980 : if ((dimsimple += d1) == newd) goto END;
5043 : }
5044 119 : continue;
5045 : }
5046 : }
5047 : /* Found splitting */
5048 476 : DTp = Q_remove_denom(Tp, &D);
5049 1295 : for (i = 1; i < lP; i++)
5050 : {
5051 1078 : GEN Ai, Xi, dXi, AAi, v, y, Pi = gel(P,i);
5052 1078 : Ai = RgX_RgM_eval(D? RgX_rescale(Pi,D): Pi, DTp);
5053 1078 : Ai = QabM_ker(Ai, POLCYC, ord);
5054 1078 : if (NF) Ai = nf_primpart(NF, Ai);
5055 :
5056 1078 : AAi = RgM_mul(A, Ai);
5057 : /* gives section, works on nonsquare matrices */
5058 1078 : Xi = QabM_pseudoinv(Ai, POLCYC, ord, &v, &dXi);
5059 1078 : Xi = RgM_Rg_div(Xi, dXi);
5060 1078 : y = gel(v,1);
5061 1078 : if (isint1(gel(E,i)))
5062 : {
5063 847 : GEN Tpi = RgM_mul(Xi, RgM_mul(rowpermute(Tp,y), Ai));
5064 847 : simplesp = vec_append(simplesp, mkvec3(AAi, Tpi, Pi));
5065 847 : if ((dimsimple += degpol(Pi)) == newd) goto END;
5066 : }
5067 : else
5068 : {
5069 231 : Xi = RgM_mul(Xi, rowpermute(X,y));
5070 231 : nextsp = vec_append(nextsp, mkvec2(AAi, Xi));
5071 : }
5072 : }
5073 : }
5074 280 : todosp = nextsp; if (lg(todosp) == 1) break;
5075 : }
5076 0 : END:
5077 1092 : if (DEBUGLEVEL) err_printf("end split, need to clean\n");
5078 1092 : return mfspclean(mf, mf0, NF, ord, sort_by_dim(simplesp), flag);
5079 : }
5080 : static GEN
5081 42 : dim_filter(GEN v, long dim)
5082 : {
5083 42 : GEN P = gel(v,2);
5084 42 : long j, l = lg(P);
5085 175 : for (j = 1; j < l; j++)
5086 161 : if (degpol(gel(P,j)) > dim)
5087 : {
5088 28 : v = mkvec2(vecslice(gel(v,1),1,j-1), vecslice(P,1,j-1));
5089 28 : break;
5090 : }
5091 42 : return v;
5092 : }
5093 : static long
5094 287 : dim_sum(GEN v)
5095 : {
5096 287 : GEN P = gel(v,2);
5097 287 : long j, l = lg(P), d = 0;
5098 707 : for (j = 1; j < l; j++) d += degpol(gel(P,j));
5099 287 : return d;
5100 : }
5101 : static GEN
5102 1169 : split_i(GEN mf, long dimlim, long flag)
5103 1169 : { long junk; return split_ii(mf, dimlim, flag, NULL, &junk); }
5104 : /* mf is either already split or output by mfinit. Splitting is done only for
5105 : * newspace except in weight 1. If flag = 0 (default) split completely.
5106 : * If flag = d > 0, only give the Galois polynomials in degree > d
5107 : * Flag is ignored if dimlim = 1. */
5108 : GEN
5109 112 : mfsplit(GEN mf0, long dimlim, long flag)
5110 : {
5111 112 : pari_sp av = avma;
5112 112 : GEN v, mf = checkMF_i(mf0);
5113 112 : if (!mf) pari_err_TYPE("mfsplit", mf0);
5114 112 : if ((v = obj_check(mf, MF_SPLIT)))
5115 42 : { if (dimlim) v = dim_filter(v, dimlim); }
5116 70 : else if (dimlim && (v = obj_check(mf, MF_SPLITN)))
5117 21 : { v = (itos(gel(v,1)) >= dimlim)? dim_filter(gel(v,2), dimlim): NULL; }
5118 112 : if (!v)
5119 : {
5120 : long newd;
5121 70 : v = split_ii(mf, dimlim, flag, NULL, &newd);
5122 70 : if (lg(v) == 1) obj_insert(mf, MF_SPLITN, mkvec2(utoi(dimlim), v));
5123 70 : else if (!flag)
5124 : {
5125 49 : if (dim_sum(v) == newd) obj_insert(mf, MF_SPLIT,v);
5126 21 : else obj_insert(mf, MF_SPLITN, mkvec2(utoi(dimlim), v));
5127 : }
5128 : }
5129 112 : return gc_GEN(av, v);
5130 : }
5131 : static GEN
5132 252 : split(GEN mf) { return split_i(mf,0,0); }
5133 : GEN
5134 819 : MF_get_newforms(GEN mf) { return gel(obj_checkbuild(mf,MF_SPLIT,&split),1); }
5135 : GEN
5136 616 : MF_get_fields(GEN mf) { return gel(obj_checkbuild(mf,MF_SPLIT,&split),2); }
5137 :
5138 : /*************************************************************************/
5139 : /* Modular forms of Weight 1 */
5140 : /*************************************************************************/
5141 : /* S_1(G_0(N)), small N. Return 1 if definitely empty; return 0 if maybe
5142 : * nonempty */
5143 : static int
5144 16632 : wt1empty(long N)
5145 : {
5146 16632 : if (N <= 100) switch (N)
5147 : { /* nonempty [32/100] */
5148 5453 : case 23: case 31: case 39: case 44: case 46:
5149 : case 47: case 52: case 55: case 56: case 57:
5150 : case 59: case 62: case 63: case 68: case 69:
5151 : case 71: case 72: case 76: case 77: case 78:
5152 : case 79: case 80: case 83: case 84: case 87:
5153 : case 88: case 92: case 93: case 94: case 95:
5154 5453 : case 99: case 100: return 0;
5155 3549 : default: return 1;
5156 : }
5157 7630 : if (N <= 600) switch(N)
5158 : { /* empty [111/500] */
5159 336 : case 101: case 102: case 105: case 106: case 109:
5160 : case 113: case 121: case 122: case 123: case 125:
5161 : case 130: case 134: case 137: case 146: case 149:
5162 : case 150: case 153: case 157: case 162: case 163:
5163 : case 169: case 170: case 173: case 178: case 181:
5164 : case 182: case 185: case 187: case 193: case 194:
5165 : case 197: case 202: case 205: case 210: case 218:
5166 : case 221: case 226: case 233: case 241: case 242:
5167 : case 245: case 246: case 250: case 257: case 265:
5168 : case 267: case 269: case 274: case 277: case 281:
5169 : case 289: case 293: case 298: case 305: case 306:
5170 : case 313: case 314: case 317: case 326: case 337:
5171 : case 338: case 346: case 349: case 353: case 361:
5172 : case 362: case 365: case 369: case 370: case 373:
5173 : case 374: case 377: case 386: case 389: case 394:
5174 : case 397: case 401: case 409: case 410: case 421:
5175 : case 425: case 427: case 433: case 442: case 449:
5176 : case 457: case 461: case 466: case 481: case 482:
5177 : case 485: case 490: case 493: case 509: case 514:
5178 : case 521: case 530: case 533: case 534: case 538:
5179 : case 541: case 545: case 554: case 557: case 562:
5180 : case 565: case 569: case 577: case 578: case 586:
5181 336 : case 593: return 1;
5182 6979 : default: return 0;
5183 : }
5184 315 : return 0;
5185 : }
5186 :
5187 : static GEN
5188 28 : initwt1trace(GEN mf)
5189 : {
5190 28 : GEN S = MF_get_S(mf), v, H;
5191 : long l, i;
5192 28 : if (lg(S) == 1) return mftrivial();
5193 28 : H = mfheckemat(mf, Mindex_as_coef(mf));
5194 28 : l = lg(H); v = cgetg(l, t_VEC);
5195 63 : for (i = 1; i < l; i++) gel(v,i) = gtrace(gel(H,i));
5196 28 : v = Minv_RgC_mul(MF_get_Minv(mf), v);
5197 28 : return mflineardiv_linear(S, v, 1);
5198 : }
5199 : static GEN
5200 21 : initwt1newtrace(GEN mf)
5201 : {
5202 21 : GEN v, D, S, Mindex, CHI = MF_get_CHI(mf);
5203 21 : long FC, lD, i, sb, N1, N2, lM, N = MF_get_N(mf);
5204 21 : CHI = mfchartoprimitive(CHI, &FC);
5205 21 : if (N % FC || mfcharparity(CHI) == 1) return mftrivial();
5206 21 : D = mydivisorsu(N/FC); lD = lg(D);
5207 21 : S = MF_get_S(mf);
5208 21 : if (lg(S) == 1) return mftrivial();
5209 21 : N2 = newd_params2(N);
5210 21 : N1 = N / N2;
5211 21 : Mindex = MF_get_Mindex(mf);
5212 21 : lM = lg(Mindex);
5213 21 : sb = Mindex[lM-1];
5214 21 : v = zerovec(sb+1);
5215 42 : for (i = 1; i < lD; i++)
5216 : {
5217 21 : long M = FC*D[i], j;
5218 21 : GEN tf = initwt1trace(M == N? mf: mfinit_Nkchi(M, 1, CHI, mf_CUSP, 0));
5219 : GEN listd, w;
5220 21 : if (mf_get_type(tf) == t_MF_CONST) continue;
5221 21 : w = mfcoefs_i(tf, sb, 1);
5222 21 : if (M == N) { v = gadd(v, w); continue; }
5223 0 : listd = mydivisorsu(u_ppo(ugcd(N/M, N1), FC));
5224 0 : for (j = 1; j < lg(listd); j++)
5225 : {
5226 0 : long d = listd[j], d2 = d*d; /* coprime to FC */
5227 0 : GEN dk = mfchareval(CHI, d);
5228 0 : long NMd = N/(M*d), m;
5229 0 : for (m = 1; m <= sb/d2; m++)
5230 : {
5231 0 : long be = mubeta2(NMd, m);
5232 0 : if (be)
5233 : {
5234 0 : GEN c = gmul(dk, gmulsg(be, gel(w, m+1)));
5235 0 : long n = m*d2;
5236 0 : gel(v, n+1) = gadd(gel(v, n+1), c);
5237 : }
5238 : }
5239 : }
5240 : }
5241 21 : if (gequal0(gel(v,2))) return mftrivial();
5242 21 : v = vecpermute(v,Mindex);
5243 21 : v = Minv_RgC_mul(MF_get_Minv(mf), v);
5244 21 : return mflineardiv_linear(S, v, 1);
5245 : }
5246 :
5247 : /* i*p + 1, i*p < lim corresponding to a_p(f_j), a_{2p}(f_j)... */
5248 : static GEN
5249 1834 : pindices(long p, long lim)
5250 : {
5251 1834 : GEN v = cgetg(lim, t_VECSMALL);
5252 : long i, ip;
5253 22190 : for (i = 1, ip = p + 1; ip < lim; i++, ip += p) v[i] = ip;
5254 1834 : setlg(v, i); return v;
5255 : }
5256 :
5257 : /* assume !wt1empty(N), in particular N>25 */
5258 : /* Returns [[lim,p], mf (weight 2), p*lim x dim matrix] */
5259 : static GEN
5260 1834 : mf1_pre(long N)
5261 : {
5262 : pari_timer tt;
5263 : GEN mf, v, L, I, M, Minv, den;
5264 : long B, lim, LIM, p;
5265 :
5266 1834 : if (DEBUGLEVEL) timer_start(&tt);
5267 1834 : mf = mfinit_Nkchi(N, 2, mfchartrivial(), mf_CUSP, 0);
5268 1834 : if (DEBUGLEVEL)
5269 0 : timer_printf(&tt, "mf1basis [pre]: S_2(%ld), dim = %ld",
5270 : N, MF_get_dim(mf));
5271 1834 : M = MF_get_M(mf); Minv = MF_get_Minv(mf); den = gel(Minv,2);
5272 1834 : B = mfsturm_mf(mf);
5273 1834 : if (uisprime(N))
5274 : {
5275 392 : lim = 2 * MF_get_dim(mf); /* ensure mfstabiter's first kernel ~ square */
5276 392 : p = 2;
5277 : }
5278 : else
5279 : {
5280 : forprime_t S;
5281 1442 : u_forprime_init(&S, 2, N);
5282 2576 : while ((p = u_forprime_next(&S)))
5283 2576 : if (N % p) break;
5284 1442 : lim = B + 1;
5285 : }
5286 1834 : LIM = (N & (N - 1))? 2 * lim: 3 * lim; /* N power of 2 ? */
5287 1834 : L = mkvecsmall4(lim, LIM, mfsturmNk(N,1), p);
5288 1834 : M = bhnmat_extend_nocache(M, N, LIM-1, 1, MF_get_S(mf));
5289 1834 : if (DEBUGLEVEL) timer_printf(&tt, "mf1basis [pre]: bnfmat_extend");
5290 1834 : v = pindices(p, LIM);
5291 1834 : if (!LIM) return mkvec4(L, mf, M, v);
5292 1834 : I = RgM_Rg_div(ZM_mul(rowslice(M, B+2, LIM), gel(Minv,1)), den);
5293 1834 : I = Q_remove_denom(I, &den);
5294 1834 : if (DEBUGLEVEL) timer_printf(&tt, "mf1basis [prec]: Iden");
5295 1834 : return mkvec5(L, mf, M, v, mkvec2(I, den));
5296 : }
5297 :
5298 : /* lg(A) > 1, E a t_POL */
5299 : static GEN
5300 700 : mfmatsermul(GEN A, GEN E)
5301 : {
5302 700 : long j, l = lg(A), r = nbrows(A);
5303 700 : GEN M = cgetg(l, t_MAT);
5304 700 : E = RgXn_red_shallow(E, r+1);
5305 6328 : for (j = 1; j < l; j++)
5306 : {
5307 5628 : GEN c = RgV_to_RgX(gel(A,j), 0);
5308 5628 : gel(M, j) = RgX_to_RgC(RgXn_mul(c, E, r+1), r);
5309 : }
5310 700 : return M;
5311 : }
5312 : /* lg(Ap) > 1, Ep an Flxn */
5313 : static GEN
5314 1141 : mfmatsermul_Fl(GEN Ap, GEN Ep, ulong p)
5315 : {
5316 1141 : long j, l = lg(Ap), r = nbrows(Ap);
5317 1141 : GEN M = cgetg(l, t_MAT);
5318 42630 : for (j = 1; j < l; j++)
5319 : {
5320 41489 : GEN c = Flv_to_Flx(gel(Ap,j), 0);
5321 41489 : gel(M,j) = Flx_to_Flv(Flxn_mul(c, Ep, r+1, p), r);
5322 : }
5323 1141 : return M;
5324 : }
5325 :
5326 : /* CHI mod F | N, return mfchar of modulus N.
5327 : * FIXME: wasteful, G should be precomputed */
5328 : static GEN
5329 13048 : mfcharinduce(GEN CHI, long N)
5330 : {
5331 : GEN G, chi;
5332 13048 : if (mfcharmodulus(CHI) == N) return CHI;
5333 1463 : G = znstar0(utoipos(N), 1);
5334 1463 : chi = zncharinduce(gel(CHI,1), gel(CHI,2), G);
5335 1463 : CHI = leafcopy(CHI);
5336 1463 : gel(CHI,1) = G;
5337 1463 : gel(CHI,2) = chi; return CHI;
5338 : }
5339 :
5340 : static GEN
5341 3983 : gmfcharno(GEN CHI)
5342 : {
5343 3983 : GEN G = gel(CHI,1), chi = gel(CHI,2);
5344 3983 : return mkintmod(znconreyexp(G, chi), znstar_get_N(G));
5345 : }
5346 : static long
5347 13699 : mfcharno(GEN CHI)
5348 : {
5349 13699 : GEN n = znconreyexp(gel(CHI,1), gel(CHI,2));
5350 13699 : return itou(n);
5351 : }
5352 :
5353 : /* return k such that minimal mfcharacter in Galois orbit of CHI is CHI^k */
5354 : static long
5355 12138 : mfconreyminimize(GEN CHI)
5356 : {
5357 12138 : GEN G = gel(CHI,1), cyc, chi;
5358 12138 : cyc = ZV_to_zv(znstar_get_cyc(G));
5359 12138 : chi = ZV_to_zv(znconreychar(G, gel(CHI,2)));
5360 12138 : return zv_cyc_minimize(cyc, chi, coprimes_zv(mfcharorder(CHI)));
5361 : }
5362 :
5363 : /* find scalar c such that first nonzero entry of c*v is 1; return c*v */
5364 : static GEN
5365 2065 : RgV_normalize(GEN v, GEN *pc)
5366 : {
5367 2065 : long i, l = lg(v);
5368 5313 : for (i = 1; i < l; i++)
5369 : {
5370 5313 : GEN c = gel(v,i);
5371 5313 : if (!gequal0(c))
5372 : {
5373 2065 : if (gequal1(c)) break;
5374 679 : *pc = ginv(c); return RgV_Rg_mul(v, *pc);
5375 : }
5376 : }
5377 1386 : *pc = gen_1; return v;
5378 : }
5379 : /* pS != NULL; dim > 0 */
5380 : static GEN
5381 784 : mftreatdihedral(long N, GEN DIH, GEN POLCYC, long ordchi, GEN *pS)
5382 : {
5383 784 : long l = lg(DIH), lim = mfsturmNk(N, 1), i;
5384 784 : GEN Minv, C = cgetg(l, t_VEC), M = cgetg(l, t_MAT);
5385 2436 : for (i = 1; i < l; i++)
5386 : {
5387 1652 : GEN c, v = mfcoefs_i(gel(DIH,i), lim, 1);
5388 1652 : gel(M,i) = RgV_normalize(v, &c);
5389 1652 : gel(C,i) = Rg_col_ei(c, l-1, i);
5390 : }
5391 784 : Minv = gel(mfclean(M,POLCYC,ordchi,0),2);
5392 784 : M = RgM_Minv_mul(M, Minv);
5393 784 : C = RgM_Minv_mul(C, Minv);
5394 784 : *pS = vecmflinear(DIH, C); return M;
5395 : }
5396 :
5397 : /* same mode a maximal ideal above q */
5398 : static GEN
5399 2408 : Tpmod(GEN Ap, GEN A, ulong chip, long p, ulong q)
5400 : {
5401 2408 : GEN B = leafcopy(Ap);
5402 2408 : long i, ip, l = lg(B);
5403 86345 : for (i = 1, ip = p; ip < l; i++, ip += p)
5404 83937 : B[ip] = Fl_add(B[ip], Fl_mul(A[i], chip, q), q);
5405 2408 : return B;
5406 : }
5407 : /* Tp(f_1), ..., Tp(f_d) mod q */
5408 : static GEN
5409 301 : matTpmod(GEN xp, GEN x, ulong chip, long p, ulong q)
5410 2709 : { pari_APPLY_same(Tpmod(gel(xp,i), gel(x,i), chip, p, q)); }
5411 :
5412 : /* Ap[i] = a_{p*i}(F), A[i] = a_i(F), i = 1..lim
5413 : * Tp(f)[n] = a_{p*n}(f) + chi(p) a_{n/p}(f) * 1_{p | n} */
5414 : static GEN
5415 469 : Tp(GEN Ap, GEN A, GEN chip, long p)
5416 : {
5417 469 : GEN B = leafcopy(Ap);
5418 469 : long i, ip, l = lg(B);
5419 12915 : for (i = 1, ip = p; ip < l; i++, ip += p)
5420 12446 : gel(B,ip) = gadd(gel(B,ip), gmul(gel(A,i), chip));
5421 469 : return B;
5422 : }
5423 : /* Tp(f_1), ..., Tp(f_d) */
5424 : static GEN
5425 56 : matTp(GEN xp, GEN x, GEN chip, long p)
5426 525 : { pari_APPLY_same(Tp(gel(xp,i), gel(x,i), chip, p)); }
5427 :
5428 : static GEN
5429 378 : _RgXQM_mul(GEN x, GEN y, GEN T)
5430 378 : { return T? RgXQM_mul(x, y, T): RgM_mul(x, y); }
5431 : /* largest T-stable Q(CHI)-subspace of Q(CHI)-vector space spanned by columns
5432 : * of A */
5433 : static GEN
5434 28 : mfstabiter(GEN *pC, GEN A0, GEN chip, GEN TMP, GEN P, long ordchi)
5435 : {
5436 28 : GEN A, Ap, vp = gel(TMP,4), C = NULL;
5437 28 : long i, lA, lim1 = gel(TMP,1)[3], p = gel(TMP,1)[4];
5438 : pari_timer tt;
5439 :
5440 28 : Ap = rowpermute(A0, vp);
5441 28 : A = rowslice(A0, 2, nbrows(Ap)+1); /* remove a0 */
5442 : for(;;)
5443 28 : {
5444 56 : GEN R = shallowconcat(matTp(Ap, A, chip, p), A);
5445 56 : GEN B = QabM_ker(R, P, ordchi);
5446 56 : long lB = lg(B);
5447 56 : if (DEBUGLEVEL)
5448 0 : timer_printf(&tt, "mf1basis: Hecke intersection (dim %ld)", lB-1);
5449 56 : if (lB == 1) return NULL;
5450 56 : lA = lg(A); if (lB == lA) break;
5451 28 : B = rowslice(B, 1, lA-1);
5452 28 : Ap = _RgXQM_mul(Ap, B, P);
5453 28 : A = _RgXQM_mul(A, B, P);
5454 28 : C = C? _RgXQM_mul(C, B, P): B;
5455 : }
5456 28 : if (nbrows(A) < lim1)
5457 : {
5458 14 : A0 = rowslice(A0, 2, lim1);
5459 14 : A = C? _RgXQM_mul(A0, C, P): A0;
5460 : }
5461 : else /* all needed coefs computed */
5462 14 : A = rowslice(A, 1, lim1-1);
5463 28 : if (*pC) C = C? _RgXQM_mul(*pC, C, P): *pC;
5464 : /* put back a0 */
5465 119 : for (i = 1; i < lA; i++) gel(A,i) = vec_prepend(gel(A,i), gen_0);
5466 28 : *pC = C; return A;
5467 : }
5468 :
5469 : static long
5470 252 : mfstabitermod(GEN A, GEN vp, ulong chip, long p, ulong q)
5471 : {
5472 252 : GEN Ap, C = NULL;
5473 252 : Ap = rowpermute(A, vp);
5474 252 : A = rowslice(A, 2, nbrows(Ap)+1);
5475 : while (1)
5476 49 : {
5477 301 : GEN Rp = shallowconcat(matTpmod(Ap, A, chip, p, q), A);
5478 301 : GEN B = Flm_ker(Rp, q);
5479 301 : long lA = lg(A), lB = lg(B);
5480 301 : if (lB == 1) return 0;
5481 266 : if (lB == lA) return lA-1;
5482 49 : B = rowslice(B, 1, lA-1);
5483 49 : Ap = Flm_mul(Ap, B, q);
5484 49 : A = Flm_mul(A, B, q);
5485 49 : C = C? Flm_mul(C, B, q): B;
5486 : }
5487 : }
5488 :
5489 : static GEN
5490 595 : mfcharinv_i(GEN CHI)
5491 : {
5492 595 : GEN G = gel(CHI,1);
5493 595 : CHI = leafcopy(CHI); gel(CHI,2) = zncharconj(G, gel(CHI,2)); return CHI;
5494 : }
5495 :
5496 : /* upper bound dim S_1(Gamma_0(N),chi) performing the linear algebra mod p */
5497 : static long
5498 595 : mf1dimmod(GEN E1, GEN E, GEN chip, long ordchi, long dih, GEN TMP)
5499 : {
5500 595 : GEN E1i, A, vp, mf, C = NULL;
5501 595 : ulong q, r = QabM_init(ordchi, &q);
5502 : long lim, LIM, p;
5503 :
5504 595 : LIM = gel(TMP,1)[2]; lim = gel(TMP,1)[1];
5505 595 : mf= gel(TMP,2);
5506 595 : A = gel(TMP,3);
5507 595 : A = QabM_to_Flm(A, r, q);
5508 595 : E1 = QabX_to_Flx(E1, r, q);
5509 595 : E1i = Flxn_inv(E1, nbrows(A), q);
5510 595 : if (E)
5511 : {
5512 574 : GEN Iden = gel(TMP,5), I = gel(Iden,1), den = gel(Iden,2);
5513 574 : GEN Mindex = MF_get_Mindex(mf), F = rowslice(A, 1, LIM);
5514 574 : GEN E1ip = Flxn_red(E1i, LIM);
5515 574 : ulong d = den? umodiu(den, q): 1;
5516 574 : long i, nE = lg(E) - 1;
5517 : pari_sp av;
5518 :
5519 574 : I = ZM_to_Flm(I, q);
5520 574 : if (d != 1) I = Flm_Fl_mul(I, Fl_inv(d, q), q);
5521 574 : av = avma;
5522 1120 : for (i = 1; i <= nE; i++)
5523 : {
5524 889 : GEN e = Flxn_mul(E1ip, QabX_to_Flx(gel(E,i), r, q), LIM, q);
5525 889 : GEN B = mfmatsermul_Fl(F, e, q), z;
5526 889 : GEN B2 = Flm_mul(I, rowpermute(B, Mindex), q);
5527 889 : B = rowslice(B, lim+1,LIM);
5528 889 : z = Flm_ker(Flm_sub(B2, B, q), q);
5529 889 : if (lg(z)-1 == dih) return dih;
5530 546 : C = C? Flm_mul(C, z, q): z;
5531 546 : F = Flm_mul(F, z, q);
5532 546 : (void)gc_all(av, 2, &F,&C);
5533 : }
5534 231 : A = F;
5535 : }
5536 : /* use Schaeffer */
5537 252 : p = gel(TMP,1)[4]; vp = gel(TMP,4);
5538 252 : A = mfmatsermul_Fl(A, E1i, q);
5539 252 : return mfstabitermod(A, vp, Qab_to_Fl(chip, r, q), p, q);
5540 : }
5541 :
5542 : static GEN
5543 224 : mf1intermat(GEN A, GEN Mindex, GEN e, GEN Iden, long lim, GEN POLCYC)
5544 : {
5545 224 : long j, l = lg(A), LIM = nbrows(A);
5546 224 : GEN I = gel(Iden,1), den = gel(Iden,2), B = cgetg(l, t_MAT);
5547 :
5548 5257 : for (j = 1; j < l; j++)
5549 : {
5550 5033 : pari_sp av = avma;
5551 5033 : GEN c = RgV_to_RgX(gel(A,j), 0), c1, c2;
5552 5033 : c = RgX_to_RgC(RgXn_mul(c, e, LIM), LIM);
5553 5033 : if (POLCYC) c = liftpol_shallow(c);
5554 5033 : c1 = vecslice(c, lim+1, LIM);
5555 5033 : if (den) c1 = RgC_Rg_mul(c1, den);
5556 5033 : c2 = RgM_RgC_mul(I, vecpermute(c, Mindex));
5557 5033 : gel(B, j) = gc_upto(av, RgC_sub(c2, c1));
5558 : }
5559 224 : return B;
5560 : }
5561 : /* Compute the full S_1(\G_0(N),\chi); return NULL if space is empty; else
5562 : * if pS is NULL, return stoi(dim), where dim is the dimension; else *pS is
5563 : * set to a vector of forms making up a basis, and return the matrix of their
5564 : * Fourier expansions. pdih gives the dimension of the subspace generated by
5565 : * dihedral forms; TMP is from mf1_pre or NULL. */
5566 : static GEN
5567 11284 : mf1basis(long N, GEN CHI, GEN TMP, GEN vSP, GEN *pS, long *pdih)
5568 : {
5569 11284 : GEN E = NULL, EB, E1, E1i, dE1i, mf, A, C, POLCYC, DIH, Minv, chip;
5570 11284 : long nE = 0, p, LIM, lim, lim1, i, lA, dimp, ordchi, dih;
5571 : pari_timer tt;
5572 : pari_sp av;
5573 :
5574 11284 : if (pdih) *pdih = 0;
5575 11284 : if (pS) *pS = NULL;
5576 11284 : if (wt1empty(N) || mfcharparity(CHI) != -1) return NULL;
5577 10990 : ordchi = mfcharorder(CHI);
5578 10990 : if (uisprime(N) && ordchi > 4) return NULL;
5579 10962 : if (pS)
5580 : {
5581 3857 : DIH = mfdihedralcusp(N, CHI, vSP);
5582 3857 : dih = lg(DIH) - 1;
5583 : }
5584 : else
5585 : {
5586 7105 : DIH = NULL;
5587 7105 : dih = mfdihedralcuspdim(N, CHI, vSP);
5588 : }
5589 10962 : POLCYC = (ordchi <= 2)? NULL: mfcharpol(CHI);
5590 10962 : if (pdih) *pdih = dih;
5591 10962 : if (N <= 600) switch(N)
5592 : {
5593 : long m;
5594 126 : case 219: case 273: case 283: case 331: case 333: case 344: case 416:
5595 : case 438: case 468: case 491: case 504: case 546: case 553: case 563:
5596 : case 566: case 581: case 592:
5597 126 : break; /* one chi with both exotic and dihedral forms */
5598 9499 : default: /* only dihedral forms */
5599 9499 : if (!dih) return NULL;
5600 : /* fall through */
5601 : case 124: case 133: case 148: case 171: case 201: case 209: case 224:
5602 : case 229: case 248: case 261: case 266: case 288: case 296: case 301:
5603 : case 309: case 325: case 342: case 371: case 372: case 380: case 399:
5604 : case 402: case 403: case 404: case 408: case 418: case 432: case 444:
5605 : case 448: case 451: case 453: case 458: case 496: case 497: case 513:
5606 : case 522: case 527: case 532: case 576: case 579:
5607 : /* no chi with both exotic and dihedral; one chi with exotic forms */
5608 3248 : if (dih)
5609 : {
5610 2338 : if (!pS) return utoipos(dih);
5611 728 : return mftreatdihedral(N, DIH, POLCYC, ordchi, pS) ;
5612 : }
5613 910 : m = mfcharno(mfcharinduce(CHI,N));
5614 910 : if (N == 124 && (m != 67 && m != 87)) return NULL;
5615 784 : if (N == 133 && (m != 83 && m !=125)) return NULL;
5616 490 : if (N == 148 && (m !=105 && m !=117)) return NULL;
5617 364 : if (N == 171 && (m != 94 && m !=151)) return NULL;
5618 364 : if (N == 201 && (m != 29 && m !=104)) return NULL;
5619 364 : if (N == 209 && (m != 87 && m !=197)) return NULL;
5620 364 : if (N == 224 && (m != 95 && m !=191)) return NULL;
5621 364 : if (N == 229 && (m !=107 && m !=122)) return NULL;
5622 364 : if (N == 248 && (m != 87 && m !=191)) return NULL;
5623 273 : if (N == 261 && (m != 46 && m !=244)) return NULL;
5624 273 : if (N == 266 && (m != 83 && m !=125)) return NULL;
5625 273 : if (N == 288 && (m != 31 && m !=223)) return NULL;
5626 273 : if (N == 296 && (m !=105 && m !=265)) return NULL;
5627 : }
5628 595 : if (DEBUGLEVEL)
5629 0 : err_printf("mf1basis: start character %Ps, conductor = %ld, order = %ld\n",
5630 : gmfcharno(CHI), mfcharconductor(CHI), ordchi);
5631 595 : if (!TMP) TMP = mf1_pre(N);
5632 595 : lim = gel(TMP,1)[1]; LIM = gel(TMP,1)[2]; lim1 = gel(TMP,1)[3];
5633 595 : p = gel(TMP,1)[4];
5634 595 : mf = gel(TMP,2);
5635 595 : A = gel(TMP,3);
5636 595 : EB = mfeisensteinbasis(N, 1, mfcharinv_i(CHI));
5637 595 : nE = lg(EB) - 1;
5638 595 : E1 = RgV_to_RgX(mftocol(gel(EB,1), LIM-1, 1), 0); /* + O(x^LIM) */
5639 595 : if (--nE)
5640 574 : E = RgM_to_RgXV(mfvectomat(vecslice(EB, 2, nE+1), LIM-1, 1), 0);
5641 595 : chip = mfchareval(CHI, p); /* != 0 */
5642 595 : if (DEBUGLEVEL) timer_start(&tt);
5643 595 : av = avma; dimp = mf1dimmod(E1, E, chip, ordchi, dih, TMP);
5644 595 : set_avma(av);
5645 595 : if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: dim mod p is %ld", dimp);
5646 595 : if (!dimp) return NULL;
5647 280 : if (!pS) return utoi(dimp);
5648 224 : if (dimp == dih) return mftreatdihedral(N, DIH, POLCYC, ordchi, pS);
5649 168 : E1i = RgXn_inv(E1, LIM); /* E[1] does not vanish at oo */
5650 168 : if (POLCYC) E1i = liftpol_shallow(E1i);
5651 168 : E1i = Q_remove_denom(E1i, &dE1i);
5652 168 : if (DEBUGLEVEL)
5653 : {
5654 0 : GEN a0 = gel(E1,2);
5655 0 : if (typ(a0) == t_POLMOD) a0 = gnorm(a0);
5656 0 : a0 = Q_abs_shallow(a0);
5657 0 : timer_printf(&tt, "mf1basis: invert E; norm(a0(E)) = %Ps", a0);
5658 : }
5659 168 : C = NULL;
5660 168 : if (nE)
5661 : { /* mf attached to S2(N), fi = mfbasis(mf)
5662 : * M = coefs(f1,...,fd) up to LIM
5663 : * F = coefs(F1,...,FD) = M * C, for some matrix C over Q(chi),
5664 : * initially 1, eventually giving \cap_E S2 / E; D <= d.
5665 : * B = coefs(E/E1 F1, .., E/E1 FD); we want X in Q(CHI)^d and
5666 : * Y in Q(CHI)^D such that
5667 : * B * X = M * Y, i.e. Minv * rowpermute(B, Mindex * X) = Y
5668 : *(B - I * rowpermute(B, Mindex)) * X = 0.
5669 : * where I = M * Minv. Rows of (B - I * ...) are 0 up to lim so
5670 : * are not included */
5671 154 : GEN Mindex = MF_get_Mindex(mf), Iden = gel(TMP,5);
5672 : pari_timer TT;
5673 154 : pari_sp av = avma;
5674 154 : if (DEBUGLEVEL) timer_start(&TT);
5675 238 : for (i = 1; i <= nE; i++)
5676 : {
5677 224 : pari_sp av2 = avma;
5678 : GEN e, z, B;
5679 :
5680 224 : e = Q_primpart(RgXn_mul(E1i, gel(E,i), LIM));
5681 224 : if (DEBUGLEVEL) timer_printf(&TT, "mf1basis: E[%ld] / E[1]", i+1);
5682 : /* the first time A is over Z and it is more efficient to lift than
5683 : * to let RgXn_mul use Kronecker's trick */
5684 224 : if (POLCYC && i == 1) e = liftpol_shallow(e);
5685 224 : B = mf1intermat(A, Mindex, e, Iden, lim, i == 1? NULL: POLCYC);
5686 224 : if (DEBUGLEVEL) timer_printf(&TT, "mf1basis: ... intermat");
5687 224 : z = gc_upto(av2, QabM_ker(B, POLCYC, ordchi));
5688 224 : if (DEBUGLEVEL)
5689 0 : timer_printf(&TT, "mf1basis: ... kernel (dim %ld)",lg(z)-1);
5690 224 : if (lg(z) == 1) return NULL;
5691 224 : if (lg(z) == lg(A)) { set_avma(av2); continue; } /* no progress */
5692 224 : C = C? _RgXQM_mul(C, z, POLCYC): z;
5693 224 : A = _RgXQM_mul(A, z, POLCYC);
5694 224 : if (DEBUGLEVEL) timer_printf(&TT, "mf1basis: ... updates");
5695 224 : if (lg(z)-1 == dimp) break;
5696 84 : if (gc_needed(av, 1))
5697 : {
5698 0 : if (DEBUGMEM > 1) pari_warn(warnmem,"mf1basis i = %ld", i);
5699 0 : (void)gc_all(av, 2, &A, &C);
5700 : }
5701 : }
5702 154 : if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: intersection [total]");
5703 : }
5704 168 : lA = lg(A);
5705 168 : if (lA-1 == dimp)
5706 : {
5707 140 : A = mfmatsermul(rowslice(A, 1, lim1), E1i);
5708 140 : if (POLCYC) A = RgXQM_red(A, POLCYC);
5709 140 : if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: matsermul [1]");
5710 : }
5711 : else
5712 : {
5713 28 : A = mfmatsermul(A, E1i);
5714 28 : if (POLCYC) A = RgXQM_red(A, POLCYC);
5715 28 : if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: matsermul [2]");
5716 28 : A = mfstabiter(&C, A, chip, TMP, POLCYC, ordchi);
5717 28 : if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: Hecke stability");
5718 28 : if (!A) return NULL;
5719 : }
5720 168 : if (dE1i) C = RgM_Rg_mul(C, dE1i);
5721 168 : if (POLCYC)
5722 : {
5723 147 : A = QXQM_to_mod_shallow(A, POLCYC);
5724 147 : C = QXQM_to_mod_shallow(C, POLCYC);
5725 : }
5726 168 : lA = lg(A);
5727 581 : for (i = 1; i < lA; i++)
5728 : {
5729 413 : GEN c, v = gel(A,i);
5730 413 : gel(A,i) = RgV_normalize(v, &c);
5731 413 : gel(C,i) = RgC_Rg_mul(gel(C,i), c);
5732 : }
5733 168 : Minv = gel(mfclean(A, POLCYC, ordchi, 0), 2);
5734 168 : A = RgM_Minv_mul(A, Minv);
5735 168 : C = RgM_Minv_mul(C, Minv);
5736 168 : *pS = vecmflineardiv0(MF_get_S(mf), C, gel(EB,1));
5737 168 : return A;
5738 : }
5739 :
5740 : static void
5741 413 : MF_set_space(GEN mf, long x) { gmael(mf,1,4) = utoi(x); }
5742 : static GEN
5743 252 : mf1_cusptonew(GEN mf, GEN vSP)
5744 : {
5745 252 : const long vy = 1;
5746 : long i, lP, dSnew, ct;
5747 252 : GEN vP, F, S, Snew, vF, v = split_ii(mf, 0, 0, vSP, &i);
5748 :
5749 252 : F = gel(v,1);
5750 252 : vP= gel(v,2); lP = lg(vP);
5751 252 : if (lP == 1) { obj_insert(mf, MF_SPLIT, v); return NULL; }
5752 238 : MF_set_space(mf, mf_NEW);
5753 238 : S = MF_get_S(mf);
5754 238 : dSnew = dim_sum(v);
5755 238 : Snew = cgetg(dSnew + 1, t_VEC); ct = 0;
5756 238 : vF = cgetg(lP, t_MAT);
5757 546 : for (i = 1; i < lP; i++)
5758 : {
5759 308 : GEN V, P = gel(vP,i), f = liftpol_shallow(gel(F,i));
5760 308 : long j, d = degpol(P);
5761 308 : gel(vF,i) = V = zerocol(dSnew);
5762 308 : if (d == 1)
5763 : {
5764 140 : gel(Snew, ct+1) = mflineardiv_linear(S, f, 0);
5765 140 : gel(V, ct+1) = gen_1;
5766 : }
5767 : else
5768 : {
5769 168 : f = RgXV_to_RgM(f,d);
5770 511 : for (j = 1; j <= d; j++)
5771 : {
5772 343 : gel(Snew, ct+j) = mflineardiv_linear(S, row(f,j), 0);
5773 343 : gel(V, ct+j) = mkpolmod(pol_xn(j-1,vy), P);
5774 : }
5775 : }
5776 308 : ct += d;
5777 : }
5778 238 : obj_insert(mf, MF_SPLIT, mkvec2(vF, vP));
5779 238 : gel(mf,3) = Snew; return mf;
5780 : }
5781 : static GEN
5782 3969 : mf1init(long N, GEN CHI, GEN TMP, GEN vSP, long space, long flraw)
5783 : {
5784 3969 : GEN mf, mf1, S, M = mf1basis(N, CHI, TMP, vSP, &S, NULL);
5785 3969 : if (!M) return NULL;
5786 952 : mf1 = mkvec4(stoi(N), gen_1, CHI, utoi(mf_CUSP));
5787 952 : mf = mkmf(mf1, cgetg(1,t_VEC), S, gen_0, NULL);
5788 952 : if (space == mf_NEW)
5789 : {
5790 252 : gel(mf,5) = mfcleanCHI(M,CHI, 0);
5791 252 : mf = mf1_cusptonew(mf, vSP); if (!mf) return NULL;
5792 238 : if (!flraw) M = mfcoefs_mf(mf, mfsturmNk(N,1)+1, 1);
5793 : }
5794 938 : gel(mf,5) = flraw? zerovec(3): mfcleanCHI(M, CHI, 0);
5795 938 : return mf;
5796 : }
5797 :
5798 : static GEN
5799 1029 : mfEMPTY(GEN mf1)
5800 : {
5801 1029 : GEN Minv = mkMinv(cgetg(1,t_MAT), NULL,NULL,NULL);
5802 1029 : GEN M = mkvec3(cgetg(1,t_VECSMALL), Minv, cgetg(1,t_MAT));
5803 1029 : return mkmf(mf1, cgetg(1,t_VEC), cgetg(1,t_VEC), cgetg(1,t_VEC), M);
5804 : }
5805 : static GEN
5806 616 : mfEMPTYall(long N, GEN gk, GEN vCHI, long space)
5807 : {
5808 : long i, l;
5809 : GEN v, gN, gs;
5810 616 : if (!vCHI) return cgetg(1, t_VEC);
5811 14 : gN = utoipos(N); gs = utoi(space);
5812 14 : l = lg(vCHI); v = cgetg(l, t_VEC);
5813 42 : for (i = 1; i < l; i++) gel(v,i) = mfEMPTY(mkvec4(gN,gk,gel(vCHI,i),gs));
5814 14 : return v;
5815 : }
5816 :
5817 : static GEN
5818 3983 : fmt_dim(GEN CHI, long d, long dih)
5819 3983 : { return mkvec4(gmfcharorder(CHI), gmfcharno(CHI), utoi(d), stoi(dih)); }
5820 : /* merge two vector of fmt_dim's for the same vector of characters. If CHI
5821 : * is not NULL, remove dim-0 spaces and add character from CHI */
5822 : static GEN
5823 7 : merge_dims(GEN V, GEN W, GEN CHI)
5824 : {
5825 7 : long i, j, id, l = lg(V);
5826 7 : GEN A = cgetg(l, t_VEC);
5827 7 : if (l == 1) return A;
5828 7 : id = CHI? 1: 3;
5829 21 : for (i = j = 1; i < l; i++)
5830 : {
5831 14 : GEN v = gel(V,i), w = gel(W,i);
5832 14 : long dv = itou(gel(v,id)), dvh = itou(gel(v,id+1)), d;
5833 14 : long dw = itou(gel(w,id)), dwh = itou(gel(w,id+1));
5834 14 : d = dv + dw;
5835 14 : if (d || CHI)
5836 14 : gel(A,j++) = CHI? fmt_dim(gel(CHI,i),d, dvh+dwh)
5837 14 : : mkvec2s(d,dvh+dwh);
5838 : }
5839 7 : setlg(A, j); return A;
5840 : }
5841 : static GEN
5842 3010 : mfdim0all(GEN w)
5843 : {
5844 3038 : if (w) retconst_vec(lg(w)-1, zerovec(2));
5845 3003 : return cgetg(1,t_VEC);
5846 : }
5847 : static long
5848 7315 : mf1cuspdim_i(long N, GEN CHI, GEN TMP, GEN vSP, long *dih)
5849 : {
5850 7315 : pari_sp av = avma;
5851 7315 : GEN b = mf1basis(N, CHI, TMP, vSP, NULL, dih);
5852 7315 : return gc_long(av, b? itou(b): 0);
5853 : }
5854 :
5855 : static long
5856 476 : mf1cuspdim(long N, GEN CHI, GEN vSP)
5857 : {
5858 476 : if (!vSP) vSP = get_vDIH(N, divisorsNF(N, mfcharconductor(CHI)));
5859 476 : return mf1cuspdim_i(N, CHI, NULL, vSP, NULL);
5860 : }
5861 : static GEN
5862 4144 : mf1cuspdimall(long N, GEN vCHI)
5863 : {
5864 : GEN z, TMP, w, vSP;
5865 : long i, j, l;
5866 4144 : if (wt1empty(N)) return mfdim0all(vCHI);
5867 1141 : w = mf1chars(N,vCHI);
5868 1141 : l = lg(w); if (l == 1) return cgetg(1,t_VEC);
5869 1141 : z = cgetg(l, t_VEC);
5870 1141 : TMP = mf1_pre(N); vSP = get_vDIH(N, NULL);
5871 7861 : for (i = j = 1; i < l; i++)
5872 : {
5873 6720 : GEN CHI = gel(w,i);
5874 6720 : long dih, d = mf1cuspdim_i(N, CHI, TMP, vSP, &dih);
5875 6720 : if (vCHI)
5876 42 : gel(z,j++) = mkvec2s(d, dih);
5877 6678 : else if (d)
5878 1428 : gel(z,j++) = fmt_dim(CHI, d, dih);
5879 : }
5880 1141 : setlg(z,j); return z;
5881 : }
5882 :
5883 : /* dimension of S_1(Gamma_1(N)) */
5884 : static long
5885 4123 : mf1cuspdimsum(long N)
5886 : {
5887 4123 : pari_sp av = avma;
5888 4123 : GEN v = mf1cuspdimall(N, NULL);
5889 4123 : long i, ct = 0, l = lg(v);
5890 5544 : for (i = 1; i < l; i++)
5891 : {
5892 1421 : GEN w = gel(v,i); /* [ord(CHI),*,dim,*] */
5893 1421 : ct += itou(gel(w,3))*myeulerphiu(itou(gel(w,1)));
5894 : }
5895 4123 : return gc_long(av,ct);
5896 : }
5897 :
5898 : static GEN
5899 56 : mf1newdimall(long N, GEN vCHI)
5900 : {
5901 : GEN z, w, vTMP, vSP, fa, P, E;
5902 : long i, c, l, lw, P1;
5903 56 : if (wt1empty(N)) return mfdim0all(vCHI);
5904 56 : w = mf1chars(N,vCHI);
5905 56 : lw = lg(w); if (lw == 1) return cgetg(1,t_VEC);
5906 56 : vTMP = const_vec(N, NULL);
5907 56 : vSP = get_vDIH(N, NULL);
5908 56 : gel(vTMP,N) = mf1_pre(N);
5909 : /* if p || N and p \nmid F(CHI), S_1^new(G0(N),chi) = 0 */
5910 56 : fa = znstar_get_faN(gmael(w,1,1));
5911 56 : P = gel(fa,1); l = lg(P);
5912 56 : E = gel(fa,2);
5913 154 : for (i = P1 = 1; i < l; i++)
5914 98 : if (E[i] == 1) P1 *= itou(gel(P,i));
5915 : /* P1 = \prod_{v_p(N) = 1} p */
5916 56 : z = cgetg(lw, t_VEC);
5917 182 : for (i = c = 1; i < lw; i++)
5918 : {
5919 : long S, j, l, F, dihnew;
5920 126 : GEN D, CHI = gel(w,i), CHIP = mfchartoprimitive(CHI,&F);
5921 :
5922 126 : S = F % P1? 0: mf1cuspdim_i(N, CHI, gel(vTMP,N), vSP, &dihnew);
5923 126 : if (!S)
5924 : {
5925 56 : if (vCHI) gel(z, c++) = zerovec(2);
5926 56 : continue;
5927 : }
5928 70 : D = mydivisorsu(N/F); l = lg(D);
5929 77 : for (j = l-2; j > 0; j--) /* skip last M = N */
5930 : {
5931 7 : long M = D[j]*F, m, s, dih;
5932 7 : GEN TMP = gel(vTMP,M);
5933 7 : if (wt1empty(M) || !(m = mubeta(D[l-j]))) continue; /*m = mubeta(N/M)*/
5934 7 : if (!TMP) gel(vTMP,M) = TMP = mf1_pre(M);
5935 7 : s = mf1cuspdim_i(M, CHIP, TMP, vSP, &dih);
5936 7 : if (s) { S += m * s; dihnew += m * dih; }
5937 : }
5938 70 : if (vCHI)
5939 63 : gel(z,c++) = mkvec2s(S, dihnew);
5940 7 : else if (S)
5941 7 : gel(z, c++) = fmt_dim(CHI, S, dihnew);
5942 : }
5943 56 : setlg(z,c); return z;
5944 : }
5945 :
5946 : static GEN
5947 28 : mf1olddimall(long N, GEN vCHI)
5948 : {
5949 : long i, j, l;
5950 : GEN z, w;
5951 28 : if (wt1empty(N)) return mfdim0all(vCHI);
5952 28 : w = mf1chars(N,vCHI);
5953 28 : l = lg(w); z = cgetg(l, t_VEC);
5954 84 : for (i = j = 1; i < l; i++)
5955 : {
5956 56 : GEN CHI = gel(w,i);
5957 56 : long d = mfolddim(N, 1, CHI);
5958 56 : if (vCHI)
5959 28 : gel(z,j++) = mkvec2s(d,d?-1:0);
5960 28 : else if (d)
5961 7 : gel(z, j++) = fmt_dim(CHI, d, -1);
5962 : }
5963 28 : setlg(z,j); return z;
5964 : }
5965 :
5966 : static long
5967 469 : mf1olddimsum(long N)
5968 : {
5969 : GEN D;
5970 469 : long N2, i, l, S = 0;
5971 469 : newd_params(N, &N2); /* will ensure mubeta != 0 */
5972 469 : D = mydivisorsu(N/N2); l = lg(D);
5973 2485 : for (i = 2; i < l; i++)
5974 : {
5975 2016 : long M = D[l-i]*N2, d = mf1cuspdimsum(M);
5976 2016 : if (d) S -= mubeta(D[i]) * d;
5977 : }
5978 469 : return S;
5979 : }
5980 : static long
5981 1050 : mf1newdimsum(long N)
5982 : {
5983 1050 : long S = mf1cuspdimsum(N);
5984 1050 : return S? S - mf1olddimsum(N): 0;
5985 : }
5986 :
5987 : /* return the automorphism of a degree-2 nf */
5988 : static GEN
5989 5768 : nf2_get_conj(GEN nf)
5990 : {
5991 5768 : GEN pol = nf_get_pol(nf);
5992 5768 : return deg1pol_shallow(gen_m1, negi(gel(pol,3)), varn(pol));
5993 : }
5994 : static int
5995 42 : foo_stable(GEN foo)
5996 42 : { return lg(foo) != 3 || equalii(gel(foo,1), gel(foo,2)); }
5997 :
5998 : static long
5999 224 : mfisdihedral(GEN vF, GEN DIH)
6000 : {
6001 224 : GEN vG = gel(DIH,1), M = gel(DIH,2), v, G, bnr, w, gen, D, f, nf, tau;
6002 224 : GEN bnr0 = NULL, f0, f0b, xin, foo;
6003 : long i, l, e, j, L, n;
6004 224 : if (lg(M) == 1) return 0;
6005 42 : v = RgM_RgC_invimage(M, vF);
6006 42 : if (!v) return 0;
6007 42 : l = lg(v);
6008 42 : for (i = 1; i < l; i++)
6009 42 : if (!gequal0(gel(v,i))) break;
6010 42 : if (i == l) return 0;
6011 42 : G = gel(vG,i);
6012 42 : bnr = gel(G,2); D = cyc_get_expo(bnr_get_cyc(bnr));
6013 42 : w = gel(G,3);
6014 42 : f = bnr_get_mod(bnr);
6015 42 : nf = bnr_get_nf(bnr);
6016 42 : tau = nf2_get_conj(nf);
6017 42 : f0 = gel(f,1); foo = gel(f,2);
6018 42 : f0b = galoisapply(nf, tau, f0);
6019 42 : xin = zv_to_ZV(gel(w,2)); /* xi(bnr.gen[i]) = e(xin[i] / D) */
6020 42 : if (!foo_stable(foo)) { foo = mkvec2(gen_1, gen_1); bnr0 = bnr; }
6021 42 : if (!gequal(f0, f0b))
6022 : {
6023 21 : f0 = idealmul(nf, f0, idealdivexact(nf, f0b, idealadd(nf, f0, f0b)));
6024 21 : bnr0 = bnr;
6025 : }
6026 42 : if (bnr0)
6027 : { /* conductor not ambiguous */
6028 : GEN S;
6029 28 : bnr = Buchray(bnr_get_bnf(bnr), mkvec2(f0, foo), nf_INIT | nf_GEN);
6030 28 : S = bnrsurjection(bnr, bnr0);
6031 28 : xin = FpV_red(RgV_RgM_mul(xin, gel(S,1)), D);
6032 : /* still xi(gen[i]) = e(xin[i] / D), for the new generators; D stays
6033 : * the same, not exponent(bnr.cyc) ! */
6034 : }
6035 42 : gen = bnr_get_gen(bnr); L = lg(gen);
6036 77 : for (j = 1, e = itou(D); j < L; j++)
6037 : {
6038 63 : GEN Ng = idealnorm(nf, gel(gen,j));
6039 63 : GEN a = shifti(gel(xin,j), 1); /* xi(g_j^2) = e(a/D) */
6040 63 : GEN b = FpV_dotproduct(xin, isprincipalray(bnr,Ng), D);
6041 63 : GEN m = Fp_sub(a, b, D); /* xi(g_j/g_j^\tau) = e(m/D) */
6042 63 : e = ugcd(e, itou(m)); if (e == 1) break;
6043 : }
6044 42 : n = itou(D) / e;
6045 42 : return n == 1? 4: 2*n;
6046 : }
6047 :
6048 : static ulong
6049 119 : myradicalu(ulong n) { return zv_prod(gel(myfactoru(n),1)); }
6050 :
6051 : /* list of fundamental discriminants unramified outside N, with sign s
6052 : * [s = 0 => no sign condition] */
6053 : static GEN
6054 119 : mfunram(long N, long s)
6055 : {
6056 119 : long cN = myradicalu(N >> vals(N)), p = 1, m = 1, l, c, i;
6057 119 : GEN D = mydivisorsu(cN), res;
6058 119 : l = lg(D);
6059 119 : if (s == 1) m = 0; else if (s == -1) p = 0;
6060 119 : res = cgetg(6*l - 5, t_VECSMALL);
6061 119 : c = 1;
6062 119 : if (!odd(N))
6063 : { /* d = 1 */
6064 56 : if (p) res[c++] = 8;
6065 56 : if (m) { res[c++] =-8; res[c++] =-4; }
6066 : }
6067 364 : for (i = 2; i < l; i++)
6068 : { /* skip d = 1, done above */
6069 245 : long d = D[i], d4 = d & 3L; /* d odd, squarefree, d4 = 1 or 3 */
6070 245 : if (d4 == 1) { if (p) res[c++] = d; }
6071 182 : else { if (m) res[c++] =-d; }
6072 245 : if (!odd(N))
6073 : {
6074 56 : if (p) { res[c++] = 8*d; if (d4 == 3) res[c++] = 4*d; }
6075 56 : if (m) { res[c++] =-8*d; if (d4 == 1) res[c++] =-4*d; }
6076 : }
6077 : }
6078 119 : setlg(res, c); return res;
6079 : }
6080 :
6081 : /* Return 1 if F is definitely not S4 type; return 0 on failure. */
6082 : static long
6083 105 : mfisnotS4(long N, GEN w)
6084 : {
6085 105 : GEN D = mfunram(N, 0);
6086 105 : long i, lD = lg(D), lw = lg(w);
6087 616 : for (i = 1; i < lD; i++)
6088 : {
6089 511 : long p, d = D[i], ok = 0;
6090 1442 : for (p = 2; p < lw; p++)
6091 1442 : if (w[p] && kross(d,p) == -1) { ok = 1; break; }
6092 511 : if (!ok) return 0;
6093 : }
6094 105 : return 1;
6095 : }
6096 :
6097 : /* Return 1 if Q(sqrt(5)) \not\subset Q(F), i.e. F is definitely not A5 type;
6098 : * return 0 on failure. */
6099 : static long
6100 105 : mfisnotA5(GEN F)
6101 : {
6102 105 : GEN CHI = mf_get_CHI(F), P = mfcharpol(CHI), T, Q;
6103 :
6104 105 : if (mfcharorder(CHI) % 5 == 0) return 0;
6105 105 : T = mf_get_field(F); if (degpol(T) == 1) return 1;
6106 105 : if (degpol(P) > 1) T = rnfequation(P,T);
6107 105 : Q = gsubgs(pol_xn(2,varn(T)), 5);
6108 105 : return (typ(nfisincl(Q, T)) == t_INT);
6109 : }
6110 :
6111 : /* v[p+1]^2 / chi(p) - 2 = z + 1/z with z primitive root of unity of order n,
6112 : * return n */
6113 : static long
6114 6741 : mffindrootof1(GEN v, long p, GEN CHI)
6115 : {
6116 6741 : GEN ap = gel(v,p+1), u0, u1, u1k, u2;
6117 6741 : long c = 1;
6118 6741 : if (gequal0(ap)) return 2;
6119 5033 : u0 = gen_2; u1k = u1 = gsubgs(gdiv(gsqr(ap), mfchareval(CHI, p)), 2);
6120 14812 : while (!gequalsg(2, liftpol_shallow(u1))) /* u1 = z^c + z^-c */
6121 : {
6122 9779 : u2 = gsub(gmul(u1k, u1), u0);
6123 9779 : u0 = u1; u1 = u2; c++;
6124 : }
6125 5033 : return c;
6126 : }
6127 :
6128 : /* we known that F is not dihedral */
6129 : static long
6130 182 : mfgaloistype_i(long N, GEN CHI, GEN F, GEN v)
6131 : {
6132 : forprime_t iter;
6133 182 : long lim = lg(v)-2;
6134 182 : GEN w = zero_zv(lim);
6135 : pari_sp av;
6136 : ulong p;
6137 182 : u_forprime_init(&iter, 2, lim);
6138 182 : av = avma;
6139 5292 : while((p = u_forprime_next(&iter))) if (N%p) switch(mffindrootof1(v, p, CHI))
6140 : {
6141 1400 : case 1: case 2: continue;
6142 3451 : case 3: w[p] = 1; break;
6143 70 : case 4: return -24; /* S4 */
6144 0 : case 5: return -60; /* A5 */
6145 7 : default: pari_err_DOMAIN("mfgaloistype", "form", "not a",
6146 : strtoGENstr("cuspidal eigenform"), F);
6147 0 : set_avma(av);
6148 : }
6149 105 : if (mfisnotS4(N,w) && mfisnotA5(F)) return -12; /* A4 */
6150 0 : return 0; /* FAILURE */
6151 : }
6152 :
6153 : static GEN
6154 224 : mfgaloistype0(long N, GEN CHI, GEN F, GEN DIH, long lim)
6155 : {
6156 224 : pari_sp av = avma;
6157 224 : GEN vF = mftocol(F, lim, 1);
6158 224 : long t = mfisdihedral(vF, DIH), bound;
6159 224 : if (t) return gc_stoi(av,t);
6160 182 : bound = maxss(200, 5*expu(N)*expu(N));
6161 : for(;;)
6162 : {
6163 182 : t = mfgaloistype_i(N, CHI, F, vF);
6164 175 : set_avma(av); if (t) return stoi(t);
6165 0 : if (lim > bound) return gen_0;
6166 0 : lim += lim >> 1;
6167 0 : vF = mfcoefs_i(F,lim,1);
6168 : }
6169 : }
6170 :
6171 : /* If f is NULL, give all the galoistypes, otherwise just for f */
6172 : /* Return 0 to indicate failure; in this case the type is either -12 or -60,
6173 : * most likely -12. FIXME using the Galois representation. */
6174 : GEN
6175 231 : mfgaloistype(GEN NK, GEN f)
6176 : {
6177 231 : pari_sp av = avma;
6178 231 : GEN CHI, T, F, DIH, SP, mf = checkMF_i(NK);
6179 : long N, k, lL, i, lim, SB;
6180 :
6181 231 : if (f && !checkmf_i(f)) pari_err_TYPE("mfgaloistype", f);
6182 224 : if (mf)
6183 : {
6184 189 : N = MF_get_N(mf);
6185 189 : k = MF_get_k(mf);
6186 189 : CHI = MF_get_CHI(mf);
6187 : }
6188 : else
6189 : {
6190 35 : checkNK(NK, &N, &k, &CHI, 0);
6191 35 : mf = f? NULL: mfinit_i(NK, mf_NEW);
6192 : }
6193 224 : if (k != 1) pari_err_DOMAIN("mfgaloistype", "k", "!=", gen_1, stoi(k));
6194 224 : SB = mf? mfsturm_mf(mf): mfsturmNk(N,1);
6195 224 : SP = get_DIH(N);
6196 224 : DIH = mfdihedralnew(N, CHI, SP);
6197 224 : lim = lg(DIH) == 1? 200: SB;
6198 224 : DIH = mkvec2(DIH, mfvectomat(DIH,SB,1));
6199 224 : if (f) return gc_INT(av, mfgaloistype0(N,CHI, f, DIH, lim));
6200 126 : F = mfeigenbasis(mf); lL = lg(F);
6201 126 : T = cgetg(lL, t_VEC);
6202 252 : for (i=1; i < lL; i++) gel(T,i) = mfgaloistype0(N, CHI, gel(F,i), DIH, lim);
6203 126 : return gc_upto(av, T);
6204 : }
6205 :
6206 : /******************************************************************/
6207 : /* Find all dihedral forms. */
6208 : /******************************************************************/
6209 : /* lim >= 2 */
6210 : static void
6211 14 : consttabdihedral(long lim) { cache_set(cache_DIH, mfdihedralall(lim)); }
6212 :
6213 : /* a ideal coprime to bnr modulus */
6214 : static long
6215 107611 : mfdiheval(GEN bnr, GEN w, GEN a)
6216 : {
6217 107611 : GEN L, cycn = gel(w,1), chin = gel(w,2);
6218 107611 : long ordmax = cycn[1];
6219 107611 : L = ZV_to_Flv(isprincipalray(bnr,a), ordmax);
6220 107611 : return Flv_dotproduct(chin, L, ordmax);
6221 : }
6222 :
6223 : /* x(t^k) mod T = polcyclo(m), 0 <= k < m */
6224 : static GEN
6225 30331 : Galois(GEN x, long k, GEN T, long m)
6226 : {
6227 : GEN B;
6228 : long i, ik, d;
6229 30331 : if (typ(x) != t_POL) return x;
6230 7455 : if (varn(x) != varn(T)) pari_APPLY_pol_normalized(Galois(gel(x,i), k, T, m));
6231 7420 : if ((d = degpol(x)) <= 0) return x;
6232 7063 : B = cgetg(m + 2, t_POL); B[1] = x[1]; gel(B,2) = gel(x,2);
6233 61565 : for (i = 1; i < m; i++) gel(B, i+2) = gen_0;
6234 23940 : for (i = 1, ik = k; i <= d; i++, ik = Fl_add(ik, k, m))
6235 16877 : gel(B, ik + 2) = gel(x, i+2);
6236 7063 : return QX_ZX_rem(normalizepol(B), T);
6237 : }
6238 : static GEN
6239 1022 : vecGalois(GEN x, long k, GEN T, long m)
6240 31332 : { pari_APPLY_same(Galois(gel(x,i), k, T, m)); }
6241 :
6242 : static GEN
6243 234178 : fix_pol(GEN S, GEN Pn, int *trace)
6244 : {
6245 234178 : if (typ(S) != t_POL) return S;
6246 118069 : S = RgX_rem(S, Pn);
6247 118069 : if (typ(S) == t_POL)
6248 : {
6249 118069 : switch(lg(S))
6250 : {
6251 45108 : case 2: return gen_0;
6252 20517 : case 3: return gel(S,2);
6253 : }
6254 52444 : *trace = 1;
6255 : }
6256 52444 : return S;
6257 : }
6258 :
6259 : static GEN
6260 13573 : dihan(GEN bnr, GEN w, GEN k0j, long m, ulong lim)
6261 : {
6262 13573 : GEN nf = bnr_get_nf(bnr), f = bid_get_ideal(bnr_get_bid(bnr));
6263 13573 : GEN v = zerovec(lim+1), cycn = gel(w,1), Tinit = gel(w,3);
6264 13573 : GEN Pn = gel(Tinit,lg(Tinit)==4? 2: 1);
6265 13573 : long j, ordmax = cycn[1];
6266 13573 : long D = itos(nf_get_disc(nf)), vt = varn(Pn);
6267 13573 : int trace = 0;
6268 : ulong p, n;
6269 : forprime_t T;
6270 :
6271 13573 : if (!lim) return v;
6272 13363 : gel(v,2) = gen_1;
6273 13363 : u_forprime_init(&T, 2, lim);
6274 : /* fill in prime powers first */
6275 116207 : while ((p = u_forprime_next(&T)))
6276 : {
6277 : GEN vP, vchiP, S;
6278 : long k, lP;
6279 : ulong q, qk;
6280 102844 : if (kross(D,p) >= 0) q = p;
6281 45192 : else if (!(q = umuluu_le(p,p,lim))) continue;
6282 : /* q = Norm P */
6283 65856 : vP = idealprimedec(nf, utoipos(p));
6284 65856 : lP = lg(vP);
6285 65856 : vchiP = cgetg(lP, t_VECSMALL);
6286 179081 : for (j = k = 1; j < lP; j++)
6287 : {
6288 113225 : GEN P = gel(vP,j);
6289 113225 : if (!idealval(nf, f, P)) vchiP[k++] = mfdiheval(bnr,w,P);
6290 : }
6291 65856 : if (k == 1) continue;
6292 62188 : setlg(vchiP, k); lP = k;
6293 62188 : if (lP == 2)
6294 : { /* one prime above p not dividing f */
6295 16765 : long s, s0 = vchiP[1];
6296 27069 : for (qk=q, s = s0;; s = Fl_add(s,s0,ordmax))
6297 : {
6298 27069 : S = Qab_zeta(s, ordmax, vt);
6299 27069 : gel(v, qk+1) = fix_pol(S, Pn, &trace);
6300 27069 : if (!(qk = umuluu_le(qk,q,lim))) break;
6301 : }
6302 : }
6303 : else /* two primes above p not dividing f */
6304 : {
6305 45423 : long s, s0 = vchiP[1], s1 = vchiP[2];
6306 45423 : for (qk=q, k = 1;; k++)
6307 18424 : { /* sum over a,b s.t. Norm( P1^a P2^b ) = q^k, i.e. a+b = k */
6308 : long a;
6309 63847 : GEN S = gen_0;
6310 220752 : for (a = 0; a <= k; a++)
6311 : {
6312 156905 : s = Fl_add(Fl_mul(a, s0, ordmax), Fl_mul(k-a, s1, ordmax), ordmax);
6313 156905 : S = gadd(S, Qab_zeta(s, ordmax, vt));
6314 : }
6315 63847 : gel(v, qk+1) = fix_pol(S, Pn, &trace);
6316 63847 : if (!(qk = umuluu_le(qk,q,lim))) break;
6317 : }
6318 : }
6319 : }
6320 : /* complete with nonprime powers */
6321 308098 : for (n = 2; n <= lim; n++)
6322 : {
6323 294735 : GEN S, fa = myfactoru(n), P = gel(fa, 1), E = gel(fa, 2);
6324 : long q;
6325 294735 : if (lg(P) == 2) continue;
6326 : /* not a prime power */
6327 143262 : q = upowuu(P[1],E[1]);
6328 143262 : S = gmul(gel(v, q + 1), gel(v, n/q + 1));
6329 143262 : gel(v, n+1) = fix_pol(S, Pn, &trace);
6330 : }
6331 13363 : if (trace)
6332 : {
6333 7154 : long k0 = k0j[1], jdeg = k0j[2];
6334 7154 : v = QabV_tracerel(Tinit, jdeg, v); /* Apply Galois Mod(k0, ordw) */
6335 7154 : if (k0 > 1) v = vecGalois(v, k0, gel(Tinit,1), m);
6336 : }
6337 13363 : return v;
6338 : }
6339 :
6340 : /* as cyc_normalize for t_VECSMALL cyc */
6341 : static GEN
6342 26810 : cyc_normalize_zv(GEN cyc)
6343 : {
6344 26810 : long i, o = cyc[1], l = lg(cyc); /* > 1 */
6345 26810 : GEN D = cgetg(l, t_VECSMALL);
6346 31185 : D[1] = o; for (i = 2; i < l; i++) D[i] = o / cyc[i];
6347 26810 : return D;
6348 : }
6349 : /* as char_normalize for t_VECSMALLs */
6350 : static GEN
6351 118517 : char_normalize_zv(GEN chi, GEN ncyc)
6352 : {
6353 118517 : long i, l = lg(chi);
6354 118517 : GEN c = cgetg(l, t_VECSMALL);
6355 118517 : if (l > 1) {
6356 118517 : c[1] = chi[1];
6357 160454 : for (i = 2; i < l; i++) c[i] = chi[i] * ncyc[i];
6358 : }
6359 118517 : return c;
6360 : }
6361 :
6362 : static GEN
6363 9331 : dihan_bnf(long D)
6364 : {
6365 9331 : GEN c = getrand(), bnf;
6366 9331 : setrand(gen_1);
6367 9331 : bnf = Buchall(quadpoly_i(stoi(D)), nf_FORCE, LOWDEFAULTPREC);
6368 9331 : setrand(c);
6369 9331 : return bnf;
6370 : }
6371 : static GEN
6372 37758 : dihan_bnr(GEN bnf, GEN A)
6373 : {
6374 37758 : GEN c = getrand(), bnr;
6375 37758 : setrand(gen_1);
6376 37758 : bnr = Buchray(bnf, A, nf_INIT|nf_GEN);
6377 37758 : setrand(c);
6378 37758 : return bnr;
6379 : }
6380 : /* Hecke xi * (D/.) = Dirichlet chi, return v in Q^r st chi(g_i) = e(v[i]).
6381 : * cycn = cyc_normalize_zv(bnr.cyc), chin = char_normalize_zv(chi,cyc) */
6382 : static GEN
6383 34489 : bnrchartwist2conrey(GEN chin, GEN cycn, GEN bnrconreyN, GEN kroconreyN)
6384 : {
6385 34489 : long l = lg(bnrconreyN), c1 = cycn[1], i;
6386 34489 : GEN v = cgetg(l, t_COL);
6387 125363 : for (i = 1; i < l; i++)
6388 : {
6389 90874 : GEN d = sstoQ(zv_dotproduct(chin, gel(bnrconreyN,i)), c1);
6390 90874 : if (kroconreyN[i] < 0) d = gadd(d, ghalf);
6391 90874 : gel(v,i) = d;
6392 : }
6393 34489 : return v;
6394 : }
6395 :
6396 : /* chi(g_i) = e(v[i]) denormalize wrt Conrey generators orders */
6397 : static GEN
6398 34489 : conreydenormalize(GEN znN, GEN v)
6399 : {
6400 34489 : GEN gcyc = znstar_get_conreycyc(znN), w;
6401 34489 : long l = lg(v), i;
6402 34489 : w = cgetg(l, t_COL);
6403 125363 : for (i = 1; i < l; i++)
6404 90874 : gel(w,i) = modii(gmul(gel(v,i), gel(gcyc,i)), gel(gcyc,i));
6405 34489 : return w;
6406 : }
6407 :
6408 : static long
6409 84028 : Miyake(GEN vchi, GEN gb, GEN cycn)
6410 : {
6411 84028 : long i, e = cycn[1], lb = lg(gb);
6412 84028 : GEN v = char_normalize_zv(vchi, cycn);
6413 124992 : for (i = 1; i < lb; i++)
6414 100268 : if ((zv_dotproduct(v, gel(gb,i)) - v[i]) % e) return 1;
6415 24724 : return 0;
6416 : }
6417 :
6418 : /* list of Hecke characters not induced by a Dirichlet character up to Galois
6419 : * conjugation, whose conductor is bnr.cond; cycn = cyc_normalize(bnr.cyc)*/
6420 : static GEN
6421 26810 : mklvchi(GEN bnr, GEN cycn, GEN gb)
6422 : {
6423 26810 : GEN cyc = bnr_get_cyc(bnr), cycsmall = ZV_to_zv(cyc);
6424 26810 : GEN vchi = cyc2elts(cycsmall);
6425 26810 : long ordmax = cycsmall[1], c, i, l;
6426 26810 : l = lg(vchi);
6427 304024 : for (i = c = 1; i < l; i++)
6428 : {
6429 277214 : GEN chi = gel(vchi,i);
6430 277214 : if (!gb || Miyake(chi, gb, cycn)) gel(vchi, c++) = Flv_to_ZV(chi);
6431 : }
6432 26810 : setlg(vchi, c); l = c;
6433 279300 : for (i = 1; i < l; i++)
6434 : {
6435 252490 : GEN chi = gel(vchi,i);
6436 : long n;
6437 252490 : if (!chi) continue;
6438 1055754 : for (n = 2; n < ordmax; n++)
6439 966476 : if (ugcd(n, ordmax) == 1)
6440 : {
6441 397670 : GEN tmp = ZV_ZV_mod(gmulsg(n, chi), cyc);
6442 : long j;
6443 7623539 : for (j = i+1; j < l; j++)
6444 7225869 : if (gel(vchi,j) && gequal(gel(vchi,j), tmp)) gel(vchi,j) = NULL;
6445 : }
6446 : }
6447 279300 : for (i = c = 1; i < l; i++)
6448 : {
6449 252490 : GEN chi = gel(vchi,i);
6450 252490 : if (chi && bnrisconductor(bnr, chi)) gel(vchi, c++) = chi;
6451 : }
6452 26810 : setlg(vchi, c); return vchi;
6453 : }
6454 :
6455 : static GEN
6456 7805 : get_gb(GEN bnr, GEN con)
6457 : {
6458 7805 : GEN gb, g = bnr_get_gen(bnr), nf = bnr_get_nf(bnr);
6459 7805 : long i, l = lg(g);
6460 7805 : gb = cgetg(l, t_VEC);
6461 18326 : for (i = 1; i < l; i++)
6462 10521 : gel(gb,i) = ZV_to_zv(isprincipalray(bnr, galoisapply(nf, con, gel(g,i))));
6463 7805 : return gb;
6464 : }
6465 : static GEN
6466 15862 : get_bnrconreyN(GEN bnr, GEN znN)
6467 : {
6468 15862 : GEN z, g = znstar_get_conreygen(znN);
6469 15862 : long i, l = lg(g);
6470 15862 : z = cgetg(l, t_VEC);
6471 57134 : for (i = 1; i < l; i++) gel(z,i) = ZV_to_zv(isprincipalray(bnr,gel(g,i)));
6472 15862 : return z;
6473 : }
6474 : /* con = NULL if D > 0 or if D < 0 and id != idcon. */
6475 : static GEN
6476 33698 : mfdihedralcommon(GEN bnf, GEN id, GEN znN, GEN kroconreyN, long vt,
6477 : long N, long D, GEN con)
6478 : {
6479 33698 : GEN bnr = dihan_bnr(bnf, id), cyc = ZV_to_zv( bnr_get_cyc(bnr) );
6480 : GEN bnrconreyN, cycn, cycN, Lvchi, res, P, vT;
6481 : long j, ordmax, l, lc, deghecke;
6482 :
6483 33698 : lc = lg(cyc); if (lc == 1) return NULL;
6484 26810 : cycn = cyc_normalize_zv(cyc);
6485 26810 : Lvchi = mklvchi(bnr, cycn, con? get_gb(bnr, con): NULL);
6486 26810 : l = lg(Lvchi);
6487 26810 : if (l == 1) return NULL;
6488 :
6489 15862 : bnrconreyN = get_bnrconreyN(bnr, znN);
6490 15862 : cycN = ZV_to_zv(znstar_get_cyc(znN));
6491 15862 : ordmax = cyc[1];
6492 15862 : vT = const_vec(odd(ordmax)? ordmax << 1: ordmax, NULL);
6493 15862 : P = polcyclo(ordmax, vt);
6494 15862 : gel(vT,ordmax) = Qab_trace_init(ordmax, ordmax, P, P);
6495 15862 : deghecke = myeulerphiu(ordmax);
6496 15862 : res = cgetg(l, t_VEC);
6497 50351 : for (j = 1; j < l; j++)
6498 : {
6499 34489 : GEN T, v, vchi = ZV_to_zv(gel(Lvchi,j));
6500 34489 : GEN chi, chin = char_normalize_zv(vchi, cycn);
6501 : long o, vnum, k0, degrel;
6502 34489 : v = bnrchartwist2conrey(chin, cycn, bnrconreyN, kroconreyN);
6503 34489 : o = itou(Q_denom(v));
6504 34489 : T = gel(vT, o);
6505 34489 : if (!T) gel(vT,o) = T = Qab_trace_init(ordmax, o, P, polcyclo(o,vt));
6506 34489 : chi = conreydenormalize(znN, v);
6507 34489 : vnum = itou(znconreyexp(znN, chi));
6508 34489 : chi = ZV_to_zv(znconreychar(znN,chi));
6509 34489 : degrel = deghecke / degpol(gel(T,1));
6510 34489 : k0 = zv_cyc_minimize(cycN, chi, coprimes_zv(o));
6511 34489 : vnum = Fl_powu(vnum, k0, N);
6512 : /* encodes degrel forms: jdeg = 0..degrel-1 */
6513 34489 : gel(res,j) = mkvec3(mkvecsmalln(5, N, k0 % o, vnum, D, degrel),
6514 : id, mkvec3(cycn,chin,T));
6515 : }
6516 15862 : return res;
6517 : }
6518 :
6519 : static long
6520 49364 : is_cond(long D, long n)
6521 : {
6522 49364 : if (D > 0) return n != 4 || (D&7L) == 1;
6523 30114 : return n != 2 && n != 3 && (n != 4 || (D&7L)!=1);
6524 : }
6525 : /* Append to v all dihedral weight 1 forms coming from D, if fundamental.
6526 : * level in [l1, l2] */
6527 : static void
6528 18718 : append_dihedral(GEN v, long D, long l1, long l2, long vt)
6529 : {
6530 18718 : long Da = labs(D), no, i, numi, ct, min, max;
6531 : GEN bnf, con, vI, resall, arch1, arch2;
6532 : pari_sp av;
6533 :
6534 : /* min <= Nf <= max */
6535 18718 : max = l2 / Da;
6536 18718 : if (l1 == l2)
6537 : { /* assume Da | l2 */
6538 140 : min = max;
6539 140 : if (D > 0 && min < 3) return;
6540 : }
6541 : else /* assume l1 < l2 */
6542 18578 : min = (l1 + Da-1)/Da;
6543 18718 : if (!sisfundamental(D)) return;
6544 :
6545 5726 : av = avma;
6546 5726 : bnf = dihan_bnf(D);
6547 5726 : con = nf2_get_conj(bnf_get_nf(bnf));
6548 5726 : vI = ideallist(bnf, max);
6549 55090 : numi = 0; for (i = min; i <= max; i++) numi += lg(gel(vI, i)) - 1;
6550 5726 : if (D > 0)
6551 : {
6552 1428 : numi <<= 1;
6553 1428 : arch1 = mkvec2(gen_1,gen_0);
6554 1428 : arch2 = mkvec2(gen_0,gen_1);
6555 : }
6556 : else
6557 4298 : arch1 = arch2 = NULL;
6558 5726 : resall = cgetg(numi+1, t_VEC); ct = 1;
6559 55090 : for (no = min; no <= max; no++) if (is_cond(D, no))
6560 : {
6561 44646 : long N = Da*no, lc, lI;
6562 44646 : GEN I = gel(vI, no), znN = znstar0(utoipos(N), 1), conreyN, kroconreyN;
6563 :
6564 44646 : conreyN = znstar_get_conreygen(znN); lc = lg(conreyN);
6565 44646 : kroconreyN = cgetg(lc, t_VECSMALL);
6566 166054 : for (i = 1; i < lc; i++) kroconreyN[i] = krosi(D, gel(conreyN, i));
6567 44646 : lI = lg(I);
6568 87822 : for (i = 1; i < lI; i++)
6569 : {
6570 43176 : GEN id = gel(I, i), idcon, z;
6571 : long j;
6572 43176 : if (typ(id) == t_INT) continue;
6573 28182 : idcon = galoisapply(bnf, con, id);
6574 51408 : for (j = i; j < lI; j++)
6575 51408 : if (gequal(idcon, gel(I, j))) { gel(I, j) = gen_0; break; }
6576 28182 : if (D < 0)
6577 : {
6578 17479 : GEN conk = i == j ? con : NULL;
6579 17479 : z = mfdihedralcommon(bnf, id, znN, kroconreyN, vt, N, D, conk);
6580 17479 : if (z) gel(resall, ct++) = z;
6581 : }
6582 : else
6583 : {
6584 : GEN ide;
6585 10703 : ide = mkvec2(id, arch1);
6586 10703 : z = mfdihedralcommon(bnf, ide, znN, kroconreyN, vt, N, D, NULL);
6587 10703 : if (z) gel(resall, ct++) = z;
6588 10703 : if (gequal(idcon,id)) continue;
6589 5516 : ide = mkvec2(id, arch2);
6590 5516 : z = mfdihedralcommon(bnf, ide, znN, kroconreyN, vt, N, D, NULL);
6591 5516 : if (z) gel(resall, ct++) = z;
6592 : }
6593 : }
6594 : }
6595 5726 : if (ct == 1) set_avma(av);
6596 : else
6597 : {
6598 4816 : setlg(resall, ct);
6599 4816 : vectrunc_append(v, gc_GEN(av, shallowconcat1(resall)));
6600 : }
6601 : }
6602 :
6603 : static long
6604 42042 : di_N(GEN a) { return gel(a,1)[1]; }
6605 : static GEN
6606 14 : mfdihedral(long N)
6607 : {
6608 14 : GEN D = mydivisorsu(N), res = vectrunc_init(2*N);
6609 14 : long j, l = lg(D), vt = fetch_user_var("t");
6610 105 : for (j = 2; j < l; j++)
6611 : { /* skip d = 1 */
6612 91 : long d = D[j];
6613 91 : if (d == 2) continue;
6614 84 : append_dihedral(res, -d, N,N, vt);
6615 84 : if (d >= 5 && D[l-j] >= 3) append_dihedral(res, d, N,N, vt);/* Nf >= 3 */
6616 : }
6617 14 : if (lg(res) > 1) res = shallowconcat1(res);
6618 14 : return res;
6619 : }
6620 : /* All primitive dihedral weight 1 forms of leven in [1, N], N > 1 */
6621 : static GEN
6622 14 : mfdihedralall(long N)
6623 : {
6624 14 : GEN res = vectrunc_init(2*N), z;
6625 14 : long D, ct, i, vt = fetch_user_var("t");
6626 :
6627 13986 : for (D = -3; D >= -N; D--) append_dihedral(res, D, 1,N, vt);
6628 : /* Nf >= 3 (GTM 193, prop 3.3.18) */
6629 4620 : for (D = N / 3; D >= 5; D--) append_dihedral(res, D, 1,N, vt);
6630 14 : ct = lg(res);
6631 14 : if (ct > 1)
6632 : { /* sort wrt N */
6633 14 : res = shallowconcat1(res);
6634 14 : res = vecpermute(res, indexvecsort(res, mkvecsmall(1)));
6635 14 : ct = lg(res);
6636 : }
6637 14 : z = const_vec(N, cgetg(1,t_VEC));
6638 7658 : for (i = 1; i < ct;)
6639 : { /* regroup result sharing the same N */
6640 7644 : long n = di_N(gel(res,i)), j = i+1, k;
6641 : GEN v;
6642 34412 : while (j < ct && di_N(gel(res,j)) == n) j++;
6643 7644 : gel(z, n) = v = cgetg(j-i+1, t_VEC);
6644 42056 : for (k = 1; i < j; k++,i++) gel(v,k) = gel(res,i);
6645 : }
6646 14 : return z;
6647 : }
6648 :
6649 : /* return [vF, index], where vecpermute(vF,index) generates dihedral forms
6650 : * for character CHI */
6651 : static GEN
6652 24969 : mfdihedralnew_i(long N, GEN CHI, GEN SP)
6653 : {
6654 : GEN bnf, Tinit, Pm, vf, M, V, NK;
6655 : long Dold, d, ordw, i, SB, c, l, k0, k1, chino, chinoorig, lv;
6656 :
6657 24969 : lv = lg(SP); if (lv == 1) return NULL;
6658 12138 : CHI = mfcharinduce(CHI,N);
6659 12138 : ordw = mfcharorder(CHI);
6660 12138 : chinoorig = mfcharno(CHI);
6661 12138 : k0 = mfconreyminimize(CHI);
6662 12138 : chino = Fl_powu(chinoorig, k0, N);
6663 12138 : k1 = Fl_inv(k0 % ordw, ordw);
6664 12138 : V = cgetg(lv, t_VEC);
6665 12138 : d = 0;
6666 39039 : for (i = l = 1; i < lv; i++)
6667 : {
6668 26901 : GEN sp = gel(SP,i), T = gel(sp,1);
6669 26901 : if (T[3] != chino) continue;
6670 4060 : d += T[5];
6671 4060 : if (k1 != 1)
6672 : {
6673 77 : GEN t = leafcopy(T);
6674 77 : t[3] = chinoorig;
6675 77 : t[2] = (t[2]*k1) % ordw;
6676 77 : sp = mkvec4(t, gel(sp,2), gel(sp,3), gel(sp,4));
6677 : }
6678 4060 : gel(V, l++) = sp;
6679 : }
6680 12138 : setlg(V, l); /* dihedral forms of level N and character CHI */
6681 12138 : if (l == 1) return NULL;
6682 :
6683 2555 : SB = mfsturmNk(N,1) + 1;
6684 2555 : M = cgetg(d+1, t_MAT);
6685 2555 : vf = cgetg(d+1, t_VEC);
6686 2555 : NK = mkNK(N, 1, CHI);
6687 2555 : bnf = NULL; Dold = 0;
6688 6615 : for (i = c = 1; i < l; i++)
6689 : { /* T = [N, k0, conreyno, D, degrel] */
6690 4060 : GEN bnr, Vi = gel(V,i), T = gel(Vi,1), id = gel(Vi,2), w = gel(Vi,3);
6691 4060 : long jdeg, k0i = T[2], D = T[4], degrel = T[5];
6692 :
6693 4060 : if (D != Dold) { Dold = D; bnf = dihan_bnf(D); }
6694 4060 : bnr = dihan_bnr(bnf, id);
6695 12054 : for (jdeg = 0; jdeg < degrel; jdeg++,c++)
6696 : {
6697 7994 : GEN k0j = mkvecsmall2(k0i, jdeg), an = dihan(bnr, w, k0j, ordw, SB);
6698 7994 : settyp(an, t_COL); gel(M,c) = an;
6699 7994 : gel(vf,c) = tag3(t_MF_DIHEDRAL, NK, bnr, w, k0j);
6700 : }
6701 : }
6702 2555 : Tinit = gmael3(V,1,3,3); Pm = gel(Tinit,1);
6703 2555 : V = QabM_indexrank(M, degpol(Pm)==1? NULL: Pm, ordw);
6704 2555 : return mkvec2(vf,gel(V,2));
6705 : }
6706 : static long
6707 16149 : mfdihedralnewdim(long N, GEN CHI, GEN SP)
6708 : {
6709 16149 : pari_sp av = avma;
6710 16149 : GEN S = mfdihedralnew_i(N, CHI, SP);
6711 16149 : return gc_long(av, S? lg(gel(S,2))-1: 0);
6712 : }
6713 : static GEN
6714 8820 : mfdihedralnew(long N, GEN CHI, GEN SP)
6715 : {
6716 8820 : pari_sp av = avma;
6717 8820 : GEN S = mfdihedralnew_i(N, CHI, SP);
6718 8820 : if (!S) retgc_const(av, cgetg(1, t_VEC));
6719 917 : return vecpermute(gel(S,1), gel(S,2));
6720 : }
6721 :
6722 : static long
6723 7105 : mfdihedralcuspdim(long N, GEN CHI, GEN vSP)
6724 : {
6725 7105 : pari_sp av = avma;
6726 : GEN D, CHIP;
6727 : long F, i, lD, dim;
6728 :
6729 7105 : CHIP = mfchartoprimitive(CHI, &F);
6730 7105 : D = mydivisorsu(N/F); lD = lg(D);
6731 7105 : dim = mfdihedralnewdim(N, CHI, gel(vSP,N)); /* d = 1 */
6732 16149 : for (i = 2; i < lD; i++)
6733 : {
6734 9044 : long d = D[i], a = mfdihedralnewdim(N/d, CHIP, gel(vSP, N/d));
6735 9044 : if (a) dim += a * mynumdivu(d);
6736 : }
6737 7105 : return gc_long(av,dim);
6738 : }
6739 :
6740 : static GEN
6741 7385 : mfbdall(GEN E, long N)
6742 : {
6743 7385 : GEN v, D = mydivisorsu(N);
6744 7385 : long i, j, nD = lg(D) - 1, nE = lg(E) - 1;
6745 7385 : v = cgetg(nD*nE + 1, t_VEC);
6746 10500 : for (j = 1; j <= nE; j++)
6747 : {
6748 3115 : GEN Ej = gel(E, j);
6749 9513 : for (i = 0; i < nD; i++) gel(v, i*nE + j) = mfbd_i(Ej, D[i+1]);
6750 : }
6751 7385 : return v;
6752 : }
6753 : static GEN
6754 3857 : mfdihedralcusp(long N, GEN CHI, GEN vSP)
6755 : {
6756 3857 : pari_sp av = avma;
6757 : GEN D, CHIP, z;
6758 : long F, i, lD;
6759 :
6760 3857 : CHIP = mfchartoprimitive(CHI, &F);
6761 3857 : D = mydivisorsu(N/F); lD = lg(D);
6762 3857 : z = cgetg(lD, t_VEC);
6763 3857 : gel(z,1) = mfdihedralnew(N, CHI, gel(vSP,N));
6764 8596 : for (i = 2; i < lD; i++) /* skip 1 */
6765 : {
6766 4739 : GEN LF = mfdihedralnew(N / D[i], CHIP, gel(vSP, N / D[i]));
6767 4739 : gel(z,i) = mfbdall(LF, D[i]);
6768 : }
6769 3857 : return gc_GEN(av, shallowconcat1(z));
6770 : }
6771 :
6772 : /* used to decide between ratlift and comatrix for ZM_inv; ratlift is better
6773 : * when N has many divisors */
6774 : static int
6775 2604 : abundant(ulong N) { return mynumdivu(N) >= 8; }
6776 :
6777 : /* CHI an mfchar */
6778 : static int
6779 371 : cmp_ord(void *E, GEN a, GEN b)
6780 : {
6781 371 : GEN chia = MF_get_CHI(a), chib = MF_get_CHI(b);
6782 371 : (void)E; return cmpii(gmfcharorder(chia), gmfcharorder(chib));
6783 : }
6784 : /* mfinit structure.
6785 : -- mf[1] contains [N,k,CHI,space],
6786 : -- mf[2] contains vector of closures of Eisenstein series, empty if not
6787 : full space.
6788 : -- mf[3] contains vector of closures, so #mf[3] = dimension of cusp/new space.
6789 : -- mf[4] contains the corresponding indices: either j for T(j)tf if newspace,
6790 : or [M,j,d] for B(d)T(j)tf_M if cuspspace or oldspace.
6791 : -- mf[5] contains the matrix M of first coefficients of basis, never cleaned.
6792 : * NK is either [N,k] or [N,k,CHI].
6793 : * mfinit does not do the splitting, only the basis generation. */
6794 :
6795 : /* Set flraw to 1 if do not need mf[5]: no mftobasis etc..., only the
6796 : expansions of the basis elements are needed. */
6797 :
6798 : static GEN
6799 5075 : mfinit_Nkchi(long N, long k, GEN CHI, long space, long flraw)
6800 : {
6801 5075 : GEN M = NULL, mf = NULL, mf1 = mkvec4(utoi(N), stoi(k), CHI, utoi(space));
6802 5075 : long sb = mfsturmNk(N, k);
6803 5075 : if (k < 0 || badchar(N, k, CHI)) return mfEMPTY(mf1);
6804 5040 : if (k == 0 || space == mf_EISEN) /*nothing*/;
6805 4879 : else if (k == 1)
6806 : {
6807 364 : switch (space)
6808 : {
6809 350 : case mf_NEW:
6810 : case mf_FULL:
6811 350 : case mf_CUSP: mf = mf1init(N, CHI, NULL, get_vDIH(N,NULL), space, flraw);
6812 350 : break;
6813 7 : case mf_OLD: pari_err_IMPL("mfinit in weight 1 for old space");
6814 7 : default: pari_err_FLAG("mfinit");
6815 : }
6816 : }
6817 : else /* k >= 2 */
6818 : {
6819 4515 : long ord = mfcharorder(CHI);
6820 4515 : GEN z = NULL, P = (ord <= 2)? NULL: mfcharpol(CHI);
6821 : cachenew_t cache;
6822 4515 : switch(space)
6823 : {
6824 1239 : case mf_NEW:
6825 1239 : mf = mfnewinit(N, k, CHI, &cache, 1);
6826 1239 : if (mf && !flraw) { M = MF_get_M(mf); z = MF_get_Mindex(mf); }
6827 1239 : break;
6828 3269 : case mf_OLD:
6829 : case mf_CUSP:
6830 : case mf_FULL:
6831 3269 : if (!(mf = mfinitcusp(N, k, CHI, &cache, space))) break;
6832 2961 : if (!flraw)
6833 : {
6834 2296 : M = bhnmat_extend(M, sb+1, 1, MF_get_S(mf), &cache);
6835 2296 : if (space != mf_FULL) gel(mf,5) = mfcleanCHI(M, CHI, abundant(N));
6836 : }
6837 2961 : dbg_cachenew(&cache); break;
6838 7 : default: pari_err_FLAG("mfinit");
6839 : }
6840 4508 : if (z) gel(mf,5) = mfclean2(M, z, P, ord);
6841 : }
6842 5019 : if (!mf) mf = mfEMPTY(mf1);
6843 : else
6844 : {
6845 4053 : gel(mf,1) = mf1;
6846 4053 : if (flraw) gel(mf,5) = zerovec(3);
6847 : }
6848 5019 : if (!space_is_cusp(space))
6849 : {
6850 861 : GEN E = mfeisensteinbasis(N, k, CHI);
6851 861 : gel(mf,2) = E;
6852 861 : if (!flraw)
6853 : {
6854 539 : if (M)
6855 231 : M = shallowconcat(mfvectomat(E, sb+1, 1), M);
6856 : else
6857 308 : M = mfcoefs_mf(mf, sb+1, 1);
6858 539 : gel(mf,5) = mfcleanCHI(M, CHI, abundant(N));
6859 : }
6860 : }
6861 5019 : return mf;
6862 : }
6863 :
6864 : /* mfinit for k = nk/dk */
6865 : static GEN
6866 2765 : mfinit_Nndkchi(long N, long nk, long dk, GEN CHI, long space, long flraw)
6867 273 : { return (dk == 2)? mf2init_Nkchi(N, nk >> 1, CHI, space, flraw)
6868 3038 : : mfinit_Nkchi(N, nk, CHI, space, flraw); }
6869 : static GEN
6870 3430 : mfinit_i(GEN NK, long space)
6871 : {
6872 : GEN CHI, mf;
6873 : long N, k, dk, joker;
6874 3430 : if (checkmf_i(NK))
6875 : {
6876 161 : N = mf_get_N(NK);
6877 161 : Qtoss(mf_get_gk(NK), &k, &dk);
6878 161 : CHI = mf_get_CHI(NK);
6879 : }
6880 3269 : else if ((mf = checkMF_i(NK)))
6881 : {
6882 21 : long s = MF_get_space(mf);
6883 21 : if (s == space) return mf;
6884 21 : Qtoss(MF_get_gk(mf), &k, &dk);
6885 21 : if (dk == 1 && k > 1 && space == mf_NEW && (s == mf_CUSP || s == mf_FULL))
6886 21 : return mfinittonew(mf);
6887 0 : N = MF_get_N(mf);
6888 0 : CHI = MF_get_CHI(mf);
6889 : }
6890 : else
6891 3248 : checkNK2(NK, &N, &k, &dk, &CHI, 1);
6892 3388 : joker = !CHI || typ(CHI) == t_COL;
6893 3388 : if (joker)
6894 : {
6895 1162 : GEN mf, vCHI = CHI;
6896 : long i, j, l;
6897 1162 : if (CHI && lg(CHI) == 1) return cgetg(1,t_VEC);
6898 1155 : if (k < 0) return mfEMPTYall(N, uutoQ(k,dk), CHI, space);
6899 1141 : if (k == 1 && dk == 1 && space != mf_EISEN)
6900 504 : {
6901 : GEN TMP, vSP, gN, gs;
6902 : pari_timer tt;
6903 1106 : if (space != mf_CUSP && space != mf_NEW)
6904 0 : pari_err_IMPL("mfinit([N,1,wildcard], space != cusp or new space)");
6905 1106 : if (wt1empty(N)) return mfEMPTYall(N, gen_1, CHI, space);
6906 504 : vCHI = mf1chars(N,vCHI);
6907 504 : l = lg(vCHI); mf = cgetg(l, t_VEC); if (l == 1) return mf;
6908 504 : TMP = mf1_pre(N); vSP = get_vDIH(N, NULL);
6909 504 : gN = utoipos(N); gs = utoi(space);
6910 504 : if (DEBUGLEVEL) timer_start(&tt);
6911 4123 : for (i = j = 1; i < l; i++)
6912 : {
6913 3619 : pari_sp av = avma;
6914 3619 : GEN c = gel(vCHI,i), z = mf1init(N, c, TMP, vSP, space, 0);
6915 3619 : if (z) z = gc_GEN(av, z);
6916 : else
6917 : {
6918 2905 : set_avma(av);
6919 2905 : if (CHI) z = mfEMPTY(mkvec4(gN,gen_1,c,gs));
6920 : }
6921 3619 : if (z) gel(mf, j++) = z;
6922 3619 : if (DEBUGLEVEL)
6923 0 : timer_printf(&tt, "mf1basis: character %ld / %ld (order = %ld)",
6924 : i, l-1, mfcharorder(c));
6925 : }
6926 : }
6927 : else
6928 : {
6929 35 : vCHI = mfchars(N,k,dk,vCHI);
6930 35 : l = lg(vCHI); mf = cgetg(l, t_VEC);
6931 119 : for (i = j = 1; i < l; i++)
6932 : {
6933 84 : pari_sp av = avma;
6934 84 : GEN v = mfinit_Nndkchi(N, k, dk, gel(vCHI,i), space, 0);
6935 84 : if (MF_get_dim(v) || CHI) gel(mf, j++) = v; else set_avma(av);
6936 : }
6937 : }
6938 539 : setlg(mf,j);
6939 539 : if (!CHI) gen_sort_inplace(mf, NULL, &cmp_ord, NULL);
6940 539 : return mf;
6941 : }
6942 2226 : return mfinit_Nndkchi(N, k, dk, CHI, space, 0);
6943 : }
6944 : GEN
6945 2450 : mfinit(GEN NK, long space)
6946 : {
6947 2450 : pari_sp av = avma;
6948 2450 : return gc_GEN(av, mfinit_i(NK, space));
6949 : }
6950 :
6951 : /* UTILITY FUNCTIONS */
6952 : static void
6953 364 : cusp_canon(GEN cusp, long N, long *pA, long *pC)
6954 : {
6955 364 : pari_sp av = avma;
6956 : long A, C, tc, cg;
6957 364 : if (N <= 0) pari_err_DOMAIN("mfcuspwidth","N","<=",gen_0,stoi(N));
6958 357 : if (!cusp || (tc = typ(cusp)) == t_INFINITY) { *pA = 1; *pC = N; return; }
6959 350 : if (tc != t_INT && tc != t_FRAC) pari_err_TYPE("checkcusp", cusp);
6960 350 : Qtoss(cusp, &A,&C);
6961 350 : if (N % C)
6962 : {
6963 : ulong uC;
6964 14 : long u = Fl_invgen((C-1)%N + 1, N, &uC);
6965 14 : A = Fl_mul(A, u, N);
6966 14 : C = (long)uC;
6967 : }
6968 350 : cg = ugcd(C, N/C);
6969 420 : while (ugcd(A, N) > 1) A += cg;
6970 350 : *pA = A % N; *pC = C; set_avma(av);
6971 : }
6972 : static long
6973 1001 : mfcuspcanon_width(long N, long C)
6974 1001 : { return (!C || C == N)? 1 : N / ugcd(N, Fl_sqr(umodsu(C,N),N)); }
6975 : /* v = [a,c] a ZC, width of cusp (a:c) */
6976 : static long
6977 9975 : mfZC_width(long N, GEN v)
6978 : {
6979 9975 : ulong C = umodiu(gel(v,2), N);
6980 9975 : return (C == 0)? 1: N / ugcd(N, Fl_sqr(C,N));
6981 : }
6982 : long
6983 161 : mfcuspwidth(GEN gN, GEN cusp)
6984 : {
6985 161 : long N = 0, A, C;
6986 : GEN mf;
6987 161 : if (typ(gN) == t_INT) N = itos(gN);
6988 42 : else if ((mf = checkMF_i(gN))) N = MF_get_N(mf);
6989 0 : else pari_err_TYPE("mfcuspwidth", gN);
6990 161 : cusp_canon(cusp, N, &A, &C);
6991 154 : return mfcuspcanon_width(N, C);
6992 : }
6993 :
6994 : /* Q a t_INT */
6995 : static GEN
6996 14 : findq(GEN al, GEN Q)
6997 : {
6998 : long n;
6999 14 : if (typ(al) == t_FRAC && cmpii(gel(al,2), Q) <= 0)
7000 0 : return mkvec(mkvec2(gel(al,1), gel(al,2)));
7001 14 : n = 1 + (long)ceil(2.0781*gtodouble(glog(Q, LOWDEFAULTPREC)));
7002 14 : return contfracpnqn(gboundcf(al,n), n);
7003 : }
7004 : static GEN
7005 91 : findqga(long N, GEN z)
7006 : {
7007 91 : GEN Q, LDC, CK = NULL, DK = NULL, ma, x, y = imag_i(z);
7008 : long j, l;
7009 91 : if (gcmpgs(gmulsg(2*N, y), 1) >= 0) return NULL;
7010 14 : x = real_i(z);
7011 14 : Q = ground(ginv(gsqrt(gmulsg(N, y), LOWDEFAULTPREC)));
7012 14 : LDC = findq(gmulsg(-N,x), Q);
7013 14 : ma = gen_1; l = lg(LDC);
7014 35 : for (j = 1; j < l; j++)
7015 : {
7016 21 : GEN D, DC = gel(LDC,j), C1 = gel(DC,2);
7017 21 : if (cmpii(C1,Q) > 0) break;
7018 21 : D = gel(DC,1);
7019 21 : if (ugcdiu(D,N) == 1)
7020 : {
7021 7 : GEN C = mului(N, C1), den;
7022 7 : den = gadd(gsqr(gmul(C,y)), gsqr(gadd(D, gmul(C,x))));
7023 7 : if (gcmp(den, ma) < 0) { ma = den; CK = C; DK = D; }
7024 : }
7025 : }
7026 14 : return DK? mkvec2(CK, DK): NULL;
7027 : }
7028 :
7029 : static long
7030 168 : valNC2(GEN P, GEN E, long e)
7031 : {
7032 168 : long i, d = 1, l = lg(P);
7033 504 : for (i = 1; i < l; i++)
7034 : {
7035 336 : long v = u_lval(e, P[i]) << 1;
7036 336 : if (v == E[i] + 1) v--;
7037 336 : d *= upowuu(P[i], v);
7038 : }
7039 168 : return d;
7040 : }
7041 :
7042 : static GEN
7043 49 : findqganew(long N, GEN z)
7044 : {
7045 49 : GEN MI, DI, x = real_i(z), y = imag_i(z), Ck = gen_0, Dk = gen_1, fa, P, E;
7046 : long i;
7047 49 : MI = uutoQ(1,N);
7048 49 : DI = mydivisorsu(mysqrtu(N));
7049 49 : fa = myfactoru(N); P = gel(fa,1); E = gel(fa,2);
7050 217 : for (i = 1; i < lg(DI); i++)
7051 : {
7052 168 : long e = DI[i], g;
7053 : GEN U, C, D, m;
7054 168 : (void)cxredsl2(gmulsg(e, z), &U);
7055 168 : C = gcoeff(U,2,1); if (!signe(C)) continue;
7056 168 : D = gcoeff(U,2,2);
7057 168 : g = ugcdiu(D,e);
7058 168 : if (g > 1) { C = muliu(C,e/g); D = diviuexact(D,g); } else C = muliu(C,e);
7059 168 : m = gadd(gsqr(gadd(gmul(C, x), D)), gsqr(gmul(C, y)));
7060 168 : m = gdivgu(m, valNC2(P, E, e));
7061 168 : if (gcmp(m, MI) < 0) { MI = m; Ck = C; Dk = D; }
7062 : }
7063 49 : return signe(Ck)? mkvec2(Ck, Dk): NULL;
7064 : }
7065 :
7066 : /* Return z' and U = [a,b;c,d] \in SL_2(Z), z' = U*z,
7067 : * Im(z')/width(U.oo) > sqrt(3)/(2N). Set *pczd = c*z+d */
7068 : static GEN
7069 182 : cxredga0N(long N, GEN z, GEN *pU, GEN *pczd, long flag)
7070 : {
7071 182 : GEN v = NULL, A, B, C, D;
7072 : long e;
7073 182 : if (N == 1) return cxredsl2_i(z, pU, pczd);
7074 140 : e = gexpo(gel(z,2));
7075 140 : if (e < 0) z = gprec_wensure(z, precision(z) + nbits2extraprec(-e));
7076 140 : v = flag? findqganew(N,z): findqga(N,z);
7077 140 : if (!v) { *pU = matid(2); *pczd = gen_1; return z; }
7078 56 : C = gel(v,1);
7079 56 : D = gel(v,2);
7080 56 : if (!is_pm1(bezout(C,D, &B,&A))) pari_err_BUG("cxredga0N [gcd > 1]");
7081 56 : B = negi(B);
7082 56 : *pU = mkmat2(mkcol2(A,C), mkcol2(B,D));
7083 56 : *pczd = gadd(gmul(C,z), D);
7084 56 : return gdiv(gadd(gmul(A,z), B), *pczd);
7085 : }
7086 :
7087 : static GEN
7088 161 : lfunthetaall(GEN b, GEN vL, GEN t, long bitprec)
7089 : {
7090 161 : long i, l = lg(vL);
7091 161 : GEN v = cgetg(l, t_VEC);
7092 350 : for (i = 1; i < l; i++)
7093 : {
7094 189 : GEN T, L = gel(vL,i), a0 = gel(L,1), ldata = gel(L,2);
7095 189 : GEN van = gel(ldata_get_an(ldata),2);
7096 189 : if (lg(van) == 1)
7097 : {
7098 0 : T = gmul(b, a0);
7099 0 : if (isexactzero(T)) { GEN z = real_0_bit(-bitprec); T = mkcomplex(z,z); }
7100 : }
7101 : else
7102 : {
7103 189 : T = gmul2n(lfuntheta(ldata, t, 0, bitprec), -1);
7104 189 : T = gmul(b, gadd(a0, T));
7105 : }
7106 189 : gel(v,i) = T;
7107 : }
7108 161 : return l == 2? gel(v,1): v;
7109 : }
7110 :
7111 : /* P in ZX, irreducible */
7112 : static GEN
7113 182 : ZX_roots(GEN P, long prec)
7114 : {
7115 182 : long d = degpol(P);
7116 182 : if (d == 1) return mkvec(gen_0);
7117 182 : if (d == 2 && isint1(gel(P,2)) && isintzero(gel(P,3)) && isint1(gel(P,4)))
7118 7 : return mkvec2(powIs(3), gen_I()); /* order as polroots */
7119 294 : return (ZX_sturm_irred(P) == d)? ZX_realroots_irred(P, prec)
7120 294 : : QX_complex_roots(P, prec);
7121 : }
7122 : /* initializations for RgX_RgV_eval / RgC_embed */
7123 : static GEN
7124 217 : rootspowers(GEN v)
7125 : {
7126 217 : long i, l = lg(v);
7127 217 : GEN w = cgetg(l, t_VEC);
7128 868 : for (i = 1; i < l; i++) gel(w,i) = gpowers(gel(v,i), l-2);
7129 217 : return w;
7130 : }
7131 : /* mf embeddings attached to Q(chi)/(T), chi attached to cyclotomic P */
7132 : static GEN
7133 938 : getembed(GEN P, GEN T, GEN zcyclo, long prec)
7134 : {
7135 : long i, l;
7136 : GEN v;
7137 938 : if (degpol(P) == 1) P = NULL; /* mfcharpol for quadratic char */
7138 938 : if (degpol(T) == 1) T = NULL; /* dim 1 orbit */
7139 938 : if (T && P)
7140 35 : { /* K(y) / (T(y)), K = Q(t)/(P) cyclotomic */
7141 35 : GEN vr = RgX_is_ZX(T)? ZX_roots(T,prec): roots(RgX_embed1(T,zcyclo), prec);
7142 35 : v = rootspowers(vr); l = lg(v);
7143 105 : for (i = 1; i < l; i++) gel(v,i) = mkcol3(P,zcyclo,gel(v,i));
7144 : }
7145 903 : else if (T)
7146 : { /* Q(y) / (T(y)), T noncyclotomic */
7147 182 : GEN vr = ZX_roots(T, prec);
7148 182 : v = rootspowers(vr); l = lg(v);
7149 763 : for (i = 1; i < l; i++) gel(v,i) = mkcol2(T, gel(v,i));
7150 : }
7151 : else /* cyclotomic or rational */
7152 721 : v = mkvec(P? mkvec2(P, zcyclo): cgetg(1,t_VEC));
7153 938 : return v;
7154 : }
7155 : static GEN
7156 791 : grootsof1_CHI(GEN CHI, long prec)
7157 791 : { return grootsof1(mfcharorder(CHI), prec); }
7158 : /* return the [Q(F):Q(chi)] embeddings of F */
7159 : static GEN
7160 623 : mfgetembed(GEN F, long prec)
7161 : {
7162 623 : GEN T = mf_get_field(F), CHI = mf_get_CHI(F), P = mfcharpol(CHI);
7163 623 : return getembed(P, T, grootsof1_CHI(CHI, prec), prec);
7164 : }
7165 : static GEN
7166 7 : mfchiembed(GEN mf, long prec)
7167 : {
7168 7 : GEN CHI = MF_get_CHI(mf), P = mfcharpol(CHI);
7169 7 : return getembed(P, pol_x(0), grootsof1_CHI(CHI, prec), prec);
7170 : }
7171 : /* mfgetembed for the successive eigenforms in MF_get_newforms */
7172 : static GEN
7173 161 : mfeigenembed(GEN mf, long prec)
7174 : {
7175 161 : GEN vP = MF_get_fields(mf), vF = MF_get_newforms(mf);
7176 161 : GEN zcyclo, vE, CHI = MF_get_CHI(mf), P = mfcharpol(CHI);
7177 161 : long i, l = lg(vP);
7178 161 : vF = Q_remove_denom(liftpol_shallow(vF), NULL);
7179 161 : prec += nbits2extraprec(gexpo(vF));
7180 161 : zcyclo = grootsof1_CHI(CHI, prec);
7181 161 : vE = cgetg(l, t_VEC);
7182 469 : for (i = 1; i < l; i++) gel(vE,i) = getembed(P, gel(vP,i), zcyclo, prec);
7183 161 : return vE;
7184 : }
7185 :
7186 : static int
7187 28 : checkPv(GEN P, GEN v)
7188 28 : { return typ(P) == t_POL && is_vec_t(typ(v)) && lg(v)-1 >= degpol(P); }
7189 : static int
7190 28 : checkemb_i(GEN E)
7191 : {
7192 28 : long t = typ(E), l = lg(E);
7193 28 : if (t == t_VEC) return l == 1 || (l == 3 && checkPv(gel(E,1), gel(E,2)));
7194 21 : if (t != t_COL) return 0;
7195 21 : if (l == 3) return checkPv(gel(E,1), gel(E,2));
7196 21 : return l == 4 && is_vec_t(typ(gel(E,2))) && checkPv(gel(E,1), gel(E,3));
7197 : }
7198 : static GEN
7199 28 : anyembed(GEN v, GEN E)
7200 : {
7201 28 : switch(typ(v))
7202 : {
7203 21 : case t_VEC: case t_COL: return mfvecembed(E, v);
7204 7 : case t_MAT: return mfmatembed(E, v);
7205 : }
7206 0 : return mfembed(E, v);
7207 : }
7208 : GEN
7209 49 : mfembed0(GEN E, GEN v, long prec)
7210 : {
7211 49 : pari_sp av = avma;
7212 49 : GEN mf, vE = NULL;
7213 49 : if (checkmf_i(E)) vE = mfgetembed(E, prec);
7214 35 : else if ((mf = checkMF_i(E))) vE = mfchiembed(mf, prec);
7215 49 : if (vE)
7216 : {
7217 21 : long i, l = lg(vE);
7218 : GEN w;
7219 21 : if (!v) return gc_GEN(av, l == 2? gel(vE,1): vE);
7220 0 : w = cgetg(l, t_VEC);
7221 0 : for (i = 1; i < l; i++) gel(w,i) = anyembed(v, gel(vE,i));
7222 0 : return gc_GEN(av, l == 2? gel(w,1): w);
7223 : }
7224 28 : if (!checkemb_i(E) || !v) pari_err_TYPE("mfembed", E);
7225 28 : return gc_GEN(av, anyembed(v,E));
7226 : }
7227 :
7228 : /* dummy lfun create for theta evaluation */
7229 : static GEN
7230 980 : mfthetaancreate(GEN van, GEN N, GEN k)
7231 : {
7232 980 : GEN L = zerovec(6);
7233 980 : gel(L,1) = lfuntag(t_LFUN_GENERIC, van);
7234 980 : gel(L,3) = mkvec2(gen_0, gen_1);
7235 980 : gel(L,4) = k;
7236 980 : gel(L,5) = N; return L;
7237 : }
7238 : /* destroy van and prepare to evaluate theta(sigma(van)), for all sigma in
7239 : * embeddings vector vE */
7240 : static GEN
7241 357 : van_embedall(GEN van, GEN vE, GEN gN, GEN gk)
7242 : {
7243 357 : GEN a0 = gel(van,1), vL;
7244 357 : long i, lE = lg(vE), l = lg(van);
7245 357 : van++; van[0] = evaltyp(t_VEC) | _evallg(l-1); /* remove a0 */
7246 357 : vL = cgetg(lE, t_VEC);
7247 945 : for (i = 1; i < lE; i++)
7248 : {
7249 588 : GEN E = gel(vE,i), v = mfvecembed(E, van);
7250 588 : gel(vL,i) = mkvec2(mfembed(E,a0), mfthetaancreate(v, gN, gk));
7251 : }
7252 357 : return vL;
7253 : }
7254 :
7255 : static int
7256 1134 : cusp_AC(GEN cusp, long *A, long *C)
7257 : {
7258 1134 : switch(typ(cusp))
7259 : {
7260 140 : case t_INFINITY: *A = 1; *C = 0; break;
7261 301 : case t_INT: *A = itos(cusp); *C = 1; break;
7262 448 : case t_FRAC: *A = itos(gel(cusp, 1)); *C = itos(gel(cusp, 2)); break;
7263 245 : case t_REAL: case t_COMPLEX:
7264 245 : *A = 0; *C = 0;
7265 245 : if (gsigne(imag_i(cusp)) <= 0)
7266 7 : pari_err_DOMAIN("mfeval","imag(tau)","<=",gen_0,cusp);
7267 238 : return 0;
7268 0 : default: pari_err_TYPE("cusp_AC", cusp);
7269 : }
7270 889 : return 1;
7271 : }
7272 : static GEN
7273 518 : cusp2mat(long A, long C)
7274 : { long B, D;
7275 518 : cbezout(A, C, &D, &B);
7276 518 : return mkmat22s(A, -B, C, D);
7277 : }
7278 : static GEN
7279 21 : mkS(void) { return mkmat22s(0,-1,1,0); }
7280 :
7281 : /* if t is a cusp, return F(t), else NULL */
7282 : static GEN
7283 364 : evalcusp(GEN mf, GEN F, GEN t, long prec)
7284 : {
7285 : long A, C;
7286 : GEN R;
7287 364 : if (!cusp_AC(t, &A,&C)) return NULL;
7288 196 : if (C % mf_get_N(F) == 0) return gel(mfcoefs_i(F, 0, 1), 1);
7289 175 : R = mfgaexpansion(mf, F, cusp2mat(A,C), 0, prec);
7290 175 : return gequal0(gel(R,1))? gmael(R,3,1): gen_0;
7291 : }
7292 : /* Evaluate an mf closure numerically, i.e., in the usual sense, either for a
7293 : * single tau or a vector of tau; for each, return a vector of results
7294 : * corresponding to all complex embeddings of F. If flag is nonzero, allow
7295 : * replacing F by F | gamma to increase imag(gamma^(-1).tau) [ expensive if
7296 : * MF_EISENSPACE not present ] */
7297 : static GEN
7298 168 : mfeval_i(GEN mf, GEN F, GEN vtau, long flag, long bitprec)
7299 : {
7300 : GEN L0, vL, vb, sqN, vczd, vTAU, vs, van, vE;
7301 168 : long N = MF_get_N(mf), N0, ta, lv, i, prec = nbits2prec(bitprec);
7302 168 : GEN gN = utoipos(N), gk = mf_get_gk(F), gk1 = gsubgs(gk,1), vgk;
7303 168 : long flscal = 0;
7304 :
7305 : /* gen_0 is ignored, second component assumes Ramanujan-Petersson in
7306 : * 1/2-integer weight */
7307 168 : vgk = mkvec2(gen_0, mfiscuspidal(mf,F)? gmul2n(gk1,-1): gk1);
7308 168 : ta = typ(vtau);
7309 168 : if (!is_vec_t(ta)) { flscal = 1; vtau = mkvec(vtau); ta = t_VEC; }
7310 168 : lv = lg(vtau);
7311 168 : sqN = sqrtr_abs(utor(N, prec));
7312 168 : vs = const_vec(lv-1, NULL);
7313 168 : vb = const_vec(lv-1, NULL);
7314 168 : vL = cgetg(lv, t_VEC);
7315 168 : vTAU = cgetg(lv, t_VEC);
7316 168 : vczd = cgetg(lv, t_VEC);
7317 168 : L0 = mfthetaancreate(NULL, gN, vgk); /* only for thetacost */
7318 168 : vE = mfgetembed(F, prec);
7319 168 : N0 = 0;
7320 357 : for (i = 1; i < lv; i++)
7321 : {
7322 196 : GEN z = gel(vtau,i), tau, U;
7323 : long w, n;
7324 :
7325 196 : gel(vs,i) = evalcusp(mf, F, z, prec);
7326 189 : if (gel(vs,i)) continue;
7327 161 : tau = cxredga0N(N, z, &U, &gel(vczd,i), flag);
7328 161 : if (!flag) w = 0; else { w = mfZC_width(N, gel(U,1)); tau = gdivgu(tau,w); }
7329 161 : gel(vTAU,i) = mulcxmI(gmul(tau, sqN));
7330 161 : n = lfunthetacost(L0, real_i(gel(vTAU,i)), 0, bitprec, NULL);
7331 161 : if (N0 < n) N0 = n;
7332 161 : if (flag)
7333 : {
7334 49 : GEN A, al, v = mfslashexpansion(mf, F, ZM_inv(U,NULL), n, 0, &A, prec);
7335 49 : gel(vL,i) = van_embedall(v, vE, gN, vgk);
7336 49 : al = gel(A,1);
7337 49 : if (!gequal0(al))
7338 7 : gel(vb,i) = gexp(gmul(gmul(gmulsg(w,al),PiI2(prec)), tau), prec);
7339 : }
7340 : }
7341 161 : if (!flag)
7342 : {
7343 112 : van = mfcoefs_i(F, N0, 1);
7344 112 : vL = const_vec(lv-1, van_embedall(van, vE, gN, vgk));
7345 : }
7346 350 : for (i = 1; i < lv; i++)
7347 : {
7348 : GEN T;
7349 189 : if (gel(vs,i)) continue;
7350 161 : T = gpow(gel(vczd,i), gneg(gk), prec);
7351 161 : if (flag && gel(vb,i)) T = gmul(T, gel(vb,i));
7352 161 : gel(vs,i) = lfunthetaall(T, gel(vL,i), gel(vTAU,i), bitprec);
7353 : }
7354 161 : return flscal? gel(vs,1): vs;
7355 : }
7356 :
7357 : static long
7358 1372 : mfistrivial(GEN F)
7359 : {
7360 1372 : switch(mf_get_type(F))
7361 : {
7362 7 : case t_MF_CONST: return lg(gel(F,2)) == 1;
7363 287 : case t_MF_LINEAR: case t_MF_LINEAR_BHN: return gequal0(gel(F,3));
7364 1078 : default: return 0;
7365 : }
7366 : }
7367 :
7368 : static long
7369 1190 : mf_same_k(GEN mf, GEN f) { return gequal(MF_get_gk(mf), mf_get_gk(f)); }
7370 : static long
7371 1148 : mf_same_CHI(GEN mf, GEN f)
7372 : {
7373 1148 : GEN F1, F2, chi1, chi2, CHI1 = MF_get_CHI(mf), CHI2 = mf_get_CHI(f);
7374 : /* are the primitive chars attached to CHI1 and CHI2 equal ? */
7375 1148 : F1 = znconreyconductor(gel(CHI1,1), gel(CHI1,2), &chi1);
7376 1148 : if (typ(F1) == t_VEC) F1 = gel(F1,1);
7377 1148 : F2 = znconreyconductor(gel(CHI2,1), gel(CHI2,2), &chi2);
7378 1148 : if (typ(F2) == t_VEC) F2 = gel(F2,1);
7379 1148 : return equalii(F1,F2) && ZV_equal(chi1,chi2);
7380 : }
7381 : /* check k and CHI rigorously, but not coefficients nor N */
7382 : static long
7383 259 : mfisinspace_i(GEN mf, GEN F)
7384 : {
7385 259 : return mfistrivial(F) || (mf_same_k(mf,F) && mf_same_CHI(mf,F));
7386 : }
7387 : static void
7388 7 : err_space(GEN F)
7389 7 : { pari_err_DOMAIN("mftobasis", "form", "does not belong to",
7390 0 : strtoGENstr("space"), F); }
7391 :
7392 : static long
7393 154 : mfcheapeisen(GEN mf)
7394 : {
7395 154 : long k, L, N = MF_get_N(mf);
7396 : GEN P;
7397 154 : if (N <= 70) return 1;
7398 84 : k = itos(gceil(MF_get_gk(mf)));
7399 84 : if (odd(k)) k--;
7400 84 : switch (k)
7401 : {
7402 0 : case 2: L = 190; break;
7403 14 : case 4: L = 162; break;
7404 70 : case 6:
7405 70 : case 8: L = 88; break;
7406 0 : case 10: L = 78; break;
7407 0 : default: L = 66; break;
7408 : }
7409 84 : P = gel(myfactoru(N), 1);
7410 84 : return P[lg(P)-1] <= L;
7411 : }
7412 :
7413 : static GEN
7414 189 : myimag_i(GEN x)
7415 : {
7416 189 : long tc = typ(x);
7417 189 : if (tc == t_INFINITY || tc == t_INT || tc == t_FRAC) return gen_1;
7418 196 : if (tc == t_VEC) pari_APPLY_same(myimag_i(gel(x,i)));
7419 154 : return imag_i(x);
7420 : }
7421 :
7422 : static GEN
7423 154 : mintau(GEN vtau)
7424 : {
7425 154 : if (!is_vec_t(typ(vtau))) return myimag_i(vtau);
7426 7 : return (lg(vtau) == 1)? gen_1: vecmin(myimag_i(vtau));
7427 : }
7428 :
7429 : /* initialization for mfgaexpansion: what does not depend on cusp */
7430 : static GEN
7431 1218 : mf_eisendec(GEN mf, GEN F, long prec)
7432 : {
7433 1218 : GEN B = liftpol_shallow(mfeisensteindec(mf, F)), v = variables_vecsmall(B);
7434 1218 : GEN Mvecj = obj_check(mf, MF_EISENSPACE);
7435 1218 : long l = lg(v), i, ord;
7436 1218 : if (lg(Mvecj) < 5) Mvecj = gel(Mvecj,1);
7437 1218 : ord = itou(gel(Mvecj,4));
7438 1274 : for (i = 1; i < l; i++)
7439 924 : if (v[i] != 1)
7440 : {
7441 : GEN d;
7442 : long e;
7443 868 : B = Q_remove_denom(B, &d);
7444 868 : e = gexpo(B);
7445 868 : if (e > 0) prec += nbits2prec(e);
7446 868 : B = gsubst(B, v[i], rootsof1u_cx(ord, prec));
7447 868 : if (d) B = gdiv(B, d);
7448 868 : break;
7449 : }
7450 1218 : return B;
7451 : }
7452 :
7453 : GEN
7454 168 : mfeval(GEN mf0, GEN F, GEN vtau, long bitprec)
7455 : {
7456 168 : pari_sp av = avma;
7457 168 : long flnew = 1;
7458 168 : GEN mf = checkMF_i(mf0);
7459 168 : if (!mf) pari_err_TYPE("mfeval", mf0);
7460 168 : if (!checkmf_i(F)) pari_err_TYPE("mfeval", F);
7461 168 : if (!mfisinspace_i(mf, F)) err_space(F);
7462 168 : if (!obj_check(mf, MF_EISENSPACE)) flnew = mfcheapeisen(mf);
7463 168 : if (flnew && gcmpgs(gmulsg(2*MF_get_N(mf), mintau(vtau)), 1) >= 0) flnew = 0;
7464 168 : return gc_GEN(av, mfeval_i(mf, F, vtau, flnew, bitprec));
7465 : }
7466 :
7467 : static long
7468 189 : val(GEN v, long bit)
7469 : {
7470 189 : long c, l = lg(v);
7471 392 : for (c = 1; c < l; c++)
7472 378 : if (gexpo(gel(v,c)) > -bit) return c-1;
7473 14 : return -1;
7474 : }
7475 : GEN
7476 203 : mfcuspval(GEN mf, GEN F, GEN cusp, long bitprec)
7477 : {
7478 203 : pari_sp av = avma;
7479 203 : long lvE, w, N, sb, n, A, C, prec = nbits2prec(bitprec);
7480 : GEN ga, gk, vE;
7481 203 : mf = checkMF(mf);
7482 203 : if (!checkmf_i(F)) pari_err_TYPE("mfcuspval",F);
7483 203 : N = MF_get_N(mf);
7484 203 : cusp_canon(cusp, N, &A, &C);
7485 203 : gk = mf_get_gk(F);
7486 203 : if (typ(gk) != t_INT)
7487 : {
7488 42 : GEN FT = mfmultheta(F), mf2 = obj_checkbuild(mf, MF_MF2INIT, &mf2init);
7489 42 : GEN r = mfcuspval(mf2, FT, cusp, bitprec);
7490 42 : if ((C & 3L) == 2)
7491 : {
7492 14 : GEN z = uutoQ(1,4);
7493 14 : r = gsub(r, typ(r) == t_VEC? const_vec(lg(r)-1, z): z);
7494 : }
7495 42 : return gc_upto(av, r);
7496 : }
7497 161 : vE = mfgetembed(F, prec);
7498 161 : lvE = lg(vE);
7499 161 : w = mfcuspcanon_width(N, C);
7500 161 : sb = w * mfsturmNk(N, itos(gk));
7501 161 : ga = cusp2mat(A,C);
7502 168 : for (n = 8;; n = minss(sb, n << 1))
7503 7 : {
7504 168 : GEN R = mfgaexpansion(mf, F, ga, n, prec), res = liftpol_shallow(gel(R,3));
7505 168 : GEN v = cgetg(lvE-1, t_VECSMALL);
7506 168 : long j, ok = 1;
7507 168 : res = RgC_embedall(res, vE);
7508 357 : for (j = 1; j < lvE; j++)
7509 : {
7510 189 : v[j] = val(gel(res,j), bitprec/2);
7511 189 : if (v[j] < 0) ok = 0;
7512 : }
7513 168 : if (ok)
7514 : {
7515 154 : res = cgetg(lvE, t_VEC);
7516 329 : for (j = 1; j < lvE; j++) gel(res,j) = gadd(gel(R,1), uutoQ(v[j], w));
7517 154 : return gc_GEN(av, lvE==2? gel(res,1): res);
7518 : }
7519 14 : if (n == sb) return lvE==2? mkoo(): const_vec(lvE-1, mkoo()); /* 0 */
7520 : }
7521 : }
7522 :
7523 : long
7524 238 : mfiscuspidal(GEN mf, GEN F)
7525 : {
7526 238 : pari_sp av = avma;
7527 : GEN mf2;
7528 238 : if (space_is_cusp(MF_get_space(mf))) return 1;
7529 105 : if (typ(mf_get_gk(F)) == t_INT)
7530 : {
7531 63 : GEN v = mftobasis(mf,F,0), vE;
7532 63 : if (lg(v)==1) return gc_long(av, 0);
7533 63 : vE = vecslice(v, 1, lg(MF_get_E(mf))-1);
7534 63 : return gc_long(av, gequal0(vE));
7535 : }
7536 42 : if (!gequal0(mfak_i(F, 0))) return 0;
7537 21 : mf2 = obj_checkbuild(mf, MF_MF2INIT, &mf2init);
7538 21 : return mfiscuspidal(mf2, mfmultheta(F));
7539 : }
7540 :
7541 : /* F = vector of newforms in mftobasis format */
7542 : static GEN
7543 119 : mffrickeeigen_i(GEN mf, GEN F, GEN vE, long prec)
7544 : {
7545 119 : GEN M, Z, L0, gN = MF_get_gN(mf), gk = MF_get_gk(mf);
7546 119 : long N0, i, lM, bit = prec2nbits(prec), k = itou(gk);
7547 119 : long LIM = 5; /* Sturm bound is enough */
7548 :
7549 119 : L0 = mfthetaancreate(NULL, gN, gk); /* only for thetacost */
7550 119 : START:
7551 119 : N0 = lfunthetacost(L0, gen_1, LIM, bit, NULL);
7552 119 : M = mfcoefs_mf(mf, N0, 1);
7553 119 : lM = lg(F);
7554 119 : Z = cgetg(lM, t_VEC);
7555 315 : for (i = 1; i < lM; i++)
7556 : { /* expansion of D * F[i] */
7557 196 : GEN D, z, van = RgM_RgC_mul(M, Q_remove_denom(gel(F,i), &D));
7558 196 : GEN L = van_embedall(van, gel(vE,i), gN, gk);
7559 196 : long l = lg(L), j, bit_add = D? expi(D): 0;
7560 196 : gel(Z,i) = z = cgetg(l, t_VEC);
7561 595 : for (j = 1; j < l; j++)
7562 : {
7563 : GEN v, C, C0;
7564 : long m, e;
7565 546 : for (m = 0; m <= LIM; m++)
7566 : {
7567 546 : v = lfuntheta(gmael(L,j,2), gen_1, m, bit);
7568 546 : if (gexpo(v) > bit_add - bit/2) break;
7569 : }
7570 399 : if (m > LIM) { LIM <<= 1; goto START; }
7571 399 : C = mulcxpowIs(gdiv(v,conj_i(v)), 2*m - k);
7572 399 : C0 = grndtoi(C, &e); if (e < 5-prec2nbits(precision(C))) C = C0;
7573 399 : gel(z,j) = C;
7574 : }
7575 : }
7576 119 : return Z;
7577 : }
7578 : static GEN
7579 84 : mffrickeeigen(GEN mf, GEN vE, long prec)
7580 : {
7581 84 : GEN D = obj_check(mf, MF_FRICKE);
7582 84 : if (D) { long p = gprecision(D); if (!p || p >= prec) return D; }
7583 77 : D = mffrickeeigen_i(mf, MF_get_newforms(mf), vE, prec);
7584 77 : return obj_insert(mf, MF_FRICKE, D);
7585 : }
7586 :
7587 : /* integral weight, new space for primitive quadratic character CHIP;
7588 : * MF = vector of embedded eigenforms coefs on mfbasis, by orbit.
7589 : * Assume N > Q > 1 and (Q,f(CHIP)) = 1 */
7590 : static GEN
7591 56 : mfatkineigenquad(GEN mf, GEN CHIP, long Q, GEN MF, long bitprec)
7592 : {
7593 : GEN L0, la2, S, F, vP, tau, wtau, Z, va, vb, den, coe, sqrtQ, sqrtN;
7594 56 : GEN M, gN, gk = MF_get_gk(mf);
7595 56 : long N0, x, yq, i, j, lF, dim, muQ, prec = nbits2prec(bitprec);
7596 56 : long N = MF_get_N(mf), k = itos(gk), NQ = N / Q;
7597 :
7598 : /* Q coprime to FC */
7599 56 : F = MF_get_newforms(mf);
7600 56 : vP = MF_get_fields(mf);
7601 56 : lF = lg(F);
7602 56 : Z = cgetg(lF, t_VEC);
7603 56 : S = MF_get_S(mf); dim = lg(S) - 1;
7604 56 : muQ = mymoebiusu(Q);
7605 56 : if (muQ)
7606 : {
7607 42 : GEN SQ = cgetg(dim+1,t_VEC), Qk = gpow(stoi(Q), sstoQ(k-2, 2), prec);
7608 42 : long i, bit2 = bitprec >> 1;
7609 154 : for (j = 1; j <= dim; j++) gel(SQ,j) = mfak_i(gel(S,j), Q);
7610 84 : for (i = 1; i < lF; i++)
7611 : {
7612 42 : GEN S = RgV_dotproduct(gel(F,i), SQ), T = gel(vP,i);
7613 : long e;
7614 42 : if (degpol(T) > 1 && typ(S) != t_POLMOD) S = gmodulo(S, T);
7615 42 : S = grndtoi(gdiv(conjvec(S, prec), Qk), &e);
7616 42 : if (e > -bit2) pari_err_PREC("mfatkineigenquad");
7617 42 : if (muQ == -1) S = gneg(S);
7618 42 : gel(Z,i) = S;
7619 : }
7620 42 : return Z;
7621 : }
7622 14 : la2 = mfchareval(CHIP, Q); /* 1 or -1 */
7623 14 : (void)cbezout(Q, NQ, &x, &yq);
7624 14 : sqrtQ = sqrtr_abs(utor(Q,prec));
7625 14 : tau = mkcomplex(gadd(sstoQ(-1, NQ), uutoQ(1, 1000)),
7626 : divru(sqrtQ, N));
7627 14 : den = gaddgs(gmulsg(NQ, tau), 1);
7628 14 : wtau = gdiv(gsub(gmulsg(x, tau), sstoQ(yq, Q)), den);
7629 14 : coe = gpowgs(gmul(sqrtQ, den), k);
7630 :
7631 14 : sqrtN = sqrtr_abs(utor(N,prec));
7632 14 : tau = mulcxmI(gmul(tau, sqrtN));
7633 14 : wtau = mulcxmI(gmul(wtau, sqrtN));
7634 14 : gN = utoipos(N);
7635 14 : L0 = mfthetaancreate(NULL, gN, gk); /* only for thetacost */
7636 14 : N0 = maxss(lfunthetacost(L0,real_i(tau), 0,bitprec, NULL),
7637 : lfunthetacost(L0,real_i(wtau),0,bitprec, NULL));
7638 14 : M = mfcoefs_mf(mf, N0, 1);
7639 14 : va = cgetg(dim+1, t_VEC);
7640 14 : vb = cgetg(dim+1, t_VEC);
7641 105 : for (j = 1; j <= dim; j++)
7642 : {
7643 91 : GEN L, v = vecslice(gel(M,j), 2, N0+1); /* remove a0 */
7644 91 : settyp(v, t_VEC); L = mfthetaancreate(v, gN, gk);
7645 91 : gel(va,j) = lfuntheta(L, tau,0,bitprec);
7646 91 : gel(vb,j) = lfuntheta(L,wtau,0,bitprec);
7647 : }
7648 84 : for (i = 1; i < lF; i++)
7649 : {
7650 70 : GEN z, FE = gel(MF,i);
7651 70 : long l = lg(FE);
7652 70 : z = cgetg(l, t_VEC);
7653 70 : for (j = 1; j < l; j++)
7654 : {
7655 70 : GEN f = gel(FE,j), a = RgV_dotproduct(va,f), b = RgV_dotproduct(vb,f);
7656 70 : GEN la = ground( gdiv(b, gmul(a,coe)) );
7657 70 : if (!gequal(gsqr(la), la2)) pari_err_PREC("mfatkineigenquad");
7658 70 : if (typ(la) == t_INT)
7659 : {
7660 70 : if (j != 1) pari_err_BUG("mfatkineigenquad");
7661 70 : z = const_vec(l-1, la); break;
7662 : }
7663 0 : gel(z,j) = la;
7664 : }
7665 70 : gel(Z,i) = z;
7666 : }
7667 14 : return Z;
7668 : }
7669 :
7670 : static GEN
7671 84 : myusqrt(ulong a, long prec)
7672 : {
7673 84 : if (a == 1UL) return gen_1;
7674 70 : if (uissquareall(a, &a)) return utoipos(a);
7675 49 : return sqrtr_abs(utor(a, prec));
7676 : }
7677 : /* Assume mf is a nontrivial new space, rational primitive character CHIP
7678 : * and (Q,FC) = 1 */
7679 : static GEN
7680 112 : mfatkinmatnewquad(GEN mf, GEN CHIP, long Q, long flag, long PREC)
7681 : {
7682 112 : GEN cM, M, D, MF, den, vE, F = MF_get_newforms(mf);
7683 112 : long i, c, e, prec, bitprec, lF = lg(F), N = MF_get_N(mf), k = MF_get_k(mf);
7684 :
7685 112 : if (Q == 1) return mkvec4(gen_0, matid(MF_get_dim(mf)), gen_1, mf);
7686 112 : den = gel(MF_get_Minv(mf), 2);
7687 112 : bitprec = expi(den) + 64;
7688 112 : if (!flag) bitprec = maxss(bitprec, prec2nbits(PREC));
7689 :
7690 35 : START:
7691 112 : prec = nbits2prec(bitprec);
7692 112 : vE = mfeigenembed(mf, prec);
7693 112 : M = cgetg(lF, t_VEC);
7694 294 : for (i = 1; i < lF; i++) gel(M,i) = RgC_embedall(gel(F,i), gel(vE,i));
7695 112 : if (Q != N)
7696 : {
7697 56 : D = mfatkineigenquad(mf, CHIP, Q, M, bitprec);
7698 56 : c = odd(k)? Q: 1;
7699 : }
7700 : else
7701 : {
7702 56 : D = mffrickeeigen(mf, vE, prec);
7703 56 : c = mfcharmodulus(CHIP); if (odd(k)) c = -Q/c;
7704 : }
7705 112 : D = shallowconcat1(D);
7706 112 : if (vec_isconst(D)) { MF = diagonal_shallow(D); flag = 0; }
7707 : else
7708 : {
7709 63 : M = shallowconcat1(M);
7710 63 : MF = RgM_mul(matmuldiagonal(M,D), ginv(M));
7711 : }
7712 112 : if (!flag) return mkvec4(gen_0, MF, gen_1, mf);
7713 :
7714 21 : if (c > 0)
7715 21 : cM = myusqrt(c, PREC);
7716 : else
7717 : {
7718 0 : MF = imag_i(MF); c = -c;
7719 0 : cM = mkcomplex(gen_0, myusqrt(c,PREC));
7720 : }
7721 21 : if (c != 1) MF = RgM_Rg_mul(MF, myusqrt(c,prec));
7722 21 : MF = grndtoi(RgM_Rg_mul(MF,den), &e);
7723 21 : if (e > -32) { bitprec <<= 1; goto START; }
7724 21 : MF = RgM_Rg_div(MF, den);
7725 21 : if (is_rational_t(typ(cM)) && !isint1(cM))
7726 0 : { MF = RgM_Rg_div(MF, cM); cM = gen_1; }
7727 21 : return mkvec4(gen_0, MF, cM, mf);
7728 : }
7729 :
7730 : /* let CHI mod N, Q || N, return \bar{CHI_Q} * CHI_{N/Q} */
7731 : static GEN
7732 112 : mfcharAL(GEN CHI, long Q)
7733 : {
7734 112 : GEN G = gel(CHI,1), c = gel(CHI,2), cycc, d, P, E, F;
7735 112 : long l = lg(c), N = mfcharmodulus(CHI), i;
7736 112 : if (N == Q) return mfcharconj(CHI);
7737 56 : if (N == 1) return CHI;
7738 42 : CHI = leafcopy(CHI);
7739 42 : gel(CHI,2) = d = leafcopy(c);
7740 42 : F = znstar_get_faN(G);
7741 42 : P = gel(F,1);
7742 42 : E = gel(F,2);
7743 42 : cycc = znstar_get_conreycyc(G);
7744 42 : if (!odd(Q) && equaliu(gel(P,1), 2) && E[1] >= 3)
7745 14 : gel(d,2) = Fp_neg(gel(d,2), gel(cycc,2));
7746 56 : else for (i = 1; i < l; i++)
7747 28 : if (!umodui(Q, gel(P,i))) gel(d,i) = Fp_neg(gel(d,i), gel(cycc,i));
7748 42 : return CHI;
7749 : }
7750 : static long
7751 245 : atkin_get_NQ(long N, long Q, const char *f)
7752 : {
7753 245 : long NQ = N / Q;
7754 245 : if (N % Q) pari_err_DOMAIN(f,"N % Q","!=",gen_0,utoi(Q));
7755 245 : if (ugcd(NQ, Q) > 1) pari_err_DOMAIN(f,"gcd(Q,N/Q)","!=",gen_1,utoi(Q));
7756 245 : return NQ;
7757 : }
7758 :
7759 : /* transform mf to new_NEW if possible */
7760 : static GEN
7761 1589 : MF_set_new(GEN mf)
7762 : {
7763 1589 : GEN vMjd, vj, gk = MF_get_gk(mf);
7764 : long l, j;
7765 1589 : if (MF_get_space(mf) != mf_CUSP
7766 1589 : || typ(gk) != t_INT || itou(gk) == 1) return mf;
7767 182 : vMjd = MFcusp_get_vMjd(mf); l = lg(vMjd);
7768 182 : if (l > 1 && gel(vMjd,1)[1] != MF_get_N(mf)) return mf; /* oldspace != 0 */
7769 175 : mf = shallowcopy(mf);
7770 175 : gel(mf,1) = shallowcopy(gel(mf,1));
7771 175 : MF_set_space(mf, mf_NEW);
7772 175 : vj = cgetg(l, t_VECSMALL);
7773 938 : for (j = 1; j < l; j++) vj[j] = gel(vMjd, j)[2];
7774 175 : gel(mf,4) = vj; return mf;
7775 : }
7776 :
7777 : /* if flag = 1, rationalize, else don't */
7778 : static GEN
7779 224 : mfatkininit_i(GEN mf, long Q, long flag, long prec)
7780 : {
7781 : GEN M, B, C, CHI, CHIAL, G, chi, P, z, g, mfB, s, Mindex, Minv;
7782 224 : long j, l, lim, ord, FC, NQ, cQ, nk, dk, N = MF_get_N(mf);
7783 :
7784 224 : B = MF_get_basis(mf); l = lg(B);
7785 224 : M = cgetg(l, t_MAT); if (l == 1) return mkvec4(gen_0,M,gen_1,mf);
7786 224 : Qtoss(MF_get_gk(mf), &nk,&dk);
7787 224 : Q = labs(Q);
7788 224 : NQ = atkin_get_NQ(N, Q, "mfatkininit");
7789 224 : CHI = MF_get_CHI(mf);
7790 224 : CHI = mfchartoprimitive(CHI, &FC);
7791 224 : ord = mfcharorder(CHI);
7792 224 : mf = MF_set_new(mf);
7793 224 : if (MF_get_space(mf) == mf_NEW && ord <= 2 && NQ % FC == 0 && dk == 1)
7794 112 : return mfatkinmatnewquad(mf, CHI, Q, flag, prec);
7795 : /* now flag != 0 */
7796 112 : G = gel(CHI,1);
7797 112 : chi = gel(CHI,2);
7798 112 : if (Q == N) { g = mkmat22s(0, -1, N, 0); cQ = NQ; } /* Fricke */
7799 : else
7800 : {
7801 28 : GEN F, gQP = utoi(ugcd(Q, FC));
7802 : long t, v;
7803 28 : chi = znchardecompose(G, chi, gQP);
7804 28 : F = znconreyconductor(G, chi, &chi);
7805 28 : G = znstar0(F,1);
7806 28 : (void)cbezout(Q, NQ, &t, &v);
7807 28 : g = mkmat22s(Q*t, 1, -N*v, Q);
7808 28 : cQ = -NQ*v;
7809 : }
7810 112 : C = s = gen_1;
7811 : /* N.B. G,chi are G_Q,chi_Q [primitive] at this point */
7812 112 : if (lg(chi) != 1) C = ginv( znchargauss(G, chi, gen_1, prec2nbits(prec)) );
7813 112 : if (dk == 1)
7814 91 : { if (odd(nk)) s = myusqrt(Q,prec); }
7815 : else
7816 : {
7817 21 : long r = nk >> 1; /* k-1/2 */
7818 21 : s = gpow(utoipos(Q), mkfracss(odd(r)? 1: 3, 4), prec);
7819 21 : if (odd(cQ))
7820 : {
7821 21 : long t = r + ((cQ-1) >> 1);
7822 21 : s = mkcomplex(s, odd(t)? gneg(s): s);
7823 : }
7824 : }
7825 112 : if (!isint1(s)) C = gmul(C, s);
7826 112 : CHIAL = mfcharAL(CHI, Q);
7827 112 : if (dk == 2)
7828 : {
7829 21 : ulong q = odd(Q)? Q << 2: Q, Nq = ulcm(q, mfcharmodulus(CHIAL));
7830 21 : CHIAL = induceN(Nq, CHIAL);
7831 21 : CHIAL = mfcharmul(CHIAL, induce(gel(CHIAL,1), utoipos(q)));
7832 : }
7833 112 : CHIAL = mfchartoprimitive(CHIAL,NULL);
7834 112 : mfB = gequal(CHIAL,CHI)? mf: mfinit_Nndkchi(N,nk,dk,CHIAL,MF_get_space(mf),0);
7835 112 : Mindex = MF_get_Mindex(mfB);
7836 112 : Minv = MF_get_Minv(mfB);
7837 112 : P = z = NULL;
7838 112 : if (ord > 2) { P = mfcharpol(CHI); z = rootsof1u_cx(ord, prec); }
7839 112 : lim = maxss(mfsturm(mfB), mfsturm(mf)) + 1;
7840 567 : for (j = 1; j < l; j++)
7841 : {
7842 455 : GEN v = mfslashexpansion(mf, gel(B,j), g, lim, 0, NULL, prec+EXTRAPREC64);
7843 : long junk;
7844 455 : if (!isint1(C)) v = RgV_Rg_mul(v, C);
7845 455 : v = bestapprnf(v, P, z, prec);
7846 455 : v = vecpermute_partial(v, Mindex, &junk);
7847 455 : v = Minv_RgC_mul(Minv, v); /* cf mftobasis_i */
7848 455 : gel(M, j) = v;
7849 : }
7850 112 : if (is_rational_t(typ(C)) && !gequal1(C)) { M = gdiv(M, C); C = gen_1; }
7851 112 : if (mfB == mf) mfB = gen_0;
7852 112 : return mkvec4(mfB, M, C, mf);
7853 : }
7854 : GEN
7855 98 : mfatkininit(GEN mf, long Q, long prec)
7856 : {
7857 98 : pari_sp av = avma;
7858 98 : mf = checkMF(mf); return gc_GEN(av, mfatkininit_i(mf, Q, 1, prec));
7859 : }
7860 : static void
7861 63 : checkmfa(GEN z)
7862 : {
7863 63 : if (typ(z) != t_VEC || lg(z) != 5 || typ(gel(z,2)) != t_MAT
7864 63 : || !checkMF_i(gel(z,4))
7865 63 : || (!isintzero(gel(z,1)) && !checkMF_i(gel(z,1))))
7866 0 : pari_err_TYPE("mfatkin [please apply mfatkininit()]",z);
7867 63 : }
7868 :
7869 : /* Apply atkin Q to closure F */
7870 : GEN
7871 63 : mfatkin(GEN mfa, GEN F)
7872 : {
7873 63 : pari_sp av = avma;
7874 : GEN z, mfB, MQ, mf;
7875 63 : checkmfa(mfa);
7876 63 : mfB= gel(mfa,1);
7877 63 : MQ = gel(mfa,2);
7878 63 : mf = gel(mfa,4);
7879 63 : if (typ(mfB) == t_INT) mfB = mf;
7880 63 : z = RgM_RgC_mul(MQ, mftobasis_i(mf,F));
7881 63 : return gc_upto(av, mflinear(mfB, z));
7882 : }
7883 :
7884 : GEN
7885 49 : mfatkineigenvalues(GEN mf, long Q, long prec)
7886 : {
7887 49 : pari_sp av = avma;
7888 : GEN vF, L, CHI, M, mfatk, C, MQ, vE, mfB;
7889 : long N, NQ, l, i;
7890 :
7891 49 : mf = checkMF(mf); N = MF_get_N(mf);
7892 49 : vF = MF_get_newforms(mf); l = lg(vF);
7893 : /* N.B. k is integral */
7894 49 : if (l == 1) retgc_const(av, cgetg(1, t_VEC));
7895 49 : L = cgetg(l, t_VEC);
7896 49 : if (Q == 1)
7897 : {
7898 7 : GEN vP = MF_get_fields(mf);
7899 21 : for (i = 1; i < l; i++) gel(L,i) = const_vec(degpol(gel(vP,i)), gen_1);
7900 7 : return L;
7901 : }
7902 42 : vE = mfeigenembed(mf,prec);
7903 42 : if (Q == N) return gc_upto(av, mffrickeeigen(mf, vE, prec));
7904 21 : Q = labs(Q);
7905 21 : NQ = atkin_get_NQ(N, Q, "mfatkineigenvalues"); /* != 1 */
7906 21 : mfatk = mfatkininit(mf, Q, prec);
7907 21 : mfB= gel(mfatk,1); if (typ(mfB) != t_VEC) mfB = mf;
7908 21 : MQ = gel(mfatk,2);
7909 21 : C = gel(mfatk,3);
7910 21 : M = row(mfcoefs_mf(mfB,1,1), 2); /* vec of a_1(b_i) for mfbasis functions */
7911 56 : for (i = 1; i < l; i++)
7912 : {
7913 35 : GEN c = RgV_dotproduct(RgM_RgC_mul(MQ,gel(vF,i)), M); /* C * eigen_i */
7914 35 : gel(L,i) = Rg_embedall_i(c, gel(vE,i));
7915 : }
7916 21 : if (!gequal1(C)) L = gdiv(L, C);
7917 21 : CHI = MF_get_CHI(mf);
7918 21 : if (mfcharorder(CHI) <= 2 && NQ % mfcharconductor(CHI) == 0) L = ground(L);
7919 21 : return gc_GEN(av, L);
7920 : }
7921 :
7922 : /* expand B_d V, keeping same length */
7923 : static GEN
7924 14168 : bdexpand(GEN V, long d)
7925 : {
7926 : GEN W;
7927 : long N, n;
7928 14168 : if (d == 1) return V;
7929 2730 : N = lg(V)-1; W = zerovec(N);
7930 47768 : for (n = 0; n <= (N-1)/d; n++) gel(W, n*d+1) = gel(V, n+1);
7931 2730 : return W;
7932 : }
7933 : /* expand B_d V, increasing length up to lim */
7934 : static GEN
7935 343 : bdexpandall(GEN V, long d, long lim)
7936 : {
7937 : GEN W;
7938 : long N, n;
7939 343 : if (d == 1) return V;
7940 49 : N = lg(V)-1; W = zerovec(lim);
7941 301 : for (n = 0; n <= N-1 && n*d <= lim; n++) gel(W, n*d+1) = gel(V, n+1);
7942 49 : return W;
7943 : }
7944 :
7945 : static void
7946 15491 : parse_vecj(GEN T, GEN *E1, GEN *E2)
7947 : {
7948 15491 : if (lg(T)==3) { *E1 = gel(T,1); *E2 = gel(T,2); }
7949 5600 : else { *E1 = T; *E2 = NULL; }
7950 15491 : }
7951 :
7952 : /* g in M_2(Z) ? */
7953 : static int
7954 3486 : check_M2Z(GEN g)
7955 3486 : { return typ(g) == t_MAT && lg(g) == 3 && lgcols(g) == 3 && RgM_is_ZM(g); }
7956 : /* g in SL_2(Z) ? */
7957 : static int
7958 2058 : check_SL2Z(GEN g) { return check_M2Z(g) && equali1(ZM_det(g)); }
7959 :
7960 : static GEN
7961 9513 : mfcharcxeval(GEN CHI, long n, long prec)
7962 : {
7963 9513 : ulong ord, N = mfcharmodulus(CHI);
7964 : GEN ordg;
7965 9513 : if (N == 1) return gen_1;
7966 3696 : if (ugcd(N, labs(n)) > 1) return gen_0;
7967 3696 : ordg = gmfcharorder(CHI);
7968 3696 : ord = itou(ordg);
7969 3696 : return rootsof1q_cx(znchareval_i(CHI,n,ordg), ord, prec);
7970 : }
7971 :
7972 : static GEN
7973 11039 : RgV_shift(GEN V, GEN gn)
7974 : {
7975 : long i, n, l;
7976 : GEN W;
7977 11039 : if (typ(gn) != t_INT) pari_err_BUG("RgV_shift [n not integral]");
7978 11039 : n = itos(gn);
7979 11039 : if (n < 0) pari_err_BUG("RgV_shift [n negative]");
7980 11039 : if (!n) return V;
7981 112 : W = cgetg_copy(V, &l); if (n > l-1) n = l-1;
7982 308 : for (i=1; i <= n; i++) gel(W,i) = gen_0;
7983 4900 : for ( ; i < l; i++) gel(W,i) = gel(V, i-n);
7984 112 : return W;
7985 : }
7986 : static GEN
7987 19236 : hash_eisengacx(hashtable *H, void *E, long w, GEN ga, long n, long prec)
7988 : {
7989 19236 : ulong h = H->hash(E);
7990 19236 : hashentry *e = hash_search2(H, E, h);
7991 : GEN v;
7992 19236 : if (e) v = (GEN)e->val;
7993 : else
7994 : {
7995 12971 : v = mfeisensteingacx((GEN)E, w, ga, n, prec);
7996 12971 : hash_insert2(H, E, (void*)v, h);
7997 : }
7998 19236 : return v;
7999 : }
8000 : static GEN
8001 11039 : vecj_expand(GEN B, hashtable *H, long w, GEN ga, long n, long prec)
8002 : {
8003 : GEN E1, E2, v;
8004 11039 : parse_vecj(B, &E1, &E2);
8005 11039 : v = hash_eisengacx(H, (void*)E1, w, ga, n, prec);
8006 11039 : if (E2)
8007 : {
8008 8141 : GEN u = hash_eisengacx(H, (void*)E2, w, ga, n, prec);
8009 8141 : GEN a = gadd(gel(v,1), gel(u,1));
8010 8141 : GEN b = RgV_mul_RgXn(gel(v,2), gel(u,2));
8011 8141 : v = mkvec2(a,b);
8012 : }
8013 11039 : return v;
8014 : }
8015 : static GEN
8016 1288 : shift_M(GEN M, GEN Valpha, long w)
8017 : {
8018 1288 : long i, l = lg(Valpha);
8019 1288 : GEN almin = vecmin(Valpha);
8020 12327 : for (i = 1; i < l; i++)
8021 : {
8022 11039 : GEN alpha = gel(Valpha, i), gsh = gmulsg(w, gsub(alpha,almin));
8023 11039 : gel(M,i) = RgV_shift(gel(M,i), gsh);
8024 : }
8025 1288 : return almin;
8026 : }
8027 : static GEN mfeisensteinspaceinit(GEN NK);
8028 : #if 0
8029 : /* ga in M_2^+(Z)), n >= 0 */
8030 : static GEN
8031 : mfgaexpansion_init(GEN mf, GEN ga, long n, long prec)
8032 : {
8033 : GEN M, Mvecj, vecj, almin, Valpha;
8034 : long i, w, l, N = MF_get_N(mf), c = itos(gcoeff(ga,2,1));
8035 : hashtable *H;
8036 :
8037 : if (c % N == 0)
8038 : { /* ga in G_0(N), trivial case; w = 1 */
8039 : GEN chid = mfcharcxeval(MF_get_CHI(mf), itos(gcoeff(ga,2,2)), prec);
8040 : return mkvec2(chid, utoi(n));
8041 : }
8042 :
8043 : Mvecj = obj_checkbuild(mf, MF_EISENSPACE, &mfeisensteinspaceinit);
8044 : if (lg(Mvecj) < 5) pari_err_IMPL("mfgaexpansion_init in this case");
8045 : w = mfcuspcanon_width(N, c);
8046 : vecj = gel(Mvecj, 3);
8047 : l = lg(vecj);
8048 : M = cgetg(l, t_VEC);
8049 : Valpha = cgetg(l, t_VEC);
8050 : H = hash_create_GEN(l, 1);
8051 : for (i = 1; i < l; i++)
8052 : {
8053 : GEN v = vecj_expand(gel(vecj,i), H, w, ga, n, prec);
8054 : gel(Valpha,i) = gel(v,1);
8055 : gel(M,i) = gel(v,2);
8056 : }
8057 : almin = shift_M(M, Valpha, w);
8058 : return mkvec3(almin, utoi(w), M);
8059 : }
8060 : /* half-integer weight not supported; vF = [F,eisendec(F)].
8061 : * Minit = mfgaexpansion_init(mf, ga, n, prec) */
8062 : static GEN
8063 : mfgaexpansion_with_init(GEN Minit, GEN vF)
8064 : {
8065 : GEN v;
8066 : if (lg(Minit) == 3)
8067 : { /* ga in G_0(N) */
8068 : GEN chid = gel(Minit,1), gn = gel(Minit,2);
8069 : v = mfcoefs_i(gel(vF,1), itou(gn), 1);
8070 : v = mkvec3(gen_0, gen_1, RgV_Rg_mul(v,chid));
8071 : }
8072 : else
8073 : {
8074 : GEN V = RgM_RgC_mul(gel(Minit,3), gel(vF,2));
8075 : v = mkvec3(gel(Minit,1), gel(Minit,2), V);
8076 : }
8077 : return v;
8078 : }
8079 : #endif
8080 :
8081 : /* B = mfeisensteindec(F) already embedded, ga in M_2^+(Z)), n >= 0 */
8082 : static GEN
8083 1288 : mfgaexpansion_i(GEN mf, GEN B0, GEN ga, long n, long prec)
8084 : {
8085 1288 : GEN M, Mvecj, vecj, almin, Valpha, B, E = NULL;
8086 1288 : long i, j, w, nw, l, N = MF_get_N(mf), bit = prec2nbits(prec) / 2;
8087 : hashtable *H;
8088 :
8089 1288 : Mvecj = obj_check(mf, MF_EISENSPACE);
8090 1288 : if (lg(Mvecj) < 5) { E = gel(Mvecj, 2); Mvecj = gel(Mvecj, 1); }
8091 1288 : vecj = gel(Mvecj, 3);
8092 1288 : l = lg(vecj);
8093 1288 : B = cgetg(l, t_COL);
8094 1288 : M = cgetg(l, t_VEC);
8095 1288 : Valpha = cgetg(l, t_VEC);
8096 1288 : w = mfZC_width(N, gel(ga,1));
8097 1288 : nw = E ? n + w : n;
8098 1288 : H = hash_create_GEN(l, 1);
8099 15673 : for (i = j = 1; i < l; i++)
8100 : {
8101 : GEN v;
8102 14385 : if (gequal0(gel(B0,i))) continue;
8103 11039 : v = vecj_expand(gel(vecj,i), H, w, ga, nw, prec);
8104 11039 : gel(B,j) = gel(B0,i);
8105 11039 : gel(Valpha,j) = gel(v,1);
8106 11039 : gel(M,j) = gel(v,2); j++;
8107 : }
8108 1288 : setlg(Valpha, j);
8109 1288 : setlg(B, j);
8110 1288 : setlg(M, j); l = j;
8111 1288 : if (l == 1) return mkvec3(gen_0, utoi(w), zerovec(n+1));
8112 1288 : almin = shift_M(M, Valpha, w);
8113 1288 : B = RgM_RgC_mul(M, B); l = lg(B);
8114 158347 : for (i = 1; i < l; i++)
8115 157059 : if (gexpo(gel(B,i)) < -bit) gel(B,i) = gen_0;
8116 1288 : settyp(B, t_VEC);
8117 1288 : if (E)
8118 : {
8119 : GEN v, e;
8120 56 : long ell = 0, vB, ve;
8121 126 : for (i = 1; i < l; i++)
8122 126 : if (!gequal0(gel(B,i))) break;
8123 56 : vB = i-1;
8124 56 : v = hash_eisengacx(H, (void*)E, w, ga, n + vB, prec);
8125 56 : e = gel(v,2); l = lg(e);
8126 56 : for (i = 1; i < l; i++)
8127 56 : if (!gequal0(gel(e,i))) break;
8128 56 : ve = i-1;
8129 56 : almin = gsub(almin, gel(v,1));
8130 56 : if (gsigne(almin) < 0)
8131 : {
8132 0 : GEN gell = gceil(gmulsg(-w, almin));
8133 0 : ell = itos(gell);
8134 0 : almin = gadd(almin, gdivgu(gell, w));
8135 0 : if (nw < ell) pari_err_IMPL("alpha < 0 in mfgaexpansion");
8136 : }
8137 56 : if (ve) { ell += ve; e = vecslice(e, ve+1, l-1); }
8138 56 : B = vecslice(B, ell + 1, minss(n + ell + 1, lg(B)-1));
8139 56 : B = RgV_div_RgXn(B, e);
8140 : }
8141 1288 : return mkvec3(almin, utoi(w), B);
8142 : }
8143 :
8144 : /* Theta multiplier: assume 4 | C, (C,D)=1 */
8145 : static GEN
8146 343 : mfthetamultiplier(GEN C, GEN D)
8147 : {
8148 343 : long s = kronecker(C, D);
8149 343 : if (Mod4(D) == 1) return s > 0 ? gen_1: gen_m1;
8150 84 : return s > 0? powIs(3): gen_I();
8151 : }
8152 : /* theta | [*,*;C,D] defined over Q(i) [else over Q] */
8153 : static int
8154 56 : mfthetaI(long C, long D) { return odd(C) || (D & 3) == 3; }
8155 : /* (theta | M) [0..n], assume (C,D) = 1 */
8156 : static GEN
8157 343 : mfthetaexpansion(GEN M, long n)
8158 : {
8159 343 : GEN w, s, al, sla, E, V = zerovec(n+1), C = gcoeff(M,2,1), D = gcoeff(M,2,2);
8160 343 : long lim, la, f, C4 = Mod4(C);
8161 343 : switch (C4)
8162 : {
8163 70 : case 0: al = gen_0; w = gen_1;
8164 70 : s = mfthetamultiplier(C,D);
8165 70 : lim = usqrt(n); gel(V, 1) = s;
8166 70 : s = gmul2n(s, 1);
8167 756 : for (f = 1; f <= lim; f++) gel(V, f*f + 1) = s;
8168 70 : break;
8169 105 : case 2: al = uutoQ(1,4); w = gen_1;
8170 105 : E = subii(C, shifti(D,1)); /* (E, D) = 1 */
8171 105 : s = gmul2n(mfthetamultiplier(E, D), 1);
8172 105 : if ((!signe(E) && equalim1(D)) || (signe(E) > 0 && signe(C) < 0))
8173 14 : s = gneg(s);
8174 105 : lim = (usqrt(n << 2) - 1) >> 1;
8175 966 : for (f = 0; f <= lim; f++) gel(V, f*(f+1) + 1) = s;
8176 105 : break;
8177 168 : default: al = gen_0; w = utoipos(4);
8178 168 : la = (-Mod4(D)*C4) & 3L;
8179 168 : E = negi(addii(D, mului(la, C)));
8180 168 : s = mfthetamultiplier(E, C); /* (E,C) = 1 */
8181 168 : if (signe(C) < 0 && signe(E) >= 0) s = gneg(s);
8182 168 : s = gsub(s, mulcxI(s));
8183 168 : sla = gmul(s, powIs(-la));
8184 168 : lim = usqrt(n); gel(V, 1) = gmul2n(s, -1);
8185 1708 : for (f = 1; f <= lim; f++) gel(V, f*f + 1) = odd(f) ? sla : s;
8186 168 : break;
8187 : }
8188 343 : return mkvec3(al, w, V);
8189 : }
8190 :
8191 : /* F 1/2 integral weight */
8192 : static GEN
8193 343 : mf2gaexpansion(GEN mf2, GEN F, GEN ga, long n, long prec)
8194 : {
8195 343 : GEN FT = mfmultheta(F), mf = obj_checkbuild(mf2, MF_MF2INIT, &mf2init);
8196 343 : GEN res, V1, Tres, V2, al, V, gsh, C = gcoeff(ga,2,1);
8197 343 : long w2, N = MF_get_N(mf), w = mfcuspcanon_width(N, umodiu(C,N));
8198 343 : long ext = (Mod4(C) != 2)? 0: (w+3) >> 2;
8199 343 : long prec2 = prec + nbits2extraprec((long)M_PI/(2*M_LN2)*sqrt(n + ext));
8200 343 : res = mfgaexpansion(mf, FT, ga, n + ext, prec2);
8201 343 : Tres = mfthetaexpansion(ga, n + ext);
8202 343 : V1 = gel(res,3);
8203 343 : V2 = gel(Tres,3);
8204 343 : al = gsub(gel(res,1), gel(Tres,1));
8205 343 : w2 = itos(gel(Tres,2));
8206 343 : if (w != itos(gel(res,2)) || w % w2)
8207 0 : pari_err_BUG("mf2gaexpansion [incorrect w2 or w]");
8208 343 : if (w2 != w) V2 = bdexpand(V2, w/w2);
8209 343 : V = RgV_div_RgXn(V1, V2);
8210 343 : gsh = gfloor(gmulsg(w, al));
8211 343 : if (!gequal0(gsh))
8212 : {
8213 35 : al = gsub(al, gdivgu(gsh, w));
8214 35 : if (gsigne(gsh) > 0)
8215 : {
8216 0 : V = RgV_shift(V, gsh);
8217 0 : V = vecslice(V, 1, n + 1);
8218 : }
8219 : else
8220 : {
8221 35 : long sh = -itos(gsh), i;
8222 35 : if (sh > ext) pari_err_BUG("mf2gaexpansion [incorrect sh]");
8223 154 : for (i = 1; i <= sh; i++)
8224 119 : if (!gequal0(gel(V,i))) pari_err_BUG("mf2gaexpansion [sh too large]");
8225 35 : V = vecslice(V, sh+1, n + sh+1);
8226 : }
8227 : }
8228 343 : obj_free(mf); return mkvec3(al, stoi(w), gprec_wtrunc(V, prec));
8229 : }
8230 :
8231 : static GEN
8232 77 : mfgaexpansionatkin(GEN mf, GEN F, GEN C, GEN D, long Q, long n, long prec)
8233 : {
8234 77 : GEN mfa = mfatkininit_i(mf, Q, 0, prec), MQ = gel(mfa,2);
8235 77 : long i, FC, k = MF_get_k(mf);
8236 77 : GEN x, v, V, z, s, CHI = mfchartoprimitive(MF_get_CHI(mf), &FC);
8237 :
8238 : /* V = mfcoefs(F | w_Q, n), can't use mfatkin because MQ nonrational */
8239 77 : V = RgM_RgC_mul(mfcoefs_mf(mf,n,1), RgM_RgC_mul(MQ, mftobasis_i(mf,F)));
8240 77 : (void)bezout(utoipos(Q), C, &x, &v);
8241 77 : s = mfchareval(CHI, (umodiu(x, FC) * umodiu(D, FC)) % FC);
8242 77 : s = gdiv(s, gpow(utoipos(Q), uutoQ(k,2), prec));
8243 77 : V = RgV_Rg_mul(V, s);
8244 77 : z = rootsof1powinit(umodiu(D,Q)*umodiu(v,Q) % Q, Q, prec);
8245 11613 : for (i = 1; i <= n+1; i++) gel(V,i) = gmul(gel(V,i), rootsof1pow(z, i-1));
8246 77 : return mkvec3(gen_0, utoipos(Q), V);
8247 : }
8248 :
8249 : static long
8250 70 : inveis_extraprec(long N, GEN ga, GEN Mvecj, long n)
8251 : {
8252 70 : long e, w = mfZC_width(N, gel(ga,1));
8253 70 : GEN f, E = gel(Mvecj,2), v = mfeisensteingacx(E, w, ga, n, DEFAULTPREC);
8254 70 : v = gel(v,2);
8255 70 : f = RgV_to_RgX(v,0); n -= RgX_valrem(f, &f);
8256 70 : e = gexpo(RgXn_inv(f, n+1));
8257 70 : return (e > 0)? nbits2extraprec(e): 0;
8258 : }
8259 : /* allow F of the form [F, mf_eisendec(F)]~ */
8260 : static GEN
8261 2051 : mfgaexpansion(GEN mf, GEN F, GEN ga, long n, long prec)
8262 : {
8263 2051 : GEN v, EF = NULL, res, Mvecj, c, d;
8264 : long precnew, N;
8265 :
8266 2051 : if (n < 0) pari_err_DOMAIN("mfgaexpansion", "n", "<", gen_0, stoi(n));
8267 2051 : if (typ(F) == t_COL && lg(F) == 3) { EF = gel(F,2); F = gel(F,1); }
8268 2051 : if (!checkmf_i(F)) pari_err_TYPE("mfgaexpansion", F);
8269 2051 : if (!check_SL2Z(ga)) pari_err_TYPE("mfgaexpansion",ga);
8270 2051 : if (typ(mf_get_gk(F)) != t_INT) return mf2gaexpansion(mf, F, ga, n, prec);
8271 1708 : c = gcoeff(ga,2,1);
8272 1708 : d = gcoeff(ga,2,2);
8273 1708 : N = MF_get_N(mf);
8274 1708 : if (!umodiu(c, mf_get_N(F)))
8275 : { /* trivial case: ga in Gamma_0(N) */
8276 343 : long w = mfcuspcanon_width(N, umodiu(c,N));
8277 343 : GEN CHI = mf_get_CHI(F);
8278 343 : GEN chid = mfcharcxeval(CHI, umodiu(d,mfcharmodulus(CHI)), prec);
8279 343 : v = mfcoefs_i(F, n/w, 1); if (!isint1(chid)) v = RgV_Rg_mul(v,chid);
8280 343 : return mkvec3(gen_0, stoi(w), bdexpandall(v,w,n+1));
8281 : }
8282 1365 : mf = MF_set_new(mf);
8283 1365 : if (MF_get_space(mf) == mf_NEW)
8284 : {
8285 483 : long cN = umodiu(c,N), g = ugcd(cN,N), Q = N/g;
8286 483 : GEN CHI = MF_get_CHI(mf);
8287 483 : if (ugcd(cN, Q)==1 && mfcharorder(CHI) <= 2
8288 231 : && g % mfcharconductor(CHI) == 0
8289 119 : && degpol(mf_get_field(F)) == 1)
8290 77 : return mfgaexpansionatkin(mf, F, c, d, Q, n, prec);
8291 : }
8292 1288 : Mvecj = obj_checkbuild(mf, MF_EISENSPACE, &mfeisensteinspaceinit);
8293 1288 : precnew = prec;
8294 1288 : if (lg(Mvecj) < 5) precnew += inveis_extraprec(N, ga, Mvecj, n);
8295 1288 : if (!EF) EF = mf_eisendec(mf, F, precnew);
8296 1288 : res = mfgaexpansion_i(mf, EF, ga, n, precnew);
8297 1288 : return precnew == prec ? res : gprec_wtrunc(res, prec);
8298 : }
8299 :
8300 : /* parity = -1 or +1 */
8301 : static GEN
8302 217 : findd(long N, long parity)
8303 : {
8304 217 : GEN L, D = mydivisorsu(N);
8305 217 : long i, j, l = lg(D);
8306 217 : L = cgetg(l, t_VEC);
8307 1218 : for (i = j = 1; i < l; i++)
8308 : {
8309 1001 : long d = D[i];
8310 1001 : if (parity == -1) d = -d;
8311 1001 : if (sisfundamental(d)) gel(L,j++) = stoi(d);
8312 : }
8313 217 : setlg(L,j); return L;
8314 : }
8315 : /* does ND contain a divisor of N ? */
8316 : static int
8317 413 : seenD(long N, GEN ND)
8318 : {
8319 413 : long j, l = lg(ND);
8320 427 : for (j = 1; j < l; j++)
8321 14 : if (N % ND[j] == 0) return 1;
8322 413 : return 0;
8323 : }
8324 : static GEN
8325 63 : search_levels(GEN vN, const char *f)
8326 : {
8327 63 : switch(typ(vN))
8328 : {
8329 28 : case t_INT: vN = mkvecsmall(itos(vN)); break;
8330 35 : case t_VEC: case t_COL: vN = ZV_to_zv(vN); break;
8331 0 : case t_VECSMALL: vN = leafcopy(vN); break;
8332 0 : default: pari_err_TYPE(f, vN);
8333 : }
8334 63 : vecsmall_sort(vN); return vN;
8335 : }
8336 : GEN
8337 28 : mfsearch(GEN NK, GEN V, long space)
8338 : {
8339 28 : pari_sp av = avma;
8340 : GEN F, gk, NbyD, vN;
8341 : long n, nk, dk, parity, nV, i, lvN;
8342 :
8343 28 : if (typ(NK) != t_VEC || lg(NK) != 3) pari_err_TYPE("mfsearch", NK);
8344 28 : gk = gel(NK,2);
8345 28 : if (typ(gmul2n(gk, 1)) != t_INT) pari_err_TYPE("mfsearch [k]", gk);
8346 28 : switch(typ(V))
8347 : {
8348 28 : case t_VEC: V = shallowtrans(V);
8349 28 : case t_COL: break;
8350 0 : default: pari_err_TYPE("mfsearch [V]", V);
8351 : }
8352 28 : vN = search_levels(gel(NK,1), "mfsearch [N]");
8353 28 : if (gequal0(V)) { set_avma(av); retmkvec(mftrivial()); }
8354 14 : lvN = lg(vN);
8355 :
8356 14 : Qtoss(gk, &nk,&dk);
8357 14 : parity = (dk == 1 && odd(nk)) ? -1 : 1;
8358 14 : nV = lg(V)-2;
8359 14 : F = cgetg(1, t_VEC);
8360 14 : NbyD = const_vec(vN[lvN-1], cgetg(1,t_VECSMALL));
8361 231 : for (n = 1; n < lvN; n++)
8362 : {
8363 217 : long N = vN[n];
8364 : GEN L;
8365 217 : if (N <= 0 || (dk == 2 && (N & 3))) continue;
8366 217 : L = findd(N, parity);
8367 630 : for (i = 1; i < lg(L); i++)
8368 : {
8369 413 : GEN mf, M, CO, gD = gel(L,i);
8370 413 : GEN *ND = (GEN*)NbyD + itou(gD); /* points to NbyD[|D|] */
8371 :
8372 413 : if (seenD(N, *ND)) continue;
8373 413 : mf = mfinit_Nndkchi(N, nk, dk, get_mfchar(gD), space, 1);
8374 413 : M = mfcoefs_mf(mf, nV, 1);
8375 413 : CO = inverseimage(M, V); if (lg(CO) == 1) continue;
8376 :
8377 42 : F = vec_append(F, mflinear(mf,CO));
8378 42 : *ND = vecsmall_append(*ND, N); /* add to NbyD[|D|] */
8379 : }
8380 : }
8381 14 : return gc_GEN(av, F);
8382 : }
8383 :
8384 : static GEN
8385 889 : search_from_split(GEN mf, GEN vap, GEN vlp)
8386 : {
8387 889 : pari_sp av = avma;
8388 889 : long lvlp = lg(vlp), j, jv, l1;
8389 889 : GEN v, NK, S1, S, M = NULL;
8390 :
8391 889 : S1 = gel(split_i(mf, 1, 0), 1); /* rational newforms */
8392 889 : l1 = lg(S1);
8393 889 : if (l1 == 1) return gc_NULL(av);
8394 455 : v = cgetg(l1, t_VEC);
8395 455 : S = MF_get_S(mf);
8396 455 : NK = mf_get_NK(gel(S,1));
8397 455 : if (lvlp > 1) M = rowpermute(mfcoefs_mf(mf, vlp[lvlp-1], 1), vlp);
8398 980 : for (j = jv = 1; j < l1; j++)
8399 : {
8400 525 : GEN vF = gel(S1,j);
8401 : long t;
8402 658 : for (t = lvlp-1; t > 0; t--)
8403 : { /* lhs = vlp[j]-th coefficient of eigenform */
8404 595 : GEN rhs = gel(vap,t), lhs = RgMrow_RgC_mul(M, vF, t);
8405 595 : if (!gequal(lhs, rhs)) break;
8406 : }
8407 525 : if (!t) gel(v,jv++) = mflinear_i(NK,S,vF);
8408 : }
8409 455 : if (jv == 1) return gc_NULL(av);
8410 63 : setlg(v,jv); return v;
8411 : }
8412 : GEN
8413 35 : mfeigensearch(GEN NK, GEN AP)
8414 : {
8415 35 : pari_sp av = avma;
8416 35 : GEN k, vN, vap, vlp, vres = cgetg(1, t_VEC), D;
8417 : long n, lvN, i, l, even;
8418 :
8419 35 : if (!AP) l = 1;
8420 : else
8421 : {
8422 28 : l = lg(AP);
8423 28 : if (typ(AP) != t_VEC) pari_err_TYPE("mfeigensearch",AP);
8424 : }
8425 35 : vap = cgetg(l, t_VEC);
8426 35 : vlp = cgetg(l, t_VECSMALL);
8427 35 : if (l > 1)
8428 : {
8429 28 : GEN perm = indexvecsort(AP, mkvecsmall(1));
8430 77 : for (i = 1; i < l; i++)
8431 : {
8432 49 : GEN v = gel(AP,perm[i]), gp, ap;
8433 49 : if (typ(v) != t_VEC || lg(v) != 3) pari_err_TYPE("mfeigensearch", AP);
8434 49 : gp = gel(v,1);
8435 49 : ap = gel(v,2);
8436 49 : if (typ(gp) != t_INT || (typ(ap) != t_INT && typ(ap) != t_INTMOD))
8437 0 : pari_err_TYPE("mfeigensearch", AP);
8438 49 : gel(vap,i) = ap;
8439 49 : vlp[i] = itos(gp)+1; if (vlp[i] < 0) pari_err_TYPE("mfeigensearch", AP);
8440 : }
8441 : }
8442 35 : l = lg(NK);
8443 35 : if (typ(NK) != t_VEC || l != 3) pari_err_TYPE("mfeigensearch",NK);
8444 35 : k = gel(NK,2);
8445 35 : vN = search_levels(gel(NK,1), "mfeigensearch [N]");
8446 35 : lvN = lg(vN);
8447 35 : vecsmall_sort(vlp);
8448 35 : even = !mpodd(k);
8449 980 : for (n = 1; n < lvN; n++)
8450 : {
8451 945 : pari_sp av2 = avma;
8452 : GEN mf, L;
8453 945 : long N = vN[n];
8454 945 : if (even) D = gen_1;
8455 : else
8456 : {
8457 112 : long r = (N&3L);
8458 112 : if (r == 1 || r == 2) continue;
8459 56 : D = stoi( corediscs(-N, NULL) ); /* < 0 */
8460 : }
8461 889 : mf = mfinit_i(mkvec3(utoipos(N), k, D), mf_NEW);
8462 889 : L = search_from_split(mf, vap, vlp);
8463 889 : if (L) vres = shallowconcat(vres, L); else set_avma(av2);
8464 : }
8465 35 : return gc_GEN(av, vres);
8466 : }
8467 :
8468 : /* tf_{N,k}(n) */
8469 : static GEN
8470 4646243 : mfnewtracecache(long N, long k, long n, cachenew_t *cache)
8471 : {
8472 4646243 : GEN C = NULL, S;
8473 : long lcache;
8474 4646243 : if (!n) return gen_0;
8475 4501854 : S = gel(cache->vnew,N);
8476 4501854 : lcache = lg(S);
8477 4501854 : if (n < lcache) C = gel(S, n);
8478 4501854 : if (C) cache->newHIT++;
8479 2673683 : else C = mfnewtrace_i(N,k,n,cache);
8480 4501854 : cache->newTOTAL++;
8481 4501854 : if (n < lcache) gel(S,n) = C;
8482 4501854 : return C;
8483 : }
8484 :
8485 : static long
8486 1400 : mfdim_Nkchi(long N, long k, GEN CHI, long space)
8487 : {
8488 1400 : if (k < 0 || badchar(N,k,CHI)) return 0;
8489 1099 : if (k == 0)
8490 35 : return mfcharistrivial(CHI) && !space_is_cusp(space)? 1: 0;
8491 1064 : switch(space)
8492 : {
8493 245 : case mf_NEW: return mfnewdim(N,k,CHI);
8494 203 : case mf_CUSP:return mfcuspdim(N,k,CHI);
8495 168 : case mf_OLD: return mfolddim(N,k,CHI);
8496 217 : case mf_FULL:return mffulldim(N,k,CHI);
8497 231 : case mf_EISEN: return mfeisensteindim(N,k,CHI);
8498 0 : default: pari_err_FLAG("mfdim");
8499 : }
8500 : return 0;/*LCOV_EXCL_LINE*/
8501 : }
8502 : static long
8503 2114 : mf1dimsum(long N, long space)
8504 : {
8505 2114 : switch(space)
8506 : {
8507 1050 : case mf_NEW: return mf1newdimsum(N);
8508 1057 : case mf_CUSP: return mf1cuspdimsum(N);
8509 7 : case mf_OLD: return mf1olddimsum(N);
8510 : }
8511 0 : pari_err_FLAG("mfdim");
8512 : return 0; /*LCOV_EXCL_LINE*/
8513 : }
8514 : /* mfdim for k = nk/dk */
8515 : static long
8516 44744 : mfdim_Nndkchi(long N, long nk, long dk, GEN CHI, long space)
8517 43463 : { return (dk == 2)? mf2dim_Nkchi(N, nk >> 1, CHI, space)
8518 88186 : : mfdim_Nkchi(N, nk, CHI, space); }
8519 : /* FIXME: use direct dim Gamma1(N) formula, don't compute individual spaces */
8520 : static long
8521 252 : mfkdimsum(long N, long k, long dk, long space)
8522 : {
8523 252 : GEN w = mfchars(N, k, dk, NULL);
8524 252 : long i, j, D = 0, l = lg(w);
8525 1239 : for (i = j = 1; i < l; i++)
8526 : {
8527 987 : GEN CHI = gel(w,i);
8528 987 : long d = mfdim_Nndkchi(N,k,dk,CHI,space);
8529 987 : if (d) D += d * myeulerphiu(mfcharorder(CHI));
8530 : }
8531 252 : return D;
8532 : }
8533 : static GEN
8534 105 : mf1dims(long N, GEN vCHI, long space)
8535 : {
8536 105 : GEN D = NULL;
8537 105 : switch(space)
8538 : {
8539 56 : case mf_NEW: D = mf1newdimall(N, vCHI); break;
8540 21 : case mf_CUSP:D = mf1cuspdimall(N, vCHI); break;
8541 28 : case mf_OLD: D = mf1olddimall(N, vCHI); break;
8542 0 : default: pari_err_FLAG("mfdim");
8543 : }
8544 105 : return D;
8545 : }
8546 : static GEN
8547 2961 : mfkdims(long N, long k, long dk, GEN vCHI, long space)
8548 : {
8549 2961 : GEN D, w = mfchars(N, k, dk, vCHI);
8550 2961 : long i, j, l = lg(w);
8551 2961 : D = cgetg(l, t_VEC);
8552 46592 : for (i = j = 1; i < l; i++)
8553 : {
8554 43631 : GEN CHI = gel(w,i);
8555 43631 : long d = mfdim_Nndkchi(N,k,dk,CHI,space);
8556 43631 : if (vCHI)
8557 574 : gel(D, j++) = mkvec2s(d, 0);
8558 43057 : else if (d)
8559 2520 : gel(D, j++) = fmt_dim(CHI, d, 0);
8560 : }
8561 2961 : setlg(D,j); return D;
8562 : }
8563 : GEN
8564 5719 : mfdim(GEN NK, long space)
8565 : {
8566 5719 : pari_sp av = avma;
8567 : long N, k, dk, joker;
8568 : GEN CHI, mf;
8569 5719 : if ((mf = checkMF_i(NK))) return utoi(MF_get_dim(mf));
8570 5586 : checkNK2(NK, &N, &k, &dk, &CHI, 2);
8571 5586 : if (!CHI) joker = 1;
8572 : else
8573 2611 : switch(typ(CHI))
8574 : {
8575 2373 : case t_INT: joker = 2; break;
8576 112 : case t_COL: joker = 3; break;
8577 126 : default: joker = 0; break;
8578 : }
8579 5586 : if (joker)
8580 : {
8581 : long d;
8582 : GEN D;
8583 5460 : if (k < 0) switch(joker)
8584 : {
8585 0 : case 1: return cgetg(1,t_VEC);
8586 7 : case 2: return gen_0;
8587 0 : case 3: return mfdim0all(CHI);
8588 : }
8589 5453 : if (k == 0)
8590 : {
8591 28 : if (space_is_cusp(space)) switch(joker)
8592 : {
8593 7 : case 1: return cgetg(1,t_VEC);
8594 0 : case 2: return gen_0;
8595 7 : case 3: return mfdim0all(CHI);
8596 : }
8597 14 : switch(joker)
8598 : {
8599 : long i, l;
8600 7 : case 1: retmkvec(fmt_dim(mfchartrivial(),0,0));
8601 0 : case 2: return gen_1;
8602 7 : case 3: l = lg(CHI); D = cgetg(l,t_VEC);
8603 35 : for (i = 1; i < l; i++)
8604 : {
8605 28 : long t = mfcharistrivial(gel(CHI,i));
8606 28 : gel(D,i) = mkvec2(t? gen_1: gen_0, gen_0);
8607 : }
8608 7 : return D;
8609 : }
8610 : }
8611 5425 : if (dk == 1 && k == 1 && space != mf_EISEN)
8612 105 : {
8613 2219 : long fix = 0, space0 = space;
8614 2219 : if (space == mf_FULL) space = mf_CUSP; /* remove Eisenstein part */
8615 2219 : if (joker == 2)
8616 : {
8617 2114 : d = mf1dimsum(N, space);
8618 2114 : if (space0 == mf_FULL) d += mfkdimsum(N,k,dk,mf_EISEN);/*add it back*/
8619 2114 : return gc_utoi(av, d);
8620 : }
8621 : /* must initialize explicitly: trivial spaces for E_k/S_k differ */
8622 105 : if (space0 == mf_FULL)
8623 : {
8624 7 : if (!CHI) fix = 1; /* must remove 0 spaces */
8625 7 : CHI = mfchars(N, k, dk, CHI);
8626 : }
8627 105 : D = mf1dims(N, CHI, space);
8628 105 : if (space0 == mf_FULL)
8629 : {
8630 7 : GEN D2 = mfkdims(N, k, dk, CHI, mf_EISEN);
8631 7 : D = merge_dims(D, D2, fix? CHI: NULL);
8632 : }
8633 : }
8634 : else
8635 : {
8636 3206 : if (joker==2) { d = mfkdimsum(N,k,dk,space); return gc_utoi(av,d); }
8637 2954 : D = mfkdims(N, k, dk, CHI, space);
8638 : }
8639 3059 : if (!CHI) return gc_upto(av, vecsort(D, mkvecsmall(1)));
8640 105 : return gc_GEN(av, D);
8641 : }
8642 126 : return utoi( mfdim_Nndkchi(N, k, dk, CHI, space) );
8643 : }
8644 :
8645 : GEN
8646 371 : mfbasis(GEN NK, long space)
8647 : {
8648 371 : pari_sp av = avma;
8649 : long N, k, dk;
8650 : GEN mf, CHI;
8651 371 : if ((mf = checkMF_i(NK))) return gconcat(gel(mf,2), gel(mf,3));
8652 14 : checkNK2(NK, &N, &k, &dk, &CHI, 0);
8653 14 : if (dk == 2) return gc_GEN(av, mf2basis(N, k>>1, CHI, NULL, space));
8654 14 : mf = mfinit_Nkchi(N, k, CHI, space, 1);
8655 14 : return gc_GEN(av, MF_get_basis(mf));
8656 : }
8657 :
8658 : static GEN
8659 49 : deg1ser_shallow(GEN a1, GEN a0, long v, long e)
8660 49 : { return RgX_to_ser(deg1pol_shallow(a1, a0, v), e+2); }
8661 : /* r / x + O(1) */
8662 : static GEN
8663 49 : simple_pole(GEN r)
8664 : {
8665 49 : GEN S = deg1ser_shallow(gen_0, r, 0, 1);
8666 49 : setvalser(S, -1); return S;
8667 : }
8668 :
8669 : /* F form, E embedding; mfa = mfatkininit or root number (eigenform case) */
8670 : static GEN
8671 175 : mflfuncreate(GEN mfa, GEN F, GEN E, GEN N, GEN gk)
8672 : {
8673 175 : GEN LF = cgetg(8,t_VEC), polar = cgetg(1,t_COL), eps;
8674 175 : long k = itou(gk);
8675 175 : gel(LF,1) = lfuntag(t_LFUN_MFCLOS, mkvec3(F,E,gen_1));
8676 175 : if (typ(mfa) != t_VEC)
8677 112 : eps = mfa; /* cuspidal eigenform: root number; no poles */
8678 : else
8679 : { /* mfatkininit */
8680 63 : GEN a0, b0, vF, vG, G = NULL;
8681 63 : GEN M = gel(mfa,2), C = gel(mfa,3), mf = gel(mfa,4);
8682 63 : M = gdiv(mfmatembed(E, M), C);
8683 63 : vF = mfvecembed(E, mftobasis_i(mf, F));
8684 63 : vG = RgM_RgC_mul(M, vF);
8685 63 : if (gequal(vF,vG)) eps = gen_1;
8686 49 : else if (gequal(vF,gneg(vG))) eps = gen_m1;
8687 : else
8688 : { /* not self-dual */
8689 42 : eps = NULL;
8690 42 : G = mfatkin(mfa, F);
8691 42 : gel(LF,2) = lfuntag(t_LFUN_MFCLOS, mkvec3(G,E,ginv(C)));
8692 42 : gel(LF,6) = powIs(k);
8693 : }
8694 : /* polar part */
8695 63 : a0 = mfembed(E, mfcoef(F,0));
8696 63 : b0 = eps? gmul(eps,a0): gdiv(mfembed(E, mfcoef(G,0)), C);
8697 63 : if (!gequal0(b0))
8698 : {
8699 28 : b0 = mulcxpowIs(gmul2n(b0,1), k);
8700 28 : polar = vec_append(polar, mkvec2(gk, simple_pole(b0)));
8701 : }
8702 63 : if (!gequal0(a0))
8703 : {
8704 21 : a0 = gneg(gmul2n(a0,1));
8705 21 : polar = vec_append(polar, mkvec2(gen_0, simple_pole(a0)));
8706 : }
8707 : }
8708 175 : if (eps) /* self-dual */
8709 : {
8710 133 : gel(LF,2) = mfcharorder(mf_get_CHI(F)) <= 2? gen_0: gen_1;
8711 133 : gel(LF,6) = mulcxpowIs(eps,k);
8712 : }
8713 175 : gel(LF,3) = mkvec2(gen_0, gen_1);
8714 175 : gel(LF,4) = gk;
8715 175 : gel(LF,5) = N;
8716 175 : if (lg(polar) == 1) setlg(LF,7); else gel(LF,7) = polar;
8717 175 : return LF;
8718 : }
8719 : static GEN
8720 147 : mflfuncreateall(long sd, GEN mfa, GEN F, GEN vE, GEN gN, GEN gk)
8721 : {
8722 147 : long i, l = lg(vE);
8723 147 : GEN L = cgetg(l, t_VEC);
8724 322 : for (i = 1; i < l; i++)
8725 175 : gel(L,i) = mflfuncreate(sd? gel(mfa,i): mfa, F, gel(vE,i), gN, gk);
8726 147 : return L;
8727 : }
8728 : GEN
8729 98 : lfunmf(GEN mf, GEN F, long bitprec)
8730 : {
8731 98 : pari_sp av = avma;
8732 98 : long i, l, prec = nbits2prec(bitprec);
8733 : GEN L, gk, gN;
8734 98 : mf = checkMF(mf);
8735 98 : gk = MF_get_gk(mf);
8736 98 : gN = MF_get_gN(mf);
8737 98 : if (typ(gk)!=t_INT) pari_err_IMPL("half-integral weight");
8738 98 : if (F)
8739 : {
8740 : GEN v;
8741 91 : long s = MF_get_space(mf);
8742 91 : if (!checkmf_i(F)) pari_err_TYPE("lfunmf", F);
8743 91 : if (!mfisinspace_i(mf, F)) err_space(F);
8744 91 : L = NULL;
8745 91 : if ((s == mf_NEW || s == mf_CUSP || s == mf_FULL)
8746 77 : && gequal(mfcoefs_i(F,1,1), mkvec2(gen_0,gen_1)))
8747 : { /* check if eigenform */
8748 49 : GEN vP, vF, b = mftobasis_i(mf, F);
8749 49 : long lF, d = degpol(mf_get_field(F));
8750 49 : v = mfsplit(mf, d, 0);
8751 49 : vF = gel(v,1);
8752 49 : vP = gel(v,2); lF = lg(vF);
8753 49 : for (i = 1; i < lF; i++)
8754 42 : if (degpol(gel(vP,i)) == d && gequal(gel(vF,i), b))
8755 : {
8756 42 : GEN vE = mfgetembed(F, prec);
8757 42 : GEN Z = mffrickeeigen_i(mf, mkvec(b), mkvec(vE), prec);
8758 42 : L = mflfuncreateall(1, gel(Z,1), F, vE, gN, gk);
8759 42 : break;
8760 : }
8761 : }
8762 91 : if (!L)
8763 : { /* not an eigenform: costly general case */
8764 49 : GEN mfa = mfatkininit_i(mf, itou(gN), 1, prec);
8765 49 : L = mflfuncreateall(0,mfa, F, mfgetembed(F,prec), gN, gk);
8766 : }
8767 91 : if (lg(L) == 2) L = gel(L,1);
8768 : }
8769 : else
8770 : {
8771 7 : GEN M = mfeigenbasis(mf), vE = mfeigenembed(mf, prec);
8772 7 : GEN v = mffrickeeigen(mf, vE, prec);
8773 7 : l = lg(vE); L = cgetg(l, t_VEC);
8774 63 : for (i = 1; i < l; i++)
8775 56 : gel(L,i) = mflfuncreateall(1,gel(v,i), gel(M,i), gel(vE,i), gN, gk);
8776 : }
8777 98 : return gc_GEN(av, L);
8778 : }
8779 :
8780 : GEN
8781 28 : mffromell(GEN E)
8782 : {
8783 28 : pari_sp av = avma;
8784 : GEN mf, F, z, v, S;
8785 : long N, i, l;
8786 :
8787 28 : checkell(E);
8788 28 : if (ell_get_type(E) != t_ELL_Q) pari_err_TYPE("mfffromell [E not over Q]", E);
8789 28 : N = itos(ellQ_get_N(E));
8790 28 : mf = mfinit_i(mkvec2(utoi(N), gen_2), mf_NEW);
8791 28 : v = split_i(mf, 1, 0);
8792 28 : S = gel(v,1); l = lg(S); /* rational newforms */
8793 28 : F = tag(t_MF_ELL, mkNK(N,2,mfchartrivial()), E);
8794 28 : z = mftobasis_i(mf, F);
8795 28 : for(i = 1; i < l; i++)
8796 28 : if (gequal(z, gel(S,i))) break;
8797 28 : if (i == l) pari_err_BUG("mffromell [E is not modular]");
8798 28 : return gc_GEN(av, mkvec3(mf, F, z));
8799 : }
8800 :
8801 : /* returns -1 if not, degree otherwise */
8802 : long
8803 140 : polishomogeneous(GEN P)
8804 : {
8805 : long i, D, l;
8806 140 : if (typ(P) != t_POL) return 0;
8807 77 : D = -1; l = lg(P);
8808 322 : for (i = 2; i < l; i++)
8809 : {
8810 245 : GEN c = gel(P,i);
8811 : long d;
8812 245 : if (gequal0(c)) continue;
8813 112 : d = polishomogeneous(c);
8814 112 : if (d < 0) return -1;
8815 112 : if (D < 0) D = d + i-2; else if (D != d + i-2) return -1;
8816 : }
8817 77 : return D;
8818 : }
8819 :
8820 : /* M a pp((Gram q)^(-1)) ZM; P a homogeneous t_POL, is P spherical ? */
8821 : static int
8822 28 : RgX_isspherical(GEN M, GEN P)
8823 : {
8824 28 : pari_sp av = avma;
8825 28 : GEN S, v = variables_vecsmall(P);
8826 28 : long i, j, l = lg(v);
8827 28 : if (l > lg(M)) pari_err(e_MISC, "too many variables in mffromqf");
8828 21 : S = gen_0;
8829 63 : for (j = 1; j < l; j++)
8830 : {
8831 42 : GEN Mj = gel(M, j), Pj = deriv(P, v[j]);
8832 105 : for (i = 1; i <= j; i++)
8833 : {
8834 63 : GEN c = gel(Mj, i);
8835 63 : if (!signe(c)) continue;
8836 42 : if (i != j) c = shifti(c, 1);
8837 42 : S = gadd(S, gmul(c, deriv(Pj, v[i])));
8838 : }
8839 : }
8840 21 : return gc_bool(av, gequal0(S));
8841 : }
8842 :
8843 : static GEN
8844 49 : c_QFsimple_i(long n, GEN Q, GEN P)
8845 : {
8846 49 : GEN V, v = qfrep0(Q, utoi(n), 1);
8847 49 : long i, l = lg(v);
8848 49 : V = cgetg(l+1, t_VEC);
8849 49 : if (!P || equali1(P))
8850 : {
8851 42 : gel(V,1) = gen_1;
8852 420 : for (i = 2; i <= l; i++) gel(V,i) = utoi(v[i-1] << 1);
8853 : }
8854 : else
8855 : {
8856 7 : gel(V,1) = gcopy(P);
8857 7 : for (i = 2; i <= l; i++) gel(V,i) = gmulgu(P, v[i-1] << 1);
8858 : }
8859 49 : return V;
8860 : }
8861 :
8862 : /* v a t_VECSMALL of variable numbers, lg(r) >= lg(v), r is a vector of
8863 : * scalars [not involving any variable in v] */
8864 : static GEN
8865 14 : gsubstvec_i(GEN e, GEN v, GEN r)
8866 : {
8867 14 : long i, l = lg(v);
8868 42 : for(i = 1; i < l; i++) e = gsubst(e, v[i], gel(r,i));
8869 14 : return e;
8870 : }
8871 : static GEN
8872 56 : c_QF_i(long n, GEN Q, GEN P)
8873 : {
8874 56 : pari_sp av = avma;
8875 : GEN V, v, va;
8876 : long i, l;
8877 56 : if (!P || typ(P) != t_POL) return gc_upto(av, c_QFsimple_i(n, Q, P));
8878 7 : v = gel(minim(Q, utoi(2*n), NULL), 3);
8879 7 : va = variables_vecsmall(P);
8880 7 : V = zerovec(n + 1); l = lg(v);
8881 21 : for (i = 1; i < l; i++)
8882 : {
8883 14 : pari_sp av = avma;
8884 14 : GEN X = gel(v,i);
8885 14 : long c = (itos(qfeval(Q, X)) >> 1) + 1;
8886 14 : gel(V, c) = gc_upto(av, gadd(gel(V, c), gsubstvec_i(P, va, X)));
8887 : }
8888 7 : return gmul2n(V, 1);
8889 : }
8890 :
8891 : GEN
8892 77 : mffromqf(GEN Q, GEN P)
8893 : {
8894 77 : pari_sp av = avma;
8895 : GEN G, Qi, F, D, N, mf, v, gk, chi;
8896 : long m, d, space;
8897 77 : if (typ(Q) != t_MAT) pari_err_TYPE("mffromqf", Q);
8898 77 : if (!RgM_is_ZM(Q) || !qfiseven(Q))
8899 0 : pari_err_TYPE("mffromqf [not integral or even]", Q);
8900 77 : m = lg(Q)-1;
8901 77 : Qi = ZM_inv(Q, &N);
8902 77 : if (!qfiseven(Qi)) N = shifti(N, 1);
8903 77 : d = 0;
8904 77 : if (!P || gequal1(P)) P = NULL;
8905 : else
8906 : {
8907 35 : P = simplify_shallow(P);
8908 35 : if (typ(P) == t_POL)
8909 : {
8910 28 : d = polishomogeneous(P);
8911 28 : if (d < 0) pari_err_TYPE("mffromqf [not homogeneous t_POL]", P);
8912 28 : if (!RgX_isspherical(Qi, P))
8913 7 : pari_err_TYPE("mffromqf [not a spherical t_POL]", P);
8914 : }
8915 : }
8916 63 : gk = uutoQ(m + 2*d, 2);
8917 63 : D = ZM_det(Q);
8918 63 : if (!odd(m)) { if ((m & 3) == 2) D = negi(D); } else D = shifti(D, 1);
8919 63 : space = d > 0 ? mf_CUSP : mf_FULL;
8920 63 : G = znstar0(N,1);
8921 63 : chi = mkvec2(G, znchar_quad(G,D));
8922 63 : mf = mfinit(mkvec3(N, gk, chi), space);
8923 63 : if (odd(d))
8924 : {
8925 7 : F = mftrivial();
8926 7 : v = zerocol(MF_get_dim(mf));
8927 : }
8928 : else
8929 : {
8930 56 : F = c_QF_i(mfsturm(mf), Q, P);
8931 56 : v = mftobasis_i(mf, F);
8932 56 : F = mflinear(mf, v);
8933 : }
8934 63 : return gc_GEN(av, mkvec3(mf, F, v));
8935 : }
8936 :
8937 : /***********************************************************************/
8938 : /* Eisenstein Series */
8939 : /***********************************************************************/
8940 : /* \sigma_{k-1}(\chi,n) */
8941 : static GEN
8942 24192 : sigchi(long k, GEN CHI, long n)
8943 : {
8944 24192 : pari_sp av = avma;
8945 24192 : GEN S = gen_1, D = mydivisorsu(u_ppo(n,mfcharmodulus(CHI)));
8946 24192 : long i, l = lg(D), ord = mfcharorder(CHI), vt = varn(mfcharpol(CHI));
8947 83671 : for (i = 2; i < l; i++) /* skip D[1] = 1 */
8948 : {
8949 59479 : long d = D[i], a = mfcharevalord(CHI, d, ord);
8950 59479 : S = gadd(S, Qab_Czeta(a, ord, powuu(d, k-1), vt));
8951 : }
8952 24192 : return gc_upto(av,S);
8953 : }
8954 :
8955 : /* write n = n0*n1*n2, (n0,N1*N2) = 1, n1 | N1^oo, n2 | N2^oo;
8956 : * return NULL if (n,N1,N2) > 1, else return factoru(n0) */
8957 : static GEN
8958 686350 : sigchi2_dec(long n, long N1, long N2, long *pn1, long *pn2)
8959 : {
8960 686350 : GEN P0, E0, P, E, fa = myfactoru(n);
8961 : long i, j, l;
8962 686350 : *pn1 = 1;
8963 686350 : *pn2 = 1;
8964 686350 : if (N1 == 1 && N2 == 1) return fa;
8965 669242 : P = gel(fa,1); l = lg(P);
8966 669242 : E = gel(fa,2);
8967 669242 : P0 = cgetg(l, t_VECSMALL);
8968 669242 : E0 = cgetg(l, t_VECSMALL);
8969 1553958 : for (i = j = 1; i < l; i++)
8970 : {
8971 989975 : long p = P[i], e = E[i];
8972 989975 : if (N1 % p == 0)
8973 : {
8974 142919 : if (N2 % p == 0) return NULL;
8975 37660 : *pn1 *= upowuu(p,e);
8976 : }
8977 847056 : else if (N2 % p == 0)
8978 129717 : *pn2 *= upowuu(p,e);
8979 717339 : else { P0[j] = p; E0[j] = e; j++; }
8980 : }
8981 563983 : setlg(P0, j);
8982 563983 : setlg(E0, j); return mkvec2(P0,E0);
8983 : }
8984 :
8985 : /* sigma_{k-1}(\chi_1,\chi_2,n), ord multiple of lcm(ord(CHI1),ord(CHI2)) */
8986 : static GEN
8987 608559 : sigchi2(long k, GEN CHI1, GEN CHI2, long n, long ord)
8988 : {
8989 608559 : pari_sp av = avma;
8990 : GEN S, D;
8991 608559 : long i, l, n1, n2, vt, N1 = mfcharmodulus(CHI1), N2 = mfcharmodulus(CHI2);
8992 608559 : D = sigchi2_dec(n, N1, N2, &n1, &n2); if (!D) return gc_const(av, gen_0);
8993 507983 : D = divisorsu_fact(D); l = lg(D);
8994 507983 : vt = varn(mfcharpol(CHI1));
8995 2192253 : for (i = 1, S = gen_0; i < l; i++)
8996 : { /* S += d^(k-1)*chi1(d)*chi2(n/d) */
8997 1684270 : long a, d = n2*D[i], nd = n1*D[l-i]; /* (d,N1)=1; (n/d,N2) = 1 */
8998 1684270 : a = mfcharevalord(CHI1, d, ord) + mfcharevalord(CHI2, nd, ord);
8999 1684270 : if (a >= ord) a -= ord;
9000 1684270 : S = gadd(S, Qab_Czeta(a, ord, powuu(d, k-1), vt));
9001 : }
9002 507983 : return gc_upto(av, S);
9003 : }
9004 :
9005 : /**************************************************************************/
9006 : /** Dirichlet characters with precomputed values **/
9007 : /**************************************************************************/
9008 : /* CHI mfchar */
9009 : static GEN
9010 33985 : mfcharcxinit(GEN CHI, long prec)
9011 : {
9012 33985 : GEN G = gel(CHI,1), chi = gel(CHI,2), z, V;
9013 33985 : GEN v = ncharvecexpo(G, znconrey_normalized(G,chi));
9014 33985 : long n, l = lg(v), o = mfcharorder(CHI);
9015 33985 : V = cgetg(l, t_VEC);
9016 33985 : z = grootsof1(o, prec); /* Mod(t, Phi_o(t)) -> e(1/o) */
9017 480851 : for (n = 1; n < l; n++) gel(V,n) = v[n] < 0? gen_0: gel(z, v[n]+1);
9018 33985 : return mkvecn(6, G, chi, gmfcharorder(CHI), v, V, mfcharpol(CHI));
9019 : }
9020 : /* v a "CHIvec" */
9021 : static long
9022 28601909 : CHIvec_N(GEN v) { return itou(znstar_get_N(gel(v,1))); }
9023 : static GEN
9024 25914 : CHIvec_CHI(GEN v)
9025 25914 : { return mkvec4(gel(v,1), gel(v,2), gel(v,3), gel(v,6)); }
9026 : /* character order */
9027 : static long
9028 66311 : CHIvec_ord(GEN v) { return itou(gel(v,3)); }
9029 : /* character exponents, i.e. t such that chi(n) = e(t) */
9030 : static GEN
9031 626913 : CHIvec_expo(GEN v) { return gel(v,4); }
9032 : /* character values chi(n) */
9033 : static GEN
9034 27670174 : CHIvec_val(GEN v) { return gel(v,5); }
9035 : /* CHI(n) */
9036 : static GEN
9037 27645779 : mychareval(GEN v, long n)
9038 : {
9039 27645779 : long N = CHIvec_N(v), ind = n%N;
9040 27645779 : if (ind <= 0) ind += N;
9041 27645779 : return gel(CHIvec_val(v), ind);
9042 : }
9043 : /* return c such that CHI(n) = e(c / ordz) or -1 if (n,N) > 1 */
9044 : static long
9045 626913 : mycharexpo(GEN v, long n)
9046 : {
9047 626913 : long N = CHIvec_N(v), ind = n%N;
9048 626913 : if (ind <= 0) ind += N;
9049 626913 : return CHIvec_expo(v)[ind];
9050 : }
9051 : /* faster than mfcharparity */
9052 : static long
9053 54754 : CHIvec_parity(GEN v) { return mycharexpo(v,-1) ? -1: 1; }
9054 : /**************************************************************************/
9055 :
9056 : static ulong
9057 77791 : sigchi2_Fl(long k, GEN CHI1vec, GEN CHI2vec, long n, GEN vz, ulong p)
9058 : {
9059 77791 : pari_sp av = avma;
9060 77791 : long ordz = lg(vz)-2, i, l, n1, n2;
9061 77791 : ulong S = 0;
9062 77791 : GEN D = sigchi2_dec(n, CHIvec_N(CHI1vec), CHIvec_N(CHI2vec), &n1, &n2);
9063 77791 : if (!D) return gc_ulong(av,S);
9064 73108 : D = divisorsu_fact(D);
9065 73108 : l = lg(D);
9066 276444 : for (i = 1; i < l; i++)
9067 : { /* S += d^(k-1)*chi1(d)*chi2(n/d) */
9068 203336 : long a, d = n2*D[i], nd = n1*D[l-i]; /* (d,N1)=1, (n/d,N2)=1 */
9069 203336 : a = mycharexpo(CHI2vec, nd) + mycharexpo(CHI1vec, d);
9070 203336 : if (a >= ordz) a -= ordz;
9071 203336 : S = Fl_add(S, Qab_Czeta_Fl(a, vz, Fl_powu(d,k-1,p), p), p);
9072 : }
9073 73108 : return gc_ulong(av,S);
9074 : }
9075 :
9076 : /**********************************************************************/
9077 : /* Fourier expansions of Eisenstein series */
9078 : /**********************************************************************/
9079 : /* L(CHI_t,0) / 2, CHI_t(n) = CHI(n)(t/n) as a character modulo N*t,
9080 : * order(CHI) | ord != 0 */
9081 : static GEN
9082 2618 : charLFwt1(long N, GEN CHI, long ord, long t)
9083 : {
9084 : GEN S;
9085 : long r, vt;
9086 :
9087 2618 : if (N == 1 && t == 1) return mkfrac(gen_m1,stoi(4));
9088 2618 : S = gen_0; vt = varn(mfcharpol(CHI));
9089 295435 : for (r = 1; r < N; r++)
9090 : { /* S += r*chi(r) */
9091 : long a, c;
9092 292817 : if (ugcd(N,r) != 1) continue;
9093 233310 : a = mfcharevalord(CHI,r,ord);
9094 233310 : c = (t != 1 && kross(t, r) < 0)? -r: r;
9095 233310 : S = gadd(S, Qab_Czeta(a, ord, stoi(c), vt));
9096 : }
9097 2618 : return gdivgs(S, -2*N);
9098 : }
9099 : /* L(CHI,0) / 2, mod p */
9100 : static ulong
9101 2002 : charLFwt1_Fl(GEN CHIvec, GEN vz, ulong p)
9102 : {
9103 2002 : long r, m = CHIvec_N(CHIvec);
9104 : ulong S;
9105 2002 : if (m == 1) return Rg_to_Fl(mkfrac(gen_m1,stoi(4)), p);
9106 2002 : S = 0;
9107 95977 : for (r = 1; r < m; r++)
9108 : { /* S += r*chi(r) */
9109 93975 : long a = mycharexpo(CHIvec,r);
9110 93975 : if (a < 0) continue;
9111 91616 : S = Fl_add(S, Qab_Czeta_Fl(a, vz, r, p), p);
9112 : }
9113 2002 : return Fl_div(Fl_neg(S,p), 2*m, p);
9114 : }
9115 : /* L(CHI_t,1-k) / 2, CHI_t(n) = CHI(n) * (t/n), order(CHI) | ord != 0;
9116 : * assume conductor of CHI_t divides N */
9117 : static GEN
9118 4557 : charLFwtk(long N, long k, GEN CHI, long ord, long t)
9119 : {
9120 : GEN S, P, dS;
9121 : long r, vt;
9122 :
9123 4557 : if (k == 1) return charLFwt1(N, CHI, ord, t);
9124 1939 : if (N == 1 && t == 1) return gdivgs(bernfrac(k),-2*k);
9125 1176 : vt = varn(mfcharpol(CHI));
9126 1176 : P = bern_init(N, k, &dS);
9127 1176 : dS = mul_denom(dS, stoi(-2*N*k));
9128 17633 : for (r = 1, S = gen_0; r < N; r++)
9129 : { /* S += P(r)*chi(r) */
9130 : long a;
9131 : GEN C;
9132 16457 : if (ugcd(r,N) != 1) continue;
9133 13860 : a = mfcharevalord(CHI,r,ord);
9134 13860 : C = ZX_Z_eval(P, utoi(r));
9135 13860 : if (t != 1 && kross(t, r) < 0) C = gneg(C);
9136 13860 : S = gadd(S, Qab_Czeta(a, ord, C, vt));
9137 : }
9138 1176 : return gdiv(S, dS);
9139 : }
9140 : /* L(CHI,1-k) / 2, mod p */
9141 : static ulong
9142 3227 : charLFwtk_Fl(long k, GEN CHIvec, GEN vz, ulong p)
9143 : {
9144 : GEN P, dS;
9145 : long r, m;
9146 : ulong S, d;
9147 3227 : if (k == 1) return charLFwt1_Fl(CHIvec, vz, p);
9148 1225 : m = CHIvec_N(CHIvec);
9149 1225 : if (m == 1) return Rg_to_Fl(gdivgs(bernfrac(k),-2*k), p);
9150 819 : P = ZX_to_Flx(bern_init(m, k, &dS), p);
9151 20167 : for (r = 1, S = 0; r < m; r++)
9152 : { /* S += P(r)*chi(r) */
9153 19348 : long a = mycharexpo(CHIvec,r);
9154 19348 : if (a < 0) continue;
9155 18088 : S = Fl_add(S, Qab_Czeta_Fl(a, vz, Flx_eval(P,r,p), p), p);
9156 : }
9157 819 : d = (2 * k * m) % p; if (dS) d = Fl_mul(d, umodiu(dS, p), p);
9158 819 : return Fl_div(Fl_neg(S,p), d, p);
9159 : }
9160 :
9161 : static GEN
9162 8365 : mfeisenstein2_0(long k, GEN CHI1, GEN CHI2, long ord)
9163 : {
9164 8365 : long N1 = mfcharmodulus(CHI1), N2 = mfcharmodulus(CHI2);
9165 8365 : if (k == 1 && N1 == 1) return charLFwtk(N2, 1, CHI2, ord, 1);
9166 5754 : if (N2 == 1) return charLFwtk(N1, k, CHI1, ord, 1);
9167 4025 : return gen_0;
9168 : }
9169 : static ulong
9170 5054 : mfeisenstein2_0_Fl(long k, GEN CHI1vec, GEN CHI2vec, GEN vz, ulong p)
9171 : {
9172 5054 : if (k == 1 && CHIvec_N(CHI1vec) == 1)
9173 2002 : return charLFwtk_Fl(k, CHI2vec, vz, p);
9174 3052 : else if (CHIvec_N(CHI2vec) == 1)
9175 1225 : return charLFwtk_Fl(k, CHI1vec, vz, p);
9176 1827 : else return 0;
9177 : }
9178 : static GEN
9179 140 : NK_eisen2(long k, GEN CHI1, GEN CHI2, long ord)
9180 : {
9181 140 : long o, N = mfcharmodulus(CHI1)*mfcharmodulus(CHI2);
9182 140 : GEN CHI = mfcharmul(CHI1, CHI2);
9183 140 : o = mfcharorder(CHI);
9184 140 : if ((ord & 3) == 2) ord >>= 1;
9185 140 : if ((o & 3) == 2) o >>= 1;
9186 140 : if (ord != o) pari_err_IMPL("mfeisenstein for these characters");
9187 133 : return mkNK(N, k, CHI);
9188 : }
9189 : static GEN
9190 343 : mfeisenstein_prim(long k, GEN CHI1, GEN CHI2)
9191 : {
9192 : long ord, vt;
9193 : GEN E0, NK, vchi, T;
9194 343 : if (!CHI2)
9195 : { /* E_k(chi1) */
9196 203 : vt = varn(mfcharpol(CHI1));
9197 203 : ord = mfcharorder(CHI1);
9198 203 : NK = mkNK(mfcharmodulus(CHI1), k, CHI1);
9199 203 : E0 = charLFwtk(mfcharmodulus(CHI1), k, CHI1, ord, 1);
9200 203 : vchi = mkvec3(E0, mkvec(mfcharpol(CHI1)), CHI1);
9201 203 : return tag(t_MF_EISEN, NK, vchi);
9202 : }
9203 : /* E_k(chi1,chi2) */
9204 140 : vt = varn(mfcharpol(CHI1));
9205 140 : ord = ulcm(mfcharorder(CHI1), mfcharorder(CHI2));
9206 140 : NK = NK_eisen2(k, CHI1, CHI2, ord);
9207 133 : E0 = mfeisenstein2_0(k, CHI1, CHI2, ord);
9208 133 : T = mkvec(polcyclo(ord, vt));
9209 133 : vchi = mkvec4(E0, T, CHI1, CHI2);
9210 133 : return tag2(t_MF_EISEN, NK, vchi, mkvecsmall2(ord,0));
9211 : }
9212 : static GEN
9213 378 : mfeisenstein_i(long k, GEN CHI1, GEN CHI2)
9214 : {
9215 378 : long s = 1, i, f = 1, N1 = 1, Nf, lD;
9216 : GEN P, E, D, L1, L2;
9217 378 : if (CHI2) { CHI2 = get_mfchar(CHI2); if (mfcharparity(CHI2) < 0) s = -s; }
9218 378 : if (CHI1)
9219 : {
9220 154 : CHI1 = get_mfchar(CHI1);
9221 140 : N1 = mfcharmodulus(CHI1);
9222 140 : CHI1 = mfchartoprimitive(CHI1, &f);
9223 140 : if (mfcharparity(CHI1) < 0) s = -s;
9224 : } else
9225 224 : CHI1 = mfchartrivial();
9226 364 : if (s != m1pk(k)) return mftrivial();
9227 343 : E = mfeisenstein_prim(k,CHI1,CHI2);
9228 336 : if (N1 == f) return E;
9229 14 : Nf = N1 / f;
9230 14 : P = gel(factoru(u_ppo(Nf, f)), 1);
9231 14 : D = divisorsu_moebius(P); lD = lg(D);
9232 14 : L1 = cgetg(lD, t_VEC); L2 = cgetg(lD, t_VEC);
9233 42 : for (i = 1; i < lD; i++)
9234 : { /* m = mu(g)*g, g | Nf, coprime to f, squarefree */
9235 28 : long m = D[i], g = labs(m);
9236 28 : GEN c = gdiv(mfchareval(CHI1,g),powuu(g,k));
9237 28 : gel(L1,i) = m < 0 ? gneg(c): c;
9238 28 : gel(L2,i) = mfbd_i(E, Nf / g);
9239 : }
9240 14 : return mflinear(L2, L1);
9241 : }
9242 :
9243 : GEN
9244 378 : mfeisenstein(long k, GEN CHI1, GEN CHI2)
9245 : {
9246 378 : pari_sp av = avma;
9247 378 : if (k < 1) pari_err_DOMAIN("mfeisenstein", "k", "<", gen_1, stoi(k));
9248 378 : return gc_GEN(av, mfeisenstein_i(k, CHI1, CHI2));
9249 : }
9250 :
9251 : static GEN
9252 2646 : mfeisenstein2all(long N0, GEN NK, long k, GEN CHI1, GEN CHI2, GEN T, long o)
9253 : {
9254 2646 : GEN E, E0 = mfeisenstein2_0(k, CHI1,CHI2, o), vchi = mkvec4(E0, T, CHI1,CHI2);
9255 2646 : long j, d = (lg(T)==4)? itou(gmael(T,3,1)): 1;
9256 2646 : E = cgetg(d+1, t_VEC);
9257 5411 : for (j=1; j<=d; j++) gel(E,j) = tag2(t_MF_EISEN, NK,vchi,mkvecsmall2(o,j-1));
9258 2646 : return mfbdall(E, N0 / mf_get_N(gel(E,1)));
9259 : }
9260 :
9261 : /* list of characters on G = (Z/NZ)^*, v[i] = NULL if (i,N) > 1, else
9262 : * the conductor of Conrey label i, [conductor, primitive char].
9263 : * Trivial chi (label 1) comes first */
9264 : static GEN
9265 1169 : zncharsG(GEN G)
9266 : {
9267 1169 : long i, l, N = itou(znstar_get_N(G));
9268 : GEN vCHI, V;
9269 1169 : if (N == 1) return mkvec2(gen_1,cgetg(1,t_COL));
9270 1169 : vCHI = const_vec(N,NULL);
9271 1169 : V = cyc2elts(znstar_get_conreycyc(G));
9272 1169 : l = lg(V);
9273 207739 : for (i = 1; i < l; i++)
9274 : {
9275 206570 : GEN chi0, chi = zc_to_ZC(gel(V,i)), n, F;
9276 206570 : F = znconreyconductor(G, chi, &chi0);
9277 206570 : if (typ(F) != t_INT) F = gel(F,1);
9278 206570 : n = znconreyexp(G, chi);
9279 206570 : gel(vCHI, itos(n)) = mkvec2(chi0, F);
9280 : }
9281 1169 : return vCHI;
9282 : }
9283 :
9284 : /* CHI primitive, f(CHI) | N. Return pairs (CHI1,CHI2) both primitive
9285 : * such that f(CHI1)*f(CHI2) | N and CHI1 * CHI2 = CHI;
9286 : * if k = 1, CHI1 is even; if k = 2, omit (1,1) if CHI = 1 */
9287 : static GEN
9288 1428 : mfeisensteinbasis_i(long N0, long k, GEN CHI)
9289 : {
9290 1428 : GEN G = gel(CHI,1), chi = gel(CHI,2), vT = const_vec(myeulerphiu(N0), NULL);
9291 1428 : GEN CHI0, GN, chiN, Lchi, LG, V, RES, NK, T, C = mfcharpol(CHI);
9292 1428 : long i, j, l, n, n1, N, ord = mfcharorder(CHI);
9293 1428 : long F = mfcharmodulus(CHI), vt = varn(mfcharpol(CHI));
9294 :
9295 1428 : CHI0 = (F == 1)? CHI: mfchartrivial();
9296 1428 : j = 1; RES = cgetg(N0+1, t_VEC);
9297 1428 : T = gel(vT,ord) = Qab_trace_init(ord, ord, C, C);
9298 1428 : if (F != 1 || k != 2)
9299 : { /* N1 = 1 */
9300 1274 : NK = mkNK(F, k, CHI);
9301 1274 : gel(RES, j++) = mfeisenstein2all(N0, NK, k, CHI0, CHI, T, ord);
9302 1274 : if (F != 1 && k != 1)
9303 329 : gel(RES, j++) = mfeisenstein2all(N0, NK, k, CHI, CHI0, T, ord);
9304 : }
9305 1428 : if (N0 == 1) { setlg(RES,j); return RES; }
9306 1330 : GN = G; chiN = chi;
9307 1330 : if (F == N0) N = N0;
9308 : else
9309 : {
9310 728 : GEN faN = myfactoru(N0), P = gel(faN,1), E = gel(faN,2);
9311 728 : long lP = lg(P);
9312 1876 : for (i = N = 1; i < lP; i++)
9313 : {
9314 1148 : long p = P[i];
9315 1148 : N *= upowuu(p, maxuu(E[i]/2, z_lval(F,p)));
9316 : }
9317 728 : if ((N & 3) == 2) N >>= 1;
9318 728 : if (N == 1) { setlg(RES,j); return RES; }
9319 567 : if (F != N)
9320 : {
9321 133 : GN = znstar0(utoipos(N),1);
9322 133 : chiN = zncharinduce(G, chi, GN);
9323 : }
9324 : }
9325 1169 : LG = const_vec(N, NULL); /* LG[d] = znstar(d,1) or NULL */
9326 1169 : gel(LG,1) = gel(CHI0,1);
9327 1169 : gel(LG,F) = G;
9328 1169 : gel(LG,N) = GN;
9329 1169 : Lchi = coprimes_zv(N);
9330 1169 : n = itou(znconreyexp(GN,chiN));
9331 1169 : V = zncharsG(GN); l = lg(V);
9332 263305 : for (n1 = 2; n1 < l; n1++) /* skip 1 (trivial char) */
9333 : {
9334 262136 : GEN v = gel(V,n1), w, chi1, chi2, G1, G2, CHI1, CHI2;
9335 : long N12, N1, N2, no, o12, t, m;
9336 262136 : if (!Lchi[n1] || n1 == n) continue; /* skip trivial chi2 */
9337 204197 : chi1 = gel(v,1); N1 = itou(gel(v,2)); /* conductor of chi1 */
9338 204197 : w = gel(V, Fl_div(n,n1,N));
9339 204197 : chi2 = gel(w,1); N2 = itou(gel(w,2)); /* conductor of chi2 */
9340 204197 : N12 = N1 * N2;
9341 204197 : if (N0 % N12) continue;
9342 :
9343 1771 : G1 = gel(LG,N1); if (!G1) gel(LG,N1) = G1 = znstar0(utoipos(N1), 1);
9344 1771 : if (k == 1 && zncharisodd(G1,chi1)) continue;
9345 1043 : G2 = gel(LG,N2); if (!G2) gel(LG,N2) = G2 = znstar0(utoipos(N2), 1);
9346 1043 : CHI1 = mfcharGL(G1, chi1);
9347 1043 : CHI2 = mfcharGL(G2, chi2);
9348 1043 : o12 = ulcm(mfcharorder(CHI1), mfcharorder(CHI2));
9349 : /* remove Galois orbit: same trace */
9350 1043 : no = Fl_powu(n1, ord, N);
9351 1414 : for (t = 1+ord, m = n1; t <= o12; t += ord)
9352 : { /* m <-> CHI1^t, if t in Gal(Q(chi1,chi2)/Q), omit (CHI1^t,CHI2^t) */
9353 371 : m = Fl_mul(m, no, N); if (!m) break;
9354 371 : if (ugcd(t, o12) == 1) Lchi[m] = 0;
9355 : }
9356 1043 : T = gel(vT,o12);
9357 1043 : if (!T) T = gel(vT,o12) = Qab_trace_init(o12, ord, polcyclo(o12,vt), C);
9358 1043 : NK = mkNK(N12, k, CHI);
9359 1043 : gel(RES, j++) = mfeisenstein2all(N0, NK, k, CHI1, CHI2, T, o12);
9360 : }
9361 1169 : setlg(RES,j); return RES;
9362 : }
9363 :
9364 : static GEN
9365 721 : mfbd_E2(GEN E2, long d, GEN CHI)
9366 : {
9367 721 : GEN E2d = mfbd_i(E2, d);
9368 721 : GEN F = mkvec2(E2, E2d), L = mkvec2(gen_1, utoineg(d));
9369 : /* cannot use mflinear_i: E2 and E2d do not have the same level */
9370 721 : return tag3(t_MF_LINEAR, mkNK(d,2,CHI), F, L, gen_1);
9371 : }
9372 : /* C-basis of E_k(Gamma_0(N),chi). If k = 1, the first basis element must not
9373 : * vanish at oo [used in mf1basis]. Here E_1(CHI), whose q^0 coefficient
9374 : * does not vanish (since L(CHI,0) does not) *if* CHI is not trivial; which
9375 : * must be the case in weight 1.
9376 : *
9377 : * (k>=3): In weight k >= 3, basis is B(d) E(CHI1,(CHI/CHI1)_prim), where
9378 : * CHI1 is primitive modulo N1, and if N2 is the conductor of CHI/CHI1
9379 : * then d*N1*N2 | N.
9380 : * (k=2): In weight k=2, same if CHI is nontrivial. If CHI is trivial, must
9381 : * not take CHI1 trivial, and must add E_2(tau)-dE_2(d tau)), where
9382 : * d|N, d > 1.
9383 : * (k=1): In weight k=1, same as k >= 3 except that we restrict to CHI1 even */
9384 : static GEN
9385 1456 : mfeisensteinbasis(long N, long k, GEN CHI)
9386 : {
9387 : long i, F;
9388 : GEN L;
9389 1456 : if (badchar(N, k, CHI)) return cgetg(1, t_VEC);
9390 1456 : if (k == 0) return mfcharistrivial(CHI)? mkvec(mf1()): cgetg(1, t_VEC);
9391 1428 : CHI = mfchartoprimitive(CHI, &F);
9392 1428 : L = mfeisensteinbasis_i(N, k, CHI);
9393 1428 : if (F == 1 && k == 2)
9394 : {
9395 154 : GEN v, E2 = mfeisenstein(2, NULL, NULL), D = mydivisorsu(N);
9396 154 : long nD = lg(D)-1;
9397 154 : v = cgetg(nD, t_VEC); L = vec_append(L,v);
9398 868 : for (i = 1; i < nD; i++) gel(v,i) = mfbd_E2(E2, D[i+1], CHI);
9399 : }
9400 1428 : return lg(L) == 1? L: shallowconcat1(L);
9401 : }
9402 :
9403 : static GEN
9404 77 : not_in_space(GEN F, long flag)
9405 : {
9406 77 : if (!flag) err_space(F);
9407 70 : return cgetg(1, t_COL);
9408 : }
9409 : /* when flag set, no error */
9410 : GEN
9411 1029 : mftobasis(GEN mf, GEN F, long flag)
9412 : {
9413 1029 : pari_sp av2, av = avma;
9414 : GEN G, v, y, gk;
9415 1029 : long N, B, ismf = checkmf_i(F);
9416 :
9417 1029 : mf = checkMF(mf);
9418 1029 : if (ismf)
9419 : {
9420 938 : if (mfistrivial(F)) return zerocol(MF_get_dim(mf));
9421 931 : if (!mf_same_k(mf, F) || !mf_same_CHI(mf, F)) return not_in_space(F, flag);
9422 : }
9423 980 : N = MF_get_N(mf);
9424 980 : gk = MF_get_gk(mf);
9425 980 : if (ismf)
9426 : {
9427 889 : long NF = mf_get_N(F);
9428 889 : B = maxuu(mfsturmNgk(NF,gk), mfsturmNgk(N,gk)) + 1;
9429 889 : v = mfcoefs_i(F,B,1);
9430 : }
9431 : else
9432 : {
9433 91 : B = mfsturmNgk(N, gk) + 1;
9434 91 : switch(typ(F))
9435 : { /* F(0),...,F(lg(v)-2) */
9436 63 : case t_SER: v = sertocol(F); settyp(v,t_VEC); break;
9437 14 : case t_VEC: v = F; break;
9438 7 : case t_COL: v = shallowtrans(F); break;
9439 7 : default: pari_err_TYPE("mftobasis",F);
9440 : v = NULL;/*LCOV_EXCL_LINE*/
9441 : }
9442 84 : if (flag) B = minss(B, lg(v)-2);
9443 : }
9444 973 : y = mftobasis_i(mf, v);
9445 973 : if (typ(y) == t_VEC)
9446 : {
9447 21 : if (flag) return gc_GEN(av, y);
9448 0 : pari_err(e_MISC, "not enough coefficients in mftobasis");
9449 : }
9450 952 : av2 = avma;
9451 952 : if (MF_get_space(mf) == mf_FULL || mfsturm(mf)+1 == B) return y;
9452 476 : G = mflinear(mf, y);
9453 476 : if (!gequal(v, mfcoefs_i(G, lg(v)-2,1))) y = NULL;
9454 476 : if (!y) { set_avma(av); return not_in_space(F, flag); }
9455 441 : set_avma(av2); return gc_upto(av, y);
9456 : }
9457 :
9458 : /* assume N > 0; first cusp is always 0 */
9459 : static GEN
9460 49 : mfcusps_i(long N)
9461 : {
9462 : long i, c, l;
9463 : GEN D, v;
9464 :
9465 49 : if (N == 1) return mkvec(gen_0);
9466 49 : D = mydivisorsu(N); l = lg(D); /* left on stack */
9467 49 : c = mfnumcuspsu_fact(myfactoru(N));
9468 49 : v = cgetg(c + 1, t_VEC);
9469 350 : for (i = c = 1; i < l; i++)
9470 : {
9471 301 : long C = D[i], NC = D[l-i], lima = ugcd(C, NC), A0, A;
9472 889 : for (A0 = 0; A0 < lima; A0++)
9473 588 : if (ugcd(A0, lima) == 1)
9474 : {
9475 539 : A = A0; while (ugcd(A,C) > 1) A += lima;
9476 392 : gel(v, c++) = uutoQ(A, C);
9477 : }
9478 : }
9479 49 : return v;
9480 : }
9481 : /* List of cusps of Gamma_0(N) */
9482 : GEN
9483 28 : mfcusps(GEN gN)
9484 : {
9485 : long N;
9486 : GEN mf;
9487 28 : if (typ(gN) == t_INT) N = itos(gN);
9488 14 : else if ((mf = checkMF_i(gN))) N = MF_get_N(mf);
9489 0 : else { pari_err_TYPE("mfcusps", gN); N = 0; }
9490 28 : if (N <= 0) pari_err_DOMAIN("mfcusps", "N", "<=", gen_0, stoi(N));
9491 28 : return mfcusps_i(N);
9492 : }
9493 :
9494 : long
9495 315 : mfcuspisregular(GEN NK, GEN cusp)
9496 : {
9497 : long v, N, dk, nk, t, o;
9498 : GEN mf, CHI, go, A, C, g, c, d;
9499 315 : if ((mf = checkMF_i(NK)))
9500 : {
9501 49 : GEN gk = MF_get_gk(mf);
9502 49 : N = MF_get_N(mf);
9503 49 : CHI = MF_get_CHI(mf);
9504 49 : Qtoss(gk, &nk, &dk);
9505 : }
9506 : else
9507 266 : checkNK2(NK, &N, &nk, &dk, &CHI, 0);
9508 315 : if (typ(cusp) == t_INFINITY) return 1;
9509 315 : if (typ(cusp) == t_FRAC) { A = gel(cusp,1); C = gel(cusp,2); }
9510 28 : else { A = cusp; C = gen_1; }
9511 315 : g = diviuexact(mului(N,C), ugcd(N, Fl_sqr(umodiu(C,N), N)));
9512 315 : c = mulii(negi(C),g);
9513 315 : d = addiu(mulii(A,g), 1);
9514 315 : if (!CHI) return 1;
9515 315 : go = gmfcharorder(CHI);
9516 315 : v = vali(go); if (v < 2) go = shifti(go, 2-v);
9517 315 : t = itou( znchareval(gel(CHI,1), gel(CHI,2), d, go) );
9518 315 : if (dk == 1) return t == 0;
9519 154 : o = itou(go);
9520 154 : if (kronecker(c,d) < 0) t = Fl_add(t, o/2, o);
9521 154 : if (Mod4(d) == 1) return t == 0;
9522 14 : t = Fl_sub(t, Fl_mul(o/4, nk, o), o);
9523 14 : return t == 0;
9524 : }
9525 :
9526 : /* Some useful closures */
9527 :
9528 : /* sum_{d|n} d^k */
9529 : static GEN
9530 48020 : mysumdivku(ulong n, ulong k)
9531 : {
9532 48020 : GEN fa = myfactoru(n);
9533 48020 : return k == 1? usumdiv_fact(fa): usumdivk_fact(fa,k);
9534 : }
9535 : static GEN
9536 882 : c_Ek(long n, long d, GEN F)
9537 : {
9538 882 : GEN E = cgetg(n + 2, t_VEC), C = gel(F,2);
9539 882 : long i, k = mf_get_k(F);
9540 882 : gel (E, 1) = gen_1;
9541 26264 : for (i = 1; i <= n; i++)
9542 : {
9543 25382 : pari_sp av = avma;
9544 25382 : gel(E, i+1) = gc_upto(av, gmul(C, mysumdivku(i*d, k-1)));
9545 : }
9546 882 : return E;
9547 : }
9548 :
9549 : GEN
9550 406 : mfEk(long k)
9551 : {
9552 406 : pari_sp av = avma;
9553 : GEN E0, NK;
9554 406 : if (k < 0 || odd(k)) pari_err_TYPE("mfEk [incorrect k]", stoi(k));
9555 406 : if (!k) return mf1();
9556 399 : E0 = gdivsg(-2*k, bernfrac(k));
9557 399 : NK = mkNK(1,k,mfchartrivial());
9558 399 : return gc_GEN(av, tag(t_MF_Ek, NK, E0));
9559 : }
9560 :
9561 : GEN
9562 56 : mfDelta(void)
9563 : {
9564 56 : pari_sp av = avma;
9565 56 : return gc_GEN(av, tag0(t_MF_DELTA, mkNK(1,12,mfchartrivial())));
9566 : }
9567 :
9568 : GEN
9569 805 : mfTheta(GEN psi)
9570 : {
9571 805 : pari_sp av = avma;
9572 : GEN N, gk, psi2;
9573 : long par;
9574 805 : if (!psi) { psi = mfchartrivial(); N = utoipos(4); par = 1; }
9575 : else
9576 : {
9577 : long FC;
9578 21 : psi = get_mfchar(psi);
9579 21 : FC = mfcharconductor(psi);
9580 21 : if (mfcharmodulus(psi) != FC)
9581 0 : pari_err_TYPE("mfTheta [nonprimitive character]", psi);
9582 21 : par = mfcharparity(psi);
9583 21 : N = shifti(sqru(FC),2);
9584 : }
9585 805 : if (par > 0) { gk = ghalf; psi2 = psi; }
9586 7 : else { gk = gsubsg(2, ghalf); psi2 = mfcharmul(psi, get_mfchar(stoi(-4))); }
9587 805 : return gc_GEN(av, tag(t_MF_THETA, mkgNK(N, gk, psi2, pol_x(1)), psi));
9588 : }
9589 :
9590 : /* Output 0 if not desired eta product: if flag=0 (default) require
9591 : * holomorphic at cusps. If flag set, accept meromorphic, but sill in some
9592 : * modular function space */
9593 : GEN
9594 210 : mffrometaquo(GEN eta, long flag)
9595 : {
9596 210 : pari_sp av = avma;
9597 : GEN NK, N, k, BR, P;
9598 210 : long v, cusp = 0;
9599 210 : if (!etaquotype(&eta, &N,&k,&P, &v, NULL, flag? NULL: &cusp) || cusp < 0)
9600 14 : return gc_const(av, gen_0);
9601 196 : if (lg(gel(eta,1)) == 1) { set_avma(av); return mf1(); }
9602 189 : BR = mkvec2(ZV_to_zv(gel(eta,1)), ZV_to_zv(gel(eta,2)));
9603 189 : if (v < 0) v = 0;
9604 189 : NK = mkgNK(N, k, get_mfchar(P), pol_x(1));
9605 189 : return gc_GEN(av, tag2(t_MF_ETAQUO, NK, BR, utoi(v)));
9606 : }
9607 :
9608 : /* Q^(-r) */
9609 : static GEN
9610 375 : RgXn_negpow(GEN Q, long r, long L)
9611 : {
9612 375 : if (r < 0) r = -r; else Q = RgXn_inv_i(Q, L);
9613 375 : if (r != 1) Q = RgXn_powu_i(Q, r, L);
9614 375 : return Q;
9615 : }
9616 : /* flag same as in mffrometaquo: if set, accept meromorphic. */
9617 : static GEN
9618 49 : mfisetaquo_i(GEN F, long flag)
9619 : {
9620 : GEN gk, P, E, M, S, G, CHI, v, w;
9621 : long b, l, L, N, vS, m, j;
9622 49 : const long bextra = 10;
9623 :
9624 49 : if (!checkmf_i(F)) pari_err_TYPE("mfisetaquo",F);
9625 49 : CHI = mf_get_CHI(F); if (mfcharorder(CHI) > 2) return NULL;
9626 49 : N = mf_get_N(F);
9627 49 : gk = mf_get_gk(F);
9628 49 : b = mfsturmNgk(N, gk);
9629 49 : L = maxss(N, b) + bextra;
9630 49 : S = mfcoefs_i(F, L, 1);
9631 49 : if (!RgV_is_ZV(S)) return NULL;
9632 889 : for (vS = 1; vS <= L+1; vS++)
9633 889 : if (signe(gel(S,vS))) break;
9634 49 : vS--;
9635 49 : if (vS >= bextra - 1) { L += vS; S = mfcoefs_i(F, L, 1); }
9636 49 : if (vS) { S = vecslice(S, vS+1, L+1); L -= vS; }
9637 49 : S = RgV_to_RgX(S, 0); l = lg(S)-2;
9638 49 : P = cgetg(l, t_COL);
9639 49 : E = cgetg(l, t_COL); w = v = gen_0; /* w = weight, v = valuation */
9640 1908 : for (m = j = 1; m+2 < lg(S); m++)
9641 : {
9642 1866 : GEN c = gel(S,m+2);
9643 : long r;
9644 1866 : if (is_bigint(c)) return NULL;
9645 1859 : r = -itos(c);
9646 1859 : if (r)
9647 : {
9648 375 : S = ZXn_mul(S, RgXn_negpow(eta_ZXn(m, L), r, L), L);
9649 375 : gel(P,j) = utoipos(m);
9650 375 : gel(E,j) = stoi(r);
9651 375 : v = addmuliu(v, gel(E,j), m);
9652 375 : w = addis(w, r);
9653 375 : j++;
9654 : }
9655 : }
9656 42 : if (!equalii(w, gmul2n(gk, 1)) || (!flag && !equalii(v, muluu(24,vS))))
9657 7 : return NULL;
9658 35 : setlg(P, j);
9659 35 : setlg(E, j); M = mkmat2(P, E); G = mffrometaquo(M, flag);
9660 35 : return (typ(G) != t_INT
9661 35 : && (mfsturmmf(G) <= b + bextra || mfisequal(F, G, b)))? M: NULL;
9662 : }
9663 : GEN
9664 49 : mfisetaquo(GEN F, long flag)
9665 : {
9666 49 : pari_sp av = avma;
9667 49 : GEN M = mfisetaquo_i(F, flag);
9668 49 : return M? gc_GEN(av, M): gc_const(av, gen_0);
9669 : }
9670 :
9671 : #if 0
9672 : /* number of primitive characters modulo N */
9673 : static ulong
9674 : numprimchars(ulong N)
9675 : {
9676 : GEN fa, P, E;
9677 : long i, l;
9678 : ulong n;
9679 : if ((N & 3) == 2) return 0;
9680 : fa = myfactoru(N);
9681 : P = gel(fa,1); l = lg(P);
9682 : E = gel(fa,2);
9683 : for (i = n = 1; i < l; i++)
9684 : {
9685 : ulong p = P[i], e = E[i];
9686 : if (e == 2) n *= p-2; else n *= (p-1)*(p-1)*upowuu(p,e-2);
9687 : }
9688 : return n;
9689 : }
9690 : #endif
9691 :
9692 : /* Space generated by products of two Eisenstein series */
9693 :
9694 : static int
9695 74431 : cmp_small_priority(void *E, GEN a, GEN b)
9696 : {
9697 74431 : GEN prio = (GEN)E;
9698 74431 : return cmpss(prio[(long)a], prio[(long)b]);
9699 : }
9700 : static long
9701 1302 : znstar_get_expo(GEN G) { return itou(cyc_get_expo(znstar_get_cyc(G))); }
9702 :
9703 : /* Return [vchi, bymod, vG]:
9704 : * vG[f] = znstar(f,1) for f a conductor of (at least) a char mod N; else NULL
9705 : * bymod[f] = vecsmall of conrey indexes of chars modulo f | N; else NULL
9706 : * vchi[n] = a list of CHIvec [G0,chi0,o,ncharvecexpo(G0,nchi0),...]:
9707 : * chi0 = primitive char attached to Conrey Mod(n,N)
9708 : * (resp. NULL if (n,N) > 1) */
9709 : static GEN
9710 651 : charsmodN(long N)
9711 : {
9712 651 : GEN D, G, prio, phio, dummy = cgetg(1,t_VEC);
9713 651 : GEN vP, vG = const_vec(N,NULL), vCHI = const_vec(N,NULL);
9714 651 : GEN bymod = const_vec(N,NULL);
9715 651 : long pn, i, l, vt = fetch_user_var("t");
9716 651 : D = mydivisorsu(N); l = lg(D);
9717 3941 : for (i = 1; i < l; i++)
9718 3290 : gel(bymod, D[i]) = vecsmalltrunc_init(myeulerphiu(D[i])+1);
9719 651 : gel(vG,N) = G = znstar0(utoipos(N),1);
9720 651 : pn = znstar_get_expo(G); /* exponent(Z/NZ)^* */
9721 651 : vP = const_vec(pn,NULL);
9722 27069 : for (i = 1; i <= N; i++)
9723 : {
9724 : GEN P, gF, G0, chi0, nchi0, chi, v, go;
9725 : long j, F, o;
9726 26418 : if (ugcd(i,N) != 1) continue;
9727 14147 : chi = znconreylog(G, utoipos(i));
9728 14147 : gF = znconreyconductor(G, chi, &chi0);
9729 14147 : F = (typ(gF) == t_INT)? itou(gF): itou(gel(gF,1));
9730 14147 : G0 = gel(vG, F); if (!G0) G0 = gel(vG,F) = znstar0(gF, 1);
9731 14147 : nchi0 = znconreylog_normalize(G0,chi0);
9732 14147 : go = gel(nchi0,1); o = itou(go); /* order(chi0) */
9733 14147 : v = ncharvecexpo(G0, nchi0);
9734 14147 : if (!equaliu(go, pn)) v = zv_z_mul(v, pn / o);
9735 14147 : P = gel(vP, o); if (!P) P = gel(vP,o) = polcyclo(o,vt);
9736 : /* mfcharcxinit with dummy complex powers */
9737 14147 : gel(vCHI,i) = mkvecn(6, G0, chi0, go, v, dummy, P);
9738 14147 : D = mydivisorsu(N / F); l = lg(D);
9739 40565 : for (j = 1; j < l; j++) vecsmalltrunc_append(gel(bymod, F*D[j]), i);
9740 : }
9741 651 : phio = zero_zv(pn); l = lg(vCHI); prio = cgetg(l, t_VEC);
9742 27069 : for (i = 1; i < l; i++)
9743 : {
9744 26418 : GEN CHI = gel(vCHI,i);
9745 : long o;
9746 26418 : if (!CHI) continue;
9747 14147 : o = CHIvec_ord(CHI);
9748 14147 : if (!phio[o]) phio[o] = myeulerphiu(o);
9749 14147 : prio[i] = phio[o];
9750 : }
9751 651 : l = lg(bymod);
9752 : /* sort characters by increasing value of phi(order) */
9753 27069 : for (i = 1; i < l; i++)
9754 : {
9755 26418 : GEN z = gel(bymod,i);
9756 26418 : if (z) gen_sort_inplace(z, (void*)prio, &cmp_small_priority, NULL);
9757 : }
9758 651 : return mkvec3(vCHI, bymod, vG);
9759 : }
9760 :
9761 : static GEN
9762 5586 : mfeisenstein2pure(long k, GEN CHI1, GEN CHI2, long ord, GEN P, long lim)
9763 : {
9764 5586 : GEN c, V = cgetg(lim+2, t_COL);
9765 : long n;
9766 5586 : c = mfeisenstein2_0(k, CHI1, CHI2, ord);
9767 5586 : if (P) c = grem(c, P);
9768 5586 : gel(V,1) = c;
9769 113400 : for (n=1; n <= lim; n++)
9770 : {
9771 107814 : c = sigchi2(k, CHI1, CHI2, n, ord);
9772 107814 : if (P) c = grem(c, P);
9773 107814 : gel(V,n+1) = c;
9774 : }
9775 5586 : return V;
9776 : }
9777 : static GEN
9778 5054 : mfeisenstein2pure_Fl(long k, GEN CHI1vec, GEN CHI2vec, GEN vz, ulong p, long lim)
9779 : {
9780 5054 : GEN V = cgetg(lim+2, t_VECSMALL);
9781 : long n;
9782 5054 : V[1] = mfeisenstein2_0_Fl(k, CHI1vec, CHI2vec, vz, p);
9783 82845 : for (n=1; n <= lim; n++) V[n+1] = sigchi2_Fl(k, CHI1vec, CHI2vec, n, vz, p);
9784 5054 : return V;
9785 : }
9786 :
9787 : static GEN
9788 252 : getcolswt2(GEN M, GEN D, ulong p)
9789 : {
9790 252 : GEN R, v = gel(M,1);
9791 252 : long i, l = lg(M) - 1;
9792 252 : R = cgetg(l, t_MAT); /* skip D[1] = 1 */
9793 1008 : for (i = 1; i < l; i++)
9794 : {
9795 756 : GEN w = Flv_Fl_mul(gel(M,i+1), D[i+1], p);
9796 756 : gel(R,i) = Flv_sub(v, w, p);
9797 : }
9798 252 : return R;
9799 : }
9800 : static GEN
9801 5852 : expandbd(GEN V, long d)
9802 : {
9803 : long L, n, nd;
9804 : GEN W;
9805 5852 : if (d == 1) return V;
9806 2121 : L = lg(V)-1; W = zerocol(L); /* nd = n/d */
9807 18263 : for (n = nd = 0; n < L; n += d, nd++) gel(W, n+1) = gel(V, nd+1);
9808 2121 : return W;
9809 : }
9810 : static GEN
9811 7714 : expandbd_Fl(GEN V, long d)
9812 : {
9813 : long L, n, nd;
9814 : GEN W;
9815 7714 : if (d == 1) return V;
9816 2660 : L = lg(V)-1; W = zero_Flv(L); /* nd = n/d */
9817 16429 : for (n = nd = 0; n < L; n += d, nd++) W[n+1] = V[nd+1];
9818 2660 : return W;
9819 : }
9820 : static void
9821 5054 : getcols_i(GEN *pM, GEN *pvj, GEN gk, GEN CHI1vec, GEN CHI2vec, long NN1, GEN vz,
9822 : ulong p, long lim)
9823 : {
9824 5054 : GEN CHI1 = CHIvec_CHI(CHI1vec), CHI2 = CHIvec_CHI(CHI2vec);
9825 5054 : long N2 = CHIvec_N(CHI2vec);
9826 5054 : GEN vj, M, D = mydivisorsu(NN1/N2);
9827 5054 : long i, l = lg(D), k = gk[2];
9828 5054 : GEN V = mfeisenstein2pure_Fl(k, CHI1vec, CHI2vec, vz, p, lim);
9829 5054 : M = cgetg(l, t_MAT);
9830 12768 : for (i = 1; i < l; i++) gel(M,i) = expandbd_Fl(V, D[i]);
9831 5054 : if (k == 2 && N2 == 1 && CHIvec_N(CHI1vec) == 1)
9832 : {
9833 252 : M = getcolswt2(M, D, p); l--;
9834 252 : D = vecslice(D, 2, l);
9835 : }
9836 5054 : *pM = M;
9837 5054 : *pvj = vj = cgetg(l, t_VEC);
9838 12516 : for (i = 1; i < l; i++) gel(vj,i) = mkvec4(gk, CHI1, CHI2, utoipos(D[i]));
9839 5054 : }
9840 :
9841 : /* find all CHI1, CHI2 mod N such that CHI1*CHI2 = CHI, f(CHI1)*f(CHI2) | N.
9842 : * set M = mfcoefs(B_e E(CHI1,CHI2), lim), vj = [e,i1,i2] */
9843 : static void
9844 2037 : getcols(GEN *pM, GEN *pv, long k, long nCHI, GEN allN, GEN vz, ulong p,
9845 : long lim)
9846 : {
9847 2037 : GEN vCHI = gel(allN,1), gk = utoi(k);
9848 2037 : GEN M = cgetg(1,t_MAT), v = cgetg(1,t_VEC);
9849 2037 : long i1, N = lg(vCHI)-1;
9850 93527 : for (i1 = 1; i1 <= N; i1++)
9851 : {
9852 91490 : GEN CHI1vec = gel(vCHI, i1), CHI2vec, M1, v1;
9853 : long NN1, i2;
9854 160972 : if (!CHI1vec) continue;
9855 73150 : if (k == 1 && CHIvec_parity(CHI1vec) == -1) continue;
9856 48391 : NN1 = N/CHIvec_N(CHI1vec); /* N/f(chi1) */;
9857 48391 : i2 = Fl_div(nCHI,i1, N);
9858 48391 : if (!i2) i2 = 1;
9859 48391 : CHI2vec = gel(vCHI,i2);
9860 48391 : if (NN1 % CHIvec_N(CHI2vec)) continue; /* f(chi1)f(chi2) | N ? */
9861 3668 : getcols_i(&M1, &v1, gk, CHI1vec, CHI2vec, NN1, vz, p, lim);
9862 3668 : M = shallowconcat(M, M1);
9863 3668 : v = shallowconcat(v, v1);
9864 : }
9865 2037 : *pM = M;
9866 2037 : *pv = v;
9867 2037 : }
9868 :
9869 : static void
9870 1239 : update_Mj(GEN *M, GEN *vecj, GEN *pz, ulong p)
9871 : {
9872 : GEN perm;
9873 1239 : *pz = Flm_indexrank(*M, p); perm = gel(*pz,2);
9874 1239 : *M = vecpermute(*M, perm);
9875 1239 : *vecj = vecpermute(*vecj, perm);
9876 1239 : }
9877 : static int
9878 441 : getcolsgen(long dim, GEN *pM, GEN *pvj, GEN *pz, long k, long ell, long nCHI,
9879 : GEN allN, GEN vz, ulong p, long lim)
9880 : {
9881 441 : GEN vCHI = gel(allN,1), bymod = gel(allN,2), gell = utoi(ell);
9882 441 : long i1, N = lg(vCHI)-1;
9883 441 : long L = lim+1;
9884 441 : if (lg(*pvj)-1 >= dim) update_Mj(pM, pvj, pz, p);
9885 441 : if (lg(*pvj)-1 == dim) return 1;
9886 1806 : for (i1 = 1; i1 <= N; i1++)
9887 : {
9888 1778 : GEN CHI1vec = gel(vCHI, i1), T;
9889 : long par1, j, l, N1, NN1;
9890 :
9891 1778 : if (!CHI1vec) continue;
9892 1750 : par1 = CHIvec_parity(CHI1vec);
9893 1750 : if (ell == 1 && par1 == -1) continue;
9894 1169 : if (odd(ell)) par1 = -par1;
9895 1169 : N1 = CHIvec_N(CHI1vec);
9896 1169 : NN1 = N/N1;
9897 1169 : T = gel(bymod, NN1); l = lg(T);
9898 4277 : for (j = 1; j < l; j++)
9899 : {
9900 3486 : long i2 = T[j], l1, l2, j1, s, nC;
9901 3486 : GEN M, M1, M2, vj, vj1, vj2, CHI2vec = gel(vCHI, i2);
9902 3486 : if (CHIvec_parity(CHI2vec) != par1) continue;
9903 1386 : nC = Fl_div(nCHI, Fl_mul(i1,i2,N), N);
9904 1386 : getcols(&M2, &vj2, k-ell, nC, allN, vz, p, lim);
9905 1386 : l2 = lg(M2); if (l2 == 1) continue;
9906 1386 : getcols_i(&M1, &vj1, gell, CHI1vec, CHI2vec, NN1, vz, p, lim);
9907 1386 : l1 = lg(M1);
9908 1386 : M1 = Flm_to_FlxV(M1, 0);
9909 1386 : M2 = Flm_to_FlxV(M2, 0);
9910 1386 : M = cgetg((l1-1)*(l2-1) + 1, t_MAT);
9911 1386 : vj = cgetg((l1-1)*(l2-1) + 1, t_VEC);
9912 3318 : for (j1 = s = 1; j1 < l1; j1++)
9913 : {
9914 1932 : GEN E = gel(M1,j1), v = gel(vj1,j1);
9915 : long j2;
9916 7805 : for (j2 = 1; j2 < l2; j2++, s++)
9917 : {
9918 5873 : GEN c = Flx_to_Flv(Flxn_mul(E, gel(M2,j2), L, p), L);
9919 5873 : gel(M,s) = c;
9920 5873 : gel(vj,s) = mkvec2(v, gel(vj2,j2));
9921 : }
9922 : }
9923 1386 : *pM = shallowconcat(*pM, M);
9924 1386 : *pvj = shallowconcat(*pvj, vj);
9925 1386 : if (lg(*pvj)-1 >= dim) update_Mj(pM, pvj, pz, p);
9926 1386 : if (lg(*pvj)-1 == dim) return 1;
9927 : }
9928 : }
9929 28 : if (ell == 1)
9930 : {
9931 21 : update_Mj(pM, pvj, pz, p);
9932 21 : return (lg(*pvj)-1 == dim);
9933 : }
9934 7 : return 0;
9935 : }
9936 :
9937 : static GEN
9938 1645 : mkF2bd(long d, long lim)
9939 : {
9940 1645 : GEN V = zerovec(lim + 1);
9941 : long n;
9942 1645 : gel(V, 1) = sstoQ(-1, 24);
9943 24248 : for (n = 1; n <= lim/d; n++) gel(V, n*d + 1) = mysumdivku(n, 1);
9944 1645 : return V;
9945 : }
9946 :
9947 : static GEN
9948 6202 : mkeisen(GEN E, long ord, GEN P, long lim)
9949 : {
9950 6202 : long k = itou(gel(E,1)), e = itou(gel(E,4));
9951 6202 : GEN CHI1 = gel(E,2), CHI2 = gel(E,3);
9952 6202 : if (k == 2 && mfcharistrivial(CHI1) && mfcharistrivial(CHI2))
9953 616 : return gsub(mkF2bd(1,lim), gmulgu(mkF2bd(e,lim), e));
9954 : else
9955 : {
9956 5586 : GEN V = mfeisenstein2pure(k, CHI1, CHI2, ord, P, lim);
9957 5586 : return expandbd(V, e);
9958 : }
9959 : }
9960 : static GEN
9961 609 : mkM(GEN vj, long pn, GEN P, long lim)
9962 : {
9963 609 : long j, l = lg(vj), L = lim+1;
9964 609 : GEN M = cgetg(l, t_MAT);
9965 5061 : for (j = 1; j < l; j++)
9966 : {
9967 : GEN E1, E2;
9968 4452 : parse_vecj(gel(vj,j), &E1,&E2);
9969 4452 : E1 = RgV_to_RgX(mkeisen(E1, pn, P, lim), 0);
9970 4452 : if (E2)
9971 : {
9972 1750 : E2 = RgV_to_RgX(mkeisen(E2, pn, P, lim), 0);
9973 1750 : E1 = RgXn_mul(E1, E2, L);
9974 : }
9975 4452 : E1 = RgX_to_RgC(E1, L);
9976 4452 : if (P && E2) E1 = RgXQV_red(E1, P);
9977 4452 : gel(M,j) = E1;
9978 : }
9979 609 : return M;
9980 : }
9981 :
9982 : /* assume N > 2 */
9983 : static GEN
9984 35 : mffindeisen1(long N)
9985 : {
9986 35 : GEN G = znstar0(utoipos(N), 1), L = chargalois(G, NULL), chi0 = NULL;
9987 35 : long j, m = N, l = lg(L);
9988 259 : for (j = 1; j < l; j++)
9989 : {
9990 245 : GEN chi = gel(L,j);
9991 245 : long r = myeulerphiu(itou(zncharorder(G,chi)));
9992 245 : if (r >= m) continue;
9993 182 : chi = znconreyfromchar(G, chi);
9994 182 : if (zncharisodd(G,chi)) { m = r; chi0 = chi; if (r == 1) break; }
9995 : }
9996 35 : if (!chi0) pari_err_BUG("mffindeisen1 [no Eisenstein series found]");
9997 35 : chi0 = znchartoprimitive(G,chi0);
9998 35 : return mfcharGL(gel(chi0,1), gel(chi0,2));
9999 : }
10000 :
10001 : static GEN
10002 651 : mfeisensteinspaceinit_i(long N, long k, GEN CHI)
10003 : {
10004 651 : GEN M, Minv, vj, vG, GN, allN, P, vz, z = NULL;
10005 651 : long nCHI, lim, ell, ord, dim = mffulldim(N, k, CHI);
10006 : ulong r, p;
10007 :
10008 651 : if (!dim) retmkvec3(cgetg(1,t_VECSMALL),
10009 : mkvec2(cgetg(1,t_MAT),gen_1),cgetg(1,t_VEC));
10010 651 : lim = mfsturmNk(N, k) + 1;
10011 651 : allN = charsmodN(N);
10012 651 : vG = gel(allN,3);
10013 651 : GN = gel(vG,N);
10014 651 : ord = znstar_get_expo(GN);
10015 651 : P = ord <= 2? NULL: polcyclo(ord, varn(mfcharpol(CHI)));
10016 651 : CHI = induce(GN, CHI); /* lift CHI mod N before mfcharno*/
10017 651 : nCHI = mfcharno(CHI);
10018 651 : r = QabM_init(ord, &p);
10019 651 : vz = Fl_powers(r, ord, p);
10020 651 : getcols(&M, &vj, k, nCHI, allN, vz, p, lim);
10021 679 : for (ell = k>>1; ell >= 1; ell--)
10022 441 : if (getcolsgen(dim, &M, &vj, &z, k, ell, nCHI, allN, vz, p, lim)) break;
10023 651 : if (!z) update_Mj(&M, &vj, &z, p);
10024 651 : if (lg(vj) - 1 < dim) return NULL;
10025 609 : M = mkM(vj, ord, P, lim);
10026 609 : Minv = QabM_Minv(rowpermute(M, gel(z,1)), P, ord);
10027 609 : return mkvec4(gel(z,1), Minv, vj, utoi(ord));
10028 : }
10029 : /* true mf */
10030 : static GEN
10031 609 : mfeisensteinspaceinit(GEN mf)
10032 : {
10033 609 : pari_sp av = avma;
10034 609 : GEN z, CHI = MF_get_CHI(mf);
10035 609 : long N = MF_get_N(mf), k = MF_get_k(mf);
10036 609 : if (!CHI) CHI = mfchartrivial();
10037 609 : z = mfeisensteinspaceinit_i(N, k, CHI);
10038 609 : if (!z)
10039 : {
10040 35 : GEN E, CHIN = mffindeisen1(N), CHI0 = mfchartrivial();
10041 35 : z = mfeisensteinspaceinit_i(N, k+1, mfcharmul(CHI, CHIN));
10042 35 : if (z) E = mkvec4(gen_1, CHI0, CHIN, gen_1);
10043 : else
10044 : {
10045 7 : z = mfeisensteinspaceinit_i(N, k+2, CHI);
10046 7 : E = mkvec4(gen_2, CHI0, CHI0, utoipos(N));
10047 : }
10048 35 : z = mkvec2(z, E);
10049 : }
10050 609 : return gc_GEN(av, z);
10051 : }
10052 :
10053 : /* decomposition of modular form on eisenspace */
10054 : static GEN
10055 1218 : mfeisensteindec(GEN mf, GEN F)
10056 : {
10057 1218 : pari_sp av = avma;
10058 : GEN M, Mindex, Mvecj, V, B, CHI;
10059 : long o, ord;
10060 :
10061 1218 : Mvecj = obj_checkbuild(mf, MF_EISENSPACE, &mfeisensteinspaceinit);
10062 1218 : if (lg(Mvecj) < 5)
10063 : {
10064 56 : GEN E, e = gel(Mvecj,2), gkE = gel(e,1);
10065 56 : long dE = itou(gel(e,4));
10066 56 : Mvecj = gel(Mvecj,1);
10067 56 : E = mfeisenstein(itou(gkE), NULL, gel(e,3));
10068 56 : if (dE != 1) E = mfbd_E2(E, dE, gel(e,2)); /* here k = 2 */
10069 56 : F = mfmul(F, E);
10070 : }
10071 1218 : M = gel(Mvecj, 2);
10072 1218 : if (lg(M) == 1) return cgetg(1, t_VEC);
10073 1218 : Mindex = gel(Mvecj, 1);
10074 1218 : ord = itou(gel(Mvecj,4));
10075 1218 : V = mfcoefs(F, Mindex[lg(Mindex)-1]-1, 1); settyp(V, t_COL);
10076 1218 : CHI = mf_get_CHI(F);
10077 1218 : o = mfcharorder(CHI);
10078 1218 : if (o > 2 && o != ord)
10079 : { /* convert Mod(.,polcyclo(o)) to Mod(., polcyclo(N)) for o | N,
10080 : * o and N both != 2 (mod 4) */
10081 84 : GEN z, P = gel(M,4); /* polcyclo(ord) */
10082 84 : long vt = varn(P);
10083 84 : z = gmodulo(pol_xn(ord/o, vt), P);
10084 84 : if (ord % o) pari_err_TYPE("mfeisensteindec", V);
10085 84 : V = gsubst(liftpol_shallow(V), vt, z);
10086 : }
10087 1218 : B = Minv_RgC_mul(M, vecpermute(V, Mindex));
10088 1218 : return gc_upto(av, B);
10089 : }
10090 :
10091 : /*********************************************************************/
10092 : /* END EISENSPACE */
10093 : /*********************************************************************/
10094 :
10095 : static GEN
10096 70 : sertocol2(GEN S, long l)
10097 : {
10098 70 : GEN C = cgetg(l + 2, t_COL);
10099 : long i;
10100 420 : for (i = 0; i <= l; i++) gel(C, i+1) = polcoef_i(S, i, -1);
10101 70 : return C;
10102 : }
10103 :
10104 : /* Compute polynomial P0 such that F=E4^(k/4)P0(E6/E4^(3/2)). */
10105 : static GEN
10106 14 : mfcanfindp0(GEN F, long k)
10107 : {
10108 14 : pari_sp ltop = avma;
10109 : GEN E4, E6, V, V1, Q, W, res, M, B;
10110 : long l, j;
10111 14 : l = k/6 + 2;
10112 14 : V = mfcoefsser(F,l);
10113 14 : E4 = mfcoefsser(mfEk(4),l);
10114 14 : E6 = mfcoefsser(mfEk(6),l);
10115 14 : V1 = gdiv(V, gpow(E4, uutoQ(k,4), 0));
10116 14 : Q = gdiv(E6, gpow(E4, uutoQ(3,2), 0));
10117 14 : W = gpowers(Q, l - 1);
10118 14 : M = cgetg(l + 1, t_MAT);
10119 70 : for (j = 1; j <= l; j++) gel(M,j) = sertocol2(gel(W,j), l);
10120 14 : B = sertocol2(V1, l);
10121 14 : res = inverseimage(M, B);
10122 14 : if (lg(res) == 1) err_space(F);
10123 14 : return gc_GEN(ltop, gtopolyrev(res, 0));
10124 : }
10125 :
10126 : /* Compute the first n+1 Taylor coeffs at tau=I of a modular form
10127 : * on SL_2(Z). */
10128 : GEN
10129 14 : mftaylor(GEN F, long n, long flreal, long prec)
10130 : {
10131 14 : pari_sp ltop = avma;
10132 14 : GEN P0, Pm1 = gen_0, v;
10133 14 : GEN X2 = mkpoln(3, ghalf,gen_0,gneg(ghalf)); /* (x^2-1) / 2 */
10134 : long k, m;
10135 14 : if (!checkmf_i(F)) pari_err_TYPE("mftaylor",F);
10136 14 : k = mf_get_k(F);
10137 14 : if (mf_get_N(F) != 1 || k < 0) pari_err_IMPL("mftaylor for this form");
10138 14 : P0 = mfcanfindp0(F, k);
10139 14 : v = cgetg(n+2, t_VEC); gel(v, 1) = RgX_coeff(P0,0);
10140 154 : for (m = 0; m < n; m++)
10141 : {
10142 140 : GEN P1 = gdivgu(gmulsg(-(k + 2*m), RgX_shift(P0,1)), 12);
10143 140 : P1 = gadd(P1, gmul(X2, RgX_deriv(P0)));
10144 140 : if (m) P1 = gsub(P1, gdivgu(gmulsg(m*(m+k-1), Pm1), 144));
10145 140 : Pm1 = P0; P0 = P1;
10146 140 : gel(v, m+2) = RgX_coeff(P0, 0);
10147 : }
10148 14 : if (flreal)
10149 : {
10150 7 : GEN pi2 = Pi2n(1, prec), pim4 = gmulsg(-2, pi2), VPC;
10151 7 : GEN C = gmulsg(3, gdiv(gpowgs(ggamma(uutoQ(1,4), prec), 8), gpowgs(pi2, 6)));
10152 : /* E_4(i): */
10153 7 : GEN facn = gen_1;
10154 7 : VPC = gpowers(gmul(pim4, gsqrt(C, prec)), n);
10155 7 : C = gpow(C, uutoQ(k,4), prec);
10156 84 : for (m = 0; m <= n; m++)
10157 : {
10158 77 : gel(v, m+1) = gdiv(gmul(C, gmul(gel(v, m+1), gel(VPC, m+1))), facn);
10159 77 : facn = gmulgu(facn, m+1);
10160 : }
10161 : }
10162 14 : return gc_GEN(ltop, v);
10163 : }
10164 :
10165 : #if 0
10166 : /* To be used in mfeigensearch() */
10167 : GEN
10168 : mfreadratfile()
10169 : {
10170 : GEN eqn;
10171 : pariFILE *F = pari_fopengz("rateigen300.gp");
10172 : eqn = gp_readvec_stream(F->file);
10173 : pari_fclose(F);
10174 : return eqn;
10175 : }
10176 : #endif
10177 : /*****************************************************************/
10178 : /* EISENSTEIN CUSPS: COMPLEX DIRECTLY: one F_k */
10179 : /*****************************************************************/
10180 :
10181 : /* CHIvec = charinit(CHI); data = [N1g/g1,N2g/g2,g1/g,g2/g,C/g1,C/g2,
10182 : * (N1g/g1)^{-1},(N2g/g2)^{-1}] */
10183 :
10184 : /* nm = n/m;
10185 : * z1 = powers of \z_{C/g}^{(Ae/g)^{-1}},
10186 : * z2 = powers of \z_N^{A^{-1}(g1g2/C)}]
10187 : * N.B. : we compute value and conjugate at the end, so it is (Ae/g)^{-1}
10188 : * and not -(Ae/g)^{-1} */
10189 : static GEN
10190 9635178 : eiscnm(long nm, long m, GEN CHI1vec, GEN CHI2vec, GEN data, GEN z1)
10191 : {
10192 9635178 : long Cg1 = data[5], s10 = (nm*data[7]) % Cg1, r10 = (nm - data[1]*s10) / Cg1;
10193 9635178 : long Cg2 = data[6], s20 = (m *data[8]) % Cg2, r20 = (m - data[2]*s20) / Cg2;
10194 : long j1, r1, s1;
10195 9635178 : GEN T = gen_0;
10196 22465660 : for (j1 = 0, r1 = r10, s1 = s10; j1 < data[3]; j1++, r1 -= data[1], s1 += Cg1)
10197 : {
10198 12830482 : GEN c1 = mychareval(CHI1vec, r1);
10199 12830482 : if (!gequal0(c1))
10200 : {
10201 : long j2, r2, s2;
10202 9925790 : GEN S = gen_0;
10203 24733030 : for (j2 = 0, r2 = r20, s2 = s20; j2 < data[4]; j2++, r2 -= data[2], s2 += Cg2)
10204 : {
10205 14807240 : GEN c2 = mychareval(CHI2vec, r2);
10206 14807240 : if (!gequal0(c2)) S = gadd(S, gmul(c2, rootsof1pow(z1, s1*s2)));
10207 : }
10208 9925790 : T = gadd(T, gmul(c1, S));
10209 : }
10210 : }
10211 9635178 : return conj_i(T);
10212 : }
10213 :
10214 : static GEN
10215 855267 : fg1g2n(long n, long k, GEN CHI1vec, GEN CHI2vec, GEN data, GEN z1, GEN z2)
10216 : {
10217 855267 : pari_sp av = avma;
10218 855267 : GEN S = gen_0, D = mydivisorsu(n);
10219 855267 : long i, l = lg(D);
10220 5672856 : for (i = 1; i < l; i++)
10221 : {
10222 4817589 : long m = D[i], nm = D[l-i]; /* n/m */
10223 4817589 : GEN u = eiscnm( nm, m, CHI1vec, CHI2vec, data, z1);
10224 4817589 : GEN v = eiscnm(-nm, -m, CHI1vec, CHI2vec, data, z1);
10225 4817589 : GEN w = odd(k) ? gsub(u, v) : gadd(u, v);
10226 4817589 : S = gadd(S, gmul(powuu(m, k-1), w));
10227 : }
10228 855267 : return gc_upto(av, gmul(S, rootsof1pow(z2, n)));
10229 : }
10230 :
10231 : static GEN
10232 33985 : gausssumcx(GEN CHIvec, long prec)
10233 : {
10234 : GEN z, S, V;
10235 33985 : long m, N = CHIvec_N(CHIvec);
10236 33985 : if (N == 1) return gen_1;
10237 18277 : V = CHIvec_val(CHIvec);
10238 18277 : z = rootsof1u_cx(N, prec);
10239 18277 : S = gmul(z, gel(V, N));
10240 431158 : for (m = N-1; m >= 1; m--) S = gmul(z, gadd(gel(V, m), S));
10241 18277 : return S;
10242 : }
10243 :
10244 : /* Computation of Q_k(\z_N^s) as a polynomial in \z_N^s. FIXME: explicit
10245 : * formula ? */
10246 : static GEN
10247 6118 : mfqk(long k, long N)
10248 : {
10249 : GEN X, P, ZI, Q, Xm1, invden;
10250 : long i;
10251 6118 : ZI = gdivgu(RgX_shift_shallow(RgV_to_RgX(identity_ZV(N-1), 0), 1), N);
10252 6118 : if (k == 1) return ZI;
10253 4956 : P = gsubgs(pol_xn(N,0), 1);
10254 4956 : invden = RgXQ_powu(ZI, k, P);
10255 4956 : X = pol_x(0); Q = gneg(X); Xm1 = gsubgs(X, 1);
10256 21784 : for (i = 2; i < k; i++)
10257 16828 : Q = RgX_shift_shallow(ZX_add(gmul(Xm1, ZX_deriv(Q)), gmulsg(-i, Q)), 1);
10258 4956 : return RgXQ_mul(Q, invden, P);
10259 : }
10260 :
10261 : /* CHI mfchar; M is a multiple of the conductor of CHI, but is NOT
10262 : * necessarily its modulus */
10263 : static GEN
10264 7903 : mfskcx(long k, GEN CHI, long M, long prec)
10265 : {
10266 : GEN S, CHIvec, P;
10267 : long F, m, i, l;
10268 7903 : CHI = mfchartoprimitive(CHI, &F);
10269 7903 : CHIvec = mfcharcxinit(CHI, prec);
10270 7903 : if (F == 1) S = gdivgu(bernfrac(k), k);
10271 : else
10272 : {
10273 6118 : GEN Q = mfqk(k, F), V = CHIvec_val(CHIvec);
10274 6118 : S = gmul(gel(V, F), RgX_coeff(Q, 0));
10275 156611 : for (m = 1; m < F; m++) S = gadd(S, gmul(gel(V, m), RgX_coeff(Q, m)));
10276 6118 : S = conj_i(S);
10277 : }
10278 : /* prime divisors of M not dividing f(chi) */
10279 7903 : P = gel(myfactoru(u_ppo(M/F,F)), 1); l = lg(P);
10280 8057 : for (i = 1; i < l; i++)
10281 : {
10282 154 : long p = P[i];
10283 154 : S = gmul(S, gsubsg(1, gdiv(mychareval(CHIvec, p), powuu(p, k))));
10284 : }
10285 7903 : return gmul(gmul(gausssumcx(CHIvec, prec), S), powuu(M/F, k));
10286 : }
10287 :
10288 : static GEN
10289 13727 : f00_i(long k, GEN CHI1vec, GEN CHI2vec, GEN G2, GEN S, long prec)
10290 : {
10291 : GEN c, a;
10292 13727 : long N1 = CHIvec_N(CHI1vec), N2 = CHIvec_N(CHI2vec);
10293 13727 : if (S[2] != N1) return gen_0;
10294 7903 : c = mychareval(CHI1vec, S[3]);
10295 7903 : if (isintzero(c)) return gen_0;
10296 7903 : a = mfskcx(k, mfchardiv(CHIvec_CHI(CHI2vec), CHIvec_CHI(CHI1vec)), N1*N2, prec);
10297 7903 : a = gmul(a, conj_i(gmul(c,G2)));
10298 7903 : return gdiv(a, mulsi(-N2, powuu(S[1], k-1)));
10299 : }
10300 :
10301 : static GEN
10302 12446 : f00(long k, GEN CHI1vec,GEN CHI2vec, GEN G1,GEN G2, GEN data, long prec)
10303 : {
10304 : GEN T1, T2;
10305 12446 : T2 = f00_i(k, CHI1vec, CHI2vec, G2, data, prec);
10306 12446 : if (k > 1) return T2;
10307 1281 : T1 = f00_i(k, CHI2vec, CHI1vec, G1, data, prec);
10308 1281 : return gadd(T1, T2);
10309 : }
10310 :
10311 : /* ga in SL_2(Z), find beta [a,b;c,d] in Gamma_0(N) and mu in Z such that
10312 : * beta * ga * T^u = [A',B';C',D'] with C' | N and N | B', C' > 0 */
10313 : static void
10314 13041 : mfgatogap(GEN ga, long N, long *pA, long *pC, long *pD, long *pd, long *pmu)
10315 : {
10316 13041 : GEN A = gcoeff(ga,1,1), B = gcoeff(ga,1,2);
10317 13041 : GEN C = gcoeff(ga,2,1), D = gcoeff(ga,2,2), a, b, c, d;
10318 : long t, Ap, Cp, B1, D1, mu;
10319 13041 : Cp = itou(bezout(muliu(A,N), C, &c, &d)); /* divides N */
10320 13041 : t = 0;
10321 13041 : if (Cp > 1)
10322 : { /* (d, N/Cp) = 1, find t such that (d - t*(A*N/Cp), N) = 1 */
10323 2604 : long dN = umodiu(d,Cp), Q = (N/Cp * umodiu(A,Cp)) % Cp;
10324 2989 : while (ugcd(dN, Cp) > 1) { t++; dN = Fl_sub(dN, Q, Cp); }
10325 : }
10326 13041 : if (t)
10327 : {
10328 385 : c = addii(c, mului(t, diviuexact(C,Cp)));
10329 385 : d = subii(d, mului(t, muliu(A, N/Cp))); /* (d,N) = 1 */
10330 : }
10331 13041 : D1 = umodiu(mulii(d,D), N);
10332 13041 : (void)bezout(d, mulis(c,-N), &a, &b); /* = 1 */
10333 13041 : t = 0; Ap = umodiu(addii(mulii(a,A), mulii(b,C)), N); /* (Ap,Cp) = 1 */
10334 22267 : while (ugcd(Ap, N) > 1) { t++; Ap = Fl_add(Ap, Cp, N); }
10335 13041 : B1 = umodiu(a,N)*umodiu(B,N) + umodiu(b,N)*umodiu(D,N) + t*D1;
10336 13041 : B1 %= N;
10337 13041 : *pmu = mu = Fl_neg(Fl_div(B1, Ap, N), N);
10338 : /* A', D' and d only needed modulo N */
10339 13041 : *pd = umodiu(d, N);
10340 13041 : *pA = Ap;
10341 13041 : *pC = Cp; *pD = (D1 + Cp*mu) % N;
10342 13041 : }
10343 :
10344 : #if 0
10345 : /* CHI is a mfchar, return alpha(CHI) */
10346 : static long
10347 : mfalchi(GEN CHI, long AN, long cg)
10348 : {
10349 : GEN G = gel(CHI,1), chi = gel(CHI,2), go = gmfcharorder(CHI);
10350 : long o = itou(go), a = itos( znchareval(G, chi, stoi(1 + AN/cg), go) );
10351 : if (a < 0 || (cg * a) % o) pari_err_BUG("mfalchi");
10352 : return (cg * a) / o;
10353 : }
10354 : #endif
10355 : /* return A such that CHI1(t) * CHI2(t) = e(A) or NULL if (t,N1*N2) > 1 */
10356 : static GEN
10357 26082 : mfcharmuleval(GEN CHI1vec, GEN CHI2vec, long t)
10358 : {
10359 26082 : long a1 = mycharexpo(CHI1vec, t), o1 = CHIvec_ord(CHI1vec);
10360 26082 : long a2 = mycharexpo(CHI2vec, t), o2 = CHIvec_ord(CHI2vec);;
10361 26082 : if (a1 < 0 || a2 < 0) return NULL;
10362 26082 : return sstoQ(a1*o2 + a2*o1, o1*o2);
10363 : }
10364 : static GEN
10365 13041 : mfcharmulcxeval(GEN CHI1vec, GEN CHI2vec, long t, long prec)
10366 : {
10367 13041 : GEN A = mfcharmuleval(CHI1vec, CHI2vec, t);
10368 : long n, d;
10369 13041 : if (!A) return gen_0;
10370 13041 : Qtoss(A, &n,&d); return rootsof1q_cx(n, d, prec);
10371 : }
10372 : /* alpha(CHI1 * CHI2) */
10373 : static long
10374 13041 : mfalchi2(GEN CHI1vec, GEN CHI2vec, long AN, long cg)
10375 : {
10376 13041 : GEN A = mfcharmuleval(CHI1vec, CHI2vec, 1 + AN/cg);
10377 : long a;
10378 13041 : if (!A) pari_err_BUG("mfalchi2");
10379 13041 : A = gmulsg(cg, A);
10380 13041 : if (typ(A) != t_INT) pari_err_BUG("mfalchi2");
10381 13041 : a = itos(A) % cg; if (a < 0) a += cg;
10382 13041 : return a;
10383 : }
10384 :
10385 : /* return g = (a,b), set u >= 0 s.t. g = a * u (mod b) */
10386 : static long
10387 52164 : mybezout(long a, long b, long *pu)
10388 : {
10389 52164 : long junk, g = cbezout(a, b, pu, &junk);
10390 52164 : if (*pu < 0) *pu += b/g;
10391 52164 : return g;
10392 : }
10393 :
10394 : /* E = [k, CHI1,CHI2, e], CHI1 and CHI2 primitive mfchars such that,
10395 : * CHI1(-1)*CHI2(-1) = (-1)^k; expansion of (B_e (E_k(CHI1,CHI2))) | ga.
10396 : * w is the width for the space of the calling function. */
10397 : static GEN
10398 13041 : mfeisensteingacx(GEN E, long w, GEN ga, long lim, long prec)
10399 : {
10400 13041 : GEN CHI1vec, CHI2vec, CHI1 = gel(E,2), CHI2 = gel(E,3), v, S, ALPHA;
10401 : GEN G1, G2, z1, z2, data;
10402 13041 : long k = itou(gel(E,1)), e = itou(gel(E,4));
10403 13041 : long N1 = mfcharmodulus(CHI1);
10404 13041 : long N2 = mfcharmodulus(CHI2), N = e * N1 * N2;
10405 : long NsurC, cg, wN, A, C, Ai, d, mu, alchi, na, da;
10406 : long eg, g, gH, U, u0, u1, u2, Aig, H, m, n, t, Cg, NC1, NC2;
10407 :
10408 13041 : mfgatogap(ga, N, &A, &C, &Ai, &d, &mu);
10409 13041 : CHI1vec = mfcharcxinit(CHI1, prec);
10410 13041 : CHI2vec = mfcharcxinit(CHI2, prec);
10411 13041 : NsurC = N/C; cg = ugcd(C, NsurC); wN = NsurC / cg;
10412 13041 : if (w%wN) pari_err_BUG("mfeisensteingacx [wN does not divide w]");
10413 13041 : alchi = mfalchi2(CHI1vec, CHI2vec, A*N, cg);
10414 13041 : ALPHA = sstoQ(alchi, NsurC);
10415 :
10416 13041 : g = mybezout(A*e, C, &u0); Cg = C/g; eg = e/g;
10417 13041 : NC1 = mybezout(N1, Cg, &u1);
10418 13041 : NC2 = mybezout(N2, Cg, &u2);
10419 13041 : H = (NC1*NC2*g)/Cg;
10420 13041 : Aig = (Ai*H)%N; if (Aig < 0) Aig += N;
10421 13041 : z1 = rootsof1powinit(u0, Cg, prec);
10422 13041 : z2 = rootsof1powinit(Aig, N, prec);
10423 13041 : data = mkvecsmalln(8, N1/NC1, N2/NC2, NC1, NC2, Cg/NC1, Cg/NC2, u1, u2);
10424 13041 : v = zerovec(lim + 1);
10425 : /* need n*H = alchi (mod cg) */
10426 13041 : gH = mybezout(H, cg, &U);
10427 13041 : if (gH > 1)
10428 : {
10429 511 : if (alchi % gH) return mkvec2(gen_0, v);
10430 511 : alchi /= gH; cg /= gH; H /= gH;
10431 : }
10432 13041 : G1 = gausssumcx(CHI1vec, prec);
10433 13041 : G2 = gausssumcx(CHI2vec, prec);
10434 13041 : if (!alchi)
10435 12446 : gel(v,1) = f00(k, CHI1vec,CHI2vec,G1,G2, mkvecsmall3(NC2,Cg,A*eg), prec);
10436 13041 : n = Fl_mul(alchi,U,cg); if (!n) n = cg;
10437 13041 : m = (n*H - alchi) / cg; /* positive, exact division */
10438 868308 : for (; m <= lim; n+=cg, m+=H)
10439 855267 : gel(v, m+1) = fg1g2n(n, k, CHI1vec, CHI2vec, data, z1,z2);
10440 13041 : t = (2*e)/g; if (odd(k)) t = -t;
10441 13041 : v = gdiv(v, gmul(conj_i(gmul(G1,G2)), mulsi(t, powuu(eg*N2/NC2, k-1))));
10442 13041 : if (k == 2 && N1 == 1 && N2 == 1) v = gsub(mkF2bd(wN,lim), gmulsg(e,v));
10443 :
10444 13041 : Qtoss(ALPHA, &na,&da);
10445 13041 : S = conj_i( mfcharmulcxeval(CHI1vec,CHI2vec,d,prec) ); /* CHI(1/d) */
10446 13041 : if (wN > 1)
10447 : {
10448 11354 : GEN z = rootsof1powinit(-mu, wN, prec);
10449 11354 : long i, l = lg(v);
10450 823739 : for (i = 1; i < l; i++) gel(v,i) = gmul(gel(v,i), rootsof1pow(z,i-1));
10451 : }
10452 13041 : v = RgV_Rg_mul(v, gmul(S, rootsof1q_cx(-mu*na, da, prec)));
10453 13041 : return mkvec2(ALPHA, bdexpand(v, w/wN));
10454 : }
10455 :
10456 : /*****************************************************************/
10457 : /* END EISENSTEIN CUSPS */
10458 : /*****************************************************************/
10459 :
10460 : static GEN
10461 1596 : mfchisimpl(GEN CHI)
10462 : {
10463 : GEN G, chi;
10464 1596 : if (typ(CHI) == t_INT) return CHI;
10465 1596 : G = gel(CHI, 1); chi = gel(CHI, 2);
10466 1596 : switch(mfcharorder(CHI))
10467 : {
10468 1148 : case 1: chi = gen_1; break;
10469 427 : case 2: chi = znchartokronecker(G,chi,1); break;
10470 21 : default:chi = mkintmod(znconreyexp(G,chi), znstar_get_N(G)); break;
10471 : }
10472 1596 : return chi;
10473 : }
10474 :
10475 : GEN
10476 700 : mfparams(GEN F)
10477 : {
10478 700 : pari_sp av = avma;
10479 : GEN z, mf, CHI;
10480 700 : if ((mf = checkMF_i(F)))
10481 : {
10482 14 : long N = MF_get_N(mf);
10483 14 : GEN gk = MF_get_gk(mf);
10484 14 : CHI = MF_get_CHI(mf);
10485 14 : z = mkvec5(utoi(N), gk, CHI, utoi(MF_get_space(mf)), mfcharpol(CHI));
10486 : }
10487 : else
10488 : {
10489 686 : if (!checkmf_i(F)) pari_err_TYPE("mfparams", F);
10490 686 : z = vec_append(mf_get_NK(F), mfcharpol(mf_get_CHI(F)));
10491 : }
10492 700 : gel(z,3) = mfchisimpl(gel(z,3));
10493 700 : return gc_GEN(av, z);
10494 : }
10495 :
10496 : GEN
10497 14 : mfisCM(GEN F)
10498 : {
10499 14 : pari_sp av = avma;
10500 : forprime_t S;
10501 : GEN D, v;
10502 : long N, k, lD, sb, p, i;
10503 14 : if (!checkmf_i(F)) pari_err_TYPE("mfisCM", F);
10504 14 : N = mf_get_N(F);
10505 14 : k = mf_get_k(F); if (N < 0 || k < 0) pari_err_IMPL("mfisCM for this F");
10506 14 : D = mfunram(N, -1);
10507 14 : lD = lg(D);
10508 14 : sb = maxss(mfsturmNk(N, k), 4*N);
10509 14 : v = mfcoefs_i(F, sb, 1);
10510 14 : u_forprime_init(&S, 2, sb);
10511 504 : while ((p = u_forprime_next(&S)))
10512 : {
10513 490 : GEN ap = gel(v, p+1);
10514 490 : if (!gequal0(ap))
10515 406 : for (i = 1; i < lD; i++)
10516 245 : if (kross(D[i], p) == -1) { D = vecsplice(D, i); lD--; }
10517 : }
10518 14 : if (lD == 1) return gc_const(av, gen_0);
10519 14 : if (lD == 2) return gc_stoi(av, D[1]);
10520 7 : if (k > 1) pari_err_BUG("mfisCM");
10521 7 : return gc_upto(av, zv_to_ZV(D));
10522 : }
10523 :
10524 : static long
10525 287 : mfspace_i(GEN mf, GEN F)
10526 : {
10527 : GEN v, vF, gk;
10528 : long n, nE, i, l, s, N;
10529 :
10530 287 : mf = checkMF(mf); s = MF_get_space(mf);
10531 287 : if (!F) return s;
10532 287 : if (!checkmf_i(F)) pari_err_TYPE("mfspace",F);
10533 287 : v = mftobasis(mf, F, 1);
10534 287 : n = lg(v)-1; if (!n) return -1;
10535 224 : nE = lg(MF_get_E(mf))-1;
10536 224 : switch(s)
10537 : {
10538 56 : case mf_NEW: case mf_OLD: case mf_EISEN: return s;
10539 140 : case mf_FULL:
10540 140 : if (mf_get_type(F) == t_MF_THETA) return mf_EISEN;
10541 133 : if (!gequal0(vecslice(v,1,nE)))
10542 63 : return gequal0(vecslice(v,nE+1,n))? mf_EISEN: mf_FULL;
10543 : }
10544 : /* mf is mf_CUSP or mf_FULL, F a cusp form */
10545 98 : gk = mf_get_gk(F);
10546 98 : if (typ(gk) == t_FRAC || equali1(gk)) return mf_CUSP;
10547 84 : vF = mftonew_i(mf, vecslice(v, nE+1, n), &N);
10548 84 : if (N != MF_get_N(mf)) return mf_OLD;
10549 56 : l = lg(vF);
10550 91 : for (i = 1; i < l; i++)
10551 56 : if (itos(gmael(vF,i,1)) != N) return mf_CUSP;
10552 35 : return mf_NEW;
10553 : }
10554 : long
10555 287 : mfspace(GEN mf, GEN F)
10556 287 : { pari_sp av = avma; return gc_long(av, mfspace_i(mf,F)); }
10557 : static GEN
10558 21 : lfunfindchi(GEN ldata, GEN van, long prec)
10559 : {
10560 21 : GEN gN = ldata_get_conductor(ldata), gk = ldata_get_k(ldata);
10561 21 : GEN G = znstar0(gN,1), cyc = znstar_get_conreycyc(G), L, go, vz;
10562 21 : long N = itou(gN), odd = typ(gk) == t_INT && mpodd(gk);
10563 21 : long i, j, o, l, B0 = 2, B = lg(van)-1, bit = 10 - prec2nbits(prec);
10564 :
10565 : /* if van is integral, chi must be trivial */
10566 21 : if (typ(van) == t_VECSMALL) return mfcharGL(G, zerocol(lg(cyc)-1));
10567 14 : L = cyc2elts(cyc); l = lg(L);
10568 42 : for (i = j = 1; i < l; i++)
10569 : {
10570 28 : GEN chi = zc_to_ZC(gel(L,i));
10571 28 : if (zncharisodd(G,chi) == odd) gel(L,j++) = mfcharGL(G,chi);
10572 : }
10573 14 : setlg(L,j); l = j;
10574 14 : if (l <= 2) return gel(L,1);
10575 0 : o = znstar_get_expo(G); go = utoi(o);
10576 0 : vz = grootsof1(o, prec);
10577 : for (;;)
10578 0 : {
10579 : long n;
10580 0 : for (n = B0; n <= B; n++)
10581 : {
10582 : GEN an, r;
10583 : long j;
10584 0 : if (ugcd(n, N) != 1) continue;
10585 0 : an = gel(van,n); if (gexpo(an) < bit) continue;
10586 0 : r = gdiv(an, conj_i(an));
10587 0 : for (i = 1; i < l; i++)
10588 : {
10589 0 : GEN CHI = gel(L,i);
10590 0 : if (gexpo(gsub(r, gel(vz, znchareval_i(CHI,n,go)+1))) > bit)
10591 0 : gel(L,i) = NULL;
10592 : }
10593 0 : for (i = j = 1; i < l; i++)
10594 0 : if (gel(L,i)) gel(L,j++) = gel(L,i);
10595 0 : l = j; setlg(L,l);
10596 0 : if (l == 2) return gel(L,1);
10597 : }
10598 0 : B0 = B+1; B <<= 1;
10599 0 : van = ldata_vecan(ldata_get_an(ldata), B, prec);
10600 : }
10601 : }
10602 :
10603 : GEN
10604 21 : mffromlfun(GEN L, long prec)
10605 : {
10606 21 : pari_sp av = avma;
10607 21 : GEN ldata = lfunmisc_to_ldata_shallow(L), Vga = ldata_get_gammavec(ldata);
10608 21 : GEN van, a0, CHI, NK, gk = ldata_get_k(ldata);
10609 : long N, space;
10610 21 : if (!gequal(Vga, mkvec2(gen_0, gen_1))) pari_err_TYPE("mffromlfun", L);
10611 21 : N = itou(ldata_get_conductor(ldata));
10612 21 : van = ldata_vecan(ldata_get_an(ldata), mfsturmNgk(N,gk) + 2, prec);
10613 21 : CHI = lfunfindchi(ldata, van, prec);
10614 21 : if (typ(van) != t_VEC) van = vecsmall_to_vec_inplace(van);
10615 21 : space = (lg(ldata) == 7)? mf_CUSP: mf_FULL;
10616 21 : a0 = (space == mf_CUSP)? gen_0: gneg(lfun(L, gen_0, prec2nbits(prec)));
10617 21 : NK = mkvec3(utoi(N), gk, mfchisimpl(CHI));
10618 21 : return gc_GEN(av, mkvec3(NK, utoi(space), shallowconcat(a0, van)));
10619 : }
10620 : /*******************************************************************/
10621 : /* */
10622 : /* HALF-INTEGRAL WEIGHT */
10623 : /* */
10624 : /*******************************************************************/
10625 : /* We use the prefix mf2; k represents the weight -1/2, so e.g.
10626 : k = 2 is weight 5/2. N is the level, so 4\mid N, and CHI is the
10627 : character, always even. */
10628 :
10629 : static long
10630 3360 : lamCO(long r, long s, long p)
10631 : {
10632 3360 : if ((s << 1) <= r)
10633 : {
10634 1232 : long rp = r >> 1;
10635 1232 : if (odd(r)) return upowuu(p, rp) << 1;
10636 336 : else return (p + 1)*upowuu(p, rp - 1);
10637 : }
10638 2128 : else return upowuu(p, r - s) << 1;
10639 : }
10640 :
10641 : static int
10642 1568 : condC(GEN faN, GEN valF)
10643 : {
10644 1568 : GEN P = gel(faN, 1), E = gel(faN, 2);
10645 1568 : long l = lg(P), i;
10646 3696 : for (i = 1; i < l; i++)
10647 3024 : if ((P[i] & 3L) == 3)
10648 : {
10649 1120 : long r = E[i];
10650 1120 : if (odd(r) || r < (valF[i] << 1)) return 1;
10651 : }
10652 672 : return 0;
10653 : }
10654 :
10655 : /* returns 2*zetaCO; weight is k + 1/2 */
10656 : static long
10657 3696 : zeta2CO(GEN faN, GEN valF, long r2, long s2, long k)
10658 : {
10659 3696 : if (r2 >= 4) return lamCO(r2, s2, 2) << 1;
10660 2912 : if (r2 == 3) return 6;
10661 1568 : if (condC(faN, valF)) return 4;
10662 672 : if (odd(k)) return s2 ? 3 : 5; else return s2 ? 5: 3;
10663 : }
10664 :
10665 : /* returns 4 times last term in formula */
10666 : static long
10667 3696 : dim22(long N, long F, long k)
10668 : {
10669 3696 : pari_sp av = avma;
10670 3696 : GEN vF, faN = myfactoru(N), P = gel(faN, 1), E = gel(faN, 2);
10671 3696 : long i, D, l = lg(P);
10672 3696 : vF = cgetg(l, t_VECSMALL);
10673 9968 : for (i = 1; i < l; i++) vF[i] = u_lval(F, P[i]);
10674 3696 : D = zeta2CO(faN, vF, E[1], vF[1], k);
10675 6272 : for (i = 2; i < l; i++) D *= lamCO(E[i], vF[i], P[i]);
10676 3696 : return gc_long(av,D);
10677 : }
10678 :
10679 : /* PSI not necessarily primitive, of conductor F */
10680 : static int
10681 13846 : charistotallyeven(GEN PSI, long F)
10682 : {
10683 13846 : pari_sp av = avma;
10684 13846 : GEN P = gel(myfactoru(F), 1);
10685 13846 : GEN G = gel(PSI,1), psi = gel(PSI,2);
10686 : long i;
10687 14350 : for (i = 1; i < lg(P); i++)
10688 : {
10689 532 : GEN psip = znchardecompose(G, psi, utoipos(P[i]));
10690 532 : if (zncharisodd(G, psip)) return gc_bool(av,0);
10691 : }
10692 13818 : return gc_bool(av,1);
10693 : }
10694 :
10695 : static GEN
10696 299775 : get_PSI(GEN CHI, long t)
10697 : {
10698 299775 : long r = t & 3L, t2 = (r == 2 || r == 3) ? t << 2 : t;
10699 299775 : return mfcharmul_i(CHI, induce(gel(CHI,1), utoipos(t2)));
10700 : }
10701 : /* space = mf_CUSP, mf_EISEN or mf_FULL, weight k + 1/2 */
10702 : static long
10703 41363 : mf2dimwt12(long N, GEN CHI, long space)
10704 : {
10705 41363 : pari_sp av = avma;
10706 41363 : GEN D = mydivisorsu(N >> 2);
10707 41363 : long i, l = lg(D), dim3 = 0, dim4 = 0;
10708 :
10709 41363 : CHI = induceN(N, CHI);
10710 341138 : for (i = 1; i < l; i++)
10711 : {
10712 299775 : long rp, t = D[i], Mt = D[l-i];
10713 299775 : GEN PSI = get_PSI(CHI,t);
10714 299775 : rp = mfcharconductor(PSI);
10715 299775 : if (Mt % (rp*rp) == 0) { dim4++; if (charistotallyeven(PSI,rp)) dim3++; }
10716 : }
10717 41363 : set_avma(av);
10718 41363 : switch (space)
10719 : {
10720 40439 : case mf_CUSP: return dim4 - dim3;
10721 462 : case mf_EISEN:return dim3;
10722 462 : case mf_FULL: return dim4;
10723 : }
10724 : return 0; /*LCOV_EXCL_LINE*/
10725 : }
10726 :
10727 : static long
10728 693 : mf2dimwt32(long N, GEN CHI, long F, long space)
10729 : {
10730 : long D;
10731 693 : switch(space)
10732 : {
10733 231 : case mf_CUSP: D = mypsiu(N) - 6*dim22(N, F, 1);
10734 231 : if (D%24) pari_err_BUG("mfdim");
10735 231 : return D/24 + mf2dimwt12(N, CHI, 4);
10736 231 : case mf_FULL: D = mypsiu(N) + 6*dim22(N, F, 0);
10737 231 : if (D%24) pari_err_BUG("mfdim");
10738 231 : return D/24 + mf2dimwt12(N, CHI, 1);
10739 231 : case mf_EISEN: D = dim22(N, F, 0) + dim22(N, F, 1);
10740 231 : if (D & 3L) pari_err_BUG("mfdim");
10741 231 : return (D >> 2) - mf2dimwt12(N, CHI, 3);
10742 : }
10743 : return 0; /*LCOV_EXCL_LINE*/
10744 : }
10745 :
10746 : /* F = conductor(CHI), weight k = r+1/2 */
10747 : static long
10748 43736 : checkmf2(long N, long r, GEN CHI, long F, long space)
10749 : {
10750 43736 : switch(space)
10751 : {
10752 43715 : case mf_FULL: case mf_CUSP: case mf_EISEN: break;
10753 14 : case mf_NEW: case mf_OLD:
10754 14 : pari_err_TYPE("half-integral weight [new/old spaces]", utoi(space));
10755 7 : default:
10756 7 : pari_err_TYPE("half-integral weight [incorrect space]",utoi(space));
10757 : }
10758 43715 : if (N & 3L)
10759 0 : pari_err_DOMAIN("half-integral weight", "N % 4", "!=", gen_0, stoi(N));
10760 43715 : return r >= 0 && mfcharparity(CHI) == 1 && N % F == 0;
10761 : }
10762 :
10763 : /* weight k = r + 1/2 */
10764 : static long
10765 43463 : mf2dim_Nkchi(long N, long r, GEN CHI, ulong space)
10766 : {
10767 43463 : long D, D2, F = mfcharconductor(CHI);
10768 43463 : if (!checkmf2(N, r, CHI, F, space)) return 0;
10769 43442 : if (r == 0) return mf2dimwt12(N, CHI, space);
10770 2772 : if (r == 1) return mf2dimwt32(N, CHI, F, space);
10771 2079 : if (space == mf_EISEN)
10772 : {
10773 693 : D = dim22(N, F, r) + dim22(N, F, 1-r);
10774 693 : if (D & 3L) pari_err_BUG("mfdim");
10775 693 : return D >> 2;
10776 : }
10777 1386 : D2 = space == mf_FULL? dim22(N, F, 1-r): -dim22(N, F, r);
10778 1386 : D = (2*r-1)*mypsiu(N) + 6*D2;
10779 1386 : if (D%24) pari_err_BUG("mfdim");
10780 1386 : return D/24;
10781 : }
10782 :
10783 : /* weight k=r+1/2 */
10784 : static GEN
10785 273 : mf2init_Nkchi(long N, long r, GEN CHI, long space, long flraw)
10786 : {
10787 273 : GEN CHI1, Minv, Minvmat, B, M, gk = gaddsg(r,ghalf);
10788 273 : GEN mf1 = mkvec4(utoi(N),gk,CHI,utoi(space));
10789 : long L;
10790 273 : if (!checkmf2(N, r, CHI, mfcharconductor(CHI), space)) return mfEMPTY(mf1);
10791 273 : if (space==mf_EISEN) pari_err_IMPL("half-integral weight Eisenstein space");
10792 273 : L = mfsturmNgk(N, gk) + 1;
10793 273 : B = mf2basis(N, r, CHI, &CHI1, space);
10794 273 : M = mflineardivtomat(N,B,L); /* defined modulo T = charpol(CHI) */
10795 273 : if (flraw) M = mkvec3(gen_0,gen_0,M);
10796 : else
10797 : {
10798 273 : long o1 = mfcharorder(CHI1), o = mfcharorder(CHI);
10799 273 : M = mfcleanCHI(M, CHI, 0);
10800 273 : Minv = gel(M,2);
10801 273 : Minvmat = RgM_Minv_mul(NULL, Minv); /* mod T */
10802 273 : if (o1 != o)
10803 : {
10804 140 : GEN tr = Qab_trace_init(o, o1, mfcharpol(CHI), mfcharpol(CHI1));
10805 140 : Minvmat = QabM_tracerel(tr, 0, Minvmat);
10806 : }
10807 : /* Minvmat mod T1 = charpol(CHI1) */
10808 273 : B = vecmflineardiv_linear(B, Minvmat);
10809 273 : gel(M,3) = RgM_Minv_mul(gel(M,3), Minv);
10810 273 : gel(M,2) = mkMinv(matid(lg(B)-1), NULL,NULL,NULL);
10811 : }
10812 273 : return mkmf(mf1, cgetg(1,t_VEC), B, gen_0, M);
10813 : }
10814 :
10815 : /**************************************************************************/
10816 : /* Kohnen + space */
10817 : /**************************************************************************/
10818 :
10819 : static GEN
10820 28 : mfkohnenbasis_i(GEN mf, GEN CHI, long eps, long sb)
10821 : {
10822 28 : GEN M = mfcoefs_mf(mf, sb, 1), p, P;
10823 28 : long c, i, n = mfcharorder(CHI), l = sb + 2;
10824 28 : p = cgetg(l, t_VECSMALL);
10825 : /* keep the a_n, n = (2 or 2+eps) mod 4 */
10826 273 : for (i = 3, c = 1; i < l; i+=4) p[c++] = i;
10827 266 : for (i = 3+eps; i < l; i+=4) p[c++] = i;
10828 28 : P = n <= 2? NULL: mfcharpol(CHI);
10829 28 : setlg(p, c);
10830 28 : return QabM_ker(rowpermute(M, p), P, n);
10831 : }
10832 : GEN
10833 28 : mfkohnenbasis(GEN mf)
10834 : {
10835 28 : pari_sp av = avma;
10836 : GEN gk, CHI, CHIP, K;
10837 : long N4, r, eps, sb;
10838 28 : mf = checkMF(mf);
10839 28 : if (MF_get_space(mf) != mf_CUSP)
10840 0 : pari_err_TYPE("mfkohnenbasis [not a cuspidal space", mf);
10841 28 : if (!MF_get_dim(mf)) return cgetg(1, t_MAT);
10842 28 : N4 = MF_get_N(mf) >> 2; gk = MF_get_gk(mf); CHI = MF_get_CHI(mf);
10843 28 : if (typ(gk) == t_INT) pari_err_TYPE("mfkohnenbasis", gk);
10844 28 : r = MF_get_r(mf);
10845 28 : CHIP = mfcharchiliftprim(CHI, N4);
10846 28 : eps = CHIP==CHI? 1: -1;
10847 28 : if (odd(r)) eps = -eps;
10848 28 : if (uissquarefree(N4))
10849 : {
10850 21 : long d = mfdim_Nkchi(N4, 2*r, mfcharpow(CHI, gen_2), mf_CUSP);
10851 21 : sb = mfsturmNgk(N4 << 2, gk) + 1;
10852 21 : K = mfkohnenbasis_i(mf, CHIP, eps, sb);
10853 21 : if (lg(K) - 1 == d) return gc_GEN(av, K);
10854 : }
10855 7 : sb = mfsturmNgk(N4 << 4, gk) + 1;
10856 7 : K = mfkohnenbasis_i(mf, CHIP, eps, sb);
10857 7 : return gc_GEN(av, K);
10858 : }
10859 :
10860 : static GEN
10861 21 : get_Shimura(GEN mf, GEN CHI, GEN vB, long t)
10862 : {
10863 21 : long N = MF_get_N(mf), r = MF_get_k(mf) >> 1;
10864 21 : long i, d = MF_get_dim(mf), sb = mfsturm_mf(mf);
10865 21 : GEN a = cgetg(d+1, t_MAT);
10866 84 : for (i = 1; i <= d; i++)
10867 : {
10868 63 : pari_sp av = avma;
10869 63 : GEN f = c_deflate(sb*sb, t, gel(vB,i));
10870 63 : f = mftobasis_i(mf, RgV_shimura(f, sb, t, N, r, CHI));
10871 63 : gel(a,i) = gc_upto(av, f);
10872 : }
10873 21 : return a;
10874 : }
10875 : static long
10876 35 : QabM_rank(GEN M, GEN P, long n)
10877 : {
10878 35 : GEN z = QabM_indexrank(M, P, n);
10879 35 : return lg(gel(z,2))-1;
10880 : }
10881 : /* discard T[*i] */
10882 : static void
10883 0 : discard_Ti(GEN T, long *i, long *lt)
10884 : {
10885 0 : long j, l = *lt-1;
10886 0 : for (j = *i; j < l; j++) T[j] = T[j+1];
10887 0 : (*i)--; *lt = l;
10888 0 : }
10889 : /* return [mf3, bijection, mfkohnenbasis, codeshi] */
10890 : static GEN
10891 14 : mfkohnenbijection_i(GEN mf)
10892 : {
10893 14 : GEN CHI = MF_get_CHI(mf), K = mfkohnenbasis(mf);
10894 : GEN mres, dMi, Mi, M, C, vB, mf3, SHI, T, P;
10895 14 : long N4 = MF_get_N(mf)>>2, r = MF_get_r(mf), dK = lg(K) - 1;
10896 : long i, c, n, oldr, lt, ltold, sb3, t, limt;
10897 14 : const long MAXlt = 100;
10898 :
10899 14 : mf3 = mfinit_Nkchi(N4, r<<1, mfcharpow(CHI,gen_2), mf_CUSP, 0);
10900 14 : if (MF_get_dim(mf3) != dK)
10901 0 : pari_err_BUG("mfkohnenbijection [different dimensions]");
10902 14 : if (!dK) return mkvec4(mf3, cgetg(1, t_MAT), K, cgetg(1, t_VEC));
10903 14 : CHI = mfcharchiliftprim(CHI, N4);
10904 14 : n = mfcharorder(CHI);
10905 14 : P = n<=2? NULL: mfcharpol(CHI);
10906 14 : SHI = cgetg(MAXlt, t_COL);
10907 14 : T = cgetg(MAXlt, t_VECSMALL);
10908 14 : sb3 = mfsturm_mf(mf3);
10909 14 : limt = 6; oldr = 0; vB = C = M = NULL;
10910 98 : for (t = lt = ltold = 1; lt < MAXlt; t++)
10911 : {
10912 : pari_sp av;
10913 98 : if (!uissquarefree(t)) continue;
10914 84 : T[lt++] = t; if (t <= limt) continue;
10915 14 : av = avma;
10916 14 : if (vB) gunclone(vB);
10917 : /* could improve the rest but 99% of running time is spent here */
10918 14 : vB = gclone( RgM_mul(mfcoefs_mf(mf, t*sb3*sb3, 1), K) );
10919 14 : set_avma(av);
10920 21 : for (i = ltold; i < lt; i++)
10921 : {
10922 : pari_sp av;
10923 : long r;
10924 21 : M = get_Shimura(mf3, CHI, vB, T[i]);
10925 21 : r = QabM_rank(M, P, n); if (!r) { discard_Ti(T, &i, <); continue; }
10926 21 : gel(SHI, i) = M; setlg(SHI, i+1);
10927 21 : if (r >= dK) { C = vecsmall_ei(dK, i); goto DONE; }
10928 14 : if (i == 1) { oldr = r; continue; }
10929 7 : av = avma; M = shallowmatconcat(SHI);
10930 7 : r = QabM_rank(M, P, n); /* >= rank(sum C[j] SHI[j]), probably sharp */
10931 7 : if (r >= dK)
10932 : {
10933 7 : M = RgV_sum(SHI);
10934 7 : if (QabM_rank(M, P, n) >= dK) { C = const_vecsmall(dK, 1); goto DONE; }
10935 0 : C = random_Flv(dK, 16);
10936 0 : M = RgV_zc_mul(SHI, C);
10937 0 : if (QabM_rank(M, P, n) >= dK) goto DONE;
10938 : }
10939 0 : else if (r == oldr) discard_Ti(T, &i, <);
10940 0 : oldr = r; set_avma(av);
10941 : }
10942 0 : limt *= 2; ltold = lt;
10943 : }
10944 0 : pari_err_BUG("mfkohnenbijection");
10945 14 : DONE:
10946 14 : gunclone(vB); lt = lg(SHI);
10947 14 : Mi = QabM_pseudoinv(M,P,n, NULL,&dMi); Mi = RgM_Rg_div(Mi,dMi);
10948 14 : mres = cgetg(lt, t_VEC);
10949 35 : for (i = c = 1; i < lt; i++)
10950 21 : if (C[i]) gel(mres,c++) = mkvec2s(T[i], C[i]);
10951 14 : setlg(mres,c); return mkvec4(mf3, Mi, K, mres);
10952 : }
10953 : GEN
10954 14 : mfkohnenbijection(GEN mf)
10955 : {
10956 14 : pari_sp av = avma;
10957 : long N;
10958 14 : mf = checkMF(mf); N = MF_get_N(mf);
10959 14 : if (!uissquarefree(N >> 2))
10960 0 : pari_err_TYPE("mfkohnenbijection [N/4 not squarefree]", utoi(N));
10961 14 : if (MF_get_space(mf) != mf_CUSP || MF_get_r(mf) == 0 || !mfshimura_space_cusp(mf))
10962 0 : pari_err_TYPE("mfkohnenbijection [incorrect mf for Kohnen]", mf);
10963 14 : return gc_GEN(av, mfkohnenbijection_i(mf));
10964 : }
10965 :
10966 : static int
10967 7 : checkbij_i(GEN b)
10968 : {
10969 7 : return typ(b) == t_VEC && lg(b) == 5 && checkMF_i(gel(b,1))
10970 7 : && typ(gel(b,2)) == t_MAT
10971 7 : && typ(gel(b,3)) == t_MAT
10972 14 : && typ(gel(b,4)) == t_VEC;
10973 : }
10974 :
10975 : /* bij is the output of mfkohnenbijection */
10976 : GEN
10977 7 : mfkohneneigenbasis(GEN mf, GEN bij)
10978 : {
10979 7 : pari_sp av = avma;
10980 : GEN mf3, mf30, B, KM, M, k;
10981 : long r, i, l, N4;
10982 7 : mf = checkMF(mf);
10983 7 : if (!checkbij_i(bij))
10984 0 : pari_err_TYPE("mfkohneneigenbasis [bijection]", bij);
10985 7 : if (MF_get_space(mf) != mf_CUSP)
10986 0 : pari_err_TYPE("mfkohneneigenbasis [not a cuspidal space]", mf);
10987 7 : if (!MF_get_dim(mf))
10988 0 : retmkvec3(cgetg(1, t_VEC), cgetg(1, t_VEC), cgetg(1, t_VEC));
10989 7 : N4 = MF_get_N(mf) >> 2; k = MF_get_gk(mf);
10990 7 : if (typ(k) == t_INT) pari_err_TYPE("mfkohneneigenbasis", k);
10991 7 : if (!uissquarefree(N4))
10992 0 : pari_err_TYPE("mfkohneneigenbasis [N not squarefree]", utoipos(N4));
10993 7 : r = MF_get_r(mf);
10994 7 : KM = RgM_mul(gel(bij,3), gel(bij,2));
10995 7 : mf3 = gel(bij,1);
10996 7 : mf30 = mfinit_Nkchi(N4, 2*r, MF_get_CHI(mf3), mf_NEW, 0);
10997 7 : B = mfcoefs_mf(mf30, mfsturm_mf(mf3), 1); l = lg(B);
10998 7 : M = cgetg(l, t_MAT);
10999 21 : for (i=1; i<l; i++) gel(M,i) = RgM_RgC_mul(KM, mftobasis_i(mf3, gel(B,i)));
11000 7 : return gc_GEN(av, mkvec3(mf30, M, RgM_mul(M, MF_get_newforms(mf30))));
11001 : }
11002 : /*************************** End Kohnen ************************************/
11003 : /***************************************************************************/
11004 :
11005 : static GEN desc(GEN F);
11006 : static GEN
11007 504 : desc_mfeisen(GEN F)
11008 : {
11009 504 : GEN R, gk = mf_get_gk(F);
11010 504 : if (typ(gk) == t_FRAC)
11011 7 : R = gsprintf("H_{%Ps}", gk);
11012 : else
11013 : {
11014 497 : GEN vchi = gel(F, 2), CHI = mfchisimpl(gel(vchi, 3));
11015 497 : long k = itou(gk);
11016 497 : if (lg(vchi) < 5) R = gsprintf("F_%ld(%Ps)", k, CHI);
11017 : else
11018 : {
11019 294 : GEN CHI2 = mfchisimpl(gel(vchi, 4));
11020 294 : R = gsprintf("F_%ld(%Ps, %Ps)", k, CHI, CHI2);
11021 : }
11022 : }
11023 504 : return R;
11024 : }
11025 : static GEN
11026 35 : desc_hecke(GEN F)
11027 : {
11028 : long n, N;
11029 35 : GEN D = gel(F,2);
11030 35 : if (typ(D) == t_VECSMALL) { N = D[3]; n = D[1]; }
11031 14 : else { GEN nN = gel(D,2); n = nN[1]; N = nN[2]; } /* half integer */
11032 35 : return gsprintf("T_%ld(%ld)(%Ps)", N, n, desc(gel(F,3)));
11033 : }
11034 : static GEN
11035 98 : desc_linear(GEN FLD, GEN dL)
11036 : {
11037 98 : GEN F = gel(FLD,2), L = gel(FLD,3), R = strtoGENstr("LIN([");
11038 98 : long n = lg(F) - 1, i;
11039 168 : for (i = 1; i <= n; i++)
11040 : {
11041 168 : R = shallowconcat(R, desc(gel(F,i))); if (i == n) break;
11042 70 : R = shallowconcat(R, strtoGENstr(", "));
11043 : }
11044 98 : return shallowconcat(R, gsprintf("], %Ps)", gdiv(L, dL)));
11045 : }
11046 : static GEN
11047 21 : desc_dihedral(GEN F)
11048 : {
11049 21 : GEN bnr = gel(F,2), D = nf_get_disc(bnr_get_nf(bnr)), f = bnr_get_mod(bnr);
11050 21 : GEN cyc = bnr_get_cyc(bnr);
11051 21 : GEN w = gel(F,3), chin = zv_to_ZV(gel(w,2)), o = utoi(gel(w,1)[1]);
11052 21 : GEN chi = char_denormalize(cyc, o, chin);
11053 21 : if (lg(gel(f,2)) == 1) f = gel(f,1);
11054 21 : return gsprintf("DIH(%Ps, %Ps, %Ps, %Ps)",D,f,cyc,chi);
11055 : }
11056 :
11057 : static void
11058 1043 : unpack0(GEN *U)
11059 1043 : { if (U) *U = mkvec2(cgetg(1, t_VEC), cgetg(1, t_VEC)); }
11060 : static void
11061 42 : unpack2(GEN F, GEN *U)
11062 42 : { if (U) *U = mkvec2(mkvec2(gel(F,2), gel(F,3)), cgetg(1, t_VEC)); }
11063 : static void
11064 308 : unpack23(GEN F, GEN *U)
11065 308 : { if (U) *U = mkvec2(mkvec(gel(F,2)), mkvec(gel(F,3))); }
11066 : static GEN
11067 1540 : desc_i(GEN F, GEN *U)
11068 : {
11069 1540 : switch(mf_get_type(F))
11070 : {
11071 7 : case t_MF_CONST: unpack0(U); return gsprintf("CONST(%Ps)", gel(F,2));
11072 504 : case t_MF_EISEN: unpack0(U); return desc_mfeisen(F);
11073 154 : case t_MF_Ek: unpack0(U); return gsprintf("E_%ld", mf_get_k(F));
11074 63 : case t_MF_DELTA: unpack0(U); return gsprintf("DELTA");
11075 35 : case t_MF_THETA: unpack0(U);
11076 35 : return gsprintf("THETA(%Ps)", mfchisimpl(gel(F,2)));
11077 56 : case t_MF_ETAQUO: unpack0(U);
11078 56 : return gsprintf("ETAQUO(%Ps, %Ps)", gel(F,2), gel(F,3));
11079 56 : case t_MF_ELL: unpack0(U);
11080 56 : return gsprintf("ELL(%Ps)", vecslice(gel(F,2), 1, 5));
11081 7 : case t_MF_TRACE: unpack0(U); return gsprintf("TR(%Ps)", mfparams(F));
11082 140 : case t_MF_NEWTRACE: unpack0(U); return gsprintf("TR^new(%Ps)", mfparams(F));
11083 21 : case t_MF_DIHEDRAL: unpack0(U); return desc_dihedral(F);
11084 28 : case t_MF_MUL: unpack2(F, U);
11085 28 : return gsprintf("MUL(%Ps, %Ps)", desc(gel(F,2)), desc(gel(F,3)));
11086 14 : case t_MF_DIV: unpack2(F, U);
11087 14 : return gsprintf("DIV(%Ps, %Ps)", desc(gel(F,2)), desc(gel(F,3)));
11088 14 : case t_MF_POW: unpack23(F, U);
11089 14 : return gsprintf("POW(%Ps, %ld)", desc(gel(F,2)), itos(gel(F,3)));
11090 14 : case t_MF_SHIFT: unpack23(F, U);
11091 14 : return gsprintf("SHIFT(%Ps, %ld)", desc(gel(F,2)), itos(gel(F,3)));
11092 14 : case t_MF_DERIV: unpack23(F, U);
11093 14 : return gsprintf("DER^%ld(%Ps)", itos(gel(F,3)), desc(gel(F,2)));
11094 21 : case t_MF_DERIVE2: unpack23(F, U);
11095 21 : return gsprintf("DERE2^%ld(%Ps)", itos(gel(F,3)), desc(gel(F,2)));
11096 14 : case t_MF_TWIST: unpack23(F, U);
11097 14 : return gsprintf("TWIST(%Ps, %Ps)", desc(gel(F,2)), gel(F,3));
11098 231 : case t_MF_BD: unpack23(F, U);
11099 231 : return gsprintf("B(%ld)(%Ps)", itou(gel(F,3)), desc(gel(F,2)));
11100 14 : case t_MF_BRACKET:
11101 14 : if (U) *U = mkvec2(mkvec2(gel(F,2), gel(F,3)), mkvec(gel(F,4)));
11102 14 : return gsprintf("MULRC_%ld(%Ps, %Ps)", itos(gel(F,4)), desc(gel(F,2)), desc(gel(F,3)));
11103 98 : case t_MF_LINEAR_BHN:
11104 : case t_MF_LINEAR:
11105 98 : if (U) *U = mkvec2(gel(F,2), mkvec(gdiv(gel(F,3), gel(F,4))));
11106 98 : return desc_linear(F,gel(F,4));
11107 35 : case t_MF_HECKE:
11108 35 : if (U) *U = mkvec2(mkvec(gel(F,3)), mkvec(stoi(gel(F,2)[1])));
11109 35 : return desc_hecke(F);
11110 0 : default: pari_err_TYPE("mfdescribe",F);
11111 : return NULL;/*LCOV_EXCL_LINE*/
11112 : }
11113 : }
11114 : static GEN
11115 623 : desc(GEN F) { return desc_i(F, NULL); }
11116 : GEN
11117 966 : mfdescribe(GEN F, GEN *U)
11118 : {
11119 966 : pari_sp av = avma;
11120 : GEN mf;
11121 966 : if ((mf = checkMF_i(F)))
11122 : {
11123 49 : const char *f = NULL;
11124 49 : switch (MF_get_space(mf))
11125 : {
11126 7 : case mf_NEW: f = "S_%Ps^new(G_0(%ld, %Ps))"; break;
11127 14 : case mf_CUSP: f = "S_%Ps(G_0(%ld, %Ps))"; break;
11128 7 : case mf_OLD: f = "S_%Ps^old(G_0(%ld, %Ps))"; break;
11129 7 : case mf_EISEN:f = "E_%Ps(G_0(%ld, %Ps))"; break;
11130 14 : case mf_FULL: f = "M_%Ps(G_0(%ld, %Ps))"; break;
11131 : }
11132 49 : if (U) *U = cgetg(1, t_VEC);
11133 49 : return gsprintf(f, MF_get_gk(mf), MF_get_N(mf), mfchisimpl(MF_get_CHI(mf)));
11134 : }
11135 917 : if (!checkmf_i(F)) pari_err_TYPE("mfdescribe", F);
11136 917 : F = desc_i(F, U); return gc_all(av, U ? 2: 1, &F, U);
11137 : }
11138 :
11139 : /***********************************************************************/
11140 : /* Eisenstein series H_r of weight r+1/2 */
11141 : /***********************************************************************/
11142 : /* radical(u_ppo(g,q)) */
11143 : static long
11144 28 : u_pporad(long g, long q)
11145 : {
11146 28 : GEN F = myfactoru(g), P = gel(F,1);
11147 : long i, l, n;
11148 28 : if (q == 1) return zv_prod(P);
11149 28 : l = lg(P);
11150 35 : for (i = n = 1; i < l; i++)
11151 : {
11152 7 : long p = P[i];
11153 7 : if (q % p) n *= p;
11154 : }
11155 28 : return n;
11156 : }
11157 : static void
11158 266 : c_F2TH4(long n, GEN *pF2, GEN *pTH4)
11159 : {
11160 266 : GEN v = mfcoefs_i(mfEk(2), n, 1), v2 = bdexpand(v,2), v4 = bdexpand(v,4);
11161 266 : GEN F2 = gdivgs(ZC_add(ZC_sub(v, ZC_z_mul(v2,3)), ZC_z_mul(v4,2)), -24);
11162 266 : GEN TH4 = gdivgs(ZC_sub(v, ZC_z_mul(v4,4)), -3);
11163 266 : settyp(F2,t_VEC); *pF2 = F2;
11164 266 : settyp(TH4,t_VEC);*pTH4= TH4;
11165 266 : }
11166 : /* r > 0, N >= 0 */
11167 : static GEN
11168 77 : mfEHcoef(long r, long N)
11169 : {
11170 : long D0, f, i, l, s;
11171 : GEN S, Df;
11172 :
11173 77 : if (r == 1) return hclassno(utoi(N));
11174 77 : if (N == 0) return gdivgs(bernfrac(2*r), -2*r);
11175 56 : s = N & 3L;
11176 56 : if (odd(r))
11177 : {
11178 42 : if (s == 2 || s == 1) return gen_0;
11179 14 : D0 = mycoredisc2neg(N,&f);
11180 : }
11181 : else
11182 : {
11183 14 : if (s == 2 || s == 3) return gen_0;
11184 14 : D0 = mycoredisc2pos(N,&f);
11185 : }
11186 28 : Df = mydivisorsu(u_pporad(f, D0)); l = lg(Df);
11187 28 : S = gen_0;
11188 63 : for (i = 1; i < l; i++)
11189 : {
11190 35 : long d = Df[i], s = mymoebiusu(d)*kross(D0, d); /* != 0 */
11191 35 : GEN c = gmul(powuu(d, r-1), mysumdivku(f/d, 2*r-1));
11192 35 : S = s > 0? addii(S, c): subii(S, c);
11193 : }
11194 28 : return gmul(lfunquadneg_naive(D0, r), S);
11195 : }
11196 : static GEN
11197 266 : mfEHmat(long lim, long r)
11198 : {
11199 266 : long j, l, d = r/2;
11200 : GEN f2, th4, th3, v, vth4, vf2;
11201 266 : c_F2TH4(lim, &f2, &th4);
11202 266 : f2 = RgV_to_ser(f2, 0, lim+3);
11203 266 : th4 = RgV_to_ser(th4, 0, lim+3);
11204 266 : th3 = RgV_to_ser(c_theta(lim, 1, mfchartrivial()), 0, lim+3);
11205 266 : if (odd(r)) th3 = gpowgs(th3, 3);
11206 266 : vth4 = gpowers(th4, d);
11207 266 : vf2 = gpowers0(f2, d, th3); /* th3 f2^j */
11208 266 : l = d+2; v = cgetg(l, t_VEC);
11209 924 : for (j = 1; j < l; j++)
11210 658 : gel(v, j) = ser2rfrac_i(gmul(gel(vth4, l-j), gel(vf2, j)));
11211 266 : return RgXV_to_RgM(v, lim);
11212 : }
11213 : static GEN
11214 7 : Hfind(long r, GEN *pden)
11215 : {
11216 7 : long lim = (r/2)+3, i;
11217 : GEN res, M, B;
11218 :
11219 7 : if (r <= 0) pari_err_DOMAIN("mfEH", "r", "<=", gen_0, stoi(r));
11220 7 : M = mfEHmat(lim, r);
11221 7 : B = cgetg(lim+1, t_COL);
11222 56 : for (i = 1; i <= lim; i++) gel(B, i) = mfEHcoef(r, i-1);
11223 7 : res = QM_gauss(M, B);
11224 7 : if (lg(res) == 1) pari_err_BUG("mfEH");
11225 7 : return Q_remove_denom(res,pden);
11226 : }
11227 : GEN
11228 266 : mfEH(GEN gk)
11229 : {
11230 266 : pari_sp av = avma;
11231 266 : GEN v, d, NK, gr = gsub(gk, ghalf);
11232 : long r;
11233 266 : if (typ(gr) != t_INT) pari_err_TYPE("mfEH", gk);
11234 266 : r = itos(gr);
11235 266 : switch (r)
11236 : {
11237 7 : case 1: v=cgetg(1,t_VEC); d=gen_1; break;
11238 133 : case 2: v=mkvec2s(1,-20); d=utoipos(120); break;
11239 56 : case 3: v=mkvec2s(-1,14); d=utoipos(252); break;
11240 35 : case 4: v=mkvec3s(1,-16,16); d=utoipos(240); break;
11241 7 : case 5: v=mkvec3s(-1,22,-88); d=utoipos(132); break;
11242 14 : case 6: v=mkvec4s(691,-18096,110136,-4160); d=utoipos(32760); break;
11243 7 : case 7: v=mkvec4s(-1,30,-240,224); d=utoipos(12); break;
11244 7 : default: v = Hfind(r, &d); break;
11245 : }
11246 266 : NK = mkgNK(utoipos(4), gaddgs(ghalf,r), mfchartrivial(), pol_x(1));
11247 266 : return gc_GEN(av, tag(t_MF_EISEN, NK, mkvec2(v,d)));
11248 : }
11249 :
11250 : /**********************************************************/
11251 : /* T(f^2) for half-integral weight */
11252 : /**********************************************************/
11253 :
11254 : /* T_p^2 V, p2 = p^2, c1 = chi(p) (-1/p)^r p^(r-1), c2 = chi(p^2)*p^(2r-1) */
11255 : static GEN
11256 70 : tp2apply(GEN V, long p, long p2, GEN c1, GEN c2)
11257 : {
11258 70 : long lw = (lg(V) - 2)/p2 + 1, m, n;
11259 70 : GEN a0 = gel(V,1), W = cgetg(lw + 1, t_VEC);
11260 :
11261 70 : gel(W,1) = gequal0(a0)? gen_0: gmul(a0, gaddsg(1, c2));
11262 11109 : for (n = 1; n < lw; n++)
11263 : {
11264 11039 : GEN c = gel(V, p2*n + 1);
11265 11039 : if (n%p) c = gadd(c, gmulsg(kross(n,p), gmul(gel(V,n+1), c1)));
11266 11039 : gel(W, n+1) = c; /* a(p^2*n) + c1 * (n/p) a(n) */
11267 : }
11268 1253 : for (m = 1, n = p2; n < lw; m++, n += p2)
11269 1183 : gel(W, n+1) = gadd(gel(W,n+1), gmul(gel(V,m+1), c2));
11270 70 : return W;
11271 : }
11272 :
11273 : /* T_{p^{2e}} V; can derecursify [Purkait, Hecke operators in half-integral
11274 : * weight, Prop 4.3], not worth it */
11275 : static GEN
11276 70 : tp2eapply(GEN V, long p, long p2, long e, GEN q, GEN c1, GEN c2)
11277 : {
11278 70 : GEN V4 = NULL;
11279 70 : if (e > 1)
11280 : {
11281 21 : V4 = vecslice(V, 1, (lg(V) - 2)/(p2*p2) + 1);
11282 21 : V = tp2eapply(V, p, p2, e-1, q, c1, c2);
11283 : }
11284 70 : V = tp2apply(V, p, p2, c1, c2);
11285 70 : if (e > 1)
11286 28 : V = gsub(V, (e == 2)? gmul(q, V4)
11287 7 : : gmul(c2, tp2eapply(V4, p, p2, e-2, q, c1, c2)));
11288 70 : return V;
11289 : }
11290 : /* weight k = r+1/2 */
11291 : static GEN
11292 98 : RgV_heckef2(long n, long d, GEN V, GEN F, GEN DATA)
11293 : {
11294 98 : GEN CHI = mf_get_CHI(F), fa = gel(DATA,1), P = gel(fa,1), E = gel(fa,2);
11295 98 : long i, l = lg(P), r = mf_get_r(F), s4 = odd(r)? -4: 4, k2m2 = (r<<1)-1;
11296 98 : if (typ(V) == t_COL) V = shallowtrans(V);
11297 140 : for (i = 1; i < l; i++)
11298 : { /* p does not divide N */
11299 42 : long p = P[i], e = E[i], p2 = p*p;
11300 42 : GEN c1, c2, a, b, q = NULL, C = mfchareval(CHI,p), C2 = gsqr(C);
11301 42 : a = r? powuu(p,r-1): mkfrac(gen_1,utoipos(p)); /* p^(r-1) = p^(k-3/2) */
11302 42 : b = r? mulii(powuu(p,r), a): a; /* p^(2r-1) = p^(2k-2) */
11303 42 : c1 = gmul(C, gmulsg(kross(s4,p),a));
11304 42 : c2 = gmul(C2, b);
11305 42 : if (e > 1)
11306 : {
11307 14 : q = r? powuu(p,k2m2): a;
11308 14 : if (e == 2) q = gmul(q, uutoQ(p+1,p)); /* special case T_{p^4} */
11309 14 : q = gmul(C2, q); /* chi(p^2) [ p^(2k-2) or (p+1)p^(2k-3) ] */
11310 : }
11311 42 : V = tp2eapply(V, p, p2, e, q, c1, c2);
11312 : }
11313 98 : return c_deflate(n, d, V);
11314 : }
11315 :
11316 : static GEN
11317 1428 : GL2toSL2(GEN g, GEN *abd)
11318 : {
11319 : GEN A, B, C, D, u, v, a, b, d, q;
11320 1428 : g = Q_primpart(g);
11321 1428 : if (!check_M2Z(g)) pari_err_TYPE("GL2toSL2", g);
11322 1428 : A = gcoeff(g,1,1); B = gcoeff(g,1,2);
11323 1428 : C = gcoeff(g,2,1); D = gcoeff(g,2,2);
11324 1428 : a = bezout(A, C, &u, &v);
11325 1428 : if (!equali1(a)) { A = diviiexact(A,a); C = diviiexact(C,a); }
11326 1428 : d = subii(mulii(A,D), mulii(B,C));
11327 1428 : if (signe(d) <= 0) pari_err_TYPE("GL2toSL2",g);
11328 1421 : q = dvmdii(addii(mulii(u,B), mulii(v,D)), d, &b);
11329 1421 : *abd = (equali1(a) && equali1(d))? NULL: mkvec3(a, b, d);
11330 1421 : return mkmat22(A, subii(mulii(q,A), v), C, addii(mulii(q,C), u));
11331 : }
11332 :
11333 : static GEN
11334 8526 : Rg_approx(GEN t, long bit)
11335 : {
11336 8526 : GEN a = real_i(t), b = imag_i(t);
11337 8526 : long ea = gexpo(a), eb = gexpo(b);
11338 2072 : return (eb < -bit)? ((ea < -bit)? gen_0: a)
11339 10598 : : ((ea < -bit)? mulcxI(b): t);
11340 : }
11341 : static GEN
11342 126 : RgV_approx(GEN x, long bit)
11343 840 : { pari_APPLY_same(Rg_approx(gel(x,i), bit)); }
11344 : /* m != 2 (mod 4), D t_INT; V has "denominator" D, recognize in Q(zeta_m) */
11345 : static GEN
11346 126 : bestapprnf2(GEN V, long m, GEN D, long prec)
11347 : {
11348 126 : long i, j, f, vt = fetch_user_var("t"), bit = prec2nbits_mul(prec, 0.8);
11349 126 : GEN Tinit, Vl, H, Pf, P = polcyclo(m, vt);
11350 :
11351 126 : V = liftpol_shallow(V);
11352 126 : V = gmul(RgV_approx(V, bit), D);
11353 126 : V = bestapprnf(V, P, NULL, prec);
11354 126 : Vl = liftpol_shallow(V);
11355 126 : H = coprimes_zv(m);
11356 672 : for (i = 2; i < m; i++)
11357 : {
11358 546 : if (H[i] != 1) continue;
11359 280 : if (!gequal(Vl, vecGalois(Vl, i, P, m))) H[i] = 0;
11360 14 : else for (j = i; j < m; j *= i) H[i] = 3;
11361 : }
11362 126 : f = znstar_conductor_bits(Flv_to_F2v(H));
11363 126 : if (f == 1) return gdiv(V, D);
11364 98 : if (f == m) return gmodulo(gdiv(V, D), P);
11365 7 : Pf = polcyclo(f, vt);
11366 7 : Tinit = Qab_trace_init(m, f, P, Pf);
11367 7 : return gmodulo(gdiv(QabV_tracerel(Tinit, 0, Vl), D), Pf);
11368 : }
11369 :
11370 : /* f | ga expansion; [f, mf_eisendec(f)]~ allowed */
11371 : GEN
11372 1365 : mfslashexpansion(GEN mf, GEN f, GEN ga, long n, long flrat, GEN *params, long prec)
11373 : {
11374 1365 : pari_sp av = avma;
11375 1365 : GEN a, b, d, res, al, V, M, ad, abd, gk, A, awd = NULL;
11376 : long i, w;
11377 :
11378 1365 : mf = checkMF(mf);
11379 1365 : gk = MF_get_gk(mf);
11380 1365 : M = GL2toSL2(ga, &abd);
11381 1358 : if (abd) { a = gel(abd,1); b = gel(abd,2); d = gel(abd,3); }
11382 903 : else { a = d = gen_1; b = gen_0; }
11383 1358 : ad = gdiv(a,d);
11384 1358 : res = mfgaexpansion(mf, f, M, n, prec);
11385 1358 : al = gel(res,1);
11386 1358 : w = itou(gel(res,2));
11387 1358 : V = gel(res,3);
11388 1358 : if (flrat)
11389 : {
11390 126 : GEN CHI = MF_get_CHI(mf);
11391 126 : long N = MF_get_N(mf), F = mfcharconductor(CHI);
11392 126 : long ord = mfcharorder(CHI), k, deg;
11393 126 : long B = umodiu(gcoeff(M,1,2), N);
11394 126 : long C = umodiu(gcoeff(M,2,1), N);
11395 126 : long D = umodiu(gcoeff(M,2,2), N);
11396 126 : long CD = (C * D) % N, BC = (B * C) % F;
11397 : GEN CV, t;
11398 : /* weight of f * Theta in 1/2-integral weight */
11399 126 : k = typ(gk) == t_INT? (long) itou(gk): MF_get_r(mf)+1;
11400 126 : CV = odd(k) ? powuu(N, k - 1) : powuu(N, k >> 1);
11401 126 : deg = ulcm(ulcm(ord, N/ugcd(N,CD)), F/ugcd(F,BC));
11402 126 : if ((deg & 3) == 2) deg >>= 1;
11403 126 : if (typ(gk) != t_INT && odd(deg) && mfthetaI(C,D)) deg <<= 2;
11404 126 : V = bestapprnf2(V, deg, CV, prec);
11405 126 : if (abd && !signe(b))
11406 : { /* can [a,0; 0,d] be simplified to id ? */
11407 7 : long nk, dk; Qtoss(gk, &nk, &dk);
11408 7 : if (ispower(ad, utoipos(2*dk), &t)) /* t^(2*dk) = a/d or t = NULL */
11409 : {
11410 7 : V = RgV_Rg_mul(V, powiu(t,nk));
11411 7 : awd = gdiv(a, muliu(d,w));
11412 : }
11413 : }
11414 : }
11415 1232 : else if (abd)
11416 : { /* ga = M * [a,b;0,d] * rational, F := f | M = q^al * \sum V[j] q^(j/w) */
11417 448 : GEN u, t = NULL, wd = muliu(d,w);
11418 : /* a > 0, 0 <= b < d; f | ga = (a/d)^(k/2) * F(tau + b/d) */
11419 448 : if (signe(b))
11420 : {
11421 : long ns, ds;
11422 : GEN z;
11423 0 : Qtoss(gdiv(b, wd), &ns, &ds); z = rootsof1powinit(ns, ds, prec);
11424 0 : for (i = 1; i <= n+1; i++) gel(V,i) = gmul(gel(V,i), rootsof1pow(z, i-1));
11425 0 : if (!gequal0(al)) t = gexp(gmul(PiI2(prec), gmul(al, gdiv(b,d))), prec);
11426 : }
11427 448 : awd = gdiv(a, wd);
11428 448 : u = gpow(ad, gmul2n(gk,-1), prec);
11429 448 : t = t? gmul(t, u): u;
11430 448 : V = RgV_Rg_mul(V, t);
11431 : }
11432 1358 : if (!awd) A = mkmat22(a, b, gen_0, d);
11433 : else
11434 : { /* rescale and update w from [a,0; 0,d] */
11435 : long ns;
11436 455 : Qtoss(awd, &ns, &w); /* update w */
11437 455 : V = bdexpand(V, ns);
11438 455 : if (!gequal0(al))
11439 : {
11440 0 : GEN adal = gmul(ad, al), sh = gfloor(adal);
11441 0 : al = gsub(adal, sh);
11442 0 : V = RgV_shift(V, sh);
11443 : }
11444 455 : A = matid(2);
11445 : }
11446 1358 : if (params) *params = mkvec3(al, utoipos(w), A);
11447 1358 : return gc_all(av,params?2:1,&V,params);
11448 : }
11449 :
11450 : /**************************************************************/
11451 : /* Alternative method for 1/2-integral weight */
11452 : /**************************************************************/
11453 : static GEN
11454 273 : mf2basis(long N, long r, GEN CHI, GEN *pCHI1, long space)
11455 : {
11456 : GEN CHI1, CHI2, mf1, mf2, B1, B2, BT, M1, M2, M, M2i, T, Th, v, den;
11457 273 : long sb, N2, o1, o2, k1 = r + 1;
11458 :
11459 273 : if (odd(k1))
11460 : {
11461 161 : CHI1 = mfcharmul(CHI, get_mfchar(stoi(-4)));
11462 161 : CHI2 = mfcharmul(CHI, get_mfchar(stoi(-8)));
11463 : }
11464 : else
11465 : {
11466 112 : CHI1 = CHI;
11467 112 : CHI2 = mfcharmul(CHI, get_mfchar(utoi(8)));
11468 : }
11469 273 : mf1 = mfinit_Nkchi(N, k1, CHI1, space, 1);
11470 273 : if (pCHI1) *pCHI1 = CHI1;
11471 273 : B1 = MF_get_basis(mf1); if (lg(B1) == 1) return cgetg(1,t_VEC);
11472 266 : N2 = ulcm(8, N);
11473 266 : mf2 = mfinit_Nkchi(N2, k1, CHI2, space, 1);
11474 266 : B2 = MF_get_basis(mf2); if (lg(B2) == 1) return cgetg(1,t_VEC);
11475 266 : sb = mfsturmNgk(N2, gaddsg(k1, ghalf));
11476 266 : M1 = mfcoefs_mf(mf1, sb, 1);
11477 266 : M2 = mfcoefs_mf(mf2, sb, 1);
11478 266 : Th = mfTheta(NULL);
11479 266 : BT = mfcoefs_i(Th, sb, 1);
11480 266 : M1 = mfmatsermul(M1, RgV_to_RgX(expandbd(BT,2),0));
11481 266 : M2 = mfmatsermul(M2, RgV_to_RgX(BT,0));
11482 266 : o1= mfcharorder(CHI1);
11483 266 : T = (o1 <= 2)? NULL: mfcharpol(CHI1);
11484 266 : if (o1 > 2) M1 = liftpol_shallow(M1);
11485 266 : o2= mfcharorder(CHI2);
11486 266 : if (T)
11487 : {
11488 14 : if (o2 == o1) M2 = liftpol_shallow(M2);
11489 : else
11490 : {
11491 0 : GEN tr = Qab_trace_init(o2, o1, mfcharpol(CHI2), mfcharpol(CHI1));
11492 0 : M2 = QabM_tracerel(tr, 0, M2);
11493 : }
11494 : }
11495 : /* now everything is defined mod T = mfcharpol(CHI1) */
11496 266 : M2i = QabM_pseudoinv_i(M2, T, o1, &v, &den);
11497 266 : M = RgM_mul(M2i, rowpermute(M1, gel(v,1)));
11498 266 : M = RgM_mul(M2, M);
11499 266 : M1 = RgM_Rg_mul(M1, den);
11500 266 : M = RgM_sub(M1, M); if (T) M = RgXQM_red(M, T);
11501 266 : return vecmflineardiv0(B1, QabM_ker(M, T, o1), Th);
11502 : }
11503 :
11504 : /*******************************************************************/
11505 : /* Integration */
11506 : /*******************************************************************/
11507 : static GEN
11508 490 : vanembed(GEN F, GEN v, long prec)
11509 : {
11510 490 : GEN CHI = mf_get_CHI(F);
11511 490 : long o = mfcharorder(CHI);
11512 490 : if (o > 2 || degpol(mf_get_field(F)) > 1) v = liftpol_shallow(v);
11513 490 : if (o > 2) v = gsubst(v, varn(mfcharpol(CHI)), rootsof1u_cx(o, prec));
11514 490 : return v;
11515 : }
11516 :
11517 : static long
11518 1253 : mfperiod_prelim_double(double t0, long k, long bitprec)
11519 : {
11520 1253 : double nlim, c = 2*M_PI*t0;
11521 1253 : nlim = ceil(bitprec * M_LN2 / c);
11522 1253 : c -= (k - 1)/(2*nlim); if (c < 1) c = 1.;
11523 1253 : nlim += ceil((0.7 + (k-1)/2*log(nlim))/c);
11524 1253 : return (long)nlim;
11525 : }
11526 : static long
11527 301 : mfperiod_prelim(GEN t0, long k, long bitprec)
11528 301 : { return mfperiod_prelim_double(gtodouble(t0), k, bitprec); }
11529 :
11530 : /* (-X)^(k-2) * P(-1/X) = (-1)^{k-2} P|_{k-2} S */
11531 : static GEN
11532 1288 : RgX_act_S(GEN P, long k)
11533 : {
11534 1288 : P = RgX_unscale(RgX_recipspec_shallow(P+2, lgpol(P), k-1), gen_m1);
11535 1288 : setvarn(P,0); return P;
11536 : }
11537 : static int
11538 2842 : RgX_act_typ(GEN P, long k)
11539 : {
11540 2842 : switch(typ(P))
11541 : {
11542 35 : case t_RFRAC: return t_RFRAC;
11543 2793 : case t_POL:
11544 2793 : if (varn(P) == 0)
11545 : {
11546 2758 : long d = degpol(P);
11547 2758 : if (d > k-2) return t_RFRAC;
11548 2604 : if (d) return t_POL;
11549 : }
11550 : }
11551 1211 : return 0;
11552 : }
11553 : static GEN
11554 2576 : act_S(GEN P, long k)
11555 : {
11556 : GEN X;
11557 2576 : switch(RgX_act_typ(P, k))
11558 : {
11559 140 : case t_RFRAC:
11560 140 : X = gneg(pol_x(0));
11561 140 : return gmul(gsubst(P, 0, ginv(X)), gpowgs(X, k - 2));
11562 1288 : case t_POL: return RgX_act_S(P, k);
11563 : }
11564 1148 : return P;
11565 : }
11566 :
11567 : static GEN
11568 203 : AX_B(GEN M)
11569 203 : { GEN A = gcoeff(M,1,1), B = gcoeff(M,1,2); return deg1pol_shallow(A,B,0); }
11570 : static GEN
11571 203 : CX_D(GEN M)
11572 203 : { GEN C = gcoeff(M,2,1), D = gcoeff(M,2,2); return deg1pol_shallow(C,D,0); }
11573 :
11574 : /* P|_{2-k}M = (CX+D)^{k-2}P((AX+B)/(CX+D)) */
11575 : static GEN
11576 154 : RgX_act_gen(GEN P, GEN M, long k)
11577 : {
11578 154 : GEN S = gen_0, PCD, PAB;
11579 : long i;
11580 154 : PCD = gpowers(CX_D(M), k-2);
11581 154 : PAB = gpowers(AX_B(M), k-2);
11582 833 : for (i = 0; i <= k-2; i++)
11583 : {
11584 679 : GEN t = RgX_coeff(P, i);
11585 679 : if (!gequal0(t)) S = gadd(S, gmul(t, gmul(gel(PCD, k-i-1), gel(PAB, i+1))));
11586 : }
11587 154 : return S;
11588 : }
11589 : static GEN
11590 266 : act_GL2(GEN P, GEN M, long k)
11591 : {
11592 266 : switch(RgX_act_typ(P, k))
11593 : {
11594 49 : case t_RFRAC:
11595 : {
11596 49 : GEN AB = AX_B(M), CD = CX_D(M);
11597 49 : return gmul(gsubst(P, 0, gdiv(AB, CD)), gpowgs(CD, k - 2));
11598 : }
11599 154 : case t_POL: return RgX_act_gen(P, M, k);
11600 : }
11601 63 : return P;
11602 : }
11603 : static GEN
11604 7 : vecact_GL2(GEN x, GEN M, long k)
11605 21 : { pari_APPLY_same(act_GL2(gel(x,i), M, k)); }
11606 :
11607 : static GEN
11608 1631 : RgX_approx(GEN x, long bit)
11609 8267 : { pari_APPLY_pol_normalized(Rg_approx(gel(x,i),bit)); }
11610 :
11611 : /* not GC clean */
11612 : static GEN
11613 2898 : normalizeapprox(GEN x, long bit)
11614 : {
11615 2898 : GEN D = NULL;
11616 2954 : if (is_vec_t(typ(x))) pari_APPLY_same(normalizeapprox(gel(x,i), bit));
11617 2870 : if (typ(x) == t_RFRAC && varn(gel(x,2)) == 0) { D = gel(x,2); x = gel(x,1); }
11618 2870 : if (typ(x) == t_POL && varn(x) == 0)
11619 : {
11620 2807 : if (lg(x) == 3)
11621 1176 : x = Rg_approx(gel(x,2), bit);
11622 : else
11623 1631 : x = RgX_approx(x, bit);
11624 : }
11625 2870 : return D? gdiv(x, D): x;
11626 : }
11627 :
11628 : /* make sure T is a t_POL in variable 0 */
11629 : static GEN
11630 2863 : toRgX0(GEN T)
11631 2863 : { return typ(T) == t_POL && varn(T) == 0? T: scalarpol_shallow(T,0); }
11632 :
11633 : /* integrate by summing nlim+1 terms of van [may be < lg(van)]
11634 : * van can be an expansion with vector coefficients
11635 : * \int_A^oo \sum_n van[n] * q^(n/w + al) * P(z-A) dz, q = e(z) */
11636 : static GEN
11637 945 : intAoo(GEN van, long nlim, GEN al, long w, GEN P, GEN A, long k, long prec)
11638 : {
11639 : GEN alw, P1, piI2A, q, S, van0;
11640 945 : long n, vz = varn(gel(P,2));
11641 :
11642 945 : if (nlim < 1) nlim = 1;
11643 945 : alw = gmulsg(w, al);
11644 945 : P1 = RgX_Rg_translate(P, gneg(A));
11645 945 : piI2A = gmul(PiI2n(1, prec), A);
11646 945 : q = gexp(gdivgu(piI2A, w), prec);
11647 945 : S = gen_0;
11648 121674 : for (n = nlim; n >= 1; n--)
11649 : {
11650 120729 : GEN t = gsubst(P1, vz, gdivsg(w, gaddsg(n, alw)));
11651 120729 : S = gadd(gmul(gel(van, n+1), t), gmul(q, S));
11652 : }
11653 945 : S = gmul(q, S);
11654 945 : van0 = gel(van, 1);
11655 945 : if (!gequal0(al))
11656 : {
11657 42 : S = gadd(S, gmul(gsubst(P1, vz, ginv(al)), van0));
11658 42 : S = gmul(S, gexp(gmul(piI2A, al), prec));
11659 : }
11660 903 : else if (!gequal0(van0))
11661 231 : S = gsub(S, gdivgu(gmul(van0, gpowgs(gsub(pol_x(0), A), k-1)), k-1));
11662 945 : if (is_vec_t(typ(S)))
11663 : {
11664 637 : long j, l = lg(S);
11665 3192 : for (j = 1; j < l; j++) gel(S,j) = toRgX0(gel(S,j));
11666 : }
11667 : else
11668 308 : S = toRgX0(S);
11669 945 : return gneg(S);
11670 : }
11671 :
11672 : /* \sum_{j <= k} X^j * (Y / (2I\pi))^{k+1-j} k! / j! */
11673 : static GEN
11674 259 : get_P(long k, long v, long prec)
11675 : {
11676 259 : GEN a, S = cgetg(k + 1, t_POL), u = invr(Pi2n(1, prec+EXTRAPREC64));
11677 259 : long j, K = k-2;
11678 259 : S[1] = evalsigne(1)|evalvarn(0); a = u;
11679 259 : gel(S,K+2) = monomial(mulcxpowIs(a,3), 1, v); /* j = K */
11680 1176 : for(j = K-1; j >= 0; j--)
11681 : {
11682 917 : a = mulrr(mulru(a,j+1), u);
11683 917 : gel(S,j+2) = monomial(mulcxpowIs(a,3*(K+1-j)), K+1-j, v);
11684 : }
11685 259 : return S;
11686 : }
11687 :
11688 : static GEN
11689 2555 : getw1w2(long N, GEN ga)
11690 2555 : { return mkvecsmall2(mfZC_width(N, gel(ga,1)),
11691 2555 : mfZC_width(N, gel(ga,2))); }
11692 :
11693 : static GEN
11694 147 : intAoowithvanall(GEN mf, GEN vanall, GEN P, GEN cosets, long bitprec)
11695 : {
11696 147 : GEN vvan = gel(vanall,1), vaw = gel(vanall,2), W1W2, resall;
11697 147 : long prec = nbits2prec(bitprec), N, k, lco, j;
11698 :
11699 147 : N = MF_get_N(mf); k = MF_get_k(mf);
11700 147 : lco = lg(cosets);
11701 147 : W1W2 = cgetg(lco, t_VEC); resall = cgetg(lco, t_VEC);
11702 2702 : for (j = 1; j < lco; j++) gel(W1W2,j) = getw1w2(N, gel(cosets, j));
11703 2702 : for (j = 1; j < lco; j++)
11704 : {
11705 2555 : GEN w1w2j = gel(W1W2,j), alj, M, VAN, RES, AR, Q;
11706 : long jq, c, w1, w2, w;
11707 2555 : if (!w1w2j) continue;
11708 637 : alj = gel(vaw,j);
11709 637 : w1 = w1w2j[1]; Q = cgetg(lco, t_VECSMALL);
11710 637 : w2 = w1w2j[2]; M = cgetg(lco, t_COL);
11711 8267 : for (c = 1, jq = j; jq < lco; jq++)
11712 : {
11713 7630 : GEN W = gel(W1W2, jq);
11714 7630 : if (jq == j || (W && gequal(W, w1w2j) && gequal(gel(vaw, jq), alj)))
11715 : {
11716 2555 : Q[c] = jq; gel(W1W2, jq) = NULL;
11717 2555 : gel(M, c) = gel(vvan, jq); c++;
11718 : }
11719 : }
11720 637 : setlg(M,c); VAN = shallowmatconcat(M);
11721 637 : AR = mkcomplex(gen_0, sqrtr_abs(divru(utor(w1, prec+EXTRAPREC64), w2)));
11722 637 : w = itos(gel(alj,2));
11723 637 : RES = intAoo(VAN, lg(VAN)-2, gel(alj,1),w, P, AR, k, prec);
11724 3192 : for (jq = 1; jq < c; jq++) gel(resall, Q[jq]) = gel(RES, jq);
11725 : }
11726 147 : return resall;
11727 : }
11728 :
11729 : GEN
11730 539 : mftobasisES(GEN mf, GEN F)
11731 : {
11732 539 : GEN v = mftobasis(mf, F, 0);
11733 532 : long nE = lg(MF_get_E(mf))-1;
11734 532 : return mkvec2(vecslice(v,1,nE), vecslice(v,nE+1,lg(v)-1));
11735 : }
11736 :
11737 : static long
11738 0 : wt1mulcond(GEN F, long D, long space)
11739 : {
11740 0 : GEN E = mfeisenstein_i(1, mfchartrivial(), get_mfchar(stoi(D))), mf;
11741 0 : F = mfmul(F, E);
11742 0 : mf = mfinit_Nkchi(mf_get_N(F), mf_get_k(F), mf_get_CHI(F), space, 0);
11743 0 : return mfconductor(mf, F);
11744 : }
11745 : static int
11746 7 : wt1newlevel(long N)
11747 : {
11748 7 : GEN P = gel(myfactoru(N),1);
11749 7 : long l = lg(P), i;
11750 14 : for (i = 1; i < l; i++)
11751 7 : if (!wt1empty(N/P[i])) return 0;
11752 7 : return 1;
11753 : }
11754 : long
11755 175 : mfconductor(GEN mf, GEN F)
11756 : {
11757 175 : pari_sp av = avma;
11758 : GEN gk;
11759 : long space, N, M;
11760 :
11761 175 : mf = checkMF(mf);
11762 175 : if (!checkmf_i(F)) pari_err_TYPE("mfconductor",F);
11763 175 : if (mfistrivial(F)) return 1;
11764 175 : space = MF_get_space(mf);
11765 175 : if (space == mf_NEW) return mf_get_N(F);
11766 175 : gk = MF_get_gk(mf);
11767 175 : if (isint1(gk))
11768 : {
11769 7 : N = mf_get_N(F);
11770 7 : if (!wt1newlevel(N))
11771 : {
11772 0 : long s = space_is_cusp(space)? mf_CUSP: mf_FULL;
11773 0 : N = ugcd(N, wt1mulcond(F,-3,s));
11774 0 : if (!wt1newlevel(N)) N = ugcd(N, wt1mulcond(F,-4,s));
11775 : }
11776 7 : return gc_long(av,N);
11777 : }
11778 168 : if (typ(gk) != t_INT)
11779 : {
11780 42 : F = mfmultheta(F);
11781 42 : mf = obj_checkbuild(mf, MF_MF2INIT, &mf2init); /* mf_FULL */
11782 : }
11783 168 : N = 1;
11784 168 : if (space_is_cusp(space))
11785 : {
11786 7 : F = mftobasis_i(mf, F);
11787 7 : if (typ(gk) != t_INT) F = vecslice(F, lg(MF_get_E(mf)), lg(F) - 1);
11788 : }
11789 : else
11790 : {
11791 161 : GEN EF = mftobasisES(mf, F), vE = gel(EF,1), B = MF_get_E(mf);
11792 161 : long i, l = lg(B);
11793 1267 : for (i = 1; i < l; i++)
11794 1106 : if (!gequal0(gel(vE,i))) N = ulcm(N, mf_get_N(gel(B, i)));
11795 161 : F = gel(EF,2);
11796 : }
11797 168 : (void)mftonew_i(mf, F, &M); /* M = conductor of cuspidal part */
11798 168 : return gc_long(av, ulcm(M, N));
11799 : }
11800 :
11801 : static GEN
11802 1463 : fs_get_MF(GEN fs) { return gel(fs,1); }
11803 : static GEN
11804 847 : fs_get_vES(GEN fs) { return gel(fs,2); }
11805 : static GEN
11806 1596 : fs_get_pols(GEN fs) { return gel(fs,3); }
11807 : static GEN
11808 2191 : fs_get_cosets(GEN fs) { return gel(fs,4); }
11809 : static long
11810 630 : fs_get_bitprec(GEN fs) { return itou(gel(fs,5)); }
11811 : static GEN
11812 1246 : fs_get_vE(GEN fs) { return gel(fs,6); }
11813 : static GEN
11814 70 : fs_get_EF(GEN fs) { return gel(fs,7); }
11815 : static GEN
11816 1890 : fs_get_expan(GEN fs) { return gel(fs,8); }
11817 : static GEN
11818 28 : fs_set_expan(GEN fs, GEN vanall)
11819 28 : { GEN f = shallowcopy(fs); gel(f,8) = vanall; return f; }
11820 : static int
11821 49 : mfs_checkmf(GEN fs, GEN mf)
11822 49 : { GEN mfF = fs_get_MF(fs); return gequal(gel(mfF,1), gel(mf,1)); }
11823 : static long
11824 798 : checkfs_i(GEN v)
11825 798 : { return typ(v) == t_VEC && lg(v) == 9 && checkMF_i(fs_get_MF(v))
11826 567 : && typ(fs_get_vES(v)) == t_VEC
11827 567 : && typ(fs_get_pols(v)) == t_VEC
11828 567 : && typ(fs_get_cosets(v)) == t_VEC
11829 567 : && typ(fs_get_vE(v)) == t_VEC
11830 567 : && lg(fs_get_pols(v)) == lg(fs_get_cosets(v))
11831 567 : && typ(fs_get_expan(v)) == t_VEC
11832 567 : && lg(fs_get_expan(v)) == 3
11833 567 : && lg(gel(fs_get_expan(v), 1)) == lg(fs_get_cosets(v))
11834 1596 : && typ(gel(v,5)) == t_INT; }
11835 : GEN
11836 19292 : checkMF_i(GEN mf)
11837 : {
11838 19292 : long l = lg(mf);
11839 : GEN v;
11840 19292 : if (typ(mf) != t_VEC) return NULL;
11841 19264 : if (l == 9) return checkMF_i(fs_get_MF(mf));
11842 19264 : if (l != 7) return NULL;
11843 7980 : v = gel(mf,1);
11844 7980 : if (typ(v) != t_VEC || lg(v) != 5) return NULL;
11845 7980 : return (typ(gel(v,1)) == t_INT
11846 7980 : && typ(gmul2n(gel(v,2), 1)) == t_INT
11847 7980 : && typ(gel(v,3)) == t_VEC
11848 15960 : && typ(gel(v,4)) == t_INT)? mf: NULL; }
11849 : GEN
11850 4228 : checkMF(GEN T)
11851 : {
11852 4228 : GEN mf = checkMF_i(T);
11853 4228 : if (!mf) pari_err_TYPE("checkMF [please use mfinit]", T);
11854 4228 : return mf;
11855 : }
11856 :
11857 : /* c,d >= 0; c * Nc = N, find coset whose image in P1(Z/NZ) ~ (c, d + k(N/c)) */
11858 : static GEN
11859 11963 : coset_complete(long c, long d, long Nc)
11860 : {
11861 : long a, b;
11862 13307 : while (ugcd(c, d) > 1) d += Nc;
11863 11963 : (void)cbezout(c, d, &b, &a);
11864 11963 : return mkmat22s(a, -b, c, d);
11865 : }
11866 : /* right cosets of $\G_0(N)$: $\G=\bigsqcup_j \G_0(N)\ga_j$. */
11867 : /* We choose them with c\mid N and d mod N/c, not the reverse */
11868 : GEN
11869 168 : mfcosets(GEN gN)
11870 : {
11871 168 : pari_sp av = avma;
11872 : GEN V, D, mf;
11873 168 : long l, i, ct, N = 0;
11874 168 : if (typ(gN) == t_INT) N = itos(gN);
11875 14 : else if ((mf = checkMF_i(gN))) N = MF_get_N(mf);
11876 7 : else pari_err_TYPE("mfcosets", gN);
11877 161 : if (N <= 0) pari_err_DOMAIN("mfcosets", "N", "<=", gen_0, stoi(N));
11878 161 : V = cgetg(mypsiu(N) + 1, t_VEC);
11879 161 : D = mydivisorsu(N); l = lg(D);
11880 588 : for (i = ct = 1; i < l; i++)
11881 : {
11882 427 : long d, c = D[i], Nc = D[l-i], e = ugcd(Nc, c);
11883 3332 : for (d = 0; d < Nc; d++)
11884 2905 : if (ugcd(d,e) == 1) gel(V, ct++) = coset_complete(c, d, Nc);
11885 : }
11886 161 : return gc_GEN(av, V);
11887 : }
11888 : static int
11889 35469 : cmp_coset(void *E, GEN A, GEN B)
11890 : {
11891 35469 : ulong N = (ulong)E, Nc, c = itou(gcoeff(A,2,1));
11892 35469 : int r = cmpuu(c, itou(gcoeff(B,2,1)));
11893 35469 : if (r) return r;
11894 30660 : Nc = N / c;
11895 30660 : return cmpuu(umodiu(gcoeff(A,2,2), Nc), umodiu(gcoeff(B,2,2), Nc));
11896 : }
11897 : /* M in SL_2(Z) */
11898 : static long
11899 9198 : mftocoset_i(ulong N, GEN M, GEN cosets)
11900 : {
11901 9198 : pari_sp av = avma;
11902 9198 : long A = itos(gcoeff(M,1,1)), c, u, v, Nc, i;
11903 9198 : long C = itos(gcoeff(M,2,1)), D = itos(gcoeff(M,2,2));
11904 : GEN ga;
11905 9198 : c = cbezout(N*A, C, &u, &v); Nc = N/c;
11906 9198 : ga = coset_complete(c, umodsu(v*D, Nc), Nc);
11907 9198 : i = gen_search(cosets, ga, (void*)N, &cmp_coset);
11908 9198 : if (i < 0) pari_err_BUG("mftocoset [no coset found]");
11909 9198 : return gc_long(av,i);
11910 : }
11911 : /* (U * V^(-1))[2,2] mod N, assuming V in SL2(Z) */
11912 : static long
11913 9177 : SL2_div_D(ulong N, GEN U, GEN V)
11914 : {
11915 9177 : long c = umodiu(gcoeff(U,2,1), N), d = umodiu(gcoeff(U,2,2), N);
11916 9177 : long a2 = umodiu(gcoeff(V,1,1), N), b2 = umodiu(gcoeff(V,1,2), N);
11917 9177 : return (a2*d - b2*c) % (long)N;
11918 : }
11919 : static long
11920 9177 : mftocoset_iD(ulong N, GEN M, GEN cosets, long *D)
11921 : {
11922 9177 : long i = mftocoset_i(N, M, cosets);
11923 9177 : *D = SL2_div_D(N, M, gel(cosets,i)); return i;
11924 : }
11925 : GEN
11926 7 : mftocoset(ulong N, GEN M, GEN cosets)
11927 : {
11928 : long i;
11929 7 : if (!check_SL2Z(M)) pari_err_TYPE("mftocoset",M);
11930 7 : i = mftocoset_i(N, M, cosets);
11931 7 : retmkvec2(gdiv(M,gel(cosets,i)), utoipos(i));
11932 : }
11933 :
11934 : static long
11935 2555 : getnlim2(long N, long w1, long w2, long nlim, long k, long bitprec)
11936 : {
11937 2555 : if (w2 == N) return nlim;
11938 483 : return mfperiod_prelim_double(1./sqrt((double)w1*w2), k, bitprec + 32);
11939 : }
11940 :
11941 : /* g * S, g 2x2 */
11942 : static GEN
11943 1337 : ZM_mulS(GEN g)
11944 1337 : { return mkmat2(gel(g,2), ZC_neg(gel(g,1))); }
11945 : /* g * T, g 2x2 */
11946 : static GEN
11947 4634 : ZM_mulT(GEN g)
11948 4634 : { return mkmat2(gel(g,1), ZC_add(gel(g,2), gel(g,1))); }
11949 : /* g * T^(-1), g 2x2 */
11950 : static GEN
11951 2352 : ZM_mulTi(GEN g)
11952 2352 : { return mkmat2(gel(g,1), ZC_sub(gel(g,2), gel(g,1))); }
11953 :
11954 : /* Compute all slashexpansions for all cosets */
11955 : static GEN
11956 175 : mfgaexpansionall(GEN mf, GEN FE, GEN cosets, double height, long prec)
11957 : {
11958 175 : GEN CHI = MF_get_CHI(mf), vres, vresaw;
11959 175 : long lco, j, k = MF_get_k(mf), N = MF_get_N(mf), bitprec = prec2nbits(prec);
11960 :
11961 175 : lco = lg(cosets);
11962 175 : vres = const_vec(lco-1, NULL);
11963 175 : vresaw = cgetg(lco, t_VEC);
11964 2912 : for (j = 1; j < lco; j++) if (!gel(vres,j))
11965 : {
11966 455 : GEN ga = gel(cosets, j), van, aw, al, z, gai;
11967 455 : long w1 = mfZC_width(N, gel(ga,1));
11968 455 : long w2 = mfZC_width(N, gel(ga,2));
11969 : long nlim, nlim2, daw, da, na, i;
11970 455 : double sqNinvdbl = height ? height/w1 : 1./sqrt((double)w1*N);
11971 455 : nlim = mfperiod_prelim_double(sqNinvdbl, k, bitprec + 32);
11972 455 : van = mfslashexpansion(mf, FE, ga, nlim, 0, &aw, prec + EXTRAPREC64);
11973 455 : van = vanembed(gel(FE, 1), van, prec + EXTRAPREC64);
11974 455 : al = gel(aw, 1);
11975 455 : nlim2 = height? nlim: getnlim2(N, w1, w2, nlim, k, bitprec);
11976 455 : gel(vres, j) = vecslice(van, 1, nlim2 + 1);
11977 455 : gel(vresaw, j) = aw;
11978 455 : Qtoss(al, &na, &da); daw = da*w1;
11979 455 : z = rootsof1powinit(1, daw, prec + EXTRAPREC64);
11980 455 : gai = ga;
11981 2737 : for (i = 1; i < w1; i++)
11982 : {
11983 : GEN V, coe;
11984 2282 : long Di, n, ind, w2, s = ((i*na) % da) * w1, t = i*da;
11985 2282 : gai = ZM_mulT(gai);
11986 2282 : ind = mftocoset_iD(N, gai, cosets, &Di);
11987 2282 : w2 = mfZC_width(N, gel(gel(cosets,ind), 2));
11988 2282 : nlim2 = height? nlim: getnlim2(N, w1, w2, nlim, k, bitprec);
11989 2282 : gel(vresaw, ind) = aw;
11990 2282 : V = cgetg(nlim2 + 2, t_VEC);
11991 909034 : for (n = 0; n <= nlim2; n++, s = Fl_add(s, t, daw))
11992 906752 : gel(V, n+1) = gmul(gel(van, n+1), rootsof1pow(z, s));
11993 2282 : coe = mfcharcxeval(CHI, Di, prec + EXTRAPREC64);
11994 2282 : if (!gequal1(coe)) V = RgV_Rg_mul(V, conj_i(coe));
11995 2282 : gel(vres, ind) = V;
11996 : }
11997 : }
11998 175 : return mkvec2(vres, vresaw);
11999 : }
12000 :
12001 : /* Compute all period pols of F|_k\ga_j, vF = mftobasis(F_S) */
12002 : static GEN
12003 168 : mfperiodpols_i(GEN mf, GEN FE, GEN cosets, GEN vanall, long bit)
12004 : {
12005 168 : long N, i, prec = nbits2prec(bit), k = MF_get_k(mf);
12006 168 : GEN vP, P, CHI, intall = gen_0;
12007 :
12008 168 : if (k == 0 && gequal0(gel(FE,2)))
12009 0 : return cosets? const_vec(lg(cosets)-1, pol_0(0)): pol_0(0);
12010 168 : N = MF_get_N(mf);
12011 168 : CHI = MF_get_CHI(mf);
12012 168 : P = get_P(k, fetch_var(), prec);
12013 168 : if (!cosets)
12014 : { /* ga = id */
12015 21 : long nlim, PREC = prec + EXTRAPREC64;
12016 21 : GEN F = gel(FE,1), sqNinv = invr(sqrtr_abs(utor(N, PREC))); /* A/w */
12017 : GEN AR, v, van, T1, T2;
12018 :
12019 21 : nlim = mfperiod_prelim(sqNinv, k, bit + 32);
12020 : /* F|id: al = 0, w = 1 */
12021 21 : v = mfcoefs_i(F, nlim, 1);
12022 21 : van = vanembed(F, v, PREC);
12023 21 : AR = mkcomplex(gen_0, sqNinv);
12024 21 : T1 = intAoo(van, nlim, gen_0,1, P, AR, k, prec);
12025 21 : if (N == 1) T2 = T1;
12026 : else
12027 : { /* F|S: al = 0, w = N */
12028 7 : v = mfgaexpansion(mf, FE, mkS(), nlim, PREC);
12029 7 : van = vanembed(F, gel(v,3), PREC);
12030 7 : AR = mkcomplex(gen_0, mulur(N,sqNinv));
12031 7 : T2 = intAoo(van, nlim, gen_0,N, P, AR, k, prec);
12032 : }
12033 21 : T1 = gsub(T1, act_S(T2, k));
12034 21 : T1 = normalizeapprox(T1, bit-20);
12035 21 : vP = gprec_wtrunc(T1, prec);
12036 : }
12037 : else
12038 : {
12039 147 : long lco = lg(cosets);
12040 147 : intall = intAoowithvanall(mf, vanall, P, cosets, bit);
12041 147 : vP = const_vec(lco-1, NULL);
12042 2702 : for (i = 1; i < lco; i++)
12043 : {
12044 2555 : GEN P, P1, P2, c, ga = gel(cosets, i);
12045 : long iS, DS;
12046 2646 : if (gel(vP,i)) continue;
12047 1323 : P1 = gel(intall, i);
12048 1323 : iS = mftocoset_iD(N, ZM_mulS(ga), cosets, &DS);
12049 1323 : c = mfcharcxeval(CHI, DS, prec + EXTRAPREC64);
12050 1323 : P2 = gel(intall, iS);
12051 :
12052 1323 : P = act_S(isint1(c)? P2: gmul(c, P2), k);
12053 1323 : P = normalizeapprox(gsub(P1, P), bit-20);
12054 1323 : gel(vP,i) = gprec_wtrunc(P, prec);
12055 1323 : if (iS == i) continue;
12056 :
12057 1232 : P = act_S(isint1(c)? P1: gmul(conj_i(c), P1), k);
12058 1232 : if (!odd(k)) P = gneg(P);
12059 1232 : P = normalizeapprox(gadd(P, P2), bit-20);
12060 1232 : gel(vP,iS) = gprec_wtrunc(P, prec);
12061 : }
12062 : }
12063 168 : delete_var(); return vP;
12064 : }
12065 :
12066 : /* when cosets = NULL, return a "fake" symbol containing only fs(oo->0) */
12067 : static GEN
12068 168 : mfsymbol_i(GEN mf, GEN F, GEN cosets, long bit)
12069 : {
12070 168 : GEN FE, van, vP, vE, Mvecj, vES = mftobasisES(mf,F);
12071 168 : long precnew, prec = nbits2prec(bit), k = MF_get_k(mf);
12072 168 : vE = mfgetembed(F, prec);
12073 168 : Mvecj = obj_checkbuild(mf, MF_EISENSPACE, &mfeisensteinspaceinit);
12074 168 : if (lg(Mvecj) >= 5) precnew = prec;
12075 : else
12076 : {
12077 14 : long N = MF_get_N(mf), n = mfperiod_prelim_double(1/(double)N, k, bit + 32);
12078 14 : precnew = prec + inveis_extraprec(N, mkS(), Mvecj, n);
12079 : }
12080 168 : FE = mkcol2(F, mf_eisendec(mf,F,precnew));
12081 168 : van = cosets? mfgaexpansionall(mf, FE, cosets, 0, prec): NULL;
12082 168 : vP = mfperiodpols_i(mf, FE, cosets, van, bit);
12083 168 : return mkvecn(8, mf, vES, vP, cosets, utoi(bit), vE, FE, van);
12084 : }
12085 :
12086 : static GEN
12087 56 : fs2_get_cusps(GEN f) { return gel(f,3); }
12088 : static GEN
12089 56 : fs2_get_MF(GEN f) { return gel(f,1); }
12090 : static GEN
12091 56 : fs2_get_W(GEN f) { return gel(f,2); }
12092 : static GEN
12093 56 : fs2_get_F(GEN f) { return gel(f,4); }
12094 : static long
12095 0 : fs2_get_bitprec(GEN f) { return itou(gel(f,5)); }
12096 : static GEN
12097 56 : fs2_get_al0(GEN f) { return gel(f,6); }
12098 : static GEN
12099 21 : fs2_get_den(GEN f) { return gel(f,7); }
12100 : static int
12101 210 : checkfs2_i(GEN f)
12102 : {
12103 : GEN W, C, F, al0;
12104 : long l;
12105 210 : if (typ(f) != t_VEC || lg(f) != 8 || typ(gel(f,5)) != t_INT) return 0;
12106 35 : C = fs2_get_cusps(f); l = lg(C);
12107 35 : W = fs2_get_W(f);
12108 35 : F = fs2_get_F(f);
12109 35 : al0 = fs2_get_al0(f);
12110 35 : return checkMF_i(fs2_get_MF(f))
12111 35 : && typ(W) == t_VEC && typ(F) == t_VEC && typ(al0) == t_VECSMALL
12112 70 : && lg(W) == l && lg(F) == l && lg(al0) == l;
12113 : }
12114 : static GEN fs2_init(GEN mf, GEN F, long bit);
12115 : GEN
12116 175 : mfsymbol(GEN mf, GEN F, long bit)
12117 : {
12118 175 : pari_sp av = avma;
12119 175 : GEN cosets = NULL;
12120 175 : if (!F)
12121 : {
12122 35 : F = mf;
12123 35 : if (!checkmf_i(F)) pari_err_TYPE("mfsymbol", F);
12124 35 : mf = mfinit_i(F, mf_FULL);
12125 : }
12126 140 : else if (!checkmf_i(F)) pari_err_TYPE("mfsymbol", F);
12127 175 : if (checkfs2_i(mf)) return fs2_init(mf, F, bit);
12128 175 : if (checkfs_i(mf))
12129 : {
12130 0 : cosets = fs_get_cosets(mf);
12131 0 : mf = fs_get_MF(mf);
12132 : }
12133 175 : else if (checkMF_i(mf))
12134 : {
12135 175 : GEN gk = MF_get_gk(mf);
12136 175 : if (typ(gk) != t_INT || equali1(gk)) return fs2_init(mf, F, bit);
12137 154 : if (signe(gk) <= 0) pari_err_TYPE("mfsymbol [k <= 0]", mf);
12138 147 : cosets = mfcosets(MF_get_gN(mf));
12139 : }
12140 0 : else pari_err_TYPE("mfsymbol",mf);
12141 147 : return gc_GEN(av, mfsymbol_i(mf, F, cosets, bit));
12142 : }
12143 :
12144 : static GEN
12145 14 : RgX_by_parity(GEN P, long odd)
12146 : {
12147 14 : long i, l = lg(P);
12148 : GEN Q;
12149 14 : if (l < 4) return odd ? pol_x(0): P;
12150 14 : Q = cgetg(l, t_POL); Q[1] = P[1];
12151 91 : for (i = odd? 2: 3; i < l; i += 2) gel(Q,i) = gen_0;
12152 91 : for (i = odd? 3: 2; i < l; i += 2) gel(Q,i) = gel(P,i);
12153 14 : return normalizepol_lg(Q, l);
12154 : }
12155 : /* flag 0: period polynomial of F, >0 or <0 with corresponding parity */
12156 : GEN
12157 35 : mfperiodpol(GEN mf0, GEN F, long flag, long bit)
12158 : {
12159 35 : pari_sp av = avma;
12160 35 : GEN pol, mf = checkMF_i(mf0);
12161 35 : if (!mf) pari_err_TYPE("mfperiodpol",mf0);
12162 35 : if (checkfs_i(F))
12163 : {
12164 14 : GEN mfpols = fs_get_pols(F);
12165 14 : if (!mfs_checkmf(F, mf)) pari_err_TYPE("mfperiodpol [different mf]",F);
12166 14 : pol = veclast(mfpols); /* trivial coset is last */
12167 : }
12168 : else
12169 : {
12170 21 : GEN gk = MF_get_gk(mf);
12171 21 : if (typ(gk) != t_INT) pari_err_TYPE("mfperiodpol [half-integral k]", mf);
12172 21 : if (equali1(gk)) pari_err_TYPE("mfperiodpol [k = 1]", mf);
12173 21 : F = mfsymbol_i(mf, F, NULL, bit);
12174 21 : pol = fs_get_pols(F);
12175 : }
12176 35 : if (flag) pol = RgX_by_parity(pol, flag < 0);
12177 35 : return gc_GEN(av, RgX_embedall(pol, fs_get_vE(F)));
12178 : }
12179 :
12180 : static int
12181 35 : mfs_iscusp(GEN mfs) { return gequal0(gmael(mfs,2,1)); }
12182 : /* given cusps s1 and s2 (rationals or oo)
12183 : * compute $\int_{s1}^{s2}(X-\tau)^{k-2}F|_k\ga_j(\tau)\,d\tau$ */
12184 : /* If flag = 1, do not give an error message if divergent, but
12185 : give the rational function as result. */
12186 :
12187 : static GEN
12188 126 : col2cusp(GEN v)
12189 : {
12190 : GEN A, C;
12191 126 : if (lg(v) != 3 || !RgV_is_ZV(v)) pari_err_TYPE("col2cusp",v);
12192 126 : A = gel(v,1);
12193 126 : C = gel(v,2);
12194 126 : if (gequal0(C))
12195 : {
12196 0 : if (gequal0(A)) pari_err_TYPE("mfsymboleval", mkvec2(A, C));
12197 0 : return mkoo();
12198 : }
12199 126 : return gdiv(A, C);
12200 : }
12201 : /* g.oo */
12202 : static GEN
12203 112 : mat2cusp(GEN g) { return col2cusp(gel(g,1)); }
12204 :
12205 : static GEN
12206 7 : pathmattovec(GEN path)
12207 7 : { return mkvec2(col2cusp(gel(path,1)), col2cusp(gel(path,2))); }
12208 :
12209 : static void
12210 546 : get_mf_F(GEN fs, GEN *mf, GEN *F)
12211 : {
12212 546 : if (lg(fs) == 3) { *mf = gel(fs,1); *F = gel(fs,2); }
12213 546 : else { *mf = fs_get_MF(fs); *F = NULL; }
12214 546 : }
12215 : static GEN
12216 189 : mfgetvan(GEN fs, GEN ga, GEN *pal, long nlim, long prec)
12217 : {
12218 : GEN van, mf, F, W;
12219 : long PREC;
12220 189 : get_mf_F(fs, &mf, &F);
12221 189 : if (!F)
12222 : {
12223 189 : GEN vanall = fs_get_expan(fs), cosets = fs_get_cosets(fs);
12224 189 : long D, jga = mftocoset_iD(MF_get_N(mf), ga, cosets, &D);
12225 189 : van = gmael(vanall, 1, jga);
12226 189 : W = gmael(vanall, 2, jga);
12227 189 : if (lg(van) >= nlim + 2)
12228 : {
12229 182 : GEN z = mfcharcxeval(MF_get_CHI(mf), D, prec);
12230 182 : if (!gequal1(z)) van = RgV_Rg_mul(van, z);
12231 182 : *pal = gel(W,1); return van;
12232 : }
12233 7 : F = gel(fs_get_EF(fs), 1);
12234 : }
12235 7 : PREC = prec + EXTRAPREC64;
12236 7 : van = mfslashexpansion(mf, F, ga, nlim, 0, &W, PREC);
12237 7 : van = vanembed(F, van, PREC);
12238 7 : *pal = gel(W,1); return van;
12239 : }
12240 : /* Computation of int_A^oo (f | ga)(t)(X-t)^{k-2} dt, assuming convergence;
12241 : * fs is either a symbol or a triple [mf,F,bitprec]. A != oo and im(A) > 0 */
12242 : static GEN
12243 77 : intAoo0(GEN fs, GEN A, GEN ga, GEN P, long bit)
12244 : {
12245 77 : long nlim, N, k, w, prec = nbits2prec(bit);
12246 : GEN van, mf, F, al;
12247 77 : get_mf_F(fs, &mf,&F); N = MF_get_N(mf); k = MF_get_k(mf);
12248 77 : w = mfZC_width(N, gel(ga,1));
12249 77 : nlim = mfperiod_prelim(gdivgu(imag_i(A), w), k, bit + 32);
12250 77 : van = mfgetvan(fs, ga, &al, nlim, prec);
12251 77 : return intAoo(van, nlim, al,w, P, A, k, prec);
12252 : }
12253 :
12254 : /* fs symbol, naive summation, A != oo, im(A) > 0 and B = oo or im(B) > 0 */
12255 : static GEN
12256 112 : mfsymboleval_direct(GEN fs, GEN path, GEN ga, GEN P)
12257 : {
12258 112 : GEN A, B, van, S, al, mf = fs_get_MF(fs);
12259 112 : long w, nlimA, nlimB = 0, N = MF_get_N(mf), k = MF_get_k(mf);
12260 112 : long bit = fs_get_bitprec(fs), prec = nbits2prec(bit);
12261 :
12262 112 : A = gel(path, 1);
12263 112 : B = gel(path, 2); if (typ(B) == t_INFINITY) B = NULL;
12264 112 : w = mfZC_width(N, gel(ga,1));
12265 112 : nlimA = mfperiod_prelim(gdivgu(imag_i(A),w), k, bit + 32);
12266 112 : if (B) nlimB = mfperiod_prelim(gdivgu(imag_i(B),w), k, bit + 32);
12267 112 : van = mfgetvan(fs, ga, &al, maxss(nlimA,nlimB), prec);
12268 112 : S = intAoo(van, nlimA, al,w, P, A, k, prec);
12269 112 : if (B) S = gsub(S, intAoo(van, nlimB, al,w, P, B, k, prec));
12270 112 : return RgX_embedall(S, fs_get_vE(fs));
12271 : }
12272 :
12273 : /* Computation of int_A^oo (f | ga)(t)(X-t)^{k-2} dt, assuming convergence;
12274 : * fs is either a symbol or a pair [mf,F]. */
12275 : static GEN
12276 77 : mfsymbolevalpartial(GEN fs, GEN A, GEN ga, long bit)
12277 : {
12278 : GEN Y, F, S, P, mf;
12279 77 : long N, k, w, prec = nbits2prec(bit);
12280 :
12281 77 : get_mf_F(fs, &mf, &F);
12282 77 : N = MF_get_N(mf); w = mfZC_width(N, gel(ga,1));
12283 77 : k = MF_get_k(mf);
12284 77 : Y = gdivgu(imag_i(A), w);
12285 77 : P = get_P(k, fetch_var(), prec);
12286 77 : if (lg(fs) != 3 && gtodouble(Y)*(2*N) < 1)
12287 21 : { /* true symbol + low imaginary part: use GL_2 action to improve */
12288 21 : GEN U, ga2, czd, A2 = cxredga0N(N, A, &U, &czd, 1);
12289 21 : GEN vE = fs_get_vE(fs);
12290 21 : ga2 = ZM_mul(ga, ZM_inv(U, NULL));
12291 21 : S = RgX_embedall(intAoo0(fs, A2, ga2, P, bit), vE);
12292 21 : S = gsub(S, mfsymboleval(fs, mkvec2(mat2cusp(U), mkoo()), ga2, bit));
12293 21 : S = typ(S) == t_VEC? vecact_GL2(S, U, k): act_GL2(S, U, k);
12294 : }
12295 : else
12296 : {
12297 56 : S = intAoo0(fs, A, ga, P, bit);
12298 56 : S = RgX_embedall(S, F? mfgetembed(F,prec): fs_get_vE(fs));
12299 : }
12300 77 : delete_var(); return normalizeapprox(S, bit-20);
12301 : }
12302 :
12303 : static GEN
12304 42 : actal(GEN x, GEN vabd)
12305 : {
12306 42 : if (typ(x) == t_INFINITY) return x;
12307 35 : return gdiv(gadd(gmul(gel(vabd,1), x), gel(vabd,2)), gel(vabd,3));
12308 : }
12309 :
12310 : static GEN
12311 14 : unact(GEN z, GEN vabd, long k, long prec)
12312 : {
12313 14 : GEN res = gsubst(z, 0, actal(pol_x(0), vabd));
12314 14 : GEN CO = gpow(gdiv(gel(vabd,3), gel(vabd,1)), sstoQ(k-2, 2), prec);
12315 14 : return gmul(CO, res);
12316 : }
12317 :
12318 : GEN
12319 210 : mfsymboleval(GEN fs, GEN path, GEN ga, long bitprec)
12320 : {
12321 210 : pari_sp av = avma;
12322 210 : GEN tau, V, LM, S, CHI, mfpols, cosets, al, be, mf, F, vabd = NULL;
12323 : long D, B, m, u, v, a, b, c, d, j, k, N, prec, tsc1, tsc2;
12324 :
12325 210 : if (checkfs_i(fs))
12326 : {
12327 203 : get_mf_F(fs, &mf, &F);
12328 203 : bitprec = minss(bitprec, fs_get_bitprec(fs));
12329 : }
12330 : else
12331 : {
12332 7 : if (checkfs2_i(fs)) pari_err_TYPE("mfsymboleval [need integral k > 1]",fs);
12333 0 : if (typ(fs) != t_VEC || lg(fs) != 3) pari_err_TYPE("mfsymboleval",fs);
12334 0 : get_mf_F(fs, &mf, &F);
12335 0 : mf = checkMF_i(mf);
12336 0 : if (!mf ||!checkmf_i(F)) pari_err_TYPE("mfsymboleval",fs);
12337 : }
12338 203 : if (lg(path) != 3) pari_err_TYPE("mfsymboleval",path);
12339 203 : if (typ(path) == t_MAT) path = pathmattovec(path);
12340 203 : if (typ(path) != t_VEC) pari_err_TYPE("mfsymboleval",path);
12341 203 : al = gel(path,1);
12342 203 : be = gel(path,2);
12343 203 : ga = ga? GL2toSL2(ga, &vabd): matid(2);
12344 203 : if (vabd)
12345 : {
12346 14 : al = actal(al, vabd);
12347 14 : be = actal(be, vabd); path = mkvec2(al, be);
12348 : }
12349 203 : tsc1 = cusp_AC(al, &a, &c);
12350 203 : tsc2 = cusp_AC(be, &b, &d);
12351 203 : prec = nbits2prec(bitprec);
12352 203 : k = MF_get_k(mf);
12353 203 : if (!tsc1)
12354 : {
12355 42 : GEN z2, z = mfsymbolevalpartial(fs, al, ga, bitprec);
12356 42 : if (tsc2)
12357 28 : z2 = d? mfsymboleval(fs, mkvec2(be, mkoo()), ga, bitprec): gen_0;
12358 : else
12359 14 : z2 = mfsymbolevalpartial(fs, be, ga, bitprec);
12360 42 : z = gsub(z, z2);
12361 42 : if (vabd) z = unact(z, vabd, k, prec);
12362 42 : return gc_GEN(av, normalizeapprox(z, bitprec-20));
12363 : }
12364 161 : else if (!tsc2)
12365 : {
12366 21 : GEN z = mfsymbolevalpartial(fs, be, ga, bitprec);
12367 21 : if (c) z = gsub(mfsymboleval(fs, mkvec2(al, mkoo()), ga, bitprec), z);
12368 7 : else z = gneg(z);
12369 21 : if (vabd) z = unact(z, vabd, k, prec);
12370 21 : return gc_GEN(av, normalizeapprox(z, bitprec-20));
12371 : }
12372 140 : if (F) pari_err_TYPE("mfsymboleval", fs);
12373 140 : D = a*d-b*c;
12374 140 : if (!D) { set_avma(av); return RgX_embedall(gen_0, fs_get_vE(fs)); }
12375 126 : mfpols = fs_get_pols(fs);
12376 126 : cosets = fs_get_cosets(fs);
12377 126 : CHI = MF_get_CHI(mf); N = MF_get_N(mf);
12378 126 : cbezout(a, c, &u, &v); B = u*b + v*d; tau = mkmat22s(a, -v, c, u);
12379 126 : V = gcf(sstoQ(B, D));
12380 126 : LM = shallowconcat(mkcol2(gen_1, gen_0), contfracpnqn(V, lg(V)));
12381 126 : S = gen_0; m = lg(LM) - 2;
12382 364 : for (j = 0; j < m; j++)
12383 : {
12384 : GEN M, P;
12385 : long D, iN;
12386 238 : M = mkmat2(gel(LM, j+2), gel(LM, j+1));
12387 238 : if (!odd(j)) gel(M,1) = ZC_neg(gel(M,1));
12388 238 : M = ZM_mul(tau, M);
12389 238 : iN = mftocoset_iD(N, ZM_mul(ga, M), cosets, &D);
12390 238 : P = gmul(gel(mfpols,iN), mfcharcxeval(CHI,D,prec));
12391 238 : S = gadd(S, act_GL2(P, ZM_inv(M, NULL), k));
12392 : }
12393 126 : if (typ(S) == t_RFRAC)
12394 : {
12395 : GEN R, S1, co;
12396 21 : gel(S,2) = primitive_part(gel(S,2), &co);
12397 21 : if (co) gel(S,1) = gdiv(gel(S,1), gtofp(co,prec));
12398 21 : S1 = poldivrem(gel(S,1), gel(S,2), &R);
12399 21 : if (gexpo(R) < -bitprec + 20) S = S1;
12400 : }
12401 126 : if (vabd) S = unact(S, vabd, k, prec);
12402 126 : S = RgX_embedall(S, fs_get_vE(fs));
12403 126 : return gc_GEN(av, normalizeapprox(S, bitprec-20));
12404 : }
12405 :
12406 : /* v a scalar or t_POL; set *pw = a if expo(a) > E for some coefficient;
12407 : * take the 'a' with largest exponent */
12408 : static void
12409 4984 : improve(GEN v, GEN *pw, long *E)
12410 : {
12411 4984 : if (typ(v) != t_POL)
12412 : {
12413 4354 : long e = gexpo(v);
12414 4354 : if (e > *E) { *E = e; *pw = v; }
12415 : }
12416 : else
12417 : {
12418 630 : long j, l = lg(v);
12419 4144 : for (j = 2; j < l; j++) improve(gel(v,j), pw, E);
12420 : }
12421 4984 : }
12422 : static GEN
12423 518 : polabstorel(GEN rnfeq, GEN x)
12424 : {
12425 518 : if (typ(x) != t_POL) return x;
12426 3500 : pari_APPLY_pol_normalized(eltabstorel(rnfeq, gel(x,i)));
12427 : }
12428 : static GEN
12429 1519 : bestapprnfrel(GEN x, GEN polabs, GEN roabs, GEN rnfeq, long prec)
12430 : {
12431 1519 : x = bestapprnf(x, polabs, roabs, prec);
12432 1519 : if (rnfeq) x = polabstorel(rnfeq, liftpol_shallow(x));
12433 1519 : return x;
12434 : }
12435 : /* v vector of polynomials polynomial in C[X] (possibly scalar).
12436 : * Set *w = coeff with largest exponent and return T / *w, rationalized */
12437 : static GEN
12438 98 : normal(GEN v, GEN polabs, GEN roabs, GEN rnfeq, GEN *w, long prec)
12439 : {
12440 98 : long i, l = lg(v), E = -(long)HIGHEXPOBIT;
12441 : GEN dv;
12442 1568 : for (i = 1; i < l; i++) improve(gel(v,i), w, &E);
12443 98 : v = RgV_Rg_mul(v, ginv(*w));
12444 1568 : for (i = 1; i < l; i++)
12445 1470 : gel(v,i) = bestapprnfrel(gel(v,i), polabs,roabs,rnfeq,prec);
12446 98 : v = Q_primitive_part(v,&dv);
12447 98 : if (dv) *w = gmul(*w,dv);
12448 98 : return v;
12449 : }
12450 :
12451 : static GEN mfpetersson_i(GEN FS, GEN GS);
12452 :
12453 : GEN
12454 42 : mfmanin(GEN FS, long bitprec)
12455 : {
12456 42 : pari_sp av = avma;
12457 : GEN mf, M, vp, vm, cosets, CHI, vpp, vmm, f, T, P, vE, polabs, roabs, rnfeq;
12458 : GEN pet;
12459 : long N, k, lco, i, prec, lvE;
12460 :
12461 42 : if (!checkfs_i(FS))
12462 : {
12463 7 : if (checkfs2_i(FS)) pari_err_TYPE("mfmanin [need integral k > 1]",FS);
12464 0 : pari_err_TYPE("mfmanin",FS);
12465 : }
12466 35 : if (!mfs_iscusp(FS)) pari_err_TYPE("mfmanin [noncuspidal]",FS);
12467 35 : mf = fs_get_MF(FS);
12468 35 : vp = fs_get_pols(FS);
12469 35 : cosets = fs_get_cosets(FS);
12470 35 : bitprec = fs_get_bitprec(FS);
12471 35 : N = MF_get_N(mf); k = MF_get_k(mf); CHI = MF_get_CHI(mf);
12472 35 : lco = lg(cosets); vm = cgetg(lco, t_VEC);
12473 35 : prec = nbits2prec(bitprec);
12474 476 : for (i = 1; i < lco; i++)
12475 : {
12476 441 : GEN g = gel(cosets, i), c;
12477 441 : long A = itos(gcoeff(g,1,1)), B = itos(gcoeff(g,1,2));
12478 441 : long C = itos(gcoeff(g,2,1)), D = itos(gcoeff(g,2,2));
12479 441 : long Dbar, ibar = mftocoset_iD(N, mkmat22s(-B,-A,D,C), cosets, &Dbar);
12480 :
12481 441 : c = mfcharcxeval(CHI, Dbar, prec); if (odd(k)) c = gneg(c);
12482 441 : T = gel(vp,ibar);
12483 441 : if (typ(T) == t_POL && varn(T) == 0)
12484 189 : T = RgX_recip(RgX_Rg_mul(T, c));
12485 : else
12486 252 : T = gmul(T, c);
12487 441 : gel(vm,i) = T;
12488 : }
12489 35 : vpp = gadd(vp,vm);
12490 35 : vmm = gsub(vp,vm);
12491 :
12492 35 : vE = fs_get_vE(FS); lvE = lg(vE);
12493 35 : f = gel(fs_get_EF(FS), 1);
12494 35 : P = mf_get_field(f); if (degpol(P) == 1) P = NULL;
12495 35 : T = mfcharpol(CHI); if (degpol(T) == 1) T = NULL;
12496 35 : if (T && P)
12497 : {
12498 7 : rnfeq = nf_rnfeqsimple(T, P);
12499 7 : polabs = gel(rnfeq,1);
12500 7 : roabs = gel(QX_complex_roots(polabs,prec), 1);
12501 : }
12502 : else
12503 : {
12504 28 : rnfeq = roabs = NULL;
12505 28 : polabs = P? P: T;
12506 : }
12507 35 : pet = mfpetersson_i(FS, NULL);
12508 35 : M = cgetg(lvE, t_VEC);
12509 84 : for (i = 1; i < lvE; i++)
12510 : {
12511 49 : GEN p, m, wp, wm, petdiag, r, E = gel(vE,i);
12512 49 : p = normal(RgXV_embed(vpp, E), polabs, roabs, rnfeq, &wp, prec);
12513 49 : m = normal(RgXV_embed(vmm, E), polabs, roabs, rnfeq, &wm, prec);
12514 49 : petdiag = typ(pet)==t_MAT? gcoeff(pet,i,i): pet;
12515 49 : r = gdiv(mulimag(wp, conj_i(wm)), petdiag);
12516 49 : r = bestapprnfrel(r, polabs, roabs, rnfeq, prec);
12517 49 : gel(M,i) = mkvec2(mkvec2(p,m), mkvec3(wp,wm,r));
12518 : }
12519 35 : return gc_GEN(av, lvE == 2? gel(M,1): M);
12520 : }
12521 :
12522 : /* flag = 0: full, flag = +1 or -1, odd/even */
12523 : /* Basis of period polynomials in level 1. */
12524 : GEN
12525 49 : mfperiodpolbasis(long k, long flag)
12526 : {
12527 49 : pari_sp av = avma;
12528 49 : long i, j, n = k - 2;
12529 : GEN M, C, v;
12530 49 : if (k <= 4) return cgetg(1,t_VEC);
12531 35 : M = cgetg(k, t_MAT);
12532 35 : C = matpascal(n);
12533 35 : if (!flag)
12534 392 : for (j = 0; j <= n; j++)
12535 : {
12536 371 : gel(M, j+1) = v = cgetg(k, t_COL);
12537 4767 : for (i = 0; i <= j; i++) gel(v, i+1) = gcoeff(C, j+1, i+1);
12538 4396 : for (; i <= n; i++) gel(v, i+1) = gcoeff(C, n-j+1, i-j+1);
12539 : }
12540 : else
12541 168 : for (j = 0; j <= n; j++)
12542 : {
12543 154 : gel(M, j+1) = v = cgetg(k, t_COL);
12544 1848 : for (i = 0; i <= n; i++)
12545 : {
12546 1694 : GEN a = i < j ? gcoeff(C, j+1, i+1) : gen_0;
12547 1694 : if (i + j >= n)
12548 : {
12549 924 : GEN b = gcoeff(C, j+1, i+j-n+1);
12550 924 : a = flag < 0 ? addii(a,b) : subii(a,b);
12551 : }
12552 1694 : gel(v, i+1) = a;
12553 : }
12554 : }
12555 35 : return gc_GEN(av, RgM_to_RgXV(ZM_ker(M), 0));
12556 : }
12557 :
12558 : static int
12559 168 : zero_at_cusp(GEN mf, GEN F, GEN c)
12560 : {
12561 168 : GEN v = evalcusp(mf, F, c, LOWDEFAULTPREC);
12562 168 : return (gequal0(v) || gexpo(v) <= -62);
12563 : }
12564 : /* Compute list E of j such that F|_k g_j vanishes at oo: return [E, s(E)] */
12565 : static void
12566 14 : mffvanish(GEN mf, GEN F, GEN G, GEN cosets, GEN *pres, GEN *press)
12567 : {
12568 14 : long j, lc = lg(cosets), N = MF_get_N(mf);
12569 : GEN v, vs;
12570 14 : *pres = v = zero_zv(lc-1);
12571 14 : *press= vs = zero_zv(lc-1);
12572 105 : for (j = 1; j < lc; j++)
12573 : {
12574 91 : GEN ga = gel(cosets,j), c = mat2cusp(ga);
12575 91 : if (zero_at_cusp(mf, F, c))
12576 14 : v[j] = vs[ mftocoset_i(N, ZM_mulS(ga), cosets) ] = 1;
12577 77 : else if (!zero_at_cusp(mf, G, c))
12578 0 : pari_err_IMPL("divergent Petersson product");
12579 : }
12580 14 : }
12581 :
12582 : static GEN
12583 15190 : _RgX_coeff(GEN T, long n)
12584 15190 : { return typ(T) == t_POL && varn(T) == 0? RgX_coeff(T,n): T; }
12585 : static GEN
12586 140 : Haberland(GEN PF, GEN PG, GEN vEF, GEN vEG, long k)
12587 : {
12588 140 : GEN S = gen_0, vC = vecbinomial(k-2); /* vC[n+1] = (-1)^n binom(k-2,n) */
12589 140 : long n, j, l = lg(PG);
12590 406 : for (n = 2; n < k; n+=2) gel(vC,n) = negi(gel(vC,n));
12591 2583 : for (j = 1; j < l; j++)
12592 : {
12593 2443 : GEN PFj = gel(PF,j), PGj = gel(PG,j);
12594 10038 : for (n = 0; n <= k-2; n++)
12595 : {
12596 7595 : GEN a = _RgX_coeff(PGj, k-2-n), b = _RgX_coeff(PFj, n);
12597 7595 : a = Rg_embedall(a, vEG);
12598 7595 : b = Rg_embedall(b, vEF);
12599 7595 : a = conj_i(a); if (typ(a) == t_VEC) settyp(a, t_COL);
12600 : /* a*b = scalar or t_VEC or t_COL or t_MAT */
12601 7595 : S = gadd(S, gdiv(gmul(a,b), gel(vC,n+1)));
12602 : }
12603 : }
12604 140 : S = mulcxpowIs(gmul2n(S, 1-k), 1+k);
12605 140 : return vEF==vEG? real_i(S): S;
12606 : }
12607 : /* F1S, F2S both symbols, same mf */
12608 : static GEN
12609 14 : mfpeterssonnoncusp(GEN F1S, GEN F2S)
12610 : {
12611 14 : pari_sp av = avma;
12612 : GEN mf, F1, F2, GF1, GF2, P2, cosets, vE1, vE2, FE1, FE2, P;
12613 : GEN I, IP1, RHO, RHOP1, INF, res, ress;
12614 14 : const double height = sqrt(3.)/2;
12615 : long k, r, j, bitprec, prec;
12616 :
12617 14 : mf = fs_get_MF(F1S);
12618 14 : FE1 = fs_get_EF(F1S); F1 = gel(FE1, 1);
12619 14 : FE2 = fs_get_EF(F2S); F2 = gel(FE2, 1);
12620 14 : cosets = fs_get_cosets(F1S);
12621 14 : bitprec = minuu(fs_get_bitprec(F1S), fs_get_bitprec(F2S));
12622 14 : prec = nbits2prec(bitprec);
12623 14 : F1S = fs_set_expan(F1S, mfgaexpansionall(mf, FE1, cosets, height, prec));
12624 14 : if (F2S != F1S)
12625 14 : F2S = fs_set_expan(F2S, mfgaexpansionall(mf, FE2, cosets, height, prec));
12626 14 : k = MF_get_k(mf); r = lg(cosets) - 1;
12627 14 : vE1 = fs_get_vE(F1S);
12628 14 : vE2 = fs_get_vE(F2S);
12629 14 : I = gen_I();
12630 14 : IP1 = mkcomplex(gen_1,gen_1);
12631 14 : RHO = rootsof1u_cx(3, prec+EXTRAPREC64);
12632 14 : RHOP1 = gaddsg(1, RHO);
12633 14 : INF = mkoo();
12634 14 : mffvanish(mf, F1, F2, cosets, &res, &ress);
12635 14 : P2 = fs_get_pols(F2S);
12636 14 : GF1 = cgetg(r+1, t_VEC);
12637 14 : GF2 = cgetg(r+1, t_VEC); P = get_P(k, fetch_var(), prec);
12638 105 : for (j = 1; j <= r; j++)
12639 : {
12640 91 : GEN g = gel(cosets,j);
12641 91 : if (res[j]) {
12642 14 : gel(GF1,j) = mfsymboleval_direct(F1S, mkvec2(RHOP1,INF), g, P);
12643 14 : gel(GF2,j) = mfsymboleval_direct(F2S, mkvec2(I,IP1), g, P);
12644 77 : } else if (ress[j]) {
12645 7 : gel(GF1,j) = mfsymboleval_direct(F1S, mkvec2(RHOP1,RHO), g, P);
12646 7 : gel(GF2,j) = mfsymboleval_direct(F2S, mkvec2(I,INF), g, P);
12647 : } else {
12648 70 : gel(GF1,j) = mfsymboleval_direct(F1S, mkvec2(RHO,I), g, P);
12649 70 : gel(GF2,j) = gneg(gel(P2,j)); /* - symboleval(F2S, [0,oo] */
12650 : }
12651 : }
12652 14 : delete_var();
12653 14 : return gc_upto(av, gdivgu(Haberland(GF1,GF2, vE1,vE2, k), r));
12654 : }
12655 :
12656 : /* Petersson product of F and G, given by mfsymbol's [k > 1 integral] */
12657 : static GEN
12658 140 : mfpetersson_i(GEN FS, GEN GS)
12659 : {
12660 140 : pari_sp av = avma;
12661 : GEN mf, ESF, ESG, PF, PG, PH, CHI, cosets, vEF, vEG;
12662 : long k, r, j, N, bitprec, prec;
12663 :
12664 140 : if (!checkfs_i(FS)) pari_err_TYPE("mfpetersson",FS);
12665 140 : mf = fs_get_MF(FS);
12666 140 : ESF = fs_get_vES(FS);
12667 140 : if (!GS) GS = FS;
12668 : else
12669 : {
12670 35 : if (!checkfs_i(GS)) pari_err_TYPE("mfpetersson",GS);
12671 35 : if (!mfs_checkmf(GS, mf))
12672 0 : pari_err_TYPE("mfpetersson [different mf]", mkvec2(FS,GS));
12673 : }
12674 140 : ESG = fs_get_vES(GS);
12675 140 : if (!gequal0(gel(ESF,1)) || !gequal0(gel(ESG,1)))
12676 14 : return mfpeterssonnoncusp(FS, GS);
12677 126 : if (gequal0(gel(ESF,2)) || gequal0(gel(ESG,2))) return gc_const(av, gen_0);
12678 126 : N = MF_get_N(mf);
12679 126 : k = MF_get_k(mf);
12680 126 : CHI = MF_get_CHI(mf);
12681 126 : PF = fs_get_pols(FS); vEF = fs_get_vE(FS);
12682 126 : PG = fs_get_pols(GS); vEG = fs_get_vE(GS);
12683 126 : cosets = fs_get_cosets(FS);
12684 126 : bitprec = minuu(fs_get_bitprec(FS), fs_get_bitprec(GS));
12685 126 : prec = nbits2prec(bitprec);
12686 126 : r = lg(PG)-1;
12687 126 : PH = cgetg(r+1, t_VEC);
12688 2478 : for (j = 1; j <= r; j++)
12689 : {
12690 2352 : GEN ga = gel(cosets,j), P, P1, Pm1;
12691 : long D;
12692 2352 : P = gel(PG, mftocoset_iD(N, ZM_mulTi(ga), cosets, &D));
12693 2352 : if (typ(P) == t_POL && varn(P) == 0)
12694 : {
12695 1372 : P1 = RgX_Rg_translate(P, gen_1);
12696 1372 : P1 = RgX_Rg_mul(P1, mfcharcxeval(CHI, D, prec));
12697 : }
12698 : else
12699 980 : P1 = gmul(P, mfcharcxeval(CHI, D, prec));
12700 :
12701 2352 : P = gel(PG, mftocoset_iD(N, ZM_mulT(ga), cosets, &D));
12702 2352 : if (typ(P) == t_POL && varn(P) == 0)
12703 : {
12704 1372 : Pm1 = RgX_Rg_translate(P, gen_m1);
12705 1372 : Pm1 = RgX_Rg_mul(Pm1, mfcharcxeval(CHI, D, prec));
12706 : }
12707 : else
12708 980 : Pm1 = gmul(P, mfcharcxeval(CHI, D, prec));
12709 2352 : gel(PH,j) = gsub(P1, Pm1);
12710 : }
12711 126 : return gc_upto(av, gdivgu(Haberland(PF, PH, vEF, vEG, k), 6*r));
12712 : }
12713 :
12714 : /****************************************************************/
12715 : /* Petersson products using Nelson-Collins */
12716 : /****************************************************************/
12717 : /* Compute W(k,z) = sum_{m >= 1} (mz)^{k-1}(mzK_{k-2}(mz)-K_{k-1}(mz))
12718 : * for z>0 and absolute accuracy < 2^{-B}.
12719 : * K_k(x) ~ (Pi/(2x))^{1/2} e^{-x} */
12720 :
12721 : static void
12722 10304 : Wparams(GEN *ph, long *pN, long k, double x, long prec)
12723 : {
12724 10304 : double B = prec2nbits(prec) + 10;
12725 10304 : double C = B + k*log(x)/M_LN2 + 1, D = C*M_LN2 + 2.065;
12726 10304 : double F = 2 * M_LN2 * (C - 1 + dbllog2(mpfact(k))) / x;
12727 10304 : double T = log(F) * (1 + 2*k/x/F), PI2 = M_PI*M_PI;
12728 10304 : *pN = (long)ceil((T/PI2) * (D + log(D/PI2)));
12729 10304 : *ph = gprec_w(dbltor(T / *pN), prec);
12730 10304 : }
12731 :
12732 : static void
12733 10304 : Wcoshall(GEN *pCH, GEN *pCHK, GEN *pCHK1, GEN h, long N, long k, long prec)
12734 : {
12735 10304 : GEN CH, CHK, CHK1, z = gexp(h, prec);
12736 10304 : GEN PO = gpowers(z, N), POK1 = gpowers(gpowgs(z, k-1), N);
12737 10304 : GEN E = ginv(gel(PO, N + 1)); /* exp(-hN) */
12738 10304 : GEN E1 = ginv(gel(POK1, N + 1)); /* exp(-(k-1)h) */
12739 : long j;
12740 10304 : *pCH = CH = cgetg(N+1, t_VEC);
12741 10304 : *pCHK = CHK = cgetg(N+1, t_VEC);
12742 10304 : *pCHK1 = CHK1 = cgetg(N+1, t_VEC);
12743 146048 : for (j = 1; j <= N; j++)
12744 : {
12745 135744 : GEN eh = gel(PO, j+1), emh = gmul(gel(PO, N-j+1), E); /* e^{jh}, e^{-jh} */
12746 135744 : GEN ek1h = gel(POK1, j+1), ek1mh = gmul(gel(POK1, N-j+1), E1);
12747 135744 : gel(CH, j) = gmul2n(gadd(eh, emh), -1); /* cosh(jh) */
12748 135744 : gel(CHK1,j) = gmul2n(gadd(ek1h, ek1mh), -1); /* cosh((k-1)jh) */
12749 135744 : gel(CHK, j) = gmul2n(gadd(gmul(eh, ek1h), gmul(emh, ek1mh)), -1);
12750 : }
12751 10304 : }
12752 :
12753 : /* computing W(k,x) via integral */
12754 : static GEN
12755 10304 : Wint(long k, GEN vP, GEN x, long prec)
12756 : {
12757 : GEN P, P1, S1, S, h, CH, CHK, CHK1;
12758 : long N, j;
12759 10304 : Wparams(&h, &N, k, gtodouble(x), prec);
12760 10304 : Wcoshall(&CH, &CHK, &CHK1, h, N, k, prec);
12761 10304 : P = gel(vP, k+1); P1 = gel(vP, k); S = S1 = NULL;
12762 156352 : for (j = 0; j <= N; j++)
12763 : {
12764 146048 : GEN eh = gexp(j? gmul(x, gel(CH, j)): x, prec);
12765 146048 : GEN eh1 = gsubgs(eh, 1), eh1k = gpowgs(eh1, k), t1, t;
12766 146048 : t = gdiv(poleval(P, eh), gmul(eh1, eh1k));
12767 146048 : t1 = gdiv(poleval(P1, eh), eh1k);
12768 146048 : if (j)
12769 : {
12770 135744 : S = gadd(S, gmul(t, gel(CHK, j)));
12771 135744 : S1 = gadd(S1, gmul(t1, gel(CHK1, j)));
12772 : }
12773 : else
12774 : {
12775 10304 : S = gmul2n(t, -1);
12776 10304 : S1 = gmul2n(t1, -1);
12777 : }
12778 : }
12779 10304 : return gmul(gmul(h, gpowgs(x, k-1)), gsub(gmul(x, S), gmulsg(2*k-1, S1)));
12780 : }
12781 :
12782 : static GEN
12783 21 : get_vP(long k)
12784 : {
12785 21 : GEN P, v = cgetg(k+2, t_VEC), Q = deg1pol_shallow(gen_1,gen_m1,0);
12786 : long j;
12787 21 : gel(v,1) = gen_1;
12788 21 : gel(v,2) = P = pol_x(0);
12789 28 : for (j = 2; j <= k; j++)
12790 7 : gel(v,j+1) = P = RgX_shift_shallow(gsub(gmulsg(j, P),
12791 : gmul(Q, ZX_deriv(P))), 1);
12792 21 : return v;
12793 : }
12794 : /* vector of (-1)^j(1/(exp(x)-1))^(j) [x = z] * z^j for 0<=j<=r */
12795 : static GEN
12796 63742 : VS(long r, GEN z, GEN V, long prec)
12797 : {
12798 63742 : GEN e = gexp(z, prec), c = ginv(gsubgs(e,1));
12799 63742 : GEN T = gpowers0(gmul(c, z), r, c);
12800 : long j;
12801 63742 : V = gsubst(V, 0, e);
12802 143864 : for (j = 1; j <= r + 1; j++) gel(V,j) = gmul(gel(V,j), gel(T,j));
12803 63742 : return V;
12804 : }
12805 :
12806 : /* U(r,x)=sum_{m >= 1} (mx)^k K_k(mx), k = r+1/2 */
12807 : static GEN
12808 71932 : Unelson(long r, GEN V)
12809 : {
12810 71932 : GEN S = gel(V,r+1), C = gen_1; /* (r+j)! / j! / (r-j)! */
12811 : long j;
12812 71932 : if (!r) return S;
12813 40950 : for (j = 1; j <= r; j++)
12814 : {
12815 24570 : C = gdivgu(gmulgu(C, (r+j)*(r-j+1)), j);
12816 24570 : S = gadd(S, gmul2n(gmul(C, gel(V, r-j+1)), -j));
12817 : }
12818 16380 : return S;
12819 : }
12820 : /* W(r+1/2,z) / sqrt(Pi/2) */
12821 : static GEN
12822 63742 : Wint2(long r, GEN vP, GEN z, long prec)
12823 : {
12824 63742 : GEN R, V = VS(r, z, vP, prec);
12825 63742 : R = Unelson(r, V);
12826 63742 : if (r) R = gsub(R, gmulsg(2*r, Unelson(r-1, V)));
12827 63742 : return R;
12828 : }
12829 : typedef GEN(*Wfun_t)(long, GEN, GEN, long);
12830 : static GEN
12831 74046 : WfromZ(GEN Z, GEN vP, GEN gkm1, Wfun_t W, long k, GEN pi4, long prec)
12832 : {
12833 74046 : pari_sp av = avma;
12834 74046 : GEN Zk = gpow(Z, gkm1, prec), z = gmul(pi4, gsqrt(Z,prec));
12835 74046 : return gc_upto(av, gdiv(W(k, vP, z, prec), Zk));
12836 : }
12837 : /* mf a true mf or an fs2 */
12838 : static GEN
12839 21 : fs2_init(GEN mf, GEN F, long bit)
12840 : {
12841 21 : pari_sp av = avma;
12842 21 : long i, l, lim, N, k, k2, prec = nbits2prec(bit);
12843 : GEN DEN, cusps, tab, gk, gkm1, W0, vW, vVW, vVF, vP, al0;
12844 21 : GEN vE = mfgetembed(F, prec), pi4 = Pi2n(2, prec);
12845 : Wfun_t Wf;
12846 :
12847 21 : if (lg(mf) == 7)
12848 : {
12849 21 : vW = cusps = NULL; /* true mf */
12850 21 : DEN = tab = NULL; /* -Wall */
12851 : }
12852 : else
12853 : { /* mf already an fs2, reset if its precision is too low */
12854 0 : vW = (fs2_get_bitprec(mf) < bit)? NULL: fs2_get_W(mf);
12855 0 : cusps = fs2_get_cusps(mf);
12856 0 : DEN = fs2_get_den(mf);
12857 0 : mf = fs2_get_MF(mf);
12858 : }
12859 21 : N = MF_get_N(mf);
12860 21 : gk = MF_get_gk(mf); gkm1 = gsubgs(gk, 1);
12861 21 : k2 = itos(gmul2n(gk,1));
12862 21 : Wf = odd(k2)? Wint2: Wint;
12863 21 : k = k2 >> 1; vP = get_vP(k);
12864 21 : if (vW) lim = (lg(gel(vW,1)) - 2) / N; /* vW[1] attached to cusp 0, width N */
12865 : else
12866 : { /* true mf */
12867 21 : double B = (bit + 10)*M_LN2;
12868 21 : double L = (B + k2*log(B)/2 + k2*k2*log(B)/(4*B)) / (4*M_PI);
12869 : long n, Lw;
12870 21 : lim = ((long)ceil(L*L));
12871 21 : Lw = N*lim;
12872 21 : tab = cgetg(Lw+1,t_VEC);
12873 59157 : for (n = 1; n <= Lw; n++)
12874 59136 : gel(tab,n) = WfromZ(uutoQ(n,N), vP, gkm1, Wf, k, pi4, prec);
12875 21 : if (!cusps) cusps = mfcusps_i(N);
12876 21 : DEN = gmul2n(gmulgu(gpow(Pi2n(3, prec), gkm1, prec), mypsiu(N)), -2);
12877 21 : if (odd(k2)) DEN = gdiv(DEN, sqrtr_abs(Pi2n(-1,prec)));
12878 : }
12879 21 : l = lg(cusps);
12880 21 : vVF = cgetg(l, t_VEC);
12881 21 : vVW = cgetg(l, t_VEC);
12882 21 : al0 = cgetg(l, t_VECSMALL);
12883 21 : W0 = k2==1? ginv(pi4): gen_0;
12884 203 : for (i = 1; i < l; i++)
12885 : {
12886 : long A, C, w, wi, Lw, n;
12887 : GEN VF, W, paramsF, al;
12888 182 : (void)cusp_AC(gel(cusps,i), &A,&C);
12889 182 : wi = ugcd(N, C*C); w = N / wi; Lw = w * lim;
12890 182 : VF = mfslashexpansion(mf, F, cusp2mat(A,C), Lw, 0, ¶msF, prec);
12891 : /* paramsF[2] = w */
12892 182 : al = gel(paramsF, 1); if (gequal0(al)) al = NULL;
12893 100240 : for (n = 0; n <= Lw; n++)
12894 : {
12895 100058 : GEN a = gel(VF,n+1);
12896 100058 : gel(VF,n+1) = gequal0(a)? gen_0: Rg_embedall(a, vE);
12897 : }
12898 182 : if (vW)
12899 0 : W = gel(vW, i);
12900 : else
12901 : {
12902 182 : W = cgetg(Lw+2, t_VEC);
12903 100240 : for (n = 0; n <= Lw; n++)
12904 100058 : gel(W, n+1) = al? WfromZ(gadd(al,uutoQ(n,w)),vP,gkm1,Wf,k,pi4, prec)
12905 100058 : : (n? gel(tab, n * wi): W0);
12906 : }
12907 182 : al0[i] = !al;
12908 182 : gel(vVF, i) = VF;
12909 182 : gel(vVW, i) = W;
12910 : }
12911 21 : if (k2 <= 1) al0 = zero_zv(l-1); /* no need to test for convergence */
12912 21 : return gc_GEN(av, mkvecn(7, mf,vVW,cusps,vVF,utoipos(bit),al0,DEN));
12913 : }
12914 :
12915 : static GEN
12916 21 : mfpetersson2(GEN Fs, GEN Gs)
12917 : {
12918 21 : pari_sp av = avma;
12919 21 : GEN VC, RES, vF, vG, vW = fs2_get_W(Fs), al0 = fs2_get_al0(Fs);
12920 21 : long N = MF_get_N(fs2_get_MF(Fs)), j, lC;
12921 :
12922 21 : VC = fs2_get_cusps(Fs); lC = lg(VC);
12923 21 : vF = fs2_get_F(Fs);
12924 21 : vG = Gs? fs2_get_F(Gs): vF;
12925 21 : RES = gen_0;
12926 203 : for (j = 1; j < lC; j++)
12927 : {
12928 182 : GEN W = gel(vW,j), VF = gel(vF,j), VG = gel(vG,j), T = gen_0;
12929 182 : long A, C, w, n, L = lg(W);
12930 182 : pari_sp av = avma;
12931 182 : (void)cusp_AC(gel(VC,j), &A,&C); w = N/ugcd(N, C*C);
12932 182 : if (al0[j] && !isintzero(gel(VF,1)) && !isintzero(gel(VG,1)))
12933 0 : pari_err_IMPL("divergent Petersson product");
12934 100240 : for (n = 1; n < L; n++)
12935 : {
12936 100058 : GEN b = gel(VF,n), a = gel(VG,n);
12937 100058 : if (!isintzero(a) && !isintzero(b))
12938 : {
12939 79964 : T = gadd(T, gmul(gel(W,n), gmul(conj_i(a),b)));
12940 79964 : if (gc_needed(av,2)) T = gc_upto(av,T);
12941 : }
12942 : }
12943 182 : if (w != 1) T = gmulgu(T,w);
12944 182 : RES = gc_upto(av, gadd(RES, T));
12945 : }
12946 21 : if (!Gs) RES = real_i(RES);
12947 21 : return gc_upto(av, gdiv(RES, fs2_get_den(Fs)));
12948 : }
12949 :
12950 : static long
12951 161 : symbol_type(GEN F)
12952 : {
12953 161 : if (checkfs_i(F)) return 1;
12954 21 : if (checkfs2_i(F)) return 2;
12955 0 : return 0;
12956 : }
12957 : static int
12958 35 : symbol_same_mf(GEN F, GEN G) { return gequal(gmael(F,1,1), gmael(G,1,1)); }
12959 : GEN
12960 126 : mfpetersson(GEN F, GEN G)
12961 : {
12962 126 : long tF = symbol_type(F);
12963 126 : if (!tF) pari_err_TYPE("mfpetersson",F);
12964 126 : if (G)
12965 : {
12966 35 : long tG = symbol_type(G);
12967 35 : if (!tG) pari_err_TYPE("mfpetersson",F);
12968 35 : if (tF != tG || !symbol_same_mf(F,G))
12969 0 : pari_err_TYPE("mfpetersson [incompatible symbols]", mkvec2(F,G));
12970 : }
12971 126 : return (tF == 1)? mfpetersson_i(F, G): mfpetersson2(F, G);
12972 : }
12973 :
12974 : /****************************************************************/
12975 : /* projective Galois representation, weight 1 */
12976 : /****************************************************************/
12977 : static void
12978 392 : moreorders(long N, GEN CHI, GEN F, GEN *pP, GEN *pO, ulong *bound)
12979 : {
12980 392 : pari_sp av = avma;
12981 : forprime_t iter;
12982 392 : ulong a = *bound+1, b = 2*(*bound), p;
12983 392 : long i = 1;
12984 392 : GEN P, O, V = mfcoefs_i(F, b, 1);
12985 392 : *bound = b;
12986 392 : P = cgetg(b-a+2, t_VECSMALL);
12987 392 : O = cgetg(b-a+2, t_VECSMALL);
12988 392 : u_forprime_init(&iter, a, b);
12989 2310 : while((p = u_forprime_next(&iter))) if (N % p)
12990 : {
12991 1813 : O[i] = mffindrootof1(V, p, CHI);
12992 1813 : P[i++] = p;
12993 : }
12994 392 : setlg(P, i); *pP = shallowconcat(*pP, P);
12995 392 : setlg(O, i); *pO = shallowconcat(*pO, O);
12996 392 : (void)gc_all(av, 2, pP, pO);
12997 392 : }
12998 :
12999 : static GEN
13000 182 : search_abelian(GEN nf, long n, long k, GEN N, GEN CHI, GEN F,
13001 : GEN *pP, GEN *pO, ulong *bound, long prec)
13002 : {
13003 182 : pari_sp av = avma;
13004 : GEN bnr, cond, H, cyc, gn, T, Bquo, P, E;
13005 182 : long sN = itos(N), r1 = nf_get_r1(nf), i, j, d;
13006 :
13007 182 : cond = idealfactor(nf, N);
13008 182 : P = gel(cond,1);
13009 182 : E = gel(cond,2);
13010 679 : for (i = j = 1; i < lg(P); i++)
13011 : {
13012 497 : GEN pr = gel(P,i), Ej = gen_1;
13013 497 : long p = itos(pr_get_p(pr));
13014 497 : if (p == n)
13015 : {
13016 98 : long e = pr_get_e(pr); /* 1 + [e*p/(p-1)] */
13017 98 : Ej = utoipos(1 + (e*p) / (p-1));
13018 : }
13019 : else
13020 : {
13021 399 : long f = pr_get_f(pr);
13022 399 : if (Fl_powu(p % n, f, n) != 1) continue;
13023 : }
13024 462 : gel(P,j) = pr;
13025 462 : gel(E,j) = Ej; j++;
13026 : }
13027 182 : setlg(P,j);
13028 182 : setlg(E,j);
13029 182 : cond = mkvec2(cond, const_vec(r1, gen_1));
13030 182 : bnr = Buchraymod(Buchall(nf, nf_FORCE, prec), cond, nf_INIT, utoipos(n));
13031 182 : cyc = bnr_get_cyc(bnr);
13032 182 : d = lg(cyc)-1;
13033 182 : H = zv_diagonal(ZV_to_Flv(cyc, n));
13034 182 : gn = utoi(n);
13035 182 : for (i = 1;;)
13036 : {
13037 2646 : for(j = 2; i < lg(*pO); i++)
13038 : {
13039 2072 : long o, q = (*pP)[i];
13040 2072 : GEN pr = idealprimedec_galois(nf, stoi(q));
13041 2072 : o = ((*pO)[i] / pr_get_f(pr)) % n;
13042 2072 : if (o)
13043 : {
13044 1442 : GEN v = ZV_to_Flv(isprincipalray(bnr, pr), n);
13045 1442 : H = vec_append(H, Flv_Fl_mul(v, o, n));
13046 : }
13047 : }
13048 574 : H = Flm_image(H, n); if (lg(cyc)-lg(H) <= k) break;
13049 392 : moreorders(sN, CHI, F, pP, pO, bound);
13050 : }
13051 182 : H = hnfmodid(shallowconcat(zm_to_ZM(H), diagonal_shallow(cyc)), gn);
13052 :
13053 182 : Bquo = cgetg(k+1, t_MAT);
13054 812 : for (i = j = 1; i <= d; i++)
13055 630 : if (!equali1(gcoeff(H,i,i))) gel(Bquo,j++) = col_ei(d,i);
13056 :
13057 441 : for (i = 1, T = NULL; i<=k; i++)
13058 : {
13059 259 : GEN Hi = hnfmodid(shallowconcat(H, vecsplice(Bquo,i)), gn);
13060 259 : GEN pol = rnfkummer(bnr, Hi, prec);
13061 259 : T = T? nfcompositum(nf, T, pol, 2): pol;
13062 : }
13063 182 : T = rnfequation(nf, T); return gc_all(av, 3, &T, pP, pO);
13064 : }
13065 :
13066 : static GEN
13067 77 : search_solvable(GEN LG, GEN mf, GEN F, long prec)
13068 : {
13069 77 : GEN N = MF_get_gN(mf), CHI = MF_get_CHI(mf), pol, O, P, nf, Nfa;
13070 77 : long i, l = lg(LG), v = fetch_var();
13071 77 : ulong bound = 1;
13072 77 : O = cgetg(1, t_VECSMALL); /* projective order of rho(Frob_p) */
13073 77 : P = cgetg(1, t_VECSMALL);
13074 77 : Nfa = Z_factor(N);
13075 77 : pol = pol_x(v);
13076 259 : for (i = 1; i < l; i++)
13077 : { /* n prime, find a (Z/nZ)^k - extension */
13078 182 : GEN G = gel(LG,i);
13079 182 : long n = G[1], k = G[2];
13080 182 : nf = nfinitred(mkvec2(pol,Nfa), prec);
13081 182 : pol = search_abelian(nf, n, k, N, CHI, F, &P, &O, &bound, prec);
13082 182 : setvarn(pol,v);
13083 : }
13084 77 : delete_var(); setvarn(pol,0); return pol;
13085 : }
13086 :
13087 : static GEN
13088 0 : search_A5(GEN mf, GEN F)
13089 : {
13090 0 : GEN CHI = MF_get_CHI(mf), O, P, L;
13091 0 : long N = MF_get_N(mf), i, j, lL, nd, r;
13092 0 : ulong bound = 1;
13093 0 : r = radicalu(N);
13094 0 : L = veccond_to_A5(zv_z_mul(divisorsu(N/r),r), 2); lL = lg(L); nd = lL-1;
13095 0 : if (nd == 1) return gmael(L,1,1);
13096 0 : O = cgetg(1, t_VECSMALL); /* projective order of rho(Frob_p) */
13097 0 : P = cgetg(1, t_VECSMALL);
13098 0 : for(i = 1; nd > 1; )
13099 : {
13100 : long l;
13101 0 : moreorders(N, CHI, F, &P, &O, &bound);
13102 0 : l = lg(P);
13103 0 : for ( ; i < l; i++)
13104 : {
13105 0 : ulong p = P[i], f = O[i];
13106 0 : for (j = 1; j < lL; j++)
13107 0 : if (gel(L,j))
13108 : {
13109 0 : GEN FE = ZpX_primedec(gmael(L,j,1), utoi(p)), F = gel(FE,1);
13110 0 : long nF = lg(F)-1;
13111 0 : if (!equaliu(gel(F, nF), f)) { gel(L,j) = NULL; nd--; }
13112 : }
13113 0 : if (nd <= 1) break;
13114 : }
13115 : }
13116 0 : for (j = 1; j < lL; j++)
13117 0 : if (gel(L,j)) return gmael(L,j,1);
13118 0 : return NULL;
13119 : }
13120 :
13121 : GEN
13122 77 : mfgaloisprojrep(GEN mf, GEN F, long prec)
13123 : {
13124 77 : pari_sp av = avma;
13125 77 : GEN LG = NULL;
13126 77 : if (!checkMF_i(mf) && !checkmf_i(F)) pari_err_TYPE("mfgaloisrep", F);
13127 77 : switch( itos(mfgaloistype(mf,F)) )
13128 : {
13129 49 : case 0: case -12:
13130 49 : LG = mkvec2(mkvecsmall2(3,1), mkvecsmall2(2,2)); break;
13131 28 : case -24:
13132 28 : LG = mkvec3(mkvecsmall2(2,1), mkvecsmall2(3,1), mkvecsmall2(2,2)); break;
13133 0 : case -60: return gc_GEN(av, search_A5(mf, F));
13134 0 : default: pari_err_IMPL("mfgaloisprojrep for types D_n");
13135 : }
13136 77 : return gc_GEN(av, search_solvable(LG, mf, F, prec));
13137 : }
|