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 - bnfunits.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.12.1 lcov report (development 25406-bf255ab81b) Lines: 193 205 94.1 %
Date: 2020-06-04 05:59:24 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Copyright (C) 2020  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. It is distributed in the hope that it will be useful, but WITHOUT
       8             : ANY WARRANTY WHATSOEVER.
       9             : 
      10             : Check the License for details. You should have received a copy of it, along
      11             : with the package; see the file 'COPYING'. If not, write to the Free Software
      12             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      13             : #include "pari.h"
      14             : #include "paripriv.h"
      15             : 
      16             : /* if x a famat, assume it is a true unit (very costly to check even that
      17             :  * it's an algebraic integer) */
      18             : GEN
      19        1631 : bnfisunit(GEN bnf, GEN x)
      20             : {
      21        1631 :   long tx = typ(x), i, r1, RU, e, n, prec;
      22        1631 :   pari_sp av = avma;
      23             :   GEN t, rlog, logunit, ex, nf, pi2_sur_w, rx, emb, arg;
      24             : 
      25        1631 :   bnf = checkbnf(bnf); nf = bnf_get_nf(bnf);
      26        1631 :   logunit = bnf_get_logfu(bnf); RU = lg(logunit);
      27        1631 :   n = bnf_get_tuN(bnf); /* # { roots of 1 } */
      28        1631 :   if (tx == t_MAT)
      29             :   { /* famat, assumed OK */
      30        1302 :     if (lg(x) != 3) pari_err_TYPE("bnfisunit [not a factorization]", x);
      31             :   } else {
      32         329 :     x = nf_to_scalar_or_basis(nf,x);
      33         329 :     if (typ(x) != t_COL)
      34             :     { /* rational unit ? */
      35             :       GEN v;
      36             :       long s;
      37         140 :       if (typ(x) != t_INT || !is_pm1(x)) return cgetg(1,t_COL);
      38         133 :       s = signe(x); set_avma(av); v = zerocol(RU);
      39         133 :       gel(v,RU) = utoi((s > 0)? 0: n>>1);
      40         133 :       return v;
      41             :     }
      42         189 :     if (!isint1(Q_denom(x))) { set_avma(av); return cgetg(1,t_COL); }
      43             :   }
      44             : 
      45        1491 :   r1 = nf_get_r1(nf);
      46        1491 :   rlog = real_i(logunit);
      47        1491 :   prec = nf_get_prec(nf);
      48        1491 :   for (i = 1;; i++)
      49             :   {
      50        1491 :     rx = nflogembed(nf,x,&emb, MEDDEFAULTPREC);
      51        1491 :     if (rx)
      52             :     {
      53        1491 :       GEN logN = RgV_sum(rx); /* log(Nx), should be ~ 0 */
      54        1491 :       if (gexpo(logN) > -20)
      55             :       { /* precision problem ? */
      56          14 :         if (typ(logN) != t_REAL) { set_avma(av); return cgetg(1,t_COL); } /*no*/
      57          28 :         if (i == 1 && typ(x) != t_MAT &&
      58          28 :             !is_pm1(nfnorm(nf, x))) { set_avma(av); return cgetg(1, t_COL); }
      59             :       }
      60             :       else
      61             :       {
      62         504 :         ex = RU == 1? cgetg(1,t_COL)
      63        1477 :                     : RgM_solve(rlog, rx); /* ~ fundamental units exponents */
      64        1477 :         if (ex) { ex = grndtoi(ex, &e); if (e < -4) break; }
      65             :       }
      66             :     }
      67           0 :     if (i == 1)
      68           0 :       prec = nbits2prec(gexpo(x) + 128);
      69             :     else
      70             :     {
      71           0 :       if (i > 4) pari_err_PREC("bnfisunit");
      72           0 :       prec = precdbl(prec);
      73             :     }
      74           0 :     if (DEBUGLEVEL) pari_warn(warnprec,"bnfisunit",prec);
      75           0 :     nf = nfnewprec_shallow(nf, prec);
      76             :   }
      77             :   /* choose a large embedding => small relative error */
      78        1975 :   for (i = 1; i < RU; i++)
      79        1352 :     if (signe(gel(rx,i)) > -1) break;
      80        1477 :   if (RU == 1) t = gen_0;
      81             :   else
      82             :   {
      83         973 :     t = imag_i( row_i(logunit,i, 1,RU-1) );
      84         973 :     t = RgV_dotproduct(t, ex);
      85         973 :     if (i > r1) t = gmul2n(t, -1);
      86             :   }
      87        1477 :   if (typ(emb) != t_MAT) arg = garg(gel(emb,i), prec);
      88             :   else
      89             :   {
      90        1302 :     GEN p = gel(emb,1), e = gel(emb,2);
      91        1302 :     long j, l = lg(p);
      92        1302 :     arg = NULL;
      93        6524 :     for (j = 1; j < l; j++)
      94             :     {
      95        5222 :       GEN a = gmul(gel(e,j), garg(gel(gel(p,j),i), prec));
      96        5222 :       arg = arg? gadd(arg, a): a;
      97             :     }
      98             :   }
      99        1477 :   t = gsub(arg, t); /* = arg(the missing root of 1) */
     100        1477 :   pi2_sur_w = divru(mppi(prec), n>>1); /* 2pi / n */
     101        1477 :   e = umodiu(roundr(divrr(t, pi2_sur_w)), n);
     102        1477 :   if (n > 2)
     103             :   {
     104           0 :     GEN z = algtobasis(nf, bnf_get_tuU(bnf)); /* primitive root of 1 */
     105           0 :     GEN ro = RgV_dotproduct(row(nf_get_M(nf), i), z);
     106           0 :     GEN p2 = roundr(divrr(garg(ro, prec), pi2_sur_w));
     107           0 :     e *= Fl_inv(umodiu(p2,n), n);
     108           0 :     e %= n;
     109             :   }
     110        1477 :   gel(ex,RU) = utoi(e); setlg(ex, RU+1); return gerepilecopy(av, ex);
     111             : }
     112             : 
     113             : /* S a list of prime ideal in idealprimedec format. If pH != NULL, set it to
     114             :  * the HNF of the S-class group and return bnfsunit, else return bnfunits */
     115             : static GEN
     116         364 : bnfsunit_i(GEN bnf, GEN S, GEN *pH, GEN *pperm, GEN *pA, GEN *pden)
     117             : {
     118         364 :   const long FLAG = nf_FORCE | (pH? nf_GEN: nf_GENMAT);
     119         364 :   long i, nH, lS = lg(S);
     120             :   GEN M, U, H, Sunit, den, S2, perm, dep, B, C, U1;
     121             : 
     122         364 :   if (!is_vec_t(typ(S))) pari_err_TYPE("bnfsunit",S);
     123         364 :   bnf = checkbnf(bnf);
     124         364 :   if (lS == 1)
     125             :   {
     126          14 :     *pperm = cgetg(1,t_VECSMALL);
     127          14 :     *pA = cgetg(1,t_MAT);
     128          14 :     *pden = gen_1; return cgetg(1,t_VEC);
     129             :   }
     130         350 :   M = cgetg(lS,t_MAT); /* relation matrix for the S class group */
     131        2751 :   for (i = 1; i < lS; i++)
     132             :   {
     133        2401 :     GEN pr = gel(S,i); checkprid(pr);
     134        2401 :     gel(M,i) = isprincipal(bnf,pr);
     135             :   }
     136             :   /* S class group */
     137         350 :   M = shallowconcat(M, diagonal_shallow(bnf_get_cyc(bnf)));
     138         350 :   H = ZM_hnfall(M, &U, 1); if (pH) *pH = H;
     139             :   /* S-units */
     140        2751 :   U1 = U; setlg(U1,lS); for (i = 1; i < lS; i++) setlg(U1[i], lS);
     141             :  /* U1 = upper left corner of U, invertible. S * U1 = principal ideals
     142             :   * whose generators generate the S-units */
     143         350 :   C = zeromat(0, lS-1); /* junk for mathnfspec */
     144         350 :   H = mathnfspec(U1, &perm, &dep, &B, &C); /* dep has 0 rows */
     145             :  /*                   [ H B  ]            [ H^-1   - H^-1 B ]
     146             :   * perm o HNF(U1) =  [ 0 Id ], inverse = [  0         Id   ]
     147             :   * S * HNF(U1) = integral generators for S-units  = Sunit */
     148         350 :   Sunit = cgetg(lS, t_VEC);
     149         350 :   S2 = vecpermute(S, perm);
     150         350 :   nH = lg(H) - 1; setlg(S2, nH + 1);
     151        2751 :   for (i = 1; i < lS; i++)
     152             :   {
     153        2401 :     GEN C = NULL, E;
     154        2401 :     if (i <= nH) E = gel(H,i); else { C = gel(S2,i), E = gel(B,i-nH); }
     155        2401 :     gel(Sunit,i) = gel(isprincipalfact(bnf, C, S2, E, FLAG), 2);
     156             :   }
     157         350 :   H = ZM_inv(H,&den);
     158         350 :   *pperm = perm;
     159         350 :   *pA = shallowconcat(H, ZM_neg(ZM_mul(H,B))); /* top inverse * den */
     160         350 :   *pden = den; return Sunit;
     161             : }
     162             : GEN
     163         168 : bnfsunit(GEN bnf,GEN S,long prec)
     164             : {
     165         168 :   pari_sp av = avma;
     166         168 :   long i, l = lg(S);
     167         168 :   GEN v, R, h, nf, perm, A, den, U, H = NULL;
     168         168 :   bnf = checkbnf(bnf); nf = bnf_get_nf(bnf);
     169         168 :   v = cgetg(7, t_VEC);
     170         168 :   gel(v,1) = U = bnfsunit_i(bnf, S, &H, &perm, &A, &den);
     171         168 :   gel(v,2) = mkvec3(perm, A, den);
     172         168 :   gel(v,3) = cgetg(1,t_VEC); /* dummy */
     173         168 :   h = gen_1;
     174         168 :   if (l == 1)
     175           7 :     gel(v,5) = bnf_get_clgp(bnf);
     176             :   else
     177             :   { /* non trivial S-class group */
     178         161 :     GEN A, u, gen = bnf_get_gen(bnf), D = ZM_snf_group(H, NULL, &u);
     179         161 :     long lD = lg(D);
     180         161 :     A = cgetg(lD, t_VEC); h = ZV_prod(D);
     181         182 :     for(i = 1; i < lD; i++) gel(A,i) = idealfactorback(nf, gen, gel(u,i), 1);
     182         161 :     gel(v,5) = mkvec3(h, D, A);
     183             :   }
     184         168 :   R = bnf_get_reg(bnf);
     185         168 :   if (l > 1)
     186             :   { /* S-regulator and S-units*/
     187         161 :     R = mpmul(R, h);
     188        1995 :     for (i = 1; i < l; i++)
     189             :     {
     190        1834 :       GEN p = pr_get_p( gel(S,i) );
     191        1834 :       R = mpmul(R, logr_abs(itor(p,prec)));
     192        1834 :       gel(U,i) = nf_to_scalar_or_alg(nf, gel(U,i));
     193             :     }
     194             :   }
     195         168 :   gel(v,4) = R;
     196         168 :   gel(v,6) = S; return gerepilecopy(av, v);
     197             : }
     198             : GEN
     199          21 : bnfunits(GEN bnf, GEN S)
     200             : {
     201          21 :   pari_sp av = avma;
     202             :   GEN perm, A, den, U, fu, tu;
     203          21 :   bnf = checkbnf(bnf);
     204          21 :   U = bnfsunit_i(bnf, S? S: cgetg(1,t_VEC), NULL, &perm, &A, &den);
     205          21 :   if (!S) S = cgetg(1,t_VEC);
     206          21 :   fu = bnf_compactfu(bnf);
     207          21 :   if (!fu)
     208             :   {
     209             :     long i, l;
     210          14 :     fu = bnf_has_fu(bnf); if (!fu) bnf_build_units(bnf);
     211          14 :     fu = shallowcopy(fu); l = lg(fu);
     212          28 :     for (i = 1; i < l; i++) gel(fu,i) = to_famat_shallow(gel(fu,i),gen_1);
     213             :   }
     214          21 :   tu = nf_to_scalar_or_basis(bnf_get_nf(bnf), bnf_get_tuU(bnf));
     215          21 :   U = shallowconcat(U, vec_append(fu, to_famat_shallow(tu,gen_1)));
     216          21 :   return gerepilecopy(av, mkvec5(U, S, perm, A, den));
     217             : }
     218             : GEN
     219         175 : sunits_mod_units(GEN bnf, GEN S)
     220             : {
     221         175 :   pari_sp av = avma;
     222             :   GEN perm, A, den;
     223         175 :   bnf = checkbnf(bnf);
     224         175 :   return gerepilecopy(av, bnfsunit_i(bnf, S, NULL, &perm, &A, &den));
     225             : }
     226             : 
     227             : /* v_S(x), x in famat form */
     228             : static GEN
     229         105 : sunit_famat_val(GEN nf, GEN S, GEN x)
     230             : {
     231         105 :   long i, l = lg(S);
     232         105 :   GEN v = cgetg(l, t_VEC);
     233        1085 :   for (i = 1; i < l; i++) gel(v,i) = famat_nfvalrem(nf, x, gel(S,i), NULL);
     234         105 :   return v;
     235             : }
     236             : /* v_S(x), x algebraic number */
     237             : static GEN
     238        1211 : sunit_val(GEN nf, GEN S, GEN x, GEN N)
     239             : {
     240        1211 :   long i, l = lg(S);
     241        1211 :   GEN v = zero_zv(l-1), N0 = N;
     242       37072 :   for (i = 1; i < l; i++)
     243             :   {
     244       35861 :     GEN P = gel(S,i), p = pr_get_p(P);
     245       35861 :     if (dvdii(N, p)) { v[i] = nfval(nf,x,P); (void)Z_pvalrem(N0, p, &N0); }
     246             :   }
     247        1211 :   return is_pm1(N0)? v: NULL;
     248             : }
     249             : 
     250             : /* if *px a famat, assume it's an S-unit */
     251             : static GEN
     252        1617 : make_unit(GEN nf, GEN U, GEN *px)
     253             : {
     254        1617 :   GEN den, v, w, A, perm, gen = gel(U,1), S = gel(U,2), x = *px;
     255        1617 :   long cH, i, l = lg(S);
     256             : 
     257        1617 :   if (l == 1) return cgetg(1, t_COL);
     258        1589 :   perm = gel(U,3); A = gel(U,4); den = gel(U,5);
     259        1589 :   cH = nbrows(A);
     260        1589 :   if (typ(x) == t_MAT && lg(x) == 3)
     261             :   {
     262         105 :     v = sunit_famat_val(nf, S, x); /* x = S v */
     263         105 :     w = vecpermute(v, perm);
     264         105 :     v = ZM_ZC_mul(A, w);
     265         105 :     w += cH; w[0] = evaltyp(t_COL) | evallg(lg(A) - cH);
     266             :   }
     267             :   else
     268             :   {
     269             :     GEN N;
     270        1484 :     x = nf_to_scalar_or_basis(nf,x);
     271        1484 :     switch(typ(x))
     272             :     {
     273         497 :       case t_INT:  N = x; if (!signe(N)) return NULL; break;
     274           0 :       case t_FRAC: N = mulii(gel(x,1),gel(x,2)); break;
     275         987 :       default: { GEN d = Q_denom(x); N = mulii(idealnorm(nf,gmul(x,d)), d); }
     276             :     }
     277             :     /* relevant primes divide N */
     278        1484 :     if (is_pm1(N)) return zerocol(l-1);
     279        1211 :     v = sunit_val(nf, S, x, N);
     280        1211 :     if (!v) return NULL;
     281        1197 :     w = vecsmallpermute(v, perm);
     282        1197 :     v = ZM_zc_mul(A, w);
     283        1197 :     w += cH; w[0] = evaltyp(t_VECSMALL) | evallg(lg(A) - cH);
     284        1197 :     w = zc_to_ZC(w);
     285             :   }
     286        2394 :   if (!is_pm1(den)) for (i = 1; i <= cH; i++)
     287             :   {
     288             :     GEN r;
     289        1092 :     gel(v,i) = dvmdii(gel(v,i), den, &r);
     290        1092 :     if (r != gen_0) return NULL;
     291             :   }
     292        1302 :   v = shallowconcat(v, w); /* append bottom of w (= [0 Id] part) */
     293       38073 :   for (i = 1; i < l; i++)
     294             :   {
     295       36771 :     GEN e = gel(v,i);
     296       36771 :     if (signe(e)) x = famat_mulpow_shallow(x, gel(gen,i), negi(e));
     297             :   }
     298        1302 :   *px = x; return v;
     299             : }
     300             : 
     301             : static GEN
     302        1617 : bnfissunit_i(GEN bnf, GEN x, GEN U)
     303             : {
     304        1617 :   GEN w, nf, v = NULL;
     305        1617 :   bnf = checkbnf(bnf);
     306        1617 :   nf = bnf_get_nf(bnf);
     307        1617 :   if ( (w = make_unit(nf, U, &x)) ) v = bnfisunit(bnf, x);
     308        1617 :   if (!v || lg(v) == 1) return NULL;
     309        1589 :   return mkvec2(v, w);
     310             : }
     311             : static int
     312         119 : checkU(GEN U)
     313             : {
     314             :   GEN g, S, perm;
     315         119 :   if (typ(U) != t_VEC || lg(U) != 6) return 0;
     316         119 :   g = gel(U,1); S = gel(U,2); perm = gel(U,3);
     317         119 :   return typ(g) == t_VEC && is_vec_t(typ(S)) && typ(perm) == t_VECSMALL
     318         238 :          && lg(S) == lg(perm);
     319             : }
     320             : GEN
     321         147 : bnfisunit0(GEN bnf, GEN x, GEN U)
     322             : {
     323         147 :   pari_sp av = avma;
     324             :   GEN z;
     325         147 :   if (!U) return bnfisunit(bnf, x);
     326         119 :   if (!checkU(U)) pari_err_TYPE("bnfisunit",U);
     327         119 :   z = bnfissunit_i(bnf, x, U);
     328         119 :   if (!z) { set_avma(av); return cgetg(1,t_COL); }
     329         105 :   return gerepilecopy(av, shallowconcat(gel(z,2), gel(z,1)));
     330             : }
     331             : 
     332             : /* OBSOLETE */
     333             : static int
     334        1498 : checkbnfS_i(GEN v)
     335             : {
     336             :   GEN S, g, w;
     337        1498 :   if (typ(v) != t_VEC || lg(v) != 7) return 0;
     338        1498 :   g = gel(v,1); w = gel(v,2); S = gel(v,6);
     339        1498 :   if (typ(g) != t_VEC || !is_vec_t(typ(S)) || lg(S) != lg(g)) return 0;
     340        1498 :   return typ(w) == t_VEC && lg(w) == 4 && typ(gel(w,1)) == t_VECSMALL;
     341             : }
     342             : /* OBSOLETE */
     343             : GEN
     344        1498 : bnfissunit(GEN bnf, GEN bnfS, GEN x)
     345             : {
     346        1498 :   pari_sp av = avma;
     347             :   GEN z, U;
     348        1498 :   if (!checkbnfS_i(bnfS)) pari_err_TYPE("bnfissunit",bnfS);
     349        1498 :   U = mkvec5(gel(bnfS,1), gel(bnfS,6), gmael(bnfS,2,1), gmael(bnfS,2,2),
     350        1498 :              gmael(bnfS,2,3));
     351        1498 :   z = bnfissunit_i(bnf, x, U);
     352        1498 :   if (!z) { set_avma(av); return cgetg(1,t_COL); }
     353        1484 :   return gerepilecopy(av, shallowconcat(gel(z,1), gel(z,2)));
     354             : }

Generated by: LCOV version 1.13