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.10.0 lcov report (development 19823-d80e022) Lines: 541 704 76.8 %
Date: 2016-12-03 05:49:13 Functions: 194 258 75.2 %
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 37555848860 : evallg(long x)
      21             : {
      22 37555848860 :   if (x & ~LGBITS) pari_err_OVERFLOW("lg()");
      23 37560894014 :   return _evallg(x);
      24             : }
      25             : INLINE long
      26    13273895 : evalvalp(long x)
      27             : {
      28    13273895 :   long v = _evalvalp(x);
      29    13273895 :   if (v & ~VALPBITS) pari_err_OVERFLOW("valp()");
      30    13273895 :   return v;
      31             : }
      32             : INLINE long
      33  4980973346 : evalexpo(long x)
      34             : {
      35  4980973346 :   long v = _evalexpo(x);
      36  4980973346 :   if (v & ~EXPOBITS) pari_err_OVERFLOW("expo()");
      37  4980973346 :   return v;
      38             : }
      39             : INLINE long
      40     1844827 : evalprecp(long x)
      41             : {
      42     1844827 :   long v = _evalprecp(x);
      43     1844827 :   if (x & ~((1UL<<(BITS_IN_LONG-VALPnumBITS))-1)) pari_err_OVERFLOW("precp()");
      44     1844826 :   return v;
      45             : }
      46             : 
      47             : INLINE int
      48   134181664 : varncmp(long x, long y)
      49             : {
      50   134181664 :   if (varpriority[x] < varpriority[y]) return  1;
      51   104755109 :   if (varpriority[x] > varpriority[y]) return -1;
      52    54947126 :   return 0;
      53             : }
      54             : INLINE long
      55           0 : varnmin(long x, long y)
      56           0 : { return (varpriority[x] <= varpriority[y])? x: y; }
      57             : INLINE long
      58         196 : varnmax(long x, long y)
      59         196 : { return (varpriority[x] >= varpriority[y])? x: y; }
      60             : 
      61             : /* Inhibit some area gerepile-wise: declare it to be a non recursive
      62             :  * type, of length l. Thus gerepile won't inspect the zone, just copy it.
      63             :  * For the following situation:
      64             :  *   z = cgetg(t,a); av = avma; garbage(); ltop = avma;
      65             :  *   for (i=1; i<HUGE; i++) gel(z,i) = blah();
      66             :  *   stackdummy(av,ltop);
      67             :  * loses (av-ltop) words but save a costly gerepile. */
      68             : INLINE void
      69  1571489226 : stackdummy(pari_sp av, pari_sp ltop) {
      70  1571489226 :   long l = ((GEN)av) - ((GEN)ltop);
      71  1571489226 :   if (l > 0) {
      72   571335628 :     GEN z = (GEN)ltop;
      73   571335628 :     z[0] = evaltyp(t_VECSMALL) | evallg(l);
      74             : #ifdef DEBUG
      75             :     { long i; for (i = 1; i < l; i++) z[i] = 0; }
      76             : #endif
      77             :   }
      78  1571953816 : }
      79             : INLINE void
      80    16361990 : fixlg(GEN x, long ly) {
      81    16361990 :   long lx = lg(x), l = lx - ly;
      82    16361990 :   if (l > 0)
      83             :   { /* stackdummy(x+lx, x+ly) */
      84     1544822 :     GEN z = x + ly;
      85     1544822 :     z[0] = evaltyp(t_VECSMALL) | evallg(l);
      86     1544812 :     setlg(x, ly);
      87             : #ifdef DEBUG
      88             :     { long i; for (i = 1; i < l; i++) z[i] = 0; }
      89             : #endif
      90             :   }
      91    16361985 : }
      92             : /* update lg(z) before affrr(y, z)  [ to cater for precision loss ]*/
      93             : INLINE void
      94    14819323 : affrr_fixlg(GEN y, GEN z) { fixlg(z, lg(y)); affrr(y, z); }
      95             : 
      96             : /*******************************************************************/
      97             : /*                                                                 */
      98             : /*                       ALLOCATE ON STACK                         */
      99             : /*                                                                 */
     100             : /*******************************************************************/
     101             : INLINE GEN
     102 34855044300 : new_chunk(size_t x) /* x is a number of longs */
     103             : {
     104 34855044300 :   GEN z = ((GEN) avma) - x;
     105             :   CHECK_CTRLC
     106 34855044300 :   if (x > (avma-pari_mainstack->bot) / sizeof(long))
     107           0 :     new_chunk_resize(x);
     108 34866227565 :   avma = (pari_sp)z;
     109             : #ifdef MEMSTEP
     110             :   if (DEBUGMEM && pari_mainstack->memused != DISABLE_MEMUSED) {
     111             :     long d = (long)pari_mainstack->memused - (long)z;
     112             :     if (labs(d) > 4*MEMSTEP)
     113             :     {
     114             :       pari_mainstack->memused = (pari_sp)z;
     115             :       err_printf("...%4.0lf Mbytes used\n",
     116             :                 (pari_mainstack->top-pari_mainstack->memused)/1048576.);
     117             :     }
     118             :   }
     119             : #endif
     120 34866227565 :   return z;
     121             : }
     122             : 
     123             : INLINE char *
     124     4241387 : stack_malloc(size_t N)
     125             : {
     126     4241387 :   long n = nchar2nlong(N);
     127     4241387 :   return (char*)new_chunk(n);
     128             : }
     129             : 
     130             : INLINE char *
     131       22227 : stack_calloc(size_t N)
     132             : {
     133       22227 :   char *p = stack_malloc(N);
     134       22227 :   memset(p, 0, N); return p;
     135             : }
     136             : 
     137             : /* cgetg(lg(x), typ(x)), set *lx. Implicit unsetisclone() */
     138             : INLINE GEN
     139   332050176 : cgetg_copy(GEN x, long *plx) {
     140             :   GEN y;
     141   332050176 :   *plx = lg(x); y = new_chunk((size_t)*plx);
     142   332049832 :   y[0] = x[0] & (TYPBITS|LGBITS); return y;
     143             : }
     144             : INLINE GEN
     145       31542 : cgetg_block(long x, long y)
     146             : {
     147       31542 :   GEN z = newblock((size_t)x);
     148       31542 :   z[0] = evaltyp(y) | evallg(x);
     149       31542 :   return z;
     150             : }
     151             : INLINE GEN
     152  4111805188 : cgetg(long x, long y)
     153             : {
     154  4111805188 :   GEN z = new_chunk((size_t)x);
     155  4112027307 :   z[0] = evaltyp(y) | evallg(x);
     156  4111258688 :   return z;
     157             : }
     158             : INLINE GEN
     159 11881362963 : cgeti(long x)
     160             : {
     161 11881362963 :   GEN z = new_chunk((size_t)x);
     162 11868641822 :   z[0] = evaltyp(t_INT) | evallg(x);
     163 11859521928 :   return z;
     164             : }
     165             : INLINE GEN
     166  7017769753 : cgetipos(long x)
     167             : {
     168  7017769753 :   GEN z = cgeti(x);
     169  7016612405 :   z[1] = evalsigne(1) | evallgefint(x);
     170  7016612405 :   return z;
     171             : }
     172             : INLINE GEN
     173   199479270 : cgetineg(long x)
     174             : {
     175   199479270 :   GEN z = cgeti(x);
     176   199479287 :   z[1] = evalsigne(-1) | evallgefint(x);
     177   199479287 :   return z;
     178             : }
     179             : INLINE GEN
     180        2725 : cgetr_block(long x)
     181             : {
     182        2725 :   GEN z = newblock((size_t)x);
     183        2725 :   z[0] = evaltyp(t_REAL) | evallg(x);
     184        2725 :   return z;
     185             : }
     186             : INLINE GEN
     187  5159838451 : cgetr(long x)
     188             : {
     189  5159838451 :   GEN z = new_chunk((size_t)x);
     190  5159838451 :   z[0] = evaltyp(t_REAL) | evallg(x);
     191  5159838451 :   return z;
     192             : }
     193             : 
     194             : /*******************************************************************/
     195             : /*                                                                 */
     196             : /*                     COPY, NEGATION, ABSOLUTE VALUE              */
     197             : /*                                                                 */
     198             : /*******************************************************************/
     199             : /* cannot do memcpy because sometimes x and y overlap */
     200             : INLINE GEN
     201  1083283371 : leafcopy(GEN x)
     202             : {
     203  1083283371 :   register long lx = lg(x);
     204  1083283371 :   GEN y = new_chunk(lx); /* can't use cgetg_copy, in case x,y overlap */
     205  1083847172 :   while (--lx > 0) y[lx] = x[lx];
     206  1083847172 :   y[0] = x[0] & (TYPBITS|LGBITS); return y;
     207             : }
     208             : INLINE GEN
     209  4150563632 : icopy(GEN x)
     210             : {
     211  4150563632 :   long i = lgefint(x), lx = i;
     212  4150563632 :   GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */
     213  4153573438 :   while (--i > 0) y[i] = x[i];
     214  4153573438 :   y[0] = evaltyp(t_INT) | evallg(lx);
     215  4151535603 :   return y;
     216             : }
     217             : INLINE GEN
     218    36217317 : icopyspec(GEN x, long nx)
     219             : {
     220    36217317 :   long i = nx+2, lx = i;
     221    36217317 :   GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */
     222    36217333 :   x -= 2; while (--i >= 2) y[i] = x[i];
     223    36217333 :   y[1] = evalsigne(1) | evallgefint(lx);
     224    36217333 :   y[0] = evaltyp(t_INT) | evallg(lx);
     225    36217326 :   return y;
     226             : }
     227   185424112 : INLINE GEN rcopy(GEN x) { return leafcopy(x); }
     228     1153237 : INLINE GEN mpcopy(GEN x) { return leafcopy(x); }
     229             : 
     230             : INLINE GEN
     231   231735758 : mpabs(GEN x) { GEN y = leafcopy(x); setabssign(y); return y; }
     232             : INLINE GEN
     233         294 : mpabs_shallow(GEN x) { return signe(x) < 0? mpabs(x): x; }
     234   193656085 : INLINE GEN absi(GEN x) { return mpabs(x); }
     235      103005 : INLINE GEN absi_shallow(GEN x) { return signe(x) < 0? negi(x): x; }
     236    23804423 : INLINE GEN absr(GEN x) { return mpabs(x); }
     237             : 
     238             : INLINE GEN
     239   291237902 : mpneg(GEN x) { GEN y = leafcopy(x); togglesign(y); return y; }
     240   193824717 : INLINE GEN negi(GEN x) { return mpneg(x); }
     241     1170588 : INLINE GEN negr(GEN x) { return mpneg(x); }
     242             : 
     243             : /* negate in place */
     244             : INLINE void
     245   714307519 : togglesign(GEN x) { if (x[1] & SIGNBITS) { x[1] ^= HIGHBIT; } }
     246             : INLINE void
     247   265156865 : setabssign(GEN x) { x[1] &= ~HIGHBIT; }
     248             : /* negate in place, except universal constants */
     249             : INLINE void
     250    43153791 : togglesign_safe(GEN *px)
     251             : {
     252    43153791 :   switch(*px - gen_1) /* gen_1, gen_2, gen_m1, gen_m2 */
     253             :   {
     254      837859 :     case 0: *px = gen_m1; break;
     255           0 :     case 3: *px = gen_m2;  break;
     256      195248 :     case 6: *px = gen_1; break;
     257           0 :     case 9: *px = gen_2;  break;
     258    42120684 :     default: togglesign(*px);
     259             :   }
     260    43153791 : }
     261             : /* setsigne(y, signe(x)) */
     262             : INLINE void
     263           0 : affectsign(GEN x, GEN y)
     264             : {
     265           0 :   y[1] = (x[1] & SIGNBITS) | (y[1] & ~SIGNBITS);
     266           0 : }
     267             : /* copies sign in place, except for universal constants */
     268             : INLINE void
     269     5214521 : affectsign_safe(GEN x, GEN *py)
     270             : {
     271     5214521 :   if (((*py)[1] ^ x[1]) & HIGHBIT) togglesign_safe(py);
     272     5214521 : }
     273             : /*******************************************************************/
     274             : /*                                                                 */
     275             : /*                     GEN -> LONG, LONG -> GEN                    */
     276             : /*                                                                 */
     277             : /*******************************************************************/
     278             : /* assume x != 0, return -x as a t_INT */
     279             : INLINE GEN
     280   199318693 : utoineg(ulong x) { GEN y = cgetineg(3); y[2] = x; return y; }
     281             : /* assume x != 0, return utoi(x) */
     282             : INLINE GEN
     283  5989149127 : utoipos(ulong x) { GEN y = cgetipos(3); y[2] = x; return y; }
     284             : INLINE GEN
     285  5000059718 : utoi(ulong x) { return x? utoipos(x): gen_0; }
     286             : INLINE GEN
     287   304255713 : stoi(long x)
     288             : {
     289   304255713 :   if (!x) return gen_0;
     290   188859558 :   return x > 0? utoipos((ulong)x): utoineg((ulong)-x);
     291             : }
     292             : 
     293             : /* x 2^BIL + y */
     294             : INLINE GEN
     295  3565238849 : uutoi(ulong x, ulong y)
     296             : {
     297             :   GEN z;
     298  3565238849 :   if (!x) return utoi(y);
     299   392546385 :   z = cgetipos(4);
     300   392092262 :   *int_W_lg(z, 1, 4) = x;
     301   392092262 :   *int_W_lg(z, 0, 4) = y; return z;
     302             : }
     303             : /* - (x 2^BIL + y) */
     304             : INLINE GEN
     305       60215 : uutoineg(ulong x, ulong y)
     306             : {
     307             :   GEN z;
     308       60215 :   if (!x) return y? utoineg(y): gen_0;
     309           0 :   z = cgetineg(4);
     310           0 :   *int_W_lg(z, 1, 4) = x;
     311           0 :   *int_W_lg(z, 0, 4) = y; return z;
     312             : }
     313             : 
     314             : INLINE long
     315   197100820 : itos(GEN x)
     316             : {
     317   197100820 :   long s = signe(x);
     318             :   long u;
     319             : 
     320   197100820 :   if (!s) return 0;
     321   186118688 :   u = x[2];
     322   186118688 :   if (lgefint(x) > 3 || u < 0)
     323          19 :     pari_err_OVERFLOW("t_INT-->long assignment");
     324   186118705 :   return (s>0) ? u : -u;
     325             : }
     326             : /* as itos, but return 0 if too large. Cf is_bigint */
     327             : INLINE long
     328     7167736 : itos_or_0(GEN x) {
     329             :   long n;
     330     7167736 :   if (lgefint(x) != 3 || (n = x[2]) & HIGHBIT) return 0;
     331     7148469 :   return signe(x) > 0? n: -n;
     332             : }
     333             : INLINE ulong
     334    25954420 : itou(GEN x)
     335             : {
     336    25954420 :   switch(lgefint(x)) {
     337     5424027 :     case 2: return 0;
     338    20530393 :     case 3: return x[2];
     339             :     default:
     340           0 :       pari_err_OVERFLOW("t_INT-->ulong assignment");
     341           0 :       return 0; /* not reached */
     342             :   }
     343             : }
     344             : 
     345             : /* as itou, but return 0 if too large. Cf is_bigint */
     346             : INLINE ulong
     347     4156591 : itou_or_0(GEN x) {
     348     4156591 :   if (lgefint(x) != 3) return 0;
     349     4146567 :   return (ulong)x[2];
     350             : }
     351             : 
     352             : INLINE GEN
     353    76599817 : real_0_bit(long bitprec) { GEN x=cgetr(2); x[1]=evalexpo(bitprec); return x; }
     354             : INLINE GEN
     355    24952175 : real_0(long prec) { return real_0_bit(-prec2nbits(prec)); }
     356             : INLINE GEN
     357      478149 : real_1_bit(long bit) { return real_1(nbits2prec(bit)); }
     358             : INLINE GEN
     359    27364213 : real_1(long prec) {
     360    27364213 :   GEN x = cgetr(prec);
     361             :   long i;
     362    27364213 :   x[1] = evalsigne(1) | _evalexpo(0);
     363    27364213 :   x[2] = (long)HIGHBIT; for (i=3; i<prec; i++) x[i] = 0;
     364    27364213 :   return x;
     365             : }
     366             : INLINE GEN
     367          84 : real_m1(long prec) {
     368          84 :   GEN x = cgetr(prec);
     369             :   long i;
     370          84 :   x[1] = evalsigne(-1) | _evalexpo(0);
     371          84 :   x[2] = (long)HIGHBIT; for (i=3; i<prec; i++) x[i] = 0;
     372          84 :   return x;
     373             : }
     374             : 
     375             : /* 2.^n */
     376             : INLINE GEN
     377       49207 : real2n(long n, long prec) { GEN z = real_1(prec); setexpo(z, n); return z; }
     378             : INLINE GEN
     379           0 : real_m2n(long n, long prec) { GEN z = real_m1(prec); setexpo(z, n); return z; }
     380             : INLINE GEN
     381   145598798 : stor(long s, long prec) { GEN z = cgetr(prec); affsr(s,z); return z; }
     382             : INLINE GEN
     383     1740895 : utor(ulong s, long prec){ GEN z = cgetr(prec); affur(s,z); return z; }
     384             : INLINE GEN
     385   132188294 : itor(GEN x, long prec) { GEN z = cgetr(prec); affir(x,z); return z; }
     386             : INLINE GEN
     387    72415244 : rtor(GEN x, long prec) { GEN z = cgetr(prec); affrr(x,z); return z; }
     388             : 
     389     5248319 : INLINE ulong int_bit(GEN x, long n)
     390             : {
     391     5248319 :   long r, q = dvmdsBIL(n, &r);
     392     5249252 :   return q < lgefint(x)-2?((ulong)*int_W(x,q) >> r) & 1UL:0;
     393             : }
     394             : 
     395             : /*******************************************************************/
     396             : /*                                                                 */
     397             : /*                           COMPARISON                            */
     398             : /*                                                                 */
     399             : /*******************************************************************/
     400             : INLINE int
     401      672632 : cmpir(GEN x, GEN y)
     402             : {
     403             :   pari_sp av;
     404             :   GEN z;
     405             : 
     406      672632 :   if (!signe(x)) return -signe(y);
     407      299032 :   if (!signe(y))
     408             :   {
     409        4468 :     if (expo(y) >= expi(x)) return 0;
     410        4440 :     return signe(x);
     411             :   }
     412      294564 :   av=avma; z = itor(x, realprec(y)); avma=av;
     413      294564 :   return cmprr(z,y); /* cmprr does no memory adjustment */
     414             : }
     415             : INLINE int
     416      436400 : cmpri(GEN x, GEN y) { return -cmpir(y,x); }
     417             : INLINE int
     418       61690 : cmpsr(long x, GEN y)
     419             : {
     420             :   pari_sp av;
     421             :   GEN z;
     422             : 
     423       61690 :   if (!x) return -signe(y);
     424       61690 :   av=avma; z = stor(x, LOWDEFAULTPREC); avma=av;
     425       61690 :   return cmprr(z,y);
     426             : }
     427             : INLINE int
     428       38640 : cmprs(GEN x, long y) { return -cmpsr(y,x); }
     429             : /* compare x and |y| */
     430             : INLINE int
     431    22784943 : abscmpui(ulong x, GEN y)
     432             : {
     433    22784943 :   long l = lgefint(y);
     434             :   ulong p;
     435             : 
     436    22784943 :   if (!x) return (l > 2)? -1: 0;
     437    22784929 :   if (l == 2) return 1;
     438    22594559 :   if (l > 3) return -1;
     439    22584118 :   p = y[2]; if (p == x) return 0;
     440    22194745 :   return p < x ? 1 : -1;
     441             : }
     442             : INLINE int
     443    22732371 : abscmpiu(GEN x, ulong y) { return -abscmpui(y,x); }
     444             : INLINE int
     445     4126818 : cmpsi(long x, GEN y)
     446             : {
     447             :   ulong p;
     448             : 
     449     4126818 :   if (!x) return -signe(y);
     450             : 
     451     4126209 :   if (x > 0)
     452             :   {
     453     4125908 :     if (signe(y)<=0) return 1;
     454     4125789 :     if (lgefint(y)>3) return -1;
     455     4112364 :     p = y[2]; if (p == (ulong)x) return 0;
     456     4078575 :     return p < (ulong)x ? 1 : -1;
     457             :   }
     458             : 
     459         301 :   if (signe(y)>=0) return -1;
     460          42 :   if (lgefint(y)>3) return 1;
     461          42 :   p = y[2]; if (p == (ulong)-x) return 0;
     462          14 :   return p < (ulong)(-x) ? -1 : 1;
     463             : }
     464             : INLINE int
     465     4125250 : cmpis(GEN x, long y) { return -cmpsi(y,x); }
     466             : INLINE int
     467      509317 : mpcmp(GEN x, GEN y)
     468             : {
     469      509317 :   if (typ(x)==t_INT)
     470        6387 :     return (typ(y)==t_INT) ? cmpii(x,y) : cmpir(x,y);
     471      502930 :   return (typ(y)==t_INT) ? -cmpir(y,x) : cmprr(x,y);
     472             : }
     473             : 
     474             : /* x == y ? */
     475             : INLINE int
     476      102490 : equalsi(long x, GEN y)
     477             : {
     478      102490 :   if (!x) return !signe(y);
     479      102490 :   if (x > 0)
     480             :   {
     481       33043 :     if (signe(y) <= 0 || lgefint(y) != 3) return 0;
     482       30082 :     return ((ulong)y[2] == (ulong)x);
     483             :   }
     484       69447 :   if (signe(y) >= 0 || lgefint(y) != 3) return 0;
     485       69447 :   return ((ulong)y[2] == (ulong)-x);
     486             : }
     487             : /* x == |y| ? */
     488             : INLINE int
     489    11611427 : absequalui(ulong x, GEN y)
     490             : {
     491    11611427 :   if (!x) return !signe(y);
     492    11611427 :   return (lgefint(y) == 3 && (ulong)y[2] == x);
     493             : }
     494             : INLINE int
     495    11508213 : absequaliu(GEN x, ulong y) { return absequalui(y,x); }
     496             : INLINE int
     497      102371 : equalis(GEN x, long y) { return equalsi(y,x); }
     498             : 
     499             : /* assume x != 0, is |x| == 2^n ? */
     500             : INLINE int
     501      761787 : absrnz_equal2n(GEN x) {
     502      761787 :   if ((ulong)x[2]==HIGHBIT)
     503             :   {
     504       31353 :     long i, lx = lg(x);
     505      393985 :     for (i = 3; i < lx; i++)
     506      368353 :       if (x[i]) return 0;
     507       25632 :     return 1;
     508             :   }
     509      730434 :   return 0;
     510             : }
     511             : /* assume x != 0, is |x| == 1 ? */
     512             : INLINE int
     513     1216649 : absrnz_equal1(GEN x) { return !expo(x) && absrnz_equal2n(x); }
     514             : 
     515             : INLINE long
     516  2547502361 : maxss(long x, long y) { return x>y?x:y; }
     517             : INLINE long
     518   817368373 : minss(long x, long y) { return x<y?x:y; }
     519             : INLINE long
     520     3268453 : minuu(ulong x, ulong y) { return x<y?x:y; }
     521             : INLINE long
     522     6498168 : maxuu(ulong x, ulong y) { return x>y?x:y; }
     523             : INLINE double
     524      930973 : maxdd(double x, double y) { return x>y?x:y; }
     525             : INLINE double
     526      384161 : mindd(double x, double y) { return x<y?x:y; }
     527             : 
     528             : /*******************************************************************/
     529             : /*                                                                 */
     530             : /*                             ADD / SUB                           */
     531             : /*                                                                 */
     532             : /*******************************************************************/
     533             : INLINE GEN
     534       25018 : subuu(ulong x, ulong y)
     535             : {
     536             :   ulong z;
     537             :   LOCAL_OVERFLOW;
     538       25018 :   z = subll(x, y);
     539       25018 :   return overflow? utoineg(-z): utoi(z);
     540             : }
     541             : INLINE GEN
     542  1443896001 : adduu(ulong x, ulong y) { ulong t = x+y; return uutoi((t < x), t); }
     543             : 
     544             : INLINE GEN
     545       25018 : addss(long x, long y)
     546             : {
     547       25018 :   if (!x) return stoi(y);
     548       25018 :   if (!y) return stoi(x);
     549       25018 :   if (x > 0) return y > 0? adduu(x,y): subuu(x, -y);
     550             : 
     551       25018 :   if (y > 0) return subuu(y, -x);
     552             :   else { /* - adduu(-x, -y) */
     553           0 :     ulong t = (-x)+(-y); return uutoineg((t < (ulong)(-x)), t);
     554             :   }
     555             : }
     556       25018 : INLINE GEN subss(long x, long y) { return addss(-y,x); }
     557             : 
     558             : INLINE GEN
     559  3691228721 : subii(GEN x, GEN y)
     560             : {
     561  3691228721 :   if (x==y) return gen_0; /* frequent with x = y = gen_0 */
     562  2695012654 :   return addii_sign(x, signe(x), y, -signe(y));
     563             : }
     564             : INLINE GEN
     565  4187942608 : addii(GEN x, GEN y) { return addii_sign(x, signe(x), y, signe(y)); }
     566             : INLINE GEN
     567   694353553 : addrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, signe(y)); }
     568             : INLINE GEN
     569   817875240 : subrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, -signe(y)); }
     570             : INLINE GEN
     571   102312179 : addir(GEN x, GEN y) { return addir_sign(x, signe(x), y, signe(y)); }
     572             : INLINE GEN
     573    75086479 : subir(GEN x, GEN y) { return addir_sign(x, signe(x), y, -signe(y)); }
     574             : INLINE GEN
     575     1350721 : subri(GEN x, GEN y) { return addir_sign(y, -signe(y), x, signe(x)); }
     576             : INLINE GEN
     577    77970562 : addsi(long x, GEN y) { return addsi_sign(x, y, signe(y)); }
     578             : INLINE GEN
     579     9365545 : addui(ulong x, GEN y) { return addui_sign(x, y, signe(y)); }
     580             : INLINE GEN
     581     3361718 : subsi(long x, GEN y) { return addsi_sign(x, y, -signe(y)); }
     582             : INLINE GEN
     583    14460056 : subui(ulong x, GEN y) { return addui_sign(x, y, -signe(y)); }
     584             : 
     585             : /*******************************************************************/
     586             : /*                                                                 */
     587             : /*                           MOD, REM, DIV                         */
     588             : /*                                                                 */
     589             : /*******************************************************************/
     590    74979937 : INLINE ulong mod2BIL(GEN x) { return *int_LSW(x); }
     591           0 : INLINE long mod64(GEN x) { return mod2BIL(x) & 63; }
     592         252 : INLINE long mod32(GEN x) { return mod2BIL(x) & 31; }
     593       57596 : INLINE long mod16(GEN x) { return mod2BIL(x) & 15; }
     594    39190017 : INLINE long mod8(GEN x)  { return mod2BIL(x) & 7; }
     595     9398253 : INLINE long mod4(GEN x)  { return mod2BIL(x) & 3; }
     596    15647973 : INLINE long mod2(GEN x)  { return mod2BIL(x) & 1; }
     597             : INLINE int
     598    21970188 : mpodd(GEN x) { return signe(x) && mod2(x); }
     599             : /* x mod 2^n, n < BITS_IN_LONG */
     600             : INLINE ulong
     601     5443802 : umodi2n(GEN x, long n)
     602             : {
     603     5443802 :   long s = signe(x);
     604     5443802 :   const ulong _2n = 1UL << n;
     605             :   ulong m;
     606     5443802 :   if (!s) return 0;
     607     5433967 :   m = *int_LSW(x) & (_2n - 1);
     608     5433967 :   if (s < 0 && m) m = _2n - m;
     609     5433967 :   return m;
     610             : }
     611           0 : INLINE ulong Mod64(GEN x){ return umodi2n(x,6); }
     612      166572 : INLINE ulong Mod32(GEN x){ return umodi2n(x,5); }
     613      167454 : INLINE ulong Mod16(GEN x){ return umodi2n(x,4); }
     614     1307992 : INLINE ulong Mod8(GEN x) { return umodi2n(x,3); }
     615     1323378 : INLINE ulong Mod4(GEN x) { return umodi2n(x,2); }
     616     2478336 : INLINE ulong Mod2(GEN x) { return umodi2n(x,1); }
     617             : 
     618             : INLINE GEN
     619    34660075 : truedivii(GEN a,GEN b) { return truedvmdii(a,b,NULL); }
     620             : INLINE GEN
     621         652 : truedivis(GEN a, long b) { return truedvmdis(a,b,NULL); }
     622             : INLINE GEN
     623     6083965 : truedivsi(long a, GEN b) { return truedvmdsi(a,b,NULL); }
     624             : 
     625             : INLINE GEN
     626     8098395 : divii(GEN a, GEN b) { return dvmdii(a,b,NULL); }
     627             : INLINE GEN
     628  1192591429 : remii(GEN a, GEN b) { return dvmdii(a,b,ONLY_REM); }
     629             : 
     630             : INLINE GEN
     631           0 : divss(long x, long y) { return stoi(x / y); }
     632             : INLINE GEN
     633      600483 : modss(long x, long y) { return stoi(smodss(x, y)); }
     634             : INLINE GEN
     635           0 : remss(long x, long y) { return stoi(x % y); }
     636             : INLINE long
     637     6300853 : smodss(long x, long y)
     638             : {
     639     6300853 :   long r = x%y;
     640     6300853 :   return (r >= 0)? r: labs(y) + r;
     641             : }
     642             : INLINE ulong
     643    11830744 : umodsu(long x, ulong y)
     644             : {
     645    11830744 :   return x>=0 ? x%y: Fl_neg((-x)%y, y);
     646             : }
     647             : 
     648             : INLINE long
     649           0 : sdivss_rem(long x, long y, long *r)
     650             : {
     651             :   long q;
     652             :   LOCAL_HIREMAINDER;
     653           0 :   if (!y) pari_err_INV("sdivss_rem",gen_0);
     654           0 :   hiremainder = 0; q = divll((ulong)labs(x),(ulong)labs(y));
     655           0 :   if (x < 0) { hiremainder = -((long)hiremainder); q = -q; }
     656           0 :   if (y < 0) q = -q;
     657           0 :   *r = hiremainder; return q;
     658             : }
     659             : INLINE GEN
     660           0 : divss_rem(long x, long y, long *r) { return stoi(sdivss_rem(x,y,r)); }
     661             : INLINE ulong
     662         455 : udivuu_rem(ulong x, ulong y, ulong *r)
     663             : {
     664         455 :   if (!y) pari_err_INV("udivuu_rem",gen_0);
     665         455 :   *r = x % y; return x / y;
     666             : }
     667             : INLINE ulong
     668       71497 : ceildivuu(ulong a, ulong b)
     669             : {
     670       71497 :   ulong c = a/b;
     671       71497 :   return (a%b)? c+1: c;
     672             : }
     673             : 
     674             : 
     675             : INLINE ulong
     676       10780 : udivui_rem(ulong x, GEN y, ulong *r)
     677             : {
     678       10780 :   long q, s = signe(y);
     679             :   LOCAL_HIREMAINDER;
     680             : 
     681       10780 :   if (!s) pari_err_INV("udivui_rem",gen_0);
     682       10780 :   if (!x || lgefint(y)>3) { *r = x; return 0; }
     683       10500 :   hiremainder=0; q = (long)divll(x, (ulong)y[2]);
     684       10500 :   if (s < 0) q = -q;
     685       10500 :   *r = hiremainder; return q;
     686             : }
     687             : 
     688             : /* assume d != 0 and |n| / d can be represented as an ulong.
     689             :  * Return |n|/d, set *r = |n| % d */
     690             : INLINE ulong
     691    12480475 : udiviu_rem(GEN n, ulong d, ulong *r)
     692             : {
     693    12480475 :   switch(lgefint(n))
     694             :   {
     695           0 :     case 2: *r = 0; return 0;
     696             :     case 3:
     697             :     {
     698    12480475 :       ulong nn = n[2];
     699    12480475 :       *r = nn % d; return nn / d;
     700             :     }
     701             :     default: /* 4 */
     702             :     {
     703             :       ulong n1, n0, q;
     704             :       LOCAL_HIREMAINDER;
     705           0 :       n0 = *int_W(n,0);
     706           0 :       n1 = *int_W(n,1);
     707           0 :       hiremainder = n1;
     708           0 :       q = divll(n0, d);
     709           0 :       *r = hiremainder; return q;
     710             :     }
     711             :   }
     712             : }
     713             : 
     714             : INLINE long
     715    13557529 : sdivsi_rem(long x, GEN y, long *r)
     716             : {
     717    13557529 :   long q, s = signe(y);
     718             :   LOCAL_HIREMAINDER;
     719             : 
     720    13557529 :   if (!s) pari_err_INV("sdivsi_rem",gen_0);
     721    13557530 :   if (!x || lgefint(y)>3 || ((long)y[2]) < 0) { *r = x; return 0; }
     722    11882351 :   hiremainder=0; q = (long)divll(labs(x), (ulong)y[2]);
     723    11882351 :   if (x < 0) { hiremainder = -((long)hiremainder); q = -q; }
     724    11882351 :   if (s < 0) q = -q;
     725    11882351 :   *r = hiremainder; return q;
     726             : }
     727             : INLINE GEN
     728           0 : divsi_rem(long s, GEN y, long *r) { return stoi(sdivsi_rem(s,y,r)); }
     729             : 
     730             : INLINE long
     731          98 : sdivsi(long x, GEN y)
     732             : {
     733          98 :   long q, s = signe(y);
     734             : 
     735          98 :   if (!s) pari_err_INV("sdivsi",gen_0);
     736          98 :   if (!x || lgefint(y)>3 || ((long)y[2]) < 0) return 0;
     737          70 :   q = labs(x) / y[2];
     738          70 :   if (x < 0) q = -q;
     739          70 :   if (s < 0) q = -q;
     740          70 :   return q;
     741             : }
     742             : 
     743             : INLINE GEN
     744           0 : dvmdss(long x, long y, GEN *z)
     745             : {
     746             :   long r;
     747           0 :   GEN q = divss_rem(x,y, &r);
     748           0 :   *z = stoi(r); return q;
     749             : }
     750             : INLINE long
     751  2505211611 : dvmdsBIL(long n, long *r) { *r = remsBIL(n); return divsBIL(n); }
     752             : INLINE ulong
     753   160687855 : dvmduBIL(ulong n, ulong *r) { *r = remsBIL(n); return divsBIL(n); }
     754             : INLINE GEN
     755           0 : dvmdsi(long x, GEN y, GEN *z)
     756             : {
     757             :   long r;
     758           0 :   GEN q = divsi_rem(x,y, &r);
     759           0 :   *z = stoi(r); return q;
     760             : }
     761             : INLINE GEN
     762           0 : dvmdis(GEN x, long y, GEN *z)
     763             : {
     764             :   long r;
     765           0 :   GEN q = divis_rem(x,y, &r);
     766           0 :   *z = stoi(r); return q;
     767             : }
     768             : 
     769             : INLINE long
     770     1240171 : smodis(GEN x, long y)
     771             : {
     772     1240171 :   pari_sp av = avma;
     773             :   long r;
     774     1240171 :   (void)divis_rem(x,y, &r); avma = av; return (r >= 0) ? r: labs(y) + r;
     775             : }
     776             : INLINE GEN
     777       36887 : modis(GEN x, long y) { return stoi(smodis(x,y)); }
     778             : INLINE GEN
     779     7473318 : modsi(long x, GEN y) {
     780             :   long r;
     781     7473318 :   (void)sdivsi_rem(x, y, &r);
     782     7473320 :   return (r >= 0)? stoi(r): addsi_sign(r, y, 1);
     783             : }
     784             : 
     785             : INLINE ulong
     786     1197605 : umodui(ulong x, GEN y)
     787             : {
     788     1197605 :   if (!signe(y)) pari_err_INV("umodui",gen_0);
     789     1197605 :   if (!x || lgefint(y) > 3) return x;
     790      204035 :   return x % (ulong)y[2];
     791             : }
     792             : 
     793             : INLINE GEN
     794           0 : remsi(long x, GEN y)
     795           0 : { long r; (void)sdivsi_rem(x,y, &r); return stoi(r); }
     796             : INLINE GEN
     797           0 : remis(GEN x, long y)
     798             : {
     799           0 :   pari_sp av = avma;
     800             :   long r;
     801           0 :   (void)divis_rem(x,y, &r); avma = av; return stoi(r);
     802             : }
     803             : 
     804             : INLINE GEN
     805           0 : rdivis(GEN x, long y, long prec)
     806             : {
     807           0 :   GEN z = cgetr(prec);
     808           0 :   pari_sp av = avma;
     809           0 :   affrr(divrs(itor(x,prec), y),z);
     810           0 :   avma = av; return z;
     811             : }
     812             : INLINE GEN
     813           0 : rdivsi(long x, GEN y, long prec)
     814             : {
     815           0 :   GEN z = cgetr(prec);
     816           0 :   pari_sp av = avma;
     817           0 :   affrr(divsr(x, itor(y,prec)), z);
     818           0 :   avma = av; return z;
     819             : }
     820             : INLINE GEN
     821      839647 : rdivss(long x, long y, long prec)
     822             : {
     823      839647 :   GEN z = cgetr(prec);
     824      839647 :   pari_sp av = avma;
     825      839647 :   affrr(divrs(stor(x, prec), y), z);
     826      839647 :   avma = av; return z;
     827             : }
     828             : 
     829             : INLINE void
     830          14 : rdiviiz(GEN x, GEN y, GEN z)
     831             : {
     832          14 :   pari_sp av = avma;
     833          14 :   long prec = realprec(z);
     834          14 :   affir(x, z);
     835          14 :   if (!is_bigint(y)) {
     836           0 :     affrr(divrs(z, y[2]), z);
     837           0 :     if (signe(y) < 0) togglesign(z);
     838             :   }
     839             :   else
     840          14 :     affrr(divrr(z, itor(y,prec)), z);
     841          14 :   avma = av;
     842          14 : }
     843             : INLINE GEN
     844    11602488 : rdivii(GEN x, GEN y, long prec)
     845             : {
     846    11602488 :   GEN z = cgetr(prec);
     847    11602488 :   pari_sp av = avma;
     848    11602488 :   affir(x, z);
     849    11602488 :   if (lg(y) == 3) {
     850     7519736 :     affrr(divru(z, y[2]), z);
     851     7519736 :     if (signe(y) < 0) togglesign(z);
     852             :   }
     853             :   else
     854     4082752 :     affrr(divrr(z, itor(y,prec)), z);
     855    11602488 :   avma = av; return z;
     856             : }
     857             : INLINE GEN
     858    11547784 : fractor(GEN x, long prec) { return rdivii(gel(x,1), gel(x,2), prec); }
     859             : 
     860             : INLINE int
     861     1337264 : dvdii(GEN x, GEN y)
     862             : {
     863     1337264 :   pari_sp av=avma;
     864     1337264 :   GEN r = remii(x,y);
     865     1337264 :   avma = av; return r == gen_0;
     866             : }
     867             : INLINE int
     868          77 : dvdsi(long x, GEN y)
     869             : {
     870          77 :   if (!signe(y)) return x == 0;
     871          77 :   if (lgefint(y) != 3) return 0;
     872          77 :   return x % y[2] == 0;
     873             : }
     874             : INLINE int
     875         147 : dvdui(ulong x, GEN y)
     876             : {
     877         147 :   if (!signe(y)) return x == 0;
     878         147 :   if (lgefint(y) != 3) return 0;
     879         147 :   return x % y[2] == 0;
     880             : }
     881             : INLINE int
     882       31477 : dvdis(GEN x, long y)
     883       31477 : { return y? smodis(x, y) == 0: signe(x) == 0; }
     884             : INLINE int
     885        1561 : dvdiu(GEN x, ulong y)
     886        1561 : { return y? umodiu(x, y) == 0: signe(x) == 0; }
     887             : 
     888             : INLINE int
     889           0 : dvdisz(GEN x, long y, GEN z)
     890             : {
     891           0 :   const pari_sp av = avma;
     892             :   long r;
     893           0 :   GEN p1 = divis_rem(x,y, &r);
     894           0 :   avma = av; if (r) return 0;
     895           0 :   affii(p1,z); return 1;
     896             : }
     897             : INLINE int
     898           0 : dvdiuz(GEN x, ulong y, GEN z)
     899             : {
     900           0 :   const pari_sp av = avma;
     901             :   ulong r;
     902           0 :   GEN p1 = diviu_rem(x,y, &r);
     903           0 :   avma = av; if (r) return 0;
     904           0 :   affii(p1,z); return 1;
     905             : }
     906             : INLINE int
     907        3768 : dvdiiz(GEN x, GEN y, GEN z)
     908             : {
     909        3768 :   const pari_sp av=avma;
     910             :   GEN p2;
     911        3768 :   const GEN p1=dvmdii(x,y,&p2);
     912             : 
     913        3768 :   if (signe(p2)) { avma=av; return 0; }
     914        3275 :   affii(p1,z); avma=av; return 1;
     915             : }
     916             : 
     917             : INLINE ulong
     918     6254883 : remlll_pre(ulong u2, ulong u1, ulong u0, ulong n, ulong ninv)
     919             : {
     920     6254883 :   u1 = remll_pre(u2, u1, n, ninv);
     921     6254883 :   return remll_pre(u1, u0, n, ninv);
     922             : }
     923             : 
     924             : INLINE ulong
     925  1876232621 : Fl_sqr_pre(ulong a, ulong p, ulong pi)
     926             : {
     927             :   register ulong x;
     928             :   LOCAL_HIREMAINDER;
     929  1876232621 :   x = mulll(a,a);
     930  1876232621 :   return remll_pre(hiremainder, x, p, pi);
     931             : }
     932             : 
     933             : INLINE ulong
     934  2397791536 : Fl_mul_pre(ulong a, ulong b, ulong p, ulong pi)
     935             : {
     936             :   register ulong x;
     937             :   LOCAL_HIREMAINDER;
     938  2397791536 :   x = mulll(a,b);
     939  2397791536 :   return remll_pre(hiremainder, x, p, pi);
     940             : }
     941             : 
     942             : INLINE ulong
     943  4237902036 : Fl_addmul_pre(ulong x0, ulong x1, ulong y0, ulong p, ulong pi)
     944             : {
     945             :   ulong l0, h0;
     946             :   LOCAL_HIREMAINDER;
     947  4237902036 :   hiremainder = y0;
     948  4237902036 :   l0 = addmul(x0, x1); h0 = hiremainder;
     949  4237902036 :   return remll_pre(h0, l0, p, pi);
     950             : }
     951             : 
     952             : INLINE ulong
     953    45155570 : Fl_addmulmul_pre(ulong x0, ulong y0, ulong x1, ulong y1, ulong p, ulong pi)
     954             : {
     955             :   ulong l0, l1, h0, h1;
     956             :   LOCAL_OVERFLOW;
     957             :   LOCAL_HIREMAINDER;
     958    45155570 :   l0 = mulll(x0, y0); h0 = hiremainder;
     959    45155570 :   l1 = mulll(x1, y1); h1 = hiremainder;
     960    45155570 :   l0 = addll(l0, l1); h0 = addllx(h0, h1);
     961    45155570 :   return overflow ? remlll_pre(1, h0, l0, p, pi): remll_pre(h0, l0, p, pi);
     962             : }
     963             : 
     964             : INLINE ulong
     965     2702412 : Fl_ellj_pre(ulong a4, ulong a6, ulong p, ulong pi)
     966             : {
     967             :   /* a43 = 4 a4^3 */
     968     2702412 :   ulong a43 = Fl_double(Fl_double(
     969             :               Fl_mul_pre(a4, Fl_sqr_pre(a4, p, pi), p, pi), p), p);
     970             :   /* a62 = 27 a6^2 */
     971     2702413 :   ulong a62 = Fl_mul_pre(Fl_sqr_pre(a6, p, pi), 27 % p, p, pi);
     972     2702415 :   ulong z1 = Fl_mul_pre(a43, 1728 % p, p, pi);
     973     2702415 :   ulong z2 = Fl_add(a43, a62, p);
     974     2702415 :   return Fl_div(z1, z2, p);
     975             : }
     976             : 
     977             : /*******************************************************************/
     978             : /*                                                                 */
     979             : /*                        MP (INT OR REAL)                         */
     980             : /*                                                                 */
     981             : /*******************************************************************/
     982             : INLINE GEN
     983          21 : mptrunc(GEN x) { return typ(x)==t_INT? icopy(x): truncr(x); }
     984             : INLINE GEN
     985           0 : mpfloor(GEN x) { return typ(x)==t_INT? icopy(x): floorr(x); }
     986             : INLINE GEN
     987           0 : mpceil(GEN x) { return typ(x)==t_INT? icopy(x): ceilr(x); }
     988             : INLINE GEN
     989      357984 : mpround(GEN x) { return typ(x) == t_INT? icopy(x): roundr(x); }
     990             : 
     991             : INLINE long
     992      203267 : mpexpo(GEN x) { return typ(x) == t_INT? expi(x): expo(x); }
     993             : 
     994             : INLINE GEN
     995    22048142 : mpadd(GEN x, GEN y)
     996             : {
     997    22048142 :   if (typ(x)==t_INT)
     998     4057065 :     return (typ(y)==t_INT) ? addii(x,y) : addir(x,y);
     999    17991077 :   return (typ(y)==t_INT) ? addir(y,x) : addrr(x,y);
    1000             : }
    1001             : INLINE GEN
    1002    12339566 : mpsub(GEN x, GEN y)
    1003             : {
    1004    12339566 :   if (typ(x)==t_INT)
    1005      230145 :     return (typ(y)==t_INT) ? subii(x,y) : subir(x,y);
    1006    12109421 :   return (typ(y)==t_INT) ? subri(x,y) : subrr(x,y);
    1007             : }
    1008             : INLINE GEN
    1009    32730797 : mpmul(GEN x, GEN y)
    1010             : {
    1011    32730797 :   if (typ(x)==t_INT)
    1012     4910190 :     return (typ(y)==t_INT) ? mulii(x,y) : mulir(x,y);
    1013    27820607 :   return (typ(y)==t_INT) ? mulir(y,x) : mulrr(x,y);
    1014             : }
    1015             : INLINE GEN
    1016     4099007 : mpsqr(GEN x) { return (typ(x)==t_INT) ? sqri(x) : sqrr(x); }
    1017             : INLINE GEN
    1018      137523 : mpdiv(GEN x, GEN y)
    1019             : {
    1020      137523 :   if (typ(x)==t_INT)
    1021       71024 :     return (typ(y)==t_INT) ? divii(x,y) : divir(x,y);
    1022       66499 :   return (typ(y)==t_INT) ? divri(x,y) : divrr(x,y);
    1023             : }
    1024             : 
    1025             : /*******************************************************************/
    1026             : /*                                                                 */
    1027             : /*                          Z/nZ, n ULONG                          */
    1028             : /*                                                                 */
    1029             : /*******************************************************************/
    1030             : INLINE ulong
    1031   643319649 : Fl_double(ulong a, ulong p)
    1032             : {
    1033   643319649 :   ulong res = a << 1;
    1034   643319649 :   return (res >= p || res < a) ? res - p : res;
    1035             : }
    1036             : INLINE ulong
    1037   100190445 : Fl_triple(ulong a, ulong p)
    1038             : {
    1039   100190445 :   ulong res = a << 1;
    1040   100190445 :   if (res >= p || res < a) res -= p;
    1041   100190445 :   res += a;
    1042   100190445 :   return (res >= p || res < a)? res - p: res;
    1043             : }
    1044             : INLINE ulong
    1045    12749186 : Fl_halve(ulong a, ulong p)
    1046             : {
    1047             :   ulong ap, ap2;
    1048    12749186 :   if ((a&1UL)==0) return a>>1;
    1049     6440181 :   ap = a + p; ap2 = ap>>1;
    1050     6440181 :   return ap>=a ? ap2: (ap2|HIGHBIT);
    1051             : }
    1052             : 
    1053             : INLINE ulong
    1054  2946431766 : Fl_add(ulong a, ulong b, ulong p)
    1055             : {
    1056  2946431766 :   ulong res = a + b;
    1057  2946431766 :   return (res >= p || res < a) ? res - p : res;
    1058             : }
    1059             : INLINE ulong
    1060    68292844 : Fl_neg(ulong x, ulong p) { return x ? p - x: 0; }
    1061             : 
    1062             : INLINE ulong
    1063  4052599975 : Fl_sub(ulong a, ulong b, ulong p)
    1064             : {
    1065  4052599975 :   ulong res = a - b;
    1066  4052599975 :   return (res > a) ? res + p: res;
    1067             : }
    1068             : 
    1069             : /* centerlift(u mod p) */
    1070             : INLINE long
    1071    19462755 : Fl_center(ulong u, ulong p, ulong ps2) { return (long) (u > ps2)? u - p: u; }
    1072             : 
    1073             : INLINE ulong
    1074  1097139815 : Fl_mul(ulong a, ulong b, ulong p)
    1075             : {
    1076             :   register ulong x;
    1077             :   LOCAL_HIREMAINDER;
    1078  1097139815 :   x = mulll(a,b);
    1079  1097139815 :   if (!hiremainder) return x % p;
    1080   187245613 :   (void)divll(x,p); return hiremainder;
    1081             : }
    1082             : INLINE ulong
    1083   111553884 : Fl_sqr(ulong a, ulong p)
    1084             : {
    1085             :   register ulong x;
    1086             :   LOCAL_HIREMAINDER;
    1087   111553884 :   x = mulll(a,a);
    1088   111553884 :   if (!hiremainder) return x % p;
    1089    33574749 :   (void)divll(x,p); return hiremainder;
    1090             : }
    1091             : INLINE ulong
    1092    15664466 : Fl_div(ulong a, ulong b, ulong p) { return Fl_mul(a, Fl_inv(b, p), p); }
    1093             : 
    1094             : /*******************************************************************/
    1095             : /*                                                                 */
    1096             : /*        DEFINED FROM EXISTING ONE EXPLOITING COMMUTATIVITY       */
    1097             : /*                                                                 */
    1098             : /*******************************************************************/
    1099             : INLINE GEN
    1100      177446 : addri(GEN x, GEN y) { return addir(y,x); }
    1101             : INLINE GEN
    1102    70797601 : addis(GEN x, long s) { return addsi(s,x); }
    1103             : INLINE GEN
    1104     9299052 : addiu(GEN x, ulong s) { return addui(s,x); }
    1105             : INLINE GEN
    1106     2530167 : addrs(GEN x, long s) { return addsr(s,x); }
    1107             : 
    1108             : INLINE GEN
    1109    11077231 : subiu(GEN x, long y) { GEN z = subui(y, x); togglesign(z); return z; }
    1110             : INLINE GEN
    1111     5660172 : subis(GEN x, long y) { return addsi(-y,x); }
    1112             : INLINE GEN
    1113     2742190 : subrs(GEN x, long y) { return addsr(-y,x); }
    1114             : 
    1115             : INLINE GEN
    1116   115872726 : mulis(GEN x, long s) { return mulsi(s,x); }
    1117             : INLINE GEN
    1118   559993834 : muliu(GEN x, ulong s) { return mului(s,x); }
    1119             : INLINE GEN
    1120     3937255 : mulru(GEN x, ulong s) { return mulur(s,x); }
    1121             : INLINE GEN
    1122    13965358 : mulri(GEN x, GEN s) { return mulir(s,x); }
    1123             : INLINE GEN
    1124    10015339 : mulrs(GEN x, long s) { return mulsr(s,x); }
    1125             : 
    1126             : /*******************************************************************/
    1127             : /*                                                                 */
    1128             : /*                  VALUATION, EXPONENT, SHIFTS                    */
    1129             : /*                                                                 */
    1130             : /*******************************************************************/
    1131             : INLINE long
    1132    63087041 : vali(GEN x)
    1133             : {
    1134             :   long i;
    1135             :   GEN xp;
    1136             : 
    1137    63087041 :   if (!signe(x)) return -1;
    1138    63087041 :   xp=int_LSW(x);
    1139    63087041 :   for (i=0; !*xp; i++) xp=int_nextW(xp);
    1140    63087041 :   return vals(*xp) + i * BITS_IN_LONG;
    1141             : }
    1142             : 
    1143             : 
    1144             : /* assume x > 0 */
    1145             : INLINE long
    1146   299296677 : expu(ulong x) { return (BITS_IN_LONG-1) - (long)bfffo(x); }
    1147             : 
    1148             : INLINE long
    1149   722866689 : expi(GEN x)
    1150             : {
    1151   722866689 :   const long lx=lgefint(x);
    1152   722866689 :   return lx==2? -(long)HIGHEXPOBIT: bit_accuracy(lx)-(long)bfffo(*int_MSW(x))-1;
    1153             : }
    1154             : 
    1155             : INLINE GEN
    1156    46267288 : shiftr(GEN x, long n)
    1157             : {
    1158    46267288 :   const long e = evalexpo(expo(x)+n);
    1159    46267288 :   const GEN y = rcopy(x);
    1160             : 
    1161    46267288 :   if (e & ~EXPOBITS) pari_err_OVERFLOW("expo()");
    1162    46267288 :   y[1] = (y[1]&~EXPOBITS) | e; return y;
    1163             : }
    1164             : INLINE GEN
    1165    11057172 : mpshift(GEN x,long s) { return (typ(x)==t_INT)?shifti(x,s):shiftr(x,s); }
    1166             : 
    1167             : /* FIXME: adapt/use mpn_[lr]shift instead */
    1168             : /* z2[imin..imax] := z1[imin..imax].f shifted left sh bits
    1169             :  * (feeding f from the right). Assume sh > 0 */
    1170             : INLINE void
    1171  2552237201 : shift_left(GEN z2, GEN z1, long imin, long imax, ulong f,  ulong sh)
    1172             : {
    1173  2552237201 :   GEN sb = z1 + imin, se = z1 + imax, te = z2 + imax;
    1174  2552237201 :   ulong l, m = BITS_IN_LONG - sh, k = f >> m;
    1175 12472182399 :   while (se > sb) {
    1176  7367707997 :     l     = *se--;
    1177  7367707997 :     *te-- = (l << sh) | k;
    1178  7367707997 :     k     = l >> m;
    1179             :   }
    1180  2552237201 :   *te = (((ulong)*se) << sh) | k;
    1181  2552237201 : }
    1182             : /* z2[imin..imax] := f.z1[imin..imax-1] shifted right sh bits
    1183             :  * (feeding f from the left). Assume sh > 0 */
    1184             : INLINE void
    1185  2529348289 : shift_right(GEN z2, GEN z1, long imin, long imax, ulong f, ulong sh)
    1186             : {
    1187  2529348289 :   GEN sb = z1 + imin, se = z1 + imax, tb = z2 + imin;
    1188  2529348289 :   ulong k, l = *sb++, m = BITS_IN_LONG - sh;
    1189  2529348289 :   *tb++ = (l >> sh) | (f << m);
    1190 13210294129 :   while (sb < se) {
    1191  8151597551 :     k     = l << m;
    1192  8151597551 :     l     = *sb++;
    1193  8151597551 :     *tb++ = (l >> sh) | k;
    1194             :   }
    1195  2529348289 : }
    1196             : 
    1197             : /* Backward compatibility. Inefficient && unused */
    1198             : extern ulong hiremainder;
    1199             : INLINE ulong
    1200           0 : shiftl(ulong x, ulong y)
    1201           0 : { hiremainder = x>>(BITS_IN_LONG-y); return (x<<y); }
    1202             : 
    1203             : INLINE ulong
    1204           0 : shiftlr(ulong x, ulong y)
    1205           0 : { hiremainder = x<<(BITS_IN_LONG-y); return (x>>y); }
    1206             : 
    1207             : INLINE void
    1208    78377129 : shiftr_inplace(GEN z, long d)
    1209             : {
    1210    78377129 :   setexpo(z, expo(z)+d);
    1211    78377129 : }
    1212             : 
    1213             : /*******************************************************************/
    1214             : /*                                                                 */
    1215             : /*                           ASSIGNMENT                            */
    1216             : /*                                                                 */
    1217             : /*******************************************************************/
    1218             : INLINE void
    1219    37764240 : affii(GEN x, GEN y)
    1220             : {
    1221    37764240 :   long lx = lgefint(x);
    1222    37764240 :   if (lg(y)<lx) pari_err_OVERFLOW("t_INT-->t_INT assignment");
    1223    37764251 :   while (--lx) y[lx] = x[lx];
    1224    37764251 : }
    1225             : INLINE void
    1226      263176 : affsi(long s, GEN x)
    1227             : {
    1228      263176 :   if (!s) x[1] = evalsigne(0) | evallgefint(2);
    1229             :   else
    1230             :   {
    1231      248771 :     if (s > 0) { x[1] = evalsigne( 1) | evallgefint(3); x[2] =  s; }
    1232       92106 :     else       { x[1] = evalsigne(-1) | evallgefint(3); x[2] = -s; }
    1233             :   }
    1234      263176 : }
    1235             : INLINE void
    1236     8404793 : affui(ulong u, GEN x)
    1237             : {
    1238     8404793 :   if (!u) x[1] = evalsigne(0) | evallgefint(2);
    1239     8403575 :   else  { x[1] = evalsigne(1) | evallgefint(3); x[2] = u; }
    1240     8404793 : }
    1241             : 
    1242             : INLINE void
    1243   145677177 : affsr(long x, GEN y)
    1244             : {
    1245   145677177 :   long sh, i, ly = lg(y);
    1246             : 
    1247   145677177 :   if (!x)
    1248             :   {
    1249     1366460 :     y[1] = evalexpo(-prec2nbits(ly));
    1250   147043637 :     return;
    1251             :   }
    1252   144310717 :   if (x < 0) {
    1253      165743 :     x = -x; sh = bfffo(x);
    1254      165743 :     y[1] = evalsigne(-1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1255             :   }
    1256             :   else
    1257             :   {
    1258   144144974 :     sh = bfffo(x);
    1259   144144974 :     y[1] = evalsigne(1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1260             :   }
    1261   144310717 :   y[2] = ((ulong)x)<<sh; for (i=3; i<ly; i++) y[i]=0;
    1262             : }
    1263             : 
    1264             : INLINE void
    1265     1822349 : affur(ulong x, GEN y)
    1266             : {
    1267     1822349 :   long sh, i, ly = lg(y);
    1268             : 
    1269     1822349 :   if (!x)
    1270             :   {
    1271         210 :     y[1] = evalexpo(-prec2nbits(ly));
    1272     1822559 :     return;
    1273             :   }
    1274     1822139 :   sh = bfffo(x);
    1275     1822139 :   y[1] = evalsigne(1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1276     1822139 :   y[2] = x<<sh; for (i=3; i<ly; i++) y[i] = 0;
    1277             : }
    1278             : 
    1279             : INLINE void
    1280       94473 : affiz(GEN x, GEN y) { if (typ(y)==t_INT) affii(x,y); else affir(x,y); }
    1281             : INLINE void
    1282           0 : affsz(long x, GEN y) { if (typ(y)==t_INT) affsi(x,y); else affsr(x,y); }
    1283             : INLINE void
    1284       96666 : mpaff(GEN x, GEN y) { if (typ(x)==t_INT) affiz(x, y); else affrr(x,y); }
    1285             : 
    1286             : /*******************************************************************/
    1287             : /*                                                                 */
    1288             : /*                    OPERATION + ASSIGNMENT                       */
    1289             : /*                                                                 */
    1290             : /*******************************************************************/
    1291             : 
    1292           0 : INLINE void addiiz(GEN x, GEN y, GEN z)
    1293           0 : { pari_sp av = avma; affii(addii(x,y),z); avma = av; }
    1294           0 : INLINE void addirz(GEN x, GEN y, GEN z)
    1295           0 : { pari_sp av = avma; affrr(addir(x,y),z); avma = av; }
    1296           0 : INLINE void addriz(GEN x, GEN y, GEN z)
    1297           0 : { pari_sp av = avma; affrr(addri(x,y),z); avma = av; }
    1298     1436864 : INLINE void addrrz(GEN x, GEN y, GEN z)
    1299     1436864 : { pari_sp av = avma; affrr(addrr(x,y),z); avma = av; }
    1300           0 : INLINE void addsiz(long s, GEN y, GEN z)
    1301           0 : { pari_sp av = avma; affii(addsi(s,y),z); avma = av; }
    1302           0 : INLINE void addsrz(long s, GEN y, GEN z)
    1303           0 : { pari_sp av = avma; affrr(addsr(s,y),z); avma = av; }
    1304           0 : INLINE void addssz(long s, long y, GEN z)
    1305           0 : { pari_sp av = avma; affii(addss(s,y),z); avma = av; }
    1306             : 
    1307          35 : INLINE void diviiz(GEN x, GEN y, GEN z)
    1308          35 : { pari_sp av = avma; affii(divii(x,y),z); avma = av; }
    1309           0 : INLINE void divirz(GEN x, GEN y, GEN z)
    1310           0 : { pari_sp av = avma; mpaff(divir(x,y),z); avma = av; }
    1311           0 : INLINE void divisz(GEN x, long y, GEN z)
    1312           0 : { pari_sp av = avma; affii(divis(x,y),z); avma = av; }
    1313           0 : INLINE void divriz(GEN x, GEN y, GEN z)
    1314           0 : { pari_sp av = avma; affrr(divri(x,y),z); avma = av; }
    1315         348 : INLINE void divrrz(GEN x, GEN y, GEN z)
    1316         348 : { pari_sp av = avma; affrr(divrr(x,y),z); avma = av; }
    1317       90548 : INLINE void divrsz(GEN y, long s, GEN z)
    1318       90548 : { pari_sp av = avma; affrr(divrs(y,s),z); avma = av; }
    1319           0 : INLINE void divsiz(long x, GEN y, GEN z)
    1320           0 : { long junk; affsi(sdivsi_rem(x,y,&junk), z); }
    1321           0 : INLINE void divsrz(long s, GEN y, GEN z)
    1322           0 : { pari_sp av = avma; mpaff(divsr(s,y),z); avma = av; }
    1323           0 : INLINE void divssz(long x, long y, GEN z)
    1324           0 : { affsi(x/y, z); }
    1325             : 
    1326           0 : INLINE void modisz(GEN y, long s, GEN z)
    1327           0 : { pari_sp av = avma; affii(modis(y,s),z); avma = av; }
    1328           0 : INLINE void modsiz(long s, GEN y, GEN z)
    1329           0 : { pari_sp av = avma; affii(modsi(s,y),z); avma = av; }
    1330           0 : INLINE void modssz(long s, long y, GEN z)
    1331           0 : { pari_sp av = avma; affii(modss(s,y),z); avma = av; }
    1332             : 
    1333           0 : INLINE void mpaddz(GEN x, GEN y, GEN z)
    1334           0 : { pari_sp av = avma; mpaff(mpadd(x,y),z); avma = av; }
    1335           0 : INLINE void mpsubz(GEN x, GEN y, GEN z)
    1336           0 : { pari_sp av = avma; mpaff(mpsub(x,y),z); avma = av; }
    1337           0 : INLINE void mpmulz(GEN x, GEN y, GEN z)
    1338           0 : { pari_sp av = avma; mpaff(mpmul(x,y),z); avma = av; }
    1339             : 
    1340           0 : INLINE void muliiz(GEN x, GEN y, GEN z)
    1341           0 : { pari_sp av = avma; affii(mulii(x,y),z); avma = av; }
    1342           0 : INLINE void mulirz(GEN x, GEN y, GEN z)
    1343           0 : { pari_sp av = avma; mpaff(mulir(x,y),z); avma = av; }
    1344           0 : INLINE void mulriz(GEN x, GEN y, GEN z)
    1345           0 : { pari_sp av = avma; mpaff(mulri(x,y),z); avma = av; }
    1346       56940 : INLINE void mulrrz(GEN x, GEN y, GEN z)
    1347       56940 : { pari_sp av = avma; affrr(mulrr(x,y),z); avma = av; }
    1348           0 : INLINE void mulsiz(long s, GEN y, GEN z)
    1349           0 : { pari_sp av = avma; affii(mulsi(s,y),z); avma = av; }
    1350           0 : INLINE void mulsrz(long s, GEN y, GEN z)
    1351           0 : { pari_sp av = avma; mpaff(mulsr(s,y),z); avma = av; }
    1352           0 : INLINE void mulssz(long s, long y, GEN z)
    1353           0 : { pari_sp av = avma; affii(mulss(s,y),z); avma = av; }
    1354             : 
    1355           0 : INLINE void remiiz(GEN x, GEN y, GEN z)
    1356           0 : { pari_sp av = avma; affii(remii(x,y),z); avma = av; }
    1357           0 : INLINE void remisz(GEN y, long s, GEN z)
    1358           0 : { pari_sp av = avma; affii(remis(y,s),z); avma = av; }
    1359           0 : INLINE void remsiz(long s, GEN y, GEN z)
    1360           0 : { pari_sp av = avma; affii(remsi(s,y),z); avma = av; }
    1361           0 : INLINE void remssz(long s, long y, GEN z)
    1362           0 : { pari_sp av = avma; affii(remss(s,y),z); avma = av; }
    1363             : 
    1364           0 : INLINE void subiiz(GEN x, GEN y, GEN z)
    1365           0 : { pari_sp av = avma; affii(subii(x,y),z); avma = av; }
    1366           0 : INLINE void subirz(GEN x, GEN y, GEN z)
    1367           0 : { pari_sp av = avma; affrr(subir(x,y),z); avma = av; }
    1368           0 : INLINE void subisz(GEN y, long s, GEN z)
    1369           0 : { pari_sp av = avma; affii(addsi(-s,y),z); avma = av; }
    1370           0 : INLINE void subriz(GEN x, GEN y, GEN z)
    1371           0 : { pari_sp av = avma; affrr(subri(x,y),z); avma = av; }
    1372     1295642 : INLINE void subrrz(GEN x, GEN y, GEN z)
    1373     1295642 : { pari_sp av = avma; affrr(subrr(x,y),z); avma = av; }
    1374           0 : INLINE void subrsz(GEN y, long s, GEN z)
    1375           0 : { pari_sp av = avma; affrr(addsr(-s,y),z); avma = av; }
    1376           0 : INLINE void subsiz(long s, GEN y, GEN z)
    1377           0 : { pari_sp av = avma; affii(subsi(s,y),z); avma = av; }
    1378           0 : INLINE void subsrz(long s, GEN y, GEN z)
    1379           0 : { pari_sp av = avma; affrr(subsr(s,y),z); avma = av; }
    1380           0 : INLINE void subssz(long x, long y, GEN z) { addssz(x,-y,z); }
    1381             : 
    1382             : INLINE void
    1383           0 : dvmdssz(long x, long y, GEN z, GEN t) {
    1384           0 :   pari_sp av = avma;
    1385             :   long r;
    1386           0 :   affii(divss_rem(x,y, &r), z); avma = av; affsi(r,t);
    1387           0 : }
    1388             : INLINE void
    1389           0 : dvmdsiz(long x, GEN y, GEN z, GEN t) {
    1390           0 :   pari_sp av = avma;
    1391             :   long r;
    1392           0 :   affii(divsi_rem(x,y, &r), z); avma = av; affsi(r,t);
    1393           0 : }
    1394             : INLINE void
    1395           0 : dvmdisz(GEN x, long y, GEN z, GEN t) {
    1396           0 :   pari_sp av = avma;
    1397             :   long r;
    1398           0 :   affii(divis_rem(x,y, &r),z); avma = av; affsi(r,t);
    1399           0 : }
    1400             : INLINE void
    1401           0 : dvmdiiz(GEN x, GEN y, GEN z, GEN t) {
    1402           0 :   pari_sp av = avma;
    1403             :   GEN r;
    1404           0 :   affii(dvmdii(x,y,&r),z); affii(r,t); avma=av;
    1405           0 : }

Generated by: LCOV version 1.11