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 - arith2.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.18.1 lcov report (development 30702-bddb8d6928) Lines: 524 558 93.9 %
Date: 2026-02-23 02:23:56 Functions: 71 76 93.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Copyright (C) 2000  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      14             : 
      15             : /*********************************************************************/
      16             : /**                     ARITHMETIC FUNCTIONS                        **/
      17             : /**                        (second part)                            **/
      18             : /*********************************************************************/
      19             : #include "pari.h"
      20             : #include "paripriv.h"
      21             : 
      22             : #define DEBUGLEVEL DEBUGLEVEL_arith
      23             : 
      24             : GEN
      25          70 : boundfact(GEN n, ulong lim)
      26             : {
      27          70 :   switch(typ(n))
      28             :   {
      29          58 :     case t_INT: return Z_factor_limit(n,lim);
      30          12 :     case t_FRAC: {
      31          12 :       pari_sp av = avma;
      32          12 :       GEN a = Z_factor_limit(gel(n,1),lim);
      33          12 :       GEN b = Z_factor_limit(gel(n,2),lim);
      34          12 :       gel(b,2) = ZC_neg(gel(b,2));
      35          12 :       return gc_GEN(av, ZM_merge_factor(a,b));
      36             :     }
      37             :   }
      38           0 :   pari_err_TYPE("boundfact",n);
      39             :   return NULL; /* LCOV_EXCL_LINE */
      40             : }
      41             : 
      42             : /* NOT memory clean */
      43             : GEN
      44       16301 : Z_lsmoothen(GEN N, GEN L, GEN *pP, GEN *pE)
      45             : {
      46       16301 :   long i, j, l = lg(L);
      47       16301 :   GEN E = new_chunk(l), P = new_chunk(l);
      48      151905 :   for (i = j = 1; i < l; i++)
      49             :   {
      50      144874 :     ulong p = uel(L,i);
      51      144874 :     long v = Z_lvalrem(N, p, &N);
      52      144874 :     if (v) { P[j] = p; E[j] = v; j++; if (is_pm1(N)) { N = NULL; break; } }
      53             :   }
      54       16301 :   P[0] = evaltyp(t_VECSMALL) | _evallg(j); if (pP) *pP = P;
      55       16301 :   E[0] = evaltyp(t_VECSMALL) | _evallg(j); if (pE) *pE = E; return N;
      56             : }
      57             : GEN
      58       66725 : Z_smoothen(GEN N, GEN L, GEN *pP, GEN *pE)
      59             : {
      60       66725 :   long i, j, l = lg(L);
      61       66725 :   GEN E = new_chunk(l), P = new_chunk(l);
      62      241464 :   for (i = j = 1; i < l; i++)
      63             :   {
      64      222565 :     GEN p = gel(L,i);
      65      222565 :     long v = Z_pvalrem(N, p, &N);
      66      222565 :     if (v)
      67             :     {
      68      165625 :       gel(P,j) = p; gel(E,j) = utoipos(v); j++;
      69      165625 :      if (is_pm1(N)) { N = NULL; break; }
      70             :     }
      71             :   }
      72       66725 :   P[0] = evaltyp(t_COL) | _evallg(j); if (pP) *pP = P;
      73       66725 :   E[0] = evaltyp(t_COL) | _evallg(j); if (pE) *pE = E; return N;
      74             : }
      75             : /***********************************************************************/
      76             : /**                    SIMPLE FACTORISATIONS                          **/
      77             : /***********************************************************************/
      78             : /* Factor n and output [p,e,c] where
      79             :  * p, e and c are vecsmall with n = prod{p[i]^e[i]} and c[i] = p[i]^e[i] */
      80             : GEN
      81      118977 : factoru_pow(ulong n)
      82             : {
      83      118977 :   GEN f = cgetg(4,t_VEC);
      84      118977 :   pari_sp av = avma;
      85             :   GEN F, P, E, p, e, c;
      86             :   long i, l;
      87             :   /* enough room to store <= 15 * [p,e,p^e] (OK if n < 2^64) */
      88      118977 :   (void)new_chunk((15 + 1)*3);
      89      118977 :   F = factoru(n);
      90      118977 :   P = gel(F,1);
      91      118977 :   E = gel(F,2); l = lg(P);
      92      118977 :   set_avma(av);
      93      118977 :   gel(f,1) = p = cgetg(l,t_VECSMALL);
      94      118977 :   gel(f,2) = e = cgetg(l,t_VECSMALL);
      95      118977 :   gel(f,3) = c = cgetg(l,t_VECSMALL);
      96      263287 :   for(i = 1; i < l; i++)
      97             :   {
      98      144310 :     p[i] = P[i];
      99      144310 :     e[i] = E[i];
     100      144310 :     c[i] = upowuu(p[i], e[i]);
     101             :   }
     102      118977 :   return f;
     103             : }
     104             : 
     105             : static GEN
     106       13931 : factorlim(GEN n, ulong lim)
     107       13931 : { return lim? Z_factor_limit(n, lim): Z_factor(n); }
     108             : /* factor p^n - 1, assuming p prime. If lim != 0, limit factorization to
     109             :  * primes <= lim */
     110             : GEN
     111        6330 : factor_pn_1_limit(GEN p, long n, ulong lim)
     112             : {
     113        6330 :   pari_sp av = avma;
     114        6330 :   GEN A = factorlim(subiu(p,1), lim), d = divisorsu(n);
     115        6330 :   long i, pp = itos_or_0(p);
     116       13639 :   for(i=2; i<lg(d); i++)
     117             :   {
     118             :     GEN B;
     119        7309 :     if (pp && d[i]%pp==0 && (
     120        2945 :        ((pp&3)==1 && (d[i]&1)) ||
     121        2927 :        ((pp&3)==3 && (d[i]&3)==2) ||
     122        2825 :        (pp==2 && (d[i]&7)==4)))
     123         292 :     {
     124         292 :       GEN f=factor_Aurifeuille_prime(p,d[i]);
     125         292 :       B = factorlim(f, lim);
     126         292 :       A = ZM_merge_factor(A, B);
     127         292 :       B = factorlim(diviiexact(polcyclo_eval(d[i],p), f), lim);
     128             :     }
     129             :     else
     130        7017 :       B = factorlim(polcyclo_eval(d[i],p), lim);
     131        7309 :     A = ZM_merge_factor(A, B);
     132             :   }
     133        6330 :   return gc_GEN(av, A);
     134             : }
     135             : GEN
     136        6330 : factor_pn_1(GEN p, ulong n)
     137        6330 : { return factor_pn_1_limit(p, n, 0); }
     138             : 
     139             : #if 0
     140             : static GEN
     141             : to_mat(GEN p, long e) {
     142             :   GEN B = cgetg(3, t_MAT);
     143             :   gel(B,1) = mkcol(p);
     144             :   gel(B,2) = mkcol(utoipos(e)); return B;
     145             : }
     146             : /* factor phi(n) */
     147             : GEN
     148             : factor_eulerphi(GEN n)
     149             : {
     150             :   pari_sp av = avma;
     151             :   GEN B = NULL, A, P, E, AP, AE;
     152             :   long i, l, v = vali(n);
     153             : 
     154             :   l = lg(n);
     155             :   /* result requires less than this: at most expi(n) primes */
     156             :   (void)new_chunk(bit_accuracy(l) * (l /*p*/ + 3 /*e*/ + 2 /*vectors*/) + 3+2);
     157             :   if (v) { n = shifti(n, -v); v--; }
     158             :   A = Z_factor(n); P = gel(A,1); E = gel(A,2); l = lg(P);
     159             :   for(i = 1; i < l; i++)
     160             :   {
     161             :     GEN p = gel(P,i), q = subiu(p,1), fa;
     162             :     long e = itos(gel(E,i)), w;
     163             : 
     164             :     w = vali(q); v += w; q = shifti(q,-w);
     165             :     if (! is_pm1(q))
     166             :     {
     167             :       fa = Z_factor(q);
     168             :       B = B? ZM_merge_factor(B, fa): fa;
     169             :     }
     170             :     if (e > 1) {
     171             :       if (B) {
     172             :         gel(B,1) = vec_append(gel(B,1), p);
     173             :         gel(B,2) = vec_append(gel(B,2), utoipos(e-1));
     174             :       } else
     175             :         B = to_mat(p, e-1);
     176             :     }
     177             :   }
     178             :   set_avma(av);
     179             :   if (!B) return v? to_mat(gen_2, v): trivial_fact();
     180             :   A = cgetg(3, t_MAT);
     181             :   P = gel(B,1); E = gel(B,2); l = lg(P);
     182             :   AP = cgetg(l+1, t_COL); gel(A,1) = AP; AP++;
     183             :   AE = cgetg(l+1, t_COL); gel(A,2) = AE; AE++;
     184             :   /* prepend "2^v" */
     185             :   gel(AP,0) = gen_2;
     186             :   gel(AE,0) = utoipos(v);
     187             :   for (i = 1; i < l; i++)
     188             :   {
     189             :     gel(AP,i) = icopy(gel(P,i));
     190             :     gel(AE,i) = icopy(gel(E,i));
     191             :   }
     192             :   return A;
     193             : }
     194             : #endif
     195             : 
     196             : /***********************************************************************/
     197             : /**         CHECK FACTORIZATION FOR ARITHMETIC FUNCTIONS              **/
     198             : /***********************************************************************/
     199             : int
     200    13678183 : RgV_is_ZVpos(GEN v)
     201             : {
     202    13678183 :   long i, l = lg(v);
     203    39505101 :   for (i = 1; i < l; i++)
     204             :   {
     205    25835613 :     GEN c = gel(v,i);
     206    25835613 :     if (typ(c) != t_INT || signe(c) <= 0) return 0;
     207             :   }
     208    13669488 :   return 1;
     209             : }
     210             : /* check whether v is a ZV with nonzero entries */
     211             : int
     212       17717 : RgV_is_ZVnon0(GEN v)
     213             : {
     214       17717 :   long i, l = lg(v);
     215      135352 :   for (i = 1; i < l; i++)
     216             :   {
     217      117675 :     GEN c = gel(v,i);
     218      117675 :     if (typ(c) != t_INT || !signe(c)) return 0;
     219             :   }
     220       17677 :   return 1;
     221             : }
     222             : /* check whether v is a ZV with nonzero entries OR exactly [0] */
     223             : static int
     224      603862 : RgV_is_ZV0(GEN v)
     225             : {
     226      603862 :   long i, l = lg(v);
     227     2074137 :   for (i = 1; i < l; i++)
     228             :   {
     229     1470377 :     GEN c = gel(v,i);
     230             :     long s;
     231     1470377 :     if (typ(c) != t_INT) return 0;
     232     1470377 :     s = signe(c);
     233     1470377 :     if (!s) return (l == 2);
     234             :   }
     235      603760 :   return 1;
     236             : }
     237             : 
     238             : int
     239      277298 : RgV_is_prV(GEN v)
     240             : {
     241      277298 :   long l = lg(v), i;
     242      624168 :   for (i = 1; i < l; i++)
     243      513895 :     if (!checkprid_i(gel(v,i))) return 0;
     244      110273 :   return 1;
     245             : }
     246             : int
     247      234079 : is_nf_factor(GEN F)
     248             : {
     249      218026 :   return typ(F) == t_MAT && lg(F) == 3
     250      452105 :     && RgV_is_prV(gel(F,1)) && RgV_is_ZVpos(gel(F,2));
     251             : }
     252             : int
     253          12 : is_nf_extfactor(GEN F)
     254             : {
     255          12 :   return typ(F) == t_MAT && lg(F) == 3
     256          24 :     && RgV_is_prV(gel(F,1)) && RgV_is_ZV(gel(F,2));
     257             : }
     258             : 
     259             : static int
     260     7118077 : is_Z_factor_i(GEN f)
     261     7118077 : { return typ(f) == t_MAT && lg(f) == 3 && RgV_is_ZVpos(gel(f,2)); }
     262             : int
     263     6503703 : is_Z_factorpos(GEN f)
     264     6503703 : { return is_Z_factor_i(f) && RgV_is_ZVpos(gel(f,1)); }
     265             : int
     266      603862 : is_Z_factor(GEN f)
     267      603862 : { return is_Z_factor_i(f) && RgV_is_ZV0(gel(f,1)); }
     268             : /* as is_Z_factorpos, also allow factor(0) */
     269             : int
     270       10512 : is_Z_factornon0(GEN f)
     271       10512 : { return is_Z_factor_i(f) && RgV_is_ZVnon0(gel(f,1)); }
     272             : GEN
     273       20849 : clean_Z_factor(GEN f)
     274             : {
     275       20849 :   GEN P = gel(f,1);
     276       20849 :   long n = lg(P)-1;
     277       20849 :   if (n && equalim1(gel(P,1)))
     278        2190 :     return mkmat2(vecslice(P,2,n), vecslice(gel(f,2),2,n));
     279       18659 :   return f;
     280             : }
     281             : GEN
     282           0 : fuse_Z_factor(GEN f, GEN B)
     283             : {
     284           0 :   GEN P = gel(f,1), E = gel(f,2), P2,E2;
     285           0 :   long i, l = lg(P);
     286           0 :   if (l == 1) return f;
     287           0 :   for (i = 1; i < l; i++)
     288           0 :     if (abscmpii(gel(P,i), B) > 0) break;
     289           0 :   if (i == l) return f;
     290             :   /* tail / initial segment */
     291           0 :   P2 = vecslice(P, i, l-1); P = vecslice(P, 1, i-1);
     292           0 :   E2 = vecslice(E, i, l-1); E = vecslice(E, 1, i-1);
     293           0 :   P = vec_append(P, factorback2(P2,E2));
     294           0 :   E = vec_append(E, gen_1);
     295           0 :   return mkmat2(P, E);
     296             : }
     297             : 
     298             : /* n attached to a factorization of a positive integer: either N (t_INT)
     299             :  * a factorization matrix faN, or a t_VEC: [N, faN] */
     300             : GEN
     301         476 : check_arith_pos(GEN n, const char *f) {
     302         476 :   switch(typ(n))
     303             :   {
     304         455 :     case t_INT:
     305         455 :       if (signe(n) <= 0) pari_err_DOMAIN(f, "argument", "<=", gen_0, gen_0);
     306         455 :       return NULL;
     307           5 :     case t_VEC:
     308           5 :       if (lg(n) != 3 || typ(gel(n,1)) != t_INT || signe(gel(n,1)) <= 0) break;
     309           5 :       n = gel(n,2); /* fall through */
     310          16 :     case t_MAT:
     311          16 :       if (!is_Z_factorpos(n)) break;
     312          16 :       return n;
     313             :   }
     314           5 :   pari_err_TYPE(f,n);
     315             :   return NULL;/*LCOV_EXCL_LINE*/
     316             : }
     317             : /* n attached to a factorization of a nonzero integer */
     318             : GEN
     319     1841895 : check_arith_non0(GEN n, const char *f) {
     320     1841895 :   switch(typ(n))
     321             :   {
     322     1831577 :     case t_INT:
     323     1831577 :       if (!signe(n)) pari_err_DOMAIN(f, "argument", "=", gen_0, gen_0);
     324     1831531 :       return NULL;
     325        1018 :     case t_VEC:
     326        1018 :       if (lg(n) != 3 || typ(gel(n,1)) != t_INT || !signe(gel(n,1))) break;
     327        1018 :       n = gel(n,2); /* fall through */
     328       10318 :     case t_MAT:
     329       10318 :       if (!is_Z_factornon0(n)) break;
     330       10278 :       return n;
     331             :   }
     332          40 :   pari_err_TYPE(f,n);
     333             :   return NULL;/*LCOV_EXCL_LINE*/
     334             : }
     335             : /* n attached to a factorization of an integer */
     336             : GEN
     337     2200196 : check_arith_all(GEN n, const char *f) {
     338     2200196 :   switch(typ(n))
     339             :   {
     340     1596329 :     case t_INT:
     341     1596329 :       return NULL;
     342      588942 :     case t_VEC:
     343      588942 :       if (lg(n) != 3 || typ(gel(n,1)) != t_INT) break;
     344      588942 :       n = gel(n,2); /* fall through */
     345      603862 :     case t_MAT:
     346      603862 :       if (!is_Z_factor(n)) break;
     347      603862 :       return n;
     348             :   }
     349           5 :   pari_err_TYPE(f,n);
     350             :   return NULL;/*LCOV_EXCL_LINE*/
     351             : }
     352             : 
     353             : /***********************************************************************/
     354             : /**                MISCELLANEOUS ARITHMETIC FUNCTIONS                 **/
     355             : /**                (ultimately depend on Z_factor())                  **/
     356             : /***********************************************************************/
     357             : /* set P,E from F. Check whether F is an integer and kill "factor" -1 */
     358             : static void
     359      259250 : set_fact_check(GEN F, GEN *pP, GEN *pE, int *isint)
     360             : {
     361             :   GEN E, P;
     362      259250 :   if (lg(F) != 3) pari_err_TYPE("divisors",F);
     363      259250 :   P = gel(F,1);
     364      259250 :   E = gel(F,2);
     365      259250 :   RgV_check_ZV(E, "divisors");
     366      259250 :   *isint = RgV_is_ZV(P);
     367      259250 :   if (*isint)
     368             :   {
     369      259240 :     long i, l = lg(P);
     370             :     /* skip -1 */
     371      259240 :     if (l>1 && signe(gel(P,1)) < 0) { E++; P = vecslice(P,2,--l); }
     372             :     /* test for 0 */
     373      839615 :     for (i = 1; i < l; i++)
     374      580380 :       if (!signe(gel(P,i)) && signe(gel(E,i)))
     375           5 :         pari_err_DOMAIN("divisors", "argument", "=", gen_0, F);
     376             :   }
     377      259245 :   *pP = P;
     378      259245 :   *pE = E;
     379      259245 : }
     380             : static void
     381        3092 : set_fact(GEN F, GEN *pP, GEN *pE) { *pP = gel(F,1); *pE = gel(F,2); }
     382             : 
     383             : int
     384      262347 : divisors_init(GEN n, GEN *pP, GEN *pE)
     385             : {
     386             :   long i,l;
     387             :   GEN E, P, e;
     388             :   int isint;
     389             : 
     390      262347 :   switch(typ(n))
     391             :   {
     392        3076 :     case t_INT:
     393        3076 :       if (!signe(n)) pari_err_DOMAIN("divisors", "argument", "=", gen_0, gen_0);
     394        3076 :       set_fact(absZ_factor(n), &P,&E);
     395        3076 :       isint = 1; break;
     396        1384 :     case t_VEC:
     397        1384 :       if (lg(n) != 3 || typ(gel(n,2)) !=t_MAT) pari_err_TYPE("divisors",n);
     398        1379 :       set_fact_check(gel(n,2), &P,&E, &isint);
     399        1379 :       break;
     400      257871 :     case t_MAT:
     401      257871 :       set_fact_check(n, &P,&E, &isint);
     402      257866 :       break;
     403          16 :     default:
     404          16 :       set_fact(factor(n), &P,&E);
     405          16 :       isint = 0; break;
     406             :   }
     407      262337 :   l = lg(P);
     408      262337 :   e = cgetg(l, t_VECSMALL);
     409      847374 :   for (i=1; i<l; i++)
     410             :   {
     411      585043 :     e[i] = itos(gel(E,i));
     412      585043 :     if (e[i] < 0) pari_err_TYPE("divisors [denominator]",n);
     413             :   }
     414      262331 :   *pP = P; *pE = e; return isint;
     415             : }
     416             : 
     417             : static long
     418      262560 : ndiv(GEN E)
     419             : {
     420             :   long i, l;
     421      262560 :   GEN e = cgetg_copy(E, &l); /* left on stack */
     422             :   ulong n;
     423      847907 :   for (i=1; i<l; i++) e[i] = E[i]+1;
     424      262560 :   n = itou_or_0( zv_prod_Z(e) );
     425      262560 :   if (!n || n & ~LGBITS) pari_err_OVERFLOW("divisors");
     426      262560 :   return n;
     427             : }
     428             : static int
     429       13149 : cmpi1(void *E, GEN a, GEN b) { (void)E; return cmpii(gel(a,1), gel(b,1)); }
     430             : /* P a t_COL of objects, E a t_VECSMALL of exponents, return cleaned-up
     431             :  * factorization (removing 0 exponents) as a t_MAT with 2 cols. */
     432             : static GEN
     433       18272 : fa_clean(GEN P, GEN E)
     434             : {
     435       18272 :   long i, j, l = lg(E);
     436       18272 :   GEN Q = cgetg(l, t_COL);
     437       51235 :   for (i = j = 1; i < l; i++)
     438       32963 :     if (E[i]) { gel(Q,j) = gel(P,i); E[j] = E[i]; j++; }
     439       18272 :   setlg(Q,j);
     440       18272 :   setlg(E,j); return mkmat2(Q,Flc_to_ZC(E));
     441             : }
     442             : GEN
     443        9170 : divisors_factored(GEN N)
     444             : {
     445        9170 :   pari_sp av = avma;
     446             :   GEN *d, *t1, *t2, *t3, D, P, E;
     447        9170 :   int isint = divisors_init(N, &P, &E);
     448        9170 :   GEN (*mul)(GEN,GEN) = isint? mulii: gmul;
     449        9170 :   long i, j, l, n = ndiv(E);
     450             : 
     451        9170 :   D = cgetg(n+1,t_VEC); d = (GEN*)D;
     452        9170 :   l = lg(E);
     453        9170 :   *++d = mkvec2(gen_1, const_vecsmall(l-1,0));
     454       24707 :   for (i=1; i<l; i++)
     455       22675 :     for (t1=(GEN*)D,j=E[i]; j; j--,t1=t2)
     456       16240 :       for (t2=d, t3=t1; t3<t2; )
     457             :       {
     458             :         GEN a, b;
     459        9102 :         a = mul(gel(*++t3,1), gel(P,i));
     460        9102 :         b = leafcopy(gel(*t3,2)); b[i]++;
     461        9102 :         *++d = mkvec2(a,b);
     462             :       }
     463        9170 :   if (isint) gen_sort_inplace(D,NULL,&cmpi1,NULL);
     464       27442 :   for (i = 1; i <= n; i++) gmael(D,i,2) = fa_clean(P, gmael(D,i,2));
     465        9170 :   return gc_GEN(av, D);
     466             : }
     467             : static int
     468        1290 : cmpu1(void *E, GEN va, GEN vb)
     469        1290 : { long a = va[1], b = vb[1]; (void)E; return a>b? 1: (a<b? -1: 0); }
     470             : static GEN
     471        1137 : fa_clean_u(GEN P, GEN E)
     472             : {
     473        1137 :   long i, j, l = lg(E);
     474        1137 :   GEN Q = cgetg(l, t_VECSMALL);
     475        3355 :   for (i = j = 1; i < l; i++)
     476        2218 :     if (E[i]) { Q[j] = P[i]; E[j] = E[i]; j++; }
     477        1137 :   setlg(Q,j);
     478        1137 :   setlg(E,j); return mkmat2(Q,E);
     479             : }
     480             : GEN
     481         264 : divisorsu_fact_factored(GEN fa)
     482             : {
     483         264 :   pari_sp av = avma;
     484         264 :   GEN *d, *t1, *t2, *t3, vD, D, P = gel(fa,1), E = gel(fa,2);
     485         264 :   long i, j, l, n = ndiv(E);
     486             : 
     487         264 :   D = cgetg(n+1,t_VEC); d = (GEN*)D;
     488         264 :   l = lg(E);
     489         264 :   *++d = mkvec2((GEN)1, const_vecsmall(l-1,0));
     490         699 :   for (i=1; i<l; i++)
     491        1008 :     for (t1=(GEN*)D,j=E[i]; j; j--,t1=t2)
     492        1446 :       for (t2=d, t3=t1; t3<t2; )
     493             :       {
     494             :         ulong a;
     495             :         GEN b;
     496         873 :         a = (*++t3)[1] * P[i];
     497         873 :         b = leafcopy(gel(*t3,2)); b[i]++;
     498         873 :         *++d = mkvec2((GEN)a,b);
     499             :       }
     500         264 :   gen_sort_inplace(D,NULL,&cmpu1,NULL);
     501         264 :   vD = cgetg(n+1, t_VECSMALL);
     502        1401 :   for (i = 1; i <= n; i++)
     503             :   {
     504        1137 :     vD[i] = umael(D,i,1);
     505        1137 :     gel(D,i) = fa_clean_u(P, gmael(D,i,2));
     506             :   }
     507         264 :   return gc_GEN(av, mkvec2(vD,D));
     508             : }
     509             : GEN
     510      253142 : divisors(GEN N)
     511             : {
     512             :   long i, j, l;
     513             :   GEN *d, *t1, *t2, *t3, D, P, E;
     514      253142 :   int isint = divisors_init(N, &P, &E);
     515      253126 :   GEN (*mul)(GEN,GEN) = isint? mulii: gmul;
     516             : 
     517      253126 :   D = cgetg(ndiv(E)+1,t_VEC); d = (GEN*)D;
     518      253126 :   l = lg(E);
     519      253126 :   *++d = gen_1;
     520      822501 :   for (i=1; i<l; i++)
     521     1539300 :     for (t1=(GEN*)D,j=E[i]; j; j--,t1=t2)
     522     3720240 :       for (t2=d, t3=t1; t3<t2; ) *++d = mul(*++t3, gel(P,i));
     523      253126 :   if (isint) ZV_sort_inplace(D);
     524      253126 :   return D;
     525             : }
     526             : GEN
     527         666 : divisors0(GEN N, long flag)
     528             : {
     529         666 :   if (flag && flag != 1) pari_err_FLAG("divisors");
     530         666 :   return flag? divisors_factored(N): divisors(N);
     531             : }
     532             : 
     533             : GEN
     534       19715 : divisorsu_moebius(GEN P)
     535             : {
     536             :   GEN d, t, t2, t3;
     537       19715 :   long i, l = lg(P);
     538       19715 :   d = t = cgetg((1 << (l-1)) + 1, t_VECSMALL);
     539       19715 :   *++d = 1;
     540       51350 :   for (i=1; i<l; i++)
     541       81333 :     for (t2=d, t3=t; t3<t2; ) *(++d) = *(++t3) * -P[i];
     542       19715 :   return t;
     543             : }
     544             : GEN
     545     8245160 : divisorsu_fact(GEN fa)
     546             : {
     547     8245160 :   GEN d, t, t1, t2, t3, P = gel(fa,1), E = gel(fa,2);
     548     8245160 :   long i, j, l = lg(P);
     549     8245160 :   d = t = cgetg(numdivu_fact(fa) + 1,t_VECSMALL);
     550     8245160 :   *++d = 1;
     551    27860770 :   for (i=1; i<l; i++)
     552    43726213 :     for (t1=t,j=E[i]; j; j--,t1=t2)
     553    88512698 :       for (t2=d, t3=t1; t3<t2; ) *(++d) = *(++t3) * P[i];
     554     8245160 :   vecsmall_sort(t); return t;
     555             : }
     556             : GEN
     557      135275 : divisorsu(ulong N)
     558             : {
     559      135275 :   pari_sp av = avma;
     560      135275 :   return gc_upto(av, divisorsu_fact(factoru(N)));
     561             : }
     562             : 
     563             : static GEN
     564           0 : corefa(GEN fa)
     565             : {
     566           0 :   GEN P = gel(fa,1), E = gel(fa,2), c = gen_1;
     567             :   long i;
     568           0 :   for (i=1; i<lg(P); i++)
     569           0 :     if (mod2(gel(E,i))) c = mulii(c,gel(P,i));
     570           0 :   return c;
     571             : }
     572             : static GEN
     573           0 : core2fa(GEN fa)
     574             : {
     575           0 :   GEN P = gel(fa,1), E = gel(fa,2), c = gen_1, f = gen_1;
     576             :   long i;
     577           0 :   for (i=1; i<lg(P); i++)
     578             :   {
     579           0 :     long e = itos(gel(E,i));
     580           0 :     if (e & 1)  c = mulii(c, gel(P,i));
     581           0 :     if (e != 1) f = mulii(f, powiu(gel(P,i), e >> 1));
     582             :   }
     583           0 :   return mkvec2(c,f);
     584             : }
     585             : GEN
     586           0 : corepartial(GEN n, long all)
     587             : {
     588           0 :   pari_sp av = avma;
     589           0 :   if (typ(n) != t_INT) pari_err_TYPE("corepartial",n);
     590           0 :   return gc_INT(av, corefa(Z_factor_limit(n,all)));
     591             : }
     592             : GEN
     593           0 : core2partial(GEN n, long all)
     594             : {
     595           0 :   pari_sp av = avma;
     596           0 :   if (typ(n) != t_INT) pari_err_TYPE("core2partial",n);
     597           0 :   return gc_GEN(av, core2fa(Z_factor_limit(n,all)));
     598             : }
     599             : /* given an arithmetic function argument, return the underlying integer */
     600             : static GEN
     601       50106 : arith_n(GEN A)
     602             : {
     603       50106 :   switch(typ(A))
     604             :   {
     605       46101 :     case t_INT: return A;
     606        2450 :     case t_VEC: return gel(A,1);
     607        1555 :     default: return factorback(A);
     608             :   }
     609             : }
     610             : static GEN
     611       46641 : core2_i(GEN n)
     612             : {
     613       46641 :   GEN f = core(n);
     614       46641 :   if (!signe(f)) return mkvec2(gen_0, gen_1);
     615       46616 :   return mkvec2(f, sqrtint(diviiexact(arith_n(n), f)));
     616             : }
     617             : GEN
     618       46570 : core2(GEN n) { pari_sp av = avma; return gc_GEN(av, core2_i(n)); }
     619             : 
     620             : GEN
     621        2236 : core0(GEN n,long flag) { return flag? core2(n): core(n); }
     622             : 
     623             : static long
     624        7366 : _mod4(GEN c) {
     625        7366 :   long r, s = signe(c);
     626        7366 :   if (!s) return 0;
     627        7366 :   r = mod4(c); if (s < 0) r = 4-r;
     628        7366 :   return r;
     629             : }
     630             : 
     631             : long
     632          48 : corediscs(long D, ulong *f)
     633             : { /* D = f^2 d */
     634          48 :   long d = D >= 0? (long)coreu(D) : -(long)coreu(-(ulong)D);
     635          48 :   if ((((ulong)d)&3UL) != 1) d *= 4;
     636          48 :   if (f) *f = usqrt((ulong)(D/d));
     637          48 :   return d;
     638             : }
     639             : 
     640             : GEN
     641        7295 : coredisc(GEN n)
     642             : {
     643        7295 :   pari_sp av = avma;
     644        7295 :   GEN c = core(n);
     645        7295 :   if (_mod4(c)<=1) return c; /* c = 0 or 1 mod 4 */
     646        2617 :   return gc_INT(av, shifti(c,2));
     647             : }
     648             : 
     649             : GEN
     650          71 : coredisc2(GEN n)
     651             : {
     652          71 :   pari_sp av = avma;
     653          71 :   GEN y = core2_i(n);
     654          71 :   GEN c = gel(y,1), f = gel(y,2);
     655          71 :   if (_mod4(c)<=1) return gc_GEN(av, y);
     656          11 :   y = cgetg(3,t_VEC);
     657          11 :   gel(y,1) = shifti(c,2);
     658          11 :   gel(y,2) = gmul2n(f,-1); return gc_upto(av, y);
     659             : }
     660             : 
     661             : GEN
     662          46 : coredisc0(GEN n,long flag) { return flag? coredisc2(n): coredisc(n); }
     663             : 
     664             : /* Write x = Df^2, where D = fundamental discriminant,
     665             :  * P^E = factorisation of conductor f */
     666             : GEN
     667       92702 : coredisc2_fact(GEN fa, long s, GEN *pP, GEN *pE)
     668             : {
     669       92702 :   GEN P, E, P0 = gel(fa,1), E0 = gel(fa,2), D = s > 0? gen_1: gen_m1;
     670       92702 :   long l = lg(P0), i, j;
     671             : 
     672       92702 :   E = cgetg(l, t_VECSMALL);
     673       92702 :   P = cgetg(l, t_VEC);
     674      351428 :   for (i = j = 1; i < l; i++)
     675             :   {
     676      258726 :     long e = itos(gel(E0,i));
     677      258726 :     GEN p = gel(P0,i);
     678      258726 :     if (odd(e)) D = mulii(D, p);
     679      258726 :     e >>= 1; if (e) { gel(P, j) = p; E[j] = e; j++; }
     680             :   }
     681       92702 :   if (Mod4(D) != 1)
     682             :   {
     683       28795 :     D = shifti(D, 2);
     684       28795 :     if (!--E[1])
     685             :     {
     686       24630 :       P[1] = P[0]; P++;
     687       24630 :       E[1] = E[0]; E++; j--;
     688             :     }
     689             :   }
     690       92702 :   setlg(P,j); *pP = P;
     691       92702 :   setlg(E,j); *pE = E; return D;
     692             : }
     693             : ulong
     694        5608 : coredisc2u_fact(GEN fa, long s, GEN *pP, GEN *pE)
     695             : {
     696        5608 :   GEN P, E, P0 = gel(fa,1), E0 = gel(fa,2);
     697        5608 :   ulong D = 1;
     698        5608 :   long i, j, l = lg(P0);
     699             : 
     700        5608 :   E = cgetg(l, t_VECSMALL);
     701        5608 :   P = cgetg(l, t_VECSMALL);
     702       16860 :   for (i = j = 1; i < l; i++)
     703             :   {
     704       11252 :     long e = E0[i], p = P0[i];
     705       11252 :     if (odd(e)) D *= p;
     706       11252 :     e >>= 1; if (e) { P[j] = p; E[j] = e; j++; }
     707             :   }
     708        5608 :   if ((D & 3) != (s > 0? 1: 3))
     709             :   {
     710        1223 :     D *= 4;
     711        1223 :     if (!--E[1])
     712             :     {
     713         887 :       P[1] = P[0]; P++;
     714         887 :       E[1] = E[0]; E++; j--;
     715             :     }
     716             :   }
     717        5608 :   setlg(P,j); *pP = P;
     718        5608 :   setlg(E,j); *pE = E; return D;
     719             : }
     720             : 
     721             : long
     722         597 : omegau(ulong n)
     723             : {
     724             :   pari_sp av;
     725         597 :   if (n == 1UL) return 0;
     726         587 :   av = avma; return gc_long(av, nbrows(factoru(n)));
     727             : }
     728             : long
     729        1155 : omega(GEN n)
     730             : {
     731             :   pari_sp av;
     732             :   GEN F, P;
     733        1155 :   if ((F = check_arith_non0(n,"omega"))) {
     734             :     long n;
     735         515 :     P = gel(F,1); n = lg(P)-1;
     736         515 :     if (n && equalim1(gel(P,1))) n--;
     737         515 :     return n;
     738             :   }
     739         630 :   if (lgefint(n) == 3) return omegau(n[2]);
     740          33 :   av = avma;
     741          33 :   F = absZ_factor(n);
     742          33 :   return gc_long(av, nbrows(F));
     743             : }
     744             : 
     745             : long
     746         613 : bigomegau(ulong n)
     747             : {
     748             :   pari_sp av;
     749         613 :   if (n == 1) return 0;
     750         603 :   av = avma; return gc_long(av, zv_sum(gel(factoru(n),2)));
     751             : }
     752             : long
     753        1155 : bigomega(GEN n)
     754             : {
     755        1155 :   pari_sp av = avma;
     756             :   GEN F, E;
     757        1155 :   if ((F = check_arith_non0(n,"bigomega")))
     758             :   {
     759         515 :     GEN P = gel(F,1);
     760         515 :     long n = lg(P)-1;
     761         515 :     E = gel(F,2);
     762         515 :     if (n && equalim1(gel(P,1))) E = vecslice(E,2,n);
     763             :   }
     764         630 :   else if (lgefint(n) == 3)
     765         601 :     return bigomegau(n[2]);
     766             :   else
     767          29 :     E = gel(absZ_factor(n), 2);
     768         544 :   E = ZV_to_zv(E);
     769         544 :   return gc_long(av, zv_sum(E));
     770             : }
     771             : 
     772             : /* assume f = factoru(n), possibly with 0 exponents. Return phi(n) */
     773             : ulong
     774      520350 : eulerphiu_fact(GEN f)
     775             : {
     776      520350 :   GEN P = gel(f,1), E = gel(f,2);
     777      520350 :   long i, m = 1, l = lg(P);
     778     1474846 :   for (i = 1; i < l; i++)
     779             :   {
     780      954496 :     ulong p = P[i], e = E[i];
     781      954496 :     if (!e) continue;
     782      954485 :     if (p == 2)
     783      275342 :     { if (e > 1) m <<= e-1; }
     784             :     else
     785             :     {
     786      679143 :       m *= (p-1);
     787      679143 :       if (e > 1) m *= upowuu(p, e-1);
     788             :     }
     789             :   }
     790      520350 :   return m;
     791             : }
     792             : ulong
     793      167857 : eulerphiu(ulong n)
     794             : {
     795             :   pari_sp av;
     796      167857 :   if (!n) return 2;
     797      167857 :   av = avma; return gc_long(av, eulerphiu_fact(factoru(n)));
     798             : }
     799             : GEN
     800      108566 : eulerphi(GEN n)
     801             : {
     802      108566 :   pari_sp av = avma;
     803             :   GEN Q, F, P, E;
     804             :   long i, l;
     805             : 
     806      108566 :   if ((F = check_arith_all(n,"eulerphi")))
     807             :   {
     808        2970 :     F = clean_Z_factor(F);
     809        2970 :     n = arith_n(n);
     810        2970 :     if (lgefint(n) == 3)
     811             :     {
     812             :       ulong e;
     813        2960 :       F = mkmat2(ZV_to_nv(gel(F,1)), ZV_to_nv(gel(F,2)));
     814        2960 :       e = eulerphiu_fact(F);
     815        2960 :       return gc_utoipos(av, e);
     816             :     }
     817             :   }
     818      105596 :   else if (lgefint(n) == 3) return utoipos(eulerphiu(uel(n,2)));
     819             :   else
     820          43 :     F = absZ_factor(n);
     821          53 :   if (!signe(n)) return gen_2;
     822          33 :   P = gel(F,1);
     823          33 :   E = gel(F,2); l = lg(P);
     824          33 :   Q = cgetg(l, t_VEC);
     825         216 :   for (i = 1; i < l; i++)
     826             :   {
     827         183 :     GEN p = gel(P,i), q;
     828         183 :     ulong v = itou(gel(E,i));
     829         183 :     q = subiu(p,1);
     830         183 :     if (v != 1) q = mulii(q, v == 2? p: powiu(p, v-1));
     831         183 :     gel(Q,i) = q;
     832             :   }
     833          33 :   return gc_INT(av, ZV_prod(Q));
     834             : }
     835             : 
     836             : long
     837     8248231 : numdivu_fact(GEN fa)
     838             : {
     839     8248231 :   GEN E = gel(fa,2);
     840     8248231 :   long n = 1, i, l = lg(E);
     841    27869206 :   for (i = 1; i < l; i++) n *= E[i]+1;
     842     8248231 :   return n;
     843             : }
     844             : long
     845         597 : numdivu(long N)
     846             : {
     847             :   pari_sp av;
     848         597 :   if (N == 1) return 1;
     849         587 :   av = avma; return gc_long(av, numdivu_fact(factoru(N)));
     850             : }
     851             : static GEN
     852         548 : numdiv_aux(GEN F)
     853             : {
     854         548 :   GEN x, E = gel(F,2);
     855         548 :   long i, l = lg(E);
     856         548 :   x = cgetg(l, t_VECSMALL);
     857        1521 :   for (i=1; i<l; i++) x[i] = itou(gel(E,i))+1;
     858         548 :   return x;
     859             : }
     860             : GEN
     861        1155 : numdiv(GEN n)
     862             : {
     863        1155 :   pari_sp av = avma;
     864             :   GEN F, E;
     865        1155 :   if ((F = check_arith_non0(n,"numdiv")))
     866             :   {
     867         515 :     F = clean_Z_factor(F);
     868         515 :     E = numdiv_aux(F);
     869             :   }
     870         630 :   else if (lgefint(n) == 3)
     871         597 :     return utoipos(numdivu(n[2]));
     872             :   else
     873          33 :     E = numdiv_aux(absZ_factor(n));
     874         548 :   return gc_INT(av, zv_prod_Z(E));
     875             : }
     876             : 
     877             : /* 1 + p + ... + p^v, p != 2^BIL - 1 */
     878             : static GEN
     879       61080 : u_euler_sumdiv(ulong p, long v)
     880             : {
     881       61080 :   GEN u = utoipos(1 + p); /* can't overflow */
     882       83760 :   for (; v > 1; v--) u = addui(1, mului(p, u));
     883       61080 :   return u;
     884             : }
     885             : /* 1 + q + ... + q^v */
     886             : static GEN
     887       15055 : euler_sumdiv(GEN q, long v)
     888             : {
     889       15055 :   GEN u = addui(1, q);
     890       20416 :   for (; v > 1; v--) u = addui(1, mulii(q, u));
     891       15055 :   return u;
     892             : }
     893             : 
     894             : static GEN
     895        1058 : sumdiv_aux(GEN F)
     896             : {
     897        1058 :   GEN x, P = gel(F,1), E = gel(F,2);
     898        1058 :   long i, l = lg(P);
     899        1058 :   x = cgetg(l, t_VEC);
     900        2816 :   for (i=1; i<l; i++) gel(x,i) = euler_sumdiv(gel(P,i), itou(gel(E,i)));
     901        1058 :   return ZV_prod(x);
     902             : }
     903             : GEN
     904        2175 : sumdiv(GEN n)
     905             : {
     906        2175 :   pari_sp av = avma;
     907             :   GEN F, v;
     908             : 
     909        2175 :   if ((F = check_arith_non0(n,"sumdiv")))
     910             :   {
     911        1030 :     F = clean_Z_factor(F);
     912        1030 :     v = sumdiv_aux(F);
     913             :   }
     914        1135 :   else if (lgefint(n) == 3)
     915             :   {
     916        1107 :     if (n[2] == 1) return gen_1;
     917        1087 :     F = factoru(n[2]);
     918        1087 :     v = usumdiv_fact(F);
     919             :   }
     920             :   else
     921          28 :     v = sumdiv_aux(absZ_factor(n));
     922        2145 :   return gc_INT(av, v);
     923             : }
     924             : 
     925             : static GEN
     926        1086 : sumdivk_aux(GEN F, long k)
     927             : {
     928        1086 :   GEN x, P = gel(F,1), E = gel(F,2);
     929        1086 :   long i, l = lg(P);
     930        1086 :   x = cgetg(l, t_VEC);
     931        3012 :   for (i=1; i<l; i++) gel(x,i) = euler_sumdiv(powiu(gel(P,i),k), gel(E,i)[2]);
     932        1086 :   return ZV_prod(x);
     933             : }
     934             : GEN
     935        6019 : sumdivk(GEN n, long k)
     936             : {
     937        6019 :   pari_sp av = avma;
     938             :   GEN F, v;
     939             :   long k1;
     940             : 
     941        6019 :   if (!k) return numdiv(n);
     942        6019 :   if (k == 1) return sumdiv(n);
     943        4864 :   if ((F = check_arith_non0(n,"sumdivk"))) F = clean_Z_factor(F);
     944        4834 :   k1 = k; if (k < 0)  k = -k;
     945        4834 :   if (k == 1)
     946        1020 :     v = sumdiv(F? F: n);
     947             :   else
     948             :   {
     949        3814 :     if (F)
     950        1030 :       v = sumdivk_aux(F,k);
     951        2784 :     else if (lgefint(n) == 3)
     952             :     {
     953        2728 :       if (n[2] == 1) return gen_1;
     954        2648 :       F = factoru(n[2]);
     955        2648 :       v = usumdivk_fact(F,k);
     956             :     }
     957             :     else
     958          56 :       v = sumdivk_aux(absZ_factor(n), k);
     959        3734 :     if (k1 > 0) return gc_INT(av, v);
     960             :   }
     961             : 
     962        1025 :   if (F) n = arith_n(n);
     963        1025 :   if (k != 1) n = powiu(n,k);
     964        1025 :   return gc_upto(av, gdiv(v, n));
     965             : }
     966             : 
     967             : GEN
     968       37207 : usumdiv_fact(GEN f)
     969             : {
     970       37207 :   GEN P = gel(f,1), E = gel(f,2);
     971       37207 :   long i, l = lg(P);
     972       37207 :   GEN v = cgetg(l, t_VEC);
     973       98287 :   for (i=1; i<l; i++) gel(v,i) = u_euler_sumdiv(P[i],E[i]);
     974       37207 :   return ZV_prod(v);
     975             : }
     976             : GEN
     977        8182 : usumdivk_fact(GEN f, ulong k)
     978             : {
     979        8182 :   GEN P = gel(f,1), E = gel(f,2);
     980        8182 :   long i, l = lg(P);
     981        8182 :   GEN v = cgetg(l, t_VEC);
     982       19553 :   for (i=1; i<l; i++) gel(v,i) = euler_sumdiv(powuu(P[i],k),E[i]);
     983        8182 :   return ZV_prod(v);
     984             : }
     985             : 
     986             : long
     987        2493 : uissquarefree_fact(GEN f)
     988             : {
     989        2493 :   GEN E = gel(f,2);
     990        2493 :   long i, l = lg(E);
     991        2493 :   if (l == 2) return umael(f,1,1)? E[1] == 1: 0; /* handle factor(0) */
     992        4977 :   for (i = 1; i < l; i++)
     993        3469 :     if (E[i] > 1) return 0;
     994        1508 :   return 1;
     995             : }
     996             : long
     997     2162572 : uissquarefree(ulong n)
     998             : {
     999     2162572 :   if (!n) return 0;
    1000     2162572 :   return moebiusu(n)? 1: 0;
    1001             : }
    1002             : long
    1003        2004 : Z_issquarefree(GEN n)
    1004             : {
    1005        2004 :   switch(lgefint(n))
    1006             :   {
    1007          12 :     case 2: return 0;
    1008        1219 :     case 3: return uissquarefree(n[2]);
    1009             :   }
    1010         773 :   return moebius(n)? 1: 0;
    1011             : }
    1012             : 
    1013             : long
    1014        2211 : Z_issquarefree_fact(GEN F)
    1015             : {
    1016        2211 :   GEN E = gel(F,2);
    1017        2211 :   long i, l = lg(E);
    1018        2211 :   if (l == 2) return signe(gcoeff(F,1,1))? equali1(gel(E,1)): 0;
    1019        4950 :   for(i = 1; i < l; i++)
    1020        3894 :     if (!equali1(gel(E,i))) return 0;
    1021        1056 :   return 1;
    1022             : }
    1023             : long
    1024        5468 : issquarefree(GEN x)
    1025             : {
    1026             :   pari_sp av;
    1027             :   GEN d;
    1028        5468 :   switch(typ(x))
    1029             :   {
    1030        1217 :     case t_INT: return Z_issquarefree(x);
    1031        3045 :     case t_POL:
    1032        3045 :       if (!signe(x)) return 0;
    1033        3045 :       av = avma; d = RgX_gcd(x, RgX_deriv(x));
    1034        3045 :       return gc_long(av, lg(d)==3);
    1035        1206 :     case t_VEC:
    1036        1206 :     case t_MAT: return Z_issquarefree_fact(check_arith_all(x,"issquarefree"));
    1037           0 :     default: pari_err_TYPE("issquarefree",x);
    1038             :       return 0; /* LCOV_EXCL_LINE */
    1039             :   }
    1040             : }

Generated by: LCOV version 1.16