Code coverage tests

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

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

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

LCOV - code coverage report
Current view: top level - kernel/none - halfgcd.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.19.0 lcov report (development 31080-f9bc4fce97) Lines: 98.2 % 219 215
Test Date: 2026-07-30 17:02:59 Functions: 100.0 % 20 20
Legend: Lines:     hit not hit

            Line data    Source code
       1              : #line 2 "../src/kernel/none/halfgcd.c"
       2              : /* Copyright (C) 2019  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; either version 2 of the License, or (at your option) any later
       9              : version. It is distributed in the hope that it will be useful, but WITHOUT
      10              : ANY WARRANTY WHATSOEVER.
      11              : 
      12              : Check the License for details. You should have received a copy of it, along
      13              : with the package; see the file 'COPYING'. If not, write to the Free Software
      14              : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      15              : 
      16              : GEN
      17         2338 : ZM2_sqr(GEN A)
      18              : {
      19         2338 :   GEN a = gcoeff(A,1,1), b = gcoeff(A,1,2), a2 = sqri(a);
      20         2338 :   GEN c = gcoeff(A,2,1), d = gcoeff(A,2,2), d2 = sqri(d), t = addii(a,d);
      21         2338 :   if (equalii(b, c)) /* symetric, 3S + 1M */
      22              :   {
      23          322 :     GEN b2 = sqri(b), M = cgetg(3, t_MAT), tb = mulii(b, t);
      24          322 :     gel(M,1) = mkcol2(addii(a2, b2), tb);
      25          322 :     gel(M,2) = mkcol2(tb, addii(b2, d2)); return M;
      26              :   }
      27              :   else
      28              :   { /* general, 2S + 3M */
      29         2016 :     GEN bc = mulii(b, c);
      30         2016 :     retmkmat2(mkcol2(addii(bc, a2), mulii(c, t)),
      31              :               mkcol2(mulii(b, t), addii(bc, d2)));
      32              :   }
      33              : }
      34              : 
      35              : GEN
      36      7531339 : ZM2_mul(GEN A, GEN B)
      37              : {
      38      7531339 :   const long t = ZM2_MUL_LIMIT+2;
      39      7531339 :   GEN A11=gcoeff(A,1,1),A12=gcoeff(A,1,2), B11=gcoeff(B,1,1),B12=gcoeff(B,1,2);
      40      7531339 :   GEN A21=gcoeff(A,2,1),A22=gcoeff(A,2,2), B21=gcoeff(B,2,1),B22=gcoeff(B,2,2);
      41      7531339 :   if (lgefint(A11) < t || lgefint(B11) < t || lgefint(A22) < t || lgefint(B22) < t
      42       134653 :    || lgefint(A12) < t || lgefint(B12) < t || lgefint(A21) < t || lgefint(B21) < t)
      43              :   { /* 8M */
      44      7399364 :     GEN a = mulii(A11, B11), b = mulii(A12, B21);
      45      7399364 :     GEN c = mulii(A11, B12), d = mulii(A12, B22);
      46      7399364 :     GEN e = mulii(A21, B11), f = mulii(A22, B21);
      47      7399364 :     GEN g = mulii(A21, B12), h = mulii(A22, B22);
      48      7399364 :     retmkmat2(mkcol2(addii(a,b), addii(e,f)), mkcol2(addii(c,d), addii(g,h)));
      49              :   } else
      50              :   { /* Strassen: 7M */
      51       131975 :     GEN M1 = mulii(addii(A11,A22), addii(B11,B22));
      52       131975 :     GEN M2 = mulii(addii(A21,A22), B11);
      53       131975 :     GEN M3 = mulii(A11, subii(B12,B22));
      54       131975 :     GEN M4 = mulii(A22, subii(B21,B11));
      55       131975 :     GEN M5 = mulii(addii(A11,A12), B22);
      56       131975 :     GEN M6 = mulii(subii(A21,A11), addii(B11,B12));
      57       131975 :     GEN M7 = mulii(subii(A12,A22), addii(B21,B22));
      58       131975 :     GEN T1 = addii(M1,M4), T2 = subii(M7,M5);
      59       131975 :     GEN T3 = subii(M1,M2), T4 = addii(M3,M6);
      60       131975 :     retmkmat2(mkcol2(addii(T1,T2), addii(M2,M4)),
      61              :               mkcol2(addii(M3,M5), addii(T3,T4)));
      62              :   }
      63              : }
      64              : 
      65              : static GEN
      66          960 : matid2(void)
      67              : {
      68          960 :     retmkmat2(mkcol2(gen_1,gen_0),
      69              :               mkcol2(gen_0,gen_1));
      70              : }
      71              : 
      72              : /* Return M*[q,1;1,0] */
      73              : static GEN
      74      4846415 : mulq(GEN M, GEN q)
      75              : {
      76      4846415 :   GEN u, v, res = cgetg(3, t_MAT);
      77      4846415 :   u = addii(mulii(gcoeff(M,1,1), q), gcoeff(M,1,2));
      78      4846415 :   v = addii(mulii(gcoeff(M,2,1), q), gcoeff(M,2,2));
      79      4846415 :   gel(res,1) = mkcol2(u, v);
      80      4846415 :   gel(res,2) = gel(M,1);
      81      4846415 :   return res;
      82              : }
      83              : static GEN
      84           80 : mulqab(GEN M, GEN q, GEN *ap, GEN *bp)
      85              : {
      86           80 :   GEN b = subii(*ap, mulii(*bp, q));
      87           80 :   *ap = *bp; *bp = b;
      88           80 :   return mulq(M,q);
      89              : }
      90              : 
      91              : /* Return M*[q,1;1,0]^-1 */
      92              : 
      93              : static GEN
      94         1461 : mulqi(GEN M, GEN q, GEN *ap, GEN *bp)
      95              : {
      96              :   GEN u, v, res, a;
      97         1461 :   a = addii(mulii(*ap, q), *bp);
      98         1461 :   *bp = *ap; *ap = a;
      99         1461 :   res = cgetg(3, t_MAT);
     100         1461 :   u = subii(gcoeff(M,1,1),mulii(gcoeff(M,1,2), q));
     101         1461 :   v = subii(gcoeff(M,2,1),mulii(gcoeff(M,2,2), q));
     102         1461 :   gel(res,1) = gel(M,2);
     103         1461 :   gel(res,2) = mkcol2(u,v);
     104         1461 :   return res;
     105              : }
     106              : 
     107              : /* test whether n is a power of 2 */
     108              : static long
     109     25662581 : isint2n(GEN n)
     110              : {
     111     25662581 :   long lx = lgefint(n), i;
     112              :   ulong a;
     113              :   GEN x;
     114     25662581 :   if (lx == 2) return 0;
     115     25662581 :   x = int_MSW(n);
     116     25662581 :   a = (ulong)*x; if (a & (a - 1)) return 0;
     117       588294 :   for (i = 3; i < lx; i++)
     118              :   {
     119       580913 :     x = int_precW(x); if (*x) return 0;
     120              :   }
     121         7381 :   return 1;
     122              : }
     123              : 
     124              : static long
     125     25662581 : uexpi(GEN a)
     126     25662581 : { return expi(a)+!isint2n(a); }
     127              : 
     128              : static GEN
     129       135669 : FIXUP0(GEN M, GEN *a, GEN *b, long m)
     130              : {
     131       135669 :   long cnt=0;
     132       172402 :   while (expi(*b) >= m)
     133              :   {
     134        36733 :     GEN r, q = dvmdii(*a, *b, &r);
     135        36733 :     *a = *b; *b = r;
     136        36733 :     M = mulq(M, q);
     137        36733 :     cnt++;
     138              :   };
     139       135669 :   if (cnt>6) pari_err_BUG("FIXUP0");
     140       135669 :   return M;
     141              : }
     142              : 
     143              : static long
     144      7625886 : signdet(GEN Q)
     145              : {
     146      7625886 :   long a = Mod4(gcoeff(Q,1,1)), b = Mod4(gcoeff(Q,1,2));
     147      7625886 :   long c = Mod4(gcoeff(Q,2,1)), d = Mod4(gcoeff(Q,2,2));
     148      7625886 :   return ((a*d-b*c)&3)==1 ? 1 : -1;
     149              : }
     150              : 
     151              : static GEN
     152      7428755 : ZM_inv2(GEN M)
     153              : {
     154      7428755 :   long e = signdet(M);
     155     11574811 :   if (e==1) return mkmat22(gcoeff(M,2,2),negi(gcoeff(M,1,2)),
     156      4146056 :                           negi(gcoeff(M,2,1)),gcoeff(M,1,1));
     157      3282699 :   else      return mkmat22(negi(gcoeff(M,2,2)),gcoeff(M,1,2),
     158      3282699 :                            gcoeff(M,2,1),negi(gcoeff(M,1,1)));
     159              : }
     160              : 
     161              : static GEN
     162         1461 : lastq(GEN Q)
     163              : {
     164         1461 :   GEN p = gcoeff(Q,1,1), q = gcoeff(Q,1,2), s = gcoeff(Q,2,2);
     165         1461 :   if (signe(q)==0) pari_err_BUG("halfgcd");
     166         1461 :   if (signe(s)==0) return p;
     167         1461 :   if (equali1(q))  return subiu(p,1);
     168         1461 :   return divii(p, q);
     169              : }
     170              : 
     171              : static GEN
     172         8231 : mulT(GEN Q, GEN *ap, GEN *bp)
     173              : {
     174         8231 :   *ap = addii(*ap, *bp);
     175         8231 :   *bp = negi(*bp);
     176         8231 :   return mkmat2(gel(Q,1),
     177         8231 :            mkcol2(subii(gcoeff(Q,1,1), gcoeff(Q,1,2)),
     178         8231 :                   subii(gcoeff(Q,2,1), gcoeff(Q,2,2))));
     179              : }
     180              : 
     181              : static GEN
     182       197131 : FIXUP1(GEN M, GEN a, GEN b, long m, long t, GEN *ap, GEN *bp)
     183              : {
     184       197131 :   GEN Q = gel(M,1), a0 = gel(M,2), b0 = gel(M,3);
     185       197131 :   GEN q, am = remi2n(a, m), bm = remi2n(b, m);
     186       197131 :   if (signdet(Q)==-1)
     187              :   {
     188       129019 :     *ap = subii(mulii(bm, gcoeff(Q,1,2)),mulii(am, gcoeff(Q,2,2)));
     189       129019 :     *bp = subii(mulii(am, gcoeff(Q,2,1)),mulii(bm, gcoeff(Q,1,1)));
     190       129019 :     *ap = addii(*ap, shifti(addii(a0, gcoeff(Q,2,2)), m));
     191       129019 :     *bp = addii(*bp, shifti(subii(b0, gcoeff(Q,2,1)), m));
     192       129019 :     if (signe(*bp) >= 0)
     193       120696 :       return Q;
     194         8323 :     if (expi(addii(*ap,*bp)) >= m+t)
     195         8231 :       return mulT(Q, ap, bp);
     196           92 :     q = lastq(Q);
     197           92 :     Q = mulqi(Q, q, ap, bp);
     198           92 :     if (cmpiu(q, 2)>=0)
     199           80 :       return mulqab(Q, subiu(q,1), ap, bp);
     200              :     else
     201           12 :       return mulqi(Q, lastq(Q), ap, bp);
     202              :   }
     203              :   else
     204              :   {
     205        68112 :     *ap = subii(mulii(am, gcoeff(Q,2,2)),mulii(bm, gcoeff(Q,1,2)));
     206        68112 :     *bp = subii(mulii(bm, gcoeff(Q,1,1)),mulii(am, gcoeff(Q,2,1)));
     207        68112 :     *ap = addii(*ap, shifti(subii(a0, gcoeff(Q,2,2)), m));
     208        68112 :     *bp = addii(*bp, shifti(addii(b0, gcoeff(Q,2,1)), m));
     209        68112 :     if (expi(*ap) >= m+t)
     210        66755 :       return FIXUP0(Q, ap, bp, m+t);
     211              :     else
     212         1357 :       return signe(gcoeff(Q,1,2))==0? Q: mulqi(Q, lastq(Q), ap, bp);
     213              :   }
     214              : }
     215              : 
     216              : static long
     217     25593688 : magic_threshold(GEN a)
     218     25593688 : { return (3+uexpi(a))>>1; }
     219              : 
     220              : static GEN
     221     16867752 : HGCD_basecase(GEN y, GEN x)
     222              : {
     223     16867752 :   pari_sp av = avma;
     224              :   GEN d, d1, q, r;
     225              :   GEN u, u1, v, v1;
     226              :   ulong xu, xu1, xv, xv1; /* Lehmer stage recurrence matrix */
     227              :   int lhmres;             /* Lehmer stage return value */
     228              : 
     229     16867752 :   long m = magic_threshold(y);
     230              : 
     231              :   /* There is no special case for single-word numbers since this is
     232              :    * mainly meant to be used with large moduli. */
     233     16867752 :   if (cmpii(y,x) <= 0)
     234              :   {
     235       107070 :     d = x; d1 = y;
     236       107070 :     u = gen_1; u1 = gen_0;
     237       107070 :     v = gen_0; v1 = gen_1;
     238              :   } else
     239              :   {
     240     16760682 :     d = y; d1 = x;
     241     16760682 :     u = gen_0; u1 = gen_1;
     242     16760682 :     v = gen_1; v1 = gen_0;
     243              :   }
     244     36879060 :   while (lgefint(d) > 3 &&  expi(d1) >= m + BITS_IN_LONG + 1)
     245              :   {
     246              :     /* do a Lehmer-Jebelean round */
     247     20343912 :     lhmres = lgcdii((ulong *)d, (ulong *)d1, &xu, &xu1, &xv, &xv1, 0);
     248              : 
     249     20343912 :     if (lhmres)
     250              :     {
     251     19277224 :       if (lhmres == 1 || lhmres == -1)
     252              :       {
     253       462233 :         if (xv1 == 1)
     254              :         {
     255       395738 :           r = subii(d,d1); d = d1; d1 = r;
     256       395738 :           r = addii(u,u1); u = u1; u1 = r;
     257       395738 :           r = addii(v,v1); v = v1; v1 = r;
     258              :         }
     259              :         else
     260              :         {
     261        66495 :           r = subii(d, mului(xv1,d1)); d = d1; d1 = r;
     262        66495 :           r = addii(u, mului(xv1,u1)); u = u1; u1 = r;
     263        66495 :           r = addii(v, mului(xv1,v1)); v = v1; v1 = r;
     264              :         }
     265              :       }
     266              :       else
     267              :       {
     268     18814991 :         r  = subii(muliu(d,xu),  muliu(d1,xv));
     269     18814991 :         d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r;
     270     18814991 :         r  = addii(muliu(u,xu),  muliu(u1,xv));
     271     18814991 :         u1 = addii(muliu(u,xu1), muliu(u1,xv1)); u = r;
     272     18814991 :         r  = addii(muliu(v,xu),  muliu(v1,xv));
     273     18814991 :         v1 = addii(muliu(v,xu1), muliu(v1,xv1)); v = r;
     274     18814991 :         if (lhmres&1) togglesign(d); else togglesign(d1);
     275              :       }
     276              :     } /* lhmres != 0 */
     277     20343912 :     if (expi(d1) < m) break;
     278              : 
     279     20011308 :     if (lhmres <= 0 && signe(d1))
     280              :     {
     281      1121162 :       q = dvmdii(d,d1,&r);
     282      1121162 :       d = d1; d1 = r;
     283      1121162 :       r = addii(u, mulii(q,u1)); u = u1; u1 = r;
     284      1121162 :       r = addii(v, mulii(q,v1)); v = v1; v1 = r;
     285              :     }
     286     20011308 :     if (gc_needed(av,1))
     287              :     {
     288            0 :       if(DEBUGMEM>1) pari_warn(warnmem,"ratlift");
     289            0 :       (void)gc_all(av, 6, &d, &d1, &u, &u1, &v, &v1);
     290              :     }
     291              :   }
     292     93781621 :   while (expi(d1) >= m)
     293              :   {
     294     76913869 :     GEN r, q = dvmdii(d,d1, &r);
     295     76913869 :     d = d1; d1 = r; swap(u,u1); swap(v,v1);
     296     76913869 :     u1 = addii(mulii(u, q), u1);
     297     76913869 :     v1 = addii(mulii(v, q), v1);
     298              :   }
     299     16867752 :   return gc_GEN(av, mkvec3(mkmat22(u1,u,v1,v), d, d1));
     300              : }
     301              : 
     302              : static GEN HGCD(GEN x, GEN y);
     303              : 
     304              : /*
     305              : Based on
     306              : Klaus Thull and Chee K. Yap,
     307              : A unified approach to HGCD algorithms for polynomials andintegers,
     308              : 1990, Manuscript.
     309              : URL: http://cs.nyu.edu/cs/faculty/yap/papers.
     310              : */
     311              : 
     312              : static GEN
     313       128790 : HGCD_split(GEN a, GEN b)
     314              : {
     315       128790 :   pari_sp av = avma;
     316       128790 :   long m = magic_threshold(a), t, l, k, tp;
     317              :   GEN a0, b0, ap, bp, c, d, c0, d0, cp, dp, R, S, T, q, r;
     318       128790 :   if (signe(b) < 0  || cmpii(a,b)<0) pari_err_BUG("HGCD_split");
     319       128790 :   if (expi(b) < m)
     320          552 :     return gc_GEN(av, mkvec3(matid2(), a, b));
     321       128238 :   a0 = addiu(shifti(a, -m), 1);
     322       128238 :   if (cmpiu(a0,7) <= 0)
     323              :   {
     324            0 :     R = FIXUP0(matid2(), &a, &b, m);
     325            0 :     return gc_GEN(av, mkvec3(R, a, b));
     326              :   }
     327       128238 :   b0 = shifti(b,-m);
     328       128238 :   t = magic_threshold(a0);
     329       128238 :   R = FIXUP1(HGCD(a0,b0),a, b, m, t, &ap, &bp);
     330       128238 :   if (expi(bp) < m)
     331        59324 :     return gc_GEN(av, mkvec3(R, ap, bp));
     332        68914 :   q = dvmdii(ap, bp, &r);
     333        68914 :   c = bp; d = r;
     334        68914 :   if (cmpiu(shifti(c,-m),6) <= 0)
     335              :   {
     336           21 :     R = FIXUP0(mulq(R, q), &c, &d, m);
     337           21 :     return gc_GEN(av, mkvec3(R, c, d));
     338              :   }
     339        68893 :   l = uexpi(c);
     340        68893 :   k = 2*m-l-1; if (k<0) pari_err_BUG("halfgcd");
     341        68893 :   c0 = addiu(shifti(c, -k), 1); if (cmpiu(c0,8)<0) pari_err_BUG("halfgcd");
     342        68893 :   d0 = shifti(d, -k);
     343        68893 :   tp = magic_threshold(c0);
     344        68893 :   S = FIXUP1(HGCD(c0,d0), c, d, k, tp, &cp, &dp);
     345        68893 :   if (!(expi(cp)>=m+1 && m+1 > expi(dp))) pari_err_BUG("halfgcd");
     346        68893 :   T = FIXUP0(ZM2_mul(mulq(R, q), S), &cp, &dp, m);
     347        68893 :   return gc_GEN(av, mkvec3(T, cp, dp));
     348              : }
     349              : 
     350              : static GEN
     351     16996542 : HGCD(GEN x, GEN y)
     352              : {
     353     16996542 :   if (lgefint(y)-2 < HALFGCD_LIMIT)
     354     16867752 :     return HGCD_basecase(x, y);
     355              :   else
     356       128790 :     return HGCD_split(x, y);
     357              : }
     358              : 
     359              : static GEN
     360     32144388 : HGCD0(GEN x, GEN y)
     361              : {
     362     32144388 :   if (signe(y) >= 0 && cmpii(x, y) >= 0)
     363     16792957 :     return HGCD(x, y);
     364     15351431 :   if (cmpii(x, y) < 0)
     365              :   {
     366     12651449 :     GEN M = HGCD0(y, x), Q = gel(M,1);
     367     12651449 :     return mkvec3(mkmat22(gcoeff(Q,2,1),gcoeff(Q,2,2),gcoeff(Q,1,1),gcoeff(Q,1,2)),
     368     12651449 :         gel(M,2),gel(M,3));
     369              :   } /* Now y <= x*/
     370      2699982 :   if (signe(x) <= 0)
     371              :   { /* y <= x <=0 */
     372         6454 :     GEN M = HGCD(negi(y), negi(x)), Q = gel(M,1);
     373         6454 :     return mkvec3(mkmat22(negi(gcoeff(Q,2,1)),negi(gcoeff(Q,2,2)),
     374         6454 :                           negi(gcoeff(Q,1,1)),negi(gcoeff(Q,1,2))),
     375         6454 :         gel(M,2),gel(M,3));
     376              :   }
     377              :   else /* y <= 0 <=x */
     378              :   {
     379      2693528 :     GEN M = HGCD0(x, negi(y)), Q = gel(M,1);
     380      2693528 :     return mkvec3(mkmat22(gcoeff(Q,1,1),gcoeff(Q,1,2),negi(gcoeff(Q,2,1)),negi(gcoeff(Q,2,2))),
     381      2693528 :         gel(M,2),gel(M,3));
     382              :   }
     383              : }
     384              : 
     385              : GEN
     386      7428347 : halfgcdii(GEN A, GEN B)
     387              : {
     388      7428347 :   pari_sp av = avma;
     389      7428347 :   GEN M, Q, a, b, m = abscmpii(A, B)>0 ? A: B;
     390      7428347 :   M = HGCD0(A,B); Q = gel(M,1); a = gel(M,2); b = gel(M,3);
     391     12168738 :   while (signe(b) && abscmpii(sqri(b), m) >= 0)
     392              :   {
     393      4740391 :     GEN r, q = dvmdii(a, b, &r);
     394      4740391 :     a = b; b = r;
     395      4740391 :     Q = mulq(Q, q);
     396              :   }
     397      7428347 :   return gc_GEN(av, mkvec2(ZM_inv2(Q),mkcol2(a,b)));
     398              : }
        

Generated by: LCOV version 2.0-1