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

Generated by: LCOV version 1.16