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 - language - sumiter.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31042-0fbe168e69) Lines: 94.8 % 1303 1235
Test Date: 2026-07-23 17:04:59 Functions: 99.1 % 107 106
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copyright (C) 2000  The PARI group.
       2              : 
       3              : This file is part of the PARI/GP package.
       4              : 
       5              : PARI/GP is free software; you can redistribute it and/or modify it under the
       6              : terms of the GNU General Public License as published by the Free Software
       7              : Foundation; either version 2 of the License, or (at your option) any later
       8              : version. It is distributed in the hope that it will be useful, but WITHOUT
       9              : ANY WARRANTY WHATSOEVER.
      10              : 
      11              : Check the License for details. You should have received a copy of it, along
      12              : with the package; see the file 'COPYING'. If not, write to the Free Software
      13              : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      14              : 
      15              : #include "pari.h"
      16              : #include "paripriv.h"
      17              : 
      18              : GEN
      19      1285442 : iferrpari(GEN a, GEN b, GEN c)
      20              : {
      21              :   GEN res;
      22              :   struct pari_evalstate state;
      23      1285442 :   evalstate_save(&state);
      24      1285442 :   pari_CATCH(CATCH_ALL)
      25              :   {
      26              :     GEN E;
      27        86474 :     if (!b&&!c) return gnil;
      28        43244 :     E = evalstate_restore_err(&state);
      29        43244 :     if (c)
      30              :     {
      31          292 :       push_lex(E,c);
      32          292 :       res = closure_evalnobrk(c);
      33          285 :       pop_lex(1);
      34          285 :       if (gequal0(res))
      35            7 :         pari_err(0, E);
      36              :     }
      37        43230 :     if (!b) return gnil;
      38        43230 :     push_lex(E,b);
      39        43230 :     res = closure_evalgen(b);
      40        43230 :     pop_lex(1);
      41        43230 :     return res;
      42              :   } pari_TRY {
      43      1285442 :     res = closure_evalgen(a);
      44      1242198 :   } pari_ENDCATCH;
      45      1242198 :   return res;
      46              : }
      47              : 
      48              : /********************************************************************/
      49              : /**                                                                **/
      50              : /**                        ITERATIONS                              **/
      51              : /**                                                                **/
      52              : /********************************************************************/
      53              : 
      54              : static void
      55      5115815 : forparii(GEN a, GEN b, GEN code)
      56              : {
      57      5115815 :   pari_sp av, av0 = avma;
      58              :   GEN aa;
      59      5115815 :   if (gcmp(b,a) < 0) return;
      60      5034033 :   if (typ(b) != t_INFINITY) b = gfloor(b);
      61      5034033 :   aa = a = setloop(a);
      62      5034033 :   av=avma;
      63      5034033 :   push_lex(a,code);
      64     71501369 :   while (gcmp(a,b) <= 0)
      65              :   {
      66     66545561 :     closure_evalvoid(code); if (loop_break()) break;
      67     66467337 :     a = get_lex(-1);
      68     66467336 :     if (a == aa)
      69              :     {
      70     66467308 :       a = incloop(a);
      71     66467308 :       if (a != aa) { set_lex(-1,a); aa = a; }
      72              :     }
      73              :     else
      74              :     { /* 'code' modified a ! Be careful (and slow) from now on */
      75           28 :       a = gaddgs(a,1);
      76           28 :       if (gc_needed(av,1))
      77              :       {
      78            0 :         if (DEBUGMEM>1) pari_warn(warnmem,"forparii");
      79            0 :         a = gc_upto(av,a);
      80              :       }
      81           28 :       set_lex(-1,a);
      82              :     }
      83              :   }
      84      5033969 :   pop_lex(1);  set_avma(av0);
      85              : }
      86              : 
      87              : void
      88      5115822 : forpari(GEN a, GEN b, GEN code)
      89              : {
      90      5115822 :   pari_sp ltop=avma, av;
      91      5115822 :   if (typ(a) == t_INT) { forparii(a,b,code); return; }
      92            7 :   b = gcopy(b); /* Kludge to work-around the a+(a=2) bug */
      93            7 :   av=avma;
      94            7 :   push_lex(a,code);
      95           28 :   while (gcmp(a,b) <= 0)
      96              :   {
      97           21 :     closure_evalvoid(code); if (loop_break()) break;
      98           21 :     a = get_lex(-1); a = gaddgs(a,1);
      99           21 :     if (gc_needed(av,1))
     100              :     {
     101            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"forpari");
     102            0 :       a = gc_upto(av,a);
     103              :     }
     104           21 :     set_lex(-1, a);
     105              :   }
     106            7 :   pop_lex(1); set_avma(ltop);
     107              : }
     108              : 
     109              : void
     110         1015 : foreachpari(GEN x, GEN code)
     111              : {
     112              :   long i, l;
     113         1015 :   switch(typ(x))
     114              :   {
     115           14 :     case t_LIST:
     116           14 :       x = list_data(x); /* FALL THROUGH */
     117           14 :       if (!x) return;
     118              :     case t_MAT: case t_VEC: case t_COL:
     119         1001 :       break;
     120            7 :     default:
     121            7 :       pari_err_TYPE("foreach",x);
     122              :       return; /*LCOV_EXCL_LINE*/
     123              :   }
     124         1001 :   clone_lock(x); l = lg(x);
     125         1001 :   push_lex(gen_0,code);
     126         5761 :   for (i = 1; i < l; i++)
     127              :   {
     128         4760 :     set_lex(-1, gel(x,i));
     129         4760 :     closure_evalvoid(code); if (loop_break()) break;
     130              :   }
     131         1001 :   pop_lex(1); clone_unlock_deep(x);
     132              : }
     133              : 
     134              : /* is it better to sieve [a,b] or to factor individually ? */
     135              : static int
     136          189 : no_sieve(ulong a, ulong b)
     137          189 : { return b - a < usqrt(b) / tridiv_boundu(b); }
     138              : 
     139              : /* 0 < a <= b. Using small consecutive chunks to 1) limit memory use, 2) allow
     140              :  * cheap early abort */
     141              : static int
     142           63 : forfactoredpos(ulong a, ulong b, GEN code)
     143              : {
     144           63 :   ulong x1, step = maxuu(2 * usqrt(b), 1024);
     145           63 :   pari_sp av = avma;
     146           63 :   if (no_sieve(a, b))
     147              :   {
     148              :     ulong n;
     149            0 :     for (n = a; n <= b; n++, set_avma(av))
     150              :     {
     151            0 :       GEN m = factoru(n);
     152            0 :       set_lex(-1, mkvec2(utoipos(n), Flm_to_ZM(m)));
     153            0 :       closure_evalvoid(code); if (loop_break()) return 1;
     154              :     }
     155            0 :     return 0;
     156              :   }
     157         3549 :   for(x1 = a;; x1 += step, set_avma(av))
     158         3486 :   { /* beware overflow, fuse last two bins (avoid a tiny remainder) */
     159         3549 :     ulong j, lv, x2 = (b >= 2*step && b - 2*step >= x1)? x1-1 + step: b;
     160         3549 :     GEN v = vecfactoru_i(x1, x2);
     161         3549 :     lv = lg(v);
     162      7005082 :     for (j = 1; j < lv; j++)
     163              :     {
     164      7001547 :       ulong n = x1-1 + j;
     165      7001547 :       set_lex(-1, mkvec2(utoipos(n), Flm_to_ZM(gel(v,j))));
     166      7001547 :       closure_evalvoid(code);
     167      7001547 :       if (loop_break()) return 1;
     168              :     }
     169         3535 :     if (x2 == b) break;
     170         3486 :     set_lex(-1, gen_0);
     171              :   }
     172           49 :   return 0;
     173              : }
     174              : 
     175              : /* vector of primes to squarefree factorization */
     176              : static GEN
     177      4255559 : zv_to_ZM(GEN v)
     178      4255559 : { return mkmat2(zc_to_ZC(v), const_col(lg(v)-1,gen_1)); }
     179              : /* vector of primes to negative squarefree factorization */
     180              : static GEN
     181      4255559 : zv_to_mZM(GEN v)
     182              : {
     183      4255559 :   long i, l = lg(v);
     184      4255559 :   GEN w = cgetg(l+1, t_COL);
     185     15388443 :   gel(w,1) = gen_m1; for (i = 1; i < l; i++) gel(w,i+1) = utoipos(v[i]);
     186      4255559 :   return mkmat2(w, const_col(l,gen_1));
     187              : }
     188              : /* 0 <= a <= b. Using small consecutive chunks to 1) limit memory use, 2) allow
     189              :  * cheap early abort */
     190              : static void
     191           21 : forsquarefreepos(ulong a, ulong b, GEN code)
     192              : {
     193           21 :   const ulong step = maxuu(1024, 2 * usqrt(b));
     194           21 :   pari_sp av = avma;
     195              :   ulong x1;
     196           21 :   if (no_sieve(a, b))
     197              :   {
     198              :     ulong n;
     199            0 :     for (n = a; n <= b; n++, set_avma(av))
     200              :     {
     201            0 :       GEN m = factoru(n);
     202            0 :       if (!uissquarefree_fact(m)) continue;
     203            0 :       set_lex(-1, mkvec2(utoipos(n), Flm_to_ZM(m)));
     204            0 :       closure_evalvoid(code); if (loop_break()) return;
     205              :     }
     206            0 :     return;
     207              :   }
     208         3507 :   for(x1 = a;; x1 += step, set_avma(av))
     209         3486 :   { /* beware overflow, fuse last two bins (avoid a tiny remainder) */
     210         3507 :     ulong j, lv, x2 = (b >= 2*step && b - 2*step >= x1)? x1-1 + step: b;
     211         3507 :     GEN v = vecfactorsquarefreeu(x1, x2);
     212         3507 :     lv = lg(v);
     213      7003619 :     for (j = 1; j < lv; j++) if (gel(v,j))
     214              :     {
     215      4255559 :       ulong n = x1-1 + j;
     216      4255559 :       set_lex(-1, mkvec2(utoipos(n), zv_to_ZM(gel(v,j))));
     217      4255559 :       closure_evalvoid(code); if (loop_break()) return;
     218              :     }
     219         3507 :     if (x2 == b) break;
     220         3486 :     set_lex(-1, gen_0);
     221              :   }
     222              : }
     223              : /* 0 <= a <= b. Loop from -b, ... -a through squarefree integers */
     224              : static void
     225           21 : forsquarefreeneg(ulong a, ulong b, GEN code)
     226              : {
     227           21 :   const ulong step = maxuu(1024, 2 * usqrt(b));
     228           21 :   pari_sp av = avma;
     229              :   ulong x2;
     230           21 :   if (no_sieve(a, b))
     231              :   {
     232              :     ulong n;
     233            0 :     for (n = b; n >= a; n--, set_avma(av))
     234              :     {
     235            0 :       GEN m = factoru(n);
     236            0 :       if (!uissquarefree_fact(m)) continue;
     237            0 :       set_lex(-1, mkvec2(utoineg(n), zv_to_mZM(gel(m,1))));
     238            0 :       closure_evalvoid(code); if (loop_break()) return;
     239              :     }
     240            0 :     return;
     241              :   }
     242         3507 :   for(x2 = b;; x2 -= step, set_avma(av))
     243         3486 :   { /* beware overflow, fuse last two bins (avoid a tiny remainder) */
     244         3507 :     ulong j, x1 = (x2 >= 2*step && x2-2*step >= a)? x2+1 - step: a;
     245         3507 :     GEN v = vecfactorsquarefreeu(x1, x2);
     246      7003619 :     for (j = lg(v)-1; j > 0; j--) if (gel(v,j))
     247              :     {
     248      4255559 :       ulong n = x1-1 + j;
     249      4255559 :       set_lex(-1, mkvec2(utoineg(n), zv_to_mZM(gel(v,j))));
     250      4255559 :       closure_evalvoid(code); if (loop_break()) return;
     251              :     }
     252         3507 :     if (x1 == a) break;
     253         3486 :     set_lex(-1, gen_0);
     254              :   }
     255              : }
     256              : void
     257           35 : forsquarefree(GEN a, GEN b, GEN code)
     258              : {
     259           35 :   pari_sp av = avma;
     260              :   long s;
     261           35 :   if (typ(a) != t_INT) pari_err_TYPE("forsquarefree", a);
     262           35 :   if (typ(b) != t_INT) pari_err_TYPE("forsquarefree", b);
     263           35 :   if (cmpii(a,b) > 0) return;
     264           35 :   s = signe(a); push_lex(NULL,code);
     265           35 :   if (s < 0)
     266              :   {
     267           21 :     if (signe(b) <= 0)
     268           14 :       forsquarefreeneg(itou(b), itou(a), code);
     269              :     else
     270              :     {
     271            7 :       forsquarefreeneg(1, itou(a), code);
     272            7 :       forsquarefreepos(1, itou(b), code);
     273              :     }
     274              :   }
     275              :   else
     276           14 :     forsquarefreepos(itou(a), itou(b), code);
     277           35 :   pop_lex(1); set_avma(av);
     278              : }
     279              : 
     280              : /* convert factoru(n) to factor(-n); M pre-allocated factorization matrix
     281              :  * with (-1)^1 already set */
     282              : static void
     283      7001582 : Flm2negfact(GEN v, GEN M)
     284              : {
     285      7001582 :   GEN p = gel(v,1), e = gel(v,2), P = gel(M,1), E = gel(M,2);
     286      7001582 :   long i, l = lg(p);
     287     26980058 :   for (i = 1; i < l; i++)
     288              :   {
     289     19978476 :     gel(P,i+1) = utoipos(p[i]);
     290     19978476 :     gel(E,i+1) = utoipos(e[i]);
     291              :   }
     292      7001582 :   setlg(P,l+1);
     293      7001582 :   setlg(E,l+1);
     294      7001582 : }
     295              : /* 0 < a <= b, from -b to -a */
     296              : static int
     297           84 : forfactoredneg(ulong a, ulong b, GEN code)
     298              : {
     299           84 :   ulong x2, step = maxuu(2 * usqrt(b), 1024);
     300              :   GEN P, E, M;
     301              :   pari_sp av;
     302              : 
     303           84 :   P = cgetg(18, t_COL); gel(P,1) = gen_m1;
     304           84 :   E = cgetg(18, t_COL); gel(E,1) = gen_1;
     305           84 :   M = mkmat2(P,E);
     306           84 :   av = avma;
     307           84 :   if (no_sieve(a, b))
     308              :   {
     309              :     ulong n;
     310            0 :     for (n = b; n >= a; n--, set_avma(av))
     311              :     {
     312            0 :       GEN m = factoru(n);
     313            0 :       Flm2negfact(m, M);
     314            0 :       set_lex(-1, mkvec2(utoineg(n), M));
     315            0 :       closure_evalvoid(code); if (loop_break()) return 1;
     316              :     }
     317            0 :     return 0;
     318              :   }
     319         3570 :   for (x2 = b;; x2 -= step, set_avma(av))
     320         3486 :   { /* beware overflow, fuse last two bins (avoid a tiny remainder) */
     321         3570 :     ulong j, x1 = (x2 >= 2*step && x2-2*step >= a)? x2+1 - step: a;
     322         3570 :     GEN v = vecfactoru_i(x1, x2);
     323      7005131 :     for (j = lg(v)-1; j; j--)
     324              :     { /* run backward: from factor(x1..x2) to factor(-x2..-x1) */
     325      7001582 :       ulong n = x1-1 + j;
     326      7001582 :       Flm2negfact(gel(v,j), M);
     327      7001582 :       set_lex(-1, mkvec2(utoineg(n), M));
     328      7001582 :       closure_evalvoid(code); if (loop_break()) return 1;
     329              :     }
     330         3549 :     if (x1 == a) break;
     331         3486 :     set_lex(-1, gen_0);
     332              :   }
     333           63 :   return 0;
     334              : }
     335              : static int
     336           70 : eval0(GEN code)
     337              : {
     338           70 :   pari_sp av = avma;
     339           70 :   set_lex(-1, mkvec2(gen_0, mkmat2(mkcol(gen_0),mkcol(gen_1))));
     340           70 :   closure_evalvoid(code); set_avma(av);
     341           70 :   return loop_break();
     342              : }
     343              : void
     344          140 : forfactored(GEN a, GEN b, GEN code)
     345              : {
     346          140 :   pari_sp av = avma;
     347          140 :   long sa, sb, stop = 0;
     348          140 :   if (typ(a) != t_INT) pari_err_TYPE("forfactored", a);
     349          140 :   if (typ(b) != t_INT) pari_err_TYPE("forfactored", b);
     350          140 :   if (cmpii(a,b) > 0) return;
     351          133 :   push_lex(NULL,code);
     352          133 :   sa = signe(a);
     353          133 :   sb = signe(b);
     354          133 :   if (sa < 0)
     355              :   {
     356           84 :     stop = forfactoredneg((sb < 0)? uel(b,2): 1UL, itou(a), code);
     357           84 :     if (!stop && sb >= 0) stop = eval0(code);
     358           84 :     if (!stop && sb > 0) forfactoredpos(1UL, b[2], code);
     359              :   }
     360              :   else
     361              :   {
     362           49 :     if (!sa) stop = eval0(code);
     363           49 :     if (!stop && sb) forfactoredpos(sa? uel(a,2): 1UL, itou(b), code);
     364              :   }
     365          133 :   pop_lex(1); set_avma(av);
     366              : }
     367              : void
     368      1797430 : whilepari(GEN a, GEN b)
     369              : {
     370      1797430 :   pari_sp av = avma;
     371              :   for(;;)
     372     17601956 :   {
     373     19399386 :     GEN res = closure_evalnobrk(a);
     374     19399386 :     if (gequal0(res)) break;
     375     17602005 :     set_avma(av);
     376     17602005 :     closure_evalvoid(b); if (loop_break()) break;
     377              :   }
     378      1797430 :   set_avma(av);
     379      1797430 : }
     380              : 
     381              : void
     382       222242 : untilpari(GEN a, GEN b)
     383              : {
     384       222242 :   pari_sp av = avma;
     385              :   for(;;)
     386      1456761 :   {
     387              :     GEN res;
     388      1679003 :     closure_evalvoid(b); if (loop_break()) break;
     389      1679003 :     res = closure_evalnobrk(a);
     390      1679003 :     if (!gequal0(res)) break;
     391      1456761 :     set_avma(av);
     392              :   }
     393       222242 :   set_avma(av);
     394       222242 : }
     395              : 
     396              : static int
     397           28 : negcmp(GEN x, GEN y) { return gcmp(y,x); }
     398              : 
     399              : void
     400         1645 : forstep(GEN a, GEN b, GEN s, GEN code)
     401              : {
     402              :   long ss, i;
     403         1645 :   pari_sp av, av0 = avma;
     404         1645 :   GEN v = NULL;
     405              :   int (*cmp)(GEN,GEN);
     406              : 
     407         1645 :   b = gcopy(b);
     408         1645 :   s = gcopy(s); av = avma;
     409         1645 :   switch(typ(s))
     410              :   {
     411           14 :     case t_VEC: case t_COL: ss = gsigne(vecsum(s)); v = s; break;
     412           21 :     case t_INTMOD:
     413           21 :       if (typ(a) != t_INT) a = gceil(a);
     414           21 :       a = addii(a, modii(subii(gel(s,2),a), gel(s,1)));
     415           21 :       s = gel(s,1); /* FALL THROUGH */
     416         1631 :     default: ss = gsigne(s);
     417              :   }
     418         1645 :   if (!ss) pari_err_DOMAIN("forstep","step","=",gen_0,s);
     419         1638 :   cmp = (ss > 0)? &gcmp: &negcmp;
     420         1638 :   i = 0;
     421         1638 :   push_lex(a,code);
     422        49847 :   while (cmp(a,b) <= 0)
     423              :   {
     424        48209 :     closure_evalvoid(code); if (loop_break()) break;
     425        48209 :     if (v)
     426              :     {
     427           98 :       if (++i >= lg(v)) i = 1;
     428           98 :       s = gel(v,i);
     429              :     }
     430        48209 :     a = get_lex(-1); a = gadd(a,s);
     431              : 
     432        48209 :     if (_gc_needed(av,1))
     433              :     {
     434            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"forstep");
     435            0 :       a = gc_upto(av,a);
     436              :     }
     437        48209 :     set_lex(-1,a);
     438              :   }
     439         1638 :   pop_lex(1); set_avma(av0);
     440         1638 : }
     441              : 
     442              : static void
     443           28 : _fordiv(GEN a, GEN code, GEN (*D)(GEN))
     444              : {
     445           28 :   pari_sp av = avma;
     446              :   long i, l;
     447           28 :   GEN t = D(a);
     448           28 :   push_lex(gen_0,code); l = lg(t);
     449          231 :   for (i=1; i<l; i++)
     450              :   {
     451          203 :     set_lex(-1,gel(t,i));
     452          203 :     closure_evalvoid(code); if (loop_break()) break;
     453              :   }
     454           28 :   pop_lex(1); set_avma(av);
     455           28 : }
     456              : void
     457           14 : fordiv(GEN a, GEN code) { return _fordiv(a, code, &divisors); }
     458              : void
     459           14 : fordivfactored(GEN a, GEN code) { return _fordiv(a, code, &divisors_factored); }
     460              : 
     461              : /* Embedded for loops:
     462              :  *   fl = 0: execute ch (a), where a = (ai) runs through all n-uplets in
     463              :  *     [m1,M1] x ... x [mn,Mn]
     464              :  *   fl = 1: impose a1 <= ... <= an
     465              :  *   fl = 2:        a1 <  ... <  an
     466              :  */
     467              : /* increment and return d->a [over integers]*/
     468              : static GEN
     469       183852 : _next_i(forvec_t *d)
     470              : {
     471       183852 :   long i = d->n;
     472       183852 :   if (d->first) { d->first = 0; return (GEN)d->a; }
     473              :   for (;;) {
     474       236035 :     if (cmpii(d->a[i], d->M[i]) < 0) {
     475       183462 :       d->a[i] = incloop(d->a[i]);
     476       183462 :       return (GEN)d->a;
     477              :     }
     478        52573 :     d->a[i] = resetloop(d->a[i], d->m[i]);
     479        52573 :     if (--i <= 0) return NULL;
     480              :   }
     481              : }
     482              : /* increment and return d->a [generic]*/
     483              : static GEN
     484           63 : _next(forvec_t *d)
     485              : {
     486           63 :   long i = d->n;
     487           63 :   if (d->first) { d->first = 0; return (GEN)d->a; }
     488              :   for (;;) {
     489           98 :     d->a[i] = gaddgs(d->a[i], 1);
     490           98 :     if (gcmp(d->a[i], d->M[i]) <= 0) return (GEN)d->a;
     491           49 :     d->a[i] = d->m[i];
     492           49 :     if (--i <= 0) return NULL;
     493              :   }
     494              : }
     495              : 
     496              : /* nondecreasing order [over integers] */
     497              : static GEN
     498          206 : _next_le_i(forvec_t *d)
     499              : {
     500          206 :   long i = d->n;
     501          206 :   if (d->first) { d->first = 0; return (GEN)d->a; }
     502              :   for (;;) {
     503          294 :     if (cmpii(d->a[i], d->M[i]) < 0)
     504              :     {
     505          152 :       d->a[i] = incloop(d->a[i]);
     506              :       /* m[i] < a[i] <= M[i] <= M[i+1] */
     507          233 :       while (i < d->n)
     508              :       {
     509              :         GEN t;
     510           81 :         i++;
     511           81 :         if (cmpii(d->a[i-1], d->a[i]) <= 0) continue;
     512              :         /* a[i] < a[i-1] <= M[i-1] <= M[i] */
     513           81 :         t = d->a[i-1]; if (cmpii(t, d->m[i]) < 0) t = d->m[i];
     514           81 :         d->a[i] = resetloop(d->a[i], t);/*a[i]:=max(a[i-1],m[i])*/
     515              :       }
     516          152 :       return (GEN)d->a;
     517              :     }
     518          142 :     d->a[i] = resetloop(d->a[i], d->m[i]);
     519          142 :     if (--i <= 0) return NULL;
     520              :   }
     521              : }
     522              : /* nondecreasing order [generic] */
     523              : static GEN
     524          154 : _next_le(forvec_t *d)
     525              : {
     526          154 :   long i = d->n;
     527          154 :   if (d->first) { d->first = 0; return (GEN)d->a; }
     528              :   for (;;) {
     529          266 :     d->a[i] = gaddgs(d->a[i], 1);
     530          266 :     if (gcmp(d->a[i], d->M[i]) <= 0)
     531              :     {
     532          224 :       while (i < d->n)
     533              :       {
     534              :         GEN c;
     535           98 :         i++;
     536           98 :         if (gcmp(d->a[i-1], d->a[i]) <= 0) continue;
     537              :         /* M[i] >= M[i-1] >= a[i-1] > a[i] */
     538           98 :         c = gceil(gsub(d->a[i-1], d->a[i]));
     539           98 :         d->a[i] = gadd(d->a[i], c);
     540              :         /* a[i-1] <= a[i] < M[i-1] + 1 => a[i] < M[i]+1 => a[i] <= M[i] */
     541              :       }
     542          126 :       return (GEN)d->a;
     543              :     }
     544          140 :     d->a[i] = d->m[i];
     545          140 :     if (--i <= 0) return NULL;
     546              :   }
     547              : }
     548              : /* strictly increasing order [over integers] */
     549              : static GEN
     550      1173574 : _next_lt_i(forvec_t *d)
     551              : {
     552      1173574 :   long i = d->n;
     553      1173574 :   if (d->first) { d->first = 0; return (GEN)d->a; }
     554              :   for (;;) {
     555      1290100 :     if (cmpii(d->a[i], d->M[i]) < 0)
     556              :     {
     557      1159954 :       d->a[i] = incloop(d->a[i]);
     558              :       /* m[i] < a[i] <= M[i] < M[i+1] */
     559      1276466 :       while (i < d->n)
     560              :       {
     561              :         pari_sp av;
     562              :         GEN t;
     563       116512 :         i++;
     564       116512 :         if (cmpii(d->a[i-1], d->a[i]) < 0) continue;
     565       116512 :         av = avma;
     566              :         /* M[i] > M[i-1] >= a[i-1] */
     567       116512 :         t = addiu(d->a[i-1],1); if (cmpii(t, d->m[i]) < 0) t = d->m[i];
     568       116512 :         d->a[i] = resetloop(d->a[i], t);/*a[i]:=max(a[i-1]+1,m[i]) <= M[i]*/
     569       116512 :         set_avma(av);
     570              :       }
     571      1159954 :       return (GEN)d->a;
     572              :     }
     573       130146 :     d->a[i] = resetloop(d->a[i], d->m[i]);
     574       130146 :     if (--i <= 0) return NULL;
     575              :   }
     576              : }
     577              : /* strictly increasing order [generic] */
     578              : static GEN
     579           84 : _next_lt(forvec_t *d)
     580              : {
     581           84 :   long i = d->n;
     582           84 :   if (d->first) { d->first = 0; return (GEN)d->a; }
     583              :   for (;;) {
     584          133 :     d->a[i] = gaddgs(d->a[i], 1);
     585          133 :     if (gcmp(d->a[i], d->M[i]) <= 0)
     586              :     {
     587           91 :       while (i < d->n)
     588              :       {
     589              :         GEN c;
     590           35 :         i++;
     591           35 :         if (gcmp(d->a[i-1], d->a[i]) < 0) continue;
     592              :         /* M[i] > M[i-1] >= a[i-1] >= a[i] */
     593           35 :         c = addiu(gfloor(gsub(d->a[i-1], d->a[i])), 1); /* > a[i-1] - a[i] */
     594           35 :         d->a[i] = gadd(d->a[i], c);
     595              :         /* a[i-1] < a[i] <= M[i-1] + 1 => a[i] < M[i]+1 => a[i] <= M[i] */
     596              :       }
     597           56 :       return (GEN)d->a;
     598              :     }
     599           77 :     d->a[i] = d->m[i];
     600           77 :     if (--i <= 0) return NULL;
     601              :   }
     602              : }
     603              : 
     604              : /* on Z^n /(cyc Z^n) [over integers]
     605              :  * torsion (cyc>0) and free (cyc=0) components may be interleaved */
     606              : static GEN
     607         8463 : _next_mod_cyc(forvec_t *d)
     608              : { /* keep free components indices t1 < t2 last nonzero < t3 */
     609         8463 :   long t, t1 = 0, t2 = 0, t3 = 0;
     610         8463 :   if (d->first) { d->first = 0; return (GEN)d->a; }
     611        27293 :   for (t = d->n; t > 0; t--)
     612              :   {
     613        24332 :     if (signe(d->M[t]) > 0)
     614              :     { /* torsion component */
     615        10738 :       d->a[t] = incloop(d->a[t]);
     616        10738 :       if (cmpii(d->a[t], d->M[t]) < 0) return (GEN)d->a;
     617         5278 :       d->a[t] = resetloop(d->a[t], gen_0);
     618              :     }
     619              :     else
     620              :     { /* set or update t1,t2,t3 */
     621        13594 :       if (t2 && !t1) t1 = t;
     622        13594 :       if (!t2 && signe(d->a[t])) t2 = t;
     623        13594 :       if (!t2) t3 = t;
     624              :     }
     625              :   }
     626         2961 :   if (!t3 && !t2) return NULL; /* no free component, stop */
     627         2947 :   if (!t2) d->a[t3] = resetloop(d->a[t3], gen_m1);
     628         2919 :   else if (!t3 && signe(d->a[t2]) < 0) togglesign(d->a[t2]);
     629         1757 :   else if (signe(d->a[t2]) < 0)
     630              :   {
     631          315 :     d->a[t2] = incloop(d->a[t2]);
     632          315 :     d->a[t3] = resetloop(d->a[t3], gen_m1);
     633              :   }
     634         1442 :   else if (!t1) { d->a[t2] = incloop(d->a[t2]); togglesign(d->a[t2]); }
     635              :   else
     636              :   {
     637         1197 :     if (signe(d->a[t1]) < 0)
     638          490 :     { d->a[t2] = incloop(d->a[t2]); togglesign(d->a[t2]); }
     639              :     else
     640          707 :     { togglesign(d->a[t2]); d->a[t2] = incloop(d->a[t2]); }
     641         1197 :     d->a[t1] = incloop(d->a[t1]);
     642              :   }
     643         2947 :   return (GEN)d->a;
     644              : }
     645              : /* for forvec(v=[],) */
     646              : static GEN
     647           14 : _next_void(forvec_t *d)
     648              : {
     649           14 :   if (d->first) { d->first = 0; return (GEN)d->a; }
     650            7 :   return NULL;
     651              : }
     652              : static int
     653         7151 : RgV_is_ZV_nonneg(GEN x)
     654              : {
     655              :   long i;
     656         7305 :   for (i = lg(x)-1; i > 0; i--)
     657         7263 :     if (typ(gel(x,i)) != t_INT || signe(gel(x, i)) < 0) return 0;
     658           42 :   return 1;
     659              : }
     660              : /* x assumed to be cyc vector, l>1 */
     661              : static int
     662           42 : forvec_mod_cyc_init(forvec_t *d, GEN x)
     663              : {
     664           42 :   long i, tx = typ(x), l = lg(x);
     665           42 :   d->a = (GEN*)cgetg(l,tx); /* current */
     666           42 :   d->M = (GEN*)cgetg(l,tx); /* cyc */
     667          175 :   for (i = 1; i < l; i++)
     668              :   {
     669          133 :     d->a[i] = setloop(gen_0);
     670          133 :     d->M[i] = setloop(gel(x, i));
     671              :   }
     672           42 :   d->first = 1;
     673           42 :   d->n = l-1;
     674           42 :   d->m = NULL;
     675           42 :   d->next = &_next_mod_cyc;
     676           42 :   return 1;
     677              : }
     678              : 
     679              : /* Initialize minima (m) and maxima (M); guarantee M[i] - m[i] integer and
     680              :  *   if flag = 1: m[i-1] <= m[i] <= M[i] <= M[i+1]
     681              :  *   if flag = 2: m[i-1] <  m[i] <= M[i] <  M[i+1],
     682              :  * for all i */
     683              : int
     684         7158 : forvec_init(forvec_t *d, GEN x, long flag)
     685              : {
     686         7158 :   long i, tx = typ(x), l = lg(x), t = t_INT;
     687         7158 :   if (!is_vec_t(tx)) pari_err_TYPE("forvec [not a vector]", x);
     688         7158 :   if (l > 1 && RgV_is_ZV_nonneg(x))
     689           42 :       return forvec_mod_cyc_init(d, x);
     690         7116 :   d->first = 1;
     691         7116 :   d->n = l - 1;
     692         7116 :   d->a = (GEN*)cgetg(l,tx);
     693         7116 :   d->m = (GEN*)cgetg(l,tx);
     694         7116 :   d->M = (GEN*)cgetg(l,tx);
     695         7116 :   if (l == 1) { d->next = &_next_void; return 1; }
     696        21565 :   for (i = 1; i < l; i++)
     697              :   {
     698        14491 :     GEN a, e = gel(x,i), m = gel(e,1), M = gel(e,2);
     699        14491 :     tx = typ(e);
     700        14491 :     if (! is_vec_t(tx) || lg(e)!=3)
     701           21 :       pari_err_TYPE("forvec [expected vector not of type [min,MAX]]",e);
     702        14470 :     if (typ(m) != t_INT) t = t_REAL;
     703        14470 :     if (i > 1) switch(flag)
     704              :     {
     705           62 :       case 1: /* a >= m[i-1] - m */
     706           62 :         a = gceil(gsub(d->m[i-1], m));
     707           62 :         if (typ(a) != t_INT) pari_err_TYPE("forvec",a);
     708           62 :         if (signe(a) > 0) m = gadd(m, a); else m = gcopy(m);
     709           62 :         break;
     710         6859 :       case 2: /* a > m[i-1] - m */
     711         6859 :         a = gfloor(gsub(d->m[i-1], m));
     712         6859 :         if (typ(a) != t_INT) pari_err_TYPE("forvec",a);
     713         6859 :         a = addiu(a, 1);
     714         6859 :         if (signe(a) > 0) m = gadd(m, a); else m = gcopy(m);
     715         6859 :         break;
     716          454 :       default: m = gcopy(m);
     717          454 :         break;
     718              :     }
     719        14470 :     M = gadd(m, gfloor(gsub(M,m))); /* ensure M-m is an integer */
     720        14463 :     if (gcmp(m,M) > 0) { d->a = NULL; d->next = &_next; return 0; }
     721        14456 :     d->m[i] = m;
     722        14456 :     d->M[i] = M;
     723              :   }
     724         7136 :   if (flag == 1) for (i = l-2; i >= 1; i--)
     725              :   {
     726           62 :     GEN M = d->M[i], a = gfloor(gsub(d->M[i+1], M));
     727           62 :     if (typ(a) != t_INT) pari_err_TYPE("forvec",a);
     728              :     /* M[i]+a <= M[i+1] */
     729           62 :     if (signe(a) < 0) d->M[i] = gadd(M, a);
     730              :   }
     731        13885 :   else if (flag == 2) for (i = l-2; i >= 1; i--)
     732              :   {
     733         6852 :     GEN M = d->M[i], a = gceil(gsub(d->M[i+1], M));
     734         6852 :     if (typ(a) != t_INT) pari_err_TYPE("forvec",a);
     735         6852 :     a = subiu(a, 1);
     736              :     /* M[i]+a < M[i+1] */
     737         6852 :     if (signe(a) < 0) d->M[i] = gadd(M, a);
     738              :   }
     739         7074 :   if (t == t_INT) {
     740        21376 :     for (i = 1; i < l; i++) {
     741        14337 :       d->a[i] = setloop(d->m[i]);
     742        14337 :       if (typ(d->M[i]) != t_INT) d->M[i] = gfloor(d->M[i]);
     743              :     }
     744              :   } else {
     745          140 :     for (i = 1; i < l; i++) d->a[i] = d->m[i];
     746              :   }
     747         7074 :   switch(flag)
     748              :   {
     749          202 :     case 0: d->next = t==t_INT? &_next_i:    &_next; break;
     750           41 :     case 1: d->next = t==t_INT? &_next_le_i: &_next_le; break;
     751         6824 :     case 2: d->next = t==t_INT? &_next_lt_i: &_next_lt; break;
     752            7 :     default: pari_err_FLAG("forvec");
     753              :   }
     754         7067 :   return 1;
     755              : }
     756              : GEN
     757      1366410 : forvec_next(forvec_t *d) { return d->next(d); }
     758              : 
     759              : void
     760         7077 : forvec(GEN x, GEN code, long flag)
     761              : {
     762         7077 :   pari_sp av = avma;
     763              :   forvec_t T;
     764              :   GEN v;
     765         7077 :   if (!forvec_init(&T, x, flag)) { set_avma(av); return; }
     766         7035 :   push_lex((GEN)T.a, code);
     767      1365798 :   while ((v = forvec_next(&T)))
     768              :   {
     769      1358791 :     closure_evalvoid(code);
     770      1358791 :     if (loop_break()) break;
     771              :   }
     772         7035 :   pop_lex(1); set_avma(av);
     773              : }
     774              : 
     775              : /********************************************************************/
     776              : /**                                                                **/
     777              : /**                              SUMS                              **/
     778              : /**                                                                **/
     779              : /********************************************************************/
     780              : 
     781              : GEN
     782        70238 : somme(GEN a, GEN b, GEN code, GEN x)
     783              : {
     784        70238 :   pari_sp av, av0 = avma;
     785              :   GEN p1;
     786              : 
     787        70238 :   if (typ(a) != t_INT) pari_err_TYPE("sum",a);
     788        70238 :   if (!x) x = gen_0;
     789        70238 :   if (gcmp(b,a) < 0) return gcopy(x);
     790              : 
     791        70238 :   b = gfloor(b);
     792        70238 :   a = setloop(a);
     793        70238 :   av=avma;
     794        70238 :   push_lex(a,code);
     795              :   for(;;)
     796              :   {
     797      1870470 :     p1 = closure_evalnobrk(code);
     798      1870470 :     x=gadd(x,p1); if (cmpii(a,b) >= 0) break;
     799      1800232 :     a = incloop(a);
     800      1800232 :     if (gc_needed(av,1))
     801              :     {
     802            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"sum");
     803            0 :       x = gc_upto(av,x);
     804              :     }
     805      1800232 :     set_lex(-1,a);
     806              :   }
     807        70238 :   pop_lex(1); return gc_upto(av0,x);
     808              : }
     809              : 
     810              : static GEN
     811           28 : sum_init(GEN x0, GEN t)
     812              : {
     813           28 :   long tp = typ(t);
     814              :   GEN x;
     815           28 :   if (is_vec_t(tp))
     816              :   {
     817            7 :     x = const_vec(lg(t)-1, x0);
     818            7 :     settyp(x, tp);
     819              :   }
     820              :   else
     821           21 :     x = x0;
     822           28 :   return x;
     823              : }
     824              : 
     825              : GEN
     826           28 : suminf(void *E, GEN (*eval)(void *, GEN), GEN a, long bit)
     827              : {
     828           28 :   long fl = 0, G = bit + 1;
     829           28 :   pari_sp av0 = avma, av;
     830           28 :   GEN x = NULL, _1;
     831              : 
     832           28 :   if (typ(a) != t_INT) pari_err_TYPE("suminf",a);
     833           28 :   a = setloop(a); av = avma;
     834              :   for(;;)
     835        15617 :   {
     836        15645 :     GEN t = eval(E, a);
     837        15645 :     if (!x) _1 = x = sum_init(real_1_bit(bit), t);
     838              : 
     839        15645 :     x = gadd(x,t);
     840        15645 :     if (!gequal0(t) && gexpo(t) > gexpo(x)-G)
     841        15449 :       fl = 0;
     842          196 :     else if (++fl == 3)
     843           28 :       break;
     844        15617 :     a = incloop(a);
     845        15617 :     if (gc_needed(av,1))
     846              :     {
     847            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"suminf");
     848            0 :       (void)gc_all(av,2, &x, &_1);
     849              :     }
     850              :   }
     851           28 :   return gc_upto(av0, gsub(x, _1));
     852              : }
     853              : GEN
     854           28 : suminf0(GEN a, GEN code, long bit)
     855           28 : { EXPR_WRAP(code, suminf(EXPR_ARG, a, bit)); }
     856              : 
     857              : GEN
     858           56 : sumdivexpr(GEN num, GEN code)
     859              : {
     860           56 :   pari_sp av = avma;
     861           56 :   GEN y = gen_0, t = divisors(num);
     862           56 :   long i, l = lg(t);
     863              : 
     864           56 :   push_lex(gen_0, code);
     865         9352 :   for (i=1; i<l; i++)
     866              :   {
     867         9296 :     set_lex(-1,gel(t,i));
     868         9296 :     y = gadd(y, closure_evalnobrk(code));
     869              :   }
     870           56 :   pop_lex(1); return gc_upto(av,y);
     871              : }
     872              : 
     873              : GEN
     874           49 : sumdivmultexpr(void *D, GEN (*fun)(void*, GEN), GEN num)
     875              : {
     876           49 :   pari_sp av = avma;
     877           49 :   GEN y = gen_1, P,E;
     878           49 :   int isint = divisors_init(num, &P,&E);
     879           49 :   long i, l = lg(P);
     880              :   GEN (*mul)(GEN,GEN);
     881              : 
     882           49 :   if (l == 1) return gc_const(av, gen_1);
     883           49 :   mul = isint? mulii: gmul;
     884          224 :   for (i=1; i<l; i++)
     885              :   {
     886          175 :     GEN p = gel(P,i), q = p, z = gen_1;
     887          175 :     long j, e = E[i];
     888          581 :     for (j = 1; j <= e; j++, q = mul(q, p))
     889              :     {
     890          581 :       z = gadd(z, fun(D, q));
     891          581 :       if (j == e) break;
     892              :     }
     893          175 :     y = gmul(y, z);
     894              :   }
     895           49 :   return gc_upto(av,y);
     896              : }
     897              : 
     898              : GEN
     899           49 : sumdivmultexpr0(GEN num, GEN code)
     900           49 : { EXPR_WRAP(code, sumdivmultexpr(EXPR_ARG, num)) }
     901              : 
     902              : /********************************************************************/
     903              : /**                                                                **/
     904              : /**                           PRODUCTS                             **/
     905              : /**                                                                **/
     906              : /********************************************************************/
     907              : 
     908              : GEN
     909       120694 : produit(GEN a, GEN b, GEN code, GEN x)
     910              : {
     911       120694 :   pari_sp av, av0 = avma;
     912              :   GEN p1;
     913              : 
     914       120694 :   if (typ(a) != t_INT) pari_err_TYPE("prod",a);
     915       120694 :   if (!x) x = gen_1;
     916       120694 :   if (gcmp(b,a) < 0) return gcopy(x);
     917              : 
     918       115416 :   b = gfloor(b);
     919       115416 :   a = setloop(a);
     920       115416 :   av=avma;
     921       115416 :   push_lex(a,code);
     922              :   for(;;)
     923              :   {
     924       349804 :     p1 = closure_evalnobrk(code);
     925       349804 :     x = gmul(x,p1); if (cmpii(a,b) >= 0) break;
     926       234388 :     a = incloop(a);
     927       234388 :     if (gc_needed(av,1))
     928              :     {
     929            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"prod");
     930            0 :       x = gc_upto(av,x);
     931              :     }
     932       234388 :     set_lex(-1,a);
     933              :   }
     934       115416 :   pop_lex(1); return gc_upto(av0,x);
     935              : }
     936              : 
     937              : GEN
     938           14 : prodinf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
     939              : {
     940           14 :   pari_sp av0 = avma, av;
     941              :   long fl,G;
     942           14 :   GEN p1,x = real_1(prec);
     943              : 
     944           14 :   if (typ(a) != t_INT) pari_err_TYPE("prodinf",a);
     945           14 :   a = setloop(a);
     946           14 :   av = avma;
     947           14 :   fl=0; G = -prec-5;
     948              :   for(;;)
     949              :   {
     950         1897 :     p1 = eval(E, a); if (gequal0(p1)) { x = p1; break; }
     951         1897 :     x = gmul(x,p1); a = incloop(a);
     952         1897 :     p1 = gsubgs(p1, 1);
     953         1897 :     if (gequal0(p1) || gexpo(p1) <= G) { if (++fl==3) break; } else fl=0;
     954         1883 :     if (gc_needed(av,1))
     955              :     {
     956            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"prodinf");
     957            0 :       x = gc_upto(av,x);
     958              :     }
     959              :   }
     960           14 :   return gc_GEN(av0,x);
     961              : }
     962              : GEN
     963            7 : prodinf1(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
     964              : {
     965            7 :   pari_sp av0 = avma, av;
     966              :   long fl,G;
     967            7 :   GEN p1,p2,x = real_1(prec);
     968              : 
     969            7 :   if (typ(a) != t_INT) pari_err_TYPE("prodinf1",a);
     970            7 :   a = setloop(a);
     971            7 :   av = avma;
     972            7 :   fl=0; G = -prec-5;
     973              :   for(;;)
     974              :   {
     975          952 :     p2 = eval(E, a); p1 = gaddgs(p2,1);
     976          952 :     if (gequal0(p1)) { x = p1; break; }
     977          952 :     x = gmul(x,p1); a = incloop(a);
     978          952 :     if (gequal0(p2) || gexpo(p2) <= G) { if (++fl==3) break; } else fl=0;
     979          945 :     if (gc_needed(av,1))
     980              :     {
     981            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"prodinf1");
     982            0 :       x = gc_upto(av,x);
     983              :     }
     984              :   }
     985            7 :   return gc_GEN(av0,x);
     986              : }
     987              : GEN
     988           28 : prodinf0(GEN a, GEN code, long flag, long prec)
     989              : {
     990           28 :   switch(flag)
     991              :   {
     992           14 :     case 0: EXPR_WRAP(code, prodinf (EXPR_ARG, a, prec));
     993            7 :     case 1: EXPR_WRAP(code, prodinf1(EXPR_ARG, a, prec));
     994              :   }
     995            7 :   pari_err_FLAG("prodinf");
     996              :   return NULL; /* LCOV_EXCL_LINE */
     997              : }
     998              : 
     999              : GEN
    1000           14 : prodeuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec)
    1001              : {
    1002           14 :   pari_sp av, av0 = avma;
    1003           14 :   GEN x = real_1(prec), prime;
    1004              :   forprime_t T;
    1005              : 
    1006           14 :   av = avma;
    1007           14 :   if (!forprime_init(&T, a,b)) return gc_const(av, x);
    1008              : 
    1009           14 :   av = avma;
    1010         8645 :   while ( (prime = forprime_next(&T)) )
    1011              :   {
    1012         8631 :     x = gmul(x, eval(E, prime));
    1013         8631 :     if (gc_needed(av,1))
    1014              :     {
    1015            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"prodeuler");
    1016            0 :       x = gc_GEN(av, x);
    1017              :     }
    1018              :   }
    1019           14 :   return gc_GEN(av0,x);
    1020              : }
    1021              : GEN
    1022           14 : prodeuler0(GEN a, GEN b, GEN code, long prec)
    1023           14 : { EXPR_WRAP(code, prodeuler(EXPR_ARG, a, b, prec)); }
    1024              : GEN
    1025          133 : direuler0(GEN a, GEN b, GEN code, GEN c)
    1026          133 : { EXPR_WRAP(code, direuler(EXPR_ARG, a, b, c)); }
    1027              : 
    1028              : /********************************************************************/
    1029              : /**                                                                **/
    1030              : /**                       VECTORS & MATRICES                       **/
    1031              : /**                                                                **/
    1032              : /********************************************************************/
    1033              : 
    1034              : INLINE GEN
    1035      2842415 : copyupto(GEN z, GEN t)
    1036              : {
    1037      2842415 :   if (is_universal_constant(z) || (z>(GEN)pari_mainstack->bot && z<=t))
    1038      2842408 :     return z;
    1039              :   else
    1040            7 :     return gcopy(z);
    1041              : }
    1042              : 
    1043              : GEN
    1044       132815 : vecexpr0(GEN vec, GEN code, GEN pred)
    1045              : {
    1046       132815 :   switch(typ(vec))
    1047              :   {
    1048           21 :     case t_LIST:
    1049              :     {
    1050           21 :       if (list_typ(vec)==t_LIST_MAP)
    1051            7 :         vec = mapdomain_shallow(vec);
    1052              :       else
    1053           14 :         vec = list_data(vec);
    1054           21 :       if (!vec) return cgetg(1, t_VEC);
    1055           14 :       break;
    1056              :     }
    1057            7 :     case t_VECSMALL:
    1058            7 :       vec = vecsmall_to_vec(vec);
    1059            7 :       break;
    1060       132787 :     case t_VEC: case t_COL: case t_MAT: break;
    1061            0 :     default: pari_err_TYPE("[_|_<-_,_]",vec);
    1062              :   }
    1063       132808 :   if (pred && code)
    1064          469 :     EXPR_WRAP(code,vecselapply((void*)pred,&gp_evalbool,EXPR_ARGUPTO,vec))
    1065       132339 :   else if (code)
    1066       132339 :     EXPR_WRAP(code,vecapply(EXPR_ARGUPTO,vec))
    1067              :   else
    1068            0 :     EXPR_WRAP(pred,vecselect(EXPR_ARGBOOL,vec))
    1069              : }
    1070              : 
    1071              : GEN
    1072           70 : vecexpreq0(GEN x, GEN code, GEN pred)
    1073              : {
    1074           70 :   if (pred)
    1075           70 :     EXPR_WRAP(code,eqselapply((void*)pred,&gp_evalbool,EXPR_ARGUPTO,x))
    1076              :   else
    1077            0 :     EXPR_WRAP(code,eqselapply(NULL,NULL,EXPR_ARGUPTO,x))
    1078              : }
    1079              : 
    1080              : GEN
    1081         2121 : vecexpr1(GEN vec, GEN code, GEN pred)
    1082              : {
    1083         2121 :   GEN v = vecexpr0(vec, code, pred);
    1084         2121 :   return lg(v) == 1? v: shallowconcat1(v);
    1085              : }
    1086              : 
    1087              : GEN
    1088            0 : vecexpreq1(GEN x, GEN code, GEN pred)
    1089              : {
    1090            0 :   GEN v = vecexpreq0(x, code, pred);
    1091            0 :   return lg(v) == 1? v: shallowconcat1(v);
    1092              : }
    1093              : 
    1094              : GEN
    1095      2369989 : vecteur(GEN nmax, GEN code)
    1096              : {
    1097              :   GEN y, c;
    1098      2369989 :   long i, m = gtos(nmax);
    1099              : 
    1100      2369989 :   if (m < 0)  pari_err_DOMAIN("vector", "dimension", "<", gen_0, stoi(m));
    1101      2369975 :   if (!code) return zerovec(m);
    1102        23785 :   c = cgetipos(3); /* left on stack */
    1103        23785 :   y = cgetg(m+1,t_VEC); push_lex(c, code);
    1104       902595 :   for (i=1; i<=m; i++)
    1105              :   {
    1106       878824 :     c[2] = i;
    1107       878824 :     gel(y,i) = copyupto(closure_evalnobrk(code), y);
    1108       878810 :     set_lex(-1,c);
    1109              :   }
    1110        23771 :   pop_lex(1); return y;
    1111              : }
    1112              : 
    1113              : GEN
    1114          791 : vecteursmall(GEN nmax, GEN code)
    1115              : {
    1116              :   pari_sp av;
    1117              :   GEN y, c;
    1118          791 :   long i, m = gtos(nmax);
    1119              : 
    1120          791 :   if (m < 0)  pari_err_DOMAIN("vectorsmall", "dimension", "<", gen_0, stoi(m));
    1121          784 :   if (!code) return zero_zv(m);
    1122          763 :   c = cgetipos(3); /* left on stack */
    1123          763 :   y = cgetg(m+1,t_VECSMALL); push_lex(c,code);
    1124          763 :   av = avma;
    1125     10186883 :   for (i = 1; i <= m; i++)
    1126              :   {
    1127     10186127 :     c[2] = i;
    1128     10186127 :     y[i] = gtos(closure_evalnobrk(code));
    1129     10186120 :     set_avma(av);
    1130     10186120 :     set_lex(-1,c);
    1131              :   }
    1132          756 :   pop_lex(1); return y;
    1133              : }
    1134              : 
    1135              : GEN
    1136         2051 : vvecteur(GEN nmax, GEN n)
    1137              : {
    1138         2051 :   GEN y = vecteur(nmax,n);
    1139         2044 :   settyp(y,t_COL); return y;
    1140              : }
    1141              : 
    1142              : GEN
    1143       161497 : matrice(GEN nlig, GEN ncol, GEN code)
    1144              : {
    1145              :   GEN c1, c2, y;
    1146              :   long i, m, n;
    1147              : 
    1148       161497 :   n = gtos(nlig);
    1149       161497 :   m = ncol? gtos(ncol): n;
    1150       161497 :   if (m < 0)  pari_err_DOMAIN("matrix", "nbcols", "<", gen_0, stoi(m));
    1151       161490 :   if (n < 0)  pari_err_DOMAIN("matrix", "nbrows", "<", gen_0, stoi(n));
    1152       161483 :   if (!m) return cgetg(1,t_MAT);
    1153       161413 :   if (!code || !n) return zeromatcopy(n, m);
    1154       158914 :   c1 = cgetipos(3); push_lex(c1,code);
    1155       158914 :   c2 = cgetipos(3); push_lex(c2,NULL); /* c1,c2 left on stack */
    1156       158914 :   y = cgetg(m+1,t_MAT);
    1157       597716 :   for (i = 1; i <= m; i++)
    1158              :   {
    1159       438802 :     GEN z = cgetg(n+1,t_COL);
    1160              :     long j;
    1161       438802 :     c2[2] = i; gel(y,i) = z;
    1162      2402400 :     for (j = 1; j <= n; j++)
    1163              :     {
    1164      1963598 :       c1[2] = j;
    1165      1963598 :       gel(z,j) = copyupto(closure_evalnobrk(code), y);
    1166      1963598 :       set_lex(-2,c1);
    1167      1963598 :       set_lex(-1,c2);
    1168              :     }
    1169              :   }
    1170       158914 :   pop_lex(2); return y;
    1171              : }
    1172              : 
    1173              : /********************************************************************/
    1174              : /**                                                                **/
    1175              : /**                         SUMMING SERIES                         **/
    1176              : /**                                                                **/
    1177              : /********************************************************************/
    1178              : /* h = (2+2x)g'- g; g has t_INT coeffs */
    1179              : static GEN
    1180         1295 : delt(GEN g, long n)
    1181              : {
    1182         1295 :   GEN h = cgetg(n+3,t_POL);
    1183              :   long k;
    1184         1295 :   h[1] = g[1];
    1185         1295 :   gel(h,2) = gel(g,2);
    1186       359954 :   for (k=1; k<n; k++)
    1187       358659 :     gel(h,k+2) = addii(mului(k+k+1,gel(g,k+2)), mului(k<<1,gel(g,k+1)));
    1188         1295 :   gel(h,n+2) = mului(n<<1, gel(g,n+1)); return h;
    1189              : }
    1190              : 
    1191              : #ifdef _MSC_VER /* Bill Daly: work around a MSVC bug */
    1192              : #pragma optimize("g",off)
    1193              : #endif
    1194              : /* P = polzagier(n,m)(-X), unnormalized (P(0) != 1) */
    1195              : static GEN
    1196           84 : polzag1(long n, long m)
    1197              : {
    1198           84 :   long d = n - m, i, k, d2, r, D;
    1199           84 :   pari_sp av = avma;
    1200              :   GEN g, T;
    1201              : 
    1202           84 :   if (d <= 0 || m < 0) return pol_0(0);
    1203           77 :   d2 = d << 1; r = (m+1) >> 1, D = (d+1) >> 1;
    1204           77 :   g = cgetg(d+2, t_POL);
    1205           77 :   g[1] = evalsigne(1)|evalvarn(0);
    1206           77 :   T = cgetg(d+1,t_VEC);
    1207              :   /* T[k+1] = binomial(2d,2k+1), 0 <= k < d */
    1208           77 :   gel(T,1) = utoipos(d2);
    1209         1344 :   for (k = 1; k < D; k++)
    1210              :   {
    1211         1267 :     long k2 = k<<1;
    1212         1267 :     gel(T,k+1) = diviiexact(mulii(gel(T,k), muluu(d2-k2+1, d2-k2)),
    1213         1267 :                             muluu(k2,k2+1));
    1214              :   }
    1215         1365 :   for (; k < d; k++) gel(T,k+1) = gel(T,d-k);
    1216           77 :   gel(g,2) = gel(T,d); /* binomial(2d, 2(d-1)+1) */
    1217         2632 :   for (i = 1; i < d; i++)
    1218              :   {
    1219         2555 :     pari_sp av2 = avma;
    1220         2555 :     GEN s, t = gel(T,d-i); /* binomial(2d, 2(d-1-i)+1) */
    1221         2555 :     s = t;
    1222       180635 :     for (k = d-i; k < d; k++)
    1223              :     {
    1224       178080 :       long k2 = k<<1;
    1225       178080 :       t = diviiexact(mulii(t, muluu(d2-k2+1, d-k)), muluu(k2+1,k-(d-i)+1));
    1226       178080 :       s = addii(s, t);
    1227              :     }
    1228              :     /* g_i = sum_{d-1-i <= k < d}, binomial(2*d, 2*k+1)*binomial(k,d-1-i) */
    1229         2555 :     gel(g,i+2) = gc_INT(av2, s);
    1230              :   }
    1231              :   /* sum_{0 <= i < d} g_i x^i * (x+x^2)^r */
    1232           77 :   g = RgX_mulXn(gmul(g, gpowgs(deg1pol_shallow(gen_1,gen_1,0),r)), r);
    1233           77 :   if (!odd(m)) g = delt(g, n);
    1234         1337 :   for (i = 1; i <= r; i++)
    1235              :   {
    1236         1260 :     g = delt(ZX_deriv(g), n);
    1237         1260 :     if (gc_needed(av,4))
    1238              :     {
    1239            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"polzag, i = %ld/%ld", i,r);
    1240            0 :       g = gc_GEN(av, g);
    1241              :     }
    1242              :   }
    1243           77 :   return g;
    1244              : }
    1245              : GEN
    1246           35 : polzag(long n, long m)
    1247              : {
    1248           35 :   pari_sp av = avma;
    1249           35 :   GEN g = polzag1(n,m);
    1250           35 :   if (lg(g) == 2) return g;
    1251           28 :   g = ZX_z_unscale(polzag1(n,m), -1);
    1252           28 :   return gc_upto(av, RgX_Rg_div(g,gel(g,2)));
    1253              : }
    1254              : 
    1255              : /*0.39322 > 1/log_2(3+sqrt(8))*/
    1256              : static ulong
    1257          154 : sumalt_N(long prec)
    1258          154 : { return (ulong)(0.39322*(prec + 7)); }
    1259              : 
    1260              : GEN
    1261           84 : sumalt(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
    1262              : {
    1263              :   ulong k, N;
    1264           84 :   pari_sp av = avma, av2;
    1265              :   GEN s, az, c, d;
    1266              : 
    1267           84 :   if (typ(a) != t_INT) pari_err_TYPE("sumalt",a);
    1268           84 :   N = sumalt_N(prec);
    1269           84 :   d = powru(addsr(3, sqrtr(utor(8,prec))), N);
    1270           84 :   d = shiftr(addrr(d, invr(d)),-1);
    1271           84 :   a = setloop(a);
    1272           84 :   az = gen_m1; c = d;
    1273           84 :   s = gen_0;
    1274           84 :   av2 = avma;
    1275           84 :   for (k=0; ; k++) /* k < N */
    1276              :   {
    1277        10752 :     c = addir(az,c); s = gadd(s, gmul(c, eval(E, a)));
    1278        10752 :     if (k==N-1) break;
    1279        10668 :     az = diviuuexact(muluui((N-k)<<1,N+k,az), k+1, (k<<1)+1);
    1280        10668 :     a = incloop(a); /* in place! */
    1281        10668 :     if (gc_needed(av,4))
    1282              :     {
    1283            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"sumalt, k = %ld/%ld", k,N-1);
    1284            0 :       (void)gc_all(av2, 3, &az,&c,&s);
    1285              :     }
    1286              :   }
    1287           84 :   return gc_upto(av, gdiv(s,d));
    1288              : }
    1289              : 
    1290              : GEN
    1291            7 : sumalt2(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
    1292              : {
    1293              :   long k, N;
    1294            7 :   pari_sp av = avma, av2;
    1295              :   GEN s, dn, pol;
    1296              : 
    1297            7 :   if (typ(a) != t_INT) pari_err_TYPE("sumalt",a);
    1298            7 :   N = (long)(0.307073*(prec + 5)); /*0.307073 > 1/log_2(\beta_B)*/
    1299            7 :   pol = ZX_div_by_X_1(polzag1(N,N>>1), &dn);
    1300            7 :   a = setloop(a);
    1301            7 :   N = degpol(pol);
    1302            7 :   s = gen_0;
    1303            7 :   av2 = avma;
    1304          280 :   for (k=0; k<=N; k++)
    1305              :   {
    1306          280 :     GEN t = itor(gel(pol,k+2), prec+EXTRAPREC64);
    1307          280 :     s = gadd(s, gmul(t, eval(E, a)));
    1308          280 :     if (k == N) break;
    1309          273 :     a = incloop(a); /* in place! */
    1310          273 :     if (gc_needed(av,4))
    1311              :     {
    1312            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"sumalt2, k = %ld/%ld", k,N-1);
    1313            0 :       s = gc_upto(av2, s);
    1314              :     }
    1315              :   }
    1316            7 :   return gc_upto(av, gdiv(s,dn));
    1317              : }
    1318              : 
    1319              : GEN
    1320           28 : sumalt0(GEN a, GEN code, long flag, long prec)
    1321              : {
    1322           28 :   switch(flag)
    1323              :   {
    1324           14 :     case 0: EXPR_WRAP(code, sumalt (EXPR_ARG,a,prec));
    1325            7 :     case 1: EXPR_WRAP(code, sumalt2(EXPR_ARG,a,prec));
    1326            7 :     default: pari_err_FLAG("sumalt");
    1327              :   }
    1328              :   return NULL; /* LCOV_EXCL_LINE */
    1329              : }
    1330              : 
    1331              : /* For k > 0, set S[k*2^i] <- g(k*2^i), k*2^i <= N = #S.
    1332              :  * Only needed with k odd (but also works for g even). */
    1333              : static void
    1334         8953 : binsum(GEN S, ulong k, void *E, GEN (*f)(void *, GEN), GEN a,
    1335              :         long G, long prec)
    1336              : {
    1337         8953 :   long e, i, N = lg(S)-1, l = expu(N / k); /* k 2^l <= N < k 2^(l+1) */
    1338         8953 :   pari_sp av = avma;
    1339         8953 :   GEN t = real_0(prec); /* unused unless f(a + k <<l) = 0 */
    1340              : 
    1341         8953 :   G -= l;
    1342         8953 :   if (!signe(a)) a = NULL;
    1343         8953 :   for (e = 0;; e++)
    1344      5389657 :   { /* compute g(k 2^l) with absolute error ~ 2^(G-l) */
    1345      5398610 :     GEN u, r = shifti(utoipos(k), l+e);
    1346      5398610 :     if (a) r = addii(r, a);
    1347      5398610 :     u = gtofp(f(E, r), prec);
    1348      5398610 :     if (typ(u) != t_REAL) pari_err_TYPE("sumpos",u);
    1349      5398610 :     if (!signe(u)) break;
    1350      5398421 :     if (!e)
    1351         8764 :       t = u;
    1352              :     else {
    1353      5389657 :       shiftr_inplace(u, e);
    1354      5389657 :       t = addrr(t,u); if (expo(u) < G) break;
    1355      5380893 :       if ((e & 0x1ff) == 0) t = gc_leaf(av, t);
    1356              :     }
    1357              :   }
    1358         8953 :   gel(S, k << l) = t = gc_leaf(av, t);
    1359              :   /* g(j) = 2g(2j) + f(a+j) for all j > 0 */
    1360        17906 :   for(i = l-1; i >= 0; i--)
    1361              :   { /* t ~ g(2 * k*2^i) with error ~ 2^(G-i-1) */
    1362              :     GEN u;
    1363         8953 :     av = avma; u = gtofp(f(E, a? addiu(a, k << i): utoipos(k << i)), prec);
    1364         8953 :     if (typ(u) != t_REAL) pari_err_TYPE("sumpos",u);
    1365         8953 :     t = addrr(gtofp(u,prec), mpshift(t,1)); /* ~ g(k*2^i) */
    1366         8953 :     gel(S, k << i) = t = gc_leaf(av, t);
    1367              :   }
    1368         8953 : }
    1369              : /* For k > 0, let g(k) := \sum_{e >= 0} 2^e f(a + k*2^e).
    1370              :  * Return [g(k), 1 <= k <= N] */
    1371              : static GEN
    1372           84 : sumpos_init(void *E, GEN (*f)(void *, GEN), GEN a, long N, long prec)
    1373              : {
    1374           84 :   GEN S = cgetg(N+1,t_VEC);
    1375           84 :   long k, G = -prec - 5;
    1376         9037 :   for (k=1; k<=N; k+=2) binsum(S,k, E,f, a,G,prec);
    1377           84 :   return S;
    1378              : }
    1379              : 
    1380              : GEN
    1381           70 : sumpos(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
    1382              : {
    1383              :   ulong k, N;
    1384           70 :   pari_sp av = avma;
    1385              :   GEN s, az, c, d, S;
    1386              : 
    1387           70 :   if (typ(a) != t_INT) pari_err_TYPE("sumpos",a);
    1388           70 :   a = subiu(a, 1);
    1389           70 :   N = sumalt_N(prec); /* > 0 */
    1390           70 :   if (odd(N)) N++; /* extra precision for free */
    1391           70 :   d = powru(addsr(3, sqrtr(utor(8,prec))), N);
    1392           70 :   d = shiftr(addrr(d, invr(d)), -1);
    1393           70 :   az = gen_m1; c = d;
    1394              : 
    1395           70 :   S = sumpos_init(E, eval, a, N, prec);
    1396           70 :   s = NULL;
    1397        13454 :   for (k = 0; k < N; k++)
    1398              :   {
    1399              :     GEN t;
    1400        13454 :     c = addir(az, c);
    1401        13454 :     t = mulrr(gel(S, k+1), c);
    1402        13454 :     s = k == 0? t: odd(k)? subrr(s, t): addrr(s, t);
    1403        13454 :     if (k == N-1) break;
    1404        13384 :     az = diviuuexact(muluui((N-k)<<1, N+k, az), k+1, (k<<1)+1);
    1405              :   }
    1406           70 :   return gc_leaf(av, divrr(s,d));
    1407              : }
    1408              : 
    1409              : GEN
    1410           14 : sumpos2(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
    1411              : {
    1412              :   ulong k, N;
    1413           14 :   pari_sp av = avma;
    1414              :   GEN s, pol, dn, S;
    1415              : 
    1416           14 :   if (typ(a) != t_INT) pari_err_TYPE("sumpos2",a);
    1417           14 :   a = subiu(a,1);
    1418           14 :   N = (ulong)(0.31*(prec + 5)); /* > 0 */
    1419              : 
    1420           14 :   if (odd(N)) N++; /* extra precision for free */
    1421           14 :   S = sumpos_init(E, eval, a, N, prec);
    1422           14 :   pol = ZX_div_by_X_1(polzag1(N,N>>1), &dn);
    1423           14 :   s = NULL;
    1424         4466 :   for (k = 0; k < N; k++)
    1425              :   {
    1426         4452 :     GEN t = mulri(gel(S,k+1), gel(pol,k+2));
    1427         4452 :     s = k == 0? t: odd(k)? subrr(s,t): addrr(s,t);
    1428              :   }
    1429           14 :   return gc_leaf(av, divri(s,dn));
    1430              : }
    1431              : 
    1432              : GEN
    1433           91 : sumpos0(GEN a, GEN code, long flag, long prec)
    1434              : {
    1435           91 :   switch(flag)
    1436              :   {
    1437           70 :     case 0: EXPR_WRAP(code, sumpos (EXPR_ARG,a,prec));
    1438           14 :     case 1: EXPR_WRAP(code, sumpos2(EXPR_ARG,a,prec));
    1439            7 :     default: pari_err_FLAG("sumpos");
    1440              :   }
    1441              :   return NULL; /* LCOV_EXCL_LINE */
    1442              : }
    1443              : 
    1444              : /********************************************************************/
    1445              : /**                                                                **/
    1446              : /**            SEARCH FOR REAL ZEROS of an expression              **/
    1447              : /**                                                                **/
    1448              : /********************************************************************/
    1449              : /* Brent's method, [a,b] bracketing interval */
    1450              : GEN
    1451        23429 : zbrent(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec)
    1452              : {
    1453              :   long sig, iter, itmax, bit, bit0;
    1454        23429 :   pari_sp av = avma;
    1455              :   GEN c, d, e, fa, fb, fc;
    1456              : 
    1457        23429 :   if (typ(a) == t_INFINITY && typ(b) != t_INFINITY) swap(a,b);
    1458        23429 :   if (typ(a) == t_INFINITY && typ(b) == t_INFINITY)
    1459              :   {
    1460            7 :     long s = gsigne(eval(E, real_0(prec))), r = 0;
    1461            7 :     if (gidentical(gel(a,1), gel(b,1)))
    1462            0 :       pari_err_DOMAIN("solve", "a and b", "=", a, mkvec2(a, b));
    1463            7 :     a = real_m1(prec); /* domain = R */
    1464            7 :     b = real_1(prec);
    1465              :     for(;;)
    1466              :     {
    1467            7 :       fa = eval(E, a);
    1468            7 :       fb = eval(E, b);
    1469            7 :       if (gsigne(fa) != s)
    1470              :       {
    1471            0 :         if (r) b[1] = evalsigne(-1) | _evalexpo(r-1); else b = real_0(prec);
    1472            0 :         break;
    1473              :       }
    1474            7 :       if (gsigne(fb) != s)
    1475              :       {
    1476            7 :         if (r) a[1] = evalsigne(1) | _evalexpo(r-1); else a = real_0(prec);
    1477            7 :         break;
    1478              :       }
    1479            0 :       r++; setexpo(a, r); setexpo(b, r);
    1480              :     }
    1481            7 :     c = b;
    1482            7 :     goto SOLVE;
    1483              :   }
    1484        23422 :   if (typ(b) == t_INFINITY)
    1485              :   { /* a real, b == [+-]oo */
    1486           28 :     long s, r, minf = inf_get_sign(b) < 0;
    1487              :     GEN inc;
    1488           28 :     if (typ(a) != t_REAL || realprec(a) < prec) a = gtofp(a, prec);
    1489           28 :     fa = eval(E, a);
    1490           28 :     s = gsigne(fa);
    1491           28 :     inc = minf ? real_m1(prec) : real_1(prec);
    1492           28 :     r = gsigne(a) ? expo(a) : 0;
    1493              :     for(;;)
    1494              :     {
    1495          570 :       setexpo(inc, r);
    1496          570 :       b = addrr(a, inc); fb = eval(E, b);
    1497          556 :       if (gsigne(fb) != s) break;
    1498          542 :       a = b; fa = fb; r++;
    1499              :     }
    1500           14 :     if (minf) { c = a; swap(a, b); swap(fa, fb);} else c = b;
    1501           14 :     goto SOLVE;
    1502              :   }
    1503        23394 :   if (typ(a) != t_REAL || realprec(a) < prec) a = gtofp(a, prec);
    1504        23394 :   if (typ(b) != t_REAL || realprec(b) < prec) b = gtofp(b, prec);
    1505        23394 :   sig = cmprr(b, a);
    1506        23394 :   if (!sig) return gc_upto(av, a);
    1507        23394 :   if (sig < 0) swap(a, b);
    1508        23394 :   fa = eval(E, a);
    1509        23394 :   fb = eval(E, b);
    1510        23394 :   if (gsigne(fa)*gsigne(fb) > 0)
    1511            7 :     pari_err_DOMAIN("solve", "f(a)f(b)", ">", gen_0, mkvec2(fa, fb));
    1512        23387 : SOLVE:
    1513        23408 :   bit0 = -prec; bit = 3+bit0; itmax = 1 - 2*bit0;
    1514        23408 :   c = b; fc = fb; e = d = NULL;
    1515       227647 :   for (iter = 1; iter <= itmax; ++iter)
    1516              :   { /* b = current best guess, a = previous one, c auxiliary point
    1517              :      * d = b - a up to sign, e = previous value of d (we use |d| and |e| only)
    1518              :      * fa = f(a), fb = f(b), fc = f(c) */
    1519              :     long bit2, exb;
    1520              :     GEN m;
    1521       227647 :     if (gsigne(fb)*gsigne(fc) > 0) { c = a; fc = fa; e = d = subrr(b, a); }
    1522       227647 :     if (gexpo(fc) < gexpo(fb)) { a = b; b = c; c = a; fa = fb; fb = fc; fc = fa; }
    1523       227647 :     if (gequal0(fb)) break; /*SUCCESS*/
    1524       227562 :     m = subrr(c, b); shiftr_inplace(m, -1);
    1525       227562 :     exb = expo(b);
    1526       227562 :     if (bit < exb)
    1527              :     {
    1528       227506 :       bit2 = bit + exb - 1;
    1529       227506 :       if (expo(m) <= exb + bit0) break; /*SUCCESS*/
    1530              :     }
    1531              :     else
    1532              :     { /* b ~ 0 */
    1533           56 :       bit2 = 2*bit - 1;
    1534           56 :       if (expo(m) <= bit2) break; /*SUCCESS*/
    1535              :     }
    1536              : 
    1537       204239 :     if (expo(e) > bit2 && gexpo(fa) > gexpo(fb))
    1538       161633 :     { /* quadratic interpolation, m != 0, f(b)f(c) < 0 */
    1539       161633 :       GEN min1, min2, p, q, s = gdiv(fb, fa);
    1540       161633 :       if (a == c || equalrr(a,c))
    1541              :       {
    1542       128616 :         p = gmul2n(gmul(m, s), 1);
    1543       128616 :         q = gsubsg(1, s);
    1544              :       }
    1545              :       else
    1546              :       {
    1547        33017 :         GEN r = gdiv(fb, fc), r_1 = gsubgs(r, 1);
    1548        33017 :         q = gdiv(fa, fc);
    1549        33017 :         p = gmul2n(gmul(gsub(q, r), gmul(m, q)), 1);
    1550        33017 :         p = gmul(s, gsub(p, gmul(subrr(b, a), r_1)));
    1551        33017 :         q = gmul(gmul(gsubgs(q, 1), r_1), gsubgs(s, 1));
    1552              :       }
    1553       161633 :       if (gsigne(p) > 0) q = gneg_i(q); else p = gneg_i(p);
    1554       161633 :       min1 = gsub(gmulsg(3, gmul(m,q)), gmul2n(gabs(q,0), bit2));
    1555       161633 :       min2 = gabs(gmul(e, q), 0);
    1556       161633 :       if (gcmp(gmul2n(p, 1), gmin_shallow(min1, min2)) < 0)
    1557       159747 :         { e = d; d = gdiv(p, q); } /* interpolation OK */
    1558              :       else
    1559         1886 :         e = d = m; /* failed, use bisection */
    1560              :     }
    1561        42606 :     else e = d = m; /* bound decreasing too slowly, use bisection */
    1562       204239 :     a = b; fa = fb;
    1563       204239 :     if (d == m) { b = addrr(c, b); shiftr_inplace(b,-1); }
    1564       159747 :     else if (gexpo(d) > bit2) b = gadd(b, d);
    1565        23825 :     else if (gsigne(m) > 0) b = addrr(b, real2n(bit2, LOWDEFAULTPREC));
    1566        10663 :     else                    b = subrr(b, real2n(bit2, LOWDEFAULTPREC));
    1567       204239 :     if (equalrr(a, b)) fb = fa;
    1568              :     else
    1569              :     {
    1570       204232 :       if (realprec(b) < prec) b = rtor(b, prec);
    1571       204232 :       fb = eval(E, b);
    1572              :     }
    1573              :   }
    1574        23408 :   if (iter > itmax) pari_err_IMPL("solve recovery [too many iterations]");
    1575        23408 :   return gc_leaf(av, rcopy(b));
    1576              : }
    1577              : 
    1578              : GEN
    1579           84 : zbrent0(GEN a, GEN b, GEN code, long prec)
    1580           84 : { EXPR_WRAP(code, zbrent(EXPR_ARG, a, b, prec)); }
    1581              : 
    1582              : /* Find zeros of a function in the real interval [a,b] by interval splitting */
    1583              : GEN
    1584          119 : solvestep(void *E, GEN (*f)(void *,GEN), GEN a, GEN b, GEN step, long flag, long prec)
    1585              : {
    1586          119 :   const long ITMAX = 10;
    1587          119 :   pari_sp av = avma;
    1588              :   GEN fa, a0, b0;
    1589          119 :   long sa0, it, bit = prec / 2, ct = 0, s = gcmp(a,b);
    1590              : 
    1591          119 :   if (!s) return gequal0(f(E, a)) ? gcopy(mkvec(a)): cgetg(1,t_VEC);
    1592          119 :   if (s > 0) swap(a, b);
    1593          119 :   if (flag&4)
    1594              :   {
    1595           84 :     if (gcmpgs(step,1)<=0) pari_err_DOMAIN("solvestep","step","<=",gen_1,step);
    1596           84 :     if (gsigne(a) <= 0) pari_err_DOMAIN("solvestep","a","<=",gen_0,a);
    1597              :   }
    1598           35 :   else if (gsigne(step) <= 0)
    1599            7 :     pari_err_DOMAIN("solvestep","step","<=",gen_0,step);
    1600          112 :   a0 = a = gtofp(a, prec); fa = f(E, a);
    1601          112 :   b0 = b = gtofp(b, prec); step = gtofp(step, prec);
    1602          112 :   sa0 = gsigne(fa);
    1603          112 :   if (gexpo(fa) < -bit) sa0 = 0;
    1604          119 :   for (it = 0; it < ITMAX; it++)
    1605              :   {
    1606          119 :     pari_sp av2 = avma;
    1607          119 :     GEN v = cgetg(1, t_VEC);
    1608          119 :     long sa = sa0;
    1609          119 :     a = a0; b = b0;
    1610        37520 :     while (gcmp(a,b) < 0)
    1611              :     {
    1612        37401 :       GEN fc, c = (flag&4)? gmul(a, step): gadd(a, step);
    1613              :       long sc;
    1614        37401 :       if (gcmp(c,b) > 0) c = b;
    1615        37401 :       fc = f(E, c); sc = gsigne(fc);
    1616        37401 :       if (gexpo(fc) < -bit) sc = 0;
    1617        37401 :       if (!sc || sa*sc < 0)
    1618              :       {
    1619        22813 :         GEN z = sc? zbrent(E, f, a, c, prec): c;
    1620              :         long e;
    1621        22813 :         (void)grndtoi(z, &e);
    1622        22813 :         if (e <= -bit) ct = 1;
    1623        22813 :         if ((flag&1) && ((!(flag&8)) || ct)) return gc_upto(av, z);
    1624        22813 :         v = shallowconcat(v, z);
    1625              :       }
    1626        37401 :       a = c; fa = fc; sa = sc;
    1627        37401 :       if (gc_needed(av2,1))
    1628              :       {
    1629           65 :         if (DEBUGMEM>1) pari_warn(warnmem,"solvestep");
    1630           65 :         (void)gc_all(av2, 4, &a, &fa, &v, &step);
    1631              :       }
    1632              :     }
    1633          119 :     if ((!(flag&2) || lg(v) > 1) && (!(flag&8) || ct))
    1634          112 :       return gc_GEN(av, v);
    1635            7 :     step = (flag&4)? sqrtnr(step,4): gmul2n(step, -2);
    1636            7 :     (void)gc_all(av2, 2, &fa, &step);
    1637              :   }
    1638            0 :   pari_err_IMPL("solvestep recovery [too many iterations]");
    1639              :   return NULL;/*LCOV_EXCL_LINE*/
    1640              : }
    1641              : 
    1642              : GEN
    1643           35 : solvestep0(GEN a, GEN b, GEN step, GEN code, long flag, long prec)
    1644           35 : { EXPR_WRAP(code, solvestep(EXPR_ARG, a,b, step, flag, prec)); }
    1645              : 
    1646              : /********************************************************************/
    1647              : /**                     Numerical derivation                       **/
    1648              : /********************************************************************/
    1649              : 
    1650              : struct deriv_data
    1651              : {
    1652              :   GEN code;
    1653              :   GEN args;
    1654              :   GEN def;
    1655              : };
    1656              : 
    1657              : static GEN
    1658          336 : deriv_eval(void *E, GEN x, long prec)
    1659              : {
    1660          336 :  struct deriv_data *data=(struct deriv_data *)E;
    1661          336 :  gel(data->args,1)=x;
    1662          336 :  uel(data->def,1)=1;
    1663          336 :  return closure_callgenvecdefprec(data->code, data->args, data->def, prec);
    1664              : }
    1665              : 
    1666              : /* Rationale: (f(2^-e) - f(-2^-e) + O(2^-b)) / (2 * 2^-e) = f'(0) + O(2^-2e)
    1667              :  * since 2nd derivatives cancel.
    1668              :  *   prec(LHS) = b - e
    1669              :  *   prec(RHS) = 2e, equal when  b = 3e = 3/2 b0 (b0 = required final bitprec)
    1670              :  *
    1671              :  * For f'(x), x far from 0: prec(LHS) = b - e - expo(x)
    1672              :  * --> pr = 3/2 b0 + expo(x) */
    1673              : GEN
    1674          966 : derivnum(void *E, GEN (*eval)(void *, GEN, long), GEN x, long prec)
    1675              : {
    1676          966 :   long newprec, e, ex = gexpo(x), p = precision(x);
    1677          966 :   long b0 = prec2nbits(p? p: prec), b = (long)ceil(b0 * 1.5 + maxss(0,ex));
    1678              :   GEN eps, u, v, y;
    1679          966 :   pari_sp av = avma;
    1680          966 :   newprec = nbits2prec(b + EXTRAPREC64);
    1681          966 :   switch(typ(x))
    1682              :   {
    1683          385 :     case t_REAL:
    1684              :     case t_COMPLEX:
    1685          385 :       x = gprec_w(x, newprec);
    1686              :   }
    1687          966 :   e = b0/2; /* 1/2 required prec (in sig. bits) */
    1688          966 :   b -= e; /* >= b0 */
    1689          966 :   eps = real2n(-e, ex < -e? newprec: nbits2prec(b));
    1690          966 :   u = eval(E, gsub(x, eps), newprec);
    1691          966 :   v = eval(E, gadd(x, eps), newprec);
    1692          966 :   y = gmul2n(gsub(v,u), e-1);
    1693          966 :   return gc_GEN(av, gprec_wtrunc(y, nbits2prec(b0)));
    1694              : }
    1695              : 
    1696              : /* Fornberg interpolation algorithm for finite differences coefficients
    1697              : * using 2N+1 equidistant grid points around 0 [ assume 2N even >= M ].
    1698              : * Compute \delta[m]_{N,i} for all derivation orders m = 0..M such that
    1699              : *   h^m * f^{(m)}(0) = \sum_{i = 0}^n delta[m]_{N,i}  f(a_i) + O(h^{N-m+1}),
    1700              : * for step size h.
    1701              : * Return a = [0,-1,1...,-N,N] and vector of vectors d: d[m+1][i+1]
    1702              : * = w'(a_i) delta[m]_{2N,i}, i = 0..2N */
    1703              : static void
    1704          147 : FD(long M, long N2, GEN *pd, GEN *pa)
    1705              : {
    1706              :   GEN d, a, b, W, F;
    1707          147 :   long N = N2>>1, m, i;
    1708              : 
    1709          147 :   F = cgetg(N2+2, t_VEC);
    1710          147 :   a = cgetg(N2+2, t_VEC);
    1711          147 :   b = cgetg(N+1, t_VEC);
    1712          147 :   gel(a,1) = gen_0;
    1713          749 :   for (i = 1; i <= N; i++)
    1714              :   {
    1715          602 :     gel(a,2*i)   = utoineg(i);
    1716          602 :     gel(a,2*i+1) = utoipos(i);
    1717          602 :     gel(b,i) = sqru(i);
    1718              :   }
    1719              :   /* w = \prod (X - a[i]) = x W(x^2) */
    1720          147 :   W = roots_to_pol(b, 0);
    1721          147 :   gel(F,1) = RgX_inflate(W,2);
    1722          749 :   for (i = 1; i <= N; i++)
    1723              :   {
    1724          602 :     pari_sp av = avma;
    1725              :     GEN r, U, S;
    1726          602 :     U = RgX_inflate(RgX_div_by_X_x(W, gel(b,i), &r), 2);
    1727          602 :     U = RgXn_red_shallow(U, M); /* higher terms not needed */
    1728          602 :     U = RgX_shift_shallow(U,1); /* w(X) / (X^2-a[i]^2) mod X^(M+1) */
    1729          602 :     S = ZX_sub(RgX_shift_shallow(U,1),
    1730          602 :                ZX_Z_mul(U, gel(a,2*i+1)));
    1731          602 :     S = gc_upto(av, S);
    1732          602 :     gel(F,2*i)   = S;
    1733          602 :     gel(F,2*i+1) = ZX_z_unscale(S, -1);
    1734              :   }
    1735              :   /* F[i] = w(X) / (X-a[i]) + O(X^(M+1)) in Z[X] */
    1736          147 :   d = cgetg(M+2, t_VEC);
    1737          714 :   for (m = 0; m <= M; m++)
    1738              :   {
    1739          567 :     GEN v = cgetg(N2+2, t_VEC); /* coeff(F[i],X^m) */
    1740        12278 :     for (i = 0; i <= N2; i++) gel(v, i+1) = gmael(F, i+1, m+2);
    1741          567 :     gel(d,m+1) = v;
    1742              :   }
    1743          147 :   *pd = d;
    1744          147 :   *pa = a;
    1745          147 : }
    1746              : 
    1747              : static void
    1748          399 : chk_ord(long m)
    1749              : {
    1750          399 :   if (m < 0)
    1751           14 :     pari_err_DOMAIN("derivnumk", "derivation order", "<", gen_0, stoi(m));
    1752          385 : }
    1753              : /* m! / N! for m in ind; vecmax(ind) <= N. Result not a GEN if ind contains 0. */
    1754              : static GEN
    1755          147 : vfact(GEN ind, long N, long prec)
    1756              : {
    1757              :   GEN v, iN;
    1758              :   long i, l;
    1759          147 :   ind = vecsmall_uniq(ind); chk_ord(ind[1]); l = lg(ind);
    1760          140 :   iN = invr(itor(mulu_interval(ind[1] + 1, N), prec));
    1761          140 :   v = const_vec(ind[l-1], NULL); gel(v, ind[1]) = iN;
    1762          231 :   for (i = 2; i < l; i++)
    1763           91 :     gel(v, ind[i]) = iN = mulri(iN, mulu_interval(ind[i-1] + 1, ind[i]));
    1764          140 :   return v;
    1765              : }
    1766              : 
    1767              : static GEN
    1768          210 : chk_ind(GEN ind, long *M)
    1769              : {
    1770          210 :   *M = 0;
    1771          210 :   switch(typ(ind))
    1772              :   {
    1773           91 :     case t_INT: ind = mkvecsmall(itos(ind)); break;
    1774            0 :     case t_VECSMALL:
    1775            0 :       if (lg(ind) == 1) return NULL;
    1776            0 :       break;
    1777          112 :     case t_VEC: case t_COL:
    1778          112 :       if (lg(ind) == 1) return NULL;
    1779          105 :       if (RgV_is_ZV(ind)) { ind = ZV_to_zv(ind); break; }
    1780              :       /* fall through */
    1781              :     default:
    1782            7 :       pari_err_TYPE("derivnum", ind);
    1783              :       return NULL; /*LCOV_EXCL_LINE*/
    1784              :   }
    1785          196 :   *M = vecsmall_max(ind); chk_ord(*M); return ind;
    1786              : }
    1787              : GEN
    1788          175 : derivnumk(void *E, GEN (*eval)(void *, GEN, long), GEN x, GEN ind0, long prec)
    1789              : {
    1790              :   GEN A, C, D, DM, T, X, F, v, ind, t;
    1791              :   long M, N, N2, fpr, p, i, pr, l, lA, e, ex, emin, emax, newprec;
    1792          175 :   pari_sp av = avma;
    1793          175 :   int allodd = 1;
    1794              : 
    1795          175 :   ind = chk_ind(ind0, &M); if (!ind) return cgetg(1, t_VEC);
    1796          161 :   l = lg(ind); F = cgetg(l, t_VEC);
    1797          161 :   if (!M) /* silly degenerate case */
    1798              :   {
    1799           14 :     X = eval(E, x, prec);
    1800           28 :     for (i = 1; i < l; i++) { chk_ord(ind[i]); gel(F,i) = X; }
    1801            7 :     if (typ(ind0) == t_INT) F = gel(F,1);
    1802            7 :     return gc_GEN(av, F);
    1803              :   }
    1804          147 :   N2 = 3*M - 1; if (odd(N2)) N2++;
    1805          147 :   N = N2 >> 1;
    1806          147 :   FD(M, N2, &D,&A); /* optimal if 'eval' uses quadratic time */
    1807          147 :   C = vecbinomial(N2); DM = gel(D,M);
    1808          147 :   T = cgetg(N2+2, t_VEC);
    1809              :   /* (2N)! / w'(i) = (2N)! / w'(-i) = (-1)^(N-i) binom(2*N, N-i) */
    1810          147 :   t = gel(C, N+1);
    1811          147 :   gel(T,1) = odd(N)? negi(t): t;
    1812          749 :   for (i = 1; i <= N; i++)
    1813              :   {
    1814          602 :     t = gel(C, N-i+1);
    1815          602 :     gel(T,2*i) = gel(T,2*i+1) = odd(N-i)? negi(t): t;
    1816              :   }
    1817          147 :   N = N2 >> 1; emin = LONG_MAX; emax = 0;
    1818          749 :   for (i = 1; i <= N; i++)
    1819              :   {
    1820          602 :     e = expi(gel(DM,i)) + expi(gel(T,i));
    1821          602 :     if (e < 0) continue; /* 0 */
    1822          511 :     if (e < emin) emin = e;
    1823          280 :     else if (e > emax) emax = e;
    1824              :   }
    1825              : 
    1826          147 :   p = precision(x);
    1827          147 :   fpr = p ? p: prec;
    1828          147 :   e = (fpr + 3*M*log2((double)M)) / (2*M);
    1829          147 :   ex = gexpo(real_i(x));
    1830          147 :   if (ex < 0) ex = 0; /* near 0 */
    1831          147 :   pr = (long)ceil(fpr + e * M); /* ~ 3fpr/2 */
    1832          147 :   newprec = nbits2prec(pr + (emax - emin) + ex + BITS_IN_LONG);
    1833          147 :   switch(typ(x))
    1834              :   {
    1835           28 :     case t_REAL:
    1836              :     case t_COMPLEX:
    1837           28 :       x = gprec_w(x, newprec);
    1838              :   }
    1839          147 :   lA = lg(A); X = cgetg(lA, t_VEC);
    1840          203 :   for (i = 1; i < l; i++)
    1841          154 :     if (!odd(ind[i])) { allodd = 0; break; }
    1842              :   /* if only odd derivation orders, the value at 0 (A[1]) is not needed */
    1843          147 :   gel(X, 1) = gen_0;
    1844         1449 :   for (i = allodd? 2: 1; i < lA; i++)
    1845              :   {
    1846         1302 :     GEN t = eval(E, gadd(x, gmul2n(gel(A,i), -e)), newprec);
    1847         1302 :     t = gmul(t, gel(T,i));
    1848         1302 :     if (!gprecision(t))
    1849          224 :       t = is_scalar_t(typ(t))? gtofp(t, newprec): gmul(t, real_1(newprec));
    1850         1302 :     gel(X,i) = t;
    1851              :   }
    1852              : 
    1853          147 :   v = vfact(ind, N2, nbits2prec(fpr + 32));
    1854          371 :   for (i = 1; i < l; i++)
    1855              :   {
    1856          231 :     long m = ind[i];
    1857          231 :     GEN t = RgV_dotproduct(gel(D,m+1), X);
    1858          231 :     gel(F,i) = gmul(t, gmul2n(gel(v, m), e*m));
    1859              :   }
    1860          140 :   if (typ(ind0) == t_INT) F = gel(F,1);
    1861          140 :   return gc_GEN(av, F);
    1862              : }
    1863              : /* v(t') */
    1864              : static long
    1865           14 : rfrac_val_deriv(GEN t)
    1866              : {
    1867           14 :   long v = varn(gel(t,2));
    1868           14 :   return gvaluation(deriv(t, v), pol_x(v));
    1869              : }
    1870              : 
    1871              : GEN
    1872         1197 : derivfunk(void *E, GEN (*eval)(void *, GEN, long), GEN x, GEN ind0, long prec)
    1873              : {
    1874              :   pari_sp av;
    1875              :   GEN ind, xp, ixp, F, G;
    1876              :   long i, l, vx, M;
    1877         1197 :   if (!ind0) return derivfun(E, eval, x, prec);
    1878          210 :   switch(typ(x))
    1879              :   {
    1880          147 :   case t_REAL: case t_INT: case t_FRAC: case t_COMPLEX:
    1881          147 :     return derivnumk(E,eval, x, ind0, prec);
    1882           21 :   case t_POL:
    1883           21 :     ind = chk_ind(ind0,&M); if (!ind) return cgetg(1,t_VEC);
    1884           21 :     xp = RgX_deriv(x);
    1885           21 :     x = RgX_to_ser(x, precdl+2 + M * (1+RgX_val(xp)));
    1886           21 :     break;
    1887            7 :   case t_RFRAC:
    1888            7 :     ind = chk_ind(ind0,&M); if (!ind) return cgetg(1,t_VEC);
    1889            7 :     x = rfrac_to_ser_i(x, precdl+2 + M * (1+rfrac_val_deriv(x)));
    1890            7 :     xp = derivser(x);
    1891            7 :     break;
    1892            7 :   case t_SER:
    1893            7 :     ind = chk_ind(ind0,&M); if (!ind) return cgetg(1,t_VEC);
    1894            7 :     xp = derivser(x);
    1895            7 :     break;
    1896           28 :   default: pari_err_TYPE("numerical derivation",x);
    1897              :     return NULL; /*LCOV_EXCL_LINE*/
    1898              :   }
    1899           35 :   av = avma; vx = varn(x);
    1900           35 :   ixp = M? ginv(xp): NULL;
    1901           35 :   F = cgetg(M+2, t_VEC);
    1902           35 :   gel(F,1) = eval(E, x, prec);
    1903          126 :   for (i = 1; i <= M; i++) gel(F,i+1) = gmul(deriv(gel(F,i),vx), ixp);
    1904           35 :   l = lg(ind); G = cgetg(l, t_VEC);
    1905           70 :   for (i = 1; i < l; i++)
    1906              :   {
    1907           35 :     long m = ind[i]; chk_ord(m);
    1908           35 :     gel(G,i) = gel(F,m+1);
    1909              :   }
    1910           35 :   if (typ(ind0) == t_INT) G = gel(G,1);
    1911           35 :   return gc_GEN(av, G);
    1912              : }
    1913              : 
    1914              : GEN
    1915          987 : derivfun(void *E, GEN (*eval)(void *, GEN, long), GEN x, long prec)
    1916              : {
    1917          987 :   pari_sp av = avma;
    1918              :   GEN xp;
    1919              :   long vx;
    1920          987 :   switch(typ(x))
    1921              :   {
    1922          966 :   case t_REAL: case t_INT: case t_FRAC: case t_COMPLEX:
    1923          966 :     return derivnum(E,eval, x, prec);
    1924            7 :   case t_POL:
    1925            7 :     xp = RgX_deriv(x);
    1926            7 :     x = RgX_to_ser(x, precdl+2+ (1 + RgX_val(xp)));
    1927            7 :     break;
    1928            7 :   case t_RFRAC:
    1929            7 :     x = rfrac_to_ser_i(x, precdl+2+ (1 + rfrac_val_deriv(x)));
    1930              :     /* fall through */
    1931           14 :   case t_SER:
    1932           14 :     xp = derivser(x);
    1933           14 :     break;
    1934            0 :   default: pari_err_TYPE("formal derivation",x);
    1935              :     return NULL; /*LCOV_EXCL_LINE*/
    1936              :   }
    1937           21 :   vx = varn(x);
    1938           21 :   return gc_upto(av, gdiv(deriv(eval(E, x, prec),vx), xp));
    1939              : }
    1940              : 
    1941              : GEN
    1942           21 : laurentseries(void *E, GEN (*f)(void*,GEN x, long), long M, long v, long prec)
    1943              : {
    1944           21 :   pari_sp av = avma;
    1945              :   long d;
    1946              : 
    1947           21 :   if (v < 0) v = 0;
    1948           21 :   d = maxss(M+1,1);
    1949              :   for (;;)
    1950           14 :   {
    1951              :     long i, dr, vr;
    1952              :     GEN s;
    1953           35 :     s = cgetg(d+2, t_SER); s[1] = evalsigne(1) | evalvalser(1) | evalvarn(v);
    1954          245 :     gel(s, 2) = gen_1; for (i = 3; i <= d+1; i++) gel(s, i) = gen_0;
    1955           35 :     s = f(E, s, prec);
    1956           35 :     if (typ(s) != t_SER || varn(s) != v) pari_err_TYPE("laurentseries", s);
    1957           35 :     vr = valser(s);
    1958           35 :     if (M < vr) { set_avma(av); return zeroser(v, M); }
    1959           35 :     dr = lg(s) + vr - 3 - M;
    1960           35 :     if (dr >= 0) return gc_upto(av, s);
    1961           14 :     set_avma(av); d -= dr;
    1962              :   }
    1963              : }
    1964              : static GEN
    1965           35 : _evalclosprec(void *E, GEN x, long prec)
    1966              : {
    1967              :   GEN s;
    1968           35 :   push_localprec(prec); s = closure_callgen1((GEN)E, x);
    1969           35 :   pop_localprec(); return s;
    1970              : }
    1971              : #define CLOS_ARGPREC __E, &_evalclosprec
    1972              : GEN
    1973           35 : laurentseries0(GEN f, long M, long v, long prec)
    1974              : {
    1975           35 :   if (typ(f) != t_CLOSURE || closure_arity(f) != 1 || closure_is_variadic(f))
    1976           14 :     pari_err_TYPE("laurentseries",f);
    1977           21 :   EXPR_WRAP(f, laurentseries(CLOS_ARGPREC,M,v,prec));
    1978              : }
    1979              : 
    1980              : GEN
    1981         1085 : derivnum0(GEN a, GEN code, GEN ind, long prec)
    1982         1085 : { EXPR_WRAP(code, derivfunk(EXPR_ARGPREC,a,ind,prec)); }
    1983              : 
    1984              : GEN
    1985          112 : derivfun0(GEN args, GEN def, GEN code, long k, long prec)
    1986              : {
    1987          112 :   pari_sp av = avma;
    1988              :   struct deriv_data E;
    1989              :   GEN z;
    1990          112 :   E.code=code; E.args=args; E.def=def;
    1991          112 :   z = gel(derivfunk((void*)&E, deriv_eval, gel(args,1), mkvecs(k), prec),1);
    1992           84 :   return gc_GEN(av, z);
    1993              : }
    1994              : 
    1995              : /********************************************************************/
    1996              : /**                   Numerical extrapolation                      **/
    1997              : /********************************************************************/
    1998              : /* [u(n), u <= N] */
    1999              : static GEN
    2000          140 : get_u(void *E, GEN (*f)(void *, GEN, long), long N, long prec)
    2001              : {
    2002              :   long n;
    2003              :   GEN u;
    2004          140 :   if (f)
    2005              :   {
    2006          126 :     GEN v = f(E, utoipos(N), prec);
    2007          126 :     u = cgetg(N+1, t_VEC);
    2008          126 :     if (typ(v) != t_VEC || lg(v) != N+1) { gel(u,N) = v; v = NULL; }
    2009              :     else
    2010              :     {
    2011           14 :       GEN w = f(E, gen_1, LOWDEFAULTPREC);
    2012           14 :       if (typ(w) != t_VEC || lg(w) != 2) { gel(u,N) = v; v = NULL; }
    2013              :     }
    2014          126 :     if (v) u = v;
    2015              :     else
    2016         9702 :       for (n = 1; n < N; n++) gel(u,n) = f(E, utoipos(n), prec);
    2017              :   }
    2018              :   else
    2019              :   {
    2020           14 :     GEN v = (GEN)E;
    2021           14 :     long t = lg(v)-1;
    2022           14 :     if (t < N) pari_err_COMPONENT("limitnum","<",stoi(N), stoi(t));
    2023           14 :     u = vecslice(v, 1, N);
    2024              :   }
    2025        12236 :   for (n = 1; n <= N; n++)
    2026              :   {
    2027        12096 :     GEN un = gel(u,n);
    2028        12096 :     if (is_rational_t(typ(un))) gel(u,n) = gtofp(un, prec);
    2029              :   }
    2030          140 :   return u;
    2031              : }
    2032              : 
    2033              : struct limit
    2034              : {
    2035              :   long prec; /* working accuracy */
    2036              :   long N; /* number of terms */
    2037              :   GEN na; /* [n^alpha, n <= N] */
    2038              :   GEN coef; /* or NULL (alpha != 1) */
    2039              : };
    2040              : 
    2041              : static GEN
    2042        20822 : _gi(void *E, GEN x)
    2043              : {
    2044        20822 :   GEN A = (GEN)E, y = gsubgs(x, 1);
    2045        20822 :   if (gequal0(y)) return A;
    2046        20808 :   return gdiv(gsubgs(gpow(x, A, LOWDEFAULTPREC), 1), y);
    2047              : }
    2048              : static GEN
    2049          166 : _g(void *E, GEN x)
    2050              : {
    2051          166 :   GEN D = (GEN)E, A = gel(D,1), T = gel(D,2);
    2052          166 :   const long prec = LOWDEFAULTPREC;
    2053          166 :   return gadd(glog(x,prec), intnum((void*)A, _gi, gen_0, gaddgs(x,1), T, prec));
    2054              : }
    2055              : 
    2056              : /* solve log(b) + int_0^{b+1} (x^(1/a)-1) / (x-1) dx = 0, b in [0,1]
    2057              :  * return -log_2(b), rounded up */
    2058              : static double
    2059          140 : get_accu(GEN a)
    2060              : {
    2061          140 :   pari_sp av = avma;
    2062          140 :   const long prec = LOWDEFAULTPREC;
    2063          140 :   const double We2 = 1.844434455794; /* (W(1/e) + 1) / log(2) */
    2064              :   GEN b, T;
    2065          140 :   if (!a) return We2;
    2066           49 :   if (typ(a) == t_INT) switch(itos_or_0(a))
    2067              :   {
    2068            0 :     case 1: return We2;
    2069           21 :     case 2: return 1.186955309668;
    2070            0 :     case 3: return 0.883182331990;
    2071              :   }
    2072           28 :   else if (typ(a) == t_FRAC && equali1(gel(a,1))) switch(itos_or_0(gel(a,2)))
    2073              :   {
    2074           14 :     case 2: return 2.644090500290;
    2075            0 :     case 3: return 3.157759214459;
    2076            0 :     case 4: return 3.536383237500;
    2077              :   }
    2078           14 :   T = intnuminit(gen_0, gen_1, 0, prec);
    2079           14 :   b = zbrent((void*)mkvec2(ginv(a), T), &_g, dbltor(1E-5), gen_1, prec);
    2080           14 :   return gc_double(av, -dbllog2r(b));
    2081              : }
    2082              : 
    2083              : static double
    2084          147 : get_c(GEN a)
    2085              : {
    2086          147 :   double A = a? gtodouble(a): 1.0;
    2087          147 :   if (A <= 0) pari_err_DOMAIN("limitnum","alpha","<=",gen_0, a);
    2088          140 :   if (A >= 2) return 0.2270;
    2089          105 :   if (A >= 1) return 0.3318;
    2090           14 :   if (A >= 0.5) return 0.6212;
    2091            0 :   if (A >= 0.3333) return 1.2;
    2092            0 :   return 3; /* only tested for A >= 0.25 */
    2093              : }
    2094              : static void
    2095          133 : limit_Nprec(struct limit *L, GEN alpha, long prec)
    2096              : {
    2097          133 :   L->N = ceil(get_c(alpha) * prec);
    2098          126 :   L->prec = nbits2prec(prec + (long)ceil(get_accu(alpha) * L->N));
    2099          126 : }
    2100              : /* solve x - a log(x) = b; a, b >= 3 */
    2101              : static double
    2102           14 : solvedivlog(double a, double b) { return dbllemma526(a,1,1,b); }
    2103              : 
    2104              : /* #u > 1, prod_{j != i} u[i] - u[j] */
    2105              : static GEN
    2106         3003 : proddiff(GEN u, long i)
    2107              : {
    2108         3003 :   pari_sp av = avma;
    2109         3003 :   long l = lg(u), j;
    2110         3003 :   GEN p = NULL;
    2111         3003 :   if (i == 1)
    2112              :   {
    2113           28 :     p = gsub(gel(u,1), gel(u,2));
    2114         2975 :     for (j = 3; j < l; j++)
    2115         2947 :       p = gmul(p, gsub(gel(u,i), gel(u,j)));
    2116              :   }
    2117              :   else
    2118              :   {
    2119         2975 :     p = gsub(gel(u,i), gel(u,1));
    2120       367346 :     for (j = 2; j < l; j++)
    2121       364371 :       if (j != i) p = gmul(p, gsub(gel(u,i), gel(u,j)));
    2122              :   }
    2123         3003 :   return gc_upto(av, p);
    2124              : }
    2125              : static GEN
    2126         1883 : vecpows(GEN x, long N) { pari_APPLY_same(gpowgs(gel(x,i), N)); }
    2127              : 
    2128              : static void
    2129          140 : limit_init(struct limit *L, GEN alpha, int asymp)
    2130              : {
    2131          140 :   long n, N = L->N, a = 0;
    2132          140 :   GEN c, v, T = NULL;
    2133              : 
    2134          140 :   if (!alpha) a = 1;
    2135           49 :   else if (typ(alpha) == t_INT)
    2136              :   {
    2137           21 :     a = itos_or_0(alpha);
    2138           21 :     if (a > 2) a = 0;
    2139              :   }
    2140           28 :   else if (typ(alpha) == t_FRAC)
    2141              :   {
    2142           14 :     long na = itos_or_0(gel(alpha,1)), da = itos_or_0(gel(alpha,2));
    2143           14 :     if (da && na && da <= 4 && na <= 4)
    2144              :     { /* don't bother with other cases */
    2145           14 :       long e = (N-1) % da, k = (N-1) / da;
    2146           14 :       if (e) { N += da - e; k++; } /* N = 1 (mod d) => simpler ^ (n/d)(N-1) */
    2147           14 :       L->N = N;
    2148           14 :       T = vecpowuu(N, na * k);
    2149              :     }
    2150              :   }
    2151          140 :   L->coef = v = cgetg(N+1, t_VEC);
    2152          140 :   if (!a)
    2153              :   {
    2154           28 :     long prec2 = gprecision(alpha);
    2155              :     GEN u;
    2156           28 :     if (prec2 && prec2 < L->prec) alpha = gprec_w(alpha, L->prec);
    2157           28 :     L->na = u = vecpowug(N, alpha, L->prec);
    2158           28 :     if (!T) T = vecpows(u, N-1);
    2159         3031 :     for (n = 1; n <= N; n++) gel(v,n) = gdiv(gel(T,n), proddiff(u,n));
    2160           28 :     return;
    2161              :   }
    2162          112 :   L->na = asymp? vecpowuu(N, a): NULL;
    2163          112 :   c = mpfactr(N-1, L->prec);
    2164          112 :   if (a == 1)
    2165              :   {
    2166           91 :     c = invr(c);
    2167           91 :     gel(v,1) = c; if (!odd(N)) togglesign(c);
    2168         7651 :     for (n = 2; n <= N; n++) gel(v,n) = divru(mulrs(gel(v,n-1), n-1-N), n);
    2169              :   }
    2170              :   else
    2171              :   { /* a = 2 */
    2172           21 :     c = invr(mulru(sqrr(c), (N*(N+1)) >> 1));
    2173           21 :     gel(v,1) = c; if (!odd(N)) togglesign(c);
    2174         1442 :     for (n = 2; n <= N; n++) gel(v,n) = divru(mulrs(gel(v,n-1), n-1-N), N+n);
    2175              :   }
    2176          112 :   T = vecpowuu(N, a*N);
    2177         9093 :   for (n = 2; n <= N; n++) gel(v,n) = mulri(gel(v,n), gel(T,n));
    2178              : }
    2179              : 
    2180              : /* Zagier/Lagrange extrapolation */
    2181              : static GEN
    2182          983 : limitnum_i(struct limit *L, GEN u, long prec)
    2183          983 : { return gprec_w(RgV_dotproduct(u,L->coef), prec); }
    2184              : GEN
    2185           84 : limitnum(void *E, GEN (*f)(void *, GEN, long), GEN alpha, long prec)
    2186              : {
    2187           84 :   pari_sp av = avma;
    2188              :   struct limit L;
    2189              :   GEN u;
    2190           84 :   limit_Nprec(&L, alpha, prec);
    2191           77 :   limit_init(&L, alpha, 0);
    2192           77 :   u = get_u(E, f, L.N, L.prec);
    2193           77 :   return gc_GEN(av, limitnum_i(&L, u, prec));
    2194              : }
    2195              : typedef GEN (*LIMIT_FUN)(void*,GEN,long);
    2196              : static LIMIT_FUN
    2197          161 : get_fun(GEN u, const char *s)
    2198              : {
    2199          161 :   switch(typ(u))
    2200              :   {
    2201           14 :     case t_COL: case t_VEC: break;
    2202          133 :     case t_CLOSURE: return gp_callprec;
    2203           14 :     default: pari_err_TYPE(s, u);
    2204              :   }
    2205           14 :   return NULL;
    2206              : }
    2207              : GEN
    2208           91 : limitnum0(GEN u, GEN alpha, long prec)
    2209           91 : { return limitnum((void*)u,get_fun(u, "limitnum"), alpha, prec); }
    2210              : 
    2211              : GEN
    2212           49 : asympnum(void *E, GEN (*f)(void *, GEN, long), GEN alpha, long prec)
    2213              : {
    2214           49 :   const long MAX = 100;
    2215           49 :   pari_sp av = avma;
    2216           49 :   GEN u, A = cgetg(MAX+1, t_VEC);
    2217           49 :   long i, B = prec2nbits(prec);
    2218           49 :   double LB = 0.9*expu(B); /* 0.9 and 0.95 below are heuristic */
    2219              :   struct limit L;
    2220           49 :   limit_Nprec(&L, alpha, prec);
    2221           49 :   if (alpha) LB *= gtodouble(alpha);
    2222           49 :   limit_init(&L, alpha, 1);
    2223           49 :   u = get_u(E, f, L.N, L.prec);
    2224          906 :   for(i = 1; i <= MAX; i++)
    2225              :   {
    2226          906 :     GEN a, v, q, s = limitnum_i(&L, u, prec);
    2227              :     long n;
    2228              :     /* NOT bestappr: lindep properly ignores the lower bits */
    2229          906 :     v = lindep_bit(mkvec2(gen_1, s), maxss((long)(0.95*floor(B - i*LB)), 32));
    2230          906 :     if (lg(v) == 1) break;
    2231          899 :     q = gel(v,2); if (!signe(q)) break;
    2232          899 :     a = gdiv(negi(gel(v,1)), q);
    2233          899 :     s = gsub(s, a);
    2234              :     /* |s|q^2 > eps */
    2235          899 :     if (!gequal0(s) && gexpo(s) + 2*expi(q) > -17) break;
    2236          857 :     gel(A,i) = a;
    2237        82293 :     for (n = 1; n <= L.N; n++) gel(u,n) = gmul(gsub(gel(u,n), a), gel(L.na,n));
    2238              :   }
    2239           49 :   setlg(A,i); return gc_GEN(av, A);
    2240              : }
    2241              : GEN
    2242           14 : asympnumraw(void *E, GEN (*f)(void *,GEN,long), long LIM, GEN alpha, long prec)
    2243              : {
    2244           14 :   pari_sp av = avma;
    2245              :   double c, d, al;
    2246              :   long i, B;
    2247              :   GEN u, A;
    2248              :   struct limit L;
    2249              : 
    2250           14 :   if (LIM < 0) return cgetg(1, t_VEC);
    2251           14 :   c = get_c(alpha);
    2252           14 :   d = get_accu(alpha);
    2253           14 :   al = alpha? gtodouble(alpha): 1.0;
    2254           14 :   B = prec2nbits(prec);
    2255           14 :   L.N = ceil(solvedivlog(c * al * LIM / M_LN2, c * B));
    2256           14 :   L.prec = nbits2prec(ceil(B + L.N / c + d * L.N));
    2257           14 :   limit_init(&L, alpha, 1);
    2258           14 :   u = get_u(E, f, L.N, L.prec);
    2259           14 :   A = cgetg(LIM+2, t_VEC);
    2260          217 :   for(i = 0; i <= LIM; i++)
    2261              :   {
    2262          203 :     GEN a = RgV_dotproduct(u,L.coef);
    2263              :     long n;
    2264        34461 :     for (n = 1; n <= L.N; n++)
    2265        34258 :       gel(u,n) = gprec_wensure(gmul(gsub(gel(u,n), a), gel(L.na,n)), L.prec);
    2266          203 :     gel(A,i+1) = gprec_wtrunc(a, prec);
    2267              :   }
    2268           14 :   return gc_GEN(av, A);
    2269              : }
    2270              : GEN
    2271           56 : asympnum0(GEN u, GEN alpha, long prec)
    2272           56 : { return asympnum((void*)u,get_fun(u, "asympnum"), alpha, prec); }
    2273              : GEN
    2274           14 : asympnumraw0(GEN u, long LIM, GEN alpha, long prec)
    2275           14 : { return asympnumraw((void*)u,get_fun(u, "asympnumraw"), LIM, alpha, prec); }
        

Generated by: LCOV version 2.0-1