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 - map.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31042-0fbe168e69) Lines: 99.2 % 242 240
Test Date: 2026-07-23 17:04:59 Functions: 100.0 % 30 30
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copyright (C) 2015  The PARI group.
       2              : 
       3              : This file is part of the PARI 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              : #include "pari.h"
      16              : #include "paripriv.h"
      17              : 
      18              : #define tvalue(i)  gmael(t,(i),1)
      19              : #define tleft(i)   mael3(t,(i),2,1)
      20              : #define tright(i)  mael3(t,(i),2,2)
      21              : #define theight(i) mael3(t,(i),2,3)
      22              : 
      23              : static GEN
      24         2583 : treesearch(GEN T, GEN x)
      25              : {
      26         2583 :   long i = 1;
      27         2583 :   GEN t = list_data(T);
      28         2583 :   if (!t || lg(t)==1) return NULL;
      29        23002 :   while (i)
      30              :   {
      31        21161 :     long c = cmp_universal(x, gel(tvalue(i),1));
      32        21161 :     if (!c) return tvalue(i);
      33        20433 :     i = c < 0 ? tleft(i): tright(i);
      34              :   }
      35         1841 :   return NULL;
      36              : }
      37              : 
      38              : static long
      39       204078 : treeparent_r(GEN t, GEN x, long i, long parent)
      40              : {
      41              :   long c;
      42       204078 :   if (i==0) return parent;
      43       204078 :   c = cmp_universal(x, gel(tvalue(i),1));
      44       204078 :   if (c < 0)
      45        89950 :     return treeparent_r(t,x,tleft(i),i);
      46       114128 :   else if (c > 0)
      47        93695 :     return treeparent_r(t,x,tright(i),i);
      48              :   else
      49        20433 :     return parent;
      50              : }
      51              : 
      52              : static void
      53          133 : treekeys(GEN t, long i, GEN V, long *n)
      54              : {
      55          133 :   if (i==0) return;
      56           56 :   treekeys(t, tleft(i), V, n);
      57           56 :   gel(V, ++*n) = gel(tvalue(i),1);
      58           56 :   treekeys(t, tright(i), V, n);
      59              : }
      60              : 
      61              : GEN
      62           21 : mapdomain_shallow(GEN T)
      63              : {
      64           21 :   GEN V, t = list_data(T);
      65           21 :   long n = 0;
      66           21 :   if (!t || lg(t)==1) return cgetg(1, t_VEC);
      67           21 :   V = cgetg(lg(t), t_VEC); treekeys(t, 1, V, &n); return V;
      68              : }
      69              : 
      70              : static void
      71           49 : treeselect(void *E, long (*f)(void* E, GEN x), GEN t, long i, GEN V, long *n)
      72              : {
      73           49 :   if (i==0) return;
      74           21 :   treeselect(E, f, t, tleft(i), V, n);
      75           21 :   if (f(E, gel(tvalue(i),2))) gel(V, ++*n) = gel(tvalue(i),1);
      76           21 :   treeselect(E, f, t, tright(i), V, n);
      77              : }
      78              : 
      79              : GEN
      80            7 : mapselect_shallow(void *E, long (*f)(void* E, GEN x), GEN T)
      81              : {
      82            7 :   GEN V, t = list_data(T);
      83            7 :   long n = 0;
      84            7 :   if (!t || lg(t)==1) return cgetg(1, t_VEC);
      85            7 :   clone_lock(T);
      86            7 :   V = cgetg(lg(t), t_COL); treeselect(E, f, t, 1, V, &n);
      87            7 :   clone_unlock_deep(T); fixlg(V, n+1); return V;
      88              : }
      89              : 
      90              : static void
      91        13118 : treemat(GEN t, long i, GEN V, long *n)
      92              : {
      93        13118 :   if (i==0) return;
      94         6202 :   treemat(t, tleft(i), V, n);
      95         6202 :   ++*n;
      96         6202 :   gmael(V, 1, *n) = gel(tvalue(i), 1);
      97         6202 :   gmael(V, 2, *n) = gel(tvalue(i), 2);
      98         6202 :   treemat(t, tright(i), V, n);
      99              : }
     100              : 
     101              : GEN
     102          721 : maptomat_shallow(GEN T)
     103              : {
     104          721 :   GEN V, t = list_data(T);
     105          721 :   long n = 0;
     106          721 :   if (!t || lg(t)==1) return cgetg(1, t_MAT);
     107          714 :   V = cgetg(3, t_MAT);
     108          714 :   gel(V,1) = cgetg(lg(t), t_COL);
     109          714 :   gel(V,2) = cgetg(lg(t), t_COL);
     110          714 :   treemat(t, 1, V, &n); return V;
     111              : }
     112              : 
     113              : static void
     114          602 : treemap_i_r(GEN t, long i, long a, long c, GEN p, GEN M)
     115              : {
     116          602 :   long b = (a+c)>>1;
     117          602 :   GEN x = mkvec2(gcopy(gmael(M, 1, p[b])), gcopy(gmael(M, 2, p[b])));
     118          602 :   if (a == c)
     119          280 :     gel(t, i) = mkvec2(x, mkvecsmall3(0, 0, 1));
     120          322 :   else if (a+1 == c)
     121              :   {
     122          161 :     treemap_i_r(t, i+1, a+1, c, p, M);
     123          161 :     gel(t, i) = mkvec2(x, mkvecsmall3(0, i+1, theight(i+1) + 1));
     124              :   }
     125              :   else
     126              :   {
     127          161 :     long l = i+1, r = l + b - a, h;
     128          161 :     treemap_i_r(t, l, a, b-1, p, M);
     129          161 :     treemap_i_r(t, r, b+1, c, p, M);
     130          161 :     h = maxss(theight(l), theight(r))+1;
     131          161 :     gel(t, i) = mkvec2(x, mkvecsmall3(l, r, h));
     132              :   }
     133          602 : }
     134              : 
     135              : static void
     136          119 : treemap_i(GEN t, GEN p, GEN M) { treemap_i_r(t, 1, 1, lg(p)-1, p, M); }
     137              : 
     138              : #define value(i)  gmael(list_data(T),(i),1)
     139              : #define left(i)   mael3(list_data(T),(i),2,1)
     140              : #define right(i)  mael3(list_data(T),(i),2,2)
     141              : #define height(i) mael3(list_data(T),(i),2,3)
     142              : 
     143              : static long
     144      3060022 : treeheight(GEN T, long i) { return i? height(i): 0; }
     145              : 
     146              : static void
     147          154 : change_leaf(GEN T, GEN x, long p)
     148              : {
     149          154 :   pari_sp av = avma;
     150          154 :   listput(T, mkvec2(x, gmael(list_data(T), p, 2)), p);
     151          154 :   set_avma(av);
     152          154 : }
     153              : 
     154              : static long
     155        51030 : new_leaf(GEN T, GEN x)
     156              : {
     157        51030 :   pari_sp av = avma;
     158        51030 :   listput(T, mkvec2(x, mkvecsmall3(0,0,1)), 0);
     159        51030 :   return gc_long(av, lg(list_data(T))-1);
     160              : }
     161              : 
     162              : static void
     163       803894 : fix_height(GEN T, long x)
     164       803894 : { height(x) = maxss(treeheight(T,left(x)), treeheight(T,right(x)))+1; }
     165              : static long
     166       726117 : treebalance(GEN T, long i)
     167       726117 : { return i ? treeheight(T,left(i)) - treeheight(T,right(i)): 0; }
     168              : 
     169              : static long
     170        21497 : rotright(GEN T, long y)
     171              : {
     172        21497 :   long x = left(y), t = right(x);
     173        21497 :   right(x) = y;
     174        21497 :   left(y)  = t;
     175        21497 :   fix_height(T, y);
     176        21497 :   fix_height(T, x);
     177        21497 :   return x;
     178              : }
     179              : 
     180              : static long
     181        21679 : rotleft(GEN T, long x)
     182              : {
     183        21679 :   long y = right(x), t = left(y);
     184        21679 :   left(y)  = x;
     185        21679 :   right(x) = t;
     186        21679 :   fix_height(T, x);
     187        21679 :   fix_height(T, y);
     188        21679 :   return y;
     189              : }
     190              : 
     191              : static long
     192       567182 : treeinsert_r(GEN T, GEN x, long i, long *d)
     193              : {
     194              :   long b, c;
     195       567182 :   if (i==0 || !list_data(T) || lg(list_data(T))==1) return new_leaf(T, x);
     196       516152 :   c = cmp_universal(gel(x,1), gel(value(i),1));
     197       516152 :   if (c < 0)
     198              :   {
     199       256508 :     long s = treeinsert_r(T, x, left(i), d);
     200       256508 :     if (s < 0) return s;
     201       256445 :     left(i) = s;
     202              :   }
     203       259644 :   else if (c > 0)
     204              :   {
     205       259490 :     long s = treeinsert_r(T, x, right(i), d);
     206       259490 :     if (s < 0) return s;
     207       259385 :     right(i) = s;
     208              :   }
     209          154 :   else return -i;
     210       515830 :   fix_height(T, i);
     211       515830 :   b = treebalance(T, i);
     212       515830 :   if (b > 1)
     213              :   {
     214        11473 :     if (*d > 0) left(i) = rotleft(T, left(i));
     215        11473 :     return rotright(T, i);
     216              :   }
     217       504357 :   if (b < -1)
     218              :   {
     219        11753 :     if (*d < 0) right(i) = rotright(T, right(i));
     220        11753 :     return rotleft(T, i);
     221              :   }
     222       492604 :   *d = c; return i;
     223              : }
     224              : 
     225              : static long
     226        51184 : treeinsert(GEN T, GEN x)
     227              : {
     228        51184 :   long c = 0, r = treeinsert_r(T, x, 1, &c);
     229              :   GEN d;
     230        51184 :   if (r < 0) return -r;
     231        51030 :   if (r == 1) return 0;
     232          126 :   d = list_data(T);
     233              :   /* By convention we want the root to be 1 */
     234          126 :   swap(gel(d,1), gel(d,r));
     235          126 :   if (left(1) == 1) left(1) = r;
     236           28 :   else if (right(1) == 1) right(1) = r;
     237            0 :   else pari_err_BUG("treeadd");
     238          126 :   return 0;
     239              : }
     240              : 
     241              : static long
     242       223608 : treedelete_r(GEN T, GEN x, long i, long *dead)
     243              : {
     244              :   long b, c;
     245       223608 :   if (i==0 || !list_data(T) || lg(list_data(T))==1) return -1;
     246       223601 :   c = cmp_universal(x, gel(value(i),1));
     247       223601 :   if (c < 0)
     248              :   {
     249       101038 :     long s = treedelete_r(T, x, left(i), dead);
     250       101038 :     if (s < 0) return s;
     251       101038 :     left(i) = s;
     252              :   }
     253       122563 :   else if (c > 0)
     254              :   {
     255        89194 :     long s = treedelete_r(T, x, right(i), dead);
     256        89194 :     if (s < 0) return s;
     257        89180 :     right(i) = s;
     258              :   }
     259              :   else
     260              :   {
     261        33369 :     *dead = i;
     262        33369 :     if (left(i)==0 && right(i)==0) return 0;
     263        17115 :     else if (left(i)==0) return right(i);
     264        12803 :     else if (right(i)==0) return left(i);
     265              :     else
     266              :     {
     267        11494 :       GEN v, d = list_data(T);
     268        11494 :       long j = right(i);
     269        28028 :       while (left(j)) j = left(j);
     270        11494 :       v = gel(value(j), 1);
     271        11494 :       right(i) = treedelete_r(T, v, right(i), dead);
     272        11494 :       swap(gel(d,i), gel(d,j));
     273        11494 :       lswap(left(i),left(j));
     274        11494 :       lswap(right(i),right(j));
     275        11494 :       lswap(height(i),height(j));
     276              :     }
     277              :   }
     278       201712 :   fix_height(T, i);
     279       201712 :   b = treebalance(T, i);
     280       201712 :   if (b > 1 && treebalance(T, left(i)) >= 0) return rotright(T, i);
     281       200109 :   if (b > 1 && treebalance(T, left(i)) < 0)
     282         1295 :   { left(i) = rotleft(T, left(i)); return rotright(T, i); }
     283       198814 :   if (b < -1 && treebalance(T, right(i)) <= 0) return rotleft(T,i);
     284       196938 :   if (b < -1 && treebalance(T, right(i)) > 0)
     285         1253 :   { right(i) = rotright(T, right(i)); return rotleft(T, i); }
     286       195685 :   return i;
     287              : }
     288              : 
     289              : static long
     290        21882 : treedelete(GEN T, GEN x)
     291              : {
     292        21882 :   long dead, l, r = treedelete_r(T, x, 1, &dead);
     293              :   GEN d;
     294        21882 :   if (r < 0) return 0;
     295        21875 :   d = list_data(T); /* != NULL and nonempty */
     296        21875 :   if (r > 1)
     297              :   { /* By convention we want the root to be 1 */
     298           14 :     swap(gel(d,1), gel(d,r));
     299           14 :     if (left(1) == 1) left(1) = r;
     300           14 :     else if (right(1) == 1) right(1) = r;
     301            7 :     else dead = r;
     302              :   }
     303              :   /* We want the dead to be last */
     304        21875 :   l = lg(d)-1;
     305        21875 :   if (dead != l)
     306              :   {
     307        20433 :     long p = treeparent_r(d, gel(value(l),1), 1, 0);
     308        20433 :     if (left(p) == l) left(p) = dead;
     309        10311 :     else if (right(p) == l) right(p) = dead;
     310            0 :     else pari_err_BUG("treedelete2");
     311        20433 :     swap(gel(d, dead),gel(d, l));
     312              :   }
     313        21875 :   listpop(T,0); return 1;
     314              : }
     315              : 
     316              : static int
     317        75712 : ismap(GEN T) { return typ(T) == t_LIST && list_typ(T) == t_LIST_MAP; }
     318              : 
     319              : void
     320        51184 : mapput(GEN T, GEN a, GEN b)
     321              : {
     322        51184 :   pari_sp av = avma;
     323        51184 :   GEN p = mkvec2(a, b);
     324              :   long i;
     325        51184 :   if (!ismap(T)) pari_err_TYPE("mapput",T);
     326        51184 :   i = treeinsert(T, p); if (i) change_leaf(T, p, i);
     327        51184 :   set_avma(av);
     328        51184 : }
     329              : 
     330              : void
     331        21889 : mapdelete(GEN T, GEN a)
     332              : {
     333        21889 :   pari_sp av = avma;
     334              :   long s;
     335        21889 :   if (!ismap(T)) pari_err_TYPE("mapdelete",T);
     336        21882 :   s = treedelete(T, a); set_avma(av);
     337        21882 :   if (!s) pari_err_COMPONENT("mapdelete", "not in", strtoGENstr("map"), a);
     338        21875 : }
     339              : 
     340              : GEN
     341          581 : mapget(GEN T, GEN a)
     342              : {
     343              :   GEN x;
     344          581 :   if (!ismap(T)) pari_err_TYPE("mapget",T);
     345          567 :   x = treesearch(T, a);
     346          567 :   if (!x) pari_err_COMPONENT("mapget", "not in", strtoGENstr("map"), a);
     347          560 :   return gcopy(gel(x, 2));
     348              : }
     349              : 
     350              : GEN
     351           42 : mapapply(GEN T, GEN a, GEN f, GEN u)
     352              : {
     353              :   GEN x;
     354           42 :   if (!ismap(T)) pari_err_TYPE("mapapply",T);
     355           42 :   x = treesearch(T, a);
     356           42 :   if (!x)
     357              :   {
     358           14 :     if (!u) pari_err_COMPONENT("mapapply", "not in", strtoGENstr("map"), a);
     359            7 :     x = closure_callgen0(u);
     360            7 :     mapput(T, a, x);
     361            7 :     return x;
     362              :   }
     363           28 :   return closure_callgen1(f, gel(x,2));
     364              : }
     365              : 
     366              : int
     367         1988 : mapisdefined(GEN T, GEN a, GEN *pt_z)
     368              : {
     369              :   GEN x;
     370         1988 :   if (!ismap(T)) pari_err_TYPE("mapisdefined",T);
     371         1974 :   x = treesearch(T, a); if (!x) return 0;
     372          140 :   if (pt_z) *pt_z = gcopy(gel(x, 2));
     373          140 :   return 1;
     374              : }
     375              : 
     376              : GEN
     377           14 : mapdomain(GEN T)
     378              : {
     379              :   long i, l;
     380              :   GEN V;
     381           14 :   if (!ismap(T)) pari_err_TYPE("mapdomain",T);
     382           14 :   V = mapdomain_shallow(T); l = lg(V);
     383           56 :   for (i = 1; i < l; i++) gel(V,i) = gcopy(gel(V,i));
     384           14 :   return V;
     385              : }
     386              : 
     387              : GEN
     388           14 : maptomat(GEN T)
     389              : {
     390              :   long i, l;
     391              :   GEN V;
     392           14 :   if (!ismap(T)) pari_err_TYPE("maptomat",T);
     393           14 :   V = maptomat_shallow(T); if (lg(V) == 1) return V;
     394           14 :   l = lgcols(V);
     395           77 :   for (i = 1; i < l; i++)
     396              :   {
     397           63 :     gcoeff(V,i,1) = gcopy(gcoeff(V,i,1));
     398           63 :     gcoeff(V,i,2) = gcopy(gcoeff(V,i,2));
     399              :   }
     400           14 :   return V;
     401              : }
     402              : 
     403              : GEN
     404          182 : gtomap(GEN x)
     405              : {
     406          182 :   if (!x) return mkmap();
     407          133 :   switch(typ(x))
     408              :   {
     409          126 :   case t_MAT:
     410              :     {
     411          126 :       long l = lg(x);
     412              :       GEN M, p;
     413          126 :       if (l == 1 || lgcols(x)==1) return mkmap();
     414          126 :       if (l != 3) pari_err_TYPE("Map",x);
     415          126 :       p = gen_indexsort_uniq(gel(x,1),(void*)&cmp_universal, cmp_nodata);
     416          126 :       l = lgcols(x);
     417          126 :       if (lg(p) != l)
     418            7 :         pari_err_DOMAIN("Map","x","is not",strtoGENstr("one-to-one"),x);
     419          119 :       M = cgetg(3, t_LIST);
     420          119 :       M[1] = evaltyp(t_LIST_MAP); /* do not set list_nmax! */
     421          119 :       list_data(M) = cgetg(l, t_VEC);
     422          119 :       treemap_i(list_data(M), p, x);
     423          119 :       return M;
     424              :     }
     425            7 :   default:
     426            7 :     pari_err_TYPE("Map",x);
     427              :   }
     428              :   return NULL; /* LCOV_EXCL_LINE */
     429              : }
        

Generated by: LCOV version 2.0-1