Code coverage tests

This page documents the degree to which the PARI/GP source code is tested by our public test suite, distributed with the source distribution in directory src/test/. This is measured by the gcov utility; we then process gcov output using the lcov frond-end.

We test a few variants depending on Configure flags on the pari.math.u-bordeaux.fr machine (x86_64 architecture), and agregate them in the final report:

The target is to exceed 90% coverage for all mathematical modules (given that branches depending on DEBUGLEVEL or DEBUGMEM are not covered). This script is run to produce the results below.

LCOV - code coverage report
Current view: top level - basemath - bern.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31042-0fbe168e69) Lines: 95.3 % 381 363
Test Date: 2026-07-23 17:04:59 Functions: 97.4 % 38 37
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copyright (C) 2018  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              : #include "pari.h"
      16              : #include "paripriv.h"
      17              : 
      18              : #define DEBUGLEVEL DEBUGLEVEL_bern
      19              : 
      20              : /********************************************************************/
      21              : /**                                                                **/
      22              : /**                     BERNOULLI NUMBERS B_2k                     **/
      23              : /**                                                                **/
      24              : /********************************************************************/
      25              : 
      26              : /* D = divisorsu(n). Return a/b = \sum_{p-1 | 2n: p prime} 1/p
      27              :  * B_2k + a/b in Z [Clausen-von Staudt] */
      28              : static GEN
      29        82434 : fracB2k(GEN D)
      30              : {
      31        82434 :   GEN a = utoipos(5), b = utoipos(6); /* 1/2 + 1/3 */
      32        82434 :   long i, l = lg(D);
      33       625634 :   for (i = 2; i < l; i++) /* skip 1 */
      34              :   {
      35       543200 :     ulong p = 2*D[i] + 1; /* a/b += 1/p */
      36       543200 :     if (uisprime(p)) { a = addii(muliu(a,p), b); b = muliu(b,p); }
      37              :   }
      38        82434 :   return mkfrac(a,b);
      39              : }
      40              : /* precision needed to compute B_k for all k <= N */
      41              : long
      42         1891 : bernbitprec(long N)
      43              : { /* 1.612086 ~ log(8Pi) / 2 */
      44         1891 :   const double log2PI = 1.83787706641;
      45         1891 :   double logN = log((double)N);
      46         1891 :   double t = (N + 4) * logN - N*(1 + log2PI) + 1.612086;
      47         1891 :   return (long)ceil(t / M_LN2) + 10;
      48              : }
      49              : static long
      50           21 : bernprec(long N) { return nbits2prec(bernbitprec(N)); }
      51              : /* \sum_{k > M} k^(-n) <= M^(1-n) / (n-1) < 2^-b */
      52              : static long
      53         1394 : zetamaxpow(long n)
      54              : {
      55         1394 :   long M = (long)ceil(n / (2 * M_PI * M_E));
      56         1394 :   return M | 1; /* make it odd */
      57              : }
      58              : /* v * zeta(k) using r precomputed odd powers */
      59              : static GEN
      60        82420 : bern_zeta(GEN v, long k, GEN pow, long r, long p)
      61              : {
      62        82420 :   GEN z, s = gel(pow, r);
      63              :   long j;
      64     10379885 :   for (j = r - 2; j >= 3; j -= 2) s = addii(s, gel(pow,j));
      65        82420 :   z = s = itor(s, nbits2prec(p));
      66        82420 :   shiftr_inplace(s, -p); /* zeta(k)(1 - 2^(-k)) - 1*/
      67        82420 :   s = addrs(s, 1); shiftr_inplace(s, -k);
      68              :   /* divide by 1 - 2^(-k): s + s/2^k + s/2^(2k) + ... */
      69       364825 :   for (; k < p; k <<= 1) s = addrr(s, shiftr(s, -k));
      70        82420 :   return addrr(v, mulrr(v, addrr(z, s)));
      71              : }
      72              : /* z * j^2 */
      73              : static GEN
      74     50934818 : muliu2(GEN z, ulong j)
      75     50934818 : { return (j | HIGHMASK)? mulii(z, sqru(j)): muliu(z, j*j); }
      76              : /* 1 <= m <= n, set y[1] = B_{2m}, ... y[n-m+1] = B_{2n} in Q */
      77              : static void
      78          302 : bernset(GEN *y, long m, long n)
      79              : {
      80          302 :   long i, j, k, p, prec, r, N = n << 1; /* up to B_N */
      81              :   GEN u, b, v, t;
      82          302 :   p = bernbitprec(N); prec = nbits2prec(p);
      83          302 :   u = sqrr(Pi2n(1, prec)); /* (2Pi)^2 */
      84          302 :   v = divrr(mpfactr(N, prec), powru(u, n)); shiftr_inplace(v,1);
      85          302 :   r = zetamaxpow(N);
      86          302 :   t = cgetg(r+1, t_VEC); b = int2n(p); /* fixed point */
      87         5719 :   for (j = 3; j <= r; j += 2)
      88              :   {
      89         5417 :     GEN z = cgeti(nbits2lg(p));
      90         5417 :     pari_sp av2 = avma;
      91         5417 :     affii(divii(b, powuu(j, N)), z);
      92         5417 :     gel(t,j) = z; set_avma(av2);
      93              :   }
      94          302 :   y += n - m;
      95          302 :   for (i = n, k = N;; i--)
      96        82118 :   { /* set B_n, k = 2i */
      97        82420 :     pari_sp av2 = avma;
      98        82420 :     GEN z = fracB2k(divisorsu(i)), B = bern_zeta(v, k, t, r, p);
      99              :     long j;
     100              :     /* B = v * zeta(k), v = 2*k! / (2Pi)^k */
     101        82420 :     if (!odd(i)) setsigne(B, -1); /* B ~ B_n */
     102        82420 :     B = roundr(addrr(B, fractor(z,LOWDEFAULTPREC))); /* B - z = B_n */
     103        82420 :     *y-- = gclone(gsub(B, z));
     104        82420 :     if (i == m) break;
     105        82118 :     affrr(divrunextu(mulrr(v,u), k-1), v);
     106     10460504 :     for (j = r; j >= 3; j -= 2) affii(muliu2(gel(t,j), j), gel(t,j));
     107        82118 :     set_avma(av2); k -= 2;
     108        82118 :     if (((N - k) & 0x7f) == 0x7e)
     109              :     { /* reduce precision if possible */
     110         1092 :       long p2 = p, prec2 = prec;
     111         1092 :       p = bernbitprec(k); prec = nbits2prec(p); if (prec2 == prec) continue;
     112         1092 :       setprec(v, prec); r = zetamaxpow(k);
     113       158624 :       for (j = 3; j <= r; j += 2) affii(shifti(gel(t,j), p - p2), gel(t,j));
     114         1092 :       set_avma(av2);
     115              :     }
     116              :   }
     117          302 : }
     118              : /* need B[2..2*nb] as t_INT or t_FRAC */
     119              : void
     120      7240848 : constbern(long nb)
     121              : {
     122      7240848 :   const pari_sp av = avma;
     123              :   long i, l;
     124              :   GEN B;
     125              :   pari_timer T;
     126              : 
     127      7240848 :   l = bernzone? lg(bernzone): 0;
     128      7240848 :   if (l > nb) return;
     129              : 
     130          302 :   nb = maxss(nb, l + 127);
     131          302 :   B = cgetg_block(nb+1, t_VEC);
     132          302 :   if (bernzone)
     133         8832 :   { for (i = 1; i < l; i++) gel(B,i) = gel(bernzone,i); }
     134              :   else
     135              :   {
     136          247 :     gel(B,1) = gclone(mkfracss(1,6));
     137          247 :     gel(B,2) = gclone(mkfracss(-1,30));
     138          247 :     gel(B,3) = gclone(mkfracss(1,42));
     139          247 :     gel(B,4) = gclone(mkfracss(-1,30));
     140          247 :     gel(B,5) = gclone(mkfracss(5,66));
     141          247 :     gel(B,6) = gclone(mkfracss(-691,2730));
     142          247 :     gel(B,7) = gclone(mkfracss(7,6));
     143          247 :     gel(B,8) = gclone(mkfracss(-3617,510));
     144          247 :     gel(B,9) = gclone(mkfracss(43867,798));
     145          247 :     gel(B,10)= gclone(mkfracss(-174611,330));
     146          247 :     gel(B,11)= gclone(mkfracss(854513,138));
     147          247 :     gel(B,12)= gclone(mkfracss(-236364091,2730));
     148          247 :     gel(B,13)= gclone(mkfracss(8553103,6)); /* B_26 */
     149          247 :     l = 14;
     150              :   }
     151          302 :   set_avma(av);
     152          302 :   if (DEBUGLEVEL) {
     153            0 :     err_printf("caching Bernoulli numbers 2*%ld to 2*%ld\n", l, nb);
     154            0 :     timer_start(&T);
     155              :   }
     156          302 :   bernset((GEN*)B + l, l, nb);
     157          302 :   if (DEBUGLEVEL) timer_printf(&T, "Bernoulli");
     158          302 :   swap(B, bernzone); guncloneNULL(B);
     159          302 :   set_avma(av);
     160              : #if 0
     161              :   if (nb > 200000)
     162              : #endif
     163              :   {
     164          302 :     const ulong p = 4294967291UL;
     165          302 :     long n = 2 * nb + 2;
     166          302 :     GEN t = const_vecsmall(n+1, 1);
     167          302 :     t[1] = evalvarn(0); t[2] = 0;
     168          302 :     t = Flx_shift(Flx_invLaplace(t, p), -1); /* t = (exp(x)-1)/x */
     169          302 :     t = Flx_Laplace(Flxn_inv(t, n, p), p);
     170        94710 :     for (i = 1; i <= nb; i++)
     171        94408 :       if (Rg_to_Fl(bernfrac(2*i), p) != uel(t,2*i+2))
     172              :       {
     173            0 :         gunclone(bernzone); bernzone = NULL;
     174            0 :         pari_err_BUG(stack_sprintf("B_{2*%ld}", i));
     175              :       }
     176          302 :     set_avma(av);
     177              :   }
     178              : }
     179              : /* Obsolete, kept for backward compatibility */
     180              : void
     181            0 : mpbern(long n, long prec) { (void)prec; constbern(n); }
     182              : 
     183              : /* assume n even > 0, if iz != NULL, assume iz = 1/zeta(n) */
     184              : static GEN
     185           21 : bernreal_using_zeta(long n, long prec)
     186              : {
     187           21 :   GEN pi2 = Pi2n(1, prec+EXTRAPREC64);
     188           21 :   GEN iz = inv_szeta_euler(n, prec);
     189           21 :   GEN z = divrr(mpfactr(n, prec), mulrr(powru(pi2, n), iz));
     190           21 :   shiftr_inplace(z, 1); /* 2 * n! * zeta(n) / (2Pi)^n */
     191           21 :   if ((n & 3) == 0) setsigne(z, -1);
     192           21 :   return z;
     193              : }
     194              : /* assume n even > 0, B = NULL or good approximation to B_n */
     195              : static GEN
     196           14 : bernfrac_i(long n, GEN B)
     197              : {
     198           14 :   GEN z = fracB2k(divisorsu(n >> 1));
     199           14 :   if (!B) B = bernreal_using_zeta(n, bernprec(n));
     200           14 :   B = roundr( gadd(B, fractor(z,LOWDEFAULTPREC)) );
     201           14 :   return gsub(B, z);
     202              : }
     203              : GEN
     204     51746803 : bernfrac(long n)
     205              : {
     206              :   pari_sp av;
     207              :   long k;
     208     51746803 :   if (n <= 1)
     209              :   {
     210     14010318 :     if (n < 0) pari_err_DOMAIN("bernfrac", "index", "<", gen_0, stoi(n));
     211     14010311 :     return n? mkfrac(gen_m1,gen_2): gen_1;
     212              :   }
     213     37736485 :   if (odd(n)) return gen_0;
     214     23731781 :   k = n >> 1;
     215     23731781 :   if (!bernzone) constbern(0);
     216     23731781 :   if (bernzone && k < lg(bernzone)) return gel(bernzone, k);
     217           14 :   av = avma;
     218           14 :   return gc_upto(av, bernfrac_i(n, NULL));
     219              : }
     220              : GEN
     221          329 : bernvec(long n)
     222              : {
     223              :   long i, l;
     224              :   GEN y;
     225          329 :   if (n < 0) return cgetg(1, t_VEC);
     226          329 :   constbern(n);
     227          329 :   l = n+2; y = cgetg(l, t_VEC); gel(y,1) = gen_1;
     228        56679 :   for (i = 2; i < l; i++) gel(y,i) = gel(bernzone,i-1);
     229          329 :   return y;
     230              : }
     231              : 
     232              : /* x := pol_x(v); B_k(x) = \sum_{i=0}^k binomial(k, i) B_i x^{k-i} */
     233              : static GEN
     234      7002660 : bernpol_i(long k, long v)
     235              : {
     236              :   GEN B, C;
     237              :   long i;
     238      7002660 :   if (v < 0) v = 0;
     239      7002660 :   constbern(k >> 1); /* cache B_2, ..., B_2[k/2] */
     240      7002660 :   C = vecbinomial(k);
     241      7002660 :   B = cgetg(k + 3, t_POL);
     242     49018592 :   for (i = 0; i <= k; ++i) gel(B, k-i+2) = gmul(gel(C,i+1), bernfrac(i));
     243      7002660 :   B[1] = evalsigne(1) | evalvarn(v);
     244      7002660 :   return B;
     245              : }
     246              : GEN
     247         2548 : bernpol(long k, long v)
     248              : {
     249         2548 :   pari_sp av = avma;
     250         2548 :   if (k < 0) pari_err_DOMAIN("bernpol", "index", "<", gen_0, stoi(k));
     251         2541 :   return gc_upto(av, bernpol_i(k, v));
     252              : }
     253              : GEN
     254      7000098 : bernpol_eval(long k, GEN x)
     255              : {
     256      7000098 :   pari_sp av = avma;
     257              :   GEN B;
     258      7000098 :   if (!x) return bernpol(k, 0);
     259      7000049 :   if (gequalX(x)) return bernpol(k, varn(x));
     260      7000049 :   if (k < 0) pari_err_DOMAIN("bernpol", "index", "<", gen_0, stoi(k));
     261      7000042 :   B = poleval(bernpol_i(k, fetch_var_higher()), x);
     262      7000042 :   delete_var();
     263      7000042 :   return gc_upto(av, B);
     264              : }
     265              : 
     266              : /* x := pol_x(v); return 1^e + ... + x^e = x^e + (B_{e+1}(x) - B_{e+1})/(e+1) */
     267              : static GEN
     268           49 : faulhaber(long e, long v)
     269              : {
     270              :   GEN B;
     271           49 :   if (e == 0) return pol_x(v);
     272           35 :   B = RgX_integ(bernpol_i(e, v)); /* (B_{e+1}(x) - B_{e+1}) / (e+1) */
     273           35 :   gel(B,e+2) = gaddgs(gel(B,e+2), 1); /* add x^e, in place */
     274           35 :   return B;
     275              : }
     276              : /* sum_v T(v), T a polynomial expression in v */
     277              : GEN
     278           49 : sumformal(GEN T, long v)
     279              : {
     280           49 :   pari_sp av = avma, av2;
     281              :   long i, t, d;
     282              :   GEN R;
     283              : 
     284           49 :   T = simplify_shallow(T);
     285           49 :   t = typ(T);
     286           49 :   if (is_scalar_t(t))
     287           14 :     return gc_upto(av, monomialcopy(T, 1, v < 0? 0: v));
     288           35 :   if (t != t_POL) pari_err_TYPE("sumformal [not a t_POL]", T);
     289           28 :   if (v < 0) v = varn(T);
     290           28 :   av2 = avma;
     291           28 :   R = gen_0;
     292           28 :   d = poldegree(T,v);
     293           91 :   for (i = d; i >= 0; i--)
     294              :   {
     295           63 :     GEN c = polcoef_i(T, i, v);
     296           63 :     if (gequal0(c)) continue;
     297           42 :     R = gadd(R, gmul(c, faulhaber(i, v)));
     298           42 :     if (gc_needed(av2,3))
     299              :     {
     300            0 :       if(DEBUGMEM>1) pari_warn(warnmem,"sumformal, i = %ld/%ld", i,d);
     301            0 :       R = gc_upto(av2, R);
     302              :     }
     303              :   }
     304           28 :   return gc_upto(av, R);
     305              : }
     306              : 
     307              : /* 1/zeta(n) using Euler product. Assume n > 0. */
     308              : GEN
     309         1194 : inv_szeta_euler(long n, long prec)
     310              : {
     311         1194 :   long bit = prec2nbits(prec);
     312              :   GEN z, res;
     313              :   pari_sp av, av2;
     314              :   double A, D, lba;
     315              :   ulong p, lim;
     316              :   forprime_t S;
     317              : 
     318         1194 :   if (n > bit) return real_1(prec);
     319              : 
     320         1187 :   lba = prec2nbits_mul(prec, M_LN2);
     321         1187 :   D = exp((lba - log((double)(n-1))) / (n-1));
     322         1187 :   lim = 1 + (ulong)ceil(D);
     323         1187 :   if (lim < 3) return subir(gen_1,real2n(-n,prec));
     324         1187 :   res = cgetr(prec); av = avma; incrprec(prec);
     325              : 
     326         1187 :   (void)u_forprime_init(&S, 3, lim);
     327         1187 :   av2 = avma; A = n / M_LN2; z = subir(gen_1, real2n(-n, prec));
     328        86205 :   while ((p = u_forprime_next(&S)))
     329              :   {
     330        85018 :     long l = bit - (long)floor(A * log((double)p));
     331              :     GEN h;
     332              : 
     333        85018 :     if (l < BITS_IN_LONG) l = BITS_IN_LONG;
     334        85018 :     l = minss(prec, nbits2prec(l));
     335        85018 :     h = divrr(z, rpowuu(p, (ulong)n, l));
     336        85018 :     z = subrr(z, h);
     337        85018 :     if (gc_needed(av,1))
     338              :     {
     339            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"inv_szeta_euler, p = %lu/%lu", p,lim);
     340            0 :       z = gc_leaf(av2, z);
     341              :     }
     342              :   }
     343         1187 :   affrr(z, res); set_avma(av); return res;
     344              : }
     345              : 
     346              : /* Return B_n */
     347              : GEN
     348        15309 : bernreal(long n, long prec)
     349              : {
     350              :   pari_sp av;
     351              :   GEN B;
     352              :   long p, k;
     353        15309 :   if (n < 0) pari_err_DOMAIN("bernreal", "index", "<", gen_0, stoi(n));
     354        15302 :   if (n == 0) return real_1(prec);
     355        15302 :   if (n == 1) return real_m2n(-1,prec); /*-1/2*/
     356        15302 :   if (odd(n)) return real_0(prec);
     357              : 
     358        15302 :   k = n >> 1;
     359        15302 :   if (!bernzone) constbern(0);
     360        15302 :   if (k < lg(bernzone)) return fractor(gel(bernzone,k), prec);
     361            7 :   p = bernprec(n); av = avma;
     362            7 :   B = bernreal_using_zeta(n, minss(p, prec));
     363            7 :   if (p < prec) B = fractor(bernfrac_i(n, B), prec);
     364            7 :   return gc_leaf(av, B);
     365              : }
     366              : 
     367              : GEN
     368           49 : eulerpol(long k, long v)
     369              : {
     370           49 :   pari_sp av = avma;
     371              :   GEN B, E;
     372           49 :   if (k < 0) pari_err_DOMAIN("eulerpol", "index", "<", gen_0, stoi(k));
     373           42 :   k++; B = bernpol_i(k, v);
     374           42 :   E = RgX_Rg_mul(RgX_sub(B, RgX_rescale(B, gen_2)), uutoQ(2,k));
     375           42 :   return gc_upto(av, E);
     376              : }
     377              : 
     378              : /* Compute substpol(x*cotanh(x+O(x^p)),x^2,x) */
     379              : static GEN
     380         1169 : cotanh_Flxn(ulong p)
     381              : {
     382              :   long i, j;
     383         1169 :   ulong t = p-1, m = (p+1)>>1;
     384         1169 :   GEN C = cgetg(m+1, t_VECSMALL);
     385         1169 :   GEN S = cgetg(m+1, t_VECSMALL);
     386         1169 :   C[1] = S[1] = 0;
     387         1169 :   C[2] = S[2] = 1;
     388       324793 :   for (i = p-1, j = m; j > 2; j--)
     389              :   {
     390       323624 :     t = Fl_mul(t, i--, p);
     391       323624 :     uel(S,j) = t;
     392       323624 :     t = Fl_mul(t, i--, p);
     393       323624 :     uel(C,j) = t;
     394              :   }
     395         1169 :   return Flxn_div(C, S, m-1, p);
     396              : }
     397              : 
     398              : long
     399         1183 : primeisregular(ulong p)
     400              : {
     401         1183 :   pari_sp av = avma;
     402              :   GEN T;
     403         1183 :   long i, m = (p+1)>>1;
     404         1183 :   if (p == 2 || p==3) return 1;
     405         1169 :   if (!uisprime(p)) pari_err_PRIME("primeisregular",utoi(p));
     406         1169 :   T = cotanh_Flxn(p);
     407         1169 :   if (lg(T)-1 < m) return 0;
     408       200592 :   for (i = 2; i <= m; i++)
     409       199878 :     if (uel(T,i)==0) return gc_long(av, 0);
     410          714 :   return gc_long(av, 1);
     411              : }
     412              : 
     413              : /*******************************************************************/
     414              : /**                      HARMONIC NUMBERS                         **/
     415              : /*******************************************************************/
     416              : /* 1/a + ... + 1/(b-1); a < b <= 2^(BIL-1) */
     417              : static GEN
     418         4683 : hrec(ulong a, ulong b)
     419              : {
     420              :   ulong m;
     421         4683 :   switch(b - a)
     422              :   {
     423         4501 :     case 1: if (a==1) return gen_1; else retmkfrac(gen_1, utoipos(a));
     424          140 :     case 2: if (a < 65536) retmkfrac(utoipos(2*a + 1), utoipos(a * a + a));
     425            0 :       retmkfrac(utoipos(2*a + 1), muluu(a, a+1));
     426              :   }
     427           42 :   m = (a + b) >> 1;
     428           42 :   return gadd(hrec(a, m), hrec(m, b));
     429              : }
     430              : /* exact Harmonic number H_n, n < 2^(BIL-1).
     431              :  * Could use H_n = sum_k 2^(-k) H^odd_{n \ 2^k} */
     432              : GEN
     433         4599 : harmonic(ulong n)
     434              : {
     435         4599 :   pari_sp av = avma;
     436         4599 :   return n? gc_upto(av, hrec(1, n+1)): gen_0;
     437              : }
     438              : 
     439              : /* 1/a^k + ... + 1/(b-1)^k; a < b */
     440              : static GEN
     441           77 : hreck(ulong a, ulong b, ulong k)
     442              : {
     443              :   ulong m;
     444           77 :   switch(b - a)
     445              :   {
     446              :     GEN x, y;
     447           14 :     case 1: retmkfrac(gen_1, powuu(a, k));
     448           28 :     case 2:
     449           28 :       x = powuu(a, k); y = powuu(a + 1, k);
     450           28 :       retmkfrac(addii(x, y), mulii(x, y));
     451              :   }
     452           35 :   m = (a + b) >> 1;
     453           35 :   return gadd(hreck(a, m, k), hreck(m, b, k));
     454              : }
     455              : GEN
     456           56 : harmonic0(ulong n, GEN k)
     457              : {
     458           56 :   pari_sp av = avma;
     459              :   ulong r;
     460           56 :   if (!n) return gen_0;
     461           49 :   if (n & HIGHBIT) pari_err_OVERFLOW("harmonic");
     462           49 :   if (!k) return harmonic(n);
     463           21 :   if (typ(k) != t_INT) pari_err_TYPE("harmonic", k);
     464           14 :   if (signe(k) < 0)
     465              :   {
     466            7 :     GEN H = poleval(faulhaber(-itos(k), 0), utoipos(n));
     467            7 :     return gc_INT(av, H);
     468              :   }
     469            7 :   r = itou(k);
     470            7 :   if (!r) return utoipos(n);
     471            7 :   if (r == 1) return harmonic(n);
     472            7 :   return gc_upto(av, hreck(1, n+1, r));
     473              : }
     474              : 
     475              : 
     476              : /**************************************************************/
     477              : /*                      Euler numbers                         */
     478              : /**************************************************************/
     479              : 
     480              : /* precision needed to compute E_k for all k <= N */
     481              : static long
     482          798 : eulerbitprec(long N)
     483              : { /* 1.1605 ~ log(32/Pi) / 2 */
     484          798 :   const double logPIS2 = 0.4515827;
     485          798 :   double t = (N + 1) * log((double)N) - N*(1 + logPIS2) + 1.1605;
     486          798 :   return (long)ceil(t / M_LN2) + 10;
     487              : }
     488              : static long
     489           14 : eulerprec(long N) { return nbits2prec(eulerbitprec(N)); }
     490              : 
     491              : /* sum_{k > M, k odd} (-1)^((k-1)/2)k^(-n) < M^(-n) < 2^-b */
     492              : static long
     493          784 : lfun4maxpow(long n)
     494              : {
     495          784 :   long M = (long)ceil(2 * n / (M_E * M_PI));
     496          784 :   return M | 1; /* make it odd */
     497              : }
     498              : 
     499              : /* lfun4(k) using r precomputed odd powers */
     500              : static GEN
     501        49791 : euler_lfun4(GEN v, GEN pow, long r, long p)
     502              : {
     503        49791 :   GEN s = ((r & 3L) == 1)? gel(pow, r): negi(gel(pow, r));
     504              :   long j;
     505     40556894 :   for (j = r - 2; j >= 3; j -= 2)
     506     40507103 :     s = ((j & 3L) == 1)? addii(s, gel(pow,j)): subii(s, gel(pow,j));
     507        49791 :   s = mulri(v, s); shiftr_inplace(s, -p);
     508        49791 :   return addrr(v, s);
     509              : }
     510              : 
     511              : /* 1 <= m <= n, set y[1] = E_{2m}, ... y[n-m+1] = E_{2n} in Z */
     512              : static void
     513           21 : eulerset(GEN *y, long m, long n)
     514              : {
     515           21 :   long i, j, k, p, prec, r, N = n << 1, N1 = N + 1; /* up to E_N */
     516              :   GEN b, u, v, t;
     517           21 :   p = eulerbitprec(N); prec = nbits2prec(p);
     518           21 :   u = sqrr(Pi2n(-1, prec)); /* (Pi/2)^2 */
     519           21 :   v = divrr(mpfactr(N, prec), mulrr(powru(u, n), Pi2n(-2,prec)));
     520           21 :   r = lfun4maxpow(N1);
     521           21 :   t = cgetg(r+1, t_VEC); b = int2n(p); /* fixed point */
     522        11921 :   for (j = 3; j <= r; j += 2)
     523              :   {
     524        11900 :     GEN z = cgeti(nbits2lg(p));
     525        11900 :     pari_sp av2 = avma;
     526        11900 :     affii(divii(b, powuu(j, N+1)), z);
     527        11900 :     gel(t,j) = z; set_avma(av2);
     528              :   }
     529           21 :   y += n - m;
     530           21 :   for (i = n, k = N1;; i--)
     531        49770 :   { /* set E_n, k = 2i + 1 */
     532        49791 :     pari_sp av2 = avma;
     533        49791 :     GEN E = euler_lfun4(v, t, r, p);
     534              :     long j;
     535              :     /* E = v * lfun4(k), v = (4/Pi)*k! / (Pi/2)^k */
     536        49791 :     E = roundr(E); if (odd(i)) setsigne(E, -1); /* E ~ E_n */
     537        49791 :     *y-- = gclone(E);
     538        49791 :     if (i == m) break;
     539        49770 :     affrr(divrunextu(mulrr(v,u), k-2), v);
     540     40606202 :     for (j = r; j >= 3; j -= 2) affii(muliu2(gel(t,j), j), gel(t,j));
     541        49770 :     set_avma(av2); k -= 2;
     542        49770 :     if (((N1 - k) & 0x7f) == 0x7e)
     543              :     { /* reduce precision if possible */
     544          763 :       long p2 = p, prec2 = prec;
     545          763 :       p = eulerbitprec(k); prec = nbits2prec(p); if (prec2 == prec) continue;
     546          763 :       setprec(v, prec); r = lfun4maxpow(k);
     547       622923 :       for (j = 3; j <= r; j += 2) affii(shifti(gel(t,j), p - p2), gel(t,j));
     548          763 :       set_avma(av2);
     549              :     }
     550              :   }
     551           21 : }
     552              : 
     553              : /* need E[2..2*nb] as t_INT */
     554              : static void
     555           28 : constreuler(long nb)
     556              : {
     557           28 :   const pari_sp av = avma;
     558              :   long i, l;
     559              :   GEN E;
     560              :   pari_timer T;
     561              : 
     562           28 :   l = eulerzone? lg(eulerzone): 0;
     563           28 :   if (l > nb) return;
     564              : 
     565           21 :   nb = maxss(nb, l + 127);
     566           21 :   E = cgetg_block(nb+1, t_VEC);
     567           21 :   if (eulerzone)
     568          896 :   { for (i = 1; i < l; i++) gel(E,i) = gel(eulerzone,i); }
     569              :   else
     570              :   {
     571           14 :     gel(E,1) = gclone(stoi(-1));
     572           14 :     gel(E,2) = gclone(stoi(5));
     573           14 :     gel(E,3) = gclone(stoi(-61));
     574           14 :     gel(E,4) = gclone(stoi(1385));
     575           14 :     gel(E,5) = gclone(stoi(-50521));
     576           14 :     gel(E,6) = gclone(stoi(2702765));
     577           14 :     gel(E,7) = gclone(stoi(-199360981));
     578           14 :     l = 8;
     579              :   }
     580           21 :   set_avma(av);
     581           21 :   if (DEBUGLEVEL) {
     582            0 :     err_printf("caching Euler numbers 2*%ld to 2*%ld\n", l, nb);
     583            0 :     timer_start(&T);
     584              :   }
     585           21 :   eulerset((GEN*)E + l, l, nb);
     586           21 :   if (DEBUGLEVEL) timer_printf(&T, "Euler");
     587           21 :   swap(E, eulerzone); guncloneNULL(E);
     588           21 :   set_avma(av);
     589              : }
     590              : 
     591              : /* 1/lfun(-4,n) using Euler product. Assume n > 0. */
     592              : static GEN
     593           14 : inv_lfun4(long n, long prec)
     594              : {
     595           14 :   long bit = prec2nbits(prec);
     596              :   GEN z, res;
     597              :   pari_sp av, av2;
     598              :   double A;
     599              :   ulong p, lim;
     600              :   forprime_t S;
     601              : 
     602           14 :   if (n > bit) return real_1(prec);
     603              : 
     604           14 :   lim = 1 + (ulong)ceil(exp2((double)bit / n));
     605           14 :   res = cgetr(prec); av = avma; incrprec(prec);
     606              : 
     607           14 :   (void)u_forprime_init(&S, 3, lim);
     608           14 :   av2 = avma; A = n / M_LN2; z = real_1(prec);
     609          369 :   while ((p = u_forprime_next(&S)))
     610              :   {
     611          355 :     long l = bit - (long)floor(A * log((double)p));
     612              :     GEN h;
     613              : 
     614          355 :     if (l < BITS_IN_LONG) l = BITS_IN_LONG;
     615          355 :     l = minss(prec, nbits2prec(l));
     616          355 :     h = rpowuu(p, (ulong)n, l); if ((p & 3UL) == 1) setsigne(h, -1);
     617          355 :     z = addrr(z, divrr(z, h)); /* z *= 1 - chi_{-4}(p) / p^n */
     618          355 :     if (gc_needed(av,1))
     619              :     {
     620            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"inv_lfun4, p = %lu/%lu", p,lim);
     621            0 :       z = gc_leaf(av2, z);
     622              :     }
     623              :   }
     624           14 :   affrr(z, res); set_avma(av); return res;
     625              : }
     626              : /* assume n even > 0, E_n = (-1)^(n/2) (4/Pi) n! lfun4(n+1) / (Pi/2)^n */
     627              : static GEN
     628           14 : eulerreal_using_lfun4(long n, long prec)
     629              : {
     630           14 :   GEN pisur2 = Pi2n(-1, prec+EXTRAPREC64);
     631           14 :   GEN iz = inv_lfun4(n+1, prec);
     632           14 :   GEN z = divrr(mpfactr(n, prec), mulrr(powru(pisur2, n+1), iz));
     633           14 :   if ((n & 3L) == 2) setsigne(z, -1);
     634           14 :   shiftr_inplace(z, 1); return z;
     635              : }
     636              : /* Euler numbers: 1, 0, -1, 0, 5, 0, -61,... */
     637              : GEN
     638          217 : eulerfrac(long n)
     639              : {
     640              :   pari_sp av;
     641              :   long k;
     642              :   GEN E;
     643          217 :   if (n <= 0)
     644              :   {
     645           21 :     if (n < 0) pari_err_DOMAIN("eulerfrac", "index", "<", gen_0, stoi(n));
     646           14 :     return gen_1;
     647              :   }
     648          196 :   if (odd(n)) return gen_0;
     649          189 :   k = n >> 1;
     650          189 :   if (!eulerzone) constreuler(0);
     651          189 :   if (eulerzone && k < lg(eulerzone)) return gel(eulerzone, k);
     652           14 :   av = avma; E = eulerreal_using_lfun4(n, eulerprec(n));
     653           14 :   return gc_leaf(av, roundr(E));
     654              : }
     655              : GEN
     656           14 : eulervec(long n)
     657              : {
     658              :   long i, l;
     659              :   GEN y;
     660           14 :   if (n < 0) return cgetg(1, t_VEC);
     661           14 :   constreuler(n);
     662           14 :   l = n+2; y = cgetg(l, t_VEC); gel(y,1) = gen_1;
     663        49224 :   for (i = 2; i < l; i++) gel(y,i) = gel(eulerzone,i-1);
     664           14 :   return y;
     665              : }
     666              : 
     667              : /* Return E_n */
     668              : GEN
     669           21 : eulerreal(long n, long prec)
     670              : {
     671           21 :   pari_sp av = avma;
     672              :   GEN B;
     673              :   long p, k;
     674           21 :   if (n < 0) pari_err_DOMAIN("eulerreal", "index", "<", gen_0, stoi(n));
     675           14 :   if (n == 0) return real_1(prec);
     676           14 :   if (odd(n)) return real_0(prec);
     677              : 
     678           14 :   k = n >> 1;
     679           14 :   if (!eulerzone) constreuler(0);
     680           14 :   if (k < lg(eulerzone)) return itor(gel(eulerzone,k), prec);
     681            0 :   p = eulerprec(n);
     682            0 :   B = eulerreal_using_lfun4(n, minss(p, prec));
     683            0 :   if (p < prec) B = itor(roundr(B), prec);
     684            0 :   return gc_leaf(av, B);
     685              : }
        

Generated by: LCOV version 2.0-1