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 - alglin3.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.18.1 lcov report (development 30702-bddb8d6928) Lines: 522 597 87.4 %
Date: 2026-02-23 02:23:56 Functions: 50 57 87.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Copyright (C) 2012  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             : /**                                                                **/
      17             : /**                         LINEAR ALGEBRA                         **/
      18             : /**                          (third part)                          **/
      19             : /**                                                                **/
      20             : /********************************************************************/
      21             : #include "pari.h"
      22             : #include "paripriv.h"
      23             : 
      24             : #define DEBUGLEVEL DEBUGLEVEL_mat
      25             : 
      26             : /*******************************************************************/
      27             : /*                                                                 */
      28             : /*                               SUM                               */
      29             : /*                                                                 */
      30             : /*******************************************************************/
      31             : 
      32             : GEN
      33      127698 : vecsum(GEN v)
      34             : {
      35      127698 :   pari_sp av = avma;
      36             :   long i, l;
      37             :   GEN p;
      38      127698 :   if (!is_vec_t(typ(v)))
      39           6 :     pari_err_TYPE("vecsum", v);
      40      127692 :   l = lg(v);
      41      127692 :   if (l == 1) return gen_0;
      42      127686 :   p = gel(v,1);
      43      127686 :   if (l == 2) return gcopy(p);
      44      212438 :   for (i=2; i<l; i++)
      45             :   {
      46      143591 :     p = gadd(p, gel(v,i));
      47      143591 :     if (gc_needed(av, 2))
      48             :     {
      49           0 :       if (DEBUGMEM>1) pari_warn(warnmem,"sum");
      50           0 :       p = gc_upto(av, p);
      51             :     }
      52             :   }
      53       68847 :   return gc_upto(av, p);
      54             : }
      55             : 
      56             : /*******************************************************************/
      57             : /*                                                                 */
      58             : /*                         TRANSPOSE                               */
      59             : /*                                                                 */
      60             : /*******************************************************************/
      61             : /* A[x0,]~ */
      62             : static GEN
      63    22004840 : row_transpose(GEN A, long x0)
      64             : {
      65    22004840 :   long i, lB = lg(A);
      66    22004840 :   GEN B  = cgetg(lB, t_COL);
      67   169633187 :   for (i=1; i<lB; i++) gel(B, i) = gcoeff(A, x0, i);
      68    22004840 :   return B;
      69             : }
      70             : static GEN
      71       13701 : row_transposecopy(GEN A, long x0)
      72             : {
      73       13701 :   long i, lB = lg(A);
      74       13701 :   GEN B  = cgetg(lB, t_COL);
      75      120306 :   for (i=1; i<lB; i++) gel(B, i) = gcopy(gcoeff(A, x0, i));
      76       13701 :   return B;
      77             : }
      78             : 
      79             : /* No copy*/
      80             : GEN
      81     5999275 : shallowtrans(GEN x)
      82             : {
      83             :   long i, dx, lx;
      84             :   GEN y;
      85     5999275 :   switch(typ(x))
      86             :   {
      87        1079 :     case t_VEC: y = leafcopy(x); settyp(y,t_COL); break;
      88         135 :     case t_COL: y = leafcopy(x); settyp(y,t_VEC); break;
      89     5998061 :     case t_MAT:
      90     5998061 :       lx = lg(x); if (lx==1) return cgetg(1,t_MAT);
      91     5996939 :       dx = lgcols(x); y = cgetg(dx,t_MAT);
      92    28001779 :       for (i = 1; i < dx; i++) gel(y,i) = row_transpose(x,i);
      93     5996939 :       break;
      94           0 :     default: pari_err_TYPE("shallowtrans",x);
      95             :       return NULL;/*LCOV_EXCL_LINE*/
      96             :   }
      97     5998153 :   return y;
      98             : }
      99             : 
     100             : GEN
     101       36625 : gtrans(GEN x)
     102             : {
     103             :   long i, dx, lx;
     104             :   GEN y;
     105       36625 :   switch(typ(x))
     106             :   {
     107       31614 :     case t_VEC: y = gcopy(x); settyp(y,t_COL); break;
     108        3573 :     case t_COL: y = gcopy(x); settyp(y,t_VEC); break;
     109        1432 :     case t_MAT:
     110        1432 :       lx = lg(x); if (lx==1) return cgetg(1,t_MAT);
     111        1426 :       dx = lgcols(x); y = cgetg(dx,t_MAT);
     112       15127 :       for (i = 1; i < dx; i++) gel(y,i) = row_transposecopy(x,i);
     113        1426 :       break;
     114           6 :     default: pari_err_TYPE("gtrans",x);
     115             :       return NULL;/*LCOV_EXCL_LINE*/
     116             :   }
     117       36613 :   return y;
     118             : }
     119             : 
     120             : /*******************************************************************/
     121             : /*                                                                 */
     122             : /*                           EXTRACTION                            */
     123             : /*                                                                 */
     124             : /*******************************************************************/
     125             : 
     126             : static long
     127         156 : str_to_long(char *s, char **pt)
     128             : {
     129         156 :   long a = atol(s);
     130         156 :   while (isspace((unsigned char)*s)) s++;
     131         156 :   if (*s == '-' || *s == '+') s++;
     132         330 :   while (isdigit((unsigned char)*s) || isspace((unsigned char)*s)) s++;
     133         156 :   *pt = s; return a;
     134             : }
     135             : 
     136             : static int
     137          96 : get_range(char *s, long *a, long *b, long *cmpl, long lx)
     138             : {
     139          96 :   long max = lx - 1;
     140             : 
     141          96 :   *a = 1; *b = max;
     142          96 :   if (*s == '^') { *cmpl = 1; s++; } else *cmpl = 0;
     143          96 :   if (!*s) return 0;
     144          96 :   if (*s != '.')
     145             :   {
     146          90 :     *a = str_to_long(s, &s);
     147          90 :     if (*a < 0) *a += lx;
     148          90 :     if (*a<1 || *a>max) return 0;
     149             :   }
     150          96 :   if (*s == '.')
     151             :   {
     152          90 :     s++; if (*s != '.') return 0;
     153          90 :     do s++; while (isspace((unsigned char)*s));
     154          90 :     if (*s)
     155             :     {
     156          66 :       *b = str_to_long(s, &s);
     157          66 :       if (*b < 0) *b += lx;
     158          66 :       if (*b<1 || *b>max || *s) return 0;
     159             :     }
     160          84 :     return 1;
     161             :   }
     162           6 :   if (*s) return 0;
     163           6 :   *b = *a; return 1;
     164             : }
     165             : 
     166             : static int
     167          30 : extract_selector_ok(long lx, GEN L)
     168             : {
     169             :   long i, l;
     170          30 :   switch (typ(L))
     171             :   {
     172           6 :     case t_INT: {
     173             :       long maxj;
     174           6 :       if (!signe(L)) return 1;
     175           6 :       l = lgefint(L)-1;
     176           6 :       maxj = BITS_IN_LONG - bfffo(*int_MSW(L));
     177           6 :       return ((l-2) * BITS_IN_LONG + maxj < lx);
     178             :     }
     179           6 :     case t_STR: {
     180             :       long first, last, cmpl;
     181           6 :       return get_range(GSTR(L), &first, &last, &cmpl, lx);
     182             :     }
     183          12 :     case t_VEC: case t_COL:
     184          12 :       l = lg(L);
     185          24 :       for (i=1; i<l; i++)
     186             :       {
     187          18 :         long j = itos(gel(L,i));
     188          18 :         if (j>=lx || j<=0) return 0;
     189             :       }
     190           6 :       return 1;
     191           6 :     case t_VECSMALL:
     192           6 :       l = lg(L);
     193          18 :       for (i=1; i<l; i++)
     194             :       {
     195          12 :         long j = L[i];
     196          12 :         if (j>=lx || j<=0) return 0;
     197             :       }
     198           6 :       return 1;
     199             :   }
     200           0 :   return 0;
     201             : }
     202             : 
     203             : GEN
     204       11327 : shallowmatextract(GEN x, GEN l1, GEN l2)
     205             : {
     206       11327 :   long i, j, n1 = lg(l1), n2 = lg(l2);
     207       11327 :   GEN M = cgetg(n2, t_MAT);
     208       65860 :   for(i=1; i < n2; i++)
     209             :   {
     210       54533 :     long ii = l2[i];
     211       54533 :     GEN C = cgetg(n1, t_COL);
     212      880150 :     for (j=1; j < n1; j++)
     213             :     {
     214      825617 :       long jj = l1[j];
     215      825617 :       gel(C, j) = gmael(x, ii, jj);
     216             :     }
     217       54533 :     gel(M, i) = C;
     218             :   }
     219       11327 :   return M;
     220             : }
     221             : 
     222             : GEN
     223       45057 : shallowextract(GEN x, GEN L)
     224             : {
     225       45057 :   long i,j, tl = typ(L), tx = typ(x), lx = lg(x);
     226             :   GEN y;
     227             : 
     228       45057 :   switch(tx)
     229             :   {
     230       45051 :     case t_VEC:
     231             :     case t_COL:
     232             :     case t_MAT:
     233       45051 :     case t_VECSMALL: break;
     234           6 :     default: pari_err_TYPE("extract",x);
     235             : 
     236             :   }
     237       45051 :   if (tl==t_INT)
     238             :   { /* extract components of x as per the bits of mask L */
     239             :     long k, l, ix, iy, maxj;
     240             :     GEN Ld;
     241        2862 :     if (!signe(L)) return cgetg(1,tx);
     242        2856 :     y = new_chunk(lx);
     243        2856 :     l = lgefint(L)-1; ix = iy = 1;
     244        2856 :     maxj = BITS_IN_LONG - bfffo(*int_MSW(L));
     245        2856 :     if ((l-2) * BITS_IN_LONG + maxj >= lx)
     246           6 :       pari_err_TYPE("vecextract [mask too large]", L);
     247        3207 :     for (k = 2, Ld = int_LSW(L); k < l; k++, Ld = int_nextW(Ld))
     248             :     {
     249         357 :       ulong B = *Ld;
     250       18981 :       for (j = 0; j < BITS_IN_LONG; j++, B >>= 1, ix++)
     251       18624 :         if (B & 1) y[iy++] = x[ix];
     252             :     }
     253             :     { /* k = l */
     254        2850 :       ulong B = *Ld;
     255       25008 :       for (j = 0; j < maxj; j++, B >>= 1, ix++)
     256       22158 :         if (B & 1) y[iy++] = x[ix];
     257             :     }
     258        2850 :     y[0] = evaltyp(tx) | evallg(iy);
     259        2850 :     return y;
     260             :   }
     261       42189 :   if (tl==t_STR)
     262             :   {
     263          90 :     char *s = GSTR(L);
     264             :     long first, last, cmpl, d;
     265          90 :     if (! get_range(s, &first, &last, &cmpl, lx))
     266           6 :       pari_err_TYPE("vecextract [incorrect range]", L);
     267          84 :     if (lx == 1) return cgetg(1,tx);
     268          84 :     d = last - first;
     269          84 :     if (cmpl)
     270             :     {
     271          18 :       if (d >= 0)
     272             :       {
     273          12 :         y = cgetg(lx - (1+d),tx);
     274         402 :         for (j=1; j<first; j++) gel(y,j) = gel(x,j);
     275         228 :         for (i=last+1; i<lx; i++,j++) gel(y,j) = gel(x,i);
     276             :       }
     277             :       else
     278             :       {
     279           6 :         y = cgetg(lx - (1-d),tx);
     280          12 :         for (j=1,i=lx-1; i>first; i--,j++) gel(y,j) = gel(x,i);
     281          12 :         for (i=last-1; i>0; i--,j++) gel(y,j) = gel(x,i);
     282             :       }
     283             :     }
     284             :     else
     285             :     {
     286          66 :       if (d >= 0)
     287             :       {
     288          30 :         y = cgetg(d+2,tx);
     289          96 :         for (i=first,j=1; i<=last; i++,j++) gel(y,j) = gel(x,i);
     290             :       }
     291             :       else
     292             :       {
     293          36 :         y = cgetg(2-d,tx);
     294         174 :         for (i=first,j=1; i>=last; i--,j++) gel(y,j) = gel(x,i);
     295             :       }
     296             :     }
     297          84 :     return y;
     298             :   }
     299             : 
     300       42099 :   if (is_vec_t(tl))
     301             :   {
     302          66 :     long ll=lg(L); y=cgetg(ll,tx);
     303         168 :     for (i=1; i<ll; i++)
     304             :     {
     305         114 :       j = itos(gel(L,i));
     306         114 :       if (j<=0) pari_err_COMPONENT("vecextract","<=",gen_0,stoi(j));
     307         108 :       if (j>=lx) pari_err_COMPONENT("vecextract",">=",stoi(lx),stoi(j));
     308         102 :       gel(y,i) = gel(x,j);
     309             :     }
     310          54 :     return y;
     311             :   }
     312       42033 :   if (tl == t_VECSMALL)
     313             :   {
     314       42027 :     long ll=lg(L); y=cgetg(ll,tx);
     315      178595 :     for (i=1; i<ll; i++)
     316             :     {
     317      136568 :       j = L[i];
     318      136568 :       if (j<=0) pari_err_COMPONENT("vecextract","<=",gen_0,stoi(j));
     319      136568 :       if (j>=lx) pari_err_COMPONENT("vecextract",">=",stoi(lx),stoi(j));
     320      136568 :       gel(y,i) = gel(x,j);
     321             :     }
     322       42027 :     return y;
     323             :   }
     324           6 :   pari_err_TYPE("vecextract [mask]", L);
     325             :   return NULL; /* LCOV_EXCL_LINE */
     326             : }
     327             : 
     328             : /* does the component selector l select 0 component ? */
     329             : static int
     330          73 : select_0(GEN l)
     331             : {
     332          73 :   switch(typ(l))
     333             :   {
     334          12 :     case t_INT:
     335          12 :       return (!signe(l));
     336          43 :     case t_VEC: case t_COL: case t_VECSMALL:
     337          43 :       return (lg(l) == 1);
     338             :   }
     339          18 :   return 0;
     340             : }
     341             : 
     342             : GEN
     343       34146 : extract0(GEN x, GEN l1, GEN l2)
     344             : {
     345       34146 :   pari_sp av = avma, av2;
     346             :   GEN y;
     347       34146 :   if (! l2)
     348             :   {
     349       34073 :     y = shallowextract(x, l1);
     350       34037 :     if (lg(y) == 1 || typ(y) == t_VECSMALL) return y;
     351       34031 :     av2 = avma;
     352       34031 :     y = gcopy(y);
     353             :   }
     354             :   else
     355             :   {
     356          73 :     if (typ(x) != t_MAT) pari_err_TYPE("extract",x);
     357          73 :     y = shallowextract(x,l2);
     358          73 :     if (select_0(l1)) { set_avma(av); return zeromat(0, lg(y)-1); }
     359          61 :     if (lg(y) == 1 && lg(x) > 1)
     360             :     {
     361          30 :       if (!extract_selector_ok(lgcols(x), l1))
     362           6 :         pari_err_TYPE("vecextract [incorrect mask]", l1);
     363          24 :       retgc_const(av, cgetg(1, t_MAT));
     364             :     }
     365          31 :     y = shallowextract(shallowtrans(y), l1);
     366          31 :     av2 = avma;
     367          31 :     y = gtrans(y);
     368             :   }
     369       34062 :   stackdummy(av, av2);
     370       34062 :   return y;
     371             : }
     372             : 
     373             : static long
     374        1691 : vecslice_parse_arg(long lA, long *y1, long *y2, long *skip)
     375             : {
     376        1691 :   *skip=0;
     377        1691 :   if (*y1==LONG_MAX)
     378             :   {
     379         199 :     if (*y2!=LONG_MAX)
     380             :     {
     381         108 :       if (*y2<0) *y2 += lA;
     382         108 :       if (*y2<0 || *y2==LONG_MAX || *y2>=lA)
     383           0 :         pari_err_DIM("_[..]");
     384         108 :       *skip=*y2;
     385             :     }
     386         199 :     *y1 = 1; *y2 = lA-1;
     387             :   }
     388        1492 :   else if (*y2==LONG_MAX) *y2 = *y1;
     389        1691 :   if (*y1<=0) *y1 += lA;
     390        1691 :   if (*y2<0) *y2 += lA;
     391        1691 :   if (*y1<=0 || *y1>*y2+1 || *y2>=lA) pari_err_DIM("_[..]");
     392        1679 :   return *y2 - *y1 + 2 - !!*skip;
     393             : }
     394             : 
     395             : static GEN
     396        2229 : vecslice_i(GEN A, long t, long lB, long y1, long skip)
     397             : {
     398        2229 :   GEN B = cgetg(lB, t);
     399             :   long i;
     400       23220 :   for (i=1; i<lB; i++, y1++)
     401             :   {
     402       20991 :     if (y1 == skip) { i--; continue; }
     403       20883 :     gel(B,i) = gcopy(gel(A,y1));
     404             :   }
     405        2229 :   return B;
     406             : }
     407             : 
     408             : static GEN
     409          10 : rowslice_i(GEN A, long lB, long x1, long y1, long skip)
     410             : {
     411          10 :   GEN B = cgetg(lB, t_VEC);
     412             :   long i;
     413          55 :   for (i=1; i<lB; i++, y1++)
     414             :   {
     415          45 :     if (y1 == skip) { i--; continue; }
     416          40 :     gel(B,i) = gcopy(gcoeff(A,x1,y1));
     417             :   }
     418          10 :   return B;
     419             : }
     420             : 
     421             : static GEN
     422           0 : rowsmallslice_i(GEN A, long lB, long x1, long y1, long skip)
     423             : {
     424           0 :   GEN B = cgetg(lB, t_VECSMALL);
     425             :   long i;
     426           0 :   for (i=1; i<lB; i++, y1++)
     427             :   {
     428           0 :     if (y1 == skip) { i--; continue; }
     429           0 :     B[i] = coeff(A,x1,y1);
     430             :   }
     431           0 :   return B;
     432             : }
     433             : 
     434             : static GEN
     435          20 : vecsmallslice_i(GEN A, long t, long lB, long y1, long skip)
     436             : {
     437          20 :   GEN B = cgetg(lB, t);
     438             :   long i;
     439          90 :   for (i=1; i<lB; i++, y1++)
     440             :   {
     441          70 :     if (y1 == skip) { i--; continue; }
     442          65 :     B[i] = A[y1];
     443             :   }
     444          20 :   return B;
     445             : }
     446             : GEN
     447        1383 : vecslice0(GEN A, long y1, long y2)
     448             : {
     449        1383 :   long skip, lB, t = typ(A);
     450        1383 :   switch(t)
     451             :   {
     452        1312 :     case t_VEC: case t_COL:
     453        1312 :       lB = vecslice_parse_arg(lg(A), &y1, &y2, &skip);
     454        1300 :       return vecslice_i(A, t,lB,y1,skip);
     455          20 :     case t_VECSMALL:
     456          20 :       lB = vecslice_parse_arg(lg(A), &y1, &y2, &skip);
     457          20 :       return vecsmallslice_i(A, t,lB,y1,skip);
     458          45 :     case t_LIST:
     459          45 :       if (list_typ(A) == t_LIST_RAW)
     460             :       {
     461          45 :         GEN y, z = list_data(A);
     462          45 :         long l = z? lg(z): 1;
     463          45 :         lB = vecslice_parse_arg(l, &y1, &y2, &skip);
     464          45 :         y = mklist(); if (!z) return y;
     465          45 :         list_data(y) = vecslice_i(z, t_VEC,lB,y1,skip);
     466          45 :         return y;
     467             :       }
     468             :     default:
     469           6 :       pari_err_TYPE("_[_.._]",A);
     470             :       return NULL;/*LCOV_EXCL_LINE*/
     471             :   }
     472             : }
     473             : 
     474             : GEN
     475         162 : matslice0(GEN A, long x1, long x2, long y1, long y2)
     476             : {
     477             :   GEN B;
     478         162 :   long i, lB, lA = lg(A), rA, t, skip, rskip, rlB;
     479         162 :   long is_col = y1!=LONG_MAX && y2==LONG_MAX;
     480         162 :   long is_row = x1!=LONG_MAX && x2==LONG_MAX;
     481             :   GEN (*slice)(GEN A, long t, long lB, long y1, long skip);
     482         162 :   if (typ(A)!=t_MAT) pari_err_TYPE("_[_.._,_.._]",A);
     483         162 :   lB = vecslice_parse_arg(lA, &y1, &y2, &skip);
     484         162 :   if (is_col) return vecslice0(gel(A, y1), x1, x2);
     485         152 :   rA = lg(A)==1 ? 1: lgcols(A);
     486         152 :   rlB = vecslice_parse_arg(rA, &x1, &x2, &rskip);
     487         152 :   t = lg(A)==1 ? t_COL: typ(gel(A,1));
     488         152 :   if (is_row) return t == t_COL ? rowslice_i(A, lB, x1, y1, skip):
     489           0 :                                   rowsmallslice_i(A, lB, x1, y1, skip);
     490         142 :   slice = t == t_COL? &vecslice_i: &vecsmallslice_i;
     491             : 
     492         142 :   B = cgetg(lB, t_MAT);
     493        1036 :   for (i=1; i<lB; i++, y1++)
     494             :   {
     495         894 :     if (y1 == skip) { i--; continue; }
     496         884 :     gel(B,i) = slice(gel(A,y1),t,rlB, x1, rskip);
     497             :   }
     498         142 :   return B;
     499             : }
     500             : 
     501             : GEN
     502        9119 : vecrange(GEN a, GEN b)
     503             : {
     504             :   GEN y;
     505             :   long i, l;
     506        9119 :   if (typ(a)!=t_INT) pari_err_TYPE("[_.._]",a);
     507        9113 :   if (typ(b)!=t_INT) pari_err_TYPE("[_.._]",b);
     508        9107 :   if (cmpii(a,b)>0) return cgetg(1,t_VEC);
     509        9102 :   l = itos(subii(b,a))+1;
     510        9102 :   a = setloop(a);
     511        9102 :   y = cgetg(l+1, t_VEC);
     512    18802132 :   for (i=1; i<=l; a = incloop(a), i++) gel(y,i) = icopy(a);
     513        9102 :   return y;
     514             : }
     515             : 
     516             : GEN
     517           0 : vecrangess(long a, long b)
     518             : {
     519             :   GEN y;
     520             :   long i, l;
     521           0 :   if (a>b) return cgetg(1,t_VEC);
     522           0 :   l = b-a+1;
     523           0 :   y = cgetg(l+1, t_VEC);
     524           0 :   for (i=1; i<=l; a++, i++) gel(y,i) = stoi(a);
     525           0 :   return y;
     526             : }
     527             : 
     528             : GEN
     529          77 : genindexselect(void *E, long (*f)(void* E, GEN x), GEN A)
     530             : {
     531             :   long l, i, lv;
     532             :   GEN v, z;
     533             :   pari_sp av;
     534          77 :   switch(typ(A))
     535             :   {
     536          11 :     case t_LIST:
     537          11 :       z = list_data(A);
     538          11 :       l = z? lg(z): 1;
     539          11 :       if (list_typ(A)==t_LIST_MAP)
     540             :       {
     541           6 :         av = avma;
     542           6 :         return gc_GEN(av, mapselect_shallow(E, f, A));
     543             :       }
     544           5 :       break;
     545          61 :     case t_VEC: case t_COL: case t_MAT:
     546          61 :       l = lg(A);
     547          61 :       z = A;
     548          61 :       break;
     549           5 :     default:
     550           5 :       pari_err_TYPE("select",A);
     551             :       return NULL;/*LCOV_EXCL_LINE*/
     552             :   }
     553          66 :   v = cgetg(l, t_VECSMALL);
     554          66 :   av = avma;
     555          66 :   clone_lock(A);
     556         657 :   for (i = lv = 1; i < l; i++) {
     557         591 :     if (f(E, gel(z,i))) v[lv++] = i;
     558         591 :     set_avma(av);
     559             :   }
     560          66 :   clone_unlock_deep(A); fixlg(v, lv); return v;
     561             : }
     562             : static GEN
     563          61 : extract_copy(GEN A, GEN v)
     564             : {
     565          61 :   long i, l = lg(v);
     566          61 :   GEN B = cgetg(l, typ(A));
     567         268 :   for (i = 1; i < l; i++) gel(B,i) = gcopy(gel(A,v[i]));
     568          61 :   return B;
     569             : }
     570             : /* as genselect, but treat A [ t_VEC,t_COL, or t_MAT] as a t_VEC */
     571             : GEN
     572           0 : vecselect(void *E, long (*f)(void* E, GEN x), GEN A)
     573             : {
     574             :   GEN v;
     575           0 :   clone_lock(A);
     576           0 :   v = genindexselect(E, f, A);
     577           0 :   A = extract_copy(A, v); settyp(A, t_VEC);
     578           0 :   clone_unlock_deep(A); return A;
     579             : }
     580             : GEN
     581          78 : genselect(void *E, long (*f)(void* E, GEN x), GEN A)
     582             : {
     583          78 :   pari_sp av  = avma;
     584             :   GEN y, z, v;/* v left on stack for efficiency */
     585          78 :   clone_lock(A);
     586          78 :   switch(typ(A))
     587             :   {
     588          28 :     case t_LIST:
     589          28 :       z = list_data(A);
     590          28 :       if (!z) y = mklist();
     591             :       else
     592             :       {
     593          28 :         if (list_typ(A)==t_LIST_MAP)
     594             :         {
     595          12 :           long i, l = z? lg(z): 1, lv=1;
     596          12 :           GEN v1 = cgetg(l, t_COL);
     597          12 :           GEN v2 = cgetg(l, t_COL);
     598          48 :           for (i = lv = 1; i < l; i++) {
     599          36 :             if (f(E, gmael3(z,i,1,2)))
     600             :            {
     601          18 :              gel(v1,lv) = gmael3(z,i,1,1);
     602          18 :              gel(v2,lv) = gmael3(z,i,1,2);
     603          18 :              lv++;
     604             :            }
     605             :           }
     606          12 :           fixlg(v1, lv); fixlg(v2, lv); y = gtomap(mkmat2(v1,v2));
     607             :         }
     608             :         else
     609             :         {
     610             :           GEN B;
     611          16 :           y = cgetg(3, t_LIST);
     612          16 :           v = genindexselect(E, f, z);
     613          16 :           B = extract_copy(z, v);
     614          16 :           y[1] = lg(B)-1;
     615          16 :           list_data(y) = B;
     616             :         }
     617             :       }
     618          28 :       break;
     619          45 :     case t_VEC: case t_COL: case t_MAT:
     620          45 :       v = genindexselect(E, f, A);
     621          45 :       y = extract_copy(A, v);
     622          45 :       break;
     623           5 :     default:
     624           5 :       pari_err_TYPE("select",A);
     625             :       return NULL;/*LCOV_EXCL_LINE*/
     626             :   }
     627          73 :   clone_unlock_deep(A); return gc_upto(av, y);
     628             : }
     629             : 
     630             : static void
     631       45332 : check_callgen1(GEN f, const char *s)
     632             : {
     633       45332 :   if (typ(f) != t_CLOSURE || closure_is_variadic(f)  || closure_arity(f) < 1)
     634           0 :     pari_err_TYPE(s, f);
     635       45332 : }
     636             : 
     637             : GEN
     638          94 : select0(GEN f, GEN x, long flag)
     639             : {
     640          94 :   check_callgen1(f, "select");
     641          94 :   switch(flag)
     642             :   {
     643          78 :     case 0: return genselect((void *) f, gp_callbool, x);
     644          16 :     case 1: return genindexselect((void *) f, gp_callbool, x);
     645           0 :     default: pari_err_FLAG("select");
     646             :              return NULL;/*LCOV_EXCL_LINE*/
     647             :   }
     648             : }
     649             : 
     650             : GEN
     651           0 : parselect(GEN C, GEN D, long flag)
     652             : {
     653             :   pari_sp av, av2;
     654           0 :   long lv, l = lg(D), i, pending = 0, workid;
     655             :   GEN V, done;
     656             :   struct pari_mt pt;
     657           0 :   check_callgen1(C, "parselect");
     658           0 :   if (!is_vec_t(typ(D))) pari_err_TYPE("parselect",D);
     659           0 :   V = cgetg(l, t_VECSMALL); av = avma;
     660           0 :   mt_queue_start_lim(&pt, C, l-1);
     661           0 :   av2 = avma;
     662           0 :   for (i=1; i<l || pending; i++)
     663             :   {
     664           0 :     mt_queue_submit(&pt, i, i<l? mkvec(gel(D,i)): NULL);
     665           0 :     done = mt_queue_get(&pt, &workid, &pending);
     666           0 :     if (done) V[workid] = !gequal0(done);
     667           0 :     set_avma(av2);
     668             :   }
     669           0 :   mt_queue_end(&pt);
     670           0 :   set_avma(av);
     671           0 :   for (lv=1, i=1; i<l; i++)
     672           0 :     if (V[i]) V[lv++]=i;
     673           0 :   fixlg(V, lv);
     674           0 :   return flag? V: extract_copy(D, V);
     675             : }
     676             : 
     677             : GEN
     678           0 : veccatapply(void *E, GEN (*f)(void*, GEN), GEN x)
     679             : {
     680           0 :   pari_sp av = avma;
     681           0 :   GEN v = vecapply(E, f, x);
     682           0 :   return lg(v) == 1? v: gc_GEN(av, shallowconcat1(v));
     683             : }
     684             : 
     685             : static GEN
     686           6 : ser_apply(void *E, GEN (*f)(void*, GEN), GEN x)
     687          24 : { pari_APPLY_ser(f(E, gel(x,i))); }
     688             : static GEN
     689           6 : RgX_apply(void *E, GEN (*f)(void*, GEN), GEN x)
     690          24 : { pari_APPLY_pol(f(E, gel(x,i))); }
     691             : static GEN
     692      157486 : RgV_apply(void *E, GEN (*f)(void*, GEN), GEN x)
     693      899796 : { pari_APPLY_same( f(E, gel(x,i)) ); }
     694             : static GEN
     695          36 : RgM_apply(void *E, GEN (*f)(void*, GEN), GEN x)
     696         108 : { pari_APPLY_same( RgV_apply(E,f,gel(x,i)) ); }
     697             : 
     698             : static GEN
     699          54 : map_apply_i(void *E, GEN (*f)(void*, GEN), GEN x)
     700          54 : { retmkvec2(mkvec2(gcopy(gmael(x,1,1)), f(E, gmael(x,1,2))),
     701             :             gcopy(gel(x, 2))); }
     702             : static GEN
     703          18 : map_apply(void *E, GEN (*f)(void* E, GEN x), GEN x)
     704          72 : { pari_APPLY_same(map_apply_i(E, f, gel(x,i))); }
     705             : 
     706             : /* as genapply, but treat A [ t_VEC,t_COL, or t_MAT] as a t_VEC */
     707             : GEN
     708      113208 : vecapply(void *E, GEN (*f)(void* E, GEN x), GEN x)
     709             : {
     710             :   GEN y;
     711      113208 :   clone_lock(x); y = RgV_apply(E,f,x);
     712      113208 :   clone_unlock_deep(x); settyp(y, t_VEC); return y;
     713             : }
     714             : GEN
     715       44278 : genapply(void *E, GEN (*f)(void* E, GEN x), GEN x)
     716             : {
     717       44278 :   long tx = typ(x);
     718             :   GEN y, z;
     719             : 
     720       44278 :   if (is_scalar_t(tx)) return f(E, x);
     721       44278 :   clone_lock(x);
     722       44278 :   switch(tx) {
     723           6 :     case t_POL: y = RgX_apply(E,f,x); break;
     724           6 :     case t_SER:
     725           6 :       y = ser_isexactzero(x)? gcopy(x): ser_apply(E,f,x);
     726           6 :       break;
     727          36 :     case t_LIST:
     728             :       {
     729          36 :         long t = list_typ(x);
     730          36 :         z = list_data(x);
     731          36 :         if (!z)
     732           6 :           y = mklist_typ(t);
     733             :         else
     734             :         {
     735          30 :           y = cgetg(3, t_LIST);
     736          30 :           y[1] = evaltyp(t)|_evallg(lg(z)-1);
     737             :           switch(t)
     738             :           {
     739          12 :             case t_LIST_RAW: list_data(y) = RgV_apply(E,f,z); break;
     740          18 :             case t_LIST_MAP: list_data(y) = map_apply(E,f,z); break;
     741             :           }
     742             :         }
     743             :       }
     744          36 :       break;
     745          36 :     case t_MAT: y = RgM_apply(E, f, x); break;
     746       44194 :     case t_VEC: case t_COL: y = RgV_apply(E,f,x); break;
     747           0 :     default:
     748           0 :       pari_err_TYPE("apply",x);
     749             :       return NULL;/*LCOV_EXCL_LINE*/
     750             :   }
     751       44278 :   clone_unlock_deep(x); return y;
     752             : }
     753             : 
     754             : GEN
     755       44278 : apply0(GEN f, GEN x)
     756             : {
     757       44278 :   check_callgen1(f, "apply");
     758       44278 :   return genapply((void *) f, gp_call, x);
     759             : }
     760             : 
     761             : GEN
     762         363 : vecselapply(void *Epred, long (*pred)(void* E, GEN x), void *Efun,
     763             :                          GEN (*fun)(void* E, GEN x), GEN A)
     764             : {
     765             :   GEN y;
     766         363 :   long i, l = lg(A), nb=1;
     767         363 :   clone_lock(A); y = cgetg(l, t_VEC);
     768    18714387 :   for (i=1; i<l; i++)
     769    18714024 :     if (pred(Epred, gel(A,i))) gel(y,nb++) = fun(Efun, gel(A,i));
     770         363 :   fixlg(y,nb); clone_unlock_deep(A); return y;
     771             : }
     772             : 
     773             : GEN
     774           0 : veccatselapply(void *Epred, long (*pred)(void* E, GEN x), void *Efun,
     775             :                             GEN (*fun)(void* E, GEN x), GEN A)
     776             : {
     777           0 :   pari_sp av = avma;
     778           0 :   GEN v = vecselapply(Epred, pred, Efun, fun, A);
     779           0 :   return lg(v) == 1? v: gc_GEN(av, shallowconcat1(v));
     780             : }
     781             : 
     782             : /* suitable for gc_upto */
     783             : GEN
     784          10 : parapply_slice_worker(GEN x, GEN worker)
     785       12510 : { pari_APPLY_same(closure_callgen1(worker, gel(x,i))); }
     786             : 
     787             : /* B <- {A[i] : i = r (mod m)}, 1 <= r <= m */
     788             : static void
     789          10 : arithprogset(GEN B, GEN A, long r, long m)
     790             : {
     791          10 :   long i, k, l = lg(A);
     792          10 :   if (typ(B)==t_VECSMALL)
     793           0 :     for (k = 1, i = r; i < l; i += m, k++) uel(B, k) = uel(A, i);
     794             :   else
     795       12510 :     for (k = 1, i = r; i < l; i += m, k++) gel(B, k) = gel(A, i);
     796          10 :   setlg(B, k);
     797          10 : }
     798             : GEN
     799          10 : gen_parapply_slice(GEN worker, GEN D, long mmin)
     800             : {
     801          10 :   long l, r, n = lg(D)-1, m = minss(mmin, n), pending = 0;
     802          10 :   GEN L = cgetg(n / m + 2, t_VEC), va = mkvec(L), V = cgetg_copy(D, &l);
     803             :   struct pari_mt pt;
     804          10 :   mt_queue_start_lim(&pt, worker, m);
     805          20 :   for (r = 1; r <= m || pending; r++)
     806             :   {
     807             :     long workid;
     808             :     GEN done;
     809          10 :     if (r <= m) arithprogset(L, D, r, m);
     810          10 :     mt_queue_submit(&pt, r, r <= m? va: NULL);
     811          10 :     done = mt_queue_get(&pt, &workid, &pending);
     812          10 :     if (done)
     813             :     {
     814          10 :       long j, k, J = lg(done)-1;
     815       12510 :       for (j = 1, k = workid; j <= J; j++, k +=m) gel(V, k) = gel(done, j);
     816             :     }
     817             :   }
     818          10 :   mt_queue_end(&pt); return V;
     819             : }
     820             : 
     821             : GEN
     822        5754 : gen_parapply_slice_zv(GEN worker, GEN D, long mmin)
     823             : {
     824        5754 :   long l, r, n = lg(D)-1, m = minss(mmin, n), pending = 0;
     825             :   struct pari_mt pt;
     826             :   GEN L, va, V;
     827        5754 :   if (m == 1) return closure_callgen1(worker, D);
     828           0 :   L = cgetg(n / m + 2, t_VECSMALL);
     829           0 :   va = mkvec(L); V = cgetg_copy(D, &l);
     830           0 :   mt_queue_start_lim(&pt, worker, m);
     831           0 :   for (r = 1; r <= m || pending; r++)
     832             :   {
     833             :     long workid;
     834             :     GEN done;
     835           0 :     if (r <= m) arithprogset(L, D, r, m);
     836           0 :     mt_queue_submit(&pt, r, r <= m? va: NULL);
     837           0 :     done = mt_queue_get(&pt, &workid, &pending);
     838           0 :     if (done)
     839             :     {
     840           0 :       long j, k, J = lg(done)-1;
     841           0 :       for (j = 1, k = workid; j <= J; j++, k +=m) V[k] = done[j];
     842             :     }
     843             :   }
     844           0 :   mt_queue_end(&pt); return V;
     845             : }
     846             : 
     847             : GEN
     848      320862 : gen_parapply_percent(GEN worker, GEN D, long percent)
     849             : {
     850      320862 :   long l = lg(D), i, pending = 0, cnt = 0, lper = -1, lcnt = 0;
     851             :   GEN W, V;
     852             :   struct pari_mt pt;
     853             : 
     854      320862 :   if (l == 1) return cgetg(1, typ(D));
     855      294826 :   W = cgetg(2, t_VEC);
     856      294826 :   V = cgetg(l, typ(D));
     857      294826 :   mt_queue_start_lim(&pt, worker, l-1);
     858     2204056 :   for (i = 1; i < l || pending; i++)
     859             :   {
     860             :     long workid;
     861             :     GEN done;
     862     1909230 :     if (i < l) gel(W,1) = gel(D,i);
     863     1909230 :     mt_queue_submit(&pt, i, i<l? W: NULL);
     864     1909230 :     done = mt_queue_get(&pt, &workid, &pending);
     865     1909230 :     if (done)
     866             :     {
     867     1909230 :       gel(V,workid) = done;
     868     1909230 :       if (percent && (++cnt)-lcnt>=percent)
     869             :       {
     870           0 :         long per = (long)(cnt*100./(l-1));
     871           0 :         lcnt = cnt;
     872           0 :         if (per > lper) { err_printf("%ld%% ",per); lper = per; }
     873             :       }
     874             :     }
     875             :   }
     876      294826 :   mt_queue_end(&pt); return V;
     877             : }
     878             : 
     879             : GEN
     880      318372 : gen_parapply(GEN worker, GEN D)
     881      318372 : { return gen_parapply_percent(worker, D, 0); }
     882             : 
     883             : GEN
     884         960 : parapply(GEN C, GEN D)
     885             : {
     886         960 :   pari_sp av = avma;
     887         960 :   check_callgen1(C, "parapply");
     888         960 :   if (!is_vec_t(typ(D))) pari_err_TYPE("parapply",D);
     889         960 :   return gc_upto(av, gen_parapply(C, D));
     890             : }
     891             : 
     892             : GEN
     893          24 : genfold(void *E, GEN (*f)(void* E, GEN x, GEN y), GEN x)
     894             : {
     895          24 :   pari_sp av = avma;
     896             :   GEN z;
     897          24 :   long i, l = lg(x);
     898          24 :   if (!is_vec_t(typ(x))|| l==1  ) pari_err_TYPE("fold",x);
     899          24 :   clone_lock(x);
     900          24 :   z = gel(x,1);
     901         102 :   for (i=2; i<l; i++)
     902             :   {
     903          78 :     z = f(E,z,gel(x,i));
     904          78 :     if (gc_needed(av, 2))
     905             :     {
     906           0 :       if (DEBUGMEM>1) pari_warn(warnmem,"fold");
     907           0 :       z = gc_GEN(av, z);
     908             :     }
     909             :   }
     910          24 :   clone_unlock_deep(x);
     911          24 :   return gc_GEN(av, z);
     912             : }
     913             : 
     914             : GEN
     915          24 : fold0(GEN f, GEN x)
     916             : {
     917          24 :   if (typ(f) != t_CLOSURE || closure_arity(f) < 2) pari_err_TYPE("fold",f);
     918          24 :   return genfold((void *) f, gp_call2, x);
     919             : }
     920             : /*******************************************************************/
     921             : /*                                                                 */
     922             : /*                     SCALAR-MATRIX OPERATIONS                    */
     923             : /*                                                                 */
     924             : /*******************************************************************/
     925             : GEN
     926      322471 : gtomat(GEN x)
     927             : {
     928             :   long lx, i;
     929             :   GEN y;
     930             : 
     931      322471 :   if (!x) return cgetg(1, t_MAT);
     932      322432 :   switch(typ(x))
     933             :   {
     934          24 :     case t_LIST:
     935          24 :       if (list_typ(x)==t_LIST_MAP)
     936          12 :         return maptomat(x);
     937          12 :       x = list_data(x);
     938          12 :       if (!x) return cgetg(1, t_MAT);
     939             :       /* fall through */
     940             :     case t_VEC: {
     941        5767 :       lx=lg(x); y=cgetg(lx,t_MAT);
     942        5767 :       if (lx == 1) break;
     943        5767 :       if (typ(gel(x,1)) == t_COL) {
     944        3789 :         long h = lgcols(x);
     945      137316 :         for (i=2; i<lx; i++) {
     946      133527 :           if (typ(gel(x,i)) != t_COL || lg(gel(x,i)) != h) break;
     947             :         }
     948        3789 :         if (i == lx) { /* matrix with h-1 rows */
     949        3789 :           y = cgetg(lx, t_MAT);
     950      141105 :           for (i=1 ; i<lx; i++) gel(y,i) = gcopy(gel(x,i));
     951        3789 :           return y;
     952             :         }
     953             :       }
     954        5928 :       for (i=1; i<lx; i++) gel(y,i) = mkcolcopy(gel(x,i));
     955        1978 :       break;
     956             :     }
     957      103878 :     case t_COL:
     958      103878 :       lx = lg(x);
     959      103878 :       if (lx == 1) return cgetg(1, t_MAT);
     960      103866 :       if (typ(gel(x,1)) == t_VEC) {
     961           6 :         long j, h = lg(gel(x,1));
     962          12 :         for (i=2; i<lx; i++) {
     963           6 :           if (typ(gel(x,i)) != t_VEC || lg(gel(x,i)) != h) break;
     964             :         }
     965           6 :         if (i == lx) { /* matrix with h cols */
     966           6 :           y = cgetg(h, t_MAT);
     967          24 :           for (j=1 ; j<h; j++) {
     968          18 :             gel(y,j) = cgetg(lx, t_COL);
     969          54 :             for (i=1; i<lx; i++) gcoeff(y,i,j) = gcopy(gmael(x,i,j));
     970             :           }
     971           6 :           return y;
     972             :         }
     973             :       }
     974      103860 :       y = mkmatcopy(x); break;
     975      211965 :     case t_MAT:
     976      211965 :       y = gcopy(x); break;
     977           6 :     case t_QFB: {
     978             :       GEN b;
     979           6 :       y = cgetg(3,t_MAT); b = gmul2n(gel(x,2),-1);
     980           6 :       gel(y,1) = mkcol2(icopy(gel(x,1)), b);
     981           6 :       gel(y,2) = mkcol2(b, icopy(gel(x,3)));
     982           6 :       break;
     983             :     }
     984         798 :     default:
     985         798 :       y = cgetg(2,t_MAT); gel(y,1) = mkcolcopy(x);
     986         798 :       break;
     987             :   }
     988      318607 :   return y;
     989             : }
     990             : 
     991             : /* create the diagonal matrix, whose diagonal is given by x */
     992             : GEN
     993     1101569 : diagonal(GEN x)
     994             : {
     995     1101569 :   long j, lx, tx = typ(x);
     996             :   GEN y;
     997             : 
     998     1101569 :   if (! is_matvec_t(tx)) return scalarmat(x,1);
     999     1101563 :   if (tx==t_MAT)
    1000             :   {
    1001          12 :     if (RgM_isdiagonal(x)) return gcopy(x);
    1002           6 :     pari_err_TYPE("diagonal",x);
    1003             :   }
    1004     1101551 :   lx=lg(x); y=cgetg(lx,t_MAT);
    1005     3956236 :   for (j=1; j<lx; j++)
    1006             :   {
    1007     2854685 :     gel(y,j) = zerocol(lx-1);
    1008     2854685 :     gcoeff(y,j,j) = gcopy(gel(x,j));
    1009             :   }
    1010     1101551 :   return y;
    1011             : }
    1012             : /* same, assuming x is a t_VEC/t_COL. Not memory clean. */
    1013             : GEN
    1014      297878 : diagonal_shallow(GEN x)
    1015             : {
    1016      297878 :   long j, lx = lg(x);
    1017      297878 :   GEN y = cgetg(lx,t_MAT);
    1018             : 
    1019      876537 :   for (j=1; j<lx; j++)
    1020             :   {
    1021      578659 :     gel(y,j) = zerocol(lx-1);
    1022      578659 :     gcoeff(y,j,j) = gel(x,j);
    1023             :   }
    1024      297878 :   return y;
    1025             : }
    1026             : 
    1027             : GEN
    1028         576 : zv_diagonal(GEN x)
    1029             : {
    1030         576 :   long j, l = lg(x), n = l-1;
    1031         576 :   GEN y = cgetg(l,t_MAT);
    1032             : 
    1033        2676 :   for (j = 1; j < l; j++)
    1034             :   {
    1035        2100 :     gel(y,j) = zero_Flv(n);
    1036        2100 :     ucoeff(y,j,j) = uel(x,j);
    1037             :   }
    1038         576 :   return y;
    1039             : }
    1040             : 
    1041             : /* compute x*diagonal(d) */
    1042             : GEN
    1043          60 : matmuldiagonal(GEN x, GEN d)
    1044             : {
    1045          60 :   if (typ(x)!=t_MAT) pari_err_TYPE("matmuldiagonal",x);
    1046          60 :   if (! is_vec_t(typ(d))) pari_err_TYPE("matmuldiagonal",d);
    1047          60 :   if (lg(d) != lg(x)) pari_err_OP("operation 'matmuldiagonal'", x,d);
    1048         300 :   pari_APPLY_same(RgC_Rg_mul(gel(x,i), gel(d,i)));
    1049             : }
    1050             : 
    1051             : /* compute A*B assuming the result is a diagonal matrix */
    1052             : GEN
    1053           6 : matmultodiagonal(GEN A, GEN B)
    1054             : {
    1055           6 :   long i, j, hA, hB, lA = lg(A), lB = lg(B);
    1056           6 :   GEN y = matid(lB-1);
    1057             : 
    1058           6 :   if (typ(A) != t_MAT) pari_err_TYPE("matmultodiagonal",A);
    1059           6 :   if (typ(B) != t_MAT) pari_err_TYPE("matmultodiagonal",B);
    1060           6 :   hA = (lA == 1)? lB: lgcols(A);
    1061           6 :   hB = (lB == 1)? lA: lgcols(B);
    1062           6 :   if (lA != hB || lB != hA) pari_err_OP("operation 'matmultodiagonal'", A,B);
    1063          48 :   for (i=1; i<lB; i++)
    1064             :   {
    1065          42 :     GEN z = gen_0;
    1066         336 :     for (j=1; j<lA; j++) z = gadd(z, gmul(gcoeff(A,i,j),gcoeff(B,j,i)));
    1067          42 :     gcoeff(y,i,i) = z;
    1068             :   }
    1069           6 :   return y;
    1070             : }
    1071             : 
    1072             : /* [m[1,1], ..., m[l,l]], internal */
    1073             : GEN
    1074      836426 : RgM_diagonal_shallow(GEN m)
    1075             : {
    1076      836426 :   long i, lx = lg(m);
    1077      836426 :   GEN y = cgetg(lx,t_VEC);
    1078     2786852 :   for (i=1; i<lx; i++) gel(y, i) = gcoeff(m,i,i);
    1079      836426 :   return y;
    1080             : }
    1081             : 
    1082             : /* same, public function */
    1083             : GEN
    1084           0 : RgM_diagonal(GEN m)
    1085             : {
    1086           0 :   long i, lx = lg(m);
    1087           0 :   GEN y = cgetg(lx,t_VEC);
    1088           0 :   for (i=1; i<lx; i++) gel(y,i) = gcopy(gcoeff(m,i,i));
    1089           0 :   return y;
    1090             : }

Generated by: LCOV version 1.16