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 - invmod.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.18.0 lcov report (development 29804-254f602fce) Lines: 51 51 100.0 %
Date: 2024-12-18 09:08:59 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #line 2 "../src/kernel/none/invmod.c"
       2             : /* Copyright (C) 2003  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             : /*==================================
      17             :  * invmod(a,b,res)
      18             :  *==================================
      19             :  *    If a is invertible, return 1, and set res  = a^{ -1 }
      20             :  *    Otherwise, return 0, and set res = gcd(a,b)
      21             :  *
      22             :  * This is sufficiently different from bezout() to be implemented separately
      23             :  * instead of having a bunch of extra conditionals in a single function body
      24             :  * to meet both purposes.
      25             :  */
      26             : 
      27             : #ifdef INVMOD_PARI
      28             : INLINE int
      29    19839995 : invmod_pari(GEN a, GEN b, GEN *res)
      30             : #else
      31             : int
      32    15752160 : invmod(GEN a, GEN b, GEN *res)
      33             : #endif
      34             : {
      35             :   GEN v,v1,d,d1,q,r;
      36             :   pari_sp av, av1;
      37             :   long s;
      38             :   ulong g;
      39             :   ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */
      40             :   int lhmres; /* Lehmer stage return value */
      41             : 
      42    35592155 :   if (!signe(b)) { *res=absi(a); return 0; }
      43    35592155 :   av = avma;
      44    35592155 :   if (lgefint(b) == 3) /* single-word affair */
      45             :   {
      46    30154567 :     ulong d1 = umodiu(a, uel(b,2));
      47    30155285 :     if (d1 == 0)
      48             :     {
      49         349 :       if (b[2] == 1L)
      50         299 :         { *res = gen_0; return 1; }
      51             :       else
      52          50 :         { *res = absi(b); return 0; }
      53             :     }
      54    30154936 :     g = xgcduu(uel(b,2), d1, 1, &xv, &xv1, &s);
      55    30157130 :     set_avma(av);
      56    30156882 :     if (g != 1UL) { *res = utoipos(g); return 0; }
      57    30156862 :     xv = xv1 % uel(b,2); if (s < 0) xv = uel(b,2) - xv;
      58    30156862 :     *res = utoipos(xv); return 1;
      59             :   }
      60             : 
      61     5437588 :   (void)new_chunk(lgefint(b));
      62     5437688 :   d = absi_shallow(b); d1 = modii(a,d);
      63             : 
      64     5437684 :   v=gen_0; v1=gen_1;        /* general case */
      65     5437684 :   av1 = avma;
      66             : 
      67    14258400 :   while (lgefint(d) > 3 && signe(d1))
      68             :   {
      69     8820716 :     lhmres = lgcdii((ulong*)d, (ulong*)d1, &xu, &xu1, &xv, &xv1, ULONG_MAX);
      70     8820721 :     if (lhmres != 0)                /* check progress */
      71             :     {                                /* apply matrix */
      72     7863792 :       if (lhmres == 1 || lhmres == -1)
      73             :       {
      74      174295 :         if (xv1 == 1)
      75             :         {
      76      158115 :           r = subii(d,d1); d=d1; d1=r;
      77      158115 :           a = subii(v,v1); v=v1; v1=a;
      78             :         }
      79             :         else
      80             :         {
      81       16180 :           r = subii(d, mului(xv1,d1)); d=d1; d1=r;
      82       16180 :           a = subii(v, mului(xv1,v1)); v=v1; v1=a;
      83             :         }
      84             :       }
      85             :       else
      86             :       {
      87     7689497 :         r  = subii(muliu(d,xu),  muliu(d1,xv));
      88     7689494 :         a  = subii(muliu(v,xu),  muliu(v1,xv));
      89     7689496 :         d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r;
      90     7689496 :         v1 = subii(muliu(v,xu1), muliu(v1,xv1)); v = a;
      91     7689496 :         if (lhmres&1) { togglesign(d);  togglesign(v); }
      92     3988778 :         else          { togglesign(d1); togglesign(v1); }
      93             :       }
      94             :     }
      95             : 
      96     8820720 :     if (lhmres <= 0 && signe(d1))
      97             :     {
      98     1156374 :       q = dvmdii(d,d1,&r);
      99     1156374 :       a = subii(v,mulii(q,v1));
     100     1156373 :       v=v1; v1=a;
     101     1156373 :       d=d1; d1=r;
     102             :     }
     103     8820719 :     if (gc_needed(av,1))
     104             :     {
     105         879 :       if(DEBUGMEM>1) pari_warn(warnmem,"invmod");
     106         879 :       gerepileall(av1, 4, &d,&d1,&v,&v1);
     107             :     }
     108             :   } /* end while */
     109             : 
     110             :   /* Postprocessing - final sprint */
     111     5437684 :   if (signe(d1))
     112             :   {
     113             :     /* Assertions: lgefint(d)==lgefint(d1)==3, and
     114             :      * gcd(d,d1) is nonzero and fits into one word
     115             :      */
     116     5340761 :     g = xxgcduu(uel(d,2), uel(d1,2), 1, &xu, &xu1, &xv, &xv1, &s);
     117     5340762 :     if (g != 1UL) { set_avma(av); *res = utoipos(g); return 0; }
     118             :     /* (From the xgcduu() blurb:)
     119             :      * For finishing the multiword modinv, we now have to multiply the
     120             :      * returned matrix  (with properly adjusted signs)  onto the values
     121             :      * v' and v1' previously obtained from the multiword division steps.
     122             :      * Actually, it is sufficient to take the scalar product of [v',v1']
     123             :      * with [u1,-v1], and change the sign if s==1.
     124             :      */
     125     5340644 :     v = subii(muliu(v,xu1),muliu(v1,xv1));
     126     5340643 :     if (s > 0) setsigne(v,-signe(v));
     127     5340643 :     set_avma(av); *res = modii(v,b); return 1;
     128             :   }
     129             :   /* get here when the final sprint was skipped (d1 was zero already) */
     130       96923 :   set_avma(av);
     131       96923 :   if (!equalii(d,gen_1)) { *res = icopy(d); return 0; }
     132       96822 :   *res = modii(v,b); return 1;
     133             : }

Generated by: LCOV version 1.16