Code coverage tests

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

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

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

LCOV - code coverage report
Current view: top level - kernel/none - level1.h (source / functions) Hit Total Coverage
Test: PARI/GP v2.12.1 lcov report (development 24782-f7724578b4) Lines: 567 728 77.9 %
Date: 2019-12-06 05:56:26 Functions: 203 270 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 49744599721 : evallg(long x)
      21             : {
      22 49744599721 :   if (x & ~LGBITS) pari_err_OVERFLOW("lg()");
      23 49745895682 :   return _evallg(x);
      24             : }
      25             : INLINE long
      26    26580606 : evalvalp(long x)
      27             : {
      28    26580606 :   long v = _evalvalp(x);
      29    26580606 :   if (v & ~VALPBITS) pari_err_OVERFLOW("valp()");
      30    26580597 :   return v;
      31             : }
      32             : INLINE long
      33  7194760791 : evalexpo(long x)
      34             : {
      35  7194760791 :   long v = _evalexpo(x);
      36  7194760791 :   if (v & ~EXPOBITS) pari_err_OVERFLOW("expo()");
      37  7193897021 :   return v;
      38             : }
      39             : INLINE long
      40     8082402 : evalprecp(long x)
      41             : {
      42     8082402 :   long v = _evalprecp(x);
      43     8082402 :   if (x & ~((1UL<<(BITS_IN_LONG-VALPnumBITS))-1)) pari_err_OVERFLOW("precp()");
      44     8082402 :   return v;
      45             : }
      46             : 
      47             : INLINE int
      48   157821585 : varncmp(long x, long y)
      49             : {
      50   157821585 :   if (varpriority[x] < varpriority[y]) return  1;
      51   121154189 :   if (varpriority[x] > varpriority[y]) return -1;
      52    64580874 :   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  1829271379 : stackdummy(pari_sp av, pari_sp ltop) {
      70  1829271379 :   long l = ((GEN)av) - ((GEN)ltop);
      71  1829271379 :   if (l > 0) {
      72   583487708 :     GEN z = (GEN)ltop;
      73   583487708 :     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  1829496804 : }
      79             : INLINE void
      80    61155736 : fixlg(GEN x, long ly) {
      81    61155736 :   long lx = lg(x), l = lx - ly;
      82    61155736 :   if (l > 0)
      83             :   { /* stackdummy(x+lx, x+ly) */
      84    43405997 :     GEN z = x + ly;
      85    43405997 :     z[0] = evaltyp(t_VECSMALL) | evallg(l);
      86    43406081 :     setlg(x, ly);
      87             : #ifdef DEBUG
      88             :     { long i; for (i = 1; i < l; i++) z[i] = 0; }
      89             : #endif
      90             :   }
      91    61155879 : }
      92             : /* update lg(z) before affrr(y, z)  [ to cater for precision loss ]*/
      93             : INLINE void
      94    17772588 : affrr_fixlg(GEN y, GEN z) { fixlg(z, lg(y)); affrr(y, z); }
      95             : 
      96             : /*******************************************************************/
      97             : /*                                                                 */
      98             : /*                       ALLOCATE ON STACK                         */
      99             : /*                                                                 */
     100             : /*******************************************************************/
     101             : INLINE void
     102 65097109790 : set_avma(ulong av) { avma = av; }
     103             : INLINE GEN
     104 47592266363 : new_chunk(size_t x) /* x is a number of longs */
     105             : {
     106 47592266363 :   GEN z = ((GEN) avma) - x;
     107             :   CHECK_CTRLC
     108 47592266363 :   if (x > (avma-pari_mainstack->bot) / sizeof(long))
     109           7 :     new_chunk_resize(x);
     110 47592266356 :   set_avma((pari_sp)z);
     111             : #ifdef MEMSTEP
     112             :   if (DEBUGMEM>1 && pari_mainstack->memused != DISABLE_MEMUSED) {
     113             :     long d = (long)pari_mainstack->memused - (long)z;
     114             :     if (labs(d) > 4*MEMSTEP)
     115             :     {
     116             :       pari_mainstack->memused = (pari_sp)z;
     117             :       err_printf("...%4.0lf Mbytes used\n",
     118             :                 (pari_mainstack->top-pari_mainstack->memused)/1048576.);
     119             :     }
     120             :   }
     121             : #endif
     122 47602520440 :   return z;
     123             : }
     124             : 
     125             : INLINE char *
     126     5295827 : stack_malloc(size_t N)
     127             : {
     128     5295827 :   long n = nchar2nlong(N);
     129     5295827 :   return (char*)new_chunk(n);
     130             : }
     131             : 
     132             : INLINE char *
     133     1454480 : stack_malloc_align(size_t N, long k)
     134             : {
     135     1454480 :   ulong d = ((ulong)avma) % k;
     136     1454480 :   if (d) (void)new_chunk(d/sizeof(long));
     137     1454480 :   return (char*) new_chunk(nchar2nlong(N));
     138             : }
     139             : 
     140             : INLINE char *
     141       56108 : stack_calloc(size_t N)
     142             : {
     143       56108 :   char *p = stack_malloc(N);
     144       56108 :   memset(p, 0, N); return p;
     145             : }
     146             : 
     147             : /* cgetg(lg(x), typ(x)), set *lx. Implicit unsetisclone() */
     148             : INLINE GEN
     149   579906967 : cgetg_copy(GEN x, long *plx) {
     150             :   GEN y;
     151   579906967 :   *plx = lg(x); y = new_chunk((size_t)*plx);
     152   579905354 :   y[0] = x[0] & (TYPBITS|LGBITS); return y;
     153             : }
     154             : INLINE GEN
     155      276447 : cgetg_block(long x, long y)
     156             : {
     157      276447 :   GEN z = newblock((size_t)x);
     158      276586 :   z[0] = CLONEBIT | evaltyp(y) | evallg(x);
     159      276539 :   return z;
     160             : }
     161             : INLINE GEN
     162  6934509107 : cgetg(long x, long y)
     163             : {
     164  6934509107 :   GEN z = new_chunk((size_t)x);
     165  6935068222 :   z[0] = evaltyp(y) | evallg(x);
     166  6933719603 :   return z;
     167             : }
     168             : INLINE GEN
     169 15332328168 : cgeti(long x)
     170             : {
     171 15332328168 :   GEN z = new_chunk((size_t)x);
     172 15323156401 :   z[0] = evaltyp(t_INT) | evallg(x);
     173 15314199591 :   return z;
     174             : }
     175             : INLINE GEN
     176  9158689839 : cgetipos(long x)
     177             : {
     178  9158689839 :   GEN z = cgeti(x);
     179  9156703042 :   z[1] = evalsigne(1) | evallgefint(x);
     180  9156703042 :   return z;
     181             : }
     182             : INLINE GEN
     183   227508921 : cgetineg(long x)
     184             : {
     185   227508921 :   GEN z = cgeti(x);
     186   227509015 :   z[1] = evalsigne(-1) | evallgefint(x);
     187   227509015 :   return z;
     188             : }
     189             : INLINE GEN
     190       23854 : cgetr_block(long x)
     191             : {
     192       23854 :   GEN z = newblock((size_t)x);
     193       23863 :   z[0] = CLONEBIT | evaltyp(t_REAL) | evallg(x);
     194       23858 :   return z;
     195             : }
     196             : INLINE GEN
     197  7428484192 : cgetr(long x)
     198             : {
     199  7428484192 :   GEN z = new_chunk((size_t)x);
     200  7427966462 :   z[0] = evaltyp(t_REAL) | evallg(x);
     201  7426536535 :   return z;
     202             : }
     203             : 
     204             : /*******************************************************************/
     205             : /*                                                                 */
     206             : /*                     COPY, NEGATION, ABSOLUTE VALUE              */
     207             : /*                                                                 */
     208             : /*******************************************************************/
     209             : /* cannot do memcpy because sometimes x and y overlap */
     210             : INLINE GEN
     211  1818022482 : leafcopy(GEN x)
     212             : {
     213  1818022482 :   register long lx = lg(x);
     214  1818022482 :   GEN y = new_chunk(lx); /* can't use cgetg_copy, in case x,y overlap */
     215  1818738589 :   while (--lx > 0) y[lx] = x[lx];
     216  1818738589 :   y[0] = x[0] & (TYPBITS|LGBITS); return y;
     217             : }
     218             : INLINE GEN
     219  4945645540 : icopy(GEN x)
     220             : {
     221  4945645540 :   long i = lgefint(x), lx = i;
     222  4945645540 :   GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */
     223  4950498754 :   while (--i > 0) y[i] = x[i];
     224  4950498754 :   y[0] = evaltyp(t_INT) | evallg(lx);
     225  4948930174 :   return y;
     226             : }
     227             : INLINE GEN
     228    37630526 : icopyspec(GEN x, long nx)
     229             : {
     230    37630526 :   long i = nx+2, lx = i;
     231    37630526 :   GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */
     232    37630438 :   x -= 2; while (--i >= 2) y[i] = x[i];
     233    37630438 :   y[1] = evalsigne(1) | evallgefint(lx);
     234    37630438 :   y[0] = evaltyp(t_INT) | evallg(lx);
     235    37630320 :   return y;
     236             : }
     237   312752779 : INLINE GEN rcopy(GEN x) { return leafcopy(x); }
     238         294 : INLINE GEN mpcopy(GEN x) { return leafcopy(x); }
     239             : 
     240             : INLINE GEN
     241   469680545 : mpabs(GEN x) { GEN y = leafcopy(x); setabssign(y); return y; }
     242             : INLINE GEN
     243     9679314 : mpabs_shallow(GEN x) { return signe(x) < 0? mpabs(x): x; }
     244   416007720 : INLINE GEN absi(GEN x) { return mpabs(x); }
     245    27957440 : INLINE GEN absi_shallow(GEN x) { return signe(x) < 0? negi(x): x; }
     246    39458452 : INLINE GEN absr(GEN x) { return mpabs(x); }
     247             : 
     248             : INLINE GEN
     249   477261067 : mpneg(GEN x) { GEN y = leafcopy(x); togglesign(y); return y; }
     250   365297864 : INLINE GEN negi(GEN x) { return mpneg(x); }
     251     1577360 : INLINE GEN negr(GEN x) { return mpneg(x); }
     252     9664712 : INLINE GEN gmax_shallow(GEN x, GEN y) { return gcmp(x,y)<0? y: x; }
     253      241831 : INLINE GEN gmin_shallow(GEN x, GEN y) { return gcmp(x,y)<0? x: y; }
     254             : 
     255             : /* negate in place */
     256             : INLINE void
     257   955422355 : togglesign(GEN x) { if (x[1] & SIGNBITS) { x[1] ^= HIGHBIT; } }
     258             : INLINE void
     259   523693185 : setabssign(GEN x) { x[1] &= ~HIGHBIT; }
     260             : /* negate in place, except universal constants */
     261             : INLINE void
     262    60824215 : togglesign_safe(GEN *px)
     263             : {
     264    60824215 :   switch(*px - gen_1) /* gen_1, gen_2, gen_m1, gen_m2 */
     265             :   {
     266      703374 :     case 0: *px = gen_m1; break;
     267           0 :     case 3: *px = gen_m2;  break;
     268      162197 :     case 6: *px = gen_1; break;
     269           0 :     case 9: *px = gen_2;  break;
     270    59958644 :     default: togglesign(*px);
     271             :   }
     272    60824215 : }
     273             : /* setsigne(y, signe(x)) */
     274             : INLINE void
     275           0 : affectsign(GEN x, GEN y)
     276             : {
     277           0 :   y[1] = (x[1] & SIGNBITS) | (y[1] & ~SIGNBITS);
     278           0 : }
     279             : /* copies sign in place, except for universal constants */
     280             : INLINE void
     281     5726367 : affectsign_safe(GEN x, GEN *py)
     282             : {
     283     5726367 :   if (((*py)[1] ^ x[1]) & HIGHBIT) togglesign_safe(py);
     284     5726367 : }
     285             : /*******************************************************************/
     286             : /*                                                                 */
     287             : /*                     GEN -> LONG, LONG -> GEN                    */
     288             : /*                                                                 */
     289             : /*******************************************************************/
     290             : /* assume x != 0, return -x as a t_INT */
     291             : INLINE GEN
     292   227323707 : utoineg(ulong x) { GEN y = cgetineg(3); y[2] = x; return y; }
     293             : /* assume x != 0, return utoi(x) */
     294             : INLINE GEN
     295  8207961445 : utoipos(ulong x) { GEN y = cgetipos(3); y[2] = x; return y; }
     296             : INLINE GEN
     297  6825846022 : utoi(ulong x) { return x? utoipos(x): gen_0; }
     298             : INLINE GEN
     299   367298073 : stoi(long x)
     300             : {
     301   367298073 :   if (!x) return gen_0;
     302   234868996 :   return x > 0? utoipos((ulong)x): utoineg((ulong)-x);
     303             : }
     304             : 
     305             : /* x 2^BIL + y */
     306             : INLINE GEN
     307  4567076403 : uutoi(ulong x, ulong y)
     308             : {
     309             :   GEN z;
     310  4567076403 :   if (!x) return utoi(y);
     311   373879642 :   z = cgetipos(4);
     312   373294537 :   *int_W_lg(z, 1, 4) = x;
     313   373294537 :   *int_W_lg(z, 0, 4) = y; return z;
     314             : }
     315             : /* - (x 2^BIL + y) */
     316             : INLINE GEN
     317      130827 : uutoineg(ulong x, ulong y)
     318             : {
     319             :   GEN z;
     320      130827 :   if (!x) return y? utoineg(y): gen_0;
     321       10243 :   z = cgetineg(4);
     322       10243 :   *int_W_lg(z, 1, 4) = x;
     323       10243 :   *int_W_lg(z, 0, 4) = y; return z;
     324             : }
     325             : 
     326             : INLINE long
     327   354054242 : itos(GEN x)
     328             : {
     329   354054242 :   long s = signe(x);
     330             :   long u;
     331             : 
     332   354054242 :   if (!s) return 0;
     333   338013852 :   u = x[2];
     334   338013852 :   if (lgefint(x) > 3 || u < 0)
     335          21 :     pari_err_OVERFLOW("t_INT-->long assignment");
     336   338013995 :   return (s>0) ? u : -u;
     337             : }
     338             : /* as itos, but return 0 if too large. Cf is_bigint */
     339             : INLINE long
     340    12829119 : itos_or_0(GEN x) {
     341             :   long n;
     342    12829119 :   if (lgefint(x) != 3 || (n = x[2]) & HIGHBIT) return 0;
     343    11207754 :   return signe(x) > 0? n: -n;
     344             : }
     345             : INLINE ulong
     346   115048421 : itou(GEN x)
     347             : {
     348   115048421 :   switch(lgefint(x)) {
     349     8714053 :     case 2: return 0;
     350   106334368 :     case 3: return x[2];
     351             :     default:
     352           0 :       pari_err_OVERFLOW("t_INT-->ulong assignment");
     353             :       return 0; /* LCOV_EXCL_LINE */
     354             :   }
     355             : }
     356             : 
     357             : /* as itou, but return 0 if too large. Cf is_bigint */
     358             : INLINE ulong
     359     4605882 : itou_or_0(GEN x) {
     360     4605882 :   if (lgefint(x) != 3) return 0;
     361     4595013 :   return (ulong)x[2];
     362             : }
     363             : 
     364             : INLINE ulong
     365     5143034 : umuluu_or_0(ulong x, ulong y)
     366             : {
     367             :   ulong z;
     368             :   LOCAL_HIREMAINDER;
     369     5143034 :   z = mulll(x, y);
     370     5143034 :   return hiremainder? 0: z;
     371             : }
     372             : /* return x*y if <= n, else 0. Beware overflow */
     373             : INLINE ulong
     374     2792160 : umuluu_le(ulong x, ulong y, ulong n)
     375             : {
     376             :   ulong z;
     377             :   LOCAL_HIREMAINDER;
     378     2792160 :   z = mulll(x, y);
     379     2792160 :   return (hiremainder || z > n)? 0: z;
     380             : }
     381             : 
     382             : INLINE GEN
     383   160013052 : real_0_bit(long bitprec) { GEN x=cgetr(2); x[1]=evalexpo(bitprec); return x; }
     384             : INLINE GEN
     385    40419352 : real_0(long prec) { return real_0_bit(-prec2nbits(prec)); }
     386             : INLINE GEN
     387      519937 : real_1_bit(long bit) { return real_1(nbits2prec(bit)); }
     388             : INLINE GEN
     389    37981648 : real_1(long prec) {
     390    37981648 :   GEN x = cgetr(prec);
     391             :   long i;
     392    37979204 :   x[1] = evalsigne(1) | _evalexpo(0);
     393    37979204 :   x[2] = (long)HIGHBIT; for (i=3; i<prec; i++) x[i] = 0;
     394    37979204 :   return x;
     395             : }
     396             : INLINE GEN
     397         147 : real_m1(long prec) {
     398         147 :   GEN x = cgetr(prec);
     399             :   long i;
     400         147 :   x[1] = evalsigne(-1) | _evalexpo(0);
     401         147 :   x[2] = (long)HIGHBIT; for (i=3; i<prec; i++) x[i] = 0;
     402         147 :   return x;
     403             : }
     404             : 
     405             : /* 2.^n */
     406             : INLINE GEN
     407      158841 : real2n(long n, long prec) { GEN z = real_1(prec); setexpo(z, n); return z; }
     408             : INLINE GEN
     409           0 : real_m2n(long n, long prec) { GEN z = real_m1(prec); setexpo(z, n); return z; }
     410             : INLINE GEN
     411   169022196 : stor(long s, long prec) { GEN z = cgetr(prec); affsr(s,z); return z; }
     412             : INLINE GEN
     413     9445424 : utor(ulong s, long prec){ GEN z = cgetr(prec); affur(s,z); return z; }
     414             : INLINE GEN
     415   251093186 : itor(GEN x, long prec) { GEN z = cgetr(prec); affir(x,z); return z; }
     416             : INLINE GEN
     417    85452803 : rtor(GEN x, long prec) { GEN z = cgetr(prec); affrr(x,z); return z; }
     418             : 
     419    11629115 : INLINE ulong int_bit(GEN x, long n)
     420             : {
     421    11629115 :   long r, q = dvmdsBIL(n, &r);
     422    11632775 :   return q < lgefint(x)-2?((ulong)*int_W(x,q) >> r) & 1UL:0;
     423             : }
     424             : 
     425             : /*******************************************************************/
     426             : /*                                                                 */
     427             : /*                           COMPARISON                            */
     428             : /*                                                                 */
     429             : /*******************************************************************/
     430             : INLINE int
     431      619164 : cmpir(GEN x, GEN y)
     432             : {
     433             :   pari_sp av;
     434             :   GEN z;
     435             : 
     436      619164 :   if (!signe(x)) return -signe(y);
     437      241680 :   if (!signe(y))
     438             :   {
     439        4005 :     if (expo(y) >= expi(x)) return 0;
     440        3977 :     return signe(x);
     441             :   }
     442      237675 :   av=avma; z = itor(x, realprec(y)); set_avma(av);
     443      237674 :   return cmprr(z,y); /* cmprr does no memory adjustment */
     444             : }
     445             : INLINE int
     446      365905 : cmpri(GEN x, GEN y) { return -cmpir(y,x); }
     447             : INLINE int
     448       96249 : cmpsr(long x, GEN y)
     449             : {
     450             :   pari_sp av;
     451             :   GEN z;
     452             : 
     453       96249 :   if (!x) return -signe(y);
     454       96249 :   av=avma; z = stor(x, LOWDEFAULTPREC); set_avma(av);
     455       96249 :   return cmprr(z,y);
     456             : }
     457             : INLINE int
     458       38682 : cmprs(GEN x, long y) { return -cmpsr(y,x); }
     459             : /* compare x and y */
     460             : INLINE int
     461     2430329 : cmpui(ulong x, GEN y)
     462             : {
     463             :   ulong p;
     464     2430329 :   if (!x) return -signe(y);
     465     2430329 :   if (signe(y) <= 0) return 1;
     466     2430322 :   if (lgefint(y) > 3) return -1;
     467     2430098 :   p = y[2]; if (p == x) return 0;
     468     2397587 :   return p < x ? 1 : -1;
     469             : }
     470             : INLINE int
     471     2430329 : cmpiu(GEN x, ulong y) { return -cmpui(y,x); }
     472             : /* compare x and |y| */
     473             : INLINE int
     474    25986255 : abscmpui(ulong x, GEN y)
     475             : {
     476    25986255 :   long l = lgefint(y);
     477             :   ulong p;
     478             : 
     479    25986255 :   if (!x) return (l > 2)? -1: 0;
     480    25986241 :   if (l == 2) return 1;
     481    25783661 :   if (l > 3) return -1;
     482    25771173 :   p = y[2]; if (p == x) return 0;
     483    25352465 :   return p < x ? 1 : -1;
     484             : }
     485             : INLINE int
     486    25526177 : abscmpiu(GEN x, ulong y) { return -abscmpui(y,x); }
     487             : INLINE int
     488     4245565 : cmpsi(long x, GEN y)
     489             : {
     490             :   ulong p;
     491             : 
     492     4245565 :   if (!x) return -signe(y);
     493             : 
     494     4244515 :   if (x > 0)
     495             :   {
     496     4243640 :     if (signe(y)<=0) return 1;
     497     4243318 :     if (lgefint(y)>3) return -1;
     498     4228060 :     p = y[2]; if (p == (ulong)x) return 0;
     499     4162001 :     return p < (ulong)x ? 1 : -1;
     500             :   }
     501             : 
     502         875 :   if (signe(y)>=0) return -1;
     503         147 :   if (lgefint(y)>3) return 1;
     504         147 :   p = y[2]; if (p == (ulong)-x) return 0;
     505          42 :   return p < (ulong)(-x) ? -1 : 1;
     506             : }
     507             : INLINE int
     508     4234962 : cmpis(GEN x, long y) { return -cmpsi(y,x); }
     509             : INLINE int
     510      573218 : mpcmp(GEN x, GEN y)
     511             : {
     512      573218 :   if (typ(x)==t_INT)
     513        9350 :     return (typ(y)==t_INT) ? cmpii(x,y) : cmpir(x,y);
     514      563868 :   return (typ(y)==t_INT) ? -cmpir(y,x) : cmprr(x,y);
     515             : }
     516             : 
     517             : /* x == y ? */
     518             : INLINE int
     519       31276 : equalui(ulong x, GEN y)
     520             : {
     521       31276 :   if (!x) return !signe(y);
     522       31276 :   if (signe(y) <= 0 || lgefint(y) != 3) return 0;
     523       31267 :   return ((ulong)y[2] == (ulong)x);
     524             : }
     525             : /* x == y ? */
     526             : INLINE int
     527      170108 : equalsi(long x, GEN y)
     528             : {
     529      170108 :   if (!x) return !signe(y);
     530      170108 :   if (x > 0)
     531             :   {
     532      170080 :     if (signe(y) <= 0 || lgefint(y) != 3) return 0;
     533      157268 :     return ((ulong)y[2] == (ulong)x);
     534             :   }
     535          28 :   if (signe(y) >= 0 || lgefint(y) != 3) return 0;
     536          28 :   return ((ulong)y[2] == (ulong)-x);
     537             : }
     538             : /* x == |y| ? */
     539             : INLINE int
     540    35178296 : absequalui(ulong x, GEN y)
     541             : {
     542    35178296 :   if (!x) return !signe(y);
     543    35178296 :   return (lgefint(y) == 3 && (ulong)y[2] == x);
     544             : }
     545             : INLINE int
     546    35071718 : absequaliu(GEN x, ulong y) { return absequalui(y,x); }
     547             : INLINE int
     548      169891 : equalis(GEN x, long y) { return equalsi(y,x); }
     549             : INLINE int
     550       31276 : equaliu(GEN x, ulong y) { return equalui(y,x); }
     551             : 
     552             : /* assume x != 0, is |x| == 2^n ? */
     553             : INLINE int
     554      288495 : absrnz_equal2n(GEN x) {
     555      288495 :   if ((ulong)x[2]==HIGHBIT)
     556             :   {
     557       16662 :     long i, lx = lg(x);
     558       72684 :     for (i = 3; i < lx; i++)
     559       64995 :       if (x[i]) return 0;
     560        7689 :     return 1;
     561             :   }
     562      271833 :   return 0;
     563             : }
     564             : /* assume x != 0, is |x| == 1 ? */
     565             : INLINE int
     566      650982 : absrnz_equal1(GEN x) { return !expo(x) && absrnz_equal2n(x); }
     567             : 
     568             : INLINE long
     569  3189754167 : maxss(long x, long y) { return x>y?x:y; }
     570             : INLINE long
     571   817876588 : minss(long x, long y) { return x<y?x:y; }
     572             : INLINE long
     573     2234523 : minuu(ulong x, ulong y) { return x<y?x:y; }
     574             : INLINE long
     575     6602916 : maxuu(ulong x, ulong y) { return x>y?x:y; }
     576             : INLINE double
     577     1157873 : maxdd(double x, double y) { return x>y?x:y; }
     578             : INLINE double
     579     1695191 : mindd(double x, double y) { return x<y?x:y; }
     580             : 
     581             : /*******************************************************************/
     582             : /*                                                                 */
     583             : /*                             ADD / SUB                           */
     584             : /*                                                                 */
     585             : /*******************************************************************/
     586             : INLINE GEN
     587       25046 : subuu(ulong x, ulong y)
     588             : {
     589             :   ulong z;
     590             :   LOCAL_OVERFLOW;
     591       25046 :   z = subll(x, y);
     592       25046 :   return overflow? utoineg(-z): utoi(z);
     593             : }
     594             : INLINE GEN
     595  2073035339 : adduu(ulong x, ulong y) { ulong t = x+y; return uutoi((t < x), t); }
     596             : 
     597             : INLINE GEN
     598       25046 : addss(long x, long y)
     599             : {
     600       25046 :   if (!x) return stoi(y);
     601       25046 :   if (!y) return stoi(x);
     602       25046 :   if (x > 0) return y > 0? adduu(x,y): subuu(x, -y);
     603             : 
     604       25046 :   if (y > 0) return subuu(y, -x);
     605             :   else { /* - adduu(-x, -y) */
     606           0 :     ulong t = (-x)+(-y); return uutoineg((t < (ulong)(-x)), t);
     607             :   }
     608             : }
     609       25046 : INLINE GEN subss(long x, long y) { return addss(-y,x); }
     610             : 
     611             : INLINE GEN
     612  4684270159 : subii(GEN x, GEN y)
     613             : {
     614  4684270159 :   if (x==y) return gen_0; /* frequent with x = y = gen_0 */
     615  3476120053 :   return addii_sign(x, signe(x), y, -signe(y));
     616             : }
     617             : INLINE GEN
     618  5466129443 : addii(GEN x, GEN y) { return addii_sign(x, signe(x), y, signe(y)); }
     619             : INLINE GEN
     620  1017971502 : addrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, signe(y)); }
     621             : INLINE GEN
     622  1299001788 : subrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, -signe(y)); }
     623             : INLINE GEN
     624   176990055 : addir(GEN x, GEN y) { return addir_sign(x, signe(x), y, signe(y)); }
     625             : INLINE GEN
     626   115675263 : subir(GEN x, GEN y) { return addir_sign(x, signe(x), y, -signe(y)); }
     627             : INLINE GEN
     628     1812749 : subri(GEN x, GEN y) { return addir_sign(y, -signe(y), x, signe(x)); }
     629             : INLINE GEN
     630    61356668 : addsi(long x, GEN y) { return addsi_sign(x, y, signe(y)); }
     631             : INLINE GEN
     632    75407505 : addui(ulong x, GEN y) { return addui_sign(x, y, signe(y)); }
     633             : INLINE GEN
     634     6706756 : subsi(long x, GEN y) { return addsi_sign(x, y, -signe(y)); }
     635             : INLINE GEN
     636    34335738 : subui(ulong x, GEN y) { return addui_sign(x, y, -signe(y)); }
     637             : 
     638             : /*******************************************************************/
     639             : /*                                                                 */
     640             : /*                           MOD, REM, DIV                         */
     641             : /*                                                                 */
     642             : /*******************************************************************/
     643   101483268 : INLINE ulong mod2BIL(GEN x) { return *int_LSW(x); }
     644           0 : INLINE long mod64(GEN x) { return mod2BIL(x) & 63; }
     645         259 : INLINE long mod32(GEN x) { return mod2BIL(x) & 31; }
     646      312011 : INLINE long mod16(GEN x) { return mod2BIL(x) & 15; }
     647    48351972 : INLINE long mod8(GEN x)  { return mod2BIL(x) & 7; }
     648    12033536 : INLINE long mod4(GEN x)  { return mod2BIL(x) & 3; }
     649    28023614 : INLINE long mod2(GEN x)  { return mod2BIL(x) & 1; }
     650             : INLINE int
     651    46262776 : mpodd(GEN x) { return signe(x) && mod2(x); }
     652             : /* x mod 2^n, n < BITS_IN_LONG */
     653             : INLINE ulong
     654     6317521 : umodi2n(GEN x, long n)
     655             : {
     656     6317521 :   long s = signe(x);
     657     6317521 :   const ulong _2n = 1UL << n;
     658             :   ulong m;
     659     6317521 :   if (!s) return 0;
     660     6310598 :   m = *int_LSW(x) & (_2n - 1);
     661     6310598 :   if (s < 0 && m) m = _2n - m;
     662     6310598 :   return m;
     663             : }
     664           0 : INLINE ulong Mod64(GEN x){ return umodi2n(x,6); }
     665      167062 : INLINE ulong Mod32(GEN x){ return umodi2n(x,5); }
     666      217049 : INLINE ulong Mod16(GEN x){ return umodi2n(x,4); }
     667     2042810 : INLINE ulong Mod8(GEN x) { return umodi2n(x,3); }
     668     2065063 : INLINE ulong Mod4(GEN x) { return umodi2n(x,2); }
     669     1825467 : INLINE ulong Mod2(GEN x) { return umodi2n(x,1); }
     670             : 
     671             : INLINE GEN
     672    25647867 : truedivii(GEN a,GEN b) { return truedvmdii(a,b,NULL); }
     673             : INLINE GEN
     674        5454 : truedivis(GEN a, long b) { return truedvmdis(a,b,NULL); }
     675             : INLINE GEN
     676     6168126 : truedivsi(long a, GEN b) { return truedvmdsi(a,b,NULL); }
     677             : 
     678             : INLINE GEN
     679     6547692 : divii(GEN a, GEN b) { return dvmdii(a,b,NULL); }
     680             : INLINE GEN
     681  1456794750 : remii(GEN a, GEN b) { return dvmdii(a,b,ONLY_REM); }
     682             : 
     683             : INLINE GEN
     684           0 : divss(long x, long y) { return stoi(x / y); }
     685             : INLINE GEN
     686           0 : modss(long x, long y) { return utoi(smodss(x, y)); }
     687             : INLINE GEN
     688           0 : remss(long x, long y) { return stoi(x % y); }
     689             : INLINE long
     690         595 : smodss(long x, long y)
     691             : {
     692         595 :   long r = x%y;
     693         595 :   return (r >= 0)? r: labs(y) + r;
     694             : }
     695             : INLINE ulong
     696   370520381 : umodsu(long x, ulong y)
     697             : {
     698   370520381 :   return x>=0 ? x%y: Fl_neg((-x)%y, y);
     699             : }
     700             : 
     701             : INLINE long
     702           0 : sdivss_rem(long x, long y, long *r)
     703             : {
     704             :   long q;
     705             :   LOCAL_HIREMAINDER;
     706           0 :   if (!y) pari_err_INV("sdivss_rem",gen_0);
     707           0 :   hiremainder = 0; q = divll((ulong)labs(x),(ulong)labs(y));
     708           0 :   if (x < 0) { hiremainder = -((long)hiremainder); q = -q; }
     709           0 :   if (y < 0) q = -q;
     710           0 :   *r = hiremainder; return q;
     711             : }
     712             : INLINE GEN
     713           0 : divss_rem(long x, long y, long *r) { return stoi(sdivss_rem(x,y,r)); }
     714             : INLINE ulong
     715    71283139 : udivuu_rem(ulong x, ulong y, ulong *r)
     716             : {
     717    71283139 :   if (!y) pari_err_INV("udivuu_rem",gen_0);
     718    71283139 :   *r = x % y; return x / y;
     719             : }
     720             : INLINE ulong
     721      204734 : ceildivuu(ulong a, ulong b)
     722             : {
     723      204734 :   ulong c = a/b;
     724      204734 :   return (a%b)? c+1: c;
     725             : }
     726             : 
     727             : INLINE ulong
     728       10591 : uabsdivui_rem(ulong x, GEN y, ulong *r)
     729             : {
     730       10591 :   long q, s = signe(y);
     731             :   LOCAL_HIREMAINDER;
     732             : 
     733       10591 :   if (!s) pari_err_INV("uabsdivui_rem",gen_0);
     734       10591 :   if (!x || lgefint(y)>3) { *r = x; return 0; }
     735       10318 :   hiremainder=0; q = (long)divll(x, (ulong)y[2]);
     736       10318 :   if (s < 0) q = -q;
     737       10318 :   *r = hiremainder; return q;
     738             : }
     739             : 
     740             : /* assume d != 0 and |n| / d can be represented as an ulong.
     741             :  * Return |n|/d, set *r = |n| % d */
     742             : INLINE ulong
     743    12480475 : uabsdiviu_rem(GEN n, ulong d, ulong *r)
     744             : {
     745    12480475 :   switch(lgefint(n))
     746             :   {
     747           0 :     case 2: *r = 0; return 0;
     748             :     case 3:
     749             :     {
     750    12480475 :       ulong nn = n[2];
     751    12480475 :       *r = nn % d; return nn / d;
     752             :     }
     753             :     default: /* 4 */
     754             :     {
     755             :       ulong n1, n0, q;
     756             :       LOCAL_HIREMAINDER;
     757           0 :       n0 = *int_W(n,0);
     758           0 :       n1 = *int_W(n,1);
     759           0 :       hiremainder = n1;
     760           0 :       q = divll(n0, d);
     761           0 :       *r = hiremainder; return q;
     762             :     }
     763             :   }
     764             : }
     765             : 
     766             : INLINE long
     767    14949348 : sdivsi_rem(long x, GEN y, long *r)
     768             : {
     769    14949348 :   long q, s = signe(y);
     770             :   LOCAL_HIREMAINDER;
     771             : 
     772    14949348 :   if (!s) pari_err_INV("sdivsi_rem",gen_0);
     773    14949348 :   if (!x || lgefint(y)>3 || ((long)y[2]) < 0) { *r = x; return 0; }
     774    13005230 :   hiremainder=0; q = (long)divll(labs(x), (ulong)y[2]);
     775    13005230 :   if (x < 0) { hiremainder = -((long)hiremainder); q = -q; }
     776    13005230 :   if (s < 0) q = -q;
     777    13005230 :   *r = hiremainder; return q;
     778             : }
     779             : INLINE GEN
     780           0 : divsi_rem(long s, GEN y, long *r) { return stoi(sdivsi_rem(s,y,r)); }
     781             : 
     782             : INLINE long
     783         140 : sdivsi(long x, GEN y)
     784             : {
     785         140 :   long q, s = signe(y);
     786             : 
     787         140 :   if (!s) pari_err_INV("sdivsi",gen_0);
     788         140 :   if (!x || lgefint(y)>3 || ((long)y[2]) < 0) return 0;
     789          98 :   q = labs(x) / y[2];
     790          98 :   if (x < 0) q = -q;
     791          98 :   if (s < 0) q = -q;
     792          98 :   return q;
     793             : }
     794             : 
     795             : INLINE GEN
     796           0 : dvmdss(long x, long y, GEN *z)
     797             : {
     798             :   long r;
     799           0 :   GEN q = divss_rem(x,y, &r);
     800           0 :   *z = stoi(r); return q;
     801             : }
     802             : INLINE long
     803  3597982335 : dvmdsBIL(long n, long *r) { *r = remsBIL(n); return divsBIL(n); }
     804             : INLINE ulong
     805   144800251 : dvmduBIL(ulong n, ulong *r) { *r = remsBIL(n); return divsBIL(n); }
     806             : INLINE GEN
     807           0 : dvmdsi(long x, GEN y, GEN *z)
     808             : {
     809             :   long r;
     810           0 :   GEN q = divsi_rem(x,y, &r);
     811           0 :   *z = stoi(r); return q;
     812             : }
     813             : INLINE GEN
     814           0 : dvmdis(GEN x, long y, GEN *z)
     815             : {
     816             :   long r;
     817           0 :   GEN q = divis_rem(x,y, &r);
     818           0 :   *z = stoi(r); return q;
     819             : }
     820             : 
     821             : INLINE long
     822    19630403 : smodis(GEN x, long y)
     823             : {
     824    19630403 :   pari_sp av = avma;
     825    19630403 :   long r; (void)divis_rem(x,y, &r);
     826    19630403 :   return gc_long(av, (r >= 0)? r: labs(y) + r);
     827             : }
     828             : INLINE GEN
     829    19591994 : modis(GEN x, long y) { return stoi(smodis(x,y)); }
     830             : INLINE GEN
     831     8780977 : modsi(long x, GEN y) {
     832     8780977 :   long r; (void)sdivsi_rem(x, y, &r);
     833     8780976 :   return (r >= 0)? stoi(r): addsi_sign(r, y, 1);
     834             : }
     835             : 
     836             : INLINE ulong
     837     1329350 : umodui(ulong x, GEN y)
     838             : {
     839     1329350 :   if (!signe(y)) pari_err_INV("umodui",gen_0);
     840     1329350 :   if (!x || lgefint(y) > 3) return x;
     841      301240 :   return x % (ulong)y[2];
     842             : }
     843             : 
     844             : INLINE ulong
     845       43267 : ugcdiu(GEN x, ulong y) { return ugcd(umodiu(x,y), y); }
     846             : INLINE ulong
     847        4792 : ugcdui(ulong y, GEN x) { return ugcd(umodiu(x,y), y); }
     848             : 
     849             : INLINE GEN
     850           0 : remsi(long x, GEN y)
     851           0 : { long r; (void)sdivsi_rem(x,y, &r); return stoi(r); }
     852             : INLINE GEN
     853           0 : remis(GEN x, long y)
     854             : {
     855           0 :   pari_sp av = avma;
     856             :   long r;
     857           0 :   (void)divis_rem(x,y, &r); set_avma(av); return stoi(r);
     858             : }
     859             : 
     860             : INLINE GEN
     861           0 : rdivis(GEN x, long y, long prec)
     862             : {
     863           0 :   GEN z = cgetr(prec);
     864           0 :   pari_sp av = avma;
     865           0 :   affrr(divrs(itor(x,prec), y),z);
     866           0 :   set_avma(av); return z;
     867             : }
     868             : INLINE GEN
     869           0 : rdivsi(long x, GEN y, long prec)
     870             : {
     871           0 :   GEN z = cgetr(prec);
     872           0 :   pari_sp av = avma;
     873           0 :   affrr(divsr(x, itor(y,prec)), z);
     874           0 :   set_avma(av); return z;
     875             : }
     876             : INLINE GEN
     877      839647 : rdivss(long x, long y, long prec)
     878             : {
     879      839647 :   GEN z = cgetr(prec);
     880      839647 :   pari_sp av = avma;
     881      839647 :   affrr(divrs(stor(x, prec), y), z);
     882      839647 :   set_avma(av); return z;
     883             : }
     884             : 
     885             : INLINE void
     886     4979348 : rdiviiz(GEN x, GEN y, GEN z)
     887             : {
     888     4979348 :   long prec = realprec(z), lx = lgefint(x), ly = lgefint(y);
     889     4979348 :   if (lx == 2) { affur(0, z); return; }
     890     4979348 :   if (ly == 3)
     891             :   {
     892      780908 :     affir(x, z); if (signe(y) < 0) togglesign(z);
     893      780908 :     affrr(divru(z, y[2]), z);
     894             :   }
     895     4198440 :   else if (lx > prec + 1 || ly > prec + 1)
     896             :   {
     897     1912343 :     affir(x,z); affrr(divri(z, y), z);
     898             :   }
     899             :   else
     900             :   {
     901     2286097 :     long b = bit_accuracy(prec) + expi(y) - expi(x) + 1;
     902     2286097 :     GEN q = divii(b > 0? shifti(x, b): x, y);
     903     2286097 :     affir(q, z); if (b > 0) shiftr_inplace(z, -b);
     904             :   }
     905     4979361 :   set_avma((ulong)z);
     906             : }
     907             : INLINE GEN
     908     4976596 : rdivii(GEN x, GEN y, long prec)
     909     4976596 : { GEN z = cgetr(prec); rdiviiz(x, y, z); return z; }
     910             : INLINE GEN
     911     4847144 : fractor(GEN x, long prec)
     912     4847144 : { return rdivii(gel(x,1), gel(x,2), prec); }
     913             : 
     914             : INLINE int
     915     7590728 : dvdii(GEN x, GEN y)
     916             : {
     917     7590728 :   pari_sp av = avma;
     918     7590728 :   GEN r = remii(x,y);
     919     7598874 :   return gc_bool(av, r == gen_0);
     920             : }
     921             : INLINE int
     922          84 : dvdsi(long x, GEN y)
     923             : {
     924          84 :   if (!signe(y)) return x == 0;
     925          84 :   if (lgefint(y) != 3) return 0;
     926          84 :   return x % y[2] == 0;
     927             : }
     928             : INLINE int
     929         147 : dvdui(ulong x, GEN y)
     930             : {
     931         147 :   if (!signe(y)) return x == 0;
     932         147 :   if (lgefint(y) != 3) return 0;
     933         147 :   return x % y[2] == 0;
     934             : }
     935             : INLINE int
     936        5621 : dvdis(GEN x, long y)
     937        5621 : { return y? smodis(x, y) == 0: signe(x) == 0; }
     938             : INLINE int
     939        3717 : dvdiu(GEN x, ulong y)
     940        3717 : { return y? umodiu(x, y) == 0: signe(x) == 0; }
     941             : 
     942             : INLINE int
     943           0 : dvdisz(GEN x, long y, GEN z)
     944             : {
     945           0 :   const pari_sp av = avma;
     946             :   long r;
     947           0 :   GEN p1 = divis_rem(x,y, &r);
     948           0 :   set_avma(av); if (r) return 0;
     949           0 :   affii(p1,z); return 1;
     950             : }
     951             : INLINE int
     952           0 : dvdiuz(GEN x, ulong y, GEN z)
     953             : {
     954           0 :   const pari_sp av = avma;
     955             :   ulong r;
     956           0 :   GEN p1 = absdiviu_rem(x,y, &r);
     957           0 :   set_avma(av); if (r) return 0;
     958           0 :   affii(p1,z); return 1;
     959             : }
     960             : INLINE int
     961        4139 : dvdiiz(GEN x, GEN y, GEN z)
     962             : {
     963        4139 :   const pari_sp av=avma;
     964        4139 :   GEN p2, p1 = dvmdii(x,y,&p2);
     965        4139 :   if (signe(p2)) return gc_bool(av,0);
     966        3345 :   affii(p1,z); return gc_bool(av,1);
     967             : }
     968             : 
     969             : INLINE ulong
     970    65868761 : remlll_pre(ulong u2, ulong u1, ulong u0, ulong n, ulong ninv)
     971             : {
     972    65868761 :   u1 = remll_pre(u2, u1, n, ninv);
     973    67053664 :   return remll_pre(u1, u0, n, ninv);
     974             : }
     975             : 
     976             : INLINE ulong
     977  1715697699 : Fl_sqr_pre(ulong a, ulong p, ulong pi)
     978             : {
     979             :   register ulong x;
     980             :   LOCAL_HIREMAINDER;
     981  1715697699 :   x = mulll(a,a);
     982  1715697699 :   return remll_pre(hiremainder, x, p, pi);
     983             : }
     984             : 
     985             : INLINE ulong
     986  2780379522 : Fl_mul_pre(ulong a, ulong b, ulong p, ulong pi)
     987             : {
     988             :   register ulong x;
     989             :   LOCAL_HIREMAINDER;
     990  2780379522 :   x = mulll(a,b);
     991  2780379522 :   return remll_pre(hiremainder, x, p, pi);
     992             : }
     993             : 
     994             : INLINE ulong
     995  5758675121 : Fl_addmul_pre(ulong y0, ulong x0, ulong x1, ulong p, ulong pi)
     996             : {
     997             :   ulong l0, h0;
     998             :   LOCAL_HIREMAINDER;
     999  5758675121 :   hiremainder = y0;
    1000  5758675121 :   l0 = addmul(x0, x1); h0 = hiremainder;
    1001  5758675121 :   return remll_pre(h0, l0, p, pi);
    1002             : }
    1003             : 
    1004             : INLINE ulong
    1005    47620368 : Fl_addmulmul_pre(ulong x0, ulong y0, ulong x1, ulong y1, ulong p, ulong pi)
    1006             : {
    1007             :   ulong l0, l1, h0, h1;
    1008             :   LOCAL_OVERFLOW;
    1009             :   LOCAL_HIREMAINDER;
    1010    47620368 :   l0 = mulll(x0, y0); h0 = hiremainder;
    1011    47620368 :   l1 = mulll(x1, y1); h1 = hiremainder;
    1012    47620368 :   l0 = addll(l0, l1); h0 = addllx(h0, h1);
    1013    47620368 :   return overflow ? remlll_pre(1, h0, l0, p, pi): remll_pre(h0, l0, p, pi);
    1014             : }
    1015             : 
    1016             : INLINE ulong
    1017      189158 : Fl_ellj_pre(ulong a4, ulong a6, ulong p, ulong pi)
    1018             : {
    1019             :   /* a43 = 4 a4^3 */
    1020      189158 :   ulong a43 = Fl_double(Fl_double(
    1021             :               Fl_mul_pre(a4, Fl_sqr_pre(a4, p, pi), p, pi), p), p);
    1022             :   /* a62 = 27 a6^2 */
    1023      189156 :   ulong a62 = Fl_mul_pre(Fl_sqr_pre(a6, p, pi), 27 % p, p, pi);
    1024      189157 :   ulong z1 = Fl_mul_pre(a43, 1728 % p, p, pi);
    1025      189156 :   ulong z2 = Fl_add(a43, a62, p);
    1026      189156 :   return Fl_div(z1, z2, p);
    1027             : }
    1028             : 
    1029             : /*******************************************************************/
    1030             : /*                                                                 */
    1031             : /*                        MP (INT OR REAL)                         */
    1032             : /*                                                                 */
    1033             : /*******************************************************************/
    1034             : INLINE GEN
    1035          21 : mptrunc(GEN x) { return typ(x)==t_INT? icopy(x): truncr(x); }
    1036             : INLINE GEN
    1037           0 : mpfloor(GEN x) { return typ(x)==t_INT? icopy(x): floorr(x); }
    1038             : INLINE GEN
    1039           0 : mpceil(GEN x) { return typ(x)==t_INT? icopy(x): ceilr(x); }
    1040             : INLINE GEN
    1041     1311896 : mpround(GEN x) { return typ(x) == t_INT? icopy(x): roundr(x); }
    1042             : 
    1043             : INLINE long
    1044      259144 : mpexpo(GEN x) { return typ(x) == t_INT? expi(x): expo(x); }
    1045             : 
    1046             : INLINE GEN
    1047    64391056 : mpadd(GEN x, GEN y)
    1048             : {
    1049    64391056 :   if (typ(x)==t_INT)
    1050    14714781 :     return (typ(y)==t_INT) ? addii(x,y) : addir(x,y);
    1051    49676275 :   return (typ(y)==t_INT) ? addir(y,x) : addrr(x,y);
    1052             : }
    1053             : INLINE GEN
    1054    28552032 : mpsub(GEN x, GEN y)
    1055             : {
    1056    28552032 :   if (typ(x)==t_INT)
    1057      260136 :     return (typ(y)==t_INT) ? subii(x,y) : subir(x,y);
    1058    28291896 :   return (typ(y)==t_INT) ? subri(x,y) : subrr(x,y);
    1059             : }
    1060             : INLINE GEN
    1061    87652626 : mpmul(GEN x, GEN y)
    1062             : {
    1063    87652626 :   if (typ(x)==t_INT)
    1064    23582476 :     return (typ(y)==t_INT) ? mulii(x,y) : mulir(x,y);
    1065    64070150 :   return (typ(y)==t_INT) ? mulir(y,x) : mulrr(x,y);
    1066             : }
    1067             : INLINE GEN
    1068    12530455 : mpsqr(GEN x) { return (typ(x)==t_INT) ? sqri(x) : sqrr(x); }
    1069             : INLINE GEN
    1070      239260 : mpdiv(GEN x, GEN y)
    1071             : {
    1072      239260 :   if (typ(x)==t_INT)
    1073      126924 :     return (typ(y)==t_INT) ? divii(x,y) : divir(x,y);
    1074      112336 :   return (typ(y)==t_INT) ? divri(x,y) : divrr(x,y);
    1075             : }
    1076             : 
    1077             : /*******************************************************************/
    1078             : /*                                                                 */
    1079             : /*                          Z/nZ, n ULONG                          */
    1080             : /*                                                                 */
    1081             : /*******************************************************************/
    1082             : INLINE ulong
    1083   364485682 : Fl_double(ulong a, ulong p)
    1084             : {
    1085   364485682 :   ulong res = a << 1;
    1086   364485682 :   return (res >= p || res < a) ? res - p : res;
    1087             : }
    1088             : INLINE ulong
    1089    70797132 : Fl_triple(ulong a, ulong p)
    1090             : {
    1091    70797132 :   ulong res = a << 1;
    1092    70797132 :   if (res >= p || res < a) res -= p;
    1093    70797132 :   res += a;
    1094    70797132 :   return (res >= p || res < a)? res - p: res;
    1095             : }
    1096             : INLINE ulong
    1097    14081815 : Fl_halve(ulong a, ulong p)
    1098             : {
    1099             :   ulong ap, ap2;
    1100    14081815 :   if ((a&1UL)==0) return a>>1;
    1101     7110553 :   ap = a + p; ap2 = ap>>1;
    1102     7110553 :   return ap>=a ? ap2: (ap2|HIGHBIT);
    1103             : }
    1104             : 
    1105             : INLINE ulong
    1106  2874462761 : Fl_add(ulong a, ulong b, ulong p)
    1107             : {
    1108  2874462761 :   ulong res = a + b;
    1109  2874462761 :   return (res >= p || res < a) ? res - p : res;
    1110             : }
    1111             : INLINE ulong
    1112   291228680 : Fl_neg(ulong x, ulong p) { return x ? p - x: 0; }
    1113             : 
    1114             : INLINE ulong
    1115  4697467931 : Fl_sub(ulong a, ulong b, ulong p)
    1116             : {
    1117  4697467931 :   ulong res = a - b;
    1118  4697467931 :   return (res > a) ? res + p: res;
    1119             : }
    1120             : 
    1121             : /* centerlift(u mod p) */
    1122             : INLINE long
    1123     2770365 : Fl_center(ulong u, ulong p, ulong ps2) { return (long) (u > ps2)? u - p: u; }
    1124             : 
    1125             : INLINE ulong
    1126   744685339 : Fl_mul(ulong a, ulong b, ulong p)
    1127             : {
    1128             :   register ulong x;
    1129             :   LOCAL_HIREMAINDER;
    1130   744685339 :   x = mulll(a,b);
    1131   744685339 :   if (!hiremainder) return x % p;
    1132   144376651 :   (void)divll(x,p); return hiremainder;
    1133             : }
    1134             : INLINE ulong
    1135    64298497 : Fl_sqr(ulong a, ulong p)
    1136             : {
    1137             :   register ulong x;
    1138             :   LOCAL_HIREMAINDER;
    1139    64298497 :   x = mulll(a,a);
    1140    64298497 :   if (!hiremainder) return x % p;
    1141    34868388 :   (void)divll(x,p); return hiremainder;
    1142             : }
    1143             : /* don't assume that p is prime: can't special case a = 0 */
    1144             : INLINE ulong
    1145    10353393 : Fl_div(ulong a, ulong b, ulong p)
    1146    10353393 : { return Fl_mul(a, Fl_inv(b, p), p); }
    1147             : 
    1148             : /*******************************************************************/
    1149             : /*                                                                 */
    1150             : /*        DEFINED FROM EXISTING ONE EXPLOITING COMMUTATIVITY       */
    1151             : /*                                                                 */
    1152             : /*******************************************************************/
    1153             : INLINE GEN
    1154      278914 : addri(GEN x, GEN y) { return addir(y,x); }
    1155             : INLINE GEN
    1156    48978747 : addis(GEN x, long s) { return addsi(s,x); }
    1157             : INLINE GEN
    1158    74572050 : addiu(GEN x, ulong s) { return addui(s,x); }
    1159             : INLINE GEN
    1160     2822952 : addrs(GEN x, long s) { return addsr(s,x); }
    1161             : 
    1162             : INLINE GEN
    1163    31060271 : subiu(GEN x, long y) { GEN z = subui(y, x); togglesign(z); return z; }
    1164             : INLINE GEN
    1165        1653 : subis(GEN x, long y) { return addsi(-y,x); }
    1166             : INLINE GEN
    1167     3163960 : subrs(GEN x, long y) { return addsr(-y,x); }
    1168             : 
    1169             : INLINE GEN
    1170   184953004 : mulis(GEN x, long s) { return mulsi(s,x); }
    1171             : INLINE GEN
    1172   134072892 : muliu(GEN x, ulong s) { return mului(s,x); }
    1173             : INLINE GEN
    1174     3002046 : mulru(GEN x, ulong s) { return mulur(s,x); }
    1175             : INLINE GEN
    1176    21244964 : mulri(GEN x, GEN s) { return mulir(s,x); }
    1177             : INLINE GEN
    1178    10271204 : mulrs(GEN x, long s) { return mulsr(s,x); }
    1179             : 
    1180             : /*******************************************************************/
    1181             : /*                                                                 */
    1182             : /*                  VALUATION, EXPONENT, SHIFTS                    */
    1183             : /*                                                                 */
    1184             : /*******************************************************************/
    1185             : INLINE long
    1186    84140630 : vali(GEN x)
    1187             : {
    1188             :   long i;
    1189             :   GEN xp;
    1190             : 
    1191    84140630 :   if (!signe(x)) return -1;
    1192    84134485 :   xp=int_LSW(x);
    1193    84134485 :   for (i=0; !*xp; i++) xp=int_nextW(xp);
    1194    84134485 :   return vals(*xp) + i * BITS_IN_LONG;
    1195             : }
    1196             : 
    1197             : 
    1198             : /* assume x > 0 */
    1199             : INLINE long
    1200   373514595 : expu(ulong x) { return (BITS_IN_LONG-1) - (long)bfffo(x); }
    1201             : 
    1202             : INLINE long
    1203   733051960 : expi(GEN x)
    1204             : {
    1205   733051960 :   const long lx=lgefint(x);
    1206   733051960 :   return lx==2? -(long)HIGHEXPOBIT: bit_accuracy(lx)-(long)bfffo(*int_MSW(x))-1;
    1207             : }
    1208             : 
    1209             : INLINE GEN
    1210    63685531 : shiftr(GEN x, long n)
    1211             : {
    1212    63685531 :   const long e = evalexpo(expo(x)+n);
    1213    63682290 :   const GEN y = rcopy(x);
    1214             : 
    1215    63676990 :   if (e & ~EXPOBITS) pari_err_OVERFLOW("expo()");
    1216    63676701 :   y[1] = (y[1]&~EXPOBITS) | e; return y;
    1217             : }
    1218             : INLINE GEN
    1219    22123604 : mpshift(GEN x,long s) { return (typ(x)==t_INT)?shifti(x,s):shiftr(x,s); }
    1220             : 
    1221             : /* FIXME: adapt/use mpn_[lr]shift instead */
    1222             : /* z2[imin..imax] := z1[imin..imax].f shifted left sh bits
    1223             :  * (feeding f from the right). Assume sh > 0 */
    1224             : INLINE void
    1225  3443975725 : shift_left(GEN z2, GEN z1, long imin, long imax, ulong f,  ulong sh)
    1226             : {
    1227  3443975725 :   GEN sb = z1 + imin, se = z1 + imax, te = z2 + imax;
    1228  3443975725 :   ulong l, m = BITS_IN_LONG - sh, k = f >> m;
    1229 20638796688 :   while (se > sb) {
    1230 13750845238 :     l     = *se--;
    1231 13750845238 :     *te-- = (l << sh) | k;
    1232 13750845238 :     k     = l >> m;
    1233             :   }
    1234  3443975725 :   *te = (((ulong)*se) << sh) | k;
    1235  3443975725 : }
    1236             : /* z2[imin..imax] := f.z1[imin..imax-1] shifted right sh bits
    1237             :  * (feeding f from the left). Assume sh > 0 */
    1238             : INLINE void
    1239  3279048798 : shift_right(GEN z2, GEN z1, long imin, long imax, ulong f, ulong sh)
    1240             : {
    1241  3279048798 :   GEN sb = z1 + imin, se = z1 + imax, tb = z2 + imin;
    1242  3279048798 :   ulong k, l = *sb++, m = BITS_IN_LONG - sh;
    1243  3279048798 :   *tb++ = (l >> sh) | (f << m);
    1244 18216971674 :   while (sb < se) {
    1245 11658874078 :     k     = l << m;
    1246 11658874078 :     l     = *sb++;
    1247 11658874078 :     *tb++ = (l >> sh) | k;
    1248             :   }
    1249  3279048798 : }
    1250             : 
    1251             : /* Backward compatibility. Inefficient && unused */
    1252             : extern ulong hiremainder;
    1253             : INLINE ulong
    1254           0 : shiftl(ulong x, ulong y)
    1255           0 : { hiremainder = x>>(BITS_IN_LONG-y); return (x<<y); }
    1256             : 
    1257             : INLINE ulong
    1258           0 : shiftlr(ulong x, ulong y)
    1259           0 : { hiremainder = x<<(BITS_IN_LONG-y); return (x>>y); }
    1260             : 
    1261             : INLINE void
    1262    94047068 : shiftr_inplace(GEN z, long d)
    1263             : {
    1264    94047068 :   setexpo(z, expo(z)+d);
    1265    94046823 : }
    1266             : 
    1267             : /*******************************************************************/
    1268             : /*                                                                 */
    1269             : /*                           ASSIGNMENT                            */
    1270             : /*                                                                 */
    1271             : /*******************************************************************/
    1272             : INLINE void
    1273    91754956 : affii(GEN x, GEN y)
    1274             : {
    1275    91754956 :   long lx = lgefint(x);
    1276    91754956 :   if (lg(y)<lx) pari_err_OVERFLOW("t_INT-->t_INT assignment");
    1277    91755120 :   while (--lx) y[lx] = x[lx];
    1278    91755120 : }
    1279             : INLINE void
    1280      549195 : affsi(long s, GEN x)
    1281             : {
    1282      549195 :   if (!s) x[1] = evalsigne(0) | evallgefint(2);
    1283             :   else
    1284             :   {
    1285      520122 :     if (s > 0) { x[1] = evalsigne( 1) | evallgefint(3); x[2] =  s; }
    1286      195595 :     else       { x[1] = evalsigne(-1) | evallgefint(3); x[2] = -s; }
    1287             :   }
    1288      549195 : }
    1289             : INLINE void
    1290     8404634 : affui(ulong u, GEN x)
    1291             : {
    1292     8404634 :   if (!u) x[1] = evalsigne(0) | evallgefint(2);
    1293     8403766 :   else  { x[1] = evalsigne(1) | evallgefint(3); x[2] = u; }
    1294     8404634 : }
    1295             : 
    1296             : INLINE void
    1297   168959033 : affsr(long x, GEN y)
    1298             : {
    1299   168959033 :   long sh, i, ly = lg(y);
    1300             : 
    1301   168959033 :   if (!x)
    1302             :   {
    1303       70966 :     y[1] = evalexpo(-prec2nbits(ly));
    1304       70966 :     return;
    1305             :   }
    1306   168888067 :   if (x < 0) {
    1307      166226 :     x = -x; sh = bfffo(x);
    1308      166226 :     y[1] = evalsigne(-1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1309             :   }
    1310             :   else
    1311             :   {
    1312   168721841 :     sh = bfffo(x);
    1313   168721841 :     y[1] = evalsigne(1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1314             :   }
    1315   168888067 :   y[2] = ((ulong)x)<<sh; for (i=3; i<ly; i++) y[i]=0;
    1316             : }
    1317             : 
    1318             : INLINE void
    1319     9445425 : affur(ulong x, GEN y)
    1320             : {
    1321     9445425 :   long sh, i, ly = lg(y);
    1322             : 
    1323     9445425 :   if (!x)
    1324             :   {
    1325     1296306 :     y[1] = evalexpo(-prec2nbits(ly));
    1326     1296306 :     return;
    1327             :   }
    1328     8149119 :   sh = bfffo(x);
    1329     8149119 :   y[1] = evalsigne(1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1330     8149119 :   y[2] = x<<sh; for (i=3; i<ly; i++) y[i] = 0;
    1331             : }
    1332             : 
    1333             : INLINE void
    1334      161918 : affiz(GEN x, GEN y) { if (typ(y)==t_INT) affii(x,y); else affir(x,y); }
    1335             : INLINE void
    1336           0 : affsz(long x, GEN y) { if (typ(y)==t_INT) affsi(x,y); else affsr(x,y); }
    1337             : INLINE void
    1338      277938 : mpaff(GEN x, GEN y) { if (typ(x)==t_INT) affiz(x, y); else affrr(x,y); }
    1339             : 
    1340             : /*******************************************************************/
    1341             : /*                                                                 */
    1342             : /*                    OPERATION + ASSIGNMENT                       */
    1343             : /*                                                                 */
    1344             : /*******************************************************************/
    1345             : 
    1346           0 : INLINE void addiiz(GEN x, GEN y, GEN z)
    1347           0 : { pari_sp av = avma; affii(addii(x,y),z); set_avma(av); }
    1348           0 : INLINE void addirz(GEN x, GEN y, GEN z)
    1349           0 : { pari_sp av = avma; affrr(addir(x,y),z); set_avma(av); }
    1350           0 : INLINE void addriz(GEN x, GEN y, GEN z)
    1351           0 : { pari_sp av = avma; affrr(addri(x,y),z); set_avma(av); }
    1352     1306252 : INLINE void addrrz(GEN x, GEN y, GEN z)
    1353     1306252 : { pari_sp av = avma; affrr(addrr(x,y),z); set_avma(av); }
    1354           0 : INLINE void addsiz(long s, GEN y, GEN z)
    1355           0 : { pari_sp av = avma; affii(addsi(s,y),z); set_avma(av); }
    1356           0 : INLINE void addsrz(long s, GEN y, GEN z)
    1357           0 : { pari_sp av = avma; affrr(addsr(s,y),z); set_avma(av); }
    1358           0 : INLINE void addssz(long s, long y, GEN z)
    1359           0 : { pari_sp av = avma; affii(addss(s,y),z); set_avma(av); }
    1360             : 
    1361           0 : INLINE void diviiz(GEN x, GEN y, GEN z)
    1362           0 : { pari_sp av = avma; affii(divii(x,y),z); set_avma(av); }
    1363           0 : INLINE void divirz(GEN x, GEN y, GEN z)
    1364           0 : { pari_sp av = avma; mpaff(divir(x,y),z); set_avma(av); }
    1365           0 : INLINE void divisz(GEN x, long y, GEN z)
    1366           0 : { pari_sp av = avma; affii(divis(x,y),z); set_avma(av); }
    1367           0 : INLINE void divriz(GEN x, GEN y, GEN z)
    1368           0 : { pari_sp av = avma; affrr(divri(x,y),z); set_avma(av); }
    1369         406 : INLINE void divrrz(GEN x, GEN y, GEN z)
    1370         406 : { pari_sp av = avma; affrr(divrr(x,y),z); set_avma(av); }
    1371           0 : INLINE void divrsz(GEN y, long s, GEN z)
    1372           0 : { pari_sp av = avma; affrr(divrs(y,s),z); set_avma(av); }
    1373           0 : INLINE void divsiz(long x, GEN y, GEN z)
    1374           0 : { long junk; affsi(sdivsi_rem(x,y,&junk), z); }
    1375           0 : INLINE void divsrz(long s, GEN y, GEN z)
    1376           0 : { pari_sp av = avma; mpaff(divsr(s,y),z); set_avma(av); }
    1377           0 : INLINE void divssz(long x, long y, GEN z)
    1378           0 : { affsi(x/y, z); }
    1379             : 
    1380           0 : INLINE void modisz(GEN y, long s, GEN z)
    1381           0 : { affsi(smodis(y,s),z); }
    1382           0 : INLINE void modsiz(long s, GEN y, GEN z)
    1383           0 : { pari_sp av = avma; affii(modsi(s,y),z); set_avma(av); }
    1384           0 : INLINE void modssz(long s, long y, GEN z)
    1385           0 : { affsi(smodss(s,y),z); }
    1386             : 
    1387           0 : INLINE void mpaddz(GEN x, GEN y, GEN z)
    1388           0 : { pari_sp av = avma; mpaff(mpadd(x,y),z); set_avma(av); }
    1389           0 : INLINE void mpsubz(GEN x, GEN y, GEN z)
    1390           0 : { pari_sp av = avma; mpaff(mpsub(x,y),z); set_avma(av); }
    1391           0 : INLINE void mpmulz(GEN x, GEN y, GEN z)
    1392           0 : { pari_sp av = avma; mpaff(mpmul(x,y),z); set_avma(av); }
    1393             : 
    1394           0 : INLINE void muliiz(GEN x, GEN y, GEN z)
    1395           0 : { pari_sp av = avma; affii(mulii(x,y),z); set_avma(av); }
    1396           0 : INLINE void mulirz(GEN x, GEN y, GEN z)
    1397           0 : { pari_sp av = avma; mpaff(mulir(x,y),z); set_avma(av); }
    1398           0 : INLINE void mulriz(GEN x, GEN y, GEN z)
    1399           0 : { pari_sp av = avma; mpaff(mulri(x,y),z); set_avma(av); }
    1400      257264 : INLINE void mulrrz(GEN x, GEN y, GEN z)
    1401      257264 : { pari_sp av = avma; affrr(mulrr(x,y),z); set_avma(av); }
    1402           0 : INLINE void mulsiz(long s, GEN y, GEN z)
    1403           0 : { pari_sp av = avma; affii(mulsi(s,y),z); set_avma(av); }
    1404           0 : INLINE void mulsrz(long s, GEN y, GEN z)
    1405           0 : { pari_sp av = avma; mpaff(mulsr(s,y),z); set_avma(av); }
    1406           0 : INLINE void mulssz(long s, long y, GEN z)
    1407           0 : { pari_sp av = avma; affii(mulss(s,y),z); set_avma(av); }
    1408             : 
    1409           0 : INLINE void remiiz(GEN x, GEN y, GEN z)
    1410           0 : { pari_sp av = avma; affii(remii(x,y),z); set_avma(av); }
    1411           0 : INLINE void remisz(GEN y, long s, GEN z)
    1412           0 : { pari_sp av = avma; affii(remis(y,s),z); set_avma(av); }
    1413           0 : INLINE void remsiz(long s, GEN y, GEN z)
    1414           0 : { pari_sp av = avma; affii(remsi(s,y),z); set_avma(av); }
    1415           0 : INLINE void remssz(long s, long y, GEN z)
    1416           0 : { pari_sp av = avma; affii(remss(s,y),z); set_avma(av); }
    1417             : 
    1418           0 : INLINE void subiiz(GEN x, GEN y, GEN z)
    1419           0 : { pari_sp av = avma; affii(subii(x,y),z); set_avma(av); }
    1420           0 : INLINE void subirz(GEN x, GEN y, GEN z)
    1421           0 : { pari_sp av = avma; affrr(subir(x,y),z); set_avma(av); }
    1422           0 : INLINE void subisz(GEN y, long s, GEN z)
    1423           0 : { pari_sp av = avma; affii(addsi(-s,y),z); set_avma(av); }
    1424           0 : INLINE void subriz(GEN x, GEN y, GEN z)
    1425           0 : { pari_sp av = avma; affrr(subri(x,y),z); set_avma(av); }
    1426     1295880 : INLINE void subrrz(GEN x, GEN y, GEN z)
    1427     1295880 : { pari_sp av = avma; affrr(subrr(x,y),z); set_avma(av); }
    1428           0 : INLINE void subrsz(GEN y, long s, GEN z)
    1429           0 : { pari_sp av = avma; affrr(addsr(-s,y),z); set_avma(av); }
    1430           0 : INLINE void subsiz(long s, GEN y, GEN z)
    1431           0 : { pari_sp av = avma; affii(subsi(s,y),z); set_avma(av); }
    1432           0 : INLINE void subsrz(long s, GEN y, GEN z)
    1433           0 : { pari_sp av = avma; affrr(subsr(s,y),z); set_avma(av); }
    1434           0 : INLINE void subssz(long x, long y, GEN z) { addssz(x,-y,z); }
    1435             : 
    1436             : INLINE void
    1437           0 : dvmdssz(long x, long y, GEN z, GEN t) {
    1438           0 :   pari_sp av = avma;
    1439             :   long r;
    1440           0 :   affii(divss_rem(x,y, &r), z); set_avma(av); affsi(r,t);
    1441           0 : }
    1442             : INLINE void
    1443           0 : dvmdsiz(long x, GEN y, GEN z, GEN t) {
    1444           0 :   pari_sp av = avma;
    1445             :   long r;
    1446           0 :   affii(divsi_rem(x,y, &r), z); set_avma(av); affsi(r,t);
    1447           0 : }
    1448             : INLINE void
    1449           0 : dvmdisz(GEN x, long y, GEN z, GEN t) {
    1450           0 :   pari_sp av = avma;
    1451             :   long r;
    1452           0 :   affii(divis_rem(x,y, &r),z); set_avma(av); affsi(r,t);
    1453           0 : }
    1454             : INLINE void
    1455           0 : dvmdiiz(GEN x, GEN y, GEN z, GEN t) {
    1456           0 :   pari_sp av = avma;
    1457             :   GEN r;
    1458           0 :   affii(dvmdii(x,y,&r),z); affii(r,t); set_avma(av);
    1459           0 : }

Generated by: LCOV version 1.13