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 - ramanujantau.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.18.1 lcov report (development 30702-bddb8d6928) Lines: 77 110 70.0 %
Date: 2026-02-23 02:23:56 Functions: 8 12 66.7 %
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             : #include "pari.h"
      15             : #include "paripriv.h"
      16             : 
      17             : /******************************************************************/
      18             : /*                                                                */
      19             : /*                 RAMANUJAN's TAU FUNCTION                       */
      20             : /*                                                                */
      21             : /******************************************************************/
      22             : /* 4|N > 0, not fundamental at 2; 6 * Hurwitz class number in level 2,
      23             :  * equal to 6*(H(N)+2H(N/4)), H=qfbhclassno */
      24             : static GEN
      25       26250 : Hspec(GEN N)
      26             : {
      27       26250 :   long v2 = Z_lvalrem(N, 2, &N), v2f = v2 >> 1;
      28             :   GEN t;
      29       26250 :   if (odd(v2)) { v2f--; N = shifti(N,3); }
      30       23255 :   else if (mod4(N)!=3) { v2f--; N = shifti(N,2); }
      31             :   /* N fundamental at 2, v2f = v2(f) s.t. N = f^2 D, D fundamental */
      32       26250 :   t = addui(3, muliu(subiu(int2n(v2f+1), 3), 2 - kroiu(N,2)));
      33       26250 :   return mulii(t, hclassno6(N));
      34             : }
      35             : 
      36             : static GEN
      37       54130 : tauprime_i(ulong t, GEN p2_7, GEN p_9, GEN p, ulong tin)
      38             : {
      39       54130 :   GEN h, a, t2 = sqru(t), D = shifti(subii(p, t2), 2); /* 4(p-t^2) */
      40             :   /* t mod 2 != tin <=> D not fundamental at 2 */
      41       54130 :   h = ((t&1UL) == tin)? hclassno6(D): Hspec(D);
      42       54130 :   a = mulii(powiu(t2,3), addii(p2_7, mulii(t2, subii(shifti(t2,2), p_9))));
      43       54130 :   return mulii(a, h);
      44             : }
      45             : GEN
      46           0 : ramanujantau_worker(GEN T, GEN p2_7, GEN p_9, GEN p)
      47             : {
      48           0 :   ulong tin = mod4(p) == 3? 1: 0;
      49           0 :   long i, l = lg(T);
      50           0 :   GEN s = gen_0;
      51           0 :   for (i = 1; i < l; i++) s = addii(s, tauprime_i(T[i], p2_7, p_9, p, tin));
      52           0 :   return s;
      53             : }
      54             : 
      55             : /* B <- {a + k * m : k = 0, ..., (b-a)/m)} */
      56             : static void
      57           0 : arithprogset(GEN B, ulong a, ulong b, ulong m)
      58             : {
      59             :   long k;
      60           0 :   for (k = 1; a <= b; a += m, k++) B[k] = a;
      61           0 :   setlg(B, k);
      62           0 : }
      63             : /* sum_{1 <= t <= N} f(t), f has integer values */
      64             : static GEN
      65           0 : parsum_u(ulong N, GEN worker)
      66             : {
      67           0 :   long a, r, pending = 0, m = usqrt(N);
      68             :   struct pari_mt pt;
      69           0 :   GEN v, s = gen_0;
      70             :   pari_sp av;
      71             : 
      72           0 :   mt_queue_start_lim(&pt, worker, m);
      73           0 :   v = mkvec(cgetg(m + 2, t_VECSMALL)); av = avma;
      74           0 :   for (r = 1, a = 1; r <= m || pending; r++)
      75             :   {
      76             :     long workid;
      77             :     GEN done;
      78           0 :     if (r <= m) { arithprogset(gel(v,1), a, N, m); a++; }
      79           0 :     mt_queue_submit(&pt, 0, r <= m? v: NULL);
      80           0 :     done = mt_queue_get(&pt, &workid, &pending);
      81           0 :     if (done) s = gc_INT(av, addii(s, done));
      82             :   }
      83           0 :   mt_queue_end(&pt); return s;
      84             : }
      85             : 
      86             : static int
      87        8160 : tau_parallel(GEN n) { return mt_nbthreads() > 1 && expi(n) > 18; }
      88             : 
      89             : /* Ramanujan tau function for p prime */
      90             : static GEN
      91       10645 : tauprime(GEN p)
      92             : {
      93       10645 :   pari_sp av = avma;
      94             :   GEN s, p2, p2_7, p_9, T;
      95             :   ulong lim;
      96             : 
      97       10645 :   if (absequaliu(p, 2)) return utoineg(24);
      98             :   /* p > 2 */
      99        8140 :   p2 = sqri(p); p2_7 = mului(7, p2); p_9 = mului(9, p);
     100        8140 :   lim = itou(sqrtint(p));
     101        8140 :   if (tau_parallel(p))
     102             :   {
     103           0 :     GEN worker = snm_closure(is_entry("_ramanujantau_worker"),
     104             :                              mkvec3(p2_7, p_9, p));
     105           0 :     s = parsum_u(lim, worker);
     106             :   }
     107             :   else
     108             :   {
     109        8140 :     pari_sp av2 = avma;
     110        8140 :     ulong tin = mod4(p) == 3? 1: 0, t;
     111        8140 :     s = gen_0;
     112       62270 :     for (t = 1; t <= lim; t++)
     113             :     {
     114       54130 :       s = addii(s, tauprime_i(t, p2_7, p_9, p, tin));
     115       54130 :       if (!(t & 255)) s = gc_INT(av2, s);
     116             :     }
     117             :   }
     118             :   /* 28p^3 - 28p^2 - 90p - 35 */
     119        8140 :   T = subii(shifti(mulii(p2_7, subiu(p,1)), 2), addiu(mului(90,p), 35));
     120        8140 :   s = shifti(diviuexact(s, 3), 6);
     121        8140 :   return gc_INT(av, subii(mulii(mulii(p2, p), T), addui(1, s)));
     122             : }
     123             : 
     124             : static GEN
     125       40445 : taugen_n_i(ulong t, GEN G, GEN n4)
     126             : {
     127       40445 :   GEN t2 = sqru(t);
     128       40445 :   return mulii(mfrhopol_eval(G, t2), hclassno6(subii(n4, t2)));
     129             : }
     130             : GEN
     131           0 : taugen_n_worker(GEN T, GEN G, GEN n4)
     132             : {
     133           0 :   long i, l = lg(T);
     134           0 :   GEN s = gen_0;
     135           0 :   for (i = 1; i < l; i++) s = addii(s, taugen_n_i(T[i], G, n4));
     136           0 :   return s;
     137             : }
     138             : 
     139             : static GEN
     140          20 : taugen_n(GEN n, GEN G)
     141             : {
     142          20 :   GEN S, r, n4 = shifti(n, 2);
     143          20 :   ulong t, lim = itou(sqrtremi(n4, &r));
     144             : 
     145          20 :   if (r == gen_0) lim--;
     146          20 :   G = ZX_unscale(G, n);
     147          20 :   if (tau_parallel(n))
     148             :   {
     149           0 :     GEN worker = snm_closure(is_entry("_taugen_n_worker"), mkvec2(G, n4));
     150           0 :     S = parsum_u(lim, worker);
     151             :   }
     152             :   else
     153             :   {
     154          20 :     pari_sp av2 = avma;
     155          20 :     S = gen_0;
     156       40465 :     for (t = 1; t <= lim; t++)
     157             :     {
     158       40445 :       S = addii(S, taugen_n_i(t, G, n4));
     159       40445 :       if (!(t & 255)) S = gc_INT(av2, S);
     160             :     }
     161             :   }
     162          20 :   S = addii(shifti(S,1), mulii(leading_coeff(G), hclassno6(n4)));
     163          20 :   return gdivgu(S, 12);
     164             : }
     165             : 
     166             : /* ell != 12 */
     167             : static GEN
     168          10 : newtrace(GEN fan, GEN n, long ell)
     169             : {
     170          10 :   pari_sp av = avma;
     171          10 :   GEN D = divisors(fan), G = mfrhopol(ell-2), T = taugen_n(n, G);
     172          10 :   long i, l = lg(D);
     173             : 
     174          30 :   for (i = 1; i < l; i++)
     175             :   {
     176          30 :     GEN d = gel(D, i), q;
     177          30 :     long c = cmpii(sqri(d), n);
     178          30 :     if (c > 0) break;
     179          20 :     q = powiu(d, ell-1);
     180          20 :     if (c < 0) T = gadd(T, q);
     181             :     else /* d^2 = n */
     182             :     {
     183           0 :       T = gadd(T, gmul2n(q, -1));
     184           0 :       T = gsub(T, gdivgu(mulii(diviiexact(q,d), mfrhopol_eval(G, utoipos(4))), 12));
     185           0 :       break;
     186             :     }
     187             :   }
     188          10 :   return gc_INT(av, negi(T));
     189             : }
     190             : 
     191             : #ifdef DEBUG
     192             : static void
     193             : checkellcong(GEN T, GEN n, long ell)
     194             : {
     195             :   long V[] = { 0, 691, 0, 3617, 43867, 283*617, 131*593, 0, 657931 };
     196             :   if (typ(T) != t_INT
     197             :       || umodiu(subii(T, sumdivk(n, ell-1)), V[ell / 2 - 5]))
     198             :     pari_err_BUG("ramanujantau");
     199             : }
     200             : #endif
     201             : 
     202             : /* Ramanujan tau function for weights ell = 12, 16, 18, 20, 22, 26,
     203             :  * return 0 for <= 0 */
     204             : GEN
     205        5050 : ramanujantau(GEN n, long ell)
     206             : {
     207        5050 :   pari_sp av = avma;
     208        5050 :   GEN T, P, E, G, F = check_arith_all(n, "ramanujantau");
     209             :   long j, lP;
     210             : 
     211        5045 :   if (ell < 12 || ell == 14 || odd(ell)) return gen_0;
     212        5045 :   if (!F)
     213             :   {
     214        5020 :     if (signe(n) <= 0) return gen_0;
     215        5015 :     F = Z_factor(n); P = gel(F,1);
     216             :   }
     217             :   else
     218             :   {
     219          25 :     P = gel(F,1);
     220          25 :     if (lg(P) == 1 || signe(gel(P,1)) <= 0) return gen_0;
     221          10 :     n = typ(n) == t_VEC? gel(n,1): NULL;
     222             :   }
     223        5025 :   if (ell > 26 || ell == 24) return newtrace(F, n? n: factorback(F), ell);
     224             :   /* dimension 1: tau is multiplicative */
     225        5015 :   E = gel(F,2); lP = lg(P); T = gen_1;
     226        5015 :   G = ell == 12? NULL: mfrhopol(ell - 2);
     227       15670 :   for (j = 1; j < lP; j++)
     228             :   {
     229       10655 :     GEN p = gel(P,j), q = powiu(p, ell-1), t, t1, t0 = gen_1;
     230       10655 :     long k, e = itou(gel(E,j));
     231          10 :     t1 = t = G? subsi(-1, taugen_n(p, G))
     232       10655 :               : tauprime(p);
     233       14410 :     for (k = 1; k < e; k++)
     234             :     {
     235        3755 :       GEN t2 = subii(mulii(t, t1), mulii(q, t0));
     236        3755 :       t0 = t1; t1 = t2;
     237             :     }
     238       10655 :     T = mulii(T, t1);
     239             :   }
     240             : #ifdef DEBUG
     241             :   checkellcong(T, n, ell);
     242             : #endif
     243        5015 :   return gc_INT(av, T);
     244             : }

Generated by: LCOV version 1.16