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 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 - kernel/none - level1.h (source / functions) Hit Total Coverage
Test: PARI/GP v2.8.0 lcov report (development 19357-d770f77) Lines: 536 697 76.9 %
Date: 2016-08-27 06:11:27 Functions: 192 255 75.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #line 2 "../src/kernel/none/level1.h"
       2             : /* Copyright (C) 2000  The PARI group.
       3             : 
       4             : This file is part of the PARI/GP package.
       5             : 
       6             : PARI/GP is free software; you can redistribute it and/or modify it under the
       7             : terms of the GNU General Public License as published by the Free Software
       8             : Foundation. 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             : /* This file defines "level 1" kernel functions.
      16             :  * These functions can be inline; they are also defined externally in
      17             :  * mpinl.c, which includes this file and never needs to be changed */
      18             : 
      19             : INLINE long
      20 41756491710 : evallg(long x)
      21             : {
      22 41756491710 :   if (x & ~LGBITS) pari_err_OVERFLOW("lg()");
      23 41761090315 :   return _evallg(x);
      24             : }
      25             : INLINE long
      26    11961356 : evalvalp(long x)
      27             : {
      28    11961356 :   long v = _evalvalp(x);
      29    11961356 :   if (v & ~VALPBITS) pari_err_OVERFLOW("valp()");
      30    11961354 :   return v;
      31             : }
      32             : INLINE long
      33  6516553643 : evalexpo(long x)
      34             : {
      35  6516553643 :   long v = _evalexpo(x);
      36  6516553643 :   if (v & ~EXPOBITS) pari_err_OVERFLOW("expo()");
      37  6516553643 :   return v;
      38             : }
      39             : INLINE long
      40     1278964 : evalprecp(long x)
      41             : {
      42     1278964 :   long v = _evalprecp(x);
      43     1278964 :   if (x & ~((1UL<<(BITS_IN_LONG-VALPnumBITS))-1)) pari_err_OVERFLOW("precp()");
      44     1278965 :   return v;
      45             : }
      46             : 
      47             : INLINE int
      48   134607282 : varncmp(long x, long y)
      49             : {
      50   134607282 :   if (varpriority[x] < varpriority[y]) return  1;
      51   105076899 :   if (varpriority[x] > varpriority[y]) return -1;
      52    55241180 :   return 0;
      53             : }
      54             : 
      55             : /* Inhibit some area gerepile-wise: declare it to be a non recursive
      56             :  * type, of length l. Thus gerepile won't inspect the zone, just copy it.
      57             :  * For the following situation:
      58             :  *   z = cgetg(t,a); av = avma; garbage(); ltop = avma;
      59             :  *   for (i=1; i<HUGE; i++) gel(z,i) = blah();
      60             :  *   stackdummy(av,ltop);
      61             :  * loses (av-ltop) words but save a costly gerepile. */
      62             : INLINE void
      63  1597097534 : stackdummy(pari_sp av, pari_sp ltop) {
      64  1597097534 :   long l = ((GEN)av) - ((GEN)ltop);
      65  1597097534 :   if (l > 0) {
      66   610612979 :     GEN z = (GEN)ltop;
      67   610612979 :     z[0] = evaltyp(t_VECSMALL) | evallg(l);
      68             : #ifdef DEBUG
      69             :     { long i; for (i = 1; i < l; i++) z[i] = 0; }
      70             : #endif
      71             :   }
      72  1597486569 : }
      73             : INLINE void
      74    14634150 : fixlg(GEN x, long ly) {
      75    14634150 :   long lx = lg(x), l = lx - ly;
      76    14634150 :   if (l > 0)
      77             :   { /* stackdummy(x+lx, x+ly) */
      78        7444 :     GEN z = x + ly;
      79        7444 :     z[0] = evaltyp(t_VECSMALL) | evallg(l);
      80        7444 :     setlg(x, ly);
      81             : #ifdef DEBUG
      82             :     { long i; for (i = 1; i < l; i++) z[i] = 0; }
      83             : #endif
      84             :   }
      85    14634150 : }
      86             : /* update lg(z) before affrr(y, z)  [ to cater for precision loss ]*/
      87             : INLINE void
      88    14628833 : affrr_fixlg(GEN y, GEN z) { fixlg(z, lg(y)); affrr(y, z); }
      89             : 
      90             : /*******************************************************************/
      91             : /*                                                                 */
      92             : /*                       ALLOCATE ON STACK                         */
      93             : /*                                                                 */
      94             : /*******************************************************************/
      95             : INLINE GEN
      96 39343628791 : new_chunk(size_t x) /* x is a number of longs */
      97             : {
      98 39343628791 :   GEN z = ((GEN) avma) - x;
      99             :   CHECK_CTRLC
     100 39343628791 :   if (x > (avma-pari_mainstack->bot) / sizeof(long))
     101           0 :     new_chunk_resize(x);
     102 39354569302 :   avma = (pari_sp)z;
     103             : #ifdef MEMSTEP
     104             :   if (DEBUGMEM && pari_mainstack->memused != DISABLE_MEMUSED) {
     105             :     long d = (long)pari_mainstack->memused - (long)z;
     106             :     if (labs(d) > 4*MEMSTEP)
     107             :     {
     108             :       pari_mainstack->memused = (pari_sp)z;
     109             :       err_printf("...%4.0lf Mbytes used\n",
     110             :                 (pari_mainstack->top-pari_mainstack->memused)/1048576.);
     111             :     }
     112             :   }
     113             : #endif
     114 39354569302 :   return z;
     115             : }
     116             : 
     117             : INLINE char *
     118     4168183 : stack_malloc(size_t N)
     119             : {
     120     4168183 :   long n = nchar2nlong(N);
     121     4168183 :   return (char*)new_chunk(n);
     122             : }
     123             : 
     124             : INLINE char *
     125       21653 : stack_calloc(size_t N)
     126             : {
     127       21653 :   char *p = stack_malloc(N);
     128       21653 :   memset(p, 0, N); return p;
     129             : }
     130             : 
     131             : /* cgetg(lg(x), typ(x)), set *lx. Implicit unsetisclone() */
     132             : INLINE GEN
     133   332316184 : cgetg_copy(GEN x, long *plx) {
     134             :   GEN y;
     135   332316184 :   *plx = lg(x); y = new_chunk((size_t)*plx);
     136   332315943 :   y[0] = x[0] & (TYPBITS|LGBITS); return y;
     137             : }
     138             : INLINE GEN
     139       31654 : cgetg_block(long x, long y)
     140             : {
     141       31654 :   GEN z = newblock((size_t)x);
     142       31654 :   z[0] = evaltyp(y) | evallg(x);
     143       31654 :   return z;
     144             : }
     145             : INLINE GEN
     146  4133737267 : cgetg(long x, long y)
     147             : {
     148  4133737267 :   GEN z = new_chunk((size_t)x);
     149  4134653012 :   z[0] = evaltyp(y) | evallg(x);
     150  4132318167 :   return z;
     151             : }
     152             : INLINE GEN
     153 13187955611 : cgeti(long x)
     154             : {
     155 13187955611 :   GEN z = new_chunk((size_t)x);
     156 13174590619 :   z[0] = evaltyp(t_INT) | evallg(x);
     157 13164708787 :   return z;
     158             : }
     159             : INLINE GEN
     160  8092857915 : cgetipos(long x)
     161             : {
     162  8092857915 :   GEN z = cgeti(x);
     163  8091593780 :   z[1] = evalsigne(1) | evallgefint(x);
     164  8091593780 :   return z;
     165             : }
     166             : INLINE GEN
     167   202563777 : cgetineg(long x)
     168             : {
     169   202563777 :   GEN z = cgeti(x);
     170   202563769 :   z[1] = evalsigne(-1) | evallgefint(x);
     171   202563769 :   return z;
     172             : }
     173             : INLINE GEN
     174        2682 : cgetr_block(long x)
     175             : {
     176        2682 :   GEN z = newblock((size_t)x);
     177        2682 :   z[0] = evaltyp(t_REAL) | evallg(x);
     178        2682 :   return z;
     179             : }
     180             : INLINE GEN
     181  6694812424 : cgetr(long x)
     182             : {
     183  6694812424 :   GEN z = new_chunk((size_t)x);
     184  6694812424 :   z[0] = evaltyp(t_REAL) | evallg(x);
     185  6694812424 :   return z;
     186             : }
     187             : 
     188             : /*******************************************************************/
     189             : /*                                                                 */
     190             : /*                     COPY, NEGATION, ABSOLUTE VALUE              */
     191             : /*                                                                 */
     192             : /*******************************************************************/
     193             : /* cannot do memcpy because sometimes x and y overlap */
     194             : INLINE GEN
     195  1087502855 : leafcopy(GEN x)
     196             : {
     197  1087502855 :   register long lx = lg(x);
     198  1087502855 :   GEN y = new_chunk(lx); /* can't use cgetg_copy, in case x,y overlap */
     199  1087508024 :   while (--lx > 0) y[lx] = x[lx];
     200  1087508024 :   y[0] = x[0] & (TYPBITS|LGBITS); return y;
     201             : }
     202             : INLINE GEN
     203  4207201131 : icopy(GEN x)
     204             : {
     205  4207201131 :   long i = lgefint(x), lx = i;
     206  4207201131 :   GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */
     207  4210043714 :   while (--i > 0) y[i] = x[i];
     208  4210043714 :   y[0] = evaltyp(t_INT) | evallg(lx);
     209  4208020851 :   return y;
     210             : }
     211             : INLINE GEN
     212    39413109 : icopyspec(GEN x, long nx)
     213             : {
     214    39413109 :   long i = nx+2, lx = i;
     215    39413109 :   GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */
     216    39413081 :   x -= 2; while (--i >= 2) y[i] = x[i];
     217    39413081 :   y[1] = evalsigne(1) | evallgefint(lx);
     218    39413081 :   y[0] = evaltyp(t_INT) | evallg(lx);
     219    39413061 :   return y;
     220             : }
     221   176167288 : INLINE GEN rcopy(GEN x) { return leafcopy(x); }
     222     1151189 : INLINE GEN mpcopy(GEN x) { return leafcopy(x); }
     223             : 
     224             : INLINE GEN
     225   258640992 : mpabs(GEN x) { GEN y = leafcopy(x); setabssign(y); return y; }
     226             : INLINE GEN
     227         294 : mpabs_shallow(GEN x) { return signe(x) < 0? mpabs(x): x; }
     228   214823997 : INLINE GEN absi(GEN x) { return mpabs(x); }
     229      108351 : INLINE GEN absi_shallow(GEN x) { return signe(x) < 0? negi(x): x; }
     230    29614196 : INLINE GEN absr(GEN x) { return mpabs(x); }
     231             : 
     232             : INLINE GEN
     233   307957189 : mpneg(GEN x) { GEN y = leafcopy(x); togglesign(y); return y; }
     234   212201828 : INLINE GEN negi(GEN x) { return mpneg(x); }
     235     1159511 : INLINE GEN negr(GEN x) { return mpneg(x); }
     236             : 
     237             : /* negate in place */
     238             : INLINE void
     239   777508821 : togglesign(GEN x) { if (x[1] & SIGNBITS) { x[1] ^= HIGHBIT; } }
     240             : INLINE void
     241   289784980 : setabssign(GEN x) { x[1] &= ~HIGHBIT; }
     242             : /* negate in place, except universal constants */
     243             : INLINE void
     244    41413725 : togglesign_safe(GEN *px)
     245             : {
     246    41413725 :   switch(*px - gen_1) /* gen_1, gen_2, gen_m1, gen_m2 */
     247             :   {
     248      827133 :     case 0: *px = gen_m1; break;
     249           0 :     case 3: *px = gen_m2;  break;
     250      191932 :     case 6: *px = gen_1; break;
     251           0 :     case 9: *px = gen_2;  break;
     252    40394660 :     default: togglesign(*px);
     253             :   }
     254    41413725 : }
     255             : /* setsigne(y, signe(x)) */
     256             : INLINE void
     257           0 : affectsign(GEN x, GEN y)
     258             : {
     259           0 :   y[1] = (x[1] & SIGNBITS) | (y[1] & ~SIGNBITS);
     260           0 : }
     261             : /* copies sign in place, except for universal constants */
     262             : INLINE void
     263     5172659 : affectsign_safe(GEN x, GEN *py)
     264             : {
     265     5172659 :   if (((*py)[1] ^ x[1]) & HIGHBIT) togglesign_safe(py);
     266     5172659 : }
     267             : /*******************************************************************/
     268             : /*                                                                 */
     269             : /*                     GEN -> LONG, LONG -> GEN                    */
     270             : /*                                                                 */
     271             : /*******************************************************************/
     272             : /* assume x != 0, return -x as a t_INT */
     273             : INLINE GEN
     274   202429279 : utoineg(ulong x) { GEN y = cgetineg(3); y[2] = x; return y; }
     275             : /* assume x != 0, return utoi(x) */
     276             : INLINE GEN
     277  7062439660 : utoipos(ulong x) { GEN y = cgetipos(3); y[2] = x; return y; }
     278             : INLINE GEN
     279  6067624098 : utoi(ulong x) { return x? utoipos(x): gen_0; }
     280             : INLINE GEN
     281   282766900 : stoi(long x)
     282             : {
     283   282766900 :   if (!x) return gen_0;
     284   186727884 :   return x > 0? utoipos((ulong)x): utoineg((ulong)-x);
     285             : }
     286             : 
     287             : /* x 2^BIL + y */
     288             : INLINE GEN
     289  4125235513 : uutoi(ulong x, ulong y)
     290             : {
     291             :   GEN z;
     292  4125235513 :   if (!x) return utoi(y);
     293   390225076 :   z = cgetipos(4);
     294   389758201 :   *int_W_lg(z, 1, 4) = x;
     295   389758201 :   *int_W_lg(z, 0, 4) = y; return z;
     296             : }
     297             : /* - (x 2^BIL + y) */
     298             : INLINE GEN
     299       60117 : uutoineg(ulong x, ulong y)
     300             : {
     301             :   GEN z;
     302       60117 :   if (!x) return y? utoineg(y): gen_0;
     303           0 :   z = cgetineg(4);
     304           0 :   *int_W_lg(z, 1, 4) = x;
     305           0 :   *int_W_lg(z, 0, 4) = y; return z;
     306             : }
     307             : 
     308             : INLINE long
     309   202844642 : itos(GEN x)
     310             : {
     311   202844642 :   long s = signe(x);
     312             :   long u;
     313             : 
     314   202844642 :   if (!s) return 0;
     315   191730944 :   u = x[2];
     316   191730944 :   if (lgefint(x) > 3 || u < 0)
     317          20 :     pari_err_OVERFLOW("t_INT-->long assignment");
     318   191730930 :   return (s>0) ? u : -u;
     319             : }
     320             : /* as itos, but return 0 if too large. Cf is_bigint */
     321             : INLINE long
     322     7302092 : itos_or_0(GEN x) {
     323             :   long n;
     324     7302092 :   if (lgefint(x) != 3 || (n = x[2]) & HIGHBIT) return 0;
     325     7281500 :   return signe(x) > 0? n: -n;
     326             : }
     327             : INLINE ulong
     328    25705605 : itou(GEN x)
     329             : {
     330    25705605 :   switch(lgefint(x)) {
     331     5208587 :     case 2: return 0;
     332    20497018 :     case 3: return x[2];
     333             :     default:
     334           0 :       pari_err_OVERFLOW("t_INT-->ulong assignment");
     335           0 :       return 0; /* not reached */
     336             :   }
     337             : }
     338             : 
     339             : /* as itou, but return 0 if too large. Cf is_bigint */
     340             : INLINE ulong
     341     4166059 : itou_or_0(GEN x) {
     342     4166059 :   if (lgefint(x) != 3) return 0;
     343     4156031 :   return (ulong)x[2];
     344             : }
     345             : 
     346             : INLINE GEN
     347    92958302 : real_0_bit(long bitprec) { GEN x=cgetr(2); x[1]=evalexpo(bitprec); return x; }
     348             : INLINE GEN
     349    30751642 : real_0(long prec) { return real_0_bit(-prec2nbits(prec)); }
     350             : INLINE GEN
     351      473902 : real_1_bit(long bit) { return real_1(nbits2prec(bit)); }
     352             : INLINE GEN
     353    26884406 : real_1(long prec) {
     354    26884406 :   GEN x = cgetr(prec);
     355             :   long i;
     356    26884406 :   x[1] = evalsigne(1) | _evalexpo(0);
     357    26884406 :   x[2] = (long)HIGHBIT; for (i=3; i<prec; i++) x[i] = 0;
     358    26884406 :   return x;
     359             : }
     360             : INLINE GEN
     361          84 : real_m1(long prec) {
     362          84 :   GEN x = cgetr(prec);
     363             :   long i;
     364          84 :   x[1] = evalsigne(-1) | _evalexpo(0);
     365          84 :   x[2] = (long)HIGHBIT; for (i=3; i<prec; i++) x[i] = 0;
     366          84 :   return x;
     367             : }
     368             : 
     369             : /* 2.^n */
     370             : INLINE GEN
     371       48190 : real2n(long n, long prec) { GEN z = real_1(prec); setexpo(z, n); return z; }
     372             : INLINE GEN
     373           0 : real_m2n(long n, long prec) { GEN z = real_m1(prec); setexpo(z, n); return z; }
     374             : INLINE GEN
     375   144473175 : stor(long s, long prec) { GEN z = cgetr(prec); affsr(s,z); return z; }
     376             : INLINE GEN
     377     1734926 : utor(ulong s, long prec){ GEN z = cgetr(prec); affur(s,z); return z; }
     378             : INLINE GEN
     379   179704679 : itor(GEN x, long prec) { GEN z = cgetr(prec); affir(x,z); return z; }
     380             : INLINE GEN
     381    71685059 : rtor(GEN x, long prec) { GEN z = cgetr(prec); affrr(x,z); return z; }
     382             : 
     383     5226318 : INLINE ulong int_bit(GEN x, long n)
     384             : {
     385     5226318 :   long r, q = dvmdsBIL(n, &r);
     386     5227492 :   return q < lgefint(x)-2?((ulong)*int_W(x,q) >> r) & 1UL:0;
     387             : }
     388             : 
     389             : /*******************************************************************/
     390             : /*                                                                 */
     391             : /*                           COMPARISON                            */
     392             : /*                                                                 */
     393             : /*******************************************************************/
     394             : INLINE int
     395      668440 : cmpir(GEN x, GEN y)
     396             : {
     397             :   pari_sp av;
     398             :   GEN z;
     399             : 
     400      668440 :   if (!signe(x)) return -signe(y);
     401      297836 :   if (!signe(y))
     402             :   {
     403        3915 :     if (expo(y) >= expi(x)) return 0;
     404        3887 :     return signe(x);
     405             :   }
     406      293921 :   av=avma; z = itor(x, realprec(y)); avma=av;
     407      293921 :   return cmprr(z,y); /* cmprr does no memory adjustment */
     408             : }
     409             : INLINE int
     410      435609 : cmpri(GEN x, GEN y) { return -cmpir(y,x); }
     411             : INLINE int
     412       61690 : cmpsr(long x, GEN y)
     413             : {
     414             :   pari_sp av;
     415             :   GEN z;
     416             : 
     417       61690 :   if (!x) return -signe(y);
     418       61690 :   av=avma; z = stor(x, LOWDEFAULTPREC); avma=av;
     419       61690 :   return cmprr(z,y);
     420             : }
     421             : INLINE int
     422       38640 : cmprs(GEN x, long y) { return -cmpsr(y,x); }
     423             : /* compare x and |y| */
     424             : INLINE int
     425    26571663 : abscmpui(ulong x, GEN y)
     426             : {
     427    26571663 :   long l = lgefint(y);
     428             :   ulong p;
     429             : 
     430    26571663 :   if (!x) return (l > 2)? -1: 0;
     431    26571649 :   if (l == 2) return 1;
     432    26381501 :   if (l > 3) return -1;
     433    26371432 :   p = y[2]; if (p == x) return 0;
     434    25979840 :   return p < x ? 1 : -1;
     435             : }
     436             : INLINE int
     437    26553148 : abscmpiu(GEN x, ulong y) { return -abscmpui(y,x); }
     438             : INLINE int
     439     4129848 : cmpsi(long x, GEN y)
     440             : {
     441             :   ulong p;
     442             : 
     443     4129848 :   if (!x) return -signe(y);
     444             : 
     445     4129246 :   if (x > 0)
     446             :   {
     447     4128945 :     if (signe(y)<=0) return 1;
     448     4128826 :     if (lgefint(y)>3) return -1;
     449     4115646 :     p = y[2]; if (p == (ulong)x) return 0;
     450     4081857 :     return p < (ulong)x ? 1 : -1;
     451             :   }
     452             : 
     453         301 :   if (signe(y)>=0) return -1;
     454          42 :   if (lgefint(y)>3) return 1;
     455          42 :   p = y[2]; if (p == (ulong)-x) return 0;
     456          14 :   return p < (ulong)(-x) ? -1 : 1;
     457             : }
     458             : INLINE int
     459     4128280 : cmpis(GEN x, long y) { return -cmpsi(y,x); }
     460             : INLINE int
     461      511220 : mpcmp(GEN x, GEN y)
     462             : {
     463      511220 :   if (typ(x)==t_INT)
     464        5863 :     return (typ(y)==t_INT) ? cmpii(x,y) : cmpir(x,y);
     465      505357 :   return (typ(y)==t_INT) ? -cmpir(y,x) : cmprr(x,y);
     466             : }
     467             : 
     468             : /* x == y ? */
     469             : INLINE int
     470       78239 : equalsi(long x, GEN y)
     471             : {
     472       78239 :   if (!x) return !signe(y);
     473       78239 :   if (x > 0)
     474             :   {
     475        8792 :     if (signe(y) <= 0 || lgefint(y) != 3) return 0;
     476        7455 :     return ((ulong)y[2] == (ulong)x);
     477             :   }
     478       69447 :   if (signe(y) >= 0 || lgefint(y) != 3) return 0;
     479       69447 :   return ((ulong)y[2] == (ulong)-x);
     480             : }
     481             : /* x == |y| ? */
     482             : INLINE int
     483    11549698 : absequalui(ulong x, GEN y)
     484             : {
     485    11549698 :   if (!x) return !signe(y);
     486    11549698 :   return (lgefint(y) == 3 && (ulong)y[2] == x);
     487             : }
     488             : INLINE int
     489    11446315 : absequaliu(GEN x, ulong y) { return absequalui(y,x); }
     490             : INLINE int
     491       78120 : equalis(GEN x, long y) { return equalsi(y,x); }
     492             : 
     493             : /* assume x != 0, is |x| == 2^n ? */
     494             : INLINE int
     495      749260 : absrnz_equal2n(GEN x) {
     496      749260 :   if ((ulong)x[2]==HIGHBIT)
     497             :   {
     498       29156 :     long i, lx = lg(x);
     499      385319 :     for (i = 3; i < lx; i++)
     500      361738 :       if (x[i]) return 0;
     501       23581 :     return 1;
     502             :   }
     503      720104 :   return 0;
     504             : }
     505             : /* assume x != 0, is |x| == 1 ? */
     506             : INLINE int
     507     1192105 : absrnz_equal1(GEN x) { return !expo(x) && absrnz_equal2n(x); }
     508             : 
     509             : INLINE long
     510  2842927934 : maxss(long x, long y) { return x>y?x:y; }
     511             : INLINE long
     512   827856408 : minss(long x, long y) { return x<y?x:y; }
     513             : INLINE long
     514     3377241 : minuu(ulong x, ulong y) { return x<y?x:y; }
     515             : INLINE long
     516     6416174 : maxuu(ulong x, ulong y) { return x>y?x:y; }
     517             : INLINE double
     518      920292 : maxdd(double x, double y) { return x>y?x:y; }
     519             : INLINE double
     520      367412 : mindd(double x, double y) { return x<y?x:y; }
     521             : 
     522             : /*******************************************************************/
     523             : /*                                                                 */
     524             : /*                             ADD / SUB                           */
     525             : /*                                                                 */
     526             : /*******************************************************************/
     527             : INLINE GEN
     528       25018 : subuu(ulong x, ulong y)
     529             : {
     530             :   ulong z;
     531             :   LOCAL_OVERFLOW;
     532       25018 :   z = subll(x, y);
     533       25018 :   return overflow? utoineg(-z): utoi(z);
     534             : }
     535             : INLINE GEN
     536  1836974600 : adduu(ulong x, ulong y) { ulong t = x+y; return uutoi((t < x), t); }
     537             : 
     538             : INLINE GEN
     539       25018 : addss(long x, long y)
     540             : {
     541       25018 :   if (!x) return stoi(y);
     542       25018 :   if (!y) return stoi(x);
     543       25018 :   if (x > 0) return y > 0? adduu(x,y): subuu(x, -y);
     544             : 
     545       25018 :   if (y > 0) return subuu(y, -x);
     546             :   else { /* - adduu(-x, -y) */
     547           0 :     ulong t = (-x)+(-y); return uutoineg((t < (ulong)(-x)), t);
     548             :   }
     549             : }
     550       25018 : INLINE GEN subss(long x, long y) { return addss(-y,x); }
     551             : 
     552             : INLINE GEN
     553  4511199995 : subii(GEN x, GEN y)
     554             : {
     555  4511199995 :   if (x==y) return gen_0; /* frequent with x = y = gen_0 */
     556  3306509820 :   return addii_sign(x, signe(x), y, -signe(y));
     557             : }
     558             : INLINE GEN
     559  4810279778 : addii(GEN x, GEN y) { return addii_sign(x, signe(x), y, signe(y)); }
     560             : INLINE GEN
     561   752516243 : addrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, signe(y)); }
     562             : INLINE GEN
     563  1500307495 : subrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, -signe(y)); }
     564             : INLINE GEN
     565    94625155 : addir(GEN x, GEN y) { return addir_sign(x, signe(x), y, signe(y)); }
     566             : INLINE GEN
     567   116510620 : subir(GEN x, GEN y) { return addir_sign(x, signe(x), y, -signe(y)); }
     568             : INLINE GEN
     569     1175463 : subri(GEN x, GEN y) { return addir_sign(y, -signe(y), x, signe(x)); }
     570             : INLINE GEN
     571    98224475 : addsi(long x, GEN y) { return addsi_sign(x, y, signe(y)); }
     572             : INLINE GEN
     573    11744641 : addui(ulong x, GEN y) { return addui_sign(x, y, signe(y)); }
     574             : INLINE GEN
     575     3382655 : subsi(long x, GEN y) { return addsi_sign(x, y, -signe(y)); }
     576             : INLINE GEN
     577    17528187 : subui(ulong x, GEN y) { return addui_sign(x, y, -signe(y)); }
     578             : 
     579             : /*******************************************************************/
     580             : /*                                                                 */
     581             : /*                           MOD, REM, DIV                         */
     582             : /*                                                                 */
     583             : /*******************************************************************/
     584    77556680 : INLINE ulong mod2BIL(GEN x) { return *int_LSW(x); }
     585           0 : INLINE long mod64(GEN x) { return mod2BIL(x) & 63; }
     586         252 : INLINE long mod32(GEN x) { return mod2BIL(x) & 31; }
     587       56987 : INLINE long mod16(GEN x) { return mod2BIL(x) & 15; }
     588    39418784 : INLINE long mod8(GEN x)  { return mod2BIL(x) & 7; }
     589     9399204 : INLINE long mod4(GEN x)  { return mod2BIL(x) & 3; }
     590    18018651 : INLINE long mod2(GEN x)  { return mod2BIL(x) & 1; }
     591             : INLINE int
     592    27414514 : mpodd(GEN x) { return signe(x) && mod2(x); }
     593             : /* x mod 2^n, n < BITS_IN_LONG */
     594             : INLINE ulong
     595     5441422 : umodi2n(GEN x, long n)
     596             : {
     597     5441422 :   long s = signe(x);
     598     5441422 :   const ulong _2n = 1UL << n;
     599             :   ulong m;
     600     5441422 :   if (!s) return 0;
     601     5431832 :   m = *int_LSW(x) & (_2n - 1);
     602     5431832 :   if (s < 0 && m) m = _2n - m;
     603     5431832 :   return m;
     604             : }
     605           0 : INLINE ulong Mod64(GEN x){ return umodi2n(x,6); }
     606      165893 : INLINE ulong Mod32(GEN x){ return umodi2n(x,5); }
     607      166733 : INLINE ulong Mod16(GEN x){ return umodi2n(x,4); }
     608     1307992 : INLINE ulong Mod8(GEN x) { return umodi2n(x,3); }
     609     1323378 : INLINE ulong Mod4(GEN x) { return umodi2n(x,2); }
     610     2477426 : INLINE ulong Mod2(GEN x) { return umodi2n(x,1); }
     611             : 
     612             : INLINE GEN
     613    38758692 : truedivii(GEN a,GEN b) { return truedvmdii(a,b,NULL); }
     614             : INLINE GEN
     615         652 : truedivis(GEN a, long b) { return truedvmdis(a,b,NULL); }
     616             : INLINE GEN
     617     6083888 : truedivsi(long a, GEN b) { return truedvmdsi(a,b,NULL); }
     618             : 
     619             : INLINE GEN
     620     8037359 : divii(GEN a, GEN b) { return dvmdii(a,b,NULL); }
     621             : INLINE GEN
     622  1224315483 : remii(GEN a, GEN b) { return dvmdii(a,b,ONLY_REM); }
     623             : 
     624             : INLINE GEN
     625           0 : divss(long x, long y) { return stoi(x / y); }
     626             : INLINE GEN
     627      600364 : modss(long x, long y) { return stoi(smodss(x, y)); }
     628             : INLINE GEN
     629           0 : remss(long x, long y) { return stoi(x % y); }
     630             : INLINE long
     631     6371473 : smodss(long x, long y)
     632             : {
     633     6371473 :   long r = x%y;
     634     6371473 :   return (r >= 0)? r: labs(y) + r;
     635             : }
     636             : INLINE ulong
     637    11845045 : umodsu(long x, ulong y)
     638             : {
     639    11845045 :   return x>=0 ? x%y: Fl_neg((-x)%y, y);
     640             : }
     641             : 
     642             : INLINE long
     643           0 : sdivss_rem(long x, long y, long *r)
     644             : {
     645             :   long q;
     646             :   LOCAL_HIREMAINDER;
     647           0 :   if (!y) pari_err_INV("sdivss_rem",gen_0);
     648           0 :   hiremainder = 0; q = divll((ulong)labs(x),(ulong)labs(y));
     649           0 :   if (x < 0) { hiremainder = -((long)hiremainder); q = -q; }
     650           0 :   if (y < 0) q = -q;
     651           0 :   *r = hiremainder; return q;
     652             : }
     653             : INLINE GEN
     654           0 : divss_rem(long x, long y, long *r) { return stoi(sdivss_rem(x,y,r)); }
     655             : INLINE ulong
     656         434 : udivuu_rem(ulong x, ulong y, ulong *r)
     657             : {
     658         434 :   if (!y) pari_err_INV("udivuu_rem",gen_0);
     659         434 :   *r = x % y; return x / y;
     660             : }
     661             : 
     662             : INLINE ulong
     663       10780 : udivui_rem(ulong x, GEN y, ulong *r)
     664             : {
     665       10780 :   long q, s = signe(y);
     666             :   LOCAL_HIREMAINDER;
     667             : 
     668       10780 :   if (!s) pari_err_INV("udivui_rem",gen_0);
     669       10780 :   if (!x || lgefint(y)>3) { *r = x; return 0; }
     670       10500 :   hiremainder=0; q = (long)divll(x, (ulong)y[2]);
     671       10500 :   if (s < 0) q = -q;
     672       10500 :   *r = hiremainder; return q;
     673             : }
     674             : 
     675             : /* assume d != 0 and |n| / d can be represented as an ulong.
     676             :  * Return |n|/d, set *r = |n| % d */
     677             : INLINE ulong
     678    12480475 : udiviu_rem(GEN n, ulong d, ulong *r)
     679             : {
     680    12480475 :   switch(lgefint(n))
     681             :   {
     682           0 :     case 2: *r = 0; return 0;
     683             :     case 3:
     684             :     {
     685    12480475 :       ulong nn = n[2];
     686    12480475 :       *r = nn % d; return nn / d;
     687             :     }
     688             :     default: /* 4 */
     689             :     {
     690             :       ulong n1, n0, q;
     691             :       LOCAL_HIREMAINDER;
     692           0 :       n0 = *int_W(n,0);
     693           0 :       n1 = *int_W(n,1);
     694           0 :       hiremainder = n1;
     695           0 :       q = divll(n0, d);
     696           0 :       *r = hiremainder; return q;
     697             :     }
     698             :   }
     699             : }
     700             : 
     701             : INLINE long
     702    13557416 : sdivsi_rem(long x, GEN y, long *r)
     703             : {
     704    13557416 :   long q, s = signe(y);
     705             :   LOCAL_HIREMAINDER;
     706             : 
     707    13557416 :   if (!s) pari_err_INV("sdivsi_rem",gen_0);
     708    13557416 :   if (!x || lgefint(y)>3 || ((long)y[2]) < 0) { *r = x; return 0; }
     709    11882323 :   hiremainder=0; q = (long)divll(labs(x), (ulong)y[2]);
     710    11882323 :   if (x < 0) { hiremainder = -((long)hiremainder); q = -q; }
     711    11882323 :   if (s < 0) q = -q;
     712    11882323 :   *r = hiremainder; return q;
     713             : }
     714             : INLINE GEN
     715           0 : divsi_rem(long s, GEN y, long *r) { return stoi(sdivsi_rem(s,y,r)); }
     716             : 
     717             : INLINE long
     718          98 : sdivsi(long x, GEN y)
     719             : {
     720          98 :   long q, s = signe(y);
     721             : 
     722          98 :   if (!s) pari_err_INV("sdivsi",gen_0);
     723          98 :   if (!x || lgefint(y)>3 || ((long)y[2]) < 0) return 0;
     724          70 :   q = labs(x) / y[2];
     725          70 :   if (x < 0) q = -q;
     726          70 :   if (s < 0) q = -q;
     727          70 :   return q;
     728             : }
     729             : 
     730             : INLINE GEN
     731           0 : dvmdss(long x, long y, GEN *z)
     732             : {
     733             :   long r;
     734           0 :   GEN q = divss_rem(x,y, &r);
     735           0 :   *z = stoi(r); return q;
     736             : }
     737             : INLINE long
     738  3262442587 : dvmdsBIL(long n, long *r) { *r = remsBIL(n); return divsBIL(n); }
     739             : INLINE ulong
     740    99882873 : dvmduBIL(ulong n, ulong *r) { *r = remsBIL(n); return divsBIL(n); }
     741             : INLINE GEN
     742           0 : dvmdsi(long x, GEN y, GEN *z)
     743             : {
     744             :   long r;
     745           0 :   GEN q = divsi_rem(x,y, &r);
     746           0 :   *z = stoi(r); return q;
     747             : }
     748             : INLINE GEN
     749           0 : dvmdis(GEN x, long y, GEN *z)
     750             : {
     751             :   long r;
     752           0 :   GEN q = divis_rem(x,y, &r);
     753           0 :   *z = stoi(r); return q;
     754             : }
     755             : 
     756             : INLINE long
     757     1214173 : smodis(GEN x, long y)
     758             : {
     759     1214173 :   pari_sp av = avma;
     760             :   long r;
     761     1214173 :   (void)divis_rem(x,y, &r); avma = av; return (r >= 0) ? r: labs(y) + r;
     762             : }
     763             : INLINE GEN
     764       36439 : modis(GEN x, long y) { return stoi(smodis(x,y)); }
     765             : INLINE GEN
     766     7473283 : modsi(long x, GEN y) {
     767             :   long r;
     768     7473283 :   (void)sdivsi_rem(x, y, &r);
     769     7473283 :   return (r >= 0)? stoi(r): addsi_sign(r, y, 1);
     770             : }
     771             : 
     772             : INLINE ulong
     773     1192964 : umodui(ulong x, GEN y)
     774             : {
     775     1192964 :   if (!signe(y)) pari_err_INV("umodui",gen_0);
     776     1192964 :   if (!x || lgefint(y) > 3) return x;
     777      203815 :   return x % (ulong)y[2];
     778             : }
     779             : 
     780             : INLINE GEN
     781           0 : remsi(long x, GEN y)
     782           0 : { long r; (void)sdivsi_rem(x,y, &r); return stoi(r); }
     783             : INLINE GEN
     784           0 : remis(GEN x, long y)
     785             : {
     786           0 :   pari_sp av = avma;
     787             :   long r;
     788           0 :   (void)divis_rem(x,y, &r); avma = av; return stoi(r);
     789             : }
     790             : 
     791             : INLINE GEN
     792           0 : rdivis(GEN x, long y, long prec)
     793             : {
     794           0 :   GEN z = cgetr(prec);
     795           0 :   pari_sp av = avma;
     796           0 :   affrr(divrs(itor(x,prec), y),z);
     797           0 :   avma = av; return z;
     798             : }
     799             : INLINE GEN
     800           0 : rdivsi(long x, GEN y, long prec)
     801             : {
     802           0 :   GEN z = cgetr(prec);
     803           0 :   pari_sp av = avma;
     804           0 :   affrr(divsr(x, itor(y,prec)), z);
     805           0 :   avma = av; return z;
     806             : }
     807             : INLINE GEN
     808      839647 : rdivss(long x, long y, long prec)
     809             : {
     810      839647 :   GEN z = cgetr(prec);
     811      839647 :   pari_sp av = avma;
     812      839647 :   affrr(divrs(stor(x, prec), y), z);
     813      839647 :   avma = av; return z;
     814             : }
     815             : 
     816             : INLINE void
     817          14 : rdiviiz(GEN x, GEN y, GEN z)
     818             : {
     819          14 :   pari_sp av = avma;
     820          14 :   long prec = realprec(z);
     821          14 :   affir(x, z);
     822          14 :   if (!is_bigint(y)) {
     823           0 :     affrr(divrs(z, y[2]), z);
     824           0 :     if (signe(y) < 0) togglesign(z);
     825             :   }
     826             :   else
     827          14 :     affrr(divrr(z, itor(y,prec)), z);
     828          14 :   avma = av;
     829          14 : }
     830             : INLINE GEN
     831    11599695 : rdivii(GEN x, GEN y, long prec)
     832             : {
     833    11599695 :   GEN z = cgetr(prec);
     834    11599695 :   pari_sp av = avma;
     835    11599695 :   affir(x, z);
     836    11599695 :   if (lg(y) == 3) {
     837     7517869 :     affrr(divru(z, y[2]), z);
     838     7517869 :     if (signe(y) < 0) togglesign(z);
     839             :   }
     840             :   else
     841     4081826 :     affrr(divrr(z, itor(y,prec)), z);
     842    11599695 :   avma = av; return z;
     843             : }
     844             : INLINE GEN
     845    11545431 : fractor(GEN x, long prec) { return rdivii(gel(x,1), gel(x,2), prec); }
     846             : 
     847             : INLINE int
     848     1493516 : dvdii(GEN x, GEN y)
     849             : {
     850     1493516 :   pari_sp av=avma;
     851     1493516 :   GEN r = remii(x,y);
     852     1493516 :   avma = av; return r == gen_0;
     853             : }
     854             : INLINE int
     855           7 : dvdsi(long x, GEN y)
     856             : {
     857           7 :   if (!signe(y)) return x == 0;
     858           7 :   if (lgefint(y) != 3) return 0;
     859           7 :   return x % y[2] == 0;
     860             : }
     861             : INLINE int
     862         126 : dvdui(ulong x, GEN y)
     863             : {
     864         126 :   if (!signe(y)) return x == 0;
     865         126 :   if (lgefint(y) != 3) return 0;
     866         126 :   return x % y[2] == 0;
     867             : }
     868             : INLINE int
     869       31435 : dvdis(GEN x, long y)
     870       31435 : { return y? smodis(x, y) == 0: signe(x) == 0; }
     871             : INLINE int
     872        1540 : dvdiu(GEN x, ulong y)
     873        1540 : { return y? umodiu(x, y) == 0: signe(x) == 0; }
     874             : 
     875             : INLINE int
     876           0 : dvdisz(GEN x, long y, GEN z)
     877             : {
     878           0 :   const pari_sp av = avma;
     879             :   long r;
     880           0 :   GEN p1 = divis_rem(x,y, &r);
     881           0 :   avma = av; if (r) return 0;
     882           0 :   affii(p1,z); return 1;
     883             : }
     884             : INLINE int
     885           0 : dvdiuz(GEN x, ulong y, GEN z)
     886             : {
     887           0 :   const pari_sp av = avma;
     888             :   ulong r;
     889           0 :   GEN p1 = diviu_rem(x,y, &r);
     890           0 :   avma = av; if (r) return 0;
     891           0 :   affii(p1,z); return 1;
     892             : }
     893             : INLINE int
     894        3761 : dvdiiz(GEN x, GEN y, GEN z)
     895             : {
     896        3761 :   const pari_sp av=avma;
     897             :   GEN p2;
     898        3761 :   const GEN p1=dvmdii(x,y,&p2);
     899             : 
     900        3761 :   if (signe(p2)) { avma=av; return 0; }
     901        3268 :   affii(p1,z); avma=av; return 1;
     902             : }
     903             : 
     904             : INLINE ulong
     905     5927553 : remlll_pre(ulong u2, ulong u1, ulong u0, ulong n, ulong ninv)
     906             : {
     907     5927553 :   u1 = remll_pre(u2, u1, n, ninv);
     908     5927553 :   return remll_pre(u1, u0, n, ninv);
     909             : }
     910             : 
     911             : INLINE ulong
     912  4343794407 : Fl_sqr_pre(ulong a, ulong p, ulong pi)
     913             : {
     914             :   register ulong x;
     915             :   LOCAL_HIREMAINDER;
     916  4343794407 :   x = mulll(a,a);
     917  4343794407 :   return remll_pre(hiremainder, x, p, pi);
     918             : }
     919             : 
     920             : INLINE ulong
     921  2816193757 : Fl_mul_pre(ulong a, ulong b, ulong p, ulong pi)
     922             : {
     923             :   register ulong x;
     924             :   LOCAL_HIREMAINDER;
     925  2816193757 :   x = mulll(a,b);
     926  2816193757 :   return remll_pre(hiremainder, x, p, pi);
     927             : }
     928             : 
     929             : INLINE ulong
     930  4633564667 : Fl_addmul_pre(ulong x0, ulong x1, ulong y0, ulong p, ulong pi)
     931             : {
     932             :   ulong l0, h0;
     933             :   LOCAL_HIREMAINDER;
     934  4633564667 :   hiremainder = y0;
     935  4633564667 :   l0 = addmul(x0, x1); h0 = hiremainder;
     936  4633564667 :   return remll_pre(h0, l0, p, pi);
     937             : }
     938             : 
     939             : INLINE ulong
     940    45193573 : Fl_addmulmul_pre(ulong x0, ulong y0, ulong x1, ulong y1, ulong p, ulong pi)
     941             : {
     942             :   ulong l0, l1, h0, h1;
     943             :   LOCAL_OVERFLOW;
     944             :   LOCAL_HIREMAINDER;
     945    45193573 :   l0 = mulll(x0, y0); h0 = hiremainder;
     946    45193573 :   l1 = mulll(x1, y1); h1 = hiremainder;
     947    45193573 :   l0 = addll(l0, l1); h0 = addllx(h0, h1);
     948    45193573 :   return overflow ? remlll_pre(1, h0, l0, p, pi): remll_pre(h0, l0, p, pi);
     949             : }
     950             : 
     951             : INLINE ulong
     952     2706454 : Fl_ellj_pre(ulong a4, ulong a6, ulong p, ulong pi)
     953             : {
     954             :   /* a43 = 4 a4^3 */
     955     2706454 :   ulong a43 = Fl_double(Fl_double(
     956             :               Fl_mul_pre(a4, Fl_sqr_pre(a4, p, pi), p, pi), p), p);
     957             :   /* a62 = 27 a6^2 */
     958     2706454 :   ulong a62 = Fl_mul_pre(Fl_sqr_pre(a6, p, pi), 27 % p, p, pi);
     959     2706456 :   ulong z1 = Fl_mul_pre(a43, 1728 % p, p, pi);
     960     2706456 :   ulong z2 = Fl_add(a43, a62, p);
     961     2706456 :   return Fl_div(z1, z2, p);
     962             : }
     963             : 
     964             : /*******************************************************************/
     965             : /*                                                                 */
     966             : /*                        MP (INT OR REAL)                         */
     967             : /*                                                                 */
     968             : /*******************************************************************/
     969             : INLINE GEN
     970          21 : mptrunc(GEN x) { return typ(x)==t_INT? icopy(x): truncr(x); }
     971             : INLINE GEN
     972           0 : mpfloor(GEN x) { return typ(x)==t_INT? icopy(x): floorr(x); }
     973             : INLINE GEN
     974           0 : mpceil(GEN x) { return typ(x)==t_INT? icopy(x): ceilr(x); }
     975             : INLINE GEN
     976      357853 : mpround(GEN x) { return typ(x) == t_INT? icopy(x): roundr(x); }
     977             : 
     978             : INLINE long
     979      203279 : mpexpo(GEN x) { return typ(x) == t_INT? expi(x): expo(x); }
     980             : 
     981             : INLINE GEN
     982    21728631 : mpadd(GEN x, GEN y)
     983             : {
     984    21728631 :   if (typ(x)==t_INT)
     985     4108989 :     return (typ(y)==t_INT) ? addii(x,y) : addir(x,y);
     986    17619642 :   return (typ(y)==t_INT) ? addir(y,x) : addrr(x,y);
     987             : }
     988             : INLINE GEN
     989    12042592 : mpsub(GEN x, GEN y)
     990             : {
     991    12042592 :   if (typ(x)==t_INT)
     992      266296 :     return (typ(y)==t_INT) ? subii(x,y) : subir(x,y);
     993    11776296 :   return (typ(y)==t_INT) ? subri(x,y) : subrr(x,y);
     994             : }
     995             : INLINE GEN
     996    31774421 : mpmul(GEN x, GEN y)
     997             : {
     998    31774421 :   if (typ(x)==t_INT)
     999     4889514 :     return (typ(y)==t_INT) ? mulii(x,y) : mulir(x,y);
    1000    26884907 :   return (typ(y)==t_INT) ? mulir(y,x) : mulrr(x,y);
    1001             : }
    1002             : INLINE GEN
    1003     3873843 : mpsqr(GEN x) { return (typ(x)==t_INT) ? sqri(x) : sqrr(x); }
    1004             : INLINE GEN
    1005      196756 : mpdiv(GEN x, GEN y)
    1006             : {
    1007      196756 :   if (typ(x)==t_INT)
    1008      101878 :     return (typ(y)==t_INT) ? divii(x,y) : divir(x,y);
    1009       94878 :   return (typ(y)==t_INT) ? divri(x,y) : divrr(x,y);
    1010             : }
    1011             : 
    1012             : /*******************************************************************/
    1013             : /*                                                                 */
    1014             : /*                          Z/nZ, n ULONG                          */
    1015             : /*                                                                 */
    1016             : /*******************************************************************/
    1017             : INLINE ulong
    1018   643258762 : Fl_double(ulong a, ulong p)
    1019             : {
    1020   643258762 :   ulong res = a << 1;
    1021   643258762 :   return (res >= p || res < a) ? res - p : res;
    1022             : }
    1023             : INLINE ulong
    1024   100052175 : Fl_triple(ulong a, ulong p)
    1025             : {
    1026   100052175 :   ulong res = a << 1;
    1027   100052175 :   if (res >= p || res < a) res -= p;
    1028   100052175 :   res += a;
    1029   100052175 :   return (res >= p || res < a)? res - p: res;
    1030             : }
    1031             : INLINE ulong
    1032    12755243 : Fl_halve(ulong a, ulong p)
    1033             : {
    1034             :   ulong ap, ap2;
    1035    12755243 :   if ((a&1UL)==0) return a>>1;
    1036     6441132 :   ap = a + p; ap2 = ap>>1;
    1037     6441132 :   return ap>=a ? ap2: (ap2|HIGHBIT);
    1038             : }
    1039             : 
    1040             : INLINE ulong
    1041  3885050015 : Fl_add(ulong a, ulong b, ulong p)
    1042             : {
    1043  3885050015 :   ulong res = a + b;
    1044  3885050015 :   return (res >= p || res < a) ? res - p : res;
    1045             : }
    1046             : INLINE ulong
    1047    70732083 : Fl_neg(ulong x, ulong p) { return x ? p - x: 0; }
    1048             : 
    1049             : INLINE ulong
    1050  4270479737 : Fl_sub(ulong a, ulong b, ulong p)
    1051             : {
    1052  4270479737 :   ulong res = a - b;
    1053  4270479737 :   return (res > a) ? res + p: res;
    1054             : }
    1055             : 
    1056             : /* centerlift(u mod p) */
    1057             : INLINE long
    1058    18491275 : Fl_center(ulong u, ulong p, ulong ps2) { return (long) (u > ps2)? u - p: u; }
    1059             : 
    1060             : INLINE ulong
    1061  2027311278 : Fl_mul(ulong a, ulong b, ulong p)
    1062             : {
    1063             :   register ulong x;
    1064             :   LOCAL_HIREMAINDER;
    1065  2027311278 :   x = mulll(a,b);
    1066  2027311278 :   if (!hiremainder) return x % p;
    1067  1049195155 :   (void)divll(x,p); return hiremainder;
    1068             : }
    1069             : INLINE ulong
    1070   124273129 : Fl_sqr(ulong a, ulong p)
    1071             : {
    1072             :   register ulong x;
    1073             :   LOCAL_HIREMAINDER;
    1074   124273129 :   x = mulll(a,a);
    1075   124273129 :   if (!hiremainder) return x % p;
    1076    48468890 :   (void)divll(x,p); return hiremainder;
    1077             : }
    1078             : INLINE ulong
    1079    15676710 : Fl_div(ulong a, ulong b, ulong p) { return Fl_mul(a, Fl_inv(b, p), p); }
    1080             : 
    1081             : /*******************************************************************/
    1082             : /*                                                                 */
    1083             : /*        DEFINED FROM EXISTING ONE EXPLOITING COMMUTATIVITY       */
    1084             : /*                                                                 */
    1085             : /*******************************************************************/
    1086             : INLINE GEN
    1087      262114 : addri(GEN x, GEN y) { return addir(y,x); }
    1088             : INLINE GEN
    1089    66365355 : addis(GEN x, long s) { return addsi(s,x); }
    1090             : INLINE GEN
    1091    11678143 : addiu(GEN x, ulong s) { return addui(s,x); }
    1092             : INLINE GEN
    1093     2411631 : addrs(GEN x, long s) { return addsr(s,x); }
    1094             : 
    1095             : INLINE GEN
    1096    14145042 : subiu(GEN x, long y) { GEN z = subui(y, x); togglesign(z); return z; }
    1097             : INLINE GEN
    1098    16299138 : subis(GEN x, long y) { return addsi(-y,x); }
    1099             : INLINE GEN
    1100     2618779 : subrs(GEN x, long y) { return addsr(-y,x); }
    1101             : 
    1102             : INLINE GEN
    1103   118133711 : mulis(GEN x, long s) { return mulsi(s,x); }
    1104             : INLINE GEN
    1105   558146964 : muliu(GEN x, ulong s) { return mului(s,x); }
    1106             : INLINE GEN
    1107     3937318 : mulru(GEN x, ulong s) { return mulur(s,x); }
    1108             : INLINE GEN
    1109    14004265 : mulri(GEN x, GEN s) { return mulir(s,x); }
    1110             : INLINE GEN
    1111    10273157 : mulrs(GEN x, long s) { return mulsr(s,x); }
    1112             : 
    1113             : /*******************************************************************/
    1114             : /*                                                                 */
    1115             : /*                  VALUATION, EXPONENT, SHIFTS                    */
    1116             : /*                                                                 */
    1117             : /*******************************************************************/
    1118             : INLINE long
    1119    65950913 : vali(GEN x)
    1120             : {
    1121             :   long i;
    1122             :   GEN xp;
    1123             : 
    1124    65950913 :   if (!signe(x)) return -1;
    1125    65950913 :   xp=int_LSW(x);
    1126    65950913 :   for (i=0; !*xp; i++) xp=int_nextW(xp);
    1127    65950913 :   return vals(*xp) + i * BITS_IN_LONG;
    1128             : }
    1129             : 
    1130             : 
    1131             : /* assume x > 0 */
    1132             : INLINE long
    1133   302899473 : expu(ulong x) { return (BITS_IN_LONG-1) - (long)bfffo(x); }
    1134             : 
    1135             : INLINE long
    1136   777454233 : expi(GEN x)
    1137             : {
    1138   777454233 :   const long lx=lgefint(x);
    1139   777454233 :   return lx==2? -(long)HIGHEXPOBIT: bit_accuracy(lx)-(long)bfffo(*int_MSW(x))-1;
    1140             : }
    1141             : 
    1142             : INLINE GEN
    1143    46149554 : shiftr(GEN x, long n)
    1144             : {
    1145    46149554 :   const long e = evalexpo(expo(x)+n);
    1146    46149554 :   const GEN y = rcopy(x);
    1147             : 
    1148    46149554 :   if (e & ~EXPOBITS) pari_err_OVERFLOW("expo()");
    1149    46149554 :   y[1] = (y[1]&~EXPOBITS) | e; return y;
    1150             : }
    1151             : INLINE GEN
    1152    10892691 : mpshift(GEN x,long s) { return (typ(x)==t_INT)?shifti(x,s):shiftr(x,s); }
    1153             : 
    1154             : /* FIXME: adapt/use mpn_[lr]shift instead */
    1155             : /* z2[imin..imax] := z1[imin..imax].f shifted left sh bits
    1156             :  * (feeding f from the right). Assume sh > 0 */
    1157             : INLINE void
    1158  2823453815 : shift_left(GEN z2, GEN z1, long imin, long imax, ulong f,  ulong sh)
    1159             : {
    1160  2823453815 :   GEN sb = z1 + imin, se = z1 + imax, te = z2 + imax;
    1161  2823453815 :   ulong l, m = BITS_IN_LONG - sh, k = f >> m;
    1162 13551238056 :   while (se > sb) {
    1163  7904330426 :     l     = *se--;
    1164  7904330426 :     *te-- = (l << sh) | k;
    1165  7904330426 :     k     = l >> m;
    1166             :   }
    1167  2823453815 :   *te = (((ulong)*se) << sh) | k;
    1168  2823453815 : }
    1169             : /* z2[imin..imax] := f.z1[imin..imax-1] shifted right sh bits
    1170             :  * (feeding f from the left). Assume sh > 0 */
    1171             : INLINE void
    1172  3323650412 : shift_right(GEN z2, GEN z1, long imin, long imax, ulong f, ulong sh)
    1173             : {
    1174  3323650412 :   GEN sb = z1 + imin, se = z1 + imax, tb = z2 + imin;
    1175  3323650412 :   ulong k, l = *sb++, m = BITS_IN_LONG - sh;
    1176  3323650412 :   *tb++ = (l >> sh) | (f << m);
    1177 14671511213 :   while (sb < se) {
    1178  8024210389 :     k     = l << m;
    1179  8024210389 :     l     = *sb++;
    1180  8024210389 :     *tb++ = (l >> sh) | k;
    1181             :   }
    1182  3323650412 : }
    1183             : 
    1184             : /* Backward compatibility. Inefficient && unused */
    1185             : extern ulong hiremainder;
    1186             : INLINE ulong
    1187           0 : shiftl(ulong x, ulong y)
    1188           0 : { hiremainder = x>>(BITS_IN_LONG-y); return (x<<y); }
    1189             : 
    1190             : INLINE ulong
    1191           0 : shiftlr(ulong x, ulong y)
    1192           0 : { hiremainder = x<<(BITS_IN_LONG-y); return (x>>y); }
    1193             : 
    1194             : INLINE void
    1195    77813932 : shiftr_inplace(GEN z, long d)
    1196             : {
    1197    77813932 :   setexpo(z, expo(z)+d);
    1198    77813932 : }
    1199             : 
    1200             : /*******************************************************************/
    1201             : /*                                                                 */
    1202             : /*                           ASSIGNMENT                            */
    1203             : /*                                                                 */
    1204             : /*******************************************************************/
    1205             : INLINE void
    1206    91285131 : affii(GEN x, GEN y)
    1207             : {
    1208    91285131 :   long lx = lgefint(x);
    1209    91285131 :   if (lg(y)<lx) pari_err_OVERFLOW("t_INT-->t_INT assignment");
    1210    91285144 :   while (--lx) y[lx] = x[lx];
    1211    91285144 : }
    1212             : INLINE void
    1213      258977 : affsi(long s, GEN x)
    1214             : {
    1215      258977 :   if (!s) x[1] = evalsigne(0) | evallgefint(2);
    1216             :   else
    1217             :   {
    1218      244671 :     if (s > 0) { x[1] = evalsigne( 1) | evallgefint(3); x[2] =  s; }
    1219       90491 :     else       { x[1] = evalsigne(-1) | evallgefint(3); x[2] = -s; }
    1220             :   }
    1221      258977 : }
    1222             : INLINE void
    1223     8397748 : affui(ulong u, GEN x)
    1224             : {
    1225     8397748 :   if (!u) x[1] = evalsigne(0) | evallgefint(2);
    1226     8396607 :   else  { x[1] = evalsigne(1) | evallgefint(3); x[2] = u; }
    1227     8397748 : }
    1228             : 
    1229             : INLINE void
    1230   144551526 : affsr(long x, GEN y)
    1231             : {
    1232   144551526 :   long sh, i, ly = lg(y);
    1233             : 
    1234   144551526 :   if (!x)
    1235             :   {
    1236     1366432 :     y[1] = evalexpo(-prec2nbits(ly));
    1237   145917958 :     return;
    1238             :   }
    1239   143185094 :   if (x < 0) {
    1240      163853 :     x = -x; sh = bfffo(x);
    1241      163853 :     y[1] = evalsigne(-1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1242             :   }
    1243             :   else
    1244             :   {
    1245   143021241 :     sh = bfffo(x);
    1246   143021241 :     y[1] = evalsigne(1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1247             :   }
    1248   143185094 :   y[2] = ((ulong)x)<<sh; for (i=3; i<ly; i++) y[i]=0;
    1249             : }
    1250             : 
    1251             : INLINE void
    1252     1816380 : affur(ulong x, GEN y)
    1253             : {
    1254     1816380 :   long sh, i, ly = lg(y);
    1255             : 
    1256     1816380 :   if (!x)
    1257             :   {
    1258         210 :     y[1] = evalexpo(-prec2nbits(ly));
    1259     1816590 :     return;
    1260             :   }
    1261     1816170 :   sh = bfffo(x);
    1262     1816170 :   y[1] = evalsigne(1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1263     1816170 :   y[2] = x<<sh; for (i=3; i<ly; i++) y[i] = 0;
    1264             : }
    1265             : 
    1266             : INLINE void
    1267       94714 : affiz(GEN x, GEN y) { if (typ(y)==t_INT) affii(x,y); else affir(x,y); }
    1268             : INLINE void
    1269           0 : affsz(long x, GEN y) { if (typ(y)==t_INT) affsi(x,y); else affsr(x,y); }
    1270             : INLINE void
    1271       98923 : mpaff(GEN x, GEN y) { if (typ(x)==t_INT) affiz(x, y); else affrr(x,y); }
    1272             : 
    1273             : /*******************************************************************/
    1274             : /*                                                                 */
    1275             : /*                    OPERATION + ASSIGNMENT                       */
    1276             : /*                                                                 */
    1277             : /*******************************************************************/
    1278             : 
    1279           0 : INLINE void addiiz(GEN x, GEN y, GEN z)
    1280           0 : { pari_sp av = avma; affii(addii(x,y),z); avma = av; }
    1281           0 : INLINE void addirz(GEN x, GEN y, GEN z)
    1282           0 : { pari_sp av = avma; affrr(addir(x,y),z); avma = av; }
    1283           0 : INLINE void addriz(GEN x, GEN y, GEN z)
    1284           0 : { pari_sp av = avma; affrr(addri(x,y),z); avma = av; }
    1285     1436864 : INLINE void addrrz(GEN x, GEN y, GEN z)
    1286     1436864 : { pari_sp av = avma; affrr(addrr(x,y),z); avma = av; }
    1287           0 : INLINE void addsiz(long s, GEN y, GEN z)
    1288           0 : { pari_sp av = avma; affii(addsi(s,y),z); avma = av; }
    1289           0 : INLINE void addsrz(long s, GEN y, GEN z)
    1290           0 : { pari_sp av = avma; affrr(addsr(s,y),z); avma = av; }
    1291           0 : INLINE void addssz(long s, long y, GEN z)
    1292           0 : { pari_sp av = avma; affii(addss(s,y),z); avma = av; }
    1293             : 
    1294          35 : INLINE void diviiz(GEN x, GEN y, GEN z)
    1295          35 : { pari_sp av = avma; affii(divii(x,y),z); avma = av; }
    1296           0 : INLINE void divirz(GEN x, GEN y, GEN z)
    1297           0 : { pari_sp av = avma; mpaff(divir(x,y),z); avma = av; }
    1298           0 : INLINE void divisz(GEN x, long y, GEN z)
    1299           0 : { pari_sp av = avma; affii(divis(x,y),z); avma = av; }
    1300           0 : INLINE void divriz(GEN x, GEN y, GEN z)
    1301           0 : { pari_sp av = avma; affrr(divri(x,y),z); avma = av; }
    1302         347 : INLINE void divrrz(GEN x, GEN y, GEN z)
    1303         347 : { pari_sp av = avma; affrr(divrr(x,y),z); avma = av; }
    1304       90548 : INLINE void divrsz(GEN y, long s, GEN z)
    1305       90548 : { pari_sp av = avma; affrr(divrs(y,s),z); avma = av; }
    1306           0 : INLINE void divsiz(long x, GEN y, GEN z)
    1307           0 : { long junk; affsi(sdivsi_rem(x,y,&junk), z); }
    1308           0 : INLINE void divsrz(long s, GEN y, GEN z)
    1309           0 : { pari_sp av = avma; mpaff(divsr(s,y),z); avma = av; }
    1310           0 : INLINE void divssz(long x, long y, GEN z)
    1311           0 : { affsi(x/y, z); }
    1312             : 
    1313           0 : INLINE void modisz(GEN y, long s, GEN z)
    1314           0 : { pari_sp av = avma; affii(modis(y,s),z); avma = av; }
    1315           0 : INLINE void modsiz(long s, GEN y, GEN z)
    1316           0 : { pari_sp av = avma; affii(modsi(s,y),z); avma = av; }
    1317           0 : INLINE void modssz(long s, long y, GEN z)
    1318           0 : { pari_sp av = avma; affii(modss(s,y),z); avma = av; }
    1319             : 
    1320           0 : INLINE void mpaddz(GEN x, GEN y, GEN z)
    1321           0 : { pari_sp av = avma; mpaff(mpadd(x,y),z); avma = av; }
    1322           0 : INLINE void mpsubz(GEN x, GEN y, GEN z)
    1323           0 : { pari_sp av = avma; mpaff(mpsub(x,y),z); avma = av; }
    1324           0 : INLINE void mpmulz(GEN x, GEN y, GEN z)
    1325           0 : { pari_sp av = avma; mpaff(mpmul(x,y),z); avma = av; }
    1326             : 
    1327           0 : INLINE void muliiz(GEN x, GEN y, GEN z)
    1328           0 : { pari_sp av = avma; affii(mulii(x,y),z); avma = av; }
    1329           0 : INLINE void mulirz(GEN x, GEN y, GEN z)
    1330           0 : { pari_sp av = avma; mpaff(mulir(x,y),z); avma = av; }
    1331           0 : INLINE void mulriz(GEN x, GEN y, GEN z)
    1332           0 : { pari_sp av = avma; mpaff(mulri(x,y),z); avma = av; }
    1333       56940 : INLINE void mulrrz(GEN x, GEN y, GEN z)
    1334       56940 : { pari_sp av = avma; affrr(mulrr(x,y),z); avma = av; }
    1335           0 : INLINE void mulsiz(long s, GEN y, GEN z)
    1336           0 : { pari_sp av = avma; affii(mulsi(s,y),z); avma = av; }
    1337           0 : INLINE void mulsrz(long s, GEN y, GEN z)
    1338           0 : { pari_sp av = avma; mpaff(mulsr(s,y),z); avma = av; }
    1339           0 : INLINE void mulssz(long s, long y, GEN z)
    1340           0 : { pari_sp av = avma; affii(mulss(s,y),z); avma = av; }
    1341             : 
    1342           0 : INLINE void remiiz(GEN x, GEN y, GEN z)
    1343           0 : { pari_sp av = avma; affii(remii(x,y),z); avma = av; }
    1344           0 : INLINE void remisz(GEN y, long s, GEN z)
    1345           0 : { pari_sp av = avma; affii(remis(y,s),z); avma = av; }
    1346           0 : INLINE void remsiz(long s, GEN y, GEN z)
    1347           0 : { pari_sp av = avma; affii(remsi(s,y),z); avma = av; }
    1348           0 : INLINE void remssz(long s, long y, GEN z)
    1349           0 : { pari_sp av = avma; affii(remss(s,y),z); avma = av; }
    1350             : 
    1351           0 : INLINE void subiiz(GEN x, GEN y, GEN z)
    1352           0 : { pari_sp av = avma; affii(subii(x,y),z); avma = av; }
    1353           0 : INLINE void subirz(GEN x, GEN y, GEN z)
    1354           0 : { pari_sp av = avma; affrr(subir(x,y),z); avma = av; }
    1355           0 : INLINE void subisz(GEN y, long s, GEN z)
    1356           0 : { pari_sp av = avma; affii(addsi(-s,y),z); avma = av; }
    1357           0 : INLINE void subriz(GEN x, GEN y, GEN z)
    1358           0 : { pari_sp av = avma; affrr(subri(x,y),z); avma = av; }
    1359     1295642 : INLINE void subrrz(GEN x, GEN y, GEN z)
    1360     1295642 : { pari_sp av = avma; affrr(subrr(x,y),z); avma = av; }
    1361           0 : INLINE void subrsz(GEN y, long s, GEN z)
    1362           0 : { pari_sp av = avma; affrr(addsr(-s,y),z); avma = av; }
    1363           0 : INLINE void subsiz(long s, GEN y, GEN z)
    1364           0 : { pari_sp av = avma; affii(subsi(s,y),z); avma = av; }
    1365           0 : INLINE void subsrz(long s, GEN y, GEN z)
    1366           0 : { pari_sp av = avma; affrr(subsr(s,y),z); avma = av; }
    1367           0 : INLINE void subssz(long x, long y, GEN z) { addssz(x,-y,z); }
    1368             : 
    1369             : INLINE void
    1370           0 : dvmdssz(long x, long y, GEN z, GEN t) {
    1371           0 :   pari_sp av = avma;
    1372             :   long r;
    1373           0 :   affii(divss_rem(x,y, &r), z); avma = av; affsi(r,t);
    1374           0 : }
    1375             : INLINE void
    1376           0 : dvmdsiz(long x, GEN y, GEN z, GEN t) {
    1377           0 :   pari_sp av = avma;
    1378             :   long r;
    1379           0 :   affii(divsi_rem(x,y, &r), z); avma = av; affsi(r,t);
    1380           0 : }
    1381             : INLINE void
    1382           0 : dvmdisz(GEN x, long y, GEN z, GEN t) {
    1383           0 :   pari_sp av = avma;
    1384             :   long r;
    1385           0 :   affii(divis_rem(x,y, &r),z); avma = av; affsi(r,t);
    1386           0 : }
    1387             : INLINE void
    1388           0 : dvmdiiz(GEN x, GEN y, GEN z, GEN t) {
    1389           0 :   pari_sp av = avma;
    1390             :   GEN r;
    1391           0 :   affii(dvmdii(x,y,&r),z); affii(r,t); avma=av;
    1392           0 : }

Generated by: LCOV version 1.11