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 - invmod.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.10.0 lcov report (development 19823-d80e022) Lines: 49 51 96.1 %
Date: 2016-12-03 05:49:13 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. 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             :  * invmod(a,b,res)
      17             :  *==================================
      18             :  *    If a is invertible, return 1, and set res  = a^{ -1 }
      19             :  *    Otherwise, return 0, and set res = gcd(a,b)
      20             :  *
      21             :  * This is sufficiently different from bezout() to be implemented separately
      22             :  * instead of having a bunch of extra conditionals in a single function body
      23             :  * to meet both purposes.
      24             :  */
      25             : 
      26             : #ifdef INVMOD_PARI
      27             : INLINE int
      28     4263026 : invmod_pari(GEN a, GEN b, GEN *res)
      29             : #else
      30             : int
      31     2557555 : invmod(GEN a, GEN b, GEN *res)
      32             : #endif
      33             : {
      34             :   GEN v,v1,d,d1,q,r;
      35             :   pari_sp av, av1;
      36             :   long s;
      37             :   ulong g;
      38             :   ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */
      39             :   int lhmres; /* Lehmer stage return value */
      40             : 
      41     6820581 :   if (!signe(b)) { *res=absi(a); return 0; }
      42     6820581 :   av = avma;
      43     6820581 :   if (lgefint(b) == 3) /* single-word affair */
      44             :   {
      45     2520890 :     ulong d1 = umodiu(a, uel(b,2));
      46     2520891 :     if (d1 == 0)
      47             :     {
      48         472 :       if (b[2] == 1L)
      49          14 :         { *res = gen_0; return 1; }
      50             :       else
      51         458 :         { *res = absi(b); return 0; }
      52             :     }
      53     2520419 :     g = xgcduu(uel(b,2), d1, 1, &xv, &xv1, &s);
      54     2520419 :     avma = av;
      55     2520419 :     if (g != 1UL) { *res = utoipos(g); return 0; }
      56     2520399 :     xv = xv1 % uel(b,2); if (s < 0) xv = uel(b,2) - xv;
      57     2520399 :     *res = utoipos(xv); return 1;
      58             :   }
      59             : 
      60     4299691 :   (void)new_chunk(lgefint(b));
      61     4286133 :   d = absi(b); d1 = modii(a,d);
      62             : 
      63     4279186 :   v=gen_0; v1=gen_1;        /* general case */
      64     4279186 :   av1 = avma;
      65             : 
      66    14271686 :   while (lgefint(d) > 3 && signe(d1))
      67             :   {
      68     5715132 :     lhmres = lgcdii((ulong*)d, (ulong*)d1, &xu, &xu1, &xv, &xv1, ULONG_MAX);
      69     5754249 :     if (lhmres != 0)                /* check progress */
      70             :     {                                /* apply matrix */
      71     5234136 :       if (lhmres == 1 || lhmres == -1)
      72             :       {
      73      194173 :         if (xv1 == 1)
      74             :         {
      75       91890 :           r = subii(d,d1); d=d1; d1=r;
      76       91889 :           a = subii(v,v1); v=v1; v1=a;
      77             :         }
      78             :         else
      79             :         {
      80        5198 :           r = subii(d, mului(xv1,d1)); d=d1; d1=r;
      81        5197 :           a = subii(v, mului(xv1,v1)); v=v1; v1=a;
      82             :         }
      83             :       }
      84             :       else
      85             :       {
      86     5137048 :         r  = subii(muliu(d,xu),  muliu(d1,xv));
      87     5111627 :         a  = subii(muliu(v,xu),  muliu(v1,xv));
      88     5084425 :         d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r;
      89     5112677 :         v1 = subii(muliu(v,xu1), muliu(v1,xv1)); v = a;
      90     5115845 :         if (lhmres&1) { togglesign(d);  togglesign(v); }
      91     2568103 :         else          { togglesign(d1); togglesign(v1); }
      92             :       }
      93             :     }
      94             : 
      95     5713332 :     if (lhmres <= 0 && signe(d1))
      96             :     {
      97      574708 :       q = dvmdii(d,d1,&r);
      98      574658 :       a = subii(v,mulii(q,v1));
      99      574690 :       v=v1; v1=a;
     100      574690 :       d=d1; d1=r;
     101             :     }
     102     5713314 :     if (gc_needed(av,1))
     103             :     {
     104           0 :       if(DEBUGMEM>1) pari_warn(warnmem,"invmod");
     105           0 :       gerepileall(av1, 4, &d,&d1,&v,&v1);
     106             :     }
     107             :   } /* end while */
     108             : 
     109             :   /* Postprocessing - final sprint */
     110     4277368 :   if (signe(d1))
     111             :   {
     112             :     /* Assertions: lgefint(d)==lgefint(d1)==3, and
     113             :      * gcd(d,d1) is nonzero and fits into one word
     114             :      */
     115     4192268 :     g = xxgcduu(uel(d,2), uel(d1,2), 1, &xu, &xu1, &xv, &xv1, &s);
     116     4228419 :     if (g != 1UL) { avma = av; *res = utoipos(g); return 0; }
     117             :     /* (From the xgcduu() blurb:)
     118             :      * For finishing the multiword modinv, we now have to multiply the
     119             :      * returned matrix  (with properly adjusted signs)  onto the values
     120             :      * v' and v1' previously obtained from the multiword division steps.
     121             :      * Actually, it is sufficient to take the scalar product of [v',v1']
     122             :      * with [u1,-v1], and change the sign if s==1.
     123             :      */
     124     4228387 :     v = subii(muliu(v,xu1),muliu(v1,xv1));
     125     4205585 :     if (s > 0) setsigne(v,-signe(v));
     126     4205585 :     avma = av; *res = modii(v,b); return 1;
     127             :   }
     128             :   /* get here when the final sprint was skipped (d1 was zero already) */
     129       85100 :   avma = av;
     130       85100 :   if (!equalii(d,gen_1)) { *res = icopy(d); return 0; }
     131       85060 :   *res = modii(v,b); return 1;
     132             : }

Generated by: LCOV version 1.11