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 20422-b487f4d) Lines: 549 710 77.3 %
Date: 2017-03-22 05:51:54 Functions: 196 260 75.4 %
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 38759047828 : evallg(long x)
      21             : {
      22 38759047828 :   if (x & ~LGBITS) pari_err_OVERFLOW("lg()");
      23 38756782373 :   return _evallg(x);
      24             : }
      25             : INLINE long
      26    12937683 : evalvalp(long x)
      27             : {
      28    12937683 :   long v = _evalvalp(x);
      29    12937683 :   if (v & ~VALPBITS) pari_err_OVERFLOW("valp()");
      30    12937686 :   return v;
      31             : }
      32             : INLINE long
      33  4992108350 : evalexpo(long x)
      34             : {
      35  4992108350 :   long v = _evalexpo(x);
      36  4992108350 :   if (v & ~EXPOBITS) pari_err_OVERFLOW("expo()");
      37  4992108350 :   return v;
      38             : }
      39             : INLINE long
      40     1844815 : evalprecp(long x)
      41             : {
      42     1844815 :   long v = _evalprecp(x);
      43     1844815 :   if (x & ~((1UL<<(BITS_IN_LONG-VALPnumBITS))-1)) pari_err_OVERFLOW("precp()");
      44     1844812 :   return v;
      45             : }
      46             : 
      47             : INLINE int
      48   137307622 : varncmp(long x, long y)
      49             : {
      50   137307622 :   if (varpriority[x] < varpriority[y]) return  1;
      51   107180691 :   if (varpriority[x] > varpriority[y]) return -1;
      52    56333032 :   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  1566513892 : stackdummy(pari_sp av, pari_sp ltop) {
      70  1566513892 :   long l = ((GEN)av) - ((GEN)ltop);
      71  1566513892 :   if (l > 0) {
      72   568336681 :     GEN z = (GEN)ltop;
      73   568336681 :     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  1566083085 : }
      79             : INLINE void
      80    38434999 : fixlg(GEN x, long ly) {
      81    38434999 :   long lx = lg(x), l = lx - ly;
      82    38434999 :   if (l > 0)
      83             :   { /* stackdummy(x+lx, x+ly) */
      84    23593986 :     GEN z = x + ly;
      85    23593986 :     z[0] = evaltyp(t_VECSMALL) | evallg(l);
      86    23593972 :     setlg(x, ly);
      87             : #ifdef DEBUG
      88             :     { long i; for (i = 1; i < l; i++) z[i] = 0; }
      89             : #endif
      90             :   }
      91    38434982 : }
      92             : /* update lg(z) before affrr(y, z)  [ to cater for precision loss ]*/
      93             : INLINE void
      94    14843457 : 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 35703116154 : new_chunk(size_t x) /* x is a number of longs */
     103             : {
     104 35703116154 :   GEN z = ((GEN) avma) - x;
     105             :   CHECK_CTRLC
     106 35703116154 :   if (x > (avma-pari_mainstack->bot) / sizeof(long))
     107           7 :     new_chunk_resize(x);
     108 35711009698 :   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 35711009698 :   return z;
     121             : }
     122             : 
     123             : INLINE char *
     124     3713810 : stack_malloc(size_t N)
     125             : {
     126     3713810 :   long n = nchar2nlong(N);
     127     3713810 :   return (char*)new_chunk(n);
     128             : }
     129             : 
     130             : INLINE char *
     131      779770 : stack_malloc_align(size_t N, long k)
     132             : {
     133      779770 :   ulong d = ((ulong)avma) % k;
     134      779770 :   if (d) (void)new_chunk(d/sizeof(long));
     135      779770 :   return (char*) new_chunk(nchar2nlong(N));
     136             : }
     137             : 
     138             : INLINE char *
     139       23319 : stack_calloc(size_t N)
     140             : {
     141       23319 :   char *p = stack_malloc(N);
     142       23319 :   memset(p, 0, N); return p;
     143             : }
     144             : 
     145             : /* cgetg(lg(x), typ(x)), set *lx. Implicit unsetisclone() */
     146             : INLINE GEN
     147   328689036 : cgetg_copy(GEN x, long *plx) {
     148             :   GEN y;
     149   328689036 :   *plx = lg(x); y = new_chunk((size_t)*plx);
     150   328688610 :   y[0] = x[0] & (TYPBITS|LGBITS); return y;
     151             : }
     152             : INLINE GEN
     153       95641 : cgetg_block(long x, long y)
     154             : {
     155       95641 :   GEN z = newblock((size_t)x);
     156       95830 :   z[0] = evaltyp(y) | evallg(x);
     157       95807 :   return z;
     158             : }
     159             : INLINE GEN
     160  4515716965 : cgetg(long x, long y)
     161             : {
     162  4515716965 :   GEN z = new_chunk((size_t)x);
     163  4514628786 :   z[0] = evaltyp(y) | evallg(x);
     164  4512006920 :   return z;
     165             : }
     166             : INLINE GEN
     167 12365628353 : cgeti(long x)
     168             : {
     169 12365628353 :   GEN z = new_chunk((size_t)x);
     170 12350766467 :   z[0] = evaltyp(t_INT) | evallg(x);
     171 12341577067 :   return z;
     172             : }
     173             : INLINE GEN
     174  7379336568 : cgetipos(long x)
     175             : {
     176  7379336568 :   GEN z = cgeti(x);
     177  7378216087 :   z[1] = evalsigne(1) | evallgefint(x);
     178  7378216087 :   return z;
     179             : }
     180             : INLINE GEN
     181   206198574 : cgetineg(long x)
     182             : {
     183   206198574 :   GEN z = cgeti(x);
     184   206198609 :   z[1] = evalsigne(-1) | evallgefint(x);
     185   206198609 :   return z;
     186             : }
     187             : INLINE GEN
     188        2578 : cgetr_block(long x)
     189             : {
     190        2578 :   GEN z = newblock((size_t)x);
     191        2578 :   z[0] = evaltyp(t_REAL) | evallg(x);
     192        2578 :   return z;
     193             : }
     194             : INLINE GEN
     195  5167537200 : cgetr(long x)
     196             : {
     197  5167537200 :   GEN z = new_chunk((size_t)x);
     198  5167537200 :   z[0] = evaltyp(t_REAL) | evallg(x);
     199  5167537200 :   return z;
     200             : }
     201             : 
     202             : /*******************************************************************/
     203             : /*                                                                 */
     204             : /*                     COPY, NEGATION, ABSOLUTE VALUE              */
     205             : /*                                                                 */
     206             : /*******************************************************************/
     207             : /* cannot do memcpy because sometimes x and y overlap */
     208             : INLINE GEN
     209  1114994637 : leafcopy(GEN x)
     210             : {
     211  1114994637 :   register long lx = lg(x);
     212  1114994637 :   GEN y = new_chunk(lx); /* can't use cgetg_copy, in case x,y overlap */
     213  1115274488 :   while (--lx > 0) y[lx] = x[lx];
     214  1115274488 :   y[0] = x[0] & (TYPBITS|LGBITS); return y;
     215             : }
     216             : INLINE GEN
     217  4240152741 : icopy(GEN x)
     218             : {
     219  4240152741 :   long i = lgefint(x), lx = i;
     220  4240152741 :   GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */
     221  4242808369 :   while (--i > 0) y[i] = x[i];
     222  4242808369 :   y[0] = evaltyp(t_INT) | evallg(lx);
     223  4240996897 :   return y;
     224             : }
     225             : INLINE GEN
     226    30580417 : icopyspec(GEN x, long nx)
     227             : {
     228    30580417 :   long i = nx+2, lx = i;
     229    30580417 :   GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */
     230    30580397 :   x -= 2; while (--i >= 2) y[i] = x[i];
     231    30580397 :   y[1] = evalsigne(1) | evallgefint(lx);
     232    30580397 :   y[0] = evaltyp(t_INT) | evallg(lx);
     233    30580373 :   return y;
     234             : }
     235   179730883 : INLINE GEN rcopy(GEN x) { return leafcopy(x); }
     236     1511631 : INLINE GEN mpcopy(GEN x) { return leafcopy(x); }
     237             : 
     238             : INLINE GEN
     239   232745206 : mpabs(GEN x) { GEN y = leafcopy(x); setabssign(y); return y; }
     240             : INLINE GEN
     241       11508 : mpabs_shallow(GEN x) { return signe(x) < 0? mpabs(x): x; }
     242   195101677 : INLINE GEN absi(GEN x) { return mpabs(x); }
     243      108045 : INLINE GEN absi_shallow(GEN x) { return signe(x) < 0? negi(x): x; }
     244    23395971 : INLINE GEN absr(GEN x) { return mpabs(x); }
     245             : 
     246             : INLINE GEN
     247   312093014 : mpneg(GEN x) { GEN y = leafcopy(x); togglesign(y); return y; }
     248   215327962 : INLINE GEN negi(GEN x) { return mpneg(x); }
     249     1194853 : INLINE GEN negr(GEN x) { return mpneg(x); }
     250             : 
     251             : /* negate in place */
     252             : INLINE void
     253   743072834 : togglesign(GEN x) { if (x[1] & SIGNBITS) { x[1] ^= HIGHBIT; } }
     254             : INLINE void
     255   259686944 : setabssign(GEN x) { x[1] &= ~HIGHBIT; }
     256             : /* negate in place, except universal constants */
     257             : INLINE void
     258    53510219 : togglesign_safe(GEN *px)
     259             : {
     260    53510219 :   switch(*px - gen_1) /* gen_1, gen_2, gen_m1, gen_m2 */
     261             :   {
     262      837586 :     case 0: *px = gen_m1; break;
     263           0 :     case 3: *px = gen_m2;  break;
     264      194264 :     case 6: *px = gen_1; break;
     265           0 :     case 9: *px = gen_2;  break;
     266    52478369 :     default: togglesign(*px);
     267             :   }
     268    53510219 : }
     269             : /* setsigne(y, signe(x)) */
     270             : INLINE void
     271           0 : affectsign(GEN x, GEN y)
     272             : {
     273           0 :   y[1] = (x[1] & SIGNBITS) | (y[1] & ~SIGNBITS);
     274           0 : }
     275             : /* copies sign in place, except for universal constants */
     276             : INLINE void
     277     5237871 : affectsign_safe(GEN x, GEN *py)
     278             : {
     279     5237871 :   if (((*py)[1] ^ x[1]) & HIGHBIT) togglesign_safe(py);
     280     5237871 : }
     281             : /*******************************************************************/
     282             : /*                                                                 */
     283             : /*                     GEN -> LONG, LONG -> GEN                    */
     284             : /*                                                                 */
     285             : /*******************************************************************/
     286             : /* assume x != 0, return -x as a t_INT */
     287             : INLINE GEN
     288   206038631 : utoineg(ulong x) { GEN y = cgetineg(3); y[2] = x; return y; }
     289             : /* assume x != 0, return utoi(x) */
     290             : INLINE GEN
     291  6318422898 : utoipos(ulong x) { GEN y = cgetipos(3); y[2] = x; return y; }
     292             : INLINE GEN
     293  5261919574 : utoi(ulong x) { return x? utoipos(x): gen_0; }
     294             : INLINE GEN
     295   305413255 : stoi(long x)
     296             : {
     297   305413255 :   if (!x) return gen_0;
     298   191055847 :   return x > 0? utoipos((ulong)x): utoineg((ulong)-x);
     299             : }
     300             : 
     301             : /* x 2^BIL + y */
     302             : INLINE GEN
     303  3901681213 : uutoi(ulong x, ulong y)
     304             : {
     305             :   GEN z;
     306  3901681213 :   if (!x) return utoi(y);
     307   422209178 :   z = cgetipos(4);
     308   421807649 :   *int_W_lg(z, 1, 4) = x;
     309   421807649 :   *int_W_lg(z, 0, 4) = y; return z;
     310             : }
     311             : /* - (x 2^BIL + y) */
     312             : INLINE GEN
     313       60187 : uutoineg(ulong x, ulong y)
     314             : {
     315             :   GEN z;
     316       60187 :   if (!x) return y? utoineg(y): gen_0;
     317           0 :   z = cgetineg(4);
     318           0 :   *int_W_lg(z, 1, 4) = x;
     319           0 :   *int_W_lg(z, 0, 4) = y; return z;
     320             : }
     321             : 
     322             : INLINE long
     323   188708976 : itos(GEN x)
     324             : {
     325   188708976 :   long s = signe(x);
     326             :   long u;
     327             : 
     328   188708976 :   if (!s) return 0;
     329   177536783 :   u = x[2];
     330   177536783 :   if (lgefint(x) > 3 || u < 0)
     331          19 :     pari_err_OVERFLOW("t_INT-->long assignment");
     332   177536802 :   return (s>0) ? u : -u;
     333             : }
     334             : /* as itos, but return 0 if too large. Cf is_bigint */
     335             : INLINE long
     336     8982661 : itos_or_0(GEN x) {
     337             :   long n;
     338     8982661 :   if (lgefint(x) != 3 || (n = x[2]) & HIGHBIT) return 0;
     339     8965104 :   return signe(x) > 0? n: -n;
     340             : }
     341             : INLINE ulong
     342    25470127 : itou(GEN x)
     343             : {
     344    25470127 :   switch(lgefint(x)) {
     345     5401294 :     case 2: return 0;
     346    20068833 :     case 3: return x[2];
     347             :     default:
     348           0 :       pari_err_OVERFLOW("t_INT-->ulong assignment");
     349             :       return 0; /* LCOV_EXCL_LINE */
     350             :   }
     351             : }
     352             : 
     353             : /* as itou, but return 0 if too large. Cf is_bigint */
     354             : INLINE ulong
     355     4162702 : itou_or_0(GEN x) {
     356     4162702 :   if (lgefint(x) != 3) return 0;
     357     4152678 :   return (ulong)x[2];
     358             : }
     359             : 
     360             : INLINE ulong
     361     1576701 : umuluu_or_0(ulong x, ulong y)
     362             : {
     363             :   ulong z;
     364             :   LOCAL_HIREMAINDER;
     365     1576701 :   z = mulll(x, y);
     366     1576701 :   return hiremainder? 0: z;
     367             : }
     368             : 
     369             : INLINE GEN
     370    75482316 : real_0_bit(long bitprec) { GEN x=cgetr(2); x[1]=evalexpo(bitprec); return x; }
     371             : INLINE GEN
     372    24535837 : real_0(long prec) { return real_0_bit(-prec2nbits(prec)); }
     373             : INLINE GEN
     374      446533 : real_1_bit(long bit) { return real_1(nbits2prec(bit)); }
     375             : INLINE GEN
     376    27207205 : real_1(long prec) {
     377    27207205 :   GEN x = cgetr(prec);
     378             :   long i;
     379    27207205 :   x[1] = evalsigne(1) | _evalexpo(0);
     380    27207205 :   x[2] = (long)HIGHBIT; for (i=3; i<prec; i++) x[i] = 0;
     381    27207205 :   return x;
     382             : }
     383             : INLINE GEN
     384          91 : real_m1(long prec) {
     385          91 :   GEN x = cgetr(prec);
     386             :   long i;
     387          91 :   x[1] = evalsigne(-1) | _evalexpo(0);
     388          91 :   x[2] = (long)HIGHBIT; for (i=3; i<prec; i++) x[i] = 0;
     389          91 :   return x;
     390             : }
     391             : 
     392             : /* 2.^n */
     393             : INLINE GEN
     394       56208 : real2n(long n, long prec) { GEN z = real_1(prec); setexpo(z, n); return z; }
     395             : INLINE GEN
     396           0 : real_m2n(long n, long prec) { GEN z = real_m1(prec); setexpo(z, n); return z; }
     397             : INLINE GEN
     398   143245473 : stor(long s, long prec) { GEN z = cgetr(prec); affsr(s,z); return z; }
     399             : INLINE GEN
     400     5418325 : utor(ulong s, long prec){ GEN z = cgetr(prec); affur(s,z); return z; }
     401             : INLINE GEN
     402   141022460 : itor(GEN x, long prec) { GEN z = cgetr(prec); affir(x,z); return z; }
     403             : INLINE GEN
     404    72886621 : rtor(GEN x, long prec) { GEN z = cgetr(prec); affrr(x,z); return z; }
     405             : 
     406     5203084 : INLINE ulong int_bit(GEN x, long n)
     407             : {
     408     5203084 :   long r, q = dvmdsBIL(n, &r);
     409     5203844 :   return q < lgefint(x)-2?((ulong)*int_W(x,q) >> r) & 1UL:0;
     410             : }
     411             : 
     412             : /*******************************************************************/
     413             : /*                                                                 */
     414             : /*                           COMPARISON                            */
     415             : /*                                                                 */
     416             : /*******************************************************************/
     417             : INLINE int
     418      672607 : cmpir(GEN x, GEN y)
     419             : {
     420             :   pari_sp av;
     421             :   GEN z;
     422             : 
     423      672607 :   if (!signe(x)) return -signe(y);
     424      300337 :   if (!signe(y))
     425             :   {
     426        4594 :     if (expo(y) >= expi(x)) return 0;
     427        4566 :     return signe(x);
     428             :   }
     429      295743 :   av=avma; z = itor(x, realprec(y)); avma=av;
     430      295743 :   return cmprr(z,y); /* cmprr does no memory adjustment */
     431             : }
     432             : INLINE int
     433      437163 : cmpri(GEN x, GEN y) { return -cmpir(y,x); }
     434             : INLINE int
     435       61200 : cmpsr(long x, GEN y)
     436             : {
     437             :   pari_sp av;
     438             :   GEN z;
     439             : 
     440       61200 :   if (!x) return -signe(y);
     441       61200 :   av=avma; z = stor(x, LOWDEFAULTPREC); avma=av;
     442       61200 :   return cmprr(z,y);
     443             : }
     444             : INLINE int
     445       38668 : cmprs(GEN x, long y) { return -cmpsr(y,x); }
     446             : /* compare x and |y| */
     447             : INLINE int
     448    24101238 : abscmpui(ulong x, GEN y)
     449             : {
     450    24101238 :   long l = lgefint(y);
     451             :   ulong p;
     452             : 
     453    24101238 :   if (!x) return (l > 2)? -1: 0;
     454    24101224 :   if (l == 2) return 1;
     455    23910163 :   if (l > 3) return -1;
     456    23900028 :   p = y[2]; if (p == x) return 0;
     457    23510318 :   return p < x ? 1 : -1;
     458             : }
     459             : INLINE int
     460    24048569 : abscmpiu(GEN x, ulong y) { return -abscmpui(y,x); }
     461             : INLINE int
     462     4126973 : cmpsi(long x, GEN y)
     463             : {
     464             :   ulong p;
     465             : 
     466     4126973 :   if (!x) return -signe(y);
     467             : 
     468     4126357 :   if (x > 0)
     469             :   {
     470     4126021 :     if (signe(y)<=0) return 1;
     471     4125825 :     if (lgefint(y)>3) return -1;
     472     4112871 :     p = y[2]; if (p == (ulong)x) return 0;
     473     4079047 :     return p < (ulong)x ? 1 : -1;
     474             :   }
     475             : 
     476         336 :   if (signe(y)>=0) return -1;
     477          63 :   if (lgefint(y)>3) return 1;
     478          63 :   p = y[2]; if (p == (ulong)-x) return 0;
     479          14 :   return p < (ulong)(-x) ? -1 : 1;
     480             : }
     481             : INLINE int
     482     4125279 : cmpis(GEN x, long y) { return -cmpsi(y,x); }
     483             : INLINE int
     484      510013 : mpcmp(GEN x, GEN y)
     485             : {
     486      510013 :   if (typ(x)==t_INT)
     487        6180 :     return (typ(y)==t_INT) ? cmpii(x,y) : cmpir(x,y);
     488      503833 :   return (typ(y)==t_INT) ? -cmpir(y,x) : cmprr(x,y);
     489             : }
     490             : 
     491             : /* x == y ? */
     492             : INLINE int
     493      102875 : equalsi(long x, GEN y)
     494             : {
     495      102875 :   if (!x) return !signe(y);
     496      102875 :   if (x > 0)
     497             :   {
     498       33428 :     if (signe(y) <= 0 || lgefint(y) != 3) return 0;
     499       30460 :     return ((ulong)y[2] == (ulong)x);
     500             :   }
     501       69447 :   if (signe(y) >= 0 || lgefint(y) != 3) return 0;
     502       69447 :   return ((ulong)y[2] == (ulong)-x);
     503             : }
     504             : /* x == |y| ? */
     505             : INLINE int
     506    11256146 : absequalui(ulong x, GEN y)
     507             : {
     508    11256146 :   if (!x) return !signe(y);
     509    11256146 :   return (lgefint(y) == 3 && (ulong)y[2] == x);
     510             : }
     511             : INLINE int
     512    11152952 : absequaliu(GEN x, ulong y) { return absequalui(y,x); }
     513             : INLINE int
     514      102756 : equalis(GEN x, long y) { return equalsi(y,x); }
     515             : 
     516             : /* assume x != 0, is |x| == 2^n ? */
     517             : INLINE int
     518      761888 : absrnz_equal2n(GEN x) {
     519      761888 :   if ((ulong)x[2]==HIGHBIT)
     520             :   {
     521       41467 :     long i, lx = lg(x);
     522      623258 :     for (i = 3; i < lx; i++)
     523      587467 :       if (x[i]) return 0;
     524       35791 :     return 1;
     525             :   }
     526      720421 :   return 0;
     527             : }
     528             : /* assume x != 0, is |x| == 1 ? */
     529             : INLINE int
     530     1295754 : absrnz_equal1(GEN x) { return !expo(x) && absrnz_equal2n(x); }
     531             : 
     532             : INLINE long
     533  2517911965 : maxss(long x, long y) { return x>y?x:y; }
     534             : INLINE long
     535   827842398 : minss(long x, long y) { return x<y?x:y; }
     536             : INLINE long
     537     3270928 : minuu(ulong x, ulong y) { return x<y?x:y; }
     538             : INLINE long
     539     6349668 : maxuu(ulong x, ulong y) { return x>y?x:y; }
     540             : INLINE double
     541      963019 : maxdd(double x, double y) { return x>y?x:y; }
     542             : INLINE double
     543      372611 : mindd(double x, double y) { return x<y?x:y; }
     544             : 
     545             : /*******************************************************************/
     546             : /*                                                                 */
     547             : /*                             ADD / SUB                           */
     548             : /*                                                                 */
     549             : /*******************************************************************/
     550             : INLINE GEN
     551       25060 : subuu(ulong x, ulong y)
     552             : {
     553             :   ulong z;
     554             :   LOCAL_OVERFLOW;
     555       25060 :   z = subll(x, y);
     556       25060 :   return overflow? utoineg(-z): utoi(z);
     557             : }
     558             : INLINE GEN
     559  1510464002 : adduu(ulong x, ulong y) { ulong t = x+y; return uutoi((t < x), t); }
     560             : 
     561             : INLINE GEN
     562       25060 : addss(long x, long y)
     563             : {
     564       25060 :   if (!x) return stoi(y);
     565       25060 :   if (!y) return stoi(x);
     566       25060 :   if (x > 0) return y > 0? adduu(x,y): subuu(x, -y);
     567             : 
     568       25060 :   if (y > 0) return subuu(y, -x);
     569             :   else { /* - adduu(-x, -y) */
     570           0 :     ulong t = (-x)+(-y); return uutoineg((t < (ulong)(-x)), t);
     571             :   }
     572             : }
     573       25060 : INLINE GEN subss(long x, long y) { return addss(-y,x); }
     574             : 
     575             : INLINE GEN
     576  3636754899 : subii(GEN x, GEN y)
     577             : {
     578  3636754899 :   if (x==y) return gen_0; /* frequent with x = y = gen_0 */
     579  2642619855 :   return addii_sign(x, signe(x), y, -signe(y));
     580             : }
     581             : INLINE GEN
     582  4496573793 : addii(GEN x, GEN y) { return addii_sign(x, signe(x), y, signe(y)); }
     583             : INLINE GEN
     584   693059237 : addrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, signe(y)); }
     585             : INLINE GEN
     586   813530131 : subrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, -signe(y)); }
     587             : INLINE GEN
     588    98123557 : addir(GEN x, GEN y) { return addir_sign(x, signe(x), y, signe(y)); }
     589             : INLINE GEN
     590    74409622 : subir(GEN x, GEN y) { return addir_sign(x, signe(x), y, -signe(y)); }
     591             : INLINE GEN
     592     1272241 : subri(GEN x, GEN y) { return addir_sign(y, -signe(y), x, signe(x)); }
     593             : INLINE GEN
     594    50251872 : addsi(long x, GEN y) { return addsi_sign(x, y, signe(y)); }
     595             : INLINE GEN
     596    31984752 : addui(ulong x, GEN y) { return addui_sign(x, y, signe(y)); }
     597             : INLINE GEN
     598     3390292 : subsi(long x, GEN y) { return addsi_sign(x, y, -signe(y)); }
     599             : INLINE GEN
     600    22623198 : subui(ulong x, GEN y) { return addui_sign(x, y, -signe(y)); }
     601             : 
     602             : /*******************************************************************/
     603             : /*                                                                 */
     604             : /*                           MOD, REM, DIV                         */
     605             : /*                                                                 */
     606             : /*******************************************************************/
     607    76530842 : INLINE ulong mod2BIL(GEN x) { return *int_LSW(x); }
     608           0 : INLINE long mod64(GEN x) { return mod2BIL(x) & 63; }
     609         252 : INLINE long mod32(GEN x) { return mod2BIL(x) & 31; }
     610       57603 : INLINE long mod16(GEN x) { return mod2BIL(x) & 15; }
     611    39318789 : INLINE long mod8(GEN x)  { return mod2BIL(x) & 7; }
     612    10864639 : INLINE long mod4(GEN x)  { return mod2BIL(x) & 3; }
     613    15607763 : INLINE long mod2(GEN x)  { return mod2BIL(x) & 1; }
     614             : INLINE int
     615    21620982 : mpodd(GEN x) { return signe(x) && mod2(x); }
     616             : /* x mod 2^n, n < BITS_IN_LONG */
     617             : INLINE ulong
     618     5492837 : umodi2n(GEN x, long n)
     619             : {
     620     5492837 :   long s = signe(x);
     621     5492837 :   const ulong _2n = 1UL << n;
     622             :   ulong m;
     623     5492837 :   if (!s) return 0;
     624     5481203 :   m = *int_LSW(x) & (_2n - 1);
     625     5481203 :   if (s < 0 && m) m = _2n - m;
     626     5481203 :   return m;
     627             : }
     628           0 : INLINE ulong Mod64(GEN x){ return umodi2n(x,6); }
     629      166586 : INLINE ulong Mod32(GEN x){ return umodi2n(x,5); }
     630      216377 : INLINE ulong Mod16(GEN x){ return umodi2n(x,4); }
     631     1307992 : INLINE ulong Mod8(GEN x) { return umodi2n(x,3); }
     632     1323406 : INLINE ulong Mod4(GEN x) { return umodi2n(x,2); }
     633     2478406 : INLINE ulong Mod2(GEN x) { return umodi2n(x,1); }
     634             : 
     635             : INLINE GEN
     636    26330778 : truedivii(GEN a,GEN b) { return truedvmdii(a,b,NULL); }
     637             : INLINE GEN
     638         659 : truedivis(GEN a, long b) { return truedvmdis(a,b,NULL); }
     639             : INLINE GEN
     640     6084042 : truedivsi(long a, GEN b) { return truedvmdsi(a,b,NULL); }
     641             : 
     642             : INLINE GEN
     643     7275335 : divii(GEN a, GEN b) { return dvmdii(a,b,NULL); }
     644             : INLINE GEN
     645  1150949080 : remii(GEN a, GEN b) { return dvmdii(a,b,ONLY_REM); }
     646             : 
     647             : INLINE GEN
     648           0 : divss(long x, long y) { return stoi(x / y); }
     649             : INLINE GEN
     650      599096 : modss(long x, long y) { return stoi(smodss(x, y)); }
     651             : INLINE GEN
     652           0 : remss(long x, long y) { return stoi(x % y); }
     653             : INLINE long
     654     6301169 : smodss(long x, long y)
     655             : {
     656     6301169 :   long r = x%y;
     657     6301169 :   return (r >= 0)? r: labs(y) + r;
     658             : }
     659             : INLINE ulong
     660    11844359 : umodsu(long x, ulong y)
     661             : {
     662    11844359 :   return x>=0 ? x%y: Fl_neg((-x)%y, y);
     663             : }
     664             : 
     665             : INLINE long
     666           0 : sdivss_rem(long x, long y, long *r)
     667             : {
     668             :   long q;
     669             :   LOCAL_HIREMAINDER;
     670           0 :   if (!y) pari_err_INV("sdivss_rem",gen_0);
     671           0 :   hiremainder = 0; q = divll((ulong)labs(x),(ulong)labs(y));
     672           0 :   if (x < 0) { hiremainder = -((long)hiremainder); q = -q; }
     673           0 :   if (y < 0) q = -q;
     674           0 :   *r = hiremainder; return q;
     675             : }
     676             : INLINE GEN
     677           0 : divss_rem(long x, long y, long *r) { return stoi(sdivss_rem(x,y,r)); }
     678             : INLINE ulong
     679         483 : udivuu_rem(ulong x, ulong y, ulong *r)
     680             : {
     681         483 :   if (!y) pari_err_INV("udivuu_rem",gen_0);
     682         483 :   *r = x % y; return x / y;
     683             : }
     684             : INLINE ulong
     685       77093 : ceildivuu(ulong a, ulong b)
     686             : {
     687       77093 :   ulong c = a/b;
     688       77093 :   return (a%b)? c+1: c;
     689             : }
     690             : 
     691             : 
     692             : INLINE ulong
     693       10752 : udivui_rem(ulong x, GEN y, ulong *r)
     694             : {
     695       10752 :   long q, s = signe(y);
     696             :   LOCAL_HIREMAINDER;
     697             : 
     698       10752 :   if (!s) pari_err_INV("udivui_rem",gen_0);
     699       10752 :   if (!x || lgefint(y)>3) { *r = x; return 0; }
     700       10472 :   hiremainder=0; q = (long)divll(x, (ulong)y[2]);
     701       10472 :   if (s < 0) q = -q;
     702       10472 :   *r = hiremainder; return q;
     703             : }
     704             : 
     705             : /* assume d != 0 and |n| / d can be represented as an ulong.
     706             :  * Return |n|/d, set *r = |n| % d */
     707             : INLINE ulong
     708    12480475 : udiviu_rem(GEN n, ulong d, ulong *r)
     709             : {
     710    12480475 :   switch(lgefint(n))
     711             :   {
     712           0 :     case 2: *r = 0; return 0;
     713             :     case 3:
     714             :     {
     715    12480475 :       ulong nn = n[2];
     716    12480475 :       *r = nn % d; return nn / d;
     717             :     }
     718             :     default: /* 4 */
     719             :     {
     720             :       ulong n1, n0, q;
     721             :       LOCAL_HIREMAINDER;
     722           0 :       n0 = *int_W(n,0);
     723           0 :       n1 = *int_W(n,1);
     724           0 :       hiremainder = n1;
     725           0 :       q = divll(n0, d);
     726           0 :       *r = hiremainder; return q;
     727             :     }
     728             :   }
     729             : }
     730             : 
     731             : INLINE long
     732    13516402 : sdivsi_rem(long x, GEN y, long *r)
     733             : {
     734    13516402 :   long q, s = signe(y);
     735             :   LOCAL_HIREMAINDER;
     736             : 
     737    13516402 :   if (!s) pari_err_INV("sdivsi_rem",gen_0);
     738    13516404 :   if (!x || lgefint(y)>3 || ((long)y[2]) < 0) { *r = x; return 0; }
     739    11841218 :   hiremainder=0; q = (long)divll(labs(x), (ulong)y[2]);
     740    11841218 :   if (x < 0) { hiremainder = -((long)hiremainder); q = -q; }
     741    11841218 :   if (s < 0) q = -q;
     742    11841218 :   *r = hiremainder; return q;
     743             : }
     744             : INLINE GEN
     745           0 : divsi_rem(long s, GEN y, long *r) { return stoi(sdivsi_rem(s,y,r)); }
     746             : 
     747             : INLINE long
     748          98 : sdivsi(long x, GEN y)
     749             : {
     750          98 :   long q, s = signe(y);
     751             : 
     752          98 :   if (!s) pari_err_INV("sdivsi",gen_0);
     753          98 :   if (!x || lgefint(y)>3 || ((long)y[2]) < 0) return 0;
     754          70 :   q = labs(x) / y[2];
     755          70 :   if (x < 0) q = -q;
     756          70 :   if (s < 0) q = -q;
     757          70 :   return q;
     758             : }
     759             : 
     760             : INLINE GEN
     761           0 : dvmdss(long x, long y, GEN *z)
     762             : {
     763             :   long r;
     764           0 :   GEN q = divss_rem(x,y, &r);
     765           0 :   *z = stoi(r); return q;
     766             : }
     767             : INLINE long
     768  2492969979 : dvmdsBIL(long n, long *r) { *r = remsBIL(n); return divsBIL(n); }
     769             : INLINE ulong
     770   154133109 : dvmduBIL(ulong n, ulong *r) { *r = remsBIL(n); return divsBIL(n); }
     771             : INLINE GEN
     772           0 : dvmdsi(long x, GEN y, GEN *z)
     773             : {
     774             :   long r;
     775           0 :   GEN q = divsi_rem(x,y, &r);
     776           0 :   *z = stoi(r); return q;
     777             : }
     778             : INLINE GEN
     779           0 : dvmdis(GEN x, long y, GEN *z)
     780             : {
     781             :   long r;
     782           0 :   GEN q = divis_rem(x,y, &r);
     783           0 :   *z = stoi(r); return q;
     784             : }
     785             : 
     786             : INLINE long
     787      752169 : smodis(GEN x, long y)
     788             : {
     789      752169 :   pari_sp av = avma;
     790             :   long r;
     791      752169 :   (void)divis_rem(x,y, &r); avma = av; return (r >= 0) ? r: labs(y) + r;
     792             : }
     793             : INLINE GEN
     794       36934 : modis(GEN x, long y) { return stoi(smodis(x,y)); }
     795             : INLINE GEN
     796     7432116 : modsi(long x, GEN y) {
     797             :   long r;
     798     7432116 :   (void)sdivsi_rem(x, y, &r);
     799     7432114 :   return (r >= 0)? stoi(r): addsi_sign(r, y, 1);
     800             : }
     801             : 
     802             : INLINE ulong
     803     1194820 : umodui(ulong x, GEN y)
     804             : {
     805     1194820 :   if (!signe(y)) pari_err_INV("umodui",gen_0);
     806     1194820 :   if (!x || lgefint(y) > 3) return x;
     807      204147 :   return x % (ulong)y[2];
     808             : }
     809             : 
     810             : INLINE GEN
     811           0 : remsi(long x, GEN y)
     812           0 : { long r; (void)sdivsi_rem(x,y, &r); return stoi(r); }
     813             : INLINE GEN
     814           0 : remis(GEN x, long y)
     815             : {
     816           0 :   pari_sp av = avma;
     817             :   long r;
     818           0 :   (void)divis_rem(x,y, &r); avma = av; return stoi(r);
     819             : }
     820             : 
     821             : INLINE GEN
     822           0 : rdivis(GEN x, long y, long prec)
     823             : {
     824           0 :   GEN z = cgetr(prec);
     825           0 :   pari_sp av = avma;
     826           0 :   affrr(divrs(itor(x,prec), y),z);
     827           0 :   avma = av; return z;
     828             : }
     829             : INLINE GEN
     830           0 : rdivsi(long x, GEN y, long prec)
     831             : {
     832           0 :   GEN z = cgetr(prec);
     833           0 :   pari_sp av = avma;
     834           0 :   affrr(divsr(x, itor(y,prec)), z);
     835           0 :   avma = av; return z;
     836             : }
     837             : INLINE GEN
     838      839647 : rdivss(long x, long y, long prec)
     839             : {
     840      839647 :   GEN z = cgetr(prec);
     841      839647 :   pari_sp av = avma;
     842      839647 :   affrr(divrs(stor(x, prec), y), z);
     843      839647 :   avma = av; return z;
     844             : }
     845             : 
     846             : INLINE void
     847          14 : rdiviiz(GEN x, GEN y, GEN z)
     848             : {
     849          14 :   pari_sp av = avma;
     850          14 :   long prec = realprec(z);
     851          14 :   affir(x, z);
     852          14 :   if (!is_bigint(y)) {
     853           0 :     affrr(divrs(z, y[2]), z);
     854           0 :     if (signe(y) < 0) togglesign(z);
     855             :   }
     856             :   else
     857          14 :     affrr(divrr(z, itor(y,prec)), z);
     858          14 :   avma = av;
     859          14 : }
     860             : INLINE GEN
     861    11510684 : rdivii(GEN x, GEN y, long prec)
     862             : {
     863    11510684 :   GEN z = cgetr(prec);
     864    11510684 :   pari_sp av = avma;
     865    11510684 :   affir(x, z);
     866    11510684 :   if (lg(y) == 3) {
     867     7410185 :     affrr(divru(z, y[2]), z);
     868     7410185 :     if (signe(y) < 0) togglesign(z);
     869             :   }
     870             :   else
     871     4100499 :     affrr(divrr(z, itor(y,prec)), z);
     872    11510684 :   avma = av; return z;
     873             : }
     874             : INLINE GEN
     875    11444565 : fractor(GEN x, long prec) { return rdivii(gel(x,1), gel(x,2), prec); }
     876             : 
     877             : INLINE int
     878     1336855 : dvdii(GEN x, GEN y)
     879             : {
     880     1336855 :   pari_sp av=avma;
     881     1336855 :   GEN r = remii(x,y);
     882     1336855 :   avma = av; return r == gen_0;
     883             : }
     884             : INLINE int
     885          77 : dvdsi(long x, GEN y)
     886             : {
     887          77 :   if (!signe(y)) return x == 0;
     888          77 :   if (lgefint(y) != 3) return 0;
     889          77 :   return x % y[2] == 0;
     890             : }
     891             : INLINE int
     892         147 : dvdui(ulong x, GEN y)
     893             : {
     894         147 :   if (!signe(y)) return x == 0;
     895         147 :   if (lgefint(y) != 3) return 0;
     896         147 :   return x % y[2] == 0;
     897             : }
     898             : INLINE int
     899       31526 : dvdis(GEN x, long y)
     900       31526 : { return y? smodis(x, y) == 0: signe(x) == 0; }
     901             : INLINE int
     902        1561 : dvdiu(GEN x, ulong y)
     903        1561 : { return y? umodiu(x, y) == 0: signe(x) == 0; }
     904             : 
     905             : INLINE int
     906           0 : dvdisz(GEN x, long y, GEN z)
     907             : {
     908           0 :   const pari_sp av = avma;
     909             :   long r;
     910           0 :   GEN p1 = divis_rem(x,y, &r);
     911           0 :   avma = av; if (r) return 0;
     912           0 :   affii(p1,z); return 1;
     913             : }
     914             : INLINE int
     915           0 : dvdiuz(GEN x, ulong y, GEN z)
     916             : {
     917           0 :   const pari_sp av = avma;
     918             :   ulong r;
     919           0 :   GEN p1 = diviu_rem(x,y, &r);
     920           0 :   avma = av; if (r) return 0;
     921           0 :   affii(p1,z); return 1;
     922             : }
     923             : INLINE int
     924        3712 : dvdiiz(GEN x, GEN y, GEN z)
     925             : {
     926        3712 :   const pari_sp av=avma;
     927             :   GEN p2;
     928        3712 :   const GEN p1=dvmdii(x,y,&p2);
     929             : 
     930        3712 :   if (signe(p2)) { avma=av; return 0; }
     931        3240 :   affii(p1,z); avma=av; return 1;
     932             : }
     933             : 
     934             : INLINE ulong
     935     8520090 : remlll_pre(ulong u2, ulong u1, ulong u0, ulong n, ulong ninv)
     936             : {
     937     8520090 :   u1 = remll_pre(u2, u1, n, ninv);
     938     8520090 :   return remll_pre(u1, u0, n, ninv);
     939             : }
     940             : 
     941             : INLINE ulong
     942  1757818230 : Fl_sqr_pre(ulong a, ulong p, ulong pi)
     943             : {
     944             :   register ulong x;
     945             :   LOCAL_HIREMAINDER;
     946  1757818230 :   x = mulll(a,a);
     947  1757818230 :   return remll_pre(hiremainder, x, p, pi);
     948             : }
     949             : 
     950             : INLINE ulong
     951  2261530638 : Fl_mul_pre(ulong a, ulong b, ulong p, ulong pi)
     952             : {
     953             :   register ulong x;
     954             :   LOCAL_HIREMAINDER;
     955  2261530638 :   x = mulll(a,b);
     956  2261530638 :   return remll_pre(hiremainder, x, p, pi);
     957             : }
     958             : 
     959             : INLINE ulong
     960  4092536155 : Fl_addmul_pre(ulong x0, ulong x1, ulong y0, ulong p, ulong pi)
     961             : {
     962             :   ulong l0, h0;
     963             :   LOCAL_HIREMAINDER;
     964  4092536155 :   hiremainder = y0;
     965  4092536155 :   l0 = addmul(x0, x1); h0 = hiremainder;
     966  4092536155 :   return remll_pre(h0, l0, p, pi);
     967             : }
     968             : 
     969             : INLINE ulong
     970    45223544 : Fl_addmulmul_pre(ulong x0, ulong y0, ulong x1, ulong y1, ulong p, ulong pi)
     971             : {
     972             :   ulong l0, l1, h0, h1;
     973             :   LOCAL_OVERFLOW;
     974             :   LOCAL_HIREMAINDER;
     975    45223544 :   l0 = mulll(x0, y0); h0 = hiremainder;
     976    45223544 :   l1 = mulll(x1, y1); h1 = hiremainder;
     977    45223544 :   l0 = addll(l0, l1); h0 = addllx(h0, h1);
     978    45223544 :   return overflow ? remlll_pre(1, h0, l0, p, pi): remll_pre(h0, l0, p, pi);
     979             : }
     980             : 
     981             : INLINE ulong
     982     2705056 : Fl_ellj_pre(ulong a4, ulong a6, ulong p, ulong pi)
     983             : {
     984             :   /* a43 = 4 a4^3 */
     985     2705056 :   ulong a43 = Fl_double(Fl_double(
     986             :               Fl_mul_pre(a4, Fl_sqr_pre(a4, p, pi), p, pi), p), p);
     987             :   /* a62 = 27 a6^2 */
     988     2705057 :   ulong a62 = Fl_mul_pre(Fl_sqr_pre(a6, p, pi), 27 % p, p, pi);
     989     2705059 :   ulong z1 = Fl_mul_pre(a43, 1728 % p, p, pi);
     990     2705058 :   ulong z2 = Fl_add(a43, a62, p);
     991     2705055 :   return Fl_div(z1, z2, p);
     992             : }
     993             : 
     994             : /*******************************************************************/
     995             : /*                                                                 */
     996             : /*                        MP (INT OR REAL)                         */
     997             : /*                                                                 */
     998             : /*******************************************************************/
     999             : INLINE GEN
    1000          21 : mptrunc(GEN x) { return typ(x)==t_INT? icopy(x): truncr(x); }
    1001             : INLINE GEN
    1002           0 : mpfloor(GEN x) { return typ(x)==t_INT? icopy(x): floorr(x); }
    1003             : INLINE GEN
    1004           0 : mpceil(GEN x) { return typ(x)==t_INT? icopy(x): ceilr(x); }
    1005             : INLINE GEN
    1006      357776 : mpround(GEN x) { return typ(x) == t_INT? icopy(x): roundr(x); }
    1007             : 
    1008             : INLINE long
    1009      203267 : mpexpo(GEN x) { return typ(x) == t_INT? expi(x): expo(x); }
    1010             : 
    1011             : INLINE GEN
    1012    32856135 : mpadd(GEN x, GEN y)
    1013             : {
    1014    32856135 :   if (typ(x)==t_INT)
    1015     5253203 :     return (typ(y)==t_INT) ? addii(x,y) : addir(x,y);
    1016    27602932 :   return (typ(y)==t_INT) ? addir(y,x) : addrr(x,y);
    1017             : }
    1018             : INLINE GEN
    1019    14118007 : mpsub(GEN x, GEN y)
    1020             : {
    1021    14118007 :   if (typ(x)==t_INT)
    1022      229195 :     return (typ(y)==t_INT) ? subii(x,y) : subir(x,y);
    1023    13888812 :   return (typ(y)==t_INT) ? subri(x,y) : subrr(x,y);
    1024             : }
    1025             : INLINE GEN
    1026    48374806 : mpmul(GEN x, GEN y)
    1027             : {
    1028    48374806 :   if (typ(x)==t_INT)
    1029    15517090 :     return (typ(y)==t_INT) ? mulii(x,y) : mulir(x,y);
    1030    32857716 :   return (typ(y)==t_INT) ? mulir(y,x) : mulrr(x,y);
    1031             : }
    1032             : INLINE GEN
    1033     6101967 : mpsqr(GEN x) { return (typ(x)==t_INT) ? sqri(x) : sqrr(x); }
    1034             : INLINE GEN
    1035      144005 : mpdiv(GEN x, GEN y)
    1036             : {
    1037      144005 :   if (typ(x)==t_INT)
    1038       72144 :     return (typ(y)==t_INT) ? divii(x,y) : divir(x,y);
    1039       71861 :   return (typ(y)==t_INT) ? divri(x,y) : divrr(x,y);
    1040             : }
    1041             : 
    1042             : /*******************************************************************/
    1043             : /*                                                                 */
    1044             : /*                          Z/nZ, n ULONG                          */
    1045             : /*                                                                 */
    1046             : /*******************************************************************/
    1047             : INLINE ulong
    1048   642439032 : Fl_double(ulong a, ulong p)
    1049             : {
    1050   642439032 :   ulong res = a << 1;
    1051   642439032 :   return (res >= p || res < a) ? res - p : res;
    1052             : }
    1053             : INLINE ulong
    1054    88720535 : Fl_triple(ulong a, ulong p)
    1055             : {
    1056    88720535 :   ulong res = a << 1;
    1057    88720535 :   if (res >= p || res < a) res -= p;
    1058    88720535 :   res += a;
    1059    88720535 :   return (res >= p || res < a)? res - p: res;
    1060             : }
    1061             : INLINE ulong
    1062    12783998 : Fl_halve(ulong a, ulong p)
    1063             : {
    1064             :   ulong ap, ap2;
    1065    12783998 :   if ((a&1UL)==0) return a>>1;
    1066     6457356 :   ap = a + p; ap2 = ap>>1;
    1067     6457356 :   return ap>=a ? ap2: (ap2|HIGHBIT);
    1068             : }
    1069             : 
    1070             : INLINE ulong
    1071  2380371982 : Fl_add(ulong a, ulong b, ulong p)
    1072             : {
    1073  2380371982 :   ulong res = a + b;
    1074  2380371982 :   return (res >= p || res < a) ? res - p : res;
    1075             : }
    1076             : INLINE ulong
    1077    73678074 : Fl_neg(ulong x, ulong p) { return x ? p - x: 0; }
    1078             : 
    1079             : INLINE ulong
    1080  3997720223 : Fl_sub(ulong a, ulong b, ulong p)
    1081             : {
    1082  3997720223 :   ulong res = a - b;
    1083  3997720223 :   return (res > a) ? res + p: res;
    1084             : }
    1085             : 
    1086             : /* centerlift(u mod p) */
    1087             : INLINE long
    1088    19782920 : Fl_center(ulong u, ulong p, ulong ps2) { return (long) (u > ps2)? u - p: u; }
    1089             : 
    1090             : INLINE ulong
    1091   770439486 : Fl_mul(ulong a, ulong b, ulong p)
    1092             : {
    1093             :   register ulong x;
    1094             :   LOCAL_HIREMAINDER;
    1095   770439486 :   x = mulll(a,b);
    1096   770439486 :   if (!hiremainder) return x % p;
    1097   114757240 :   (void)divll(x,p); return hiremainder;
    1098             : }
    1099             : INLINE ulong
    1100    36514093 : Fl_sqr(ulong a, ulong p)
    1101             : {
    1102             :   register ulong x;
    1103             :   LOCAL_HIREMAINDER;
    1104    36514093 :   x = mulll(a,a);
    1105    36514093 :   if (!hiremainder) return x % p;
    1106    14092073 :   (void)divll(x,p); return hiremainder;
    1107             : }
    1108             : INLINE ulong
    1109    10977106 : Fl_div(ulong a, ulong b, ulong p) { return Fl_mul(a, Fl_inv(b, p), p); }
    1110             : 
    1111             : /*******************************************************************/
    1112             : /*                                                                 */
    1113             : /*        DEFINED FROM EXISTING ONE EXPLOITING COMMUTATIVITY       */
    1114             : /*                                                                 */
    1115             : /*******************************************************************/
    1116             : INLINE GEN
    1117      180764 : addri(GEN x, GEN y) { return addir(y,x); }
    1118             : INLINE GEN
    1119    49447780 : addis(GEN x, long s) { return addsi(s,x); }
    1120             : INLINE GEN
    1121    31362081 : addiu(GEN x, ulong s) { return addui(s,x); }
    1122             : INLINE GEN
    1123     2564393 : addrs(GEN x, long s) { return addsr(s,x); }
    1124             : 
    1125             : INLINE GEN
    1126    19230673 : subiu(GEN x, long y) { GEN z = subui(y, x); togglesign(z); return z; }
    1127             : INLINE GEN
    1128        4268 : subis(GEN x, long y) { return addsi(-y,x); }
    1129             : INLINE GEN
    1130     2772996 : subrs(GEN x, long y) { return addsr(-y,x); }
    1131             : 
    1132             : INLINE GEN
    1133   122912181 : mulis(GEN x, long s) { return mulsi(s,x); }
    1134             : INLINE GEN
    1135   563478128 : muliu(GEN x, ulong s) { return mului(s,x); }
    1136             : INLINE GEN
    1137     4245258 : mulru(GEN x, ulong s) { return mulur(s,x); }
    1138             : INLINE GEN
    1139    13880750 : mulri(GEN x, GEN s) { return mulir(s,x); }
    1140             : INLINE GEN
    1141    10015339 : mulrs(GEN x, long s) { return mulsr(s,x); }
    1142             : 
    1143             : /*******************************************************************/
    1144             : /*                                                                 */
    1145             : /*                  VALUATION, EXPONENT, SHIFTS                    */
    1146             : /*                                                                 */
    1147             : /*******************************************************************/
    1148             : INLINE long
    1149    54914885 : vali(GEN x)
    1150             : {
    1151             :   long i;
    1152             :   GEN xp;
    1153             : 
    1154    54914885 :   if (!signe(x)) return -1;
    1155    54914745 :   xp=int_LSW(x);
    1156    54914745 :   for (i=0; !*xp; i++) xp=int_nextW(xp);
    1157    54914745 :   return vals(*xp) + i * BITS_IN_LONG;
    1158             : }
    1159             : 
    1160             : 
    1161             : /* assume x > 0 */
    1162             : INLINE long
    1163   323314765 : expu(ulong x) { return (BITS_IN_LONG-1) - (long)bfffo(x); }
    1164             : 
    1165             : INLINE long
    1166   723727044 : expi(GEN x)
    1167             : {
    1168   723727044 :   const long lx=lgefint(x);
    1169   723727044 :   return lx==2? -(long)HIGHEXPOBIT: bit_accuracy(lx)-(long)bfffo(*int_MSW(x))-1;
    1170             : }
    1171             : 
    1172             : INLINE GEN
    1173    47874425 : shiftr(GEN x, long n)
    1174             : {
    1175    47874425 :   const long e = evalexpo(expo(x)+n);
    1176    47874425 :   const GEN y = rcopy(x);
    1177             : 
    1178    47874425 :   if (e & ~EXPOBITS) pari_err_OVERFLOW("expo()");
    1179    47874425 :   y[1] = (y[1]&~EXPOBITS) | e; return y;
    1180             : }
    1181             : INLINE GEN
    1182    10970135 : mpshift(GEN x,long s) { return (typ(x)==t_INT)?shifti(x,s):shiftr(x,s); }
    1183             : 
    1184             : /* FIXME: adapt/use mpn_[lr]shift instead */
    1185             : /* z2[imin..imax] := z1[imin..imax].f shifted left sh bits
    1186             :  * (feeding f from the right). Assume sh > 0 */
    1187             : INLINE void
    1188  2543708998 : shift_left(GEN z2, GEN z1, long imin, long imax, ulong f,  ulong sh)
    1189             : {
    1190  2543708998 :   GEN sb = z1 + imin, se = z1 + imax, te = z2 + imax;
    1191  2543708998 :   ulong l, m = BITS_IN_LONG - sh, k = f >> m;
    1192 12411730923 :   while (se > sb) {
    1193  7324312927 :     l     = *se--;
    1194  7324312927 :     *te-- = (l << sh) | k;
    1195  7324312927 :     k     = l >> m;
    1196             :   }
    1197  2543708998 :   *te = (((ulong)*se) << sh) | k;
    1198  2543708998 : }
    1199             : /* z2[imin..imax] := f.z1[imin..imax-1] shifted right sh bits
    1200             :  * (feeding f from the left). Assume sh > 0 */
    1201             : INLINE void
    1202  2481910207 : shift_right(GEN z2, GEN z1, long imin, long imax, ulong f, ulong sh)
    1203             : {
    1204  2481910207 :   GEN sb = z1 + imin, se = z1 + imax, tb = z2 + imin;
    1205  2481910207 :   ulong k, l = *sb++, m = BITS_IN_LONG - sh;
    1206  2481910207 :   *tb++ = (l >> sh) | (f << m);
    1207 12405929119 :   while (sb < se) {
    1208  7442108705 :     k     = l << m;
    1209  7442108705 :     l     = *sb++;
    1210  7442108705 :     *tb++ = (l >> sh) | k;
    1211             :   }
    1212  2481910207 : }
    1213             : 
    1214             : /* Backward compatibility. Inefficient && unused */
    1215             : extern ulong hiremainder;
    1216             : INLINE ulong
    1217           0 : shiftl(ulong x, ulong y)
    1218           0 : { hiremainder = x>>(BITS_IN_LONG-y); return (x<<y); }
    1219             : 
    1220             : INLINE ulong
    1221           0 : shiftlr(ulong x, ulong y)
    1222           0 : { hiremainder = x<<(BITS_IN_LONG-y); return (x>>y); }
    1223             : 
    1224             : INLINE void
    1225    78141167 : shiftr_inplace(GEN z, long d)
    1226             : {
    1227    78141167 :   setexpo(z, expo(z)+d);
    1228    78141167 : }
    1229             : 
    1230             : /*******************************************************************/
    1231             : /*                                                                 */
    1232             : /*                           ASSIGNMENT                            */
    1233             : /*                                                                 */
    1234             : /*******************************************************************/
    1235             : INLINE void
    1236    37878897 : affii(GEN x, GEN y)
    1237             : {
    1238    37878897 :   long lx = lgefint(x);
    1239    37878897 :   if (lg(y)<lx) pari_err_OVERFLOW("t_INT-->t_INT assignment");
    1240    37878889 :   while (--lx) y[lx] = x[lx];
    1241    37878889 : }
    1242             : INLINE void
    1243      279197 : affsi(long s, GEN x)
    1244             : {
    1245      279197 :   if (!s) x[1] = evalsigne(0) | evallgefint(2);
    1246             :   else
    1247             :   {
    1248      263802 :     if (s > 0) { x[1] = evalsigne( 1) | evallgefint(3); x[2] =  s; }
    1249       92203 :     else       { x[1] = evalsigne(-1) | evallgefint(3); x[2] = -s; }
    1250             :   }
    1251      279197 : }
    1252             : INLINE void
    1253     8404835 : affui(ulong u, GEN x)
    1254             : {
    1255     8404835 :   if (!u) x[1] = evalsigne(0) | evallgefint(2);
    1256     8403561 :   else  { x[1] = evalsigne(1) | evallgefint(3); x[2] = u; }
    1257     8404835 : }
    1258             : 
    1259             : INLINE void
    1260   143323173 : affsr(long x, GEN y)
    1261             : {
    1262   143323173 :   long sh, i, ly = lg(y);
    1263             : 
    1264   143323173 :   if (!x)
    1265             :   {
    1266     1366460 :     y[1] = evalexpo(-prec2nbits(ly));
    1267   144689633 :     return;
    1268             :   }
    1269   141956713 :   if (x < 0) {
    1270      165661 :     x = -x; sh = bfffo(x);
    1271      165661 :     y[1] = evalsigne(-1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1272             :   }
    1273             :   else
    1274             :   {
    1275   141791052 :     sh = bfffo(x);
    1276   141791052 :     y[1] = evalsigne(1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1277             :   }
    1278   141956713 :   y[2] = ((ulong)x)<<sh; for (i=3; i<ly; i++) y[i]=0;
    1279             : }
    1280             : 
    1281             : INLINE void
    1282     5487749 : affur(ulong x, GEN y)
    1283             : {
    1284     5487749 :   long sh, i, ly = lg(y);
    1285             : 
    1286     5487749 :   if (!x)
    1287             :   {
    1288         266 :     y[1] = evalexpo(-prec2nbits(ly));
    1289     5488015 :     return;
    1290             :   }
    1291     5487483 :   sh = bfffo(x);
    1292     5487483 :   y[1] = evalsigne(1) | _evalexpo((BITS_IN_LONG-1)-sh);
    1293     5487483 :   y[2] = x<<sh; for (i=3; i<ly; i++) y[i] = 0;
    1294             : }
    1295             : 
    1296             : INLINE void
    1297      106226 : affiz(GEN x, GEN y) { if (typ(y)==t_INT) affii(x,y); else affir(x,y); }
    1298             : INLINE void
    1299           0 : affsz(long x, GEN y) { if (typ(y)==t_INT) affsi(x,y); else affsr(x,y); }
    1300             : INLINE void
    1301      133499 : mpaff(GEN x, GEN y) { if (typ(x)==t_INT) affiz(x, y); else affrr(x,y); }
    1302             : 
    1303             : /*******************************************************************/
    1304             : /*                                                                 */
    1305             : /*                    OPERATION + ASSIGNMENT                       */
    1306             : /*                                                                 */
    1307             : /*******************************************************************/
    1308             : 
    1309           0 : INLINE void addiiz(GEN x, GEN y, GEN z)
    1310           0 : { pari_sp av = avma; affii(addii(x,y),z); avma = av; }
    1311           0 : INLINE void addirz(GEN x, GEN y, GEN z)
    1312           0 : { pari_sp av = avma; affrr(addir(x,y),z); avma = av; }
    1313           0 : INLINE void addriz(GEN x, GEN y, GEN z)
    1314           0 : { pari_sp av = avma; affrr(addri(x,y),z); avma = av; }
    1315     1411916 : INLINE void addrrz(GEN x, GEN y, GEN z)
    1316     1411916 : { pari_sp av = avma; affrr(addrr(x,y),z); avma = av; }
    1317           0 : INLINE void addsiz(long s, GEN y, GEN z)
    1318           0 : { pari_sp av = avma; affii(addsi(s,y),z); avma = av; }
    1319           0 : INLINE void addsrz(long s, GEN y, GEN z)
    1320           0 : { pari_sp av = avma; affrr(addsr(s,y),z); avma = av; }
    1321           0 : INLINE void addssz(long s, long y, GEN z)
    1322           0 : { pari_sp av = avma; affii(addss(s,y),z); avma = av; }
    1323             : 
    1324          21 : INLINE void diviiz(GEN x, GEN y, GEN z)
    1325          21 : { pari_sp av = avma; affii(divii(x,y),z); avma = av; }
    1326           0 : INLINE void divirz(GEN x, GEN y, GEN z)
    1327           0 : { pari_sp av = avma; mpaff(divir(x,y),z); avma = av; }
    1328           0 : INLINE void divisz(GEN x, long y, GEN z)
    1329           0 : { pari_sp av = avma; affii(divis(x,y),z); avma = av; }
    1330           0 : INLINE void divriz(GEN x, GEN y, GEN z)
    1331           0 : { pari_sp av = avma; affrr(divri(x,y),z); avma = av; }
    1332         354 : INLINE void divrrz(GEN x, GEN y, GEN z)
    1333         354 : { pari_sp av = avma; affrr(divrr(x,y),z); avma = av; }
    1334       90548 : INLINE void divrsz(GEN y, long s, GEN z)
    1335       90548 : { pari_sp av = avma; affrr(divrs(y,s),z); avma = av; }
    1336           0 : INLINE void divsiz(long x, GEN y, GEN z)
    1337           0 : { long junk; affsi(sdivsi_rem(x,y,&junk), z); }
    1338           0 : INLINE void divsrz(long s, GEN y, GEN z)
    1339           0 : { pari_sp av = avma; mpaff(divsr(s,y),z); avma = av; }
    1340           0 : INLINE void divssz(long x, long y, GEN z)
    1341           0 : { affsi(x/y, z); }
    1342             : 
    1343           0 : INLINE void modisz(GEN y, long s, GEN z)
    1344           0 : { affsi(smodis(y,s),z); }
    1345           0 : INLINE void modsiz(long s, GEN y, GEN z)
    1346           0 : { pari_sp av = avma; affii(modsi(s,y),z); avma = av; }
    1347           0 : INLINE void modssz(long s, long y, GEN z)
    1348           0 : { affsi(smodss(s,y),z); }
    1349             : 
    1350           0 : INLINE void mpaddz(GEN x, GEN y, GEN z)
    1351           0 : { pari_sp av = avma; mpaff(mpadd(x,y),z); avma = av; }
    1352           0 : INLINE void mpsubz(GEN x, GEN y, GEN z)
    1353           0 : { pari_sp av = avma; mpaff(mpsub(x,y),z); avma = av; }
    1354           0 : INLINE void mpmulz(GEN x, GEN y, GEN z)
    1355           0 : { pari_sp av = avma; mpaff(mpmul(x,y),z); avma = av; }
    1356             : 
    1357           0 : INLINE void muliiz(GEN x, GEN y, GEN z)
    1358           0 : { pari_sp av = avma; affii(mulii(x,y),z); avma = av; }
    1359           0 : INLINE void mulirz(GEN x, GEN y, GEN z)
    1360           0 : { pari_sp av = avma; mpaff(mulir(x,y),z); avma = av; }
    1361           0 : INLINE void mulriz(GEN x, GEN y, GEN z)
    1362           0 : { pari_sp av = avma; mpaff(mulri(x,y),z); avma = av; }
    1363       56940 : INLINE void mulrrz(GEN x, GEN y, GEN z)
    1364       56940 : { pari_sp av = avma; affrr(mulrr(x,y),z); avma = av; }
    1365           0 : INLINE void mulsiz(long s, GEN y, GEN z)
    1366           0 : { pari_sp av = avma; affii(mulsi(s,y),z); avma = av; }
    1367           0 : INLINE void mulsrz(long s, GEN y, GEN z)
    1368           0 : { pari_sp av = avma; mpaff(mulsr(s,y),z); avma = av; }
    1369           0 : INLINE void mulssz(long s, long y, GEN z)
    1370           0 : { pari_sp av = avma; affii(mulss(s,y),z); avma = av; }
    1371             : 
    1372           0 : INLINE void remiiz(GEN x, GEN y, GEN z)
    1373           0 : { pari_sp av = avma; affii(remii(x,y),z); avma = av; }
    1374           0 : INLINE void remisz(GEN y, long s, GEN z)
    1375           0 : { pari_sp av = avma; affii(remis(y,s),z); avma = av; }
    1376           0 : INLINE void remsiz(long s, GEN y, GEN z)
    1377           0 : { pari_sp av = avma; affii(remsi(s,y),z); avma = av; }
    1378           0 : INLINE void remssz(long s, long y, GEN z)
    1379           0 : { pari_sp av = avma; affii(remss(s,y),z); avma = av; }
    1380             : 
    1381           0 : INLINE void subiiz(GEN x, GEN y, GEN z)
    1382           0 : { pari_sp av = avma; affii(subii(x,y),z); avma = av; }
    1383           0 : INLINE void subirz(GEN x, GEN y, GEN z)
    1384           0 : { pari_sp av = avma; affrr(subir(x,y),z); avma = av; }
    1385           0 : INLINE void subisz(GEN y, long s, GEN z)
    1386           0 : { pari_sp av = avma; affii(addsi(-s,y),z); avma = av; }
    1387           0 : INLINE void subriz(GEN x, GEN y, GEN z)
    1388           0 : { pari_sp av = avma; affrr(subri(x,y),z); avma = av; }
    1389     1295642 : INLINE void subrrz(GEN x, GEN y, GEN z)
    1390     1295642 : { pari_sp av = avma; affrr(subrr(x,y),z); avma = av; }
    1391           0 : INLINE void subrsz(GEN y, long s, GEN z)
    1392           0 : { pari_sp av = avma; affrr(addsr(-s,y),z); avma = av; }
    1393           0 : INLINE void subsiz(long s, GEN y, GEN z)
    1394           0 : { pari_sp av = avma; affii(subsi(s,y),z); avma = av; }
    1395           0 : INLINE void subsrz(long s, GEN y, GEN z)
    1396           0 : { pari_sp av = avma; affrr(subsr(s,y),z); avma = av; }
    1397           0 : INLINE void subssz(long x, long y, GEN z) { addssz(x,-y,z); }
    1398             : 
    1399             : INLINE void
    1400           0 : dvmdssz(long x, long y, GEN z, GEN t) {
    1401           0 :   pari_sp av = avma;
    1402             :   long r;
    1403           0 :   affii(divss_rem(x,y, &r), z); avma = av; affsi(r,t);
    1404           0 : }
    1405             : INLINE void
    1406           0 : dvmdsiz(long x, GEN y, GEN z, GEN t) {
    1407           0 :   pari_sp av = avma;
    1408             :   long r;
    1409           0 :   affii(divsi_rem(x,y, &r), z); avma = av; affsi(r,t);
    1410           0 : }
    1411             : INLINE void
    1412           0 : dvmdisz(GEN x, long y, GEN z, GEN t) {
    1413           0 :   pari_sp av = avma;
    1414             :   long r;
    1415           0 :   affii(divis_rem(x,y, &r),z); avma = av; affsi(r,t);
    1416           0 : }
    1417             : INLINE void
    1418           0 : dvmdiiz(GEN x, GEN y, GEN z, GEN t) {
    1419           0 :   pari_sp av = avma;
    1420             :   GEN r;
    1421           0 :   affii(dvmdii(x,y,&r),z); affii(r,t); avma=av;
    1422           0 : }

Generated by: LCOV version 1.11