Line data Source code
1 : /* Copyright (C) 2015 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : /********************************************************************/
16 : /** **/
17 : /** L-functions **/
18 : /** **/
19 : /********************************************************************/
20 :
21 : #include "pari.h"
22 : #include "paripriv.h"
23 :
24 : #define DEBUGLEVEL DEBUGLEVEL_lfun
25 :
26 : /*******************************************************************/
27 : /* Accessors */
28 : /*******************************************************************/
29 :
30 : static GEN
31 12605 : mysercoeff(GEN x, long n)
32 : {
33 12605 : long N = n - valser(x);
34 12605 : return (N < 0)? gen_0: gel(x, N+2);
35 : }
36 :
37 : long
38 76869 : ldata_get_type(GEN ldata) { return mael3(ldata, 1, 1, 1); }
39 :
40 : GEN
41 74774 : ldata_get_an(GEN ldata) { return gel(ldata, 1); }
42 :
43 : GEN
44 59822 : ldata_get_dual(GEN ldata) { return gel(ldata, 2); }
45 :
46 : long
47 2820 : ldata_isreal(GEN ldata) { return isintzero(gel(ldata, 2)); }
48 :
49 : GEN
50 349224 : ldata_get_gammavec(GEN ldata) { return gel(ldata, 3); }
51 :
52 : long
53 26129 : ldata_get_degree(GEN ldata) { return lg(gel(ldata, 3))-1; }
54 :
55 : GEN
56 154574 : ldata_get_k(GEN ldata)
57 : {
58 154574 : GEN w = gel(ldata,4);
59 154574 : if (typ(w) == t_VEC) w = gel(w,1);
60 154574 : return w;
61 : }
62 :
63 : /* a_n = O(n^{k1 + epsilon}) */
64 : GEN
65 105 : ldata_get_k1(GEN ldata)
66 : {
67 105 : GEN w = gel(ldata,4);
68 105 : if (typ(w) == t_VEC) return gel(w,2);
69 : /* by default, assume that k1 = k-1 and even (k-1)/2 for entire functions */
70 105 : w = gaddgs(w,-1);
71 105 : return ldata_get_residue(ldata)? w: gmul2n(w, -1);
72 : }
73 :
74 : /* a_n = O(n^{k1 + epsilon}) */
75 : static double
76 91534 : ldata_get_k1_dbl(GEN ldata)
77 : {
78 91534 : GEN w = gel(ldata,4);
79 : double k;
80 91534 : if (typ(w) == t_VEC) return gtodouble(gel(w,2));
81 : /* by default, assume that k1 = k-1 and even (k-1)/2 for entire functions */
82 90085 : k = gtodouble(w);
83 90085 : return ldata_get_residue(ldata)? k-1: (k-1)/2.;
84 : }
85 :
86 : GEN
87 272747 : ldata_get_conductor(GEN ldata) { return gel(ldata, 5); }
88 :
89 : GEN
90 105539 : ldata_get_rootno(GEN ldata) { return gel(ldata, 6); }
91 :
92 : GEN
93 175630 : ldata_get_residue(GEN ldata) { return lg(ldata) == 7 ? NULL: gel(ldata, 7); }
94 :
95 : long
96 147249 : linit_get_type(GEN linit) { return mael(linit, 1, 1); }
97 :
98 : GEN
99 197211 : linit_get_ldata(GEN linit) { return gel(linit, 2); }
100 :
101 : GEN
102 249330 : linit_get_tech(GEN linit) { return gel(linit, 3); }
103 :
104 : long
105 300325 : is_linit(GEN data)
106 : {
107 184065 : return lg(data) == 4 && typ(data) == t_VEC
108 484390 : && typ(gel(data, 1)) == t_VECSMALL;
109 : }
110 :
111 : GEN
112 31967 : lfun_get_step(GEN tech) { return gmael(tech, 2, 1);}
113 :
114 : GEN
115 31967 : lfun_get_pol(GEN tech) { return gmael(tech, 2, 2);}
116 :
117 : GEN
118 5305 : lfun_get_Residue(GEN tech) { return gmael(tech, 2, 3);}
119 :
120 : GEN
121 50054 : lfun_get_k2(GEN tech) { return gmael(tech, 3, 1);}
122 :
123 : GEN
124 19354 : lfun_get_w2(GEN tech) { return gmael(tech, 3, 2);}
125 :
126 : GEN
127 19354 : lfun_get_expot(GEN tech) { return gmael(tech, 3, 3);}
128 :
129 : GEN
130 9940 : lfun_get_factgammavec(GEN tech) { return gmael(tech, 3, 4); }
131 :
132 : /* Handle complex Vga whose sum is real */
133 : static GEN
134 103441 : sumVga(GEN Vga) { return real_i(vecsum(Vga)); }
135 : /* sum_i max (Im v[i],0) */
136 : static double
137 27092 : sumVgaimpos(GEN v)
138 : {
139 27092 : double d = 0.;
140 27092 : long i, l = lg(v);
141 74654 : for (i = 1; i < l; i++)
142 : {
143 47562 : GEN c = imag_i(gel(v,i));
144 47562 : if (gsigne(c) > 0) d += gtodouble(c);
145 : }
146 27092 : return d;
147 : }
148 :
149 : static long
150 42402 : vgaell(GEN Vga)
151 : {
152 42402 : if (lg(Vga) == 3)
153 30628 : { GEN c = gsub(gel(Vga,1), gel(Vga,2)); return gequal1(c) || gequalm1(c); }
154 11774 : return 0;
155 : }
156 : int
157 87073 : Vgaeasytheta(GEN Vga) { return lg(Vga)-1 == 1 || vgaell(Vga); }
158 : /* return b(n) := a(n) * n^c, when Vgaeasytheta(Vga) is set */
159 : static GEN
160 18627 : antwist(GEN an, GEN Vga, long prec)
161 : {
162 : long l, i;
163 18627 : GEN b, c = vecmin(Vga);
164 18627 : if (gequal0(c)) return an;
165 4382 : l = lg(an); b = cgetg(l, t_VEC);
166 4382 : if (gequal1(c))
167 : {
168 3626 : if (typ(an) == t_VECSMALL)
169 17647 : for (i = 1; i < l; i++) gel(b,i) = mulss(an[i], i);
170 : else
171 41356 : for (i = 1; i < l; i++) gel(b,i) = gmulgu(gel(an,i), i);
172 : }
173 : else
174 : {
175 756 : GEN v = vecpowug(l-1, c, prec);
176 756 : if (typ(an) == t_VECSMALL)
177 0 : for (i = 1; i < l; i++) gel(b,i) = gmulsg(an[i], gel(v,i));
178 : else
179 34048 : for (i = 1; i < l; i++) gel(b,i) = gmul(gel(an,i), gel(v,i));
180 : }
181 4382 : return b;
182 : }
183 :
184 : static GEN
185 9646 : theta_dual(GEN theta, GEN bn)
186 : {
187 9646 : if (typ(bn)==t_INT) return NULL;
188 : else
189 : {
190 77 : GEN thetad = shallowcopy(theta), ldata = linit_get_ldata(theta);
191 77 : GEN Vga = ldata_get_gammavec(ldata);
192 77 : GEN tech = shallowcopy(linit_get_tech(theta));
193 77 : GEN an = theta_get_an(tech);
194 77 : long prec = nbits2prec(theta_get_bitprec(tech));
195 77 : GEN vb = ldata_vecan(bn, lg(an)-1, prec);
196 77 : if (!theta_get_m(tech) && Vgaeasytheta(Vga)) vb = antwist(vb, Vga, prec);
197 77 : gel(tech,1) = vb;
198 77 : gel(thetad,3) = tech; return thetad;
199 : }
200 : }
201 :
202 : static GEN
203 84608 : domain_get_dom(GEN domain) { return gel(domain,1); }
204 : static long
205 25582 : domain_get_der(GEN domain) { return mael2(domain, 2, 1); }
206 : static long
207 36957 : domain_get_bitprec(GEN domain) { return mael2(domain, 2, 2); }
208 : GEN
209 85175 : lfun_get_domain(GEN tech) { return gel(tech,1); }
210 : long
211 91 : lfun_get_bitprec(GEN tech){ return domain_get_bitprec(lfun_get_domain(tech)); }
212 : GEN
213 59425 : lfun_get_dom(GEN tech) { return domain_get_dom(lfun_get_domain(tech)); }
214 :
215 : GEN
216 2575 : lfunprod_get_fact(GEN tech) { return gel(tech, 2); }
217 :
218 : GEN
219 52178 : theta_get_an(GEN tdata) { return gel(tdata, 1);}
220 : GEN
221 8043 : theta_get_K(GEN tdata) { return gel(tdata, 2);}
222 : GEN
223 5929 : theta_get_R(GEN tdata) { return gel(tdata, 3);}
224 : long
225 65646 : theta_get_bitprec(GEN tdata) { return itos(gel(tdata, 4));}
226 : long
227 101528 : theta_get_m(GEN tdata) { return itos(gel(tdata, 5));}
228 : GEN
229 53732 : theta_get_tdom(GEN tdata) { return gel(tdata, 6);}
230 : GEN
231 62692 : theta_get_isqrtN(GEN tdata) { return gel(tdata, 7);}
232 :
233 : /*******************************************************************/
234 : /* Helper functions related to Gamma products */
235 : /*******************************************************************/
236 : /* x != 0 */
237 : static int
238 6979 : serisscalar(GEN x)
239 : {
240 : long i;
241 6979 : if (valser(x)) return 0;
242 9296 : for (i = lg(x)-1; i > 3; i--) if (!gequal0(gel(x,i))) return 0;
243 6727 : return 1;
244 : }
245 :
246 : /* return -itos(s) >= 0 if scalar s is (approximately) equal to a nonpositive
247 : * integer, and -1 otherwise */
248 : static long
249 21245 : isnegint(GEN s)
250 : {
251 21245 : GEN r = ground(real_i(s));
252 21245 : if (signe(r) <= 0 && gequal(s, r)) return -itos(r);
253 21119 : return -1;
254 : }
255 : /* if s = a + O(x^n), a <= 0 integer, replace by a + b*x^n + O(x^(n+1)) */
256 : static GEN
257 7000 : serextendifnegint(GEN s, GEN b, long *ext)
258 : {
259 7000 : if (!signe(s) || (serisscalar(s) && isnegint(gel(s,2)) >= 0))
260 : {
261 112 : long l = lg(s);
262 112 : GEN t = cgetg(l+1, t_SER);
263 301 : gel(t, l) = b; while (--l > 1) gel(t,l) = gel(s,l);
264 112 : if (gequal0(gel(t,2))) gel(t,2) = gen_0;
265 112 : t[1] = s[1]; s = normalizeser(t); *ext = 1;
266 : }
267 7000 : return s;
268 : }
269 :
270 : /* r/x + O(1), r != 0 */
271 : static GEN
272 5131 : serpole(GEN r)
273 : {
274 5131 : GEN s = cgetg(3, t_SER);
275 5131 : s[1] = evalsigne(1)|evalvalser(-1)|evalvarn(0);
276 5131 : gel(s,2) = r; return s;
277 : }
278 : /* a0 + a1 x + O(x^e), e >= 0 */
279 : static GEN
280 8267 : deg1ser_shallow(GEN a1, GEN a0, long v, long e)
281 8267 : { return RgX_to_ser(deg1pol_shallow(a1, a0, v), e+2); }
282 :
283 : /* pi^(-s/2) Gamma(s/2) */
284 : static GEN
285 10416 : gamma_R(GEN s, long *ext, long prec)
286 : {
287 10416 : GEN s2 = gmul2n(s, -1);
288 : long ms;
289 :
290 10416 : if (typ(s) == t_SER)
291 4900 : s2 = serextendifnegint(s2, ghalf, ext);
292 5516 : else if ((ms = isnegint(s2)) >= 0)
293 : {
294 35 : GEN r = gmul(powPis(stoi(ms),prec), gdivsg(odd(ms)? -2: 2, mpfact(ms)));
295 35 : return serpole(r);
296 : }
297 10381 : return gdiv(ggamma(s2,prec), powPis(s2,prec));
298 : }
299 : /* gamma_R(s)gamma_R(s+1) = 2 (2pi)^(-s) Gamma(s) */
300 : static GEN
301 11102 : gamma_C(GEN s, long *ext, long prec)
302 : {
303 : long ms;
304 11102 : if (typ(s) == t_SER)
305 2100 : s = serextendifnegint(s, gen_1, ext);
306 9002 : else if ((ms = isnegint(s)) >= 0)
307 : {
308 0 : GEN r = gmul(pow2Pis(stoi(ms),prec), gdivsg(odd(ms)? -2: 2, mpfact(ms)));
309 0 : return serpole(r);
310 : }
311 11102 : return gmul2n(gdiv(ggamma(s,prec), pow2Pis(s,prec)), 1);
312 : }
313 :
314 : static GEN
315 1995 : gammafrac(GEN r, long d)
316 : {
317 1995 : long i, l = labs(d) + 1, j = (d > 0)? 0: 2*d;
318 1995 : GEN T, v = cgetg(l, t_COL);
319 6867 : for (i = 1; i < l; i++, j += 2)
320 4872 : gel(v,i) = deg1pol_shallow(gen_1, gaddgs(r, j), 0);
321 1995 : T = RgV_prod(v); return d > 0? T: mkrfrac(gen_1, T);
322 : }
323 :
324 : /*
325 : GR(s)=Pi^-(s/2)*gamma(s/2);
326 : GC(s)=2*(2*Pi)^-s*gamma(s)
327 : gdirect(F,s)=prod(i=1,#F,GR(s+F[i]))
328 : gfact(F,s)=
329 : { my([R,A,B]=gammafactor(F), [a,e]=A, [b,f]=B, p=poldegree(R));
330 : subst(R,x,s) * (2*Pi)^-p * prod(i=1,#a,GR(s+a[i])^e[i])
331 : * prod(i=1,#b,GC(s+b[i])^f[i]); }
332 : */
333 : static GEN
334 22099 : gammafactor(GEN Vga)
335 : {
336 22099 : long i, r, c, l = lg(Vga);
337 22099 : GEN v, P, a, b, e, f, E, F = cgetg(l, t_VEC), R = gen_1;
338 62104 : for (i = 1; i < l; ++i)
339 : {
340 40005 : GEN a = gel(Vga,i), r = gmul2n(real_i(a), -1);
341 40005 : long q = itos(gfloor(r)); /* [Re a/2] */
342 40005 : r = gmul2n(gsubgs(r, q), 1);
343 40005 : gel(F,i) = gequal0(imag_i(a)) ? r : mkcomplex(r, imag_i(a)); /* 2{Re a/2} + I*(Im a) */
344 40005 : if (q) R = gmul(R, gammafrac(gel(F,i), q));
345 : }
346 22099 : F = vec_reduce(F, &E); l = lg(E);
347 22099 : v = cgetg(l, t_VEC);
348 56140 : for (i = 1; i < l; i++)
349 34041 : gel(v,i) = mkvec2(gsub(gel(F,i),gfloor(real_i(gel(F,i)))), stoi(E[i]));
350 22099 : gen_sort_inplace(v, (void*)cmp_universal, cmp_nodata, &P);
351 22099 : a = cgetg(l, t_VEC); e = cgetg(l, t_VECSMALL);
352 22099 : b = cgetg(l, t_VEC); f = cgetg(l, t_VECSMALL);
353 45164 : for (i = r = c = 1; i < l;)
354 23065 : if (i==l-1 || cmp_universal(gel(v,i), gel(v,i+1)))
355 12089 : { gel(a, r) = gel(F, P[i]); e[r++] = E[P[i]]; i++; }
356 : else
357 10976 : { gel(b, c) = gel(F, P[i]); f[c++] = E[P[i]]; i+=2; }
358 22099 : setlg(a, r); setlg(e, r);
359 22099 : setlg(b, c); setlg(f, c); return mkvec3(R, mkvec2(a,e), mkvec2(b,f));
360 : }
361 :
362 : static GEN
363 4508 : polgammaeval(GEN F, GEN s)
364 : {
365 4508 : GEN r = poleval(F, s);
366 4508 : if (typ(s) != t_SER && gequal0(r))
367 : { /* here typ(F) = t_POL */
368 : long e;
369 7 : for (e = 1;; e++)
370 : {
371 7 : F = RgX_deriv(F); r = poleval(F,s);
372 7 : if (!gequal0(r)) break;
373 : }
374 7 : if (e > 1) r = gdiv(r, mpfact(e));
375 7 : r = serpole(r); setvalser(r, e);
376 : }
377 4508 : return r;
378 : }
379 : static long
380 2226 : rfrac_degree(GEN R)
381 : {
382 2226 : GEN a = gel(R,1), b = gel(R,2);
383 2226 : return ((typ(a) == t_POL)? degpol(a): 0) - degpol(b);
384 : }
385 : static GEN
386 20524 : fracgammaeval(GEN F, GEN s, long prec)
387 : {
388 20524 : GEN R = gel(F,1);
389 : long d;
390 20524 : switch(typ(R))
391 : {
392 56 : case t_POL:
393 56 : d = degpol(R);
394 56 : R = polgammaeval(R, s); break;
395 2226 : case t_RFRAC:
396 2226 : d = rfrac_degree(R);
397 2226 : R = gdiv(polgammaeval(gel(R,1), s), polgammaeval(gel(R,2), s)); break;
398 18242 : default: return R;
399 : }
400 2282 : return gmul(R, powrs(Pi2n(1,prec), -d));
401 : }
402 :
403 : static GEN
404 20524 : gammafactproduct(GEN F, GEN s, long *ext, long prec)
405 : {
406 20524 : pari_sp av = avma;
407 20524 : GEN R = gel(F,2), Rw = gel(R,1), Re = gel(R,2);
408 20524 : GEN C = gel(F,3), Cw = gel(C,1), Ce = gel(C,2), z = fracgammaeval(F,s,prec);
409 20524 : long i, lR = lg(Rw), lC = lg(Cw);
410 20524 : *ext = 0;
411 30940 : for (i = 1; i < lR; i++)
412 10416 : z = gmul(z, gpowgs(gamma_R(gadd(s,gel(Rw, i)), ext, prec), Re[i]));
413 31626 : for (i = 1; i < lC; i++)
414 11102 : z = gmul(z, gpowgs(gamma_C(gadd(s,gel(Cw, i)), ext, prec), Ce[i]));
415 20524 : return gc_upto(av, z);
416 : }
417 :
418 : static int
419 5264 : gammaordinary(GEN Vga, GEN s)
420 : {
421 5264 : long i, d = lg(Vga)-1;
422 13951 : for (i = 1; i <= d; i++)
423 : {
424 8862 : GEN z = gadd(s, gel(Vga,i));
425 : long e;
426 8862 : if (gexpo(imag_i(z)) < -10)
427 : {
428 8862 : z = real_i(z);
429 8862 : if (gsigne(z) <= 0) { (void)grndtoi(z, &e); if (e < -10) return 0; }
430 : }
431 : }
432 5089 : return 1;
433 : }
434 :
435 : /* Exponent A of t in asymptotic expansion; K(t) ~ C t^A exp(-pi d t^(2/d)).
436 : * suma = vecsum(Vga)*/
437 : static double
438 91527 : gammavec_expo(long d, double suma) { return (1 - d + suma) / d; }
439 :
440 : /*******************************************************************/
441 : /* First part: computations only involving Theta(t) */
442 : /*******************************************************************/
443 :
444 : static void
445 139363 : get_cone(GEN t, double *r, double *a)
446 : {
447 139363 : const long prec = LOWDEFAULTPREC;
448 139363 : if (typ(t) == t_COMPLEX)
449 : {
450 21700 : t = gprec_w(t, prec);
451 21700 : *r = gtodouble(gabs(t, prec));
452 21700 : *a = fabs(gtodouble(garg(t, prec)));
453 : }
454 : else
455 : {
456 117663 : *r = fabs(gtodouble(t));
457 117663 : *a = 0.;
458 : }
459 139363 : if (!*r && !*a) pari_err_DOMAIN("lfunthetainit","t","=",gen_0,t);
460 139356 : }
461 : /* slightly larger cone than necessary, to avoid round-off problems */
462 : static void
463 85631 : get_cone_fuzz(GEN t, double *r, double *a)
464 85631 : { get_cone(t, r, a); *r -= 1e-10; if (*a) *a += 1e-10; }
465 :
466 : /* Initialization m-th Theta derivative. tdom is either
467 : * - [rho,alpha]: assume |t| >= rho and |arg(t)| <= alpha
468 : * - a positive real scalar: assume t real, t >= tdom;
469 : * - a complex number t: compute at t;
470 : * N is the conductor (either the true one from ldata or a guess from
471 : * lfunconductor) */
472 : long
473 64442 : lfunthetacost(GEN ldata, GEN tdom, long m, long bit, long *extrabit)
474 : {
475 64442 : pari_sp av = avma;
476 64442 : GEN Vga = ldata_get_gammavec(ldata);
477 64442 : long d = lg(Vga)-1;
478 64442 : double k1 = maxdd(ldata_get_k1_dbl(ldata), 0.);
479 64442 : double c = d/2., a, A, B, logC, al, rho, T;
480 64442 : double N = gtodouble(ldata_get_conductor(ldata));
481 :
482 64442 : if (extrabit) *extrabit = 0;
483 64442 : if (!N) pari_err_TYPE("lfunthetaneed [missing conductor]", ldata);
484 64442 : if (typ(tdom) == t_VEC && lg(tdom) == 3)
485 : {
486 7 : rho= gtodouble(gel(tdom,1));
487 7 : al = gtodouble(gel(tdom,2));
488 : }
489 : else
490 64435 : get_cone_fuzz(tdom, &rho, &al);
491 64435 : A = gammavec_expo(d, gtodouble(sumVga(Vga))); set_avma(av);
492 64435 : a = (A+k1+1) + (m-1)/c;
493 64435 : if (fabs(a) < 1e-10) a = 0.;
494 64435 : logC = c*M_LN2 - log(c)/2;
495 : /* +1: fudge factor */
496 64435 : B = M_LN2*bit+logC+m*log(2*M_PI) + 1 + (k1+1)*log(N)/2 - (k1+m+1)*log(rho);
497 64435 : if (al)
498 : { /* t = rho e^(i*al), T^(1/c) = Re(t^(1/c)) > 0, T = rho cos^c(al/c) */
499 10857 : double z = cos(al/c);
500 10857 : if (z <= 0)
501 7 : pari_err_DOMAIN("lfunthetaneed", "arg t", ">", dbltor(c*M_PI/2), tdom);
502 10850 : T = (d == 2 && typ(tdom) != t_VEC)? gtodouble(real_i(tdom)): rho*pow(z,c);
503 10850 : B -= log(z) * (c * (k1+A+1) + m);
504 : }
505 : else
506 53578 : T = rho;
507 64428 : if (B <= 0) return 0;
508 64428 : A = floor(0.9 + dblcoro526(a,c,B) / T * sqrt(N));
509 64428 : if (dblexpo(A) >= BITS_IN_LONG-1) pari_err_OVERFLOW("lfunthetacost");
510 64421 : if (extrabit && A && a * log2(A) > 16) *extrabit = a * log2(A);
511 64421 : return (long)A;
512 : }
513 : long
514 21 : lfunthetacost0(GEN L, GEN tdom, long m, long bitprec)
515 : {
516 : long n;
517 21 : if (is_linit(L) && linit_get_type(L)==t_LDESC_THETA)
518 7 : {
519 7 : GEN tech = linit_get_tech(L);
520 7 : n = lg(theta_get_an(tech))-1;
521 : }
522 : else
523 : {
524 14 : pari_sp av = avma;
525 14 : GEN ldata = lfunmisc_to_ldata_shallow(L);
526 14 : n = lfunthetacost(ldata, tdom? tdom: gen_1, m, bitprec, NULL);
527 7 : set_avma(av);
528 : }
529 14 : return n;
530 : }
531 :
532 : static long
533 6769 : fracgammadegree(GEN FVga)
534 6769 : { GEN F = gel(FVga,1); return (typ(F)==t_RFRAC)? degpol(gel(F,2)): 0; }
535 :
536 : /* Poles of a L-function can be represented in the following ways:
537 : * 1) Nothing (ldata has only 6 components, ldata_get_residue = NULL).
538 : * 2) a complex number (single pole at s = k with given residue, unknown if 0).
539 : * 3) A vector (possibly empty) of 2-component vectors [a, ra], where a is the
540 : * pole, ra a t_SER: its Taylor expansion at a. A t_VEC encodes the polar
541 : * part of L, a t_COL, the polar part of Lambda */
542 :
543 : /* 'a' a complex number (pole), 'r' the polar part of L at 'a';
544 : * return 'R' the polar part of Lambda at 'a' */
545 : static GEN
546 5082 : rtoR(GEN a, GEN r, GEN FVga, GEN N, long prec)
547 : {
548 5082 : long v = lg(r)-2, d = fracgammadegree(FVga), ext;
549 5082 : GEN Na, as = deg1ser_shallow(gen_1, a, varn(r), v);
550 5082 : Na = gpow(N, gdivgu(as, 2), prec);
551 : /* make up for a possible loss of accuracy */
552 5082 : if (d) as = deg1ser_shallow(gen_1, a, varn(r), v + d);
553 5082 : return gmul(gmul(r, Na), gammafactproduct(FVga, as, &ext, prec));
554 : }
555 :
556 : /* assume r in normalized form: t_VEC of pairs [be,re] */
557 : GEN
558 4683 : lfunrtopoles(GEN r)
559 : {
560 4683 : long j, l = lg(r);
561 4683 : GEN v = cgetg(l, t_VEC);
562 9765 : for (j = 1; j < l; j++) gel(v,j) = gmael(r, j, 1);
563 4683 : gen_sort_inplace(v, (void*)&cmp_universal, cmp_nodata, NULL);
564 4683 : return v;
565 : }
566 :
567 : /* r / x + O(1) */
568 : static GEN
569 5236 : simple_pole(GEN r)
570 5236 : { return isintzero(r)? gen_0: serpole(r); }
571 : static GEN
572 6174 : normalize_simple_pole(GEN r, GEN k)
573 : {
574 6174 : long tx = typ(r);
575 6174 : if (is_vec_t(tx)) return r;
576 5236 : if (!is_scalar_t(tx)) pari_err_TYPE("lfunrootres [poles]", r);
577 5236 : return mkvec(mkvec2(k, simple_pole(r)));
578 : }
579 : /* check and normalize the description of a polar part as a t_VEC (r for L)
580 : * or t_COL (R for Lambda) of pairs [a, ra] */
581 : static GEN
582 5572 : normalizepoles(GEN r, GEN k)
583 : {
584 : long iv, j, l;
585 : GEN v;
586 5572 : if (!is_vec_t(typ(r))) return normalize_simple_pole(r, k);
587 2429 : v = cgetg_copy(r, &l);
588 6181 : for (j = iv = 1; j < l; j++)
589 : {
590 3752 : GEN rj = gel(r,j), a = gel(rj,1), ra = gel(rj,2);
591 3752 : if (!is_scalar_t(typ(a)) || typ(ra) != t_SER)
592 0 : pari_err_TYPE("lfunrootres [poles]",r);
593 3752 : gel(v,iv++) = rj;
594 : }
595 2429 : setlg(v, iv); return v;
596 : }
597 : static int
598 9016 : residues_known(GEN r)
599 : {
600 9016 : long i, l = lg(r);
601 9016 : if (isintzero(r)) return 0;
602 8687 : if (!is_vec_t(typ(r))) return 1;
603 11942 : for (i = 1; i < l; i++)
604 : {
605 7308 : GEN ri = gel(r,i);
606 7308 : if (!is_vec_t(typ(ri)) || lg(ri)!=3)
607 0 : pari_err_TYPE("lfunrootres [poles]",r);
608 7308 : if (isintzero(gel(ri, 2))) return 0;
609 : }
610 4634 : return 1;
611 : }
612 :
613 : /* Compute R's from r's (r = Taylor devts of L(s), R of Lambda(s)).
614 : * 'r/eno' passed to override the one from ldata */
615 : static GEN
616 23898 : lfunrtoR_i(GEN ldata, GEN r, GEN eno, long prec)
617 : {
618 23898 : GEN Vga = ldata_get_gammavec(ldata), N = ldata_get_conductor(ldata);
619 : GEN R, vr, FVga;
620 23898 : pari_sp av = avma;
621 : long lr, j, jR;
622 23898 : GEN k = ldata_get_k(ldata);
623 :
624 23898 : if (!r || isintzero(eno) || !residues_known(r))
625 18326 : return gen_0;
626 5572 : r = normalizepoles(r, k);
627 5572 : if (typ(r) == t_COL) return gc_GEN(av, r);
628 4683 : if (typ(ldata_get_dual(ldata)) != t_INT)
629 0 : pari_err(e_MISC,"please give the Taylor expansion of Lambda");
630 4683 : vr = lfunrtopoles(r); lr = lg(vr);
631 4683 : FVga = gammafactor(Vga);
632 4683 : R = cgetg(2*lr, t_COL);
633 9765 : for (j = jR = 1; j < lr; j++)
634 : {
635 5082 : GEN rj = gel(r,j), a = gel(rj,1), ra = gel(rj,2);
636 5082 : GEN b, Ra = rtoR(a, ra, FVga, N, prec);
637 5082 : long o = -valser(Ra); /* Lambda pole order */
638 5082 : if (o <= 0) continue;
639 5082 : b = gsub(k, conj_i(a));
640 5082 : if (lg(Ra)-2 < o)
641 0 : pari_err(e_MISC,
642 : "please give more terms in L function's Taylor expansion at %Ps", a);
643 5082 : setlg(Ra, o + 2); /* truncate useless terms */
644 5082 : gel(R,jR++) = mkvec2(a, Ra);
645 5082 : if (!tablesearch(vr, b, (int (*)(GEN,GEN))&cmp_universal))
646 : {
647 4865 : GEN mX = gneg(pol_x(varn(Ra)));
648 4865 : GEN Rb = gmul(eno, gsubst(conj_i(Ra), varn(Ra), mX));
649 4865 : gel(R,jR++) = mkvec2(b, Rb);
650 : }
651 : }
652 4683 : setlg(R, jR); return gc_GEN(av, R);
653 : }
654 : static GEN
655 23422 : lfunrtoR_eno(GEN ldata, GEN eno, long prec)
656 23422 : { return lfunrtoR_i(ldata, ldata_get_residue(ldata), eno, prec); }
657 : static GEN
658 21203 : lfunrtoR(GEN ldata, long prec)
659 21203 : { return lfunrtoR_eno(ldata, ldata_get_rootno(ldata), prec); }
660 :
661 : static long
662 21203 : prec_fix(long prec)
663 : {
664 : #ifndef LONG_IS_64BIT
665 : /* make sure that default accuracy is the same on 32/64bit */
666 3029 : if (odd(prec)) prec += EXTRAPREC64;
667 : #endif
668 21203 : return prec;
669 : }
670 :
671 : /* thetainit using {an: n <= L}; if (m = 0 && easytheta), an2 is an * n^al */
672 : static GEN
673 21203 : lfunthetainit0(GEN ldata, GEN tdom, GEN an2, long m,
674 : long bitprec, long extrabit)
675 : {
676 21203 : long prec = nbits2prec(bitprec);
677 21203 : GEN tech, N = ldata_get_conductor(ldata);
678 21203 : GEN K = gammamellininvinit(ldata, m, bitprec + extrabit);
679 21203 : GEN R = lfunrtoR(ldata, prec);
680 21203 : if (!tdom) tdom = gen_1;
681 21203 : if (typ(tdom) != t_VEC)
682 : {
683 : double r, a;
684 21196 : get_cone_fuzz(tdom, &r, &a);
685 21196 : tdom = mkvec2(dbltor(r), a? dbltor(a): gen_0);
686 : }
687 21203 : prec += maxss(EXTRAPREC64, nbits2extraprec(extrabit));
688 21203 : tech = mkvecn(7, an2,K,R, stoi(bitprec), stoi(m), tdom,
689 : gsqrt(ginv(N), prec_fix(prec)));
690 21203 : return mkvec3(mkvecsmall(t_LDESC_THETA), ldata, tech);
691 : }
692 :
693 : /* tdom: 1) positive real number r, t real, t >= r; or
694 : * 2) [r,a], describing the cone |t| >= r, |arg(t)| <= a */
695 : static GEN
696 10409 : lfunthetainit_i(GEN data, GEN tdom, long m, long bit)
697 : {
698 10409 : GEN ldata = lfunmisc_to_ldata_shallow(data);
699 10409 : long extrabit, b = 32, L = lfunthetacost(ldata, tdom, m, bit, &extrabit);
700 10395 : long prec = nbits2prec(bit + extrabit);
701 10395 : GEN ldatan = ldata_newprec(ldata, prec);
702 10395 : GEN an = ldata_get_an(ldatan), Vga = ldata_get_gammavec(ldatan);
703 10395 : an = ldata_vecan(an, L, prec);
704 10395 : if (m == 0 && Vgaeasytheta(Vga)) an = antwist(an, Vga, prec);
705 10395 : if (typ(an) != t_VECSMALL) b = maxss(b, gexpo(an));
706 10395 : return lfunthetainit0(ldatan, tdom, an, m, bit, b);
707 : }
708 :
709 : GEN
710 343 : lfunthetainit(GEN ldata, GEN tdom, long m, long bitprec)
711 : {
712 343 : pari_sp av = avma;
713 343 : GEN S = lfunthetainit_i(ldata, tdom? tdom: gen_1, m, bitprec);
714 343 : return gc_GEN(av, S);
715 : }
716 :
717 : GEN
718 2464 : lfunan(GEN ldata, long L, long prec)
719 : {
720 2464 : pari_sp av = avma;
721 : GEN an ;
722 2464 : ldata = ldata_newprec(lfunmisc_to_ldata_shallow(ldata), prec);
723 2464 : an = gc_GEN(av, ldata_vecan(ldata_get_an(ldata), L, prec));
724 2408 : if (typ(an) != t_VEC) an = vecsmall_to_vec_inplace(an);
725 2408 : return an;
726 : }
727 :
728 : static GEN
729 15890 : mulrealvec(GEN x, GEN y)
730 : {
731 15890 : if (is_vec_t(typ(x)) && is_vec_t(typ(y)))
732 84 : pari_APPLY_same(mulreal(gel(x,i),gel(y,i)))
733 : else
734 15862 : return mulreal(x,y);
735 : }
736 : static GEN
737 31568 : gmulvec(GEN x, GEN y)
738 : {
739 31568 : if (is_vec_t(typ(x)) && is_vec_t(typ(y)))
740 2702 : pari_APPLY_same(gmul(gel(x,i),gel(y,i)))
741 : else
742 30903 : return gmul(x,y);
743 : }
744 : static GEN
745 9625 : gdivvec(GEN x, GEN y)
746 : {
747 9625 : if (is_vec_t(typ(x)) && is_vec_t(typ(y)))
748 2247 : pari_APPLY_same(gdiv(gel(x,i),gel(y,i)))
749 : else
750 9051 : return gdiv(x,y);
751 : }
752 :
753 : static GEN
754 3584 : gsubvec(GEN x, GEN y)
755 : {
756 3584 : if (is_vec_t(typ(x)) && !is_vec_t(typ(y)))
757 0 : pari_APPLY_same(gsub(gel(x,i),y))
758 : else
759 3584 : return gsub(x,y);
760 : }
761 :
762 : /* return [1^(2/d), 2^(2/d),...,lim^(2/d)] */
763 : static GEN
764 8043 : mkvroots(long d, long lim, long prec)
765 : {
766 8043 : if (d <= 4)
767 : {
768 7693 : GEN v = cgetg(lim+1,t_VEC);
769 : long n;
770 7693 : switch(d)
771 : {
772 2828 : case 1:
773 53104 : for (n=1; n <= lim; n++) gel(v,n) = sqru(n);
774 2828 : return v;
775 1407 : case 2:
776 230496 : for (n=1; n <= lim; n++) gel(v,n) = utoipos(n);
777 1407 : return v;
778 1990 : case 4:
779 6117579 : for (n=1; n <= lim; n++) gel(v,n) = sqrtr(utor(n, prec));
780 1990 : return v;
781 : }
782 : }
783 1818 : return vecpowug(lim, gdivgu(gen_2,d), prec);
784 : }
785 :
786 : GEN
787 61866 : lfunthetacheckinit(GEN data, GEN t, long m, long bitprec)
788 : {
789 61866 : if (is_linit(data) && linit_get_type(data)==t_LDESC_THETA)
790 : {
791 53732 : GEN tdom, thetainit = linit_get_tech(data);
792 53732 : long bitprecnew = theta_get_bitprec(thetainit);
793 53732 : long m0 = theta_get_m(thetainit);
794 : double r, al, rt, alt;
795 53732 : if (m0 != m)
796 0 : pari_err_DOMAIN("lfuntheta","derivative order","!=", stoi(m),stoi(m0));
797 53732 : if (bitprec > bitprecnew) goto INIT;
798 53732 : get_cone(t, &rt, &alt);
799 53732 : tdom = theta_get_tdom(thetainit);
800 53732 : r = gtodouble(gel(tdom,1));
801 53732 : al= gtodouble(gel(tdom,2)); if (rt >= r && alt <= al) return data;
802 : }
803 8134 : INIT:
804 9975 : return lfunthetainit_i(data, t, m, bitprec);
805 : }
806 :
807 : static GEN
808 14713635 : get_an(GEN an, long n)
809 : {
810 14713635 : if (typ(an) == t_VECSMALL) { long a = an[n]; if (a) return stoi(a); }
811 14713635 : else { GEN a = gel(an,n); if (a && !gequal0(a)) return a; }
812 12685598 : return NULL;
813 : }
814 : /* x * an[n] */
815 : static GEN
816 12724209 : mul_an(GEN an, long n, GEN x)
817 : {
818 12724209 : if (typ(an) == t_VECSMALL) { long a = an[n]; if (a) return gmulsg(a,x); }
819 7463082 : else { GEN a = gel(an,n); if (a && !gequal0(a)) return gmul(a,x); }
820 2440404 : return NULL;
821 : }
822 : /* 2*t^a * x **/
823 : static GEN
824 334556 : mulT(GEN t, GEN a, GEN x, long prec)
825 : {
826 334556 : if (gequal0(a)) return gmul2n(x,1);
827 32651 : return gmul(x, gmul2n(gequal1(a)? t: gpow(t,a,prec), 1));
828 : }
829 :
830 : static GEN
831 35549489 : vecan_cmul(void *E, GEN P, long a, GEN x)
832 : {
833 : (void)E;
834 35549489 : if (typ(P) == t_VECSMALL)
835 24692520 : return (a==0 || !P[a])? NULL: gmulsg(P[a], x);
836 : else
837 10856969 : return (a==0 || !gel(P,a))? NULL: gmul(gel(P,a), x);
838 : }
839 : /* d=2, 2 sum_{n <= N} a(n) (n t)^al q^n, q = exp(-2pi t),
840 : * an2[n] = a(n) * n^al */
841 : static GEN
842 294993 : theta2_i(GEN an2, long N, GEN t, GEN al, long prec)
843 : {
844 294993 : GEN S, q, pi2 = Pi2n(1,prec);
845 294980 : const struct bb_algebra *alg = get_Rg_algebra();
846 294980 : setsigne(pi2,-1); q = gexp(gmul(pi2, t), prec);
847 : /* Brent-Kung in case the a_n are small integers */
848 294973 : S = gen_bkeval(an2, N, q, 1, NULL, alg, vecan_cmul);
849 294987 : return mulT(t, al, S, prec);
850 : }
851 : static GEN
852 286841 : theta2(GEN an2, long N, GEN t, GEN al, long prec)
853 : {
854 286841 : pari_sp av = avma;
855 286841 : return gc_upto(av, theta2_i(an2, N, t, al, prec));
856 : }
857 :
858 : /* d=1, 2 sum_{n <= N} a_n (n t)^al q^(n^2), q = exp(-pi t^2),
859 : * an2[n] is a_n n^al */
860 : static GEN
861 39568 : theta1(GEN an2, long N, GEN t, GEN al, long prec)
862 : {
863 39568 : GEN q = gexp(gmul(negr(mppi(prec)), gsqr(t)), prec);
864 39568 : GEN vexp = gsqrpowers(q, N), S = gen_0;
865 39568 : pari_sp av = avma;
866 : long n;
867 6620667 : for (n = 1; n <= N; n++)
868 : {
869 6581099 : GEN c = mul_an(an2, n, gel(vexp,n));
870 6581099 : if (c)
871 : {
872 5504689 : S = gadd(S, c);
873 5504689 : if (gc_needed(av, 3)) S = gc_upto(av, S);
874 : }
875 : }
876 39568 : return mulT(t, al, S, prec);
877 : }
878 :
879 : /* If m > 0, compute m-th derivative of theta(t) = theta0(t/sqrt(N))
880 : * with absolute error 2^-bitprec; theta(t)=\sum_{n\ge1}a(n)K(nt/N^(1/2)) */
881 : GEN
882 51891 : lfuntheta(GEN data, GEN t, long m, long bitprec)
883 : {
884 51891 : pari_sp ltop = avma;
885 : long limt, d;
886 : GEN isqN, vecan, Vga, ldata, theta, thetainit, S;
887 : long n, prec;
888 :
889 51891 : theta = lfunthetacheckinit(data, t, m, bitprec);
890 51884 : ldata = linit_get_ldata(theta);
891 51884 : thetainit = linit_get_tech(theta);
892 51884 : vecan = theta_get_an(thetainit);
893 51884 : isqN = theta_get_isqrtN(thetainit);
894 51884 : prec = maxss(realprec(isqN), nbits2prec(bitprec));
895 51884 : t = gprec_w(t, prec);
896 51884 : limt = lg(vecan)-1;
897 51884 : if (theta == data)
898 47684 : limt = minss(limt, lfunthetacost(ldata, t, m, bitprec, NULL));
899 51884 : if (!limt)
900 : {
901 14 : set_avma(ltop); S = real_0_bit(-bitprec);
902 14 : if (!is_real_t(typ(t)) || !ldata_isreal(ldata))
903 7 : S = gc_GEN(ltop, mkcomplex(S,S));
904 14 : return S;
905 : }
906 51870 : t = gmul(t, isqN);
907 51870 : Vga = ldata_get_gammavec(ldata);
908 51870 : d = lg(Vga)-1;
909 51870 : if (m == 0 && Vgaeasytheta(Vga))
910 : {
911 47719 : if (theta_get_m(thetainit) > 0) vecan = antwist(vecan, Vga, prec);
912 47719 : if (d == 1) S = theta1(vecan, limt, t, gel(Vga,1), prec);
913 8151 : else S = theta2_i(vecan, limt, t, vecmin(Vga), prec);
914 : }
915 : else
916 : {
917 4151 : GEN K = theta_get_K(thetainit);
918 4151 : GEN vroots = mkvroots(d, limt, prec);
919 : pari_sp av;
920 4151 : t = gpow(t, gdivgu(gen_2,d), prec);
921 4151 : S = gen_0; av = avma;
922 14717786 : for (n = 1; n <= limt; ++n)
923 : {
924 14713635 : GEN nt, an = get_an(vecan, n);
925 14713635 : if (!an) continue;
926 2028037 : nt = gmul(gel(vroots,n), t);
927 2028037 : if (m) an = gmul(an, powuu(n, m));
928 2028037 : S = gadd(S, gmul(an, gammamellininvrt(K, nt, bitprec)));
929 2028037 : if ((n & 0x1ff) == 0) S = gc_upto(av, S);
930 : }
931 4151 : if (m) S = gmul(S, gpowgs(isqN, m));
932 : }
933 51870 : return gc_upto(ltop, S);
934 : }
935 :
936 : /*******************************************************************/
937 : /* Second part: Computation of L-Functions. */
938 : /*******************************************************************/
939 :
940 : struct lfunp {
941 : long precmax, Dmax, D, M, m0, nmax, d, vgaell;
942 : double k1, dc, dw, dh, MAXs, sub;
943 : GEN L, an, bn;
944 : };
945 :
946 : static void
947 27092 : lfunp_set(GEN ldata, long der, long bitprec, struct lfunp *S)
948 : {
949 27092 : const long derprec = (der > 1)? dbllog2(mpfact(der)): 0; /* log2(der!) */
950 : GEN Vga, N, L, k;
951 : long k1, d, m, M, flag, nmax;
952 : double a, A, E, hd, Ep, d2, suma, maxs, mins, sub, B0,B1;
953 : double logN2, logC, Lestimate, Mestimate;
954 :
955 27092 : Vga = ldata_get_gammavec(ldata);
956 27092 : S->d = d = lg(Vga)-1; d2 = d/2.;
957 :
958 27092 : suma = gtodouble(sumVga(Vga));
959 27092 : k = ldata_get_k(ldata);
960 27092 : N = ldata_get_conductor(ldata);
961 27092 : logN2 = log(gtodouble(N)) / 2;
962 27092 : maxs = S->dc + S->dw;
963 27092 : mins = S->dc - S->dw;
964 27092 : S->MAXs = maxdd(maxs, gtodouble(k)-mins);
965 :
966 : /* we compute Lambda^(der)(s) / der!; need to compensate for L^(der)(s)
967 : * ln |gamma(s)| ~ -(pi/4) \sum_i |Im(s + a_i)|; max with 1: fudge factor */
968 27092 : a = (M_PI/(4*M_LN2))*(d*S->dh + sumVgaimpos(Vga));
969 27092 : S->D = (long)ceil(bitprec + derprec + maxdd(a, 1));
970 27092 : E = M_LN2*S->D; /* D:= required absolute bitprec */
971 :
972 27092 : Ep = E + maxdd(M_PI * S->dh * d2, (d*S->MAXs + suma - 1) * log(E));
973 27092 : hd = d2*M_PI*M_PI / Ep;
974 27092 : S->m0 = (long)ceil(M_LN2/hd);
975 27092 : hd = M_LN2/S->m0;
976 :
977 27092 : logC = d2*M_LN2 - log(d2)/2;
978 27092 : k1 = maxdd(ldata_get_k1_dbl(ldata), 0.);
979 27092 : S->k1 = k1; /* assume |a_n| << n^k1 with small implied constant */
980 27092 : A = gammavec_expo(d, suma);
981 :
982 27092 : sub = 0.;
983 27092 : if (mins > 1)
984 : {
985 5264 : GEN sig = dbltor(mins);
986 5264 : sub += logN2*mins;
987 5264 : if (gammaordinary(Vga, sig))
988 : {
989 : long ext;
990 5089 : GEN gas = gammafactproduct(gammafactor(Vga), sig, &ext, LOWDEFAULTPREC);
991 5089 : if (typ(gas) != t_SER)
992 : {
993 5089 : double dg = dbllog2(gas);
994 5089 : if (dg > 0) sub += dg * M_LN2;
995 : }
996 : }
997 : }
998 27092 : S->sub = sub;
999 27092 : M = 1000;
1000 27092 : L = cgetg(M+2, t_VECSMALL);
1001 27092 : a = S->k1 + A;
1002 :
1003 27092 : B0 = 5 + E - S->sub + logC + S->k1*logN2; /* 5 extra bits */
1004 27092 : B1 = hd * (S->MAXs - S->k1);
1005 27092 : Lestimate = dblcoro526(a + S->MAXs - 2./d, d/2.,
1006 27092 : E - S->sub + logC - log(2*M_PI*hd) + S->MAXs*logN2);
1007 27092 : Mestimate = ((Lestimate > 0? log(Lestimate): 0) + logN2) / hd;
1008 27092 : nmax = 0;
1009 27092 : flag = 0;
1010 27092 : for (m = 0;; m++)
1011 2416841 : {
1012 2443933 : double x, H = logN2 - m*hd, B = B0 + m*B1;
1013 : long n;
1014 2443933 : x = dblcoro526(a, d/2., B);
1015 2443933 : n = floor(x*exp(H));
1016 2443933 : if (n > nmax) nmax = n;
1017 2443933 : if (m > M) { M *= 2; L = vecsmall_lengthen(L,M+2); }
1018 2443933 : L[m+1] = n;
1019 2443933 : if (n == 0) { if (++flag > 2 && m > Mestimate) break; } else flag = 0;
1020 : }
1021 27932 : m -= 2; while (m > 0 && !L[m]) m--;
1022 27092 : if (m == 0) { nmax = 1; L[1] = 1; m = 1; } /* can happen for tiny bitprec */
1023 27092 : setlg(L, m+1); S->M = m-1;
1024 27092 : S->L = L;
1025 27092 : S->nmax = nmax;
1026 :
1027 27092 : S->Dmax = S->D + (long)ceil((S->M * hd * S->MAXs - S->sub) / M_LN2);
1028 27092 : if (S->Dmax < S->D) S->Dmax = S->D;
1029 27092 : S->precmax = nbits2prec(S->Dmax);
1030 27092 : if (DEBUGLEVEL > 1)
1031 0 : err_printf("Dmax=%ld, D=%ld, M = %ld, nmax = %ld, m0 = %ld\n",
1032 : S->Dmax,S->D,S->M,S->nmax, S->m0);
1033 27092 : }
1034 :
1035 : static GEN
1036 10962 : lfuninit_pol(GEN v, GEN poqk, long prec)
1037 : {
1038 10962 : long m, M = lg(v) - 2;
1039 10962 : GEN pol = cgetg(M+3, t_POL);
1040 10962 : pol[1] = evalsigne(1) | evalvarn(0);
1041 10962 : gel(pol, 2) = gprec_w(gmul2n(gel(v,1), -1), prec);
1042 10962 : if (poqk)
1043 526438 : for (m = 2; m <= M+1; m++)
1044 515532 : gel(pol, m+1) = gprec_w(gmul(gel(poqk,m), gel(v,m)), prec);
1045 : else
1046 2324 : for (m = 2; m <= M+1; m++)
1047 2268 : gel(pol, m+1) = gprec_w(gel(v,m), prec);
1048 10962 : return RgX_renormalize_lg(pol, M+3);
1049 : }
1050 :
1051 : static void
1052 79539 : worker_init(long q, GEN *an, GEN *bn, GEN *AB, GEN *A, GEN *B)
1053 : {
1054 79539 : if (typ(*bn) == t_INT) *bn = NULL;
1055 79539 : if (*bn)
1056 : {
1057 712 : *AB = cgetg(3, t_VEC);
1058 712 : gel(*AB,1) = *A = cgetg(q+1, t_VEC);
1059 712 : gel(*AB,2) = *B = cgetg(q+1, t_VEC);
1060 712 : if (typ(an) == t_VEC) *an = RgV_kill0(*an);
1061 712 : if (typ(bn) == t_VEC) *bn = RgV_kill0(*bn);
1062 : }
1063 : else
1064 : {
1065 78827 : *B = NULL;
1066 78827 : *AB = *A = cgetg(q+1, t_VEC);
1067 78825 : if (typ(*an) == t_VEC) *an = RgV_kill0(*an);
1068 : }
1069 79543 : }
1070 : GEN
1071 22393 : lfuninit_theta2_worker(long r, GEN L, GEN qk, GEN a, GEN di, GEN an, GEN bn)
1072 : {
1073 22393 : long q, m, prec = di[1], M = di[2], m0 = di[3], L0 = lg(an)-1;
1074 : GEN AB, A, B;
1075 22393 : worker_init((M - r) / m0 + 1, &an, &bn, &AB, &A, &B);
1076 302257 : for (q = 0, m = r; m <= M; m += m0, q++)
1077 : {
1078 279875 : GEN t = gel(qk, m+1);
1079 279875 : long N = minss(L[m+1],L0);
1080 279875 : gel(A, q+1) = theta2(an, N, t, a, prec); /* theta(exp(mh)) */
1081 279864 : if (bn) gel(B, q+1) = theta2(bn, N, t, a, prec);
1082 : }
1083 22382 : return AB;
1084 : }
1085 :
1086 : /* theta(exp(mh)) ~ sum_{n <= N} a(n) k[m,n] */
1087 : static GEN
1088 241842 : an_msum(GEN an, long N, GEN vKm)
1089 : {
1090 241842 : pari_sp av = avma;
1091 241842 : GEN s = gen_0;
1092 : long n;
1093 12572491 : for (n = 1; n <= N; n++)
1094 12331196 : if (gel(vKm,n))
1095 : {
1096 6143089 : GEN c = mul_an(an, n, gel(vKm,n));
1097 6143976 : if (c) s = gadd(s, c);
1098 : }
1099 241295 : return gc_upto(av, s);
1100 : }
1101 :
1102 : GEN
1103 57163 : lfuninit_worker(long r, GEN K, GEN L, GEN peh2d, GEN vroots, GEN dr, GEN di,
1104 : GEN an, GEN bn)
1105 : {
1106 57163 : pari_sp av0 = avma;
1107 57163 : long m, n, q, L0 = lg(an)-1;
1108 57163 : double sig0 = rtodbl(gel(dr,1)), sub2 = rtodbl(gel(dr,2));
1109 57158 : double k1 = rtodbl(gel(dr,3)), MAXs = rtodbl(gel(dr,4));
1110 57155 : long D = di[1], M = di[2], m0 = di[3];
1111 57155 : double M0 = sig0? sub2 / sig0: 1./0.;
1112 57155 : GEN AB, A, B, vK = cgetg(M/m0 + 2, t_VEC);
1113 :
1114 297922 : for (q = 0, m = r; m <= M; m += m0, q++)
1115 240779 : gel(vK, q+1) = const_vec(L[m+1], NULL);
1116 57143 : worker_init(q, &an, &bn, &AB, &A, &B);
1117 297044 : for (m -= m0, q--; m >= 0; m -= m0, q--)
1118 : {
1119 240851 : double c1 = D + ((m > M0)? m * sig0 - sub2 : 0);
1120 240851 : GEN vKm = gel(vK,q+1); /* conceptually K(m,n) */
1121 12590576 : for (n = 1; n <= L[m+1]; n++)
1122 : {
1123 : GEN t2d, kmn;
1124 12350682 : long nn, mm, qq, p = 0;
1125 : double c, c2;
1126 : pari_sp av;
1127 :
1128 12350682 : if (gel(vKm, n)) continue; /* done already */
1129 9264703 : c = c1 + k1 * log2(n);
1130 : /* n *= 2; m -= m0 => c += c2, provided m >= M0. Else c += k1 */
1131 9264703 : c2 = k1 - MAXs;
1132 : /* p = largest (absolute) accuracy to which we need K(m,n) */
1133 14700767 : for (mm=m,nn=n; mm >= M0;)
1134 : {
1135 11073969 : if (nn <= L[mm+1] && (gel(an, nn) || (bn && gel(bn, nn))))
1136 3012019 : if (c > 0) p = maxuu(p, (ulong)c);
1137 11074224 : nn <<= 1;
1138 11074224 : mm -= m0; if (mm >= M0) c += c2; else { c += k1; break; }
1139 : }
1140 : /* mm < M0 || nn > L[mm+1] */
1141 16514548 : for ( ; mm >= 0; nn<<=1,mm-=m0,c+=k1)
1142 7249682 : if (nn <= L[mm+1] && (gel(an, nn) || (bn && gel(bn, nn))))
1143 1771339 : if (c > 0) p = maxuu(p, (ulong)c);
1144 9264866 : if (!p) continue; /* a_{n 2^v} = 0 for all v in range */
1145 3063021 : av = avma;
1146 3063021 : t2d = mpmul(gel(vroots,n), gel(peh2d,m+1));/*(n exp(mh)/sqrt(N))^(2/d)*/
1147 3063878 : kmn = gc_upto(av, gammamellininvrt(K, t2d, p));
1148 9361122 : for (qq=q,mm=m,nn=n; mm >= 0; nn<<=1,mm-=m0,qq--)
1149 6299221 : if (nn <= L[mm+1]) gmael(vK, qq+1, nn) = kmn;
1150 : }
1151 : }
1152 297016 : for (q = 0, m = r; m <= M; m += m0, q++)
1153 : {
1154 240825 : long N = minss(L0, L[m+1]);
1155 240827 : gel(A, q+1) = an_msum(an, N, gel(vK,q+1));
1156 240823 : if (bn) gel(B, q+1) = an_msum(bn, N, gel(vK,q+1));
1157 : }
1158 56191 : return gc_upto(av0, AB);
1159 : }
1160 : /* return A = [\theta(exp(mh)), m=0..M], theta(t) = sum a(n) K(n/sqrt(N) t),
1161 : * h = log(2)/m0. If bn != NULL, return the pair [A, B] */
1162 : static GEN
1163 10808 : lfuninit_ab(GEN theta, GEN h, struct lfunp *S)
1164 : {
1165 10808 : const long M = S->M, prec = S->precmax;
1166 10808 : GEN tech = linit_get_tech(theta), isqN = theta_get_isqrtN(tech);
1167 10808 : GEN an = S->an, bn = S->bn, va, vb;
1168 : struct pari_mt pt;
1169 : GEN worker;
1170 : long m0, r, pending;
1171 :
1172 10808 : if (S->vgaell)
1173 : { /* d=2 and Vga = [a,a+1] */
1174 7126 : GEN a = vecmin(ldata_get_gammavec(linit_get_ldata(theta)));
1175 7126 : GEN qk = gpowers0(mpexp(h), M, isqN);
1176 7126 : m0 = minss(M+1, mt_nbthreads());
1177 7126 : worker = snm_closure(is_entry("_lfuninit_theta2_worker"),
1178 : mkvecn(6, S->L, qk, a, mkvecsmall3(prec, M, m0),
1179 : an, bn? bn: gen_0));
1180 : }
1181 : else
1182 : {
1183 : GEN vroots, peh2d, d2;
1184 3682 : double sig0 = S->MAXs / S->m0, sub2 = S->sub / M_LN2;
1185 : /* For all 0<= m <= M, and all n <= L[m+1] such that a_n!=0, we compute
1186 : * k[m,n] = K(n exp(mh)/sqrt(N))
1187 : * with ln(absolute error) <= E + max(mh sigma - sub, 0) + k1 * log(n).
1188 : * N.B. we use the 'rt' variant and pass (n exp(mh)/sqrt(N))^(2/d).
1189 : * Speedup: if n' = 2n and m' = m - m0 >= 0; then k[m,n] = k[m',n']. */
1190 3682 : vroots = mkvroots(S->d, S->nmax, prec); /* vroots[n] = n^(2/d) */
1191 3682 : d2 = gdivgu(gen_2, S->d);
1192 3682 : peh2d = gpowers0(gexp(gmul(d2,h), prec), M, gpow(isqN, d2, prec));
1193 3682 : m0 = S->m0; /* peh2d[m+1] = (exp(mh)/sqrt(N))^(2/d) */
1194 3682 : worker = snm_closure(is_entry("_lfuninit_worker"),
1195 : mkvecn(8, theta_get_K(tech), S->L, peh2d, vroots,
1196 : mkvec4(dbltor(sig0), dbltor(sub2),
1197 : dbltor(S->k1), dbltor(S->MAXs)),
1198 : mkvecsmall3(S->D, M, m0),
1199 : an, bn? bn: gen_0));
1200 : /* For each 0 <= m <= M, we will sum for n<=L[m+1] a(n) K(m,n)
1201 : * bit accuracy for K(m,n): D + k1*log2(n) + 1_{m > M0} (m*sig0 - sub2)
1202 : * We restrict m to arithmetic progressions r mod m0 to save memory and
1203 : * allow parallelization */
1204 : }
1205 10808 : va = cgetg(M+2, t_VEC);
1206 10808 : vb = bn? cgetg(M+2, t_VEC): NULL;
1207 10808 : mt_queue_start_lim(&pt, worker, m0);
1208 10808 : pending = 0;
1209 111701 : for (r = 0; r < m0 || pending; r++)
1210 : { /* m = q m0 + r */
1211 : GEN done, A, B;
1212 : long q, m, workid;
1213 100893 : mt_queue_submit(&pt, r, r < m0 ? mkvec(utoi(r)): NULL);
1214 100893 : done = mt_queue_get(&pt, &workid, &pending);
1215 100893 : if (!done) continue;
1216 79566 : if (bn) { A = gel(done,1); B = gel(done,2); } else { A = done; B = NULL; }
1217 600348 : for (q = 0, m = workid; m <= M; m += m0, q++)
1218 : {
1219 520782 : gel(va, m+1) = gel(A, q+1);
1220 520782 : if (bn) gel(vb, m+1) = gel(B, q+1);
1221 : }
1222 : }
1223 10808 : mt_queue_end(&pt);
1224 10808 : return bn? mkvec2(va, vb): va;
1225 : }
1226 :
1227 : static void
1228 141280 : parse_dom(double k, GEN dom, struct lfunp *S)
1229 : {
1230 141280 : long l = lg(dom);
1231 141280 : if (typ(dom)!=t_VEC) pari_err_TYPE("lfuninit [domain]", dom);
1232 141280 : if (l == 1)
1233 : {
1234 98 : S->dc = 0;
1235 98 : S->dw = -1;
1236 98 : S->dh = -1; return;
1237 : }
1238 141182 : if (l == 2)
1239 : {
1240 38117 : S->dc = k/2.;
1241 38117 : S->dw = 0.;
1242 38117 : S->dh = gtodouble(gel(dom,1));
1243 : }
1244 103065 : else if (l == 3)
1245 : {
1246 301 : S->dc = k/2.;
1247 301 : S->dw = gtodouble(gel(dom,1));
1248 301 : S->dh = gtodouble(gel(dom,2));
1249 : }
1250 102764 : else if (l == 4)
1251 : {
1252 102764 : S->dc = gtodouble(gel(dom,1));
1253 102764 : S->dw = gtodouble(gel(dom,2));
1254 102764 : S->dh = gtodouble(gel(dom,3));
1255 : }
1256 : else
1257 : {
1258 0 : pari_err_TYPE("lfuninit [domain]", dom);
1259 0 : S->dc = S->dw = S->dh = 0; /*-Wall*/
1260 : }
1261 141182 : if (S->dw < 0 || S->dh < 0) pari_err_TYPE("lfuninit [domain]", dom);
1262 : }
1263 :
1264 : /* do we have dom \subset dom0 ? dom = [center, width, height] */
1265 : int
1266 25078 : sdomain_isincl(double k, GEN dom, GEN dom0)
1267 : {
1268 : struct lfunp S0, S;
1269 25078 : parse_dom(k, dom, &S); if (S.dw < 0) return 1;
1270 25078 : parse_dom(k, dom0, &S0); if (S0.dw < 0) return 0;
1271 25078 : return S0.dc - S0.dw <= S.dc - S.dw
1272 25078 : && S0.dc + S0.dw >= S.dc + S.dw && S0.dh >= S.dh;
1273 : }
1274 :
1275 : static int
1276 25155 : checklfuninit(GEN linit, GEN DOM, long der, long bitprec)
1277 : {
1278 25155 : GEN ldata = linit_get_ldata(linit);
1279 25155 : GEN domain = lfun_get_domain(linit_get_tech(linit));
1280 25155 : GEN dom = domain_get_dom(domain);
1281 25155 : if (lg(dom) == 1) return 1;
1282 25078 : return domain_get_der(domain) >= der
1283 25078 : && domain_get_bitprec(domain) >= bitprec
1284 50156 : && sdomain_isincl(gtodouble(ldata_get_k(ldata)), DOM, dom);
1285 : }
1286 :
1287 : static GEN
1288 2387 : ginvsqrtvec(GEN x, long prec)
1289 : {
1290 2387 : if (is_vec_t(typ(x)))
1291 1813 : pari_APPLY_same(ginv(gsqrt(gel(x,i), prec)))
1292 1939 : else return ginv(gsqrt(x, prec));
1293 : }
1294 :
1295 : GEN
1296 11914 : lfuninit_make(long t, GEN ldata, GEN tech, GEN domain)
1297 : {
1298 11914 : GEN Vga = ldata_get_gammavec(ldata);
1299 11914 : long d = lg(Vga)-1;
1300 11914 : GEN w2 = gen_1, k2 = gmul2n(ldata_get_k(ldata), -1);
1301 11914 : GEN expot = gdivgu(gadd(gmulsg(d, gsubgs(k2, 1)), sumVga(Vga)), 4);
1302 11914 : if (typ(ldata_get_dual(ldata))==t_INT)
1303 : {
1304 11760 : GEN eno = ldata_get_rootno(ldata);
1305 11760 : long prec = nbits2prec( domain_get_bitprec(domain) );
1306 11760 : if (!isint1(eno)) w2 = ginvsqrtvec(eno, prec);
1307 : }
1308 11914 : tech = mkvec3(domain, tech, mkvec4(k2, w2, expot, gammafactor(Vga)));
1309 11914 : return mkvec3(mkvecsmall(t), ldata, tech);
1310 : }
1311 : static GEN
1312 224 : lfunnoinit(GEN ldata, long bitprec)
1313 : {
1314 224 : GEN tech, domain = mkvec2(cgetg(1,t_VEC), mkvecsmall2(0, bitprec));
1315 224 : GEN R = gen_0, r = ldata_get_residue(ldata), v = lfunrootres(ldata, bitprec);
1316 224 : ldata = shallowcopy(ldata);
1317 224 : gel(ldata,6) = gel(v,3);
1318 224 : if (r)
1319 : {
1320 196 : if (isintzero(r)) setlg(ldata,7); else gel(ldata,7) = r;
1321 196 : R = gel(v,2);
1322 : }
1323 224 : tech = mkvec3(domain, gen_0, R);
1324 224 : return lfuninit_make(t_LDESC_INIT, ldata, tech, domain);
1325 : }
1326 :
1327 : static void
1328 3682 : lfunparams2(struct lfunp *S)
1329 : {
1330 3682 : GEN L = S->L, an = S->an, bn = S->bn;
1331 : double pmax;
1332 3682 : long m, nan, nmax, neval, M = S->M;
1333 :
1334 3682 : S->vgaell = 0;
1335 : /* try to reduce parameters now we know the a_n (some may be 0) */
1336 3682 : if (typ(an) == t_VEC) an = RgV_kill0(an);
1337 3682 : nan = S->nmax; /* lg(an)-1 may be large than this */
1338 3682 : nmax = neval = 0;
1339 3682 : if (!bn)
1340 243533 : for (m = 0; m <= M; m++)
1341 : {
1342 239872 : long n = minss(nan, L[m+1]);
1343 344480 : while (n > 0 && !gel(an,n)) n--;
1344 239872 : if (n > nmax) nmax = n;
1345 239872 : neval += n;
1346 239872 : L[m+1] = n; /* reduce S->L[m+1] */
1347 : }
1348 : else
1349 : {
1350 21 : if (typ(bn) == t_VEC) bn = RgV_kill0(bn);
1351 1036 : for (m = 0; m <= M; m++)
1352 : {
1353 1015 : long n = minss(nan, L[m+1]);
1354 1057 : while (n > 0 && !gel(an,n) && !gel(bn,n)) n--;
1355 1015 : if (n > nmax) nmax = n;
1356 1015 : neval += n;
1357 1015 : L[m+1] = n; /* reduce S->L[m+1] */
1358 : }
1359 : }
1360 3682 : if (DEBUGLEVEL >= 1) err_printf("expected evaluations: %ld\n", neval);
1361 3682 : for (; M > 0; M--)
1362 3682 : if (L[M+1]) break;
1363 3682 : setlg(L, M+2);
1364 3682 : S->M = M;
1365 3682 : S->nmax = nmax;
1366 :
1367 : /* need K(n*exp(mh)/sqrt(N)) to absolute accuracy
1368 : * D + k1*log(n) + max(m * sig0 - sub2, 0) */
1369 3682 : pmax = S->D + S->k1 * log2(L[1]);
1370 3682 : if (S->MAXs)
1371 : {
1372 3682 : double sig0 = S->MAXs/S->m0, sub2 = S->sub / M_LN2;
1373 205151 : for (m = ceil(sub2 / sig0); m <= S->M; m++)
1374 : {
1375 201469 : double c = S->D + m*sig0 - sub2;
1376 201469 : if (S->k1 > 0) c += S->k1 * log2(L[m+1]);
1377 201469 : pmax = maxdd(pmax, c);
1378 : }
1379 : }
1380 3682 : S->Dmax = pmax;
1381 3682 : S->precmax = nbits2prec(pmax);
1382 3682 : }
1383 :
1384 : static GEN
1385 10822 : lfun_init_theta(GEN ldata, GEN eno, struct lfunp *S)
1386 : {
1387 10822 : GEN an2, dual, tdom = NULL, Vga = ldata_get_gammavec(ldata);
1388 10822 : long L, extrabit = 0, prec = S->precmax;
1389 10822 : if (eno)
1390 6608 : L = S->nmax;
1391 : else
1392 : {
1393 4214 : tdom = dbltor(sqrt(0.5));
1394 4214 : L = maxss(S->nmax, lfunthetacost(ldata, tdom, 0, S->D, &extrabit));
1395 4214 : prec += nbits2extraprec(extrabit);
1396 : }
1397 10822 : dual = ldata_get_dual(ldata);
1398 10822 : S->an = ldata_vecan(ldata_get_an(ldata), L, prec);
1399 10808 : S->bn = typ(dual)==t_INT? NULL: ldata_vecan(dual, S->nmax, prec);
1400 10808 : if (!vgaell(Vga)) lfunparams2(S);
1401 : else
1402 : {
1403 7126 : S->an = antwist(S->an, Vga, prec);
1404 7126 : if (S->bn) S->bn = antwist(S->bn, Vga, prec);
1405 7126 : S->vgaell = 1;
1406 : }
1407 10808 : an2 = lg(Vga)-1 == 1? antwist(S->an, Vga, prec): S->an;
1408 10808 : return lfunthetainit0(ldata, tdom, an2, 0, S->Dmax, extrabit);
1409 : }
1410 :
1411 : GEN
1412 16270 : lfuncost(GEN L, GEN dom, long der, long bit)
1413 : {
1414 16270 : pari_sp av = avma;
1415 16270 : GEN ldata = lfunmisc_to_ldata_shallow(L);
1416 16270 : GEN w, k = ldata_get_k(ldata);
1417 : struct lfunp S;
1418 :
1419 16270 : parse_dom(gtodouble(k), dom, &S); if (S.dw < 0) return mkvecsmall2(0, 0);
1420 16270 : lfunp_set(ldata, der, bit, &S);
1421 16270 : w = ldata_get_rootno(ldata);
1422 16270 : if (isintzero(w)) /* for lfunrootres */
1423 7 : S.nmax = maxss(S.nmax, lfunthetacost(ldata,dbltor(sqrt(0.5)),0,bit+1,NULL));
1424 16270 : set_avma(av); return mkvecsmall2(S.nmax, S.Dmax);
1425 : }
1426 : GEN
1427 49 : lfuncost0(GEN L, GEN dom, long der, long bitprec)
1428 : {
1429 49 : pari_sp av = avma;
1430 : GEN C;
1431 :
1432 49 : if (is_linit(L))
1433 : {
1434 28 : GEN tech = linit_get_tech(L);
1435 28 : GEN domain = lfun_get_domain(tech);
1436 28 : dom = domain_get_dom(domain);
1437 28 : der = domain_get_der(domain);
1438 28 : bitprec = domain_get_bitprec(domain);
1439 28 : if (linit_get_type(L) == t_LDESC_PRODUCT)
1440 : {
1441 21 : GEN v = lfunprod_get_fact(linit_get_tech(L)), F = gel(v,1);
1442 21 : long i, l = lg(F);
1443 21 : C = cgetg(l, t_VEC);
1444 70 : for (i = 1; i < l; ++i)
1445 49 : gel(C, i) = zv_to_ZV( lfuncost(gel(F,i), dom, der, bitprec) );
1446 21 : return gc_upto(av, C);
1447 : }
1448 : }
1449 28 : if (!dom) pari_err_TYPE("lfuncost [missing s domain]", L);
1450 28 : C = lfuncost(L,dom,der,bitprec);
1451 28 : return gc_upto(av, zv_to_ZV(C));
1452 : }
1453 :
1454 : static int
1455 9758 : is_dirichlet(GEN ldata)
1456 : {
1457 9758 : switch(ldata_get_type(ldata))
1458 : {
1459 1330 : case t_LFUN_ZETA:
1460 : case t_LFUN_KRONECKER:
1461 1330 : case t_LFUN_CHIZ: return 1;
1462 980 : case t_LFUN_CHIGEN: return ldata_get_degree(ldata)==1;
1463 7448 : default: return 0;
1464 : }
1465 : }
1466 :
1467 : static ulong
1468 11016 : lfuninit_cutoff(GEN ldata)
1469 : {
1470 11016 : GEN gN = ldata_get_conductor(ldata);
1471 : ulong L, N;
1472 11016 : if (ldata_get_type(ldata) == t_LFUN_NF) /* N ~ f^(d-1), exact for d prime */
1473 742 : gN = sqrtnint(gN, ldata_get_degree(ldata) - 1);
1474 11016 : N = itou_or_0(gN);
1475 11016 : if (N > 1000) L = 7000;
1476 11002 : else if (N > 100) L = 5000;
1477 8013 : else if (N > 15) L = 3000;
1478 7558 : else L = 2500;
1479 11016 : return L;
1480 : }
1481 :
1482 : GEN
1483 36775 : lfuninit(GEN lmisc, GEN dom, long der, long bitprec)
1484 : {
1485 36775 : pari_sp av = avma;
1486 : GEN poqk, AB, R, h, theta, ldata, eno, r, domain, tech, k;
1487 : struct lfunp S;
1488 :
1489 36775 : if (is_linit(lmisc))
1490 : {
1491 25204 : long t = linit_get_type(lmisc);
1492 25204 : if (t == t_LDESC_INIT || t == t_LDESC_PRODUCT)
1493 : {
1494 25155 : if (checklfuninit(lmisc, dom, der, bitprec)) return lmisc;
1495 21 : pari_warn(warner,"lfuninit: insufficient initialization");
1496 : }
1497 : }
1498 11641 : ldata = lfunmisc_to_ldata_shallow(lmisc);
1499 :
1500 11641 : switch (ldata_get_type(ldata))
1501 : {
1502 630 : case t_LFUN_NF:
1503 : {
1504 630 : GEN T = gel(ldata_get_an(ldata), 2);
1505 630 : return gc_GEN(av, lfunzetakinit(T, dom, der, bitprec));
1506 : }
1507 91 : case t_LFUN_ABELREL:
1508 : {
1509 91 : GEN T = gel(ldata_get_an(ldata), 2);
1510 91 : return gc_GEN(av, lfunabelianrelinit(gel(T,1), gel(T,2), dom, der, bitprec));
1511 : }
1512 : }
1513 10920 : k = ldata_get_k(ldata);
1514 10920 : parse_dom(gtodouble(k), dom, &S);
1515 : /* Reduce domain for Dirichlet characters. NOT for Abelian t_LFUN_NF,
1516 : * handled above. */
1517 10920 : if (S.dw >= 0 && (!der && is_dirichlet(ldata)))
1518 1750 : S.dh = mindd(S.dh, lfuninit_cutoff(ldata));
1519 10920 : if (S.dw < 0)
1520 : {
1521 98 : if (der)
1522 0 : pari_err_IMPL("domain = [] for derivatives in lfuninit");
1523 98 : if (!is_dirichlet(ldata))
1524 0 : pari_err_IMPL("domain = [] for L functions of degree > 1");
1525 98 : return gc_GEN(av, lfunnoinit(ldata, bitprec));
1526 : }
1527 :
1528 10822 : lfunp_set(ldata, der, bitprec, &S);
1529 10822 : ldata = ldata_newprec(ldata, nbits2prec(S.Dmax));
1530 10822 : r = ldata_get_residue(ldata);
1531 : /* Note: all guesses should already have been performed (thetainit more
1532 : * expensive than needed: should be either tdom = 1 or bitprec = S.D).
1533 : * BUT if the root number / polar part do not have an algebraic
1534 : * expression, there is no way to do this until we know the
1535 : * precision, i.e. now. So we can't remove guessing code from here and
1536 : * lfun_init_theta */
1537 10822 : if (r && isintzero(r)) eno = NULL;
1538 : else
1539 : {
1540 10822 : eno = ldata_get_rootno(ldata);
1541 10822 : if (isintzero(eno)) eno = NULL;
1542 : }
1543 10822 : theta = lfun_init_theta(ldata, eno, &S);
1544 10808 : if (eno && !r)
1545 4599 : R = gen_0;
1546 : else
1547 : {
1548 6209 : GEN v = lfunrootres(theta, S.D);
1549 6209 : ldata = shallowcopy(ldata);
1550 6209 : gel(ldata, 6) = gel(v,3);
1551 6209 : r = gel(v,1);
1552 6209 : R = gel(v,2);
1553 6209 : if (isintzero(r)) setlg(ldata,7); else gel(ldata, 7) = r;
1554 : }
1555 10808 : h = divru(mplog2(S.precmax), S.m0);
1556 : /* exp(kh/2 . [0..M]) */
1557 10808 : poqk = gequal0(k) ? NULL
1558 10808 : : gpowers(gprec_w(mpexp(gmul2n(gmul(k,h), -1)), S.precmax), S.M);
1559 10808 : AB = lfuninit_ab(theta, h, &S);
1560 10808 : if (S.bn)
1561 : {
1562 154 : GEN A = gel(AB,1), B = gel(AB,2);
1563 154 : A = lfuninit_pol(A, poqk, S.precmax);
1564 154 : B = lfuninit_pol(B, poqk, S.precmax);
1565 154 : AB = mkvec2(A, B);
1566 : }
1567 : else
1568 10654 : AB = lfuninit_pol(AB, poqk, S.precmax);
1569 10808 : tech = mkvec3(h, AB, R);
1570 10808 : domain = mkvec2(dom, mkvecsmall2(der, bitprec));
1571 10808 : return gc_GEN(av, lfuninit_make(t_LDESC_INIT, ldata, tech, domain));
1572 : }
1573 :
1574 : GEN
1575 539 : lfuninit0(GEN lmisc, GEN dom, long der, long bitprec)
1576 : {
1577 539 : GEN z = lfuninit(lmisc, dom, der, bitprec);
1578 539 : return z == lmisc? gcopy(z): z;
1579 : }
1580 :
1581 : /* If s is a pole of Lambda, return polar part at s; else return NULL */
1582 : static GEN
1583 5305 : lfunpoleresidue(GEN R, GEN s)
1584 : {
1585 : long j;
1586 15390 : for (j = 1; j < lg(R); j++)
1587 : {
1588 10645 : GEN Rj = gel(R, j), be = gel(Rj, 1);
1589 10645 : if (gequal(s, be)) return gel(Rj, 2);
1590 : }
1591 4745 : return NULL;
1592 : }
1593 :
1594 : /* Compute contribution of polar part at s when not a pole. */
1595 : static GEN
1596 8825 : veccothderivn(GEN a, long n)
1597 : {
1598 : long i;
1599 8825 : pari_sp av = avma;
1600 8825 : GEN c = pol_x(0), cp = mkpoln(3, gen_m1, gen_0, gen_1);
1601 8825 : GEN v = cgetg(n+2, t_VEC);
1602 8825 : gel(v, 1) = poleval(c, a);
1603 26594 : for(i = 2; i <= n+1; i++)
1604 : {
1605 17769 : c = ZX_mul(ZX_deriv(c), cp);
1606 17769 : gel(v, i) = gdiv(poleval(c, a), mpfact(i-1));
1607 : }
1608 8825 : return gc_GEN(av, v);
1609 : }
1610 :
1611 : static GEN
1612 8944 : polepart(long n, GEN h, GEN C)
1613 : {
1614 8944 : GEN h2n = gpowgs(gdiv(h, gen_2), n-1);
1615 8944 : GEN res = gmul(h2n, gel(C,n));
1616 8944 : return odd(n)? res : gneg(res);
1617 : }
1618 :
1619 : static GEN
1620 4283 : lfunsumcoth(GEN R, GEN s, GEN h, long prec)
1621 : {
1622 : long i,j;
1623 4283 : GEN S = gen_0;
1624 13108 : for (j = 1; j < lg(R); ++j)
1625 : {
1626 8825 : GEN r = gel(R,j), be = gel(r,1), Rj = gel(r, 2);
1627 8825 : long e = valser(Rj);
1628 8825 : GEN z1 = gexpm1(gmul(h, gsub(s,be)), prec); /* exp(h(s-beta))-1 */
1629 8825 : GEN c1 = gaddgs(gdivsg(2, z1), 1); /* coth((h/2)(s-beta)) */
1630 8825 : GEN C1 = veccothderivn(c1, 1-e);
1631 17769 : for (i = e; i < 0; i++)
1632 : {
1633 8944 : GEN Rbe = mysercoeff(Rj, i);
1634 8944 : GEN p1 = polepart(-i, h, C1);
1635 8944 : S = gadd(S, gmul(Rbe, p1));
1636 : }
1637 : }
1638 4283 : return gmul2n(S, -1);
1639 : }
1640 :
1641 : static GEN lfunlambda_OK(GEN linit, GEN s, GEN sdom, long bitprec);
1642 : /* L is a t_LDESC_PRODUCT or t_LDESC_INIT Linit */
1643 : static GEN
1644 2456 : _product(GEN (*fun)(GEN,GEN,long), GEN L, GEN s, long bitprec)
1645 : {
1646 2456 : GEN ldata = linit_get_ldata(L), v, r, F, E, C, cs;
1647 : long i, l;
1648 : int isreal;
1649 2456 : if (linit_get_type(L) == t_LDESC_INIT) return fun(ldata, s, bitprec);
1650 1924 : v = lfunprod_get_fact(linit_get_tech(L));
1651 1924 : F = gel(v,1); E = gel(v,2); C = gel(v,3); l = lg(F);
1652 1924 : cs = conj_i(s); isreal = gequal(imag_i(s), imag_i(cs));
1653 6374 : for (i = 1, r = gen_1; i < l; ++i)
1654 : {
1655 4450 : GEN f = fun(gel(F, i), s, bitprec);
1656 4450 : if (typ(f)==t_VEC) f = RgV_prod(f);
1657 4450 : if (E[i]) r = gmul(r, gpowgs(f, E[i]));
1658 4450 : if (C[i])
1659 : {
1660 0 : GEN fc = isreal? f: conj_i(fun(gel(F, i), cs, bitprec));
1661 0 : r = gmul(r, gpowgs(fc, C[i]));
1662 : }
1663 : }
1664 1924 : return (ldata_isreal(ldata) && gequal0(imag_i(s)))? real_i(r): r;
1665 : }
1666 :
1667 : /* s a t_SER; # terms - 1 */
1668 : static long
1669 2290 : der_level(GEN s)
1670 2290 : { return signe(s)? lg(s)-3: valser(s)-1; }
1671 :
1672 : /* s a t_SER; return coeff(s, X^0) */
1673 : static GEN
1674 1260 : ser_coeff0(GEN s) { return simplify_shallow(polcoef_i(s, 0, -1)); }
1675 :
1676 : static GEN
1677 19962 : get_domain(GEN s, GEN *dom, long *der)
1678 : {
1679 19962 : GEN sa = s;
1680 19962 : *der = 0;
1681 19962 : switch(typ(s))
1682 : {
1683 7 : case t_POL:
1684 7 : case t_RFRAC: s = toser_i(s);
1685 1260 : case t_SER:
1686 1260 : *der = der_level(s);
1687 1260 : sa = ser_coeff0(s);
1688 : }
1689 19962 : *dom = mkvec3(real_i(sa), gen_0, gabs(imag_i(sa),DEFAULTPREC));
1690 19962 : return s;
1691 : }
1692 : /* assume s went through get_domain and s/bitprec belong to domain */
1693 : static GEN
1694 33646 : lfunlambda_OK(GEN linit, GEN s, GEN sdom, long bitprec)
1695 : {
1696 33646 : GEN dom, eno, ldata, tech, h, pol, k2, cost, S, S0 = NULL;
1697 : long prec, prec0;
1698 : struct lfunp D, D0;
1699 :
1700 33646 : if (linit_get_type(linit) == t_LDESC_PRODUCT)
1701 1679 : return _product(&lfunlambda, linit, s, bitprec);
1702 31967 : ldata = linit_get_ldata(linit);
1703 31967 : eno = ldata_get_rootno(ldata);
1704 31967 : tech = linit_get_tech(linit);
1705 31967 : dom = lfun_get_dom(tech);
1706 31967 : if (lg(dom) == 1) return lfunlambda(linit, s, bitprec); /* FIXME:not OK! */
1707 31967 : h = lfun_get_step(tech); prec = realprec(h);
1708 : /* try to reduce accuracy */
1709 31967 : parse_dom(0, sdom, &D0);
1710 31967 : parse_dom(0, dom, &D);
1711 31967 : if (0.8 * D.dh > D0.dh)
1712 : {
1713 16193 : cost = lfuncost(linit, sdom, typ(s)==t_SER? der_level(s): 0, bitprec);
1714 16193 : prec0 = nbits2prec(cost[2]);
1715 16193 : if (prec0 < prec) { prec = prec0; h = gprec_w(h, prec); }
1716 : }
1717 31967 : pol = lfun_get_pol(tech);
1718 31967 : s = gprec_w(s, prec);
1719 31967 : if (ldata_get_residue(ldata))
1720 : {
1721 4682 : GEN R = lfun_get_Residue(tech);
1722 4682 : GEN Ra = lfunpoleresidue(R, s);
1723 4682 : if (Ra) return gprec_w(Ra, nbits2prec(bitprec));
1724 4283 : S0 = lfunsumcoth(R, s, h, prec);
1725 : }
1726 31568 : k2 = lfun_get_k2(tech);
1727 31568 : if (typ(pol)==t_POL && typ(s) != t_SER && gequal(real_i(s), k2))
1728 25093 : { /* on critical line: shortcut */
1729 25093 : GEN polz, b = imag_i(s);
1730 25093 : polz = gequal0(b)? poleval(pol,gen_1): poleval(pol, expIr(gmul(h,b)));
1731 25093 : S = gadd(polz, gmulvec(eno, conj_i(polz)));
1732 : }
1733 : else
1734 : {
1735 6475 : GEN z = gexp(gmul(h, gsub(s, k2)), prec);
1736 6475 : GEN zi = ginv(z), zc = conj_i(zi);
1737 6475 : if (typ(pol)==t_POL)
1738 6279 : S = gadd(poleval(pol, z), gmulvec(eno, conj_i(poleval(pol, zc))));
1739 : else
1740 196 : S = gadd(poleval(gel(pol,1), z), gmulvec(eno, poleval(gel(pol,2), zi)));
1741 : }
1742 31568 : if (S0) S = gadd(S,S0);
1743 31568 : return gprec_w(gmul(S,h), nbits2prec(bitprec));
1744 : }
1745 :
1746 : static long
1747 38427 : lfunspec_OK(GEN lmisc, GEN s, GEN *pldata)
1748 : {
1749 38427 : long t, large = 0;
1750 : GEN ldata;
1751 38427 : *pldata = ldata = lfunmisc_to_ldata_shallow(lmisc);
1752 38420 : if (!is_linit(lmisc)) lmisc = ldata;
1753 25883 : else switch(linit_get_type(lmisc))
1754 : {
1755 25841 : case t_LDESC_INIT: case t_LDESC_PRODUCT:
1756 25841 : if (lg(lfun_get_dom(linit_get_tech(lmisc))) == 1) large = 1;
1757 25841 : break;
1758 42 : default: return 0;
1759 : }
1760 38378 : switch(typ(s))
1761 : {
1762 38007 : case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: break;
1763 371 : default: return 0;
1764 : }
1765 38007 : t = ldata_get_type(ldata);
1766 38007 : switch(t)
1767 : {
1768 7930 : case t_LFUN_KRONECKER: case t_LFUN_ZETA:
1769 7930 : if (typ(s) == t_INT && !is_bigint(s)) return 1;
1770 : /* fall through */
1771 : case t_LFUN_NF: case t_LFUN_CHIZ:
1772 8056 : if (!large)
1773 7762 : large = (fabs(gtodouble(imag_i(s))) >= lfuninit_cutoff(ldata));
1774 8056 : break;
1775 2057 : case t_LFUN_CHIGEN:
1776 2057 : if (ldata_get_degree(ldata) != 1) return 0;
1777 1735 : if (!large)
1778 1483 : large = (fabs(gtodouble(imag_i(s))) >= lfuninit_cutoff(ldata));
1779 1735 : break;
1780 : }
1781 33604 : if (large)
1782 : {
1783 1904 : if (t == t_LFUN_NF)
1784 : {
1785 14 : GEN an = ldata_get_an(ldata), nf = gel(an,2), G = galoisinit(nf, NULL);
1786 14 : if (isintzero(G) || !group_isabelian(galois_group(G))) return 0;
1787 : }
1788 1904 : return 2;
1789 : }
1790 31700 : return 0;
1791 : }
1792 :
1793 : GEN
1794 5108 : lfunlambda(GEN lmisc, GEN s, long bitprec)
1795 : {
1796 5108 : pari_sp av = avma;
1797 5108 : GEN linit = NULL, dom, z;
1798 : long der;
1799 5108 : s = get_domain(s, &dom, &der);
1800 5108 : if (!der)
1801 : {
1802 : GEN ldata;
1803 4261 : long t = lfunspec_OK(lmisc, s, &ldata);
1804 4261 : if (t == 1)
1805 : { /* special value ? */
1806 553 : GEN z = lfun(ldata, s, bitprec), gv = ldata_get_gammavec(ldata);
1807 553 : long e = itou(gel(gv, 1));
1808 553 : if (!isintzero(z) && (e || gsigne(s) > 0)) /* TODO */
1809 : {
1810 476 : GEN q = ldata_get_conductor(ldata);
1811 476 : long prec = nbits2prec(bitprec);
1812 476 : GEN se, r, Q = divir(q, mppi(prec));
1813 476 : se = gmul2n(gaddgs(s, e), -1);
1814 476 : r = gmul(gpow(Q, se, prec), ggamma(se, prec));
1815 476 : if (e && !equali1(q)) r = gdiv(r, gsqrt(q, prec));
1816 504 : return gc_upto(av, gmul(r, z));
1817 : }
1818 : }
1819 3785 : if (is_linit(lmisc)) linit = lmisc; else lmisc = ldata;
1820 3785 : if (t == 2)
1821 28 : return gc_GEN(av, linit? _product(&lfunlambda, linit, s, bitprec)
1822 0 : : lfunlambdalarge(ldata, s, bitprec));
1823 : }
1824 4604 : linit = lfuninit(lmisc, dom, der, bitprec);
1825 4604 : z = lfunlambda_OK(linit,s, dom, bitprec);
1826 4604 : return gc_GEN(av, z);
1827 : }
1828 :
1829 : static long
1830 18585 : is_ser(GEN x)
1831 : {
1832 18585 : long t = typ(x);
1833 18585 : if (t == t_SER) return 1;
1834 16562 : if (!is_vec_t(t) || lg(x)==1) return 0;
1835 350 : if (typ(gel(x,1))==t_SER) return 1;
1836 252 : return 0;
1837 : }
1838 :
1839 : static GEN
1840 371 : lfunser(GEN L)
1841 : {
1842 371 : long v = valser(L);
1843 371 : if (v > 0) return gen_0;
1844 329 : if (v == 0) L = gel(L, 2);
1845 : else
1846 203 : setlg(L, minss(lg(L), 2-v));
1847 329 : return L;
1848 : }
1849 :
1850 : static GEN
1851 371 : lfunservec(GEN x)
1852 : {
1853 371 : if (typ(x)==t_SER) return lfunser(x);
1854 0 : pari_APPLY_same(lfunser(gel(x,i)))
1855 : }
1856 : static GEN
1857 105 : lfununext(GEN L)
1858 : {
1859 105 : setlg(L, maxss(lg(L)-1, valser(L)? 2: 3));
1860 105 : return normalizeser(L);
1861 : }
1862 : static GEN
1863 105 : lfununextvec(GEN x)
1864 : {
1865 105 : if (typ(x)==t_SER) return lfununext(x);
1866 0 : pari_APPLY_same(lfununext(gel(x,i)));
1867 : }
1868 :
1869 : /* assume lmisc is an linit, s went through get_domain and s/bitprec belong
1870 : * to domain */
1871 : static GEN
1872 9940 : lfun_OK(GEN linit, GEN s, GEN sdom, long bitprec)
1873 : {
1874 9940 : GEN N, gas, S, FVga, res, ss = s;
1875 9940 : long prec = nbits2prec(bitprec), ext;
1876 :
1877 9940 : FVga = lfun_get_factgammavec(linit_get_tech(linit));
1878 9940 : S = lfunlambda_OK(linit, s, sdom, bitprec);
1879 9940 : if (is_ser(S))
1880 : {
1881 1687 : GEN r = typ(S)==t_SER ? S : gel(S,1);
1882 1687 : long d = lg(r) - 2 + fracgammadegree(FVga);
1883 1687 : if (typ(s) == t_SER)
1884 1358 : ss = sertoser(s, d);
1885 : else
1886 329 : ss = deg1ser_shallow(gen_1, s, varn(r), d);
1887 : }
1888 9940 : gas = gammafactproduct(FVga, ss, &ext, prec);
1889 9940 : N = ldata_get_conductor(linit_get_ldata(linit));
1890 9940 : res = gdiv(S, gmul(gpow(N, gdivgu(ss, 2), prec), gas));
1891 9940 : if (typ(s) != t_SER && is_ser(res)) res = lfunservec(res);
1892 9569 : else if (ext) res = lfununextvec(res);
1893 9940 : return gprec_w(res, prec);
1894 : }
1895 :
1896 : GEN
1897 13209 : lfun(GEN lmisc, GEN s, long bitprec)
1898 : {
1899 13209 : pari_sp av = avma;
1900 13209 : GEN linit = NULL, ldata, dom, z;
1901 : long der;
1902 13209 : s = get_domain(s, &dom, &der);
1903 13209 : if (der && typ(s) != t_SER)
1904 : {
1905 0 : if (lfunspec_OK(lmisc, s, &ldata))
1906 : {
1907 0 : linit = lfuninit(lmisc, cgetg(1,t_VEC), 0, bitprec);
1908 0 : return derivnumk((void*)linit, (GEN(*)(void*,GEN,long))&lfun,
1909 : s, stoi(der), nbits2prec(bitprec));
1910 : }
1911 : }
1912 : else
1913 : {
1914 13209 : long t = lfunspec_OK(lmisc, s, &ldata);
1915 13202 : if (t == 1)
1916 : { /* special value ? */
1917 3353 : long D = itos_or_0(gel(ldata_get_an(ldata), 2)), ss = itos(s);
1918 3353 : if (D)
1919 : {
1920 3353 : if (ss <= 0) return lfunquadneg(D, ss);
1921 : /* ss > 0 */
1922 770 : if ((!odd(ss) && D > 0) || (odd(ss) && D < 0))
1923 : {
1924 672 : long prec = nbits2prec(bitprec), q = labs(D);
1925 672 : ss = 1 - ss; /* <= 0 */
1926 672 : z = powrs(divrs(mppi(prec + EXTRAPREC64), q), 1-ss);
1927 672 : z = mulrr(shiftr(z, -ss), sqrtr_abs(utor(q, prec)));
1928 672 : z = gdiv(z, mpfactr(-ss, prec));
1929 672 : if (smodss(ss, 4) > 1) togglesign(z);
1930 672 : return gmul(z, lfunquadneg(D, ss));
1931 : }
1932 : }
1933 : }
1934 9947 : if (is_linit(lmisc)) linit = lmisc; else lmisc = ldata;
1935 9947 : if (t == 2)
1936 1211 : return gc_GEN(av, linit? _product(&lfun, linit, s, bitprec)
1937 231 : : lfunlarge(ldata, s, bitprec));
1938 : }
1939 8967 : linit = lfuninit(lmisc, dom, der, bitprec);
1940 8953 : z = lfun_OK(linit, s, dom, bitprec);
1941 8953 : return gc_GEN(av, z);
1942 : }
1943 :
1944 : /* given a t_SER a+x*s(x), return x*s(x), shallow */
1945 : static GEN
1946 42 : sersplit1(GEN s, GEN *head)
1947 : {
1948 42 : long i, l = lg(s);
1949 : GEN y;
1950 42 : *head = simplify_shallow(mysercoeff(s, 0));
1951 42 : if (valser(s) > 0) return s;
1952 28 : y = cgetg(l-1, t_SER); y[1] = s[1];
1953 28 : setvalser(y, 1);
1954 140 : for (i=3; i < l; i++) gel(y,i-1) = gel(s,i);
1955 28 : return normalizeser(y);
1956 : }
1957 :
1958 : /* order of pole of Lambda at s (0 if regular point) */
1959 : static long
1960 2254 : lfunlambdaord(GEN linit, GEN s)
1961 : {
1962 2254 : GEN tech = linit_get_tech(linit);
1963 2254 : if (linit_get_type(linit)==t_LDESC_PRODUCT)
1964 : {
1965 287 : GEN v = lfunprod_get_fact(linit_get_tech(linit));
1966 287 : GEN F = gel(v, 1), E = gel(v, 2), C = gel(v, 3);
1967 287 : long i, ex = 0, l = lg(F);
1968 980 : for (i = 1; i < l; i++)
1969 693 : ex += lfunlambdaord(gel(F,i), s) * (E[i]+C[i]);
1970 287 : return ex;
1971 : }
1972 1967 : if (ldata_get_residue(linit_get_ldata(linit)))
1973 : {
1974 623 : GEN r = lfunpoleresidue(lfun_get_Residue(tech), s);
1975 623 : if (r) return lg(r)-2;
1976 : }
1977 1806 : return 0;
1978 : }
1979 :
1980 : static GEN
1981 126 : derser(GEN res, long m)
1982 : {
1983 126 : long v = valser(res);
1984 126 : if (v > m) return gen_0;
1985 126 : if (v >= 0)
1986 126 : return gmul(mysercoeff(res, m), mpfact(m));
1987 : else
1988 0 : return derivn(res, m, -1);
1989 : }
1990 :
1991 : static GEN
1992 189 : derservec(GEN x, long m) { pari_APPLY_same(derser(gel(x,i),m)) }
1993 :
1994 : /* derivative of order m > 0 of L (flag = 0) or Lambda (flag = 1) */
1995 : static GEN
1996 1652 : lfunderiv(GEN lmisc, long m, GEN s, long flag, long bitprec)
1997 : {
1998 1652 : pari_sp ltop = avma;
1999 1652 : GEN res, S = NULL, linit, ldata, dom;
2000 1652 : long der, prec = nbits2prec(bitprec);
2001 1652 : if (m <= 0) pari_err_DOMAIN("lfun", "D", "<=", gen_0, stoi(m));
2002 1645 : s = get_domain(s, &dom, &der);
2003 1645 : if (typ(s) != t_SER && lfunspec_OK(lmisc, s, &ldata) == 2)
2004 : {
2005 28 : linit = lfuninit(lmisc, cgetg(1,t_VEC), 0, bitprec);
2006 28 : return derivnumk((void*)linit, (GEN(*)(void*,GEN,long))&lfun,
2007 : s, stoi(der + m), prec);
2008 : }
2009 1617 : linit = lfuninit(lmisc, dom, der + m, bitprec);
2010 1617 : if (lg(lfun_get_dom(linit_get_tech(linit))) == 1)
2011 14 : pari_err_IMPL("domain = [] for derivatives in lfuninit");
2012 1603 : if (typ(s) == t_SER)
2013 : {
2014 : GEN a;
2015 42 : if (valser(s) < 0) pari_err_DOMAIN("lfun","valuation", "<", gen_0, s);
2016 42 : S = sersplit1(s, &a);
2017 42 : s = deg1ser_shallow(gen_1, a, varn(S), m + ceildivuu(lg(s)-2, valser(S)));
2018 : }
2019 : else
2020 : {
2021 1561 : long e = lfunlambdaord(linit, s) + m + 1;
2022 : /* HACK: pretend lfuninit was done to right accuracy */
2023 1561 : if (gequal0(s)) { s = gen_0; e--; }
2024 1561 : s = deg1ser_shallow(gen_1, s, 0, e);
2025 : }
2026 1603 : res = flag ? lfunlambda_OK(linit, s, dom, bitprec):
2027 987 : lfun_OK(linit, s, dom, bitprec);
2028 1603 : if (S)
2029 42 : res = gsubst(derivn(res, m, -1), varn(S), S);
2030 1561 : else if (typ(res)==t_SER)
2031 : {
2032 1498 : long v = valser(res);
2033 1498 : if (v > m) { set_avma(ltop); return gen_0; }
2034 1484 : if (v >= 0)
2035 1358 : res = gmul(mysercoeff(res, m), mpfact(m));
2036 : else
2037 126 : res = derivn(res, m, -1);
2038 : }
2039 63 : else if (is_ser(res))
2040 63 : res = derservec(res, m);
2041 1589 : return gc_GEN(ltop, gprec_w(res, prec));
2042 : }
2043 :
2044 : GEN
2045 1540 : lfunlambda0(GEN lmisc, GEN s, long der, long bitprec)
2046 : {
2047 637 : return der? lfunderiv(lmisc, der, s, 1, bitprec)
2048 2170 : : lfunlambda(lmisc, s, bitprec);
2049 : }
2050 :
2051 : GEN
2052 6930 : lfun0(GEN lmisc, GEN s, long der, long bitprec)
2053 : {
2054 1015 : return der? lfunderiv(lmisc, der, s, 0, bitprec)
2055 7931 : : lfun(lmisc, s, bitprec);
2056 : }
2057 :
2058 : GEN
2059 19361 : lfunhardy(GEN lmisc, GEN t, long bitprec)
2060 : {
2061 19361 : pari_sp ltop = avma;
2062 19361 : long prec = nbits2prec(bitprec), d, isbig = 0;
2063 : GEN linit, h, ldata, tech, w2, k2, E, a, argz, z;
2064 :
2065 19361 : switch(typ(t))
2066 : {
2067 19354 : case t_INT: case t_FRAC: case t_REAL: break;
2068 7 : default: pari_err_TYPE("lfunhardy",t);
2069 : }
2070 19354 : if (lfunspec_OK(lmisc, mkcomplex(gen_0, t), &ldata) == 2)
2071 : {
2072 868 : long B = bitprec + maxss(gexpo(t), 0);
2073 868 : GEN L = NULL;
2074 868 : isbig = 1;
2075 868 : k2 = ghalf;
2076 868 : z = mkcomplex(k2, t);
2077 868 : if (is_linit(lmisc))
2078 : {
2079 742 : linit = lmisc;
2080 742 : if (linit_get_type(linit) == t_LDESC_PRODUCT)
2081 14 : L = mkvec(linit);/*HACK*/
2082 : }
2083 : else
2084 : {
2085 126 : linit = lfunnoinit(ldata, B);
2086 126 : ldata = linit_get_ldata(linit); /* make sure eno is included */
2087 : }
2088 868 : h = lfunloglambdalarge(L? L: ldata, gprec_w(z, nbits2prec(B)), B);
2089 868 : tech = linit_get_tech(linit);
2090 : }
2091 : else
2092 : {
2093 18486 : GEN k = ldata_get_k(ldata);
2094 18486 : GEN dom = mkvec3(gmul2n(k, -1), gen_0, gabs(t,LOWDEFAULTPREC));
2095 18486 : if (!is_linit(lmisc)) lmisc = ldata;
2096 18486 : linit = lfuninit(lmisc, dom, 0, bitprec);
2097 18486 : tech = linit_get_tech(linit);
2098 18486 : k2 = lfun_get_k2(tech);
2099 18486 : z = mkcomplex(k2, t);
2100 18486 : h = lfunlambda_OK(linit, z, dom, bitprec);
2101 : }
2102 19354 : w2 = lfun_get_w2(tech);
2103 19354 : E = lfun_get_expot(tech); /* 4E = d(k2 - 1) + real(vecsum(Vga)) */
2104 19354 : d = ldata_get_degree(ldata);
2105 : /* more accurate than garg: k/2 in Q */
2106 19354 : argz = gequal0(k2)? Pi2n(-1, prec): gatan(gdiv(t, k2), prec);
2107 19354 : prec = precision(argz);
2108 : /* prec may have increased: don't lose accuracy if |z|^2 is exact */
2109 19354 : a = gsub(gmulsg(d, gmul(t, gmul2n(argz,-1))),
2110 : gmul(E, glog(gnorm(z),prec)));
2111 19354 : if (!isint1(w2) && typ(ldata_get_dual(ldata))==t_INT)
2112 16198 : h = isbig ? gadd(h, glog(w2, prec)) : mulrealvec(h, w2);
2113 19354 : if (typ(h) == t_COMPLEX && gexpo(imag_i(h)) < -(bitprec >> 1))
2114 2547 : h = real_i(h);
2115 19354 : if (isbig) h = greal(gexp(gadd(h, a), prec));
2116 18486 : else h = gmul(h, gexp(a, prec));
2117 19354 : return gc_upto(ltop, h);
2118 : }
2119 :
2120 : /* L = log(t); return \sum_{i = 0}^{v-1} R[-i-1] L^i/i! */
2121 : static GEN
2122 2030 : theta_pole_contrib(GEN R, long v, GEN L)
2123 : {
2124 2030 : GEN s = mysercoeff(R,-v);
2125 : long i;
2126 2135 : for (i = v-1; i >= 1; i--)
2127 105 : s = gadd(mysercoeff(R,-i), gdivgu(gmul(s,L), i));
2128 2030 : return s;
2129 : }
2130 : /* subtract successively rather than adding everything then subtracting.
2131 : * The polar part is "large" and suffers from cancellation: a little stabler
2132 : * this way */
2133 : static GEN
2134 6979 : theta_add_polar_part(GEN S, GEN R, GEN t, long prec)
2135 : {
2136 6979 : GEN logt = NULL;
2137 6979 : long j, l = lg(R);
2138 9009 : for (j = 1; j < l; j++)
2139 : {
2140 2030 : GEN Rj = gel(R,j), b = gel(Rj,1), Rb = gel(Rj,2);
2141 2030 : long v = -valser(Rb);
2142 2030 : if (v > 1 && !logt) logt = glog(t, prec);
2143 2030 : S = gsub(S, gmul(theta_pole_contrib(Rb,v,logt), gpow(t,b,prec)));
2144 : }
2145 6979 : return S;
2146 : }
2147 :
2148 : static long
2149 3626 : lfuncheckfeq_i(GEN theta, GEN thetad, GEN t0, GEN t0i, long bitprec)
2150 : {
2151 3626 : GEN ldata = linit_get_ldata(theta);
2152 : GEN S0, S0i, w, eno;
2153 3626 : long prec = nbits2prec(bitprec);
2154 3626 : if (thetad)
2155 70 : S0 = lfuntheta(thetad, t0, 0, bitprec);
2156 : else
2157 3556 : S0 = conj_i(lfuntheta(theta, conj_i(t0), 0, bitprec));
2158 3626 : S0i = lfuntheta(theta, t0i, 0, bitprec);
2159 :
2160 3626 : eno = ldata_get_rootno(ldata);
2161 3626 : if (ldata_get_residue(ldata))
2162 : {
2163 987 : GEN R = theta_get_R(linit_get_tech(theta));
2164 987 : if (gequal0(R))
2165 : {
2166 : GEN v, r;
2167 105 : long t = ldata_get_type(ldata);
2168 105 : if (t == t_LFUN_NF || t == t_LFUN_ABELREL)
2169 : { /* inefficient since theta not needed; no need to optimize for this
2170 : (artificial) query [e.g. lfuncheckfeq(t_POL)] */
2171 42 : GEN L = lfuninit(ldata,zerovec(3),0,bitprec);
2172 42 : return lfuncheckfeq(L,t0,bitprec);
2173 : }
2174 63 : v = lfunrootres(theta, bitprec);
2175 63 : r = gel(v,1);
2176 63 : if (gequal0(eno)) eno = gel(v,3);
2177 63 : R = lfunrtoR_i(ldata, r, eno, nbits2prec(bitprec));
2178 : }
2179 945 : S0i = theta_add_polar_part(S0i, R, t0, prec);
2180 : }
2181 3584 : if (gequal0(S0i) || gequal0(S0)) pari_err_PREC("lfuncheckfeq");
2182 :
2183 3584 : w = gdivvec(S0i, gmul(S0, gpow(t0, ldata_get_k(ldata), prec)));
2184 : /* missing rootno: guess it */
2185 3584 : if (gequal0(eno)) eno = lfunrootno(theta, bitprec);
2186 3584 : w = gsubvec(w, eno);
2187 3584 : if (thetad) w = gdivvec(w, eno); /* |eno| may be large in non-dual case */
2188 3584 : return gexpo(w);
2189 : }
2190 :
2191 : /* Check whether the coefficients, conductor, weight, polar part and root
2192 : * number are compatible with the functional equation at t0 and 1/t0.
2193 : * Different from lfunrootres. */
2194 : long
2195 3759 : lfuncheckfeq(GEN lmisc, GEN t0, long bitprec)
2196 : {
2197 : GEN ldata, theta, thetad, t0i;
2198 : pari_sp av;
2199 :
2200 3759 : if (is_linit(lmisc) && linit_get_type(lmisc)==t_LDESC_PRODUCT)
2201 : {
2202 168 : GEN v = lfunprod_get_fact(linit_get_tech(lmisc)), F = gel(v,1);
2203 168 : long i, b = -bitprec, l = lg(F);
2204 560 : for (i = 1; i < l; i++) b = maxss(b, lfuncheckfeq(gel(F,i), t0, bitprec));
2205 168 : return b;
2206 : }
2207 3591 : av = avma;
2208 3591 : if (!t0)
2209 : { /* ~Pi/3 + I/7, some random complex number */
2210 3416 : t0 = mkcomplex(uutoQ(355,339), uutoQ(1,7));
2211 3416 : t0i = ginv(t0);
2212 : }
2213 175 : else if (gcmpgs(gnorm(t0), 1) < 0) { t0i = t0; t0 = ginv(t0); }
2214 119 : else t0i = ginv(t0);
2215 : /* |t0| >= 1 */
2216 3591 : theta = lfunthetacheckinit(lmisc, t0i, 0, bitprec);
2217 3584 : ldata = linit_get_ldata(theta);
2218 3584 : thetad = theta_dual(theta, ldata_get_dual(ldata));
2219 3584 : return gc_long(av, lfuncheckfeq_i(theta, thetad, t0, t0i, bitprec));
2220 : }
2221 :
2222 : /*******************************************************************/
2223 : /* Compute root number and residues */
2224 : /*******************************************************************/
2225 : /* round root number to \pm 1 if close to integer. */
2226 : static GEN
2227 6384 : ropm1(GEN w, long prec)
2228 : {
2229 : long e;
2230 : GEN r;
2231 6384 : if (typ(w) == t_INT) return w;
2232 5978 : r = grndtoi(w, &e);
2233 5978 : return (e < -prec/2)? r: w;
2234 : }
2235 :
2236 : /* theta for t=1/sqrt(2) and t2==2t simultaneously, saving 25% of the work.
2237 : * Assume correct initialization (no thetacheck) */
2238 : static void
2239 434 : lfunthetaspec(GEN linit, long bitprec, GEN *pv, GEN *pv2)
2240 : {
2241 434 : pari_sp av = avma, av2;
2242 : GEN t, Vga, an, K, ldata, thetainit, v, v2, vroots;
2243 : long L, prec, n, d;
2244 :
2245 434 : ldata = linit_get_ldata(linit);
2246 434 : thetainit = linit_get_tech(linit);
2247 434 : prec = nbits2prec(bitprec);
2248 434 : Vga = ldata_get_gammavec(ldata); d = lg(Vga)-1;
2249 434 : if (Vgaeasytheta(Vga))
2250 : {
2251 224 : GEN v2 = sqrtr(real2n(1, nbits2prec(bitprec)));
2252 224 : GEN v = shiftr(v2,-1);
2253 224 : *pv = lfuntheta(linit, v, 0, bitprec);
2254 224 : *pv2= lfuntheta(linit, v2, 0, bitprec);
2255 224 : return;
2256 : }
2257 210 : an = RgV_kill0( theta_get_an(thetainit) );
2258 210 : L = lg(an)-1;
2259 : /* to compute theta(1/sqrt(2)) */
2260 210 : t = ginv(gsqrt(gmul2n(ldata_get_conductor(ldata), 1), prec));
2261 : /* t = 1/sqrt(2N) */
2262 :
2263 : /* From then on, the code is generic and could be used to compute
2264 : * theta(t) / theta(2t) without assuming t = 1/sqrt(2) */
2265 210 : K = theta_get_K(thetainit);
2266 210 : vroots = mkvroots(d, L, prec);
2267 210 : t = gpow(t, gdivgu(gen_2, d), prec); /* rt variant: t->t^(2/d) */
2268 : /* v = \sum_{n <= L, n odd} a_n K(nt) */
2269 1815212 : for (v = gen_0, n = 1; n <= L; n+=2)
2270 : {
2271 1815002 : GEN tn, Kn, a = gel(an, n);
2272 :
2273 1815002 : if (!a) continue;
2274 113729 : av2 = avma;
2275 113729 : tn = gmul(t, gel(vroots,n));
2276 113729 : Kn = gammamellininvrt(K, tn, bitprec);
2277 113729 : v = gc_upto(av2, gadd(v, gmul(a,Kn)));
2278 : }
2279 : /* v += \sum_{n <= L, n even} a_n K(nt), v2 = \sum_{n <= L/2} a_n K(2n t) */
2280 1815114 : for (v2 = gen_0, n = 1; n <= L/2; n++)
2281 : {
2282 1814904 : GEN t2n, K2n, a = gel(an, n), a2 = gel(an,2*n);
2283 :
2284 1814904 : if (!a && !a2) continue;
2285 120484 : av2 = avma;
2286 120484 : t2n = gmul(t, gel(vroots,2*n));
2287 120484 : K2n = gc_upto(av2, gammamellininvrt(K, t2n, bitprec));
2288 120484 : if (a) v2 = gadd(v2, gmul(a, K2n));
2289 120484 : if (a2) v = gadd(v, gmul(a2,K2n));
2290 : }
2291 210 : *pv = v;
2292 210 : *pv2 = v2;
2293 210 : (void)gc_all(av, 2, pv,pv2);
2294 : }
2295 :
2296 : static GEN
2297 413 : Rtor(GEN a, GEN R, GEN ldata, long prec)
2298 : {
2299 413 : GEN FVga = gammafactor(ldata_get_gammavec(ldata));
2300 413 : GEN Na = gpow(ldata_get_conductor(ldata), gdivgu(a,2), prec);
2301 : long ext;
2302 413 : return gdiv(R, gmul(Na, gammafactproduct(FVga, a, &ext, prec)));
2303 : }
2304 :
2305 : /* v = theta~(t), vi = theta(1/t) */
2306 : static GEN
2307 6034 : get_eno(GEN R, GEN k, GEN t, GEN v, GEN vi, long vx, long bitprec, long force)
2308 : {
2309 6034 : long prec = nbits2prec(bitprec);
2310 6034 : GEN a0, a1, S = deg1pol(gmul(gpow(t,k,prec), gneg(v)), vi, vx);
2311 :
2312 6034 : S = theta_add_polar_part(S, R, t, prec);
2313 6034 : if (typ(S) != t_POL || degpol(S) != 1) return NULL;
2314 6034 : a1 = gel(S,3); if (!force && gexpo(a1) < -bitprec/4) return NULL;
2315 5971 : a0 = gel(S,2);
2316 5971 : return gdivvec(a0, gneg(a1));
2317 :
2318 : }
2319 : /* Return w using theta(1/t) - w t^k \bar{theta}(t) = polar_part(t,w).
2320 : * The full Taylor expansion of L must be known */
2321 : GEN
2322 5971 : lfunrootno(GEN linit, long bitprec)
2323 : {
2324 : GEN ldata, t, eno, v, vi, R, thetad;
2325 5971 : long c = 0, prec = nbits2prec(bitprec), vx = fetch_var();
2326 : GEN k;
2327 : pari_sp av;
2328 :
2329 : /* initialize for t > 1/sqrt(2) */
2330 5971 : linit = lfunthetacheckinit(linit, dbltor(sqrt(0.5)), 0, bitprec);
2331 5971 : ldata = linit_get_ldata(linit);
2332 5971 : k = ldata_get_k(ldata);
2333 5985 : R = ldata_get_residue(ldata)? lfunrtoR_eno(ldata, pol_x(vx), prec)
2334 5971 : : cgetg(1, t_VEC);
2335 5971 : t = gen_1;
2336 5971 : v = lfuntheta(linit, t, 0, bitprec);
2337 5971 : thetad = theta_dual(linit, ldata_get_dual(ldata));
2338 5971 : vi = !thetad ? conj_i(v): lfuntheta(thetad, t, 0, bitprec);
2339 5971 : eno = get_eno(R,k,t,vi,v, vx, bitprec, 0);
2340 5971 : if (!eno && !thetad)
2341 : { /* t = sqrt(2), vi = theta(1/t), v = theta(t) */
2342 21 : lfunthetaspec(linit, bitprec, &vi, &v);
2343 21 : t = sqrtr(utor(2, prec));
2344 21 : eno = get_eno(R,k,t,conj_i(v),vi, vx, bitprec, 0);
2345 : }
2346 5971 : av = avma;
2347 6013 : while (!eno)
2348 : {
2349 42 : t = addsr(1, shiftr(utor(pari_rand(), prec), -2-BITS_IN_LONG));
2350 : /* t in [1,1.25[ */
2351 0 : v = thetad? lfuntheta(thetad, t, 0, bitprec)
2352 42 : : conj_i(lfuntheta(linit, t, 0, bitprec));
2353 42 : vi = lfuntheta(linit, ginv(t), 0, bitprec);
2354 42 : eno = get_eno(R,k,t,v,vi, vx, bitprec, c++ == 5);
2355 42 : set_avma(av);
2356 : }
2357 5971 : delete_var(); return ropm1(eno,prec);
2358 : }
2359 :
2360 : /* Find root number and/or residues when L-function coefficients and
2361 : conductor are known. For the moment at most a single residue allowed. */
2362 : GEN
2363 6902 : lfunrootres(GEN data, long bitprec)
2364 : {
2365 6902 : pari_sp ltop = avma;
2366 : GEN k, w, r, R, a, b, e, v, v2, be, ldata, linit;
2367 : long prec;
2368 :
2369 6902 : ldata = lfunmisc_to_ldata_shallow(data);
2370 6902 : r = ldata_get_residue(ldata);
2371 6902 : k = ldata_get_k(ldata);
2372 6902 : w = ldata_get_rootno(ldata);
2373 6902 : if (r) r = normalize_simple_pole(r, k);
2374 6902 : if (!r || residues_known(r))
2375 : {
2376 6489 : if (isintzero(w)) w = lfunrootno(data, bitprec);
2377 6489 : if (!r)
2378 4284 : r = R = gen_0;
2379 : else
2380 2205 : R = lfunrtoR_eno(ldata, w, nbits2prec(bitprec));
2381 6489 : return gc_GEN(ltop, mkvec3(r, R, w));
2382 : }
2383 413 : linit = lfunthetacheckinit(data, dbltor(sqrt(0.5)), 0, bitprec);
2384 413 : prec = nbits2prec(bitprec);
2385 413 : if (lg(r) > 2) pari_err_IMPL("multiple poles in lfunrootres");
2386 : /* Now residue unknown, and r = [[be,0]]. */
2387 413 : be = gmael(r, 1, 1);
2388 413 : if (ldata_isreal(ldata) && gequalm1(w))
2389 0 : R = lfuntheta(linit, gen_1, 0, bitprec);
2390 : else
2391 : {
2392 413 : GEN p2k = gpow(gen_2,k,prec);
2393 413 : lfunthetaspec(linit, bitprec, &v2, &v);
2394 413 : if (gequal(gmulsg(2, be), k)) pari_err_IMPL("pole at k/2 in lfunrootres");
2395 413 : if (gequal(be, k))
2396 : {
2397 147 : a = conj_i(gsub(gmul(p2k, v), v2));
2398 147 : b = subiu(p2k, 1);
2399 147 : e = gmul(gsqrt(p2k, prec), gsub(v2, v));
2400 : }
2401 : else
2402 : {
2403 266 : GEN tk2 = gsqrt(p2k, prec);
2404 266 : GEN tbe = gpow(gen_2, be, prec);
2405 266 : GEN tkbe = gpow(gen_2, gdivgu(gsub(k, be), 2), prec);
2406 266 : a = conj_i(gsub(gmul(tbe, v), v2));
2407 266 : b = gsub(gdiv(tbe, tkbe), tkbe);
2408 266 : e = gsub(gmul(gdiv(tbe, tk2), v2), gmul(tk2, v));
2409 : }
2410 413 : if (isintzero(w))
2411 : { /* Now residue unknown, r = [[be,0]], and w unknown. */
2412 7 : GEN t0 = mkfrac(utoi(11),utoi(10));
2413 7 : GEN th1 = lfuntheta(linit, t0, 0, bitprec);
2414 7 : GEN th2 = lfuntheta(linit, ginv(t0), 0, bitprec);
2415 7 : GEN tbe = gpow(t0, gmulsg(2, be), prec);
2416 7 : GEN tkbe = gpow(t0, gsub(k, be), prec);
2417 7 : GEN tk2 = gpow(t0, k, prec);
2418 7 : GEN c = conj_i(gsub(gmul(tbe, th1), th2));
2419 7 : GEN d = gsub(gdiv(tbe, tkbe), tkbe);
2420 7 : GEN f = gsub(gmul(gdiv(tbe, tk2), th2), gmul(tk2, th1));
2421 7 : GEN D = gsub(gmul(a, d), gmul(b, c));
2422 7 : w = gdiv(gsub(gmul(d, e), gmul(b, f)), D);
2423 : }
2424 413 : w = ropm1(w, prec);
2425 413 : R = gdiv(gsub(e, gmul(a, w)), b);
2426 : }
2427 413 : r = normalize_simple_pole(Rtor(be, R, ldata, prec), be);
2428 413 : R = lfunrtoR_i(ldata, r, w, prec);
2429 413 : return gc_GEN(ltop, mkvec3(r, R, w));
2430 : }
2431 :
2432 : /*******************************************************************/
2433 : /* Zeros */
2434 : /*******************************************************************/
2435 : struct lhardyz_t {
2436 : long bitprec, prec;
2437 : GEN linit;
2438 : };
2439 :
2440 : static GEN
2441 18563 : lfunhardyzeros(void *E, GEN t)
2442 : {
2443 18563 : struct lhardyz_t *S = (struct lhardyz_t*)E;
2444 18563 : GEN z = gprec_wensure(lfunhardy(S->linit, t, S->bitprec), S->prec);
2445 18563 : return typ(z) == t_VEC ? RgV_prod(z): z;
2446 : }
2447 :
2448 : /* initialize for computation on critical line up to height h, zero
2449 : * of order <= m */
2450 : static GEN
2451 567 : lfuncenterinit(GEN lmisc, double h, long m, long bitprec)
2452 : {
2453 567 : GEN ldata = lfunmisc_to_ldata_shallow(lmisc);
2454 567 : if (m < 0)
2455 : { /* choose a sensible default */
2456 567 : m = 4;
2457 567 : if (is_linit(lmisc) && linit_get_type(lmisc) == t_LDESC_INIT)
2458 : {
2459 476 : GEN domain = lfun_get_domain(linit_get_tech(lmisc));
2460 476 : m = domain_get_der(domain);
2461 : }
2462 : }
2463 567 : if (is_dirichlet(ldata)) m = 0;
2464 567 : return lfuninit(lmisc, mkvec(dbltor(h)), m, bitprec);
2465 : }
2466 :
2467 : long
2468 560 : lfunorderzero(GEN lmisc, long m, long bitprec)
2469 : {
2470 560 : pari_sp ltop = avma;
2471 : GEN eno, ldata, linit, k2;
2472 : long G, c0, c, st;
2473 :
2474 560 : if (is_linit(lmisc) && linit_get_type(lmisc) == t_LDESC_PRODUCT)
2475 : {
2476 84 : GEN M = gmael(linit_get_tech(lmisc), 2,1);
2477 84 : long i, l = lg(M);
2478 280 : for (c=0, i=1; i < l; i++) c += lfunorderzero(gel(M,i), m, bitprec);
2479 84 : return c;
2480 : }
2481 476 : linit = lfuncenterinit(lmisc, 0, m, bitprec);
2482 476 : ldata = linit_get_ldata(linit);
2483 476 : eno = ldata_get_rootno(ldata);
2484 476 : k2 = gmul2n(ldata_get_k(ldata), -1);
2485 476 : G = -bitprec/2;
2486 476 : c0 = 0; st = 1;
2487 476 : if (typ(eno) == t_VEC)
2488 : {
2489 42 : long i, l = lg(eno), cnt = l-1, s = 0;
2490 42 : GEN v = zero_zv(l-1);
2491 42 : if (ldata_isreal(ldata)) st = 2;
2492 84 : for (c = c0; cnt; c += st)
2493 : {
2494 42 : GEN L = lfun0(linit, k2, c, bitprec);
2495 154 : for (i = 1; i < l; i++)
2496 : {
2497 112 : if (v[i]==0 && gexpo(gel(L,i)) > G)
2498 : {
2499 112 : v[i] = c; cnt--; s += c;
2500 : }
2501 : }
2502 : }
2503 42 : return gc_long(ltop,s);
2504 : }
2505 : else
2506 : {
2507 434 : if (ldata_isreal(ldata)) { st = 2; if (!gequal1(eno)) c0 = 1; }
2508 462 : for (c = c0;; c += st)
2509 462 : if (gexpo(lfun0(linit, k2, c, bitprec)) > G) return gc_long(ltop, c);
2510 : }
2511 : }
2512 :
2513 : /* assume T1 * T2 > 0, T1 <= T2 */
2514 : static void
2515 98 : lfunzeros_i(struct lhardyz_t *S, GEN *pw, long *ct, GEN T1, GEN T2, long d,
2516 : GEN cN, GEN pi2, GEN pi2div, long precinit, long prec)
2517 : {
2518 98 : GEN T = T1, w = *pw;
2519 98 : long W = lg(w)-1, s = gsigne(lfunhardyzeros(S, T1));
2520 : for(;;)
2521 427 : {
2522 525 : pari_sp av = avma;
2523 : GEN D, T0, z;
2524 525 : D = gcmp(T, pi2) < 0? cN
2525 525 : : gadd(cN, gmulsg(d, glog(gdiv(T, pi2), prec)));
2526 525 : D = gdiv(pi2div, gmulsg(d, D));
2527 : for(;;)
2528 13482 : {
2529 : long s0;
2530 14007 : T0 = T; T = gadd(T, D);
2531 14007 : if (gcmp(T, T2) >= 0) T = T2;
2532 14007 : s0 = gsigne(lfunhardyzeros(S, T));
2533 14007 : if (s0 != s) { s = s0; break; }
2534 13580 : if (T == T2) { setlg(w, *ct); *pw = w; return; }
2535 : }
2536 427 : z = zbrent(S, lfunhardyzeros, T0, T, prec); /* T <= T2 */
2537 427 : (void)gc_all(av, 2, &T, &z);
2538 427 : if (*ct > W) { W *= 2; w = vec_lengthen(w, W); }
2539 427 : if (typ(z) == t_REAL) z = rtor(z, precinit);
2540 427 : gel(w, (*ct)++) = z;
2541 : }
2542 : setlg(w, *ct); *pw = w;
2543 : }
2544 : GEN
2545 98 : lfunzeros(GEN ldata, GEN lim, long divz, long bitprec)
2546 : {
2547 98 : pari_sp ltop = avma;
2548 : GEN linit, pi2, pi2div, cN, w, T, h1, h2;
2549 98 : long i, d, NEWD, c, ct, s1, s2, prec, prec0 = nbits2prec(bitprec);
2550 : double maxt;
2551 : struct lhardyz_t S;
2552 :
2553 98 : if (is_linit(ldata) && linit_get_type(ldata) == t_LDESC_PRODUCT)
2554 : {
2555 0 : GEN M = gmael(linit_get_tech(ldata), 2,1);
2556 0 : long l = lg(M);
2557 0 : w = cgetg(l, t_VEC);
2558 0 : for (i = 1; i < l; i++) gel(w,i) = lfunzeros(gel(M,i), lim, divz, bitprec);
2559 0 : return gc_upto(ltop, vecsort0(shallowconcat1(w), NULL, 0));
2560 : }
2561 98 : if (typ(lim) == t_VEC)
2562 : {
2563 : double H1, H2;
2564 63 : if (lg(lim) != 3 || gcmp(gel(lim, 1), gel(lim, 2)) >= 0)
2565 7 : pari_err_TYPE("lfunzeros",lim);
2566 56 : h1 = gel(lim, 1); H1 = gtodouble(h1);
2567 56 : h2 = gel(lim, 2); H2 = gtodouble(h2);
2568 56 : maxt = maxdd(fabs(H1), fabs(H2));
2569 56 : if (H1 * H2 > 0)
2570 : {
2571 35 : GEN LDATA = lfunmisc_to_ldata_shallow(ldata);
2572 35 : double m = mindd(fabs(H1), fabs(H2));
2573 35 : if (is_dirichlet(LDATA) && m > lfuninit_cutoff(LDATA)) maxt = 0;
2574 : }
2575 : }
2576 : else
2577 : {
2578 35 : if (gcmp(lim, gen_0) <= 0) pari_err_TYPE("lfunzeros",lim);
2579 35 : h1 = gen_0;
2580 35 : h2 = lim;
2581 35 : maxt = gtodouble(h2);
2582 : }
2583 91 : S.linit = linit = lfuncenterinit(ldata, maxt, -1, bitprec);
2584 91 : S.bitprec = bitprec;
2585 91 : S.prec = prec0;
2586 91 : ldata = linit_get_ldata(linit);
2587 91 : d = ldata_get_degree(ldata);
2588 :
2589 91 : NEWD = minss((long) ceil(bitprec + (M_PI/(4*M_LN2)) * d * maxt),
2590 : lfun_get_bitprec(linit_get_tech(linit)));
2591 91 : prec = nbits2prec(NEWD);
2592 91 : cN = gdiv(ldata_get_conductor(ldata), gpowgs(Pi2n(-1, prec), d));
2593 91 : cN = gexpo(cN) >= 0? gaddsg(d, gmulsg(2, glog(cN, prec))): utoi(d);
2594 91 : pi2 = Pi2n(1, prec);
2595 91 : pi2div = gdivgu(pi2, labs(divz));
2596 91 : s1 = gsigne(h1);
2597 91 : s2 = gsigne(h2);
2598 91 : w = cgetg(100+1, t_VEC); c = 1; ct = 0; T = NULL;
2599 91 : if (s1 <= 0 && s2 >= 0)
2600 : {
2601 56 : GEN r = ldata_get_residue(ldata);
2602 56 : if (!r || gequal0(r))
2603 : {
2604 35 : ct = lfunorderzero(linit, -1, bitprec);
2605 35 : if (ct) T = real2n(-prec / (2*ct), prec);
2606 : }
2607 : }
2608 91 : if (s1 <= 0)
2609 : {
2610 63 : if (s1 < 0)
2611 21 : lfunzeros_i(&S, &w, &c, h1, T? negr(T): h2,
2612 : d, cN, pi2, pi2div, prec0, prec);
2613 63 : if (ct)
2614 : {
2615 21 : long n = lg(w)-1;
2616 21 : if (c + ct >= n) w = vec_lengthen(w, n + ct);
2617 84 : for (i = 1; i <= ct; i++) gel(w,c++) = gen_0;
2618 : }
2619 : }
2620 91 : if (s2 > 0 && (T || s1 >= 0))
2621 77 : lfunzeros_i(&S, &w, &c, T? T: h1, h2, d, cN, pi2, pi2div, prec0, prec);
2622 91 : return gc_GEN(ltop, w);
2623 : }
2624 :
2625 : /*******************************************************************/
2626 : /* Guess conductor */
2627 : /*******************************************************************/
2628 : struct huntcond_t {
2629 : GEN k;
2630 : GEN theta, thetad;
2631 : GEN *pM, *psqrtM, *pMd, *psqrtMd;
2632 : };
2633 :
2634 : static void
2635 11879 : condset(struct huntcond_t *S, GEN M, long prec)
2636 : {
2637 11879 : *(S->pM) = M;
2638 11879 : *(S->psqrtM) = gsqrt(ginv(M), prec);
2639 11879 : if (S->thetad != S->theta)
2640 : {
2641 0 : *(S->pMd) = *(S->pM);
2642 0 : *(S->psqrtMd) = *(S->psqrtM);
2643 : }
2644 11879 : }
2645 :
2646 : /* M should eventually converge to N, the conductor. L has no pole. */
2647 : static GEN
2648 6895 : wrap1(void *E, GEN M)
2649 : {
2650 6895 : struct huntcond_t *S = (struct huntcond_t*)E;
2651 : GEN thetainit, tk, p1, p1inv;
2652 6895 : GEN t = mkfrac(stoi(11), stoi(10));
2653 : long prec, bitprec;
2654 :
2655 6895 : thetainit = linit_get_tech(S->theta);
2656 6895 : bitprec = theta_get_bitprec(thetainit);
2657 6895 : prec = nbits2prec(bitprec);
2658 6895 : condset(S, M, prec);
2659 6895 : tk = gpow(t, S->k, prec);
2660 6895 : p1 = lfuntheta(S->thetad, t, 0, bitprec);
2661 6895 : p1inv = lfuntheta(S->theta, ginv(t), 0, bitprec);
2662 6895 : return glog(gabs(gmul(tk, gdiv(p1, p1inv)), prec), prec);
2663 : }
2664 :
2665 : /* M should eventually converge to N, the conductor. L has a pole. */
2666 : static GEN
2667 4942 : wrap2(void *E, GEN M)
2668 : {
2669 4942 : struct huntcond_t *S = (struct huntcond_t*)E;
2670 : GEN t1k, t2k, p1, p1inv, p2, p2inv, thetainit, R;
2671 4942 : GEN t1 = mkfrac(stoi(11), stoi(10)), t2 = mkfrac(stoi(13), stoi(11));
2672 : GEN t1be, t2be, t1bemk, t2bemk, t1kmbe, t2kmbe;
2673 : GEN F11, F12, F21, F22, P1, P2, res;
2674 : long prec, bitprec;
2675 4942 : GEN k = S->k;
2676 :
2677 4942 : thetainit = linit_get_tech(S->theta);
2678 4942 : bitprec = theta_get_bitprec(thetainit);
2679 4942 : prec = nbits2prec(bitprec);
2680 4942 : condset(S, M, prec);
2681 :
2682 4942 : p1 = lfuntheta(S->thetad, t1, 0, bitprec);
2683 4942 : p2 = lfuntheta(S->thetad, t2, 0, bitprec);
2684 4942 : p1inv = lfuntheta(S->theta, ginv(t1), 0, bitprec);
2685 4942 : p2inv = lfuntheta(S->theta, ginv(t2), 0, bitprec);
2686 4942 : t1k = gpow(t1, k, prec);
2687 4942 : t2k = gpow(t2, k, prec);
2688 4942 : R = theta_get_R(thetainit);
2689 4942 : if (typ(R) == t_VEC)
2690 : {
2691 0 : GEN be = gmael(R, 1, 1);
2692 0 : t1be = gpow(t1, be, prec); t1bemk = gdiv(gsqr(t1be), t1k);
2693 0 : t2be = gpow(t2, be, prec); t2bemk = gdiv(gsqr(t2be), t2k);
2694 0 : t1kmbe = gdiv(t1k, t1be);
2695 0 : t2kmbe = gdiv(t2k, t2be);
2696 : }
2697 : else
2698 : { /* be = k */
2699 4942 : t1be = t1k; t1bemk = t1k; t1kmbe = gen_1;
2700 4942 : t2be = t2k; t2bemk = t2k; t2kmbe = gen_1;
2701 : }
2702 4942 : F11 = conj_i(gsub(gmul(gsqr(t1be), p1), p1inv));
2703 4942 : F12 = conj_i(gsub(gmul(gsqr(t2be), p2), p2inv));
2704 4942 : F21 = gsub(gmul(t1k, p1), gmul(t1bemk, p1inv));
2705 4942 : F22 = gsub(gmul(t2k, p2), gmul(t2bemk, p2inv));
2706 4942 : P1 = gsub(gmul(t1bemk, t1be), t1kmbe);
2707 4942 : P2 = gsub(gmul(t2bemk, t2be), t2kmbe);
2708 4942 : res = gdiv(gsub(gmul(P2,F21), gmul(P1,F22)),
2709 : gsub(gmul(P2,F11), gmul(P1,F12)));
2710 4942 : return glog(gabs(res, prec), prec);
2711 : }
2712 :
2713 : /* If flag = 0 (default) return all conductors found as integers. If
2714 : flag = 1, return the approximations, not the integers. If flag = 2,
2715 : return all, even nonintegers. */
2716 :
2717 : static GEN
2718 84 : checkconductor(GEN v, long bit, long flag)
2719 : {
2720 : GEN w;
2721 84 : long e, j, k, l = lg(v);
2722 84 : if (flag == 2) return v;
2723 84 : w = cgetg(l, t_VEC);
2724 322 : for (j = k = 1; j < l; j++)
2725 : {
2726 238 : GEN N = grndtoi(gel(v,j), &e);
2727 238 : if (e < -bit) gel(w,k++) = flag ? gel(v,j): N;
2728 : }
2729 84 : if (k == 2) return gel(w,1);
2730 7 : setlg(w,k); return w;
2731 : }
2732 :
2733 : static GEN
2734 98 : parse_maxcond(GEN maxN)
2735 : {
2736 : GEN M;
2737 98 : if (!maxN)
2738 49 : M = utoipos(10000);
2739 49 : else if (typ(maxN) == t_VEC)
2740 : {
2741 14 : if (!RgV_is_ZV(maxN)) pari_err_TYPE("lfunconductor",maxN);
2742 14 : return ZV_sort_shallow(maxN);
2743 : }
2744 : else
2745 35 : M = maxN;
2746 84 : return (typ(M) == t_INT)? addiu(M, 1): gceil(M);
2747 : }
2748 :
2749 : GEN
2750 98 : lfunconductor(GEN data, GEN maxcond, long flag, long bitprec)
2751 : {
2752 : struct huntcond_t S;
2753 98 : pari_sp av = avma;
2754 98 : GEN ldata = lfunmisc_to_ldata_shallow(data);
2755 98 : GEN ld, r, v, theta, thetad, M, tdom, t0 = NULL, t0i = NULL;
2756 : GEN (*eval)(void *, GEN);
2757 : long prec;
2758 98 : M = parse_maxcond(maxcond);
2759 98 : r = ldata_get_residue(ldata);
2760 98 : if (typ(M) == t_VEC) /* select in list */
2761 : {
2762 14 : if (lg(M) == 1) retgc_const(av, cgetg(1, t_VEC));
2763 7 : eval = NULL; tdom = dbltor(0.7);
2764 : }
2765 84 : else if (!r) { eval = wrap1; tdom = uutoQ(10,11); }
2766 : else
2767 : {
2768 21 : if (typ(r) == t_VEC && lg(r) > 2)
2769 0 : pari_err_IMPL("multiple poles in lfunconductor");
2770 21 : eval = wrap2; tdom = uutoQ(11,13);
2771 : }
2772 91 : if (eval) bitprec += bitprec/2;
2773 91 : prec = nbits2prec(bitprec);
2774 91 : ld = shallowcopy(ldata);
2775 91 : gel(ld, 5) = eval? M: veclast(M);
2776 91 : theta = lfunthetainit_i(ld, tdom, 0, bitprec);
2777 91 : thetad = theta_dual(theta, ldata_get_dual(ldata));
2778 91 : gel(theta,3) = shallowcopy(linit_get_tech(theta));
2779 91 : S.k = ldata_get_k(ldata);
2780 91 : S.theta = theta;
2781 91 : S.thetad = thetad? thetad: theta;
2782 91 : S.pM = &gel(linit_get_ldata(theta),5);
2783 91 : S.psqrtM = &gel(linit_get_tech(theta),7);
2784 91 : if (thetad)
2785 : {
2786 0 : S.pMd = &gel(linit_get_ldata(thetad),5);
2787 0 : S.psqrtMd = &gel(linit_get_tech(thetad),7);
2788 : }
2789 91 : if (!eval)
2790 : {
2791 7 : long i, besti = 0, beste = -10, l = lg(M);
2792 7 : t0 = uutoQ(11,10); t0i = uutoQ(10,11);
2793 49 : for (i = 1; i < l; i++)
2794 : {
2795 42 : pari_sp av2 = avma;
2796 : long e;
2797 42 : condset(&S, gel(M,i), prec);
2798 42 : e = lfuncheckfeq_i(theta, thetad, t0, t0i, bitprec);
2799 42 : set_avma(av2);
2800 42 : if (e < beste) { beste = e; besti = i; }
2801 35 : else if (e == beste) beste = besti = 0; /* tie: forget */
2802 : }
2803 7 : if (!besti) retgc_const(av, cgetg(1, t_VEC));
2804 7 : return gc_GEN(av, mkvec2(gel(M,besti), stoi(beste)));
2805 : }
2806 84 : v = solvestep((void*)&S, eval, ghalf, M, gen_2, 14, prec);
2807 84 : return gc_GEN(av, checkconductor(v, bitprec/2, flag));
2808 : }
2809 :
2810 : /* assume chi primitive */
2811 : static GEN
2812 2863 : znchargauss_i(GEN G, GEN chi, long bitprec)
2813 : {
2814 2863 : GEN z, q, F = znstar_get_N(G);
2815 : long prec;
2816 :
2817 2863 : if (equali1(F)) return gen_1;
2818 2863 : prec = nbits2prec(bitprec);
2819 2863 : q = sqrtr_abs(itor(F, prec));
2820 2863 : z = lfuntheta(mkvec2(G,chi), gen_1, 0, bitprec);
2821 2863 : if (gexpo(z) < 10 - bitprec)
2822 : {
2823 28 : if (equaliu(F,300))
2824 : {
2825 14 : GEN z = rootsof1u_cx(25, prec);
2826 14 : GEN n = znconreyexp(G, chi);
2827 14 : if (equaliu(n, 131)) return gmul(q, gpowgs(z,14));
2828 7 : if (equaliu(n, 71)) return gmul(q, gpowgs(z,11));
2829 : }
2830 14 : if (equaliu(F,600))
2831 : {
2832 14 : GEN z = rootsof1u_cx(25, prec);
2833 14 : GEN n = znconreyexp(G, chi);
2834 14 : if (equaliu(n, 491)) return gmul(q, gpowgs(z,7));
2835 7 : if (equaliu(n, 11)) return gmul(q, gpowgs(z,18));
2836 : }
2837 0 : pari_err_BUG("znchargauss [ Theta(chi,1) = 0 ]");
2838 : }
2839 2835 : z = gmul(gdiv(z, conj_i(z)), q);
2840 2835 : if (zncharisodd(G,chi)) z = mulcxI(z);
2841 2835 : return z;
2842 : }
2843 : static GEN
2844 2863 : Z_radical(GEN N, long *om)
2845 : {
2846 2863 : GEN P = gel(Z_factor(N), 1);
2847 2863 : *om = lg(P)-1; return ZV_prod(P);
2848 : }
2849 : GEN
2850 5516 : znchargauss(GEN G, GEN chi, GEN a, long bitprec)
2851 : {
2852 : GEN v, T, N, F, b0, b1, b2, bF, a1, aF, A, r, GF, tau, B, faB, u, S;
2853 5516 : long omb0, prec = nbits2prec(bitprec);
2854 5516 : pari_sp av = avma;
2855 :
2856 5516 : if (typ(chi) != t_COL) chi = znconreylog(G,chi);
2857 5516 : T = znchartoprimitive(G, chi);
2858 5516 : GF = gel(T,1);
2859 5516 : chi = gel(T,2); /* now primitive */
2860 5516 : N = znstar_get_N(G);
2861 5516 : F = znstar_get_N(GF);
2862 5516 : if (equalii(N,F)) b1 = bF = gen_1;
2863 : else
2864 : {
2865 245 : v = Z_ppio(diviiexact(N,F), F);
2866 245 : bF = gel(v,2); /* (N/F, F^oo) */
2867 245 : b1 = gel(v,3); /* cofactor */
2868 : }
2869 5516 : if (!a) a = a1 = aF = gen_1;
2870 : else
2871 : {
2872 5467 : if (typ(a) != t_INT) pari_err_TYPE("znchargauss",a);
2873 5467 : a = modii(a, N);
2874 5467 : if (!signe(a)) { set_avma(av); return is_pm1(F)? eulerphi(N): gen_0; }
2875 3031 : v = Z_ppio(a, F);
2876 3031 : aF = gel(v,2);
2877 3031 : a1 = gel(v,3);
2878 : }
2879 3080 : if (!equalii(aF, bF)) { set_avma(av); return gen_0; }
2880 2863 : b0 = Z_radical(b1, &omb0);
2881 2863 : b2 = diviiexact(b1, b0);
2882 2863 : A = dvmdii(a1, b2, &r);
2883 2863 : if (r != gen_0) { set_avma(av); return gen_0; }
2884 2863 : B = gcdii(A,b0); faB = Z_factor(B); /* squarefree */
2885 2863 : S = eulerphi(mkvec2(B,faB));
2886 2863 : if (odd(omb0 + lg(gel(faB,1))-1)) S = negi(S); /* moebius(b0/B) * phi(B) */
2887 2863 : S = mulii(S, mulii(aF,b2));
2888 2863 : tau = znchargauss_i(GF, chi, bitprec);
2889 2863 : u = Fp_div(b0, A, F);
2890 2863 : if (!equali1(u))
2891 : {
2892 7 : GEN ord = zncharorder(GF, chi), z = rootsof1_cx(ord, prec);
2893 7 : tau = gmul(tau, znchareval(GF, chi, u, mkvec2(z,ord)));
2894 : }
2895 2863 : return gc_upto(av, gmul(tau, S));
2896 : }
|