Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2012 The PARI group.12This file is part of the PARI/GP package.34PARI/GP is free software; you can redistribute it and/or modify it under the5terms of the GNU General Public License as published by the Free Software6Foundation; either version 2 of the License, or (at your option) any later7version. It is distributed in the hope that it will be useful, but WITHOUT8ANY WARRANTY WHATSOEVER.910Check the License for details. You should have received a copy of it, along11with the package; see the file 'COPYING'. If not, write to the Free Software12Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */1314/********************************************************************/15/** **/16/** LINEAR ALGEBRA **/17/** (third part) **/18/** **/19/********************************************************************/20#include "pari.h"21#include "paripriv.h"2223#define DEBUGLEVEL DEBUGLEVEL_mat2425/*******************************************************************/26/* */27/* SUM */28/* */29/*******************************************************************/3031GEN32vecsum(GEN v)33{34pari_sp av = avma;35long i, l;36GEN p;37if (!is_vec_t(typ(v)))38pari_err_TYPE("vecsum", v);39l = lg(v);40if (l == 1) return gen_0;41p = gel(v,1);42if (l == 2) return gcopy(p);43for (i=2; i<l; i++)44{45p = gadd(p, gel(v,i));46if (gc_needed(av, 2))47{48if (DEBUGMEM>1) pari_warn(warnmem,"sum");49p = gerepileupto(av, p);50}51}52return gerepileupto(av, p);53}5455/*******************************************************************/56/* */57/* TRANSPOSE */58/* */59/*******************************************************************/60/* A[x0,]~ */61static GEN62row_transpose(GEN A, long x0)63{64long i, lB = lg(A);65GEN B = cgetg(lB, t_COL);66for (i=1; i<lB; i++) gel(B, i) = gcoeff(A, x0, i);67return B;68}69static GEN70row_transposecopy(GEN A, long x0)71{72long i, lB = lg(A);73GEN B = cgetg(lB, t_COL);74for (i=1; i<lB; i++) gel(B, i) = gcopy(gcoeff(A, x0, i));75return B;76}7778/* No copy*/79GEN80shallowtrans(GEN x)81{82long i, dx, lx;83GEN y;84switch(typ(x))85{86case t_VEC: y = leafcopy(x); settyp(y,t_COL); break;87case t_COL: y = leafcopy(x); settyp(y,t_VEC); break;88case t_MAT:89lx = lg(x); if (lx==1) return cgetg(1,t_MAT);90dx = lgcols(x); y = cgetg(dx,t_MAT);91for (i = 1; i < dx; i++) gel(y,i) = row_transpose(x,i);92break;93default: pari_err_TYPE("shallowtrans",x);94return NULL;/*LCOV_EXCL_LINE*/95}96return y;97}9899GEN100gtrans(GEN x)101{102long i, dx, lx;103GEN y;104switch(typ(x))105{106case t_VEC: y = gcopy(x); settyp(y,t_COL); break;107case t_COL: y = gcopy(x); settyp(y,t_VEC); break;108case t_MAT:109lx = lg(x); if (lx==1) return cgetg(1,t_MAT);110dx = lgcols(x); y = cgetg(dx,t_MAT);111for (i = 1; i < dx; i++) gel(y,i) = row_transposecopy(x,i);112break;113default: pari_err_TYPE("gtrans",x);114return NULL;/*LCOV_EXCL_LINE*/115}116return y;117}118119/*******************************************************************/120/* */121/* EXTRACTION */122/* */123/*******************************************************************/124125static long126str_to_long(char *s, char **pt)127{128long a = atol(s);129while (isspace((int)*s)) s++;130if (*s == '-' || *s == '+') s++;131while (isdigit((int)*s) || isspace((int)*s)) s++;132*pt = s; return a;133}134135static int136get_range(char *s, long *a, long *b, long *cmpl, long lx)137{138long max = lx - 1;139140*a = 1; *b = max;141if (*s == '^') { *cmpl = 1; s++; } else *cmpl = 0;142if (!*s) return 0;143if (*s != '.')144{145*a = str_to_long(s, &s);146if (*a < 0) *a += lx;147if (*a<1 || *a>max) return 0;148}149if (*s == '.')150{151s++; if (*s != '.') return 0;152do s++; while (isspace((int)*s));153if (*s)154{155*b = str_to_long(s, &s);156if (*b < 0) *b += lx;157if (*b<1 || *b>max || *s) return 0;158}159return 1;160}161if (*s) return 0;162*b = *a; return 1;163}164165static int166extract_selector_ok(long lx, GEN L)167{168long i, l;169switch (typ(L))170{171case t_INT: {172long maxj;173if (!signe(L)) return 1;174l = lgefint(L)-1;175maxj = BITS_IN_LONG - bfffo(*int_MSW(L));176return ((l-2) * BITS_IN_LONG + maxj < lx);177}178case t_STR: {179long first, last, cmpl;180return get_range(GSTR(L), &first, &last, &cmpl, lx);181}182case t_VEC: case t_COL:183l = lg(L);184for (i=1; i<l; i++)185{186long j = itos(gel(L,i));187if (j>=lx || j<=0) return 0;188}189return 1;190case t_VECSMALL:191l = lg(L);192for (i=1; i<l; i++)193{194long j = L[i];195if (j>=lx || j<=0) return 0;196}197return 1;198}199return 0;200}201202GEN203shallowmatextract(GEN x, GEN l1, GEN l2)204{205long i, j, n1 = lg(l1), n2 = lg(l2);206GEN M = cgetg(n2, t_MAT);207for(i=1; i < n2; i++)208{209long ii = l2[i];210GEN C = cgetg(n1, t_COL);211for (j=1; j < n1; j++)212{213long jj = l1[j];214gel(C, j) = gmael(x, ii, jj);215}216gel(M, i) = C;217}218return M;219}220221GEN222shallowextract(GEN x, GEN L)223{224long i,j, tl = typ(L), tx = typ(x), lx = lg(x);225GEN y;226227switch(tx)228{229case t_VEC:230case t_COL:231case t_MAT:232case t_VECSMALL: break;233default: pari_err_TYPE("extract",x);234235}236if (tl==t_INT)237{ /* extract components of x as per the bits of mask L */238long k, l, ix, iy, maxj;239GEN Ld;240if (!signe(L)) return cgetg(1,tx);241y = new_chunk(lx);242l = lgefint(L)-1; ix = iy = 1;243maxj = BITS_IN_LONG - bfffo(*int_MSW(L));244if ((l-2) * BITS_IN_LONG + maxj >= lx)245pari_err_TYPE("vecextract [mask too large]", L);246for (k = 2, Ld = int_LSW(L); k < l; k++, Ld = int_nextW(Ld))247{248ulong B = *Ld;249for (j = 0; j < BITS_IN_LONG; j++, B >>= 1, ix++)250if (B & 1) y[iy++] = x[ix];251}252{ /* k = l */253ulong B = *Ld;254for (j = 0; j < maxj; j++, B >>= 1, ix++)255if (B & 1) y[iy++] = x[ix];256}257y[0] = evaltyp(tx) | evallg(iy);258return y;259}260if (tl==t_STR)261{262char *s = GSTR(L);263long first, last, cmpl, d;264if (! get_range(s, &first, &last, &cmpl, lx))265pari_err_TYPE("vecextract [incorrect range]", L);266if (lx == 1) return cgetg(1,tx);267d = last - first;268if (cmpl)269{270if (d >= 0)271{272y = cgetg(lx - (1+d),tx);273for (j=1; j<first; j++) gel(y,j) = gel(x,j);274for (i=last+1; i<lx; i++,j++) gel(y,j) = gel(x,i);275}276else277{278y = cgetg(lx - (1-d),tx);279for (j=1,i=lx-1; i>first; i--,j++) gel(y,j) = gel(x,i);280for (i=last-1; i>0; i--,j++) gel(y,j) = gel(x,i);281}282}283else284{285if (d >= 0)286{287y = cgetg(d+2,tx);288for (i=first,j=1; i<=last; i++,j++) gel(y,j) = gel(x,i);289}290else291{292y = cgetg(2-d,tx);293for (i=first,j=1; i>=last; i--,j++) gel(y,j) = gel(x,i);294}295}296return y;297}298299if (is_vec_t(tl))300{301long ll=lg(L); y=cgetg(ll,tx);302for (i=1; i<ll; i++)303{304j = itos(gel(L,i));305if (j<=0) pari_err_COMPONENT("vecextract","<=",gen_0,stoi(j));306if (j>=lx) pari_err_COMPONENT("vecextract",">=",stoi(lx),stoi(j));307gel(y,i) = gel(x,j);308}309return y;310}311if (tl == t_VECSMALL)312{313long ll=lg(L); y=cgetg(ll,tx);314for (i=1; i<ll; i++)315{316j = L[i];317if (j<=0) pari_err_COMPONENT("vecextract","<=",gen_0,stoi(j));318if (j>=lx) pari_err_COMPONENT("vecextract",">=",stoi(lx),stoi(j));319gel(y,i) = gel(x,j);320}321return y;322}323pari_err_TYPE("vecextract [mask]", L);324return NULL; /* LCOV_EXCL_LINE */325}326327/* does the component selector l select 0 component ? */328static int329select_0(GEN l)330{331switch(typ(l))332{333case t_INT:334return (!signe(l));335case t_VEC: case t_COL: case t_VECSMALL:336return (lg(l) == 1);337}338return 0;339}340341GEN342extract0(GEN x, GEN l1, GEN l2)343{344pari_sp av = avma, av2;345GEN y;346if (! l2)347{348y = shallowextract(x, l1);349if (lg(y) == 1 || typ(y) == t_VECSMALL) return y;350av2 = avma;351y = gcopy(y);352}353else354{355if (typ(x) != t_MAT) pari_err_TYPE("extract",x);356y = shallowextract(x,l2);357if (select_0(l1)) { set_avma(av); return zeromat(0, lg(y)-1); }358if (lg(y) == 1 && lg(x) > 1)359{360if (!extract_selector_ok(lgcols(x), l1))361pari_err_TYPE("vecextract [incorrect mask]", l1);362set_avma(av); return cgetg(1, t_MAT);363}364y = shallowextract(shallowtrans(y), l1);365av2 = avma;366y = gtrans(y);367}368stackdummy(av, av2);369return y;370}371372static long373vecslice_parse_arg(long lA, long *y1, long *y2, long *skip)374{375*skip=0;376if (*y1==LONG_MAX)377{378if (*y2!=LONG_MAX)379{380if (*y2<0) *y2 += lA;381if (*y2<0 || *y2==LONG_MAX || *y2>=lA)382pari_err_DIM("_[..]");383*skip=*y2;384}385*y1 = 1; *y2 = lA-1;386}387else if (*y2==LONG_MAX) *y2 = *y1;388if (*y1<=0) *y1 += lA;389if (*y2<0) *y2 += lA;390if (*y1<=0 || *y1>*y2+1 || *y2>=lA) pari_err_DIM("_[..]");391return *y2 - *y1 + 2 - !!*skip;392}393394static GEN395vecslice_i(GEN A, long t, long lB, long y1, long skip)396{397GEN B = cgetg(lB, t);398long i;399for (i=1; i<lB; i++, y1++)400{401if (y1 == skip) { i--; continue; }402gel(B,i) = gcopy(gel(A,y1));403}404return B;405}406407static GEN408rowslice_i(GEN A, long lB, long x1, long y1, long skip)409{410GEN B = cgetg(lB, t_VEC);411long i;412for (i=1; i<lB; i++, y1++)413{414if (y1 == skip) { i--; continue; }415gel(B,i) = gcopy(gcoeff(A,x1,y1));416}417return B;418}419420static GEN421rowsmallslice_i(GEN A, long lB, long x1, long y1, long skip)422{423GEN B = cgetg(lB, t_VECSMALL);424long i;425for (i=1; i<lB; i++, y1++)426{427if (y1 == skip) { i--; continue; }428B[i] = coeff(A,x1,y1);429}430return B;431}432433static GEN434vecsmallslice_i(GEN A, long t, long lB, long y1, long skip)435{436GEN B = cgetg(lB, t);437long i;438for (i=1; i<lB; i++, y1++)439{440if (y1 == skip) { i--; continue; }441B[i] = A[y1];442}443return B;444}445GEN446vecslice0(GEN A, long y1, long y2)447{448long skip, lB, t = typ(A);449switch(t)450{451case t_VEC: case t_COL:452lB = vecslice_parse_arg(lg(A), &y1, &y2, &skip);453return vecslice_i(A, t,lB,y1,skip);454case t_VECSMALL:455lB = vecslice_parse_arg(lg(A), &y1, &y2, &skip);456return vecsmallslice_i(A, t,lB,y1,skip);457case t_LIST:458if (list_typ(A) == t_LIST_RAW)459{460GEN y, z = list_data(A);461long l = z? lg(z): 1;462lB = vecslice_parse_arg(l, &y1, &y2, &skip);463y = mklist(); if (!z) return y;464list_data(y) = vecslice_i(z, t_VEC,lB,y1,skip);465return y;466}467default:468pari_err_TYPE("_[_.._]",A);469return NULL;/*LCOV_EXCL_LINE*/470}471}472473GEN474matslice0(GEN A, long x1, long x2, long y1, long y2)475{476GEN B;477long i, lB, lA = lg(A), rA, t, skip, rskip, rlB;478long is_col = y1!=LONG_MAX && y2==LONG_MAX;479long is_row = x1!=LONG_MAX && x2==LONG_MAX;480GEN (*slice)(GEN A, long t, long lB, long y1, long skip);481if (typ(A)!=t_MAT) pari_err_TYPE("_[_.._,_.._]",A);482lB = vecslice_parse_arg(lA, &y1, &y2, &skip);483if (is_col) return vecslice0(gel(A, y1), x1, x2);484rA = lg(A)==1 ? 1: lgcols(A);485rlB = vecslice_parse_arg(rA, &x1, &x2, &rskip);486t = lg(A)==1 ? t_COL: typ(gel(A,1));487if (is_row) return t == t_COL ? rowslice_i(A, lB, x1, y1, skip):488rowsmallslice_i(A, lB, x1, y1, skip);489slice = t == t_COL? &vecslice_i: &vecsmallslice_i;490491B = cgetg(lB, t_MAT);492for (i=1; i<lB; i++, y1++)493{494if (y1 == skip) { i--; continue; }495gel(B,i) = slice(gel(A,y1),t,rlB, x1, rskip);496}497return B;498}499500GEN501vecrange(GEN a, GEN b)502{503GEN y;504long i, l;505if (typ(a)!=t_INT) pari_err_TYPE("[_.._]",a);506if (typ(b)!=t_INT) pari_err_TYPE("[_.._]",b);507if (cmpii(a,b)>0) return cgetg(1,t_VEC);508l = itos(subii(b,a))+1;509a = setloop(a);510y = cgetg(l+1, t_VEC);511for (i=1; i<=l; a = incloop(a), i++) gel(y,i) = icopy(a);512return y;513}514515GEN516vecrangess(long a, long b)517{518GEN y;519long i, l;520if (a>b) return cgetg(1,t_VEC);521l = b-a+1;522y = cgetg(l+1, t_VEC);523for (i=1; i<=l; a++, i++) gel(y,i) = stoi(a);524return y;525}526527GEN528genindexselect(void *E, long (*f)(void* E, GEN x), GEN A)529{530long l, i, lv;531GEN v, z;532pari_sp av;533clone_lock(A);534switch(typ(A))535{536case t_LIST:537z = list_data(A);538l = z? lg(z): 1;539break;540case t_VEC: case t_COL: case t_MAT:541l = lg(A);542z = A;543break;544default:545pari_err_TYPE("select",A);546return NULL;/*LCOV_EXCL_LINE*/547}548v = cgetg(l, t_VECSMALL);549av = avma;550for (i = lv = 1; i < l; i++) {551if (f(E, gel(z,i))) v[lv++] = i;552set_avma(av);553}554clone_unlock_deep(A); fixlg(v, lv); return v;555}556static GEN557extract_copy(GEN A, GEN v)558{559long i, l = lg(v);560GEN B = cgetg(l, typ(A));561for (i = 1; i < l; i++) gel(B,i) = gcopy(gel(A,v[i]));562return B;563}564/* as genselect, but treat A [ t_VEC,t_COL, or t_MAT] as a t_VEC */565GEN566vecselect(void *E, long (*f)(void* E, GEN x), GEN A)567{568GEN v;569clone_lock(A);570v = genindexselect(E, f, A);571A = extract_copy(A, v); settyp(A, t_VEC);572clone_unlock_deep(A); return A;573}574GEN575genselect(void *E, long (*f)(void* E, GEN x), GEN A)576{577GEN y, z, v;/* v left on stack for efficiency */578clone_lock(A);579switch(typ(A))580{581case t_LIST:582z = list_data(A);583if (!z) y = mklist();584else585{586GEN B;587y = cgetg(3, t_LIST);588v = genindexselect(E, f, z);589B = extract_copy(z, v);590y[1] = lg(B)-1;591list_data(y) = B;592}593break;594case t_VEC: case t_COL: case t_MAT:595v = genindexselect(E, f, A);596y = extract_copy(A, v);597break;598default:599pari_err_TYPE("select",A);600return NULL;/*LCOV_EXCL_LINE*/601}602clone_unlock_deep(A); return y;603}604605static void606check_callgen1(GEN f, const char *s)607{608if (typ(f) != t_CLOSURE || closure_is_variadic(f) || closure_arity(f) < 1)609pari_err_TYPE(s, f);610}611612GEN613select0(GEN f, GEN x, long flag)614{615check_callgen1(f, "select");616switch(flag)617{618case 0: return genselect((void *) f, gp_callbool, x);619case 1: return genindexselect((void *) f, gp_callbool, x);620default: pari_err_FLAG("select");621return NULL;/*LCOV_EXCL_LINE*/622}623}624625GEN626parselect_worker(GEN d, GEN C)627{628return gequal0(closure_callgen1(C, d))? gen_0: gen_1;629}630631GEN632parselect(GEN C, GEN D, long flag)633{634pari_sp av;635long lv, l = lg(D), i;636GEN V, W, worker;637check_callgen1(C, "parselect");638if (!is_vec_t(typ(D))) pari_err_TYPE("parselect",D);639W = cgetg(l, t_VECSMALL); av = avma;640worker = snm_closure(is_entry("_parselect_worker"), mkvec(C));641V = gen_parapply(worker, D);642for (lv=1, i=1; i<l; i++)643if (signe(gel(V,i))) W[lv++] = i;644fixlg(W, lv);645set_avma(av);646return flag? W: extract_copy(D, W);647}648649GEN650veccatapply(void *E, GEN (*f)(void* E, GEN x), GEN x)651{652pari_sp av = avma;653GEN v = vecapply(E, f, x);654return lg(v) == 1? v: gerepilecopy(av, shallowconcat1(v));655}656657static GEN658vecapply2(void *E, GEN (*f)(void* E, GEN x), GEN x)659{660long i, lx;661GEN y = cgetg_copy(x, &lx); y[1] = x[1];662for (i=2; i<lx; i++) gel(y,i) = f(E, gel(x,i));663return y;664}665static GEN666vecapply1(void *E, GEN (*f)(void* E, GEN x), GEN x)667{668long i, lx;669GEN y = cgetg_copy(x, &lx);670for (i=1; i<lx; i++) gel(y,i) = f(E, gel(x,i));671return y;672}673static GEN674mapapply1(void *E, GEN (*f)(void* E, GEN x), GEN x)675{676long i, lx;677GEN y = cgetg_copy(x, &lx);678for (i=1; i<lx; i++)679{680GEN xi = gel(x, i);681gel(y,i) = mkvec2(mkvec2(gcopy(gmael(xi, 1, 1)), f(E,gmael(xi, 1, 2))),682gcopy(gel(xi, 2)));683}684return y;685}686/* as genapply, but treat A [ t_VEC,t_COL, or t_MAT] as a t_VEC */687GEN688vecapply(void *E, GEN (*f)(void* E, GEN x), GEN x)689{690GEN y;691clone_lock(x); y = vecapply1(E,f,x);692clone_unlock_deep(x); settyp(y, t_VEC); return y;693}694GEN695genapply(void *E, GEN (*f)(void* E, GEN x), GEN x)696{697long i, lx, tx = typ(x);698GEN y, z;699if (is_scalar_t(tx)) return f(E, x);700clone_lock(x);701switch(tx) {702case t_POL: y = normalizepol(vecapply2(E,f,x)); break;703case t_SER:704y = ser_isexactzero(x)? gcopy(x): normalize(vecapply2(E,f,x));705break;706case t_LIST:707{708long t = list_typ(x);709z = list_data(x);710if (!z)711y = mklist_typ(t);712else713{714y = cgetg(3, t_LIST);715y[1] = evaltyp(t)|evallg(lg(z)-1);716switch(t)717{718case t_LIST_RAW:719list_data(y) = vecapply1(E,f,z);720break;721case t_LIST_MAP:722list_data(y) = mapapply1(E,f,z);723break;724}725}726}727break;728case t_MAT:729y = cgetg_copy(x, &lx);730for (i = 1; i < lx; i++) gel(y,i) = vecapply1(E,f,gel(x,i));731break;732733case t_VEC: case t_COL: y = vecapply1(E,f,x); break;734default:735pari_err_TYPE("apply",x);736return NULL;/*LCOV_EXCL_LINE*/737}738clone_unlock_deep(x); return y;739}740741GEN742apply0(GEN f, GEN x)743{744check_callgen1(f, "apply");745return genapply((void *) f, gp_call, x);746}747748GEN749vecselapply(void *Epred, long (*pred)(void* E, GEN x), void *Efun,750GEN (*fun)(void* E, GEN x), GEN A)751{752GEN y;753long i, l = lg(A), nb=1;754clone_lock(A); y = cgetg(l, t_VEC);755for (i=1; i<l; i++)756if (pred(Epred, gel(A,i))) gel(y,nb++) = fun(Efun, gel(A,i));757fixlg(y,nb); clone_unlock_deep(A); return y;758}759760GEN761veccatselapply(void *Epred, long (*pred)(void* E, GEN x), void *Efun,762GEN (*fun)(void* E, GEN x), GEN A)763{764pari_sp av = avma;765GEN v = vecselapply(Epred, pred, Efun, fun, A);766return lg(v) == 1? v: gerepilecopy(av, shallowconcat1(v));767}768769/* suitable for gerepileupto */770GEN771parapply_slice_worker(GEN D, GEN worker)772{773long l, i;774GEN w = cgetg_copy(D, &l);775for (i = 1; i < l; i++) gel(w,i) = closure_callgen1(worker, gel(D,i));776return w;777}778779/* B <- {A[i] : i = r (mod m)}, 1 <= r <= m */780static void781arithprogset(GEN B, GEN A, long r, long m)782{783long i, k, l = lg(A);784for (k = 1, i = r; i < l; i += m, k++) gel(B, k) = gel(A, i);785setlg(B, k);786}787GEN788gen_parapply_slice(GEN worker, GEN D, long mmin)789{790long l, r, n = lg(D)-1, m = minss(mmin, n), pending = 0;791GEN L = cgetg(n / m + 2, t_VEC), va = mkvec(L), V = cgetg_copy(D, &l);792struct pari_mt pt;793mt_queue_start_lim(&pt, worker, m);794for (r = 1; r <= m || pending; r++)795{796long workid;797GEN done;798if (r <= m) arithprogset(L, D, r, m);799mt_queue_submit(&pt, r, r <= m? va: NULL);800done = mt_queue_get(&pt, &workid, &pending);801if (done)802{803long j, k, J = lg(done)-1;804for (j = 1, k = workid; j <= J; j++, k +=m) gel(V, k) = gel(done, j);805}806}807mt_queue_end(&pt); return V;808}809810GEN811gen_parapply(GEN worker, GEN D)812{813long l = lg(D), i, pending = 0;814GEN W, V;815struct pari_mt pt;816817if (l == 1) return cgetg(1, typ(D));818W = cgetg(2, t_VEC);819V = cgetg(l, typ(D));820mt_queue_start_lim(&pt, worker, l-1);821for (i = 1; i < l || pending; i++)822{823long workid;824GEN done;825if (i < l) gel(W,1) = gel(D,i);826mt_queue_submit(&pt, i, i<l? W: NULL);827done = mt_queue_get(&pt, &workid, &pending);828if (done) gel(V,workid) = done;829}830mt_queue_end(&pt); return V;831}832833GEN834parapply(GEN C, GEN D)835{836pari_sp av = avma;837check_callgen1(C, "parapply");838if (!is_vec_t(typ(D))) pari_err_TYPE("parapply",D);839return gerepileupto(av, gen_parapply(C, D));840}841842GEN843genfold(void *E, GEN (*f)(void* E, GEN x, GEN y), GEN x)844{845pari_sp av = avma;846GEN z;847long i, l = lg(x);848if (!is_vec_t(typ(x))|| l==1 ) pari_err_TYPE("fold",x);849clone_lock(x);850z = gel(x,1);851for (i=2; i<l; i++)852{853z = f(E,z,gel(x,i));854if (gc_needed(av, 2))855{856if (DEBUGMEM>1) pari_warn(warnmem,"fold");857z = gerepilecopy(av, z);858}859}860clone_unlock_deep(x);861return gerepilecopy(av, z);862}863864GEN865fold0(GEN f, GEN x)866{867if (typ(f) != t_CLOSURE || closure_arity(f) < 2) pari_err_TYPE("apply",f);868return genfold((void *) f, gp_call2, x);869}870/*******************************************************************/871/* */872/* SCALAR-MATRIX OPERATIONS */873/* */874/*******************************************************************/875GEN876gtomat(GEN x)877{878long lx, i;879GEN y;880881if (!x) return cgetg(1, t_MAT);882switch(typ(x))883{884case t_LIST:885if (list_typ(x)==t_LIST_MAP)886return maptomat(x);887x = list_data(x);888if (!x) return cgetg(1, t_MAT);889/* fall through */890case t_VEC: {891lx=lg(x); y=cgetg(lx,t_MAT);892if (lx == 1) break;893if (typ(gel(x,1)) == t_COL) {894long h = lgcols(x);895for (i=2; i<lx; i++) {896if (typ(gel(x,i)) != t_COL || lg(gel(x,i)) != h) break;897}898if (i == lx) { /* matrix with h-1 rows */899y = cgetg(lx, t_MAT);900for (i=1 ; i<lx; i++) gel(y,i) = gcopy(gel(x,i));901return y;902}903}904for (i=1; i<lx; i++) gel(y,i) = mkcolcopy(gel(x,i));905break;906}907case t_COL:908lx = lg(x);909if (lx == 1) return cgetg(1, t_MAT);910if (typ(gel(x,1)) == t_VEC) {911long j, h = lg(gel(x,1));912for (i=2; i<lx; i++) {913if (typ(gel(x,i)) != t_VEC || lg(gel(x,i)) != h) break;914}915if (i == lx) { /* matrix with h cols */916y = cgetg(h, t_MAT);917for (j=1 ; j<h; j++) {918gel(y,j) = cgetg(lx, t_COL);919for (i=1; i<lx; i++) gcoeff(y,i,j) = gcopy(gmael(x,i,j));920}921return y;922}923}924y = mkmatcopy(x); break;925case t_MAT:926y = gcopy(x); break;927case t_QFB: {928GEN b;929y = cgetg(3,t_MAT); b = gmul2n(gel(x,2),-1);930gel(y,1) = mkcol2(icopy(gel(x,1)), b);931gel(y,2) = mkcol2(b, icopy(gel(x,3)));932break;933}934default:935y = cgetg(2,t_MAT); gel(y,1) = mkcolcopy(x);936break;937}938return y;939}940941/* create the diagonal matrix, whose diagonal is given by x */942GEN943diagonal(GEN x)944{945long j, lx, tx = typ(x);946GEN y;947948if (! is_matvec_t(tx)) return scalarmat(x,1);949if (tx==t_MAT)950{951if (RgM_isdiagonal(x)) return gcopy(x);952pari_err_TYPE("diagonal",x);953}954lx=lg(x); y=cgetg(lx,t_MAT);955for (j=1; j<lx; j++)956{957gel(y,j) = zerocol(lx-1);958gcoeff(y,j,j) = gcopy(gel(x,j));959}960return y;961}962/* same, assuming x is a t_VEC/t_COL. Not memory clean. */963GEN964diagonal_shallow(GEN x)965{966long j, lx = lg(x);967GEN y = cgetg(lx,t_MAT);968969for (j=1; j<lx; j++)970{971gel(y,j) = zerocol(lx-1);972gcoeff(y,j,j) = gel(x,j);973}974return y;975}976977GEN978zv_diagonal(GEN x)979{980long j, l = lg(x), n = l-1;981GEN y = cgetg(l,t_MAT);982983for (j = 1; j < l; j++)984{985gel(y,j) = zero_Flv(n);986ucoeff(y,j,j) = uel(x,j);987}988return y;989}990991/* compute m*diagonal(d) */992GEN993matmuldiagonal(GEN m, GEN d)994{995long j, lx;996GEN y = cgetg_copy(m, &lx);997998if (typ(m)!=t_MAT) pari_err_TYPE("matmuldiagonal",m);999if (! is_vec_t(typ(d))) pari_err_TYPE("matmuldiagonal",d);1000if (lg(d) != lx) pari_err_OP("operation 'matmuldiagonal'", m,d);1001for (j=1; j<lx; j++) gel(y,j) = RgC_Rg_mul(gel(m,j), gel(d,j));1002return y;1003}10041005/* compute A*B assuming the result is a diagonal matrix */1006GEN1007matmultodiagonal(GEN A, GEN B)1008{1009long i, j, hA, hB, lA = lg(A), lB = lg(B);1010GEN y = matid(lB-1);10111012if (typ(A) != t_MAT) pari_err_TYPE("matmultodiagonal",A);1013if (typ(B) != t_MAT) pari_err_TYPE("matmultodiagonal",B);1014hA = (lA == 1)? lB: lgcols(A);1015hB = (lB == 1)? lA: lgcols(B);1016if (lA != hB || lB != hA) pari_err_OP("operation 'matmultodiagonal'", A,B);1017for (i=1; i<lB; i++)1018{1019GEN z = gen_0;1020for (j=1; j<lA; j++) z = gadd(z, gmul(gcoeff(A,i,j),gcoeff(B,j,i)));1021gcoeff(y,i,i) = z;1022}1023return y;1024}10251026/* [m[1,1], ..., m[l,l]], internal */1027GEN1028RgM_diagonal_shallow(GEN m)1029{1030long i, lx = lg(m);1031GEN y = cgetg(lx,t_VEC);1032for (i=1; i<lx; i++) gel(y, i) = gcoeff(m,i,i);1033return y;1034}10351036/* same, public function */1037GEN1038RgM_diagonal(GEN m)1039{1040long i, lx = lg(m);1041GEN y = cgetg(lx,t_VEC);1042for (i=1; i<lx; i++) gel(y,i) = gcopy(gcoeff(m,i,i));1043return y;1044}104510461047