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 - basemath - random.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31041-bd73e9fcdd) Lines: 99.4 % 162 161
Test Date: 2026-07-22 22:45:42 Functions: 100.0 % 17 17
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copyright (C) 2000  The PARI group.
       2              : 
       3              : This file is part of the PARI/GP package.
       4              : 
       5              : PARI/GP is free software; you can redistribute it and/or modify it under the
       6              : terms of the GNU General Public License as published by the Free Software
       7              : Foundation; either version 2 of the License, or (at your option) any later
       8              : version. It is distributed in the hope that it will be useful, but WITHOUT
       9              : ANY WARRANTY WHATSOEVER.
      10              : 
      11              : Check the License for details. You should have received a copy of it, along
      12              : with the package; see the file 'COPYING'. If not, write to the Free Software
      13              : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      14              : /********************************************************************/
      15              : /*                                                                  */
      16              : /*                      PSEUDO-RANDOM INTEGERS                      */
      17              : /*                                                                  */
      18              : /********************************************************************/
      19              : #include "pari.h"
      20              : #include "paripriv.h"
      21              : /********************************************************************/
      22              : /*                    XORGEN (Richard P. Brent)                     */
      23              : /*          http://wwwmaths.anu.edu.au/~brent/random.html           */
      24              : /*        (initial adaptation to PARI/GP by Randall Rathbun)        */
      25              : /********************************************************************/
      26              : /* Adapted from xorgens.c version 3.04, Richard P. Brent, 20060628 (GPL).
      27              :  * 32-bit or 64-bit integer random number generator with period at
      28              :  * least 2**4096-1. It is assumed that "ulong" is a 32-bit or 64-bit integer */
      29              : 
      30              : #ifdef LONG_IS_64BIT
      31              :   typedef ulong u64;
      32              : #else
      33              :   typedef unsigned long long u64;
      34              : static u64
      35       448111 : _32to64(ulong a, ulong b) { u64 v = a; return (v<<32)|b; }
      36              : static void
      37     13724897 : _64to32(u64 v, ulong *a, ulong *b) { *a = v>>32; *b = v&0xFFFFFFFF; }
      38              : #endif
      39              : static THREAD u64 state[64];
      40              : static THREAD u64 xorgen_w;
      41              : static THREAD int xorgen_i;
      42              : /* weyl = odd approximation to 2^64*(sqrt(5)-1)/2. */
      43              : static const u64 weyl = (((u64)0x61c88646U)<<32)|((u64)0x80b583ebU);
      44              : 
      45              : static u64
      46    193822188 : block(void)
      47              : {
      48    193822188 :   const int r = 64;
      49    193822188 :   const int a = 33, b = 26, c = 27, d = 29, s = 53;
      50              :   u64 t, v, w;
      51    193822188 :   xorgen_i = (xorgen_i+1)&(r-1);
      52    193822188 :   t = state[xorgen_i];
      53    193822188 :   v = state[(xorgen_i+(r-s))&(r-1)];   /* index is (i-s) mod r */
      54    193822188 :   t ^= t<<a; t ^= t>>b;                   /* (I + L^a)(I + R^b) */
      55    193822188 :   v ^= v<<c; v ^= v>>d;                   /* (I + L^c)(I + R^d) */
      56    193822188 :   w = t^v;
      57    193822188 :   return state[xorgen_i] = w;               /* update circular array */
      58              : }
      59              : 
      60              : /* v > 0 */
      61              : static void
      62       440916 : init_xor4096i(u64 v)
      63              : {
      64       440916 :   const int r = 64;
      65              :   int k;
      66              : 
      67     28647759 :   for (k = r; k > 0; k--) {/* avoid correlations for close seeds */
      68     28206843 :     v ^= v<<10; v ^= v>>15; /* recurrence has period 2**64-1 */
      69     28206843 :     v ^= v<<4;  v ^= v>>13;
      70              :   }
      71     28632099 :   for (xorgen_w = v, k = 0; k < r; k++) { /* initialise circular array */
      72     28191183 :     v ^= v<<10; v ^= v>>15;
      73     28191183 :     v ^= v<<4;  v ^= v>>13;
      74     28191183 :     state[k] = v + (xorgen_w+=weyl);
      75              :   }
      76              :   /* discard first 4*r results */
      77    111443103 :   for (xorgen_i = r-1, k = 4*r; k > 0; k--) (void)block();
      78       435190 : }
      79              : 
      80              : void
      81       378486 : pari_init_rand(void) { init_xor4096i(1UL); }
      82              : 
      83              : static u64
      84     82812382 : rand64(void)
      85              : {
      86     82812382 :   u64 v = block();
      87     82825067 :   xorgen_w += weyl; /* update Weyl generator */
      88     82825067 :   return v + (xorgen_w ^ (xorgen_w>>27));
      89              : }
      90              : 
      91              : /* One random number uniformly distributed in [0..2**BIL) is returned, where
      92              :  * BIL = 8*sizeof(ulong) = 32 or 64. */
      93              : ulong
      94        94984 : pari_rand(void) { return rand64(); }
      95              : 
      96              : void
      97       110704 : setrand(GEN x)
      98              : {
      99       110704 :   const int r2 = numberof(state);
     100              :   long i, lx;
     101              :   u64 v;
     102              :   GEN xp;
     103       110704 :   if (typ(x)!=t_INT) pari_err_TYPE("setrand",x);
     104       110704 :   if (signe(x) <= 0) pari_err_DOMAIN("setrand","n", "<=", gen_0, x);
     105       110697 :   lx = lgefint(x);
     106       110697 :   if (lx == 3) { v = x[2]; init_xor4096i(v); return; }
     107              : #ifndef LONG_IS_64BIT
     108         6896 :   if (lx == 4)
     109              :   {
     110            1 :     v = _32to64(*int_W(x,1),*int_W(x,0));
     111            1 :     init_xor4096i(v); return;
     112              :   }
     113              : #endif
     114        48271 :   xp = int_LSW(x);
     115              : #ifdef LONG_IS_64BIT
     116        41376 :   if (lx != 2 + r2+2)
     117            6 :     pari_err_DOMAIN("setrand", "n", "!=", strtoGENstr("getrand()"), x);
     118      2689050 :   for (i = 0; i < r2; i++, xp = int_nextW(xp)) state[i] = *xp;
     119        41370 :   xorgen_w = *xp; xp = int_nextW(xp);
     120              : #else
     121         6895 :   if (lx != 2 + 2*r2+3)
     122            1 :     pari_err_DOMAIN("setrand", "n", "!=", strtoGENstr("getrand()"), x);
     123       448110 :   for (i = 0; i < r2; i++, xp = int_nextW(int_nextW(xp)))
     124       441216 :     state[i] = _32to64(*int_nextW(xp), *xp);
     125         6894 :   xorgen_w = _32to64(*int_nextW(xp), *xp); xp = int_nextW(int_nextW(xp));
     126              : #endif
     127        48264 :   xorgen_i =  (*xp) & 63;
     128              : }
     129              : 
     130              : GEN
     131      1458690 : getrand(void)
     132              : {
     133      1458690 :   const int r2 = numberof(state);
     134              :   GEN x;
     135              :   ulong *xp;
     136              :   long i;
     137      1458690 :   if (xorgen_i < 0) init_xor4096i(1UL);
     138              : 
     139              : #ifdef LONG_IS_64BIT
     140      1250530 :   x = cgetipos(2+r2+2); xp = (ulong *) int_LSW(x);
     141     81284330 :   for (i = 0; i < r2; i++, xp = int_nextW(xp)) *xp = state[i];
     142      1250530 :   *xp = xorgen_w; xp = int_nextW(xp);
     143              : #else
     144       208160 :   x = cgetipos(2+2*r2+3); xp = (ulong *) int_LSW(x);
     145     13530400 :   for (i = 0; i < r2; i++, xp = int_nextW(int_nextW(xp)))
     146     13322240 :     _64to32(state[i], int_nextW(xp), xp);
     147       208160 :   _64to32(xorgen_w, int_nextW(xp), xp); xp = int_nextW(int_nextW(xp));
     148              : #endif
     149      1458690 :   *xp = xorgen_i? xorgen_i: 64; return x;
     150              : }
     151              : 
     152              : /* assume 0 <= k <= BITS_IN_LONG. Return uniform random 0 <= x < (1<<k) */
     153              : long
     154     23997516 : random_bits(long k) { return rand64() >> (64-k); }
     155              : 
     156              : /********************************************************************/
     157              : /*                                                                  */
     158              : /*                         GENERIC ROUTINES                         */
     159              : /*                                                                  */
     160              : /********************************************************************/
     161              : 
     162              : /* assume n > 0 */
     163              : ulong
     164     40370307 : random_Fl(ulong n)
     165              : {
     166              :   ulong d;
     167              :   int shift;
     168              : #ifdef LONG_IS_64BIT
     169     34032323 :   int SHIFT = 0;
     170              : #else
     171      6337984 :   int SHIFT = 32;
     172              : #endif
     173              : 
     174     40370307 :   if (n == 1) return 0;
     175              : 
     176     40108724 :   shift = bfffo(n); /* 2^(BIL-shift) > n >= 2^(BIL-shift-1)*/
     177              :   /* if N a power of 2, increment shift. No reject */
     178     40108724 :   if ((n << shift) == HIGHBIT) return rand64() >> (SHIFT+shift+1);
     179              :   for (;;) {
     180     55746237 :     d = rand64() >> (SHIFT+shift); /* d < 2^(64-shift) uniformly distributed */
     181              :     /* reject strategy: proba success = n 2^(shift-64), in [1/2, 1[ */
     182     55760326 :     if (d < n) return d;
     183              :   }
     184              : }
     185              : 
     186              : /* assume N > 0, see random_Fl() for algorithm. Make sure that 32-bit and
     187              :  * 64-bit architectures produce the same integers (consuming random bits
     188              :  * by packets of 64) */
     189              : GEN
     190      2883010 : randomi(GEN N)
     191              : {
     192      2883010 :   long lx = lgefint(N);
     193              :   GEN x, d;
     194              :   int shift;
     195              : 
     196      2883010 :   if (lx == 3) return utoi( random_Fl(N[2]) );
     197              : 
     198       254341 :   shift = bfffo(*int_MSW(N));
     199              :   /* if N a power of 2, increment shift */
     200       254341 :   if (Z_ispow2(N) && ++shift == BITS_IN_LONG) { shift = 0; lx--; }
     201       254342 :   x = cgetipos(lx);
     202       207891 :   for (;;) {
     203       462233 :     GEN y, MSW = int_MSW(x), STOP = MSW;
     204              : #ifdef LONG_IS_64BIT
     205      1016938 :     for (d = int_LSW(x); d != STOP; d = int_nextW(d)) *d = rand64();
     206       376515 :     *d = rand64() >> shift;
     207              : #else
     208        85718 :     if (!odd(lx)) STOP = int_precW(STOP);
     209              :     /* STOP points to where MSW would in 64-bit */
     210       194497 :     for (d = int_LSW(x); d != STOP; d = int_nextW(d))
     211              :     {
     212       108779 :       ulong a, b; _64to32(rand64(), &a,&b);
     213       108779 :       *d = b; d = int_nextW(d);
     214       108779 :       *d = a;
     215              :     }
     216              :     {
     217        85718 :       ulong a, b; _64to32(rand64() >> shift, &a,&b);
     218        85718 :       if (d == MSW) /* 32 bits needed */
     219        56060 :         *d = a;
     220              :       else
     221              :       { /* 64 bits needed */
     222        29658 :         *d = b; d = int_nextW(d);
     223        29658 :         *d = a;
     224              :       }
     225              :     }
     226              : #endif
     227       462233 :     y = int_normalize(x, 0);
     228       462233 :     if (abscmpii(y, N) < 0) return y;
     229              :   }
     230              : }
     231              : 
     232              : GEN
     233       546425 : random_F2x(long d, long vs)
     234              : {
     235       546425 :   ulong db, dl = dvmduBIL(d,&db);
     236       546425 :   long i, l = 2 + dl + !!db;
     237       546425 :   GEN y = cgetg(l,t_VECSMALL); y[1] = vs;
     238              : #ifdef LONG_IS_64BIT
     239       937528 :   for (i=2; i<l; i++) uel(y,i) = rand64();
     240              : #else
     241        78100 :   for (i=2; i<l-1; i+=2)
     242              :   {
     243          136 :     u64 v = rand64();
     244          136 :     uel(y,i)   = (ulong) v;
     245          136 :     uel(y,i+1) = (ulong) (v>>32);
     246              :   }
     247        77964 :   if (i<l) uel(y,i) = (ulong) rand64();
     248              : #endif
     249       546425 :   if (db) uel(y,l-1) &= ((1UL<<db)-1UL);
     250       546425 :   return F2x_renormalize(y,l);
     251              : }
     252              : 
     253              : GEN
     254           59 : random_zv(long n)
     255              : {
     256           59 :   GEN y = cgetg(n+1, t_VECSMALL);
     257              :   long i;
     258        94981 :   for (i=1; i<=n; i++) uel(y,i) = pari_rand();
     259           59 :   return y;
     260              : }
     261              : 
     262              : GEN
     263         4473 : randomr(long prec)
     264              : {
     265              :   pari_sp av;
     266              :   long b;
     267              :   GEN x, y;
     268         4473 :   if (prec <= 2) return real_0_bit(0);
     269         4445 :   x = cgetr(prec); av = avma;
     270         4445 :   b = prec2nbits(prec);
     271         4445 :   y = randomi(int2n(b));
     272         4445 :   if (!signe(y)) return real_0_bit(b);
     273         4445 :   affir(y, x); shiftr_inplace(x, - b);
     274         4445 :   set_avma(av); return x;
     275              : }
     276              : 
     277              : static GEN
     278       156772 : polrandom(GEN N) /* assume N!=0 */
     279              : {
     280       156772 :   long i, d = lg(N);
     281       156772 :   GEN z = leading_coeff(N);
     282       156772 :   GEN y = cgetg(d,t_POL);
     283       156772 :   y[1] = evalsigne(1) | evalvarn(varn(N));
     284       716086 :   for (i=2; i<d; i++) gel(y,i) = genrand(z);
     285       156772 :   return normalizepol_lg(y,d);
     286              : }
     287              : 
     288              : GEN
     289      5592018 : genrand(GEN N)
     290              : {
     291              :   GEN z;
     292      5592018 :   if (!N) return utoi( random_bits(31) );
     293      5591339 :   switch(typ(N))
     294              :   {
     295       747460 :     case t_INT:
     296       747460 :       switch(signe(N))
     297              :       {
     298              :         pari_sp av;
     299              :         GEN d;
     300       287000 :         case 1:
     301       287000 :           return randomi(N);
     302       460453 :         case -1:
     303       460453 :           av = avma; N = addiu(N, 1); d = subui(1, shifti(N, 1));
     304       460453 :           return gc_INT(av, addii(N, randomi(d)));
     305            7 :         default: pari_err_DOMAIN("random","N","=",gen_0,gen_0);
     306              :       }
     307            7 :     case t_REAL:
     308            7 :       return randomr(realprec(N));
     309       680421 :     case t_INTMOD:
     310       680421 :       z = cgetg(3, t_INTMOD);
     311       680421 :       gel(z,1) = icopy(gel(N,1));
     312       680421 :       gel(z,2) = randomi(gel(N,1)); return z;
     313       184493 :     case t_FFELT:
     314       184493 :       return ffrandom(N);
     315       156772 :     case t_POL:
     316       156772 :       if (signe(N)==0) return pol_0(varn(N));
     317       156772 :       return polrandom(N);
     318      3822179 :     case t_VEC:
     319      3822179 :       if (lg(N) == 3)
     320              :       {
     321      3576174 :         pari_sp av = avma;
     322      3576174 :         GEN a = gel(N,1), b = gel(N,2), d;
     323              :         long s;
     324      3576174 :         if (typ(a) != t_INT) a = gceil(a);
     325      3576174 :         if (typ(b) != t_INT) b = gfloor(b);
     326      3576174 :         if (typ(a) != t_INT || typ(b) != t_INT) pari_err_TYPE("random", N);
     327      3576174 :         d = subii(b,a); s = signe(d);
     328      3576174 :         if (s <= 0)
     329              :         {
     330        10066 :           if (!s) return gc_GEN(av, a);
     331            0 :           pari_err_TYPE("random([a,b]) (a > b)", N);
     332              :         }
     333      3566108 :         if (lgefint(d) == 3)
     334              :         {
     335      3564687 :           ulong z = d[2];
     336      3564687 :           if (z != ~0UL) return gc_INT(av, addiu(a, random_Fl(z + 1)));
     337              :         }
     338         1421 :         return gc_INT(av, addii(a, randomi(addiu(d,1))));
     339              :       }
     340       246005 :       return ellrandom(N);
     341            7 :     default:
     342            7 :       pari_err_TYPE("genrand",N);
     343              :       return NULL;/*LCOV_EXCL_LINE*/
     344              :   }
     345              : }
        

Generated by: LCOV version 2.0-1