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 - ellpadiclambdamu.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.18.0 lcov report (development 29818-b3e15d99d2) Lines: 113 113 100.0 %
Date: 2024-12-27 09:09:37 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Copyright (C) 2011  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
      14             : 
      15             : #include "pari.h"
      16             : #include "paripriv.h"
      17             : 
      18             : /** Batch p-adic logarithms **/
      19             : /* a/b mod q */
      20             : static ulong
      21        1771 : divmodulo(ulong a, ulong b, ulong p, ulong q)
      22             : {
      23        1771 :   long v = u_lvalrem(b, p, &b);
      24        1771 :   if (v) a /= upowuu(p,v);
      25             :   /* a/b is now a p-integer */
      26        1771 :   return Fl_div(a, b, q);
      27             : }
      28             : /* to compute log_p(a) mod q = p^n, p < 2^31 */
      29             : static GEN
      30         854 : initQplog(long p, ulong q, long n)
      31             : {
      32             :   long i, nn, nt;
      33             :   ulong a, P;
      34             :   GEN C;
      35        1316 :   for(nn = n, nt = n + 1; nn >= p; nn /= p) nt++;
      36         854 :   if (p == 2)
      37             :   {
      38          70 :     P = q - 8;
      39         378 :     while (3 * (nt - 1) > u_lval(nt-1, p) + n) nt--;
      40             :   }
      41             :   else
      42             :   {
      43         784 :     P = q - p;
      44        1750 :     while (nt > u_lval(nt-1, p) + n) nt--;
      45             :   }
      46         854 :   C = cgetg(nt, t_VECSMALL);
      47             :   /* [ P^(k-1) / k, k = 1..nt ] / (p - 1) */
      48        2625 :   for(i = 1, a = 1; i < nt; i++, a = Fl_mul(a, P, q))
      49        1771 :     C[i] = divmodulo(a, i * (p-1), p, q);
      50         854 :   return C;
      51             : }
      52             : /* compute log_p(a) / p (resp. log_2(a) / 4) mod p^n, 'a' a p-unit,
      53             :  * C = initQplog(p,q,n), q = p^n */
      54             : static ulong
      55     1638574 : logp(GEN C, ulong a, ulong p, ulong q, ulong pn)
      56             : {
      57     1638574 :   long i, b, z, n = lg(C)-1;
      58     1638574 :   a %= q;
      59             :   /* Euclidean quotient (a^2 = 1 mod 8, a^(p-1) = 1 mod p) */
      60     1638574 :   if (p == 2)
      61         476 :     b = Fl_sqr(a, q << 1) >> 3;
      62             :   else
      63     1638098 :     b = Fl_powu(a, p-1, q) / p;
      64     1638574 :   z = Fl_mul(b, C[n], pn);
      65     5354790 :   for (i = n-1; i > 0; i--) z = Fl_mul(z + C[i], b, pn);
      66     1638574 :   return z;
      67             : }
      68             : 
      69             : /* p-adic integration against d mu_E, mod p^n, m > 0. D fundamental,
      70             :  * W a msinit for k = 2, xpm an eigensymbol.
      71             :  * Assume |D p^n| < MAX_LONG. Much cheaper than oms at low precision.
      72             :  * Return 1/2 * correct value [half loop over a]. Assume xpm belongs to
      73             :  * (-1)^i (D/-1) - part */
      74             : static GEN
      75        1211 : polPn(GEN W, GEN xpm, long p, long D, long R, long n)
      76             : {
      77        1211 :   pari_sp av = avma, av2;
      78        1211 :   long N = (p == 2)? n + 2: n + 1;
      79        1211 :   ulong aD = labs(D), pn = upowuu(p, n), q = upowuu(p, N), ic = 0;
      80        1211 :   GEN v, Dq = muluu(aD, q), nc = icopy(gen_1), c = mkfrac(nc, Dq);
      81        1211 :   GEN C = n? initQplog(p, q, N): NULL;
      82        1211 :   GEN tab = R? ZV_to_Flv(teichmullerinit(p, N), q): NULL;
      83        1211 :   long a, A = itou(shifti(Dq,-1));
      84             : 
      85        1211 :   if (n) ic = Fl_inv(logp(C, 1 + (p == 2? 4: p), p, q, pn), pn);
      86        1211 :   v = zero_zv(pn); av2 = avma;
      87     3619819 :   for (a = 1; a <= A; a++, set_avma(av2))
      88             :   {
      89             :     GEN X;
      90     3618608 :     long s, ap = a % p;
      91             :     ulong x, j;
      92     3618608 :     if (!ap || !(s = kross(D,a))) continue;
      93     2210964 :     nc[2] = (long)a;
      94     2210964 :     X = mseval2_ooQ(W, xpm, c); /* xpm(a / Dq) */
      95     2210964 :     x = umodiu(X, q); if (!x) continue;
      96             :     /* log(a) / log(c) */
      97     1657705 :     j = n? Fl_mul(logp(C, a, p, q, pn), ic, pn): 0;
      98     1657705 :     if (R) x = Fl_mul(x, tab[Fl_powu(ap, R, p)], q);
      99     1657705 :     if (s < 0) x = Fl_neg(x, q);
     100     1657705 :     v[j + 1] = Fl_add(v[j + 1], x, q);
     101             :   }
     102        1211 :   v = Flv_to_Flx(v, evalvarn(0));
     103        1211 :   v = zlx_translate1(v, p, N);
     104        1211 :   return gerepileupto(av, Flx_to_ZX(v));
     105             : }
     106             : /* return lambda, assuming mu = 0 [else infinite loop] */
     107             : static long
     108         798 : lambda_ss(GEN W, GEN xpm, long v, long p, long D, long R, long n)
     109             : {
     110         378 :   for (;; n += 2)
     111         378 :   {
     112         798 :     GEN P = polPn(W, xpm, p, D, R, n);
     113             :     long mu;
     114         798 :     if (!signe(P)) continue;
     115         574 :     mu = ZX_lvalrem(P, p, &P) + v;
     116         574 :     if (!mu)
     117             :     {
     118         420 :       long M = upowuu(p,n);
     119         420 :       if (odd(n)) M -= p; else M--;
     120         420 :       M /= p + 1;
     121         420 :       return Flx_val(ZX_to_Flx(P, p)) - M;
     122             :     }
     123             :   }
     124             : }
     125             : /* return lambda, assuming mu = 0 [else infinite loop] */
     126             : static long
     127         147 : lambda_ord(GEN W, GEN xpm, long v, long p, long D, long R, GEN ap)
     128             : {
     129         147 :   GEN P1, P0 = polPn(W, xpm, p, D, R, 0);
     130             :   long n;
     131         147 :   for (n = 1;; n++, P0 = P1)
     132         119 :   {
     133         266 :     long mu, pn = upowuu(p,n);
     134         266 :     GEN P, xi, alpha, Q = utoipos(pn);
     135             : 
     136         266 :     P1 = polPn(W, xpm, p, D, R, n);
     137         266 :     alpha = mspadic_unit_eigenvalue(ap, 2, utoipos(p), n+1);
     138         266 :     alpha = padic_to_Q(ginv(alpha));
     139         266 :     xi = FpX_translate(polcyclo(pn, 0), gen_1, Q);
     140         266 :     P = ZX_sub(P1, ZX_Z_mul(FpX_mul(P0, xi, Q), alpha)); /* mod p^n */
     141             : 
     142         266 :     if (!signe(P) || n + v <= 0) continue;
     143         147 :     mu = ZX_lvalrem(P, p, &P) + v;
     144         147 :     if (!mu) return Flx_val(ZX_to_Flx(P, p));
     145             :   }
     146             : }
     147             : GEN
     148         378 : ellpadiclambdamu(GEN E, long p, long D, long R)
     149             : {
     150         378 :   pari_sp av = avma;
     151         378 :   long vC, s, muadd = 0;
     152             :   GEN W, xpm, C, ap;
     153             : 
     154         378 :   if (!sisfundamental(D))
     155           7 :     pari_err_DOMAIN("ellpadiclambdamu", "isfundamental(D)","=", gen_0, stoi(D));
     156         371 :   s = D < 0? -1: 1;
     157         371 :   if (odd(R)) s = -s;
     158             : 
     159         371 :   ap = ellap(E, utoi(p));
     160         371 :   if (ell_get_type(E) != t_ELL_Q)
     161           7 :     pari_err_TYPE("ellpadiclambdamu", E);
     162         364 :   if (!umodiu(ap, p))
     163             :   {
     164         217 :     if (Z_lval(ellQ_get_N(E), p) >= 2)
     165           7 :       pari_err_IMPL("additive reduction in ellpadiclambdamu");
     166         210 :     ap = NULL; /* supersingular */
     167             :   }
     168         357 :   if (ap)
     169             :   { /* ordinary */
     170         147 :     GEN v = ellisomat(E, p, 1), vE = gel(v,1), M = gel(v,2);
     171         147 :     if (lg(M) != 2) /* some p-isogeny */
     172             :     {
     173          70 :       long i, imax = 0, l = lg(vE);
     174          70 :       GEN wmax = NULL, vw = cgetg(l, t_VEC);
     175         245 :       for (i = 1; i < l; i++)
     176             :       {
     177         175 :         GEN w, e = ellinit(gel(vE,i), gen_1, 0), em = ellminimalmodel(e, NULL);
     178         175 :         gel(vE,i) = em; obj_free(e);
     179         175 :         w = ellQtwist_bsdperiod(gel(vE,i), s);
     180         175 :         if (s < 0) w = gel(w,2);
     181         175 :         gel(vw,i) = w;
     182             :         /* w is a positive real number, either Omega^+ or Omega^- / I */
     183         175 :         if (!imax || gcmp(w, wmax) > 0) { imax = i; wmax = w; }
     184             :       }
     185          70 :       if (imax != 1) muadd = Z_lval(ground(gdiv(gel(vw,imax), gel(vw,1))), p);
     186         245 :       for (i = 1; i < l; i++) obj_free(gel(vE,i));
     187          70 :       E = gel(vE, imax);
     188             :     }
     189             :   }
     190             : 
     191         357 :   W = msfromell(E, s);
     192         357 :   xpm = gel(W,2); W = gel(W,1);
     193         357 :   xpm = Q_primitive_part(xpm, &C);
     194         357 :   vC = C? Q_pval(C, utoipos(p)): 0;
     195         357 :   if (p == 2) vC++; /* due to half-loop in polPn */
     196         357 :   if (vC > 0) pari_err_BUG("ellpadiclambdamu [mu > 0]");
     197             : 
     198         357 :   if (ap)
     199             :   { /* ordinary */
     200         147 :     long L = lambda_ord(W, xpm, vC, p, D, R, ap);
     201         147 :     set_avma(av); return mkvec2s(L, muadd);
     202             :   }
     203             :   else
     204             :   {
     205         210 :     long Lp = lambda_ss(W, xpm, vC, p, D, R, 0);
     206         210 :     long Lm = lambda_ss(W, xpm, vC, p, D, R, 1);
     207         210 :     set_avma(av); retmkvec2(mkvec2s(Lp, Lm), zerovec(2));
     208             :   }
     209             : }

Generated by: LCOV version 1.16