Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2000 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#include "pari.h"15#include "paripriv.h"1617int18RgM_is_ZM(GEN x)19{20long i, j, h, l = lg(x);21if (l == 1) return 1;22h = lgcols(x);23if (h == 1) return 1;24for (j = l-1; j > 0; j--)25for (i = h-1; i > 0; i--)26if (typ(gcoeff(x,i,j)) != t_INT) return 0;27return 1;28}2930int31RgM_is_QM(GEN x)32{33long i, j, h, l = lg(x);34if (l == 1) return 1;35h = lgcols(x);36if (h == 1) return 1;37for (j = l-1; j > 0; j--)38for (i = h-1; i > 0; i--)39if (!is_rational_t(typ(gcoeff(x,i,j)))) return 0;40return 1;41}4243int44RgV_is_ZMV(GEN V)45{46long i, l = lg(V);47for (i=1; i<l; i++)48if (typ(gel(V,i))!=t_MAT || !RgM_is_ZM(gel(V,i)))49return 0;50return 1;51}5253/********************************************************************/54/** **/55/** GENERIC LINEAR ALGEBRA **/56/** **/57/********************************************************************/58/* GENERIC MULTIPLICATION involving zc/zm */5960/* x[i,] * y */61static GEN62RgMrow_zc_mul_i(GEN x, GEN y, long c, long i)63{64pari_sp av = avma;65GEN s = NULL;66long j;67for (j=1; j<c; j++)68{69long t = y[j];70if (!t) continue;71if (!s) { s = gmulgs(gcoeff(x,i,j),t); continue; }72switch(t)73{74case 1: s = gadd(s, gcoeff(x,i,j)); break;75case -1: s = gsub(s, gcoeff(x,i,j)); break;76default: s = gadd(s, gmulgs(gcoeff(x,i,j), t)); break;77}78}79return s? gerepileupto(av, s): gc_const(av, gen_0);80}81GEN82RgMrow_zc_mul(GEN x, GEN y, long i) { return RgMrow_zc_mul_i(x,y,lg(y),i); }83/* x nonempty t_MAT, y a compatible zc (dimension > 0). */84static GEN85RgM_zc_mul_i(GEN x, GEN y, long c, long l)86{87GEN z = cgetg(l,t_COL);88long i;89for (i = 1; i < l; i++) gel(z,i) = RgMrow_zc_mul_i(x,y,c,i);90return z;91}92GEN93RgM_zc_mul(GEN x, GEN y) { return RgM_zc_mul_i(x,y, lg(x), lgcols(x)); }94/* x t_MAT, y a compatible zm (dimension > 0). */95GEN96RgM_zm_mul(GEN x, GEN y)97{98long j, c, l = lg(x), ly = lg(y);99GEN z = cgetg(ly, t_MAT);100if (l == 1) return z;101c = lgcols(x);102for (j = 1; j < ly; j++) gel(z,j) = RgM_zc_mul_i(x, gel(y,j), l,c);103return z;104}105106/* x[i,]*y, l = lg(y) > 1 */107static GEN108RgMrow_ZC_mul_i(GEN x, GEN y, long i, long l)109{110pari_sp av = avma;111GEN t = gmul(gcoeff(x,i,1), gel(y,1)); /* l > 1 ! */112long j;113for (j=2; j<l; j++)114if (signe(gel(y,j))) t = gadd(t, gmul(gcoeff(x,i,j), gel(y,j)));115return gerepileupto(av,t);116}117118/* compatible t_MAT * t_COL, lx = lg(x) = lg(y) > 1, l = lgcols(x) */119static GEN120RgM_ZC_mul_i(GEN x, GEN y, long lx, long l)121{122GEN z = cgetg(l,t_COL);123long i;124for (i=1; i<l; i++) gel(z,i) = RgMrow_ZC_mul_i(x,y,i,lx);125return z;126}127128/* mostly useful when y is sparse */129GEN130RgM_ZM_mul(GEN x, GEN y)131{132long j, c, l = lg(x), ly = lg(y);133GEN z = cgetg(ly, t_MAT);134if (l == 1) return z;135c = lgcols(x);136for (j = 1; j < ly; j++) gel(z,j) = RgM_ZC_mul_i(x, gel(y,j), l,c);137return z;138}139140static GEN141RgV_zc_mul_i(GEN x, GEN y, long l)142{143long i;144GEN z = gen_0;145pari_sp av = avma;146for (i = 1; i < l; i++) z = gadd(z, gmulgs(gel(x,i), y[i]));147return gerepileupto(av, z);148}149GEN150RgV_zc_mul(GEN x, GEN y) { return RgV_zc_mul_i(x, y, lg(x)); }151152GEN153RgV_zm_mul(GEN x, GEN y)154{155long j, l = lg(x), ly = lg(y);156GEN z = cgetg(ly, t_VEC);157for (j = 1; j < ly; j++) gel(z,j) = RgV_zc_mul_i(x, gel(y,j), l);158return z;159}160161/* scalar product x.x */162GEN163RgV_dotsquare(GEN x)164{165long i, lx = lg(x);166pari_sp av = avma;167GEN z;168if (lx == 1) return gen_0;169z = gsqr(gel(x,1));170for (i=2; i<lx; i++)171{172z = gadd(z, gsqr(gel(x,i)));173if (gc_needed(av,3))174{175if(DEBUGMEM>1) pari_warn(warnmem,"RgV_dotsquare, i = %ld",i);176z = gerepileupto(av, z);177}178}179return gerepileupto(av,z);180}181182/* scalar product x.y, lx = lg(x) = lg(y) */183static GEN184RgV_dotproduct_i(GEN x, GEN y, long lx)185{186pari_sp av = avma;187long i;188GEN z;189if (lx == 1) return gen_0;190z = gmul(gel(x,1),gel(y,1));191for (i=2; i<lx; i++)192{193z = gadd(z, gmul(gel(x,i), gel(y,i)));194if (gc_needed(av,3))195{196if(DEBUGMEM>1) pari_warn(warnmem,"RgV_dotproduct, i = %ld",i);197z = gerepileupto(av, z);198}199}200return gerepileupto(av,z);201}202GEN203RgV_dotproduct(GEN x,GEN y)204{205if (x == y) return RgV_dotsquare(x);206return RgV_dotproduct_i(x, y, lg(x));207}208/* v[1] + ... + v[lg(v)-1] */209GEN210RgV_sum(GEN v)211{212GEN p;213long i, l = lg(v);214if (l == 1) return gen_0;215p = gel(v,1); for (i=2; i<l; i++) p = gadd(p, gel(v,i));216return p;217}218/* v[1] + ... + v[n]. Assume lg(v) > n. */219GEN220RgV_sumpart(GEN v, long n)221{222GEN p;223long i;224if (!n) return gen_0;225p = gel(v,1); for (i=2; i<=n; i++) p = gadd(p, gel(v,i));226return p;227}228/* v[m] + ... + v[n]. Assume lg(v) > n, m > 0. */229GEN230RgV_sumpart2(GEN v, long m, long n)231{232GEN p;233long i;234if (n < m) return gen_0;235p = gel(v,m); for (i=m+1; i<=n; i++) p = gadd(p, gel(v,i));236return p;237}238GEN239RgM_sumcol(GEN A)240{241long i,j,m,l = lg(A);242GEN v;243244if (l == 1) return cgetg(1,t_MAT);245if (l == 2) return gcopy(gel(A,1));246m = lgcols(A);247v = cgetg(m, t_COL);248for (i = 1; i < m; i++)249{250pari_sp av = avma;251GEN s = gcoeff(A,i,1);252for (j = 2; j < l; j++) s = gadd(s, gcoeff(A,i,j));253gel(v, i) = gerepileupto(av, s);254}255return v;256}257258static GEN259_gmul(void *data, GEN x, GEN y)260{ (void)data; return gmul(x,y); }261262GEN263RgV_prod(GEN x)264{265return gen_product(x, NULL, _gmul);266}267268/* ADDITION SCALAR + MATRIX */269/* x square matrix, y scalar; create the square matrix x + y*Id */270GEN271RgM_Rg_add(GEN x, GEN y)272{273long l = lg(x), i, j;274GEN z = cgetg(l,t_MAT);275276if (l==1) return z;277if (l != lgcols(x)) pari_err_OP( "+", x, y);278z = cgetg(l,t_MAT);279for (i=1; i<l; i++)280{281GEN zi = cgetg(l,t_COL), xi = gel(x,i);282gel(z,i) = zi;283for (j=1; j<l; j++)284gel(zi,j) = i==j? gadd(y,gel(xi,j)): gcopy(gel(xi,j));285}286return z;287}288GEN289RgM_Rg_sub(GEN x, GEN y)290{291long l = lg(x), i, j;292GEN z = cgetg(l,t_MAT);293294if (l==1) return z;295if (l != lgcols(x)) pari_err_OP( "-", x, y);296z = cgetg(l,t_MAT);297for (i=1; i<l; i++)298{299GEN zi = cgetg(l,t_COL), xi = gel(x,i);300gel(z,i) = zi;301for (j=1; j<l; j++)302gel(zi,j) = i==j? gsub(gel(xi,j), y): gcopy(gel(xi,j));303}304return z;305}306GEN307RgM_Rg_add_shallow(GEN x, GEN y)308{309long l = lg(x), i, j;310GEN z = cgetg(l,t_MAT);311312if (l==1) return z;313if (l != lgcols(x)) pari_err_OP( "+", x, y);314for (i=1; i<l; i++)315{316GEN zi = cgetg(l,t_COL), xi = gel(x,i);317gel(z,i) = zi;318for (j=1; j<l; j++) gel(zi,j) = gel(xi,j);319gel(zi,i) = gadd(gel(zi,i), y);320}321return z;322}323GEN324RgM_Rg_sub_shallow(GEN x, GEN y)325{326long l = lg(x), i, j;327GEN z = cgetg(l,t_MAT);328329if (l==1) return z;330if (l != lgcols(x)) pari_err_OP( "-", x, y);331for (i=1; i<l; i++)332{333GEN zi = cgetg(l,t_COL), xi = gel(x,i);334gel(z,i) = zi;335for (j=1; j<l; j++) gel(zi,j) = gel(xi,j);336gel(zi,i) = gsub(gel(zi,i), y);337}338return z;339}340341GEN342RgC_Rg_add(GEN x, GEN y)343{344long k, lx = lg(x);345GEN z = cgetg(lx, t_COL);346if (lx == 1)347{348if (isintzero(y)) return z;349pari_err_TYPE2("+",x,y);350}351gel(z,1) = gadd(y,gel(x,1));352for (k = 2; k < lx; k++) gel(z,k) = gcopy(gel(x,k));353return z;354}355GEN356RgC_Rg_sub(GEN x, GEN y)357{358long k, lx = lg(x);359GEN z = cgetg(lx, t_COL);360if (lx == 1)361{362if (isintzero(y)) return z;363pari_err_TYPE2("-",x,y);364}365gel(z,1) = gsub(gel(x,1), y);366for (k = 2; k < lx; k++) gel(z,k) = gcopy(gel(x,k));367return z;368}369/* a - x */370GEN371Rg_RgC_sub(GEN a, GEN x)372{373long k, lx = lg(x);374GEN z = cgetg(lx,t_COL);375if (lx == 1)376{377if (isintzero(a)) return z;378pari_err_TYPE2("-",a,x);379}380gel(z,1) = gsub(a, gel(x,1));381for (k = 2; k < lx; k++) gel(z,k) = gneg(gel(x,k));382return z;383}384385static GEN386RgC_add_i(GEN x, GEN y, long lx)387{388GEN A = cgetg(lx, t_COL);389long i;390for (i=1; i<lx; i++) gel(A,i) = gadd(gel(x,i), gel(y,i));391return A;392}393GEN394RgC_add(GEN x, GEN y) { return RgC_add_i(x, y, lg(x)); }395GEN396RgV_add(GEN x, GEN y)397{ pari_APPLY_type(t_VEC, gadd(gel(x,i), gel(y,i))) }398399static GEN400RgC_sub_i(GEN x, GEN y, long lx)401{402long i;403GEN A = cgetg(lx, t_COL);404for (i=1; i<lx; i++) gel(A,i) = gsub(gel(x,i), gel(y,i));405return A;406}407GEN408RgC_sub(GEN x, GEN y) { return RgC_sub_i(x, y, lg(x)); }409GEN410RgV_sub(GEN x, GEN y)411{ pari_APPLY_type(t_VEC, gsub(gel(x,i), gel(y,i))) }412413GEN414RgM_add(GEN x, GEN y)415{416long lx = lg(x), l, j;417GEN z;418if (lx == 1) return cgetg(1, t_MAT);419z = cgetg(lx, t_MAT); l = lgcols(x);420for (j = 1; j < lx; j++) gel(z,j) = RgC_add_i(gel(x,j), gel(y,j), l);421return z;422}423GEN424RgM_sub(GEN x, GEN y)425{426long lx = lg(x), l, j;427GEN z;428if (lx == 1) return cgetg(1, t_MAT);429z = cgetg(lx, t_MAT); l = lgcols(x);430for (j = 1; j < lx; j++) gel(z,j) = RgC_sub_i(gel(x,j), gel(y,j), l);431return z;432}433434static GEN435RgC_neg_i(GEN x, long lx)436{437long i;438GEN y = cgetg(lx, t_COL);439for (i=1; i<lx; i++) gel(y,i) = gneg(gel(x,i));440return y;441}442GEN443RgC_neg(GEN x) { return RgC_neg_i(x, lg(x)); }444GEN445RgV_neg(GEN x)446{ pari_APPLY_type(t_VEC, gneg(gel(x,i))) }447GEN448RgM_neg(GEN x)449{450long i, hx, lx = lg(x);451GEN y = cgetg(lx, t_MAT);452if (lx == 1) return y;453hx = lgcols(x);454for (i=1; i<lx; i++) gel(y,i) = RgC_neg_i(gel(x,i), hx);455return y;456}457458GEN459RgV_RgC_mul(GEN x, GEN y)460{461long lx = lg(x);462if (lx != lg(y)) pari_err_OP("operation 'RgV_RgC_mul'", x, y);463return RgV_dotproduct_i(x, y, lx);464}465GEN466RgC_RgV_mul(GEN x, GEN y)467{468long i, ly = lg(y);469GEN z = cgetg(ly,t_MAT);470for (i=1; i<ly; i++) gel(z,i) = RgC_Rg_mul(x, gel(y,i));471return z;472}473GEN474RgC_RgM_mul(GEN x, GEN y)475{476long i, ly = lg(y);477GEN z = cgetg(ly,t_MAT);478if (ly != 1 && lgcols(y) != 2) pari_err_OP("operation 'RgC_RgM_mul'",x,y);479for (i=1; i<ly; i++) gel(z,i) = RgC_Rg_mul(x, gcoeff(y,1,i));480return z;481}482GEN483RgM_RgV_mul(GEN x, GEN y)484{485if (lg(x) != 2) pari_err_OP("operation 'RgM_RgV_mul'", x,y);486return RgC_RgV_mul(gel(x,1), y);487}488489/* x[i,]*y, l = lg(y) > 1 */490static GEN491RgMrow_RgC_mul_i(GEN x, GEN y, long i, long l)492{493pari_sp av = avma;494GEN t = gmul(gcoeff(x,i,1), gel(y,1)); /* l > 1 ! */495long j;496for (j=2; j<l; j++)497{498GEN c = gcoeff(x,i,j);499if (!isintzero(c)) t = gadd(t, gmul(c, gel(y,j)));500}501return gerepileupto(av,t);502}503GEN504RgMrow_RgC_mul(GEN x, GEN y, long i)505{ return RgMrow_RgC_mul_i(x, y, i, lg(x)); }506507static GEN508RgM_RgC_mul_FpM(GEN x, GEN y, GEN p)509{510pari_sp av = avma;511GEN r;512if (lgefint(p) == 3)513{514ulong pp = uel(p, 2);515r = Flc_to_ZC_inplace(Flm_Flc_mul(RgM_to_Flm(x, pp),516RgV_to_Flv(y, pp), pp));517}518else519r = FpM_FpC_mul(RgM_to_FpM(x, p), RgC_to_FpC(y, p), p);520return gerepileupto(av, FpC_to_mod(r, p));521}522523static GEN524RgM_RgC_mul_FqM(GEN x, GEN y, GEN pol, GEN p)525{526pari_sp av = avma;527GEN b, T = RgX_to_FpX(pol, p);528if (signe(T) == 0) pari_err_OP("*", x, y);529b = FqM_FqC_mul(RgM_to_FqM(x, T, p), RgC_to_FqC(y, T, p), T, p);530return gerepileupto(av, FqC_to_mod(b, T, p));531}532533#define code(t1,t2) ((t1 << 6) | t2)534static GEN535RgM_RgC_mul_fast(GEN x, GEN y)536{537GEN p, pol;538long pa;539long t = RgM_RgC_type(x,y, &p,&pol,&pa);540switch(t)541{542case t_INT: return ZM_ZC_mul(x,y);543case t_FRAC: return QM_QC_mul(x,y);544case t_FFELT: return FFM_FFC_mul(x, y, pol);545case t_INTMOD: return RgM_RgC_mul_FpM(x, y, p);546case code(t_POLMOD, t_INTMOD):547return RgM_RgC_mul_FqM(x, y, pol, p);548default: return NULL;549}550}551#undef code552553/* compatible t_MAT * t_COL, lx = lg(x) = lg(y) > 1, l = lgcols(x) */554static GEN555RgM_RgC_mul_i(GEN x, GEN y, long lx, long l)556{557GEN z = cgetg(l,t_COL);558long i;559for (i=1; i<l; i++) gel(z,i) = RgMrow_RgC_mul_i(x,y,i,lx);560return z;561}562563GEN564RgM_RgC_mul(GEN x, GEN y)565{566long lx = lg(x);567GEN z;568if (lx != lg(y)) pari_err_OP("operation 'RgM_RgC_mul'", x,y);569if (lx == 1) return cgetg(1,t_COL);570z = RgM_RgC_mul_fast(x, y);571if (z) return z;572return RgM_RgC_mul_i(x, y, lx, lgcols(x));573}574575GEN576RgV_RgM_mul(GEN x, GEN y)577{578long i, lx, ly = lg(y);579GEN z;580if (ly == 1) return cgetg(1,t_VEC);581lx = lg(x);582if (lx != lgcols(y)) pari_err_OP("operation 'RgV_RgM_mul'", x,y);583z = cgetg(ly, t_VEC);584for (i=1; i<ly; i++) gel(z,i) = RgV_dotproduct_i(x, gel(y,i), lx);585return z;586}587588static GEN589RgM_mul_FpM(GEN x, GEN y, GEN p)590{591pari_sp av = avma;592GEN r;593if (lgefint(p) == 3)594{595ulong pp = uel(p, 2);596if (pp==2)597r = F2m_to_ZM(F2m_mul(RgM_to_F2m(x), RgM_to_F2m(y)));598else if (pp==3)599r = F3m_to_ZM(F3m_mul(RgM_to_F3m(x), RgM_to_F3m(y)));600else601r = Flm_to_ZM_inplace(Flm_mul(RgM_to_Flm(x, pp),602RgM_to_Flm(y, pp), pp));603}604else605r = FpM_mul(RgM_to_FpM(x, p), RgM_to_FpM(y, p), p);606return gerepileupto(av, FpM_to_mod(r, p));607}608609static GEN610RgM_mul_FqM(GEN x, GEN y, GEN pol, GEN p)611{612pari_sp av = avma;613GEN b, T = RgX_to_FpX(pol, p);614if (signe(T) == 0) pari_err_OP("*", x, y);615b = FqM_mul(RgM_to_FqM(x, T, p), RgM_to_FqM(y, T, p), T, p);616return gerepileupto(av, FqM_to_mod(b, T, p));617}618619static GEN620RgM_liftred(GEN x, GEN T)621{ return RgXQM_red(liftpol_shallow(x), T); }622623static GEN624RgM_mul_ZXQM(GEN x, GEN y, GEN T)625{626pari_sp av = avma;627GEN b = ZXQM_mul(RgM_liftred(x,T), RgM_liftred(y, T), T);628return gerepilecopy(av, QXQM_to_mod_shallow(b,T));629}630631static GEN632RgM_sqr_ZXQM(GEN x, GEN T)633{634pari_sp av = avma;635GEN b = ZXQM_sqr(RgM_liftred(x, T), T);636return gerepilecopy(av, QXQM_to_mod_shallow(b,T));637}638639static GEN640RgM_mul_QXQM(GEN x, GEN y, GEN T)641{642pari_sp av = avma;643GEN b = QXQM_mul(RgM_liftred(x, T), RgM_liftred(y, T), T);644return gerepilecopy(av, QXQM_to_mod_shallow(b,T));645}646647static GEN648RgM_sqr_QXQM(GEN x, GEN T)649{650pari_sp av = avma;651GEN b = QXQM_sqr(RgM_liftred(x, T), T);652return gerepilecopy(av, QXQM_to_mod_shallow(b,T));653}654655INLINE int656RgX_is_monic_ZX(GEN pol)657{ return RgX_is_ZX(pol) && ZX_is_monic(pol); }658659#define code(t1,t2) ((t1 << 6) | t2)660static GEN661RgM_mul_fast(GEN x, GEN y)662{663GEN p, pol;664long pa;665long t = RgM_type2(x,y, &p,&pol,&pa);666switch(t)667{668case t_INT: return ZM_mul(x,y);669case t_FRAC: return QM_mul(x,y);670case t_FFELT: return FFM_mul(x, y, pol);671case t_INTMOD: return RgM_mul_FpM(x, y, p);672case code(t_POLMOD, t_INT):673return ZX_is_monic(pol)? RgM_mul_ZXQM(x, y, pol): NULL;674case code(t_POLMOD, t_FRAC):675return RgX_is_monic_ZX(pol)? RgM_mul_QXQM(x, y, pol): NULL;676case code(t_POLMOD, t_INTMOD):677return RgM_mul_FqM(x, y, pol, p);678default: return NULL;679}680}681682static GEN683RgM_sqr_fast(GEN x)684{685GEN p, pol;686long pa;687long t = RgM_type(x, &p,&pol,&pa);688switch(t)689{690case t_INT: return ZM_sqr(x);691case t_FRAC: return QM_sqr(x);692case t_FFELT: return FFM_mul(x, x, pol);693case t_INTMOD: return RgM_mul_FpM(x, x, p);694case code(t_POLMOD, t_INT):695return ZX_is_monic(pol)? RgM_sqr_ZXQM(x, pol): NULL;696case code(t_POLMOD, t_FRAC):697return RgX_is_monic_ZX(pol)? RgM_sqr_QXQM(x, pol): NULL;698case code(t_POLMOD, t_INTMOD):699return RgM_mul_FqM(x, x, pol, p);700default: return NULL;701}702}703704#undef code705706/* lx, ly > 1 */707static GEN708RgM_mul_basic(GEN x, GEN y, long lx, long ly)709{710GEN z = cgetg(ly, t_MAT);711long j, l = lgcols(x);712for (j = 1; j < ly; j++) gel(z,j) = RgM_RgC_mul_i(x, gel(y,j), lx, l);713return z;714}715GEN716RgM_mul_i(GEN x, GEN y)717{718long lx, ly = lg(y);719if (ly == 1) return cgetg(1,t_MAT);720lx = lg(x);721if (lx != lgcols(y)) pari_err_OP("operation 'RgM_mul'", x,y);722if (lx == 1) return zeromat(0,ly-1);723return RgM_mul_basic(x, y, lx, ly);724}725GEN726RgM_mul(GEN x, GEN y)727{728long lx, ly = lg(y);729GEN z;730if (ly == 1) return cgetg(1,t_MAT);731lx = lg(x);732if (lx != lgcols(y)) pari_err_OP("operation 'RgM_mul'", x,y);733if (lx == 1) return zeromat(0,ly-1);734z = RgM_mul_fast(x, y);735if (z) return z;736return RgM_mul_basic(x, y, lx, ly);737}738739GEN740RgM_sqr(GEN x)741{742long j, lx = lg(x);743GEN z;744if (lx == 1) return cgetg(1, t_MAT);745if (lx != lgcols(x)) pari_err_OP("operation 'RgM_mul'", x,x);746z = RgM_sqr_fast(x);747if (z) return z;748z = cgetg(lx, t_MAT);749for (j=1; j<lx; j++) gel(z,j) = RgM_RgC_mul_i(x, gel(x,j), lx, lx);750return z;751}752753/* assume result is symmetric */754GEN755RgM_multosym(GEN x, GEN y)756{757long j, lx, ly = lg(y);758GEN M;759if (ly == 1) return cgetg(1,t_MAT);760lx = lg(x);761if (lx != lgcols(y)) pari_err_OP("operation 'RgM_multosym'", x,y);762if (lx == 1) return cgetg(1,t_MAT);763if (ly != lgcols(x)) pari_err_OP("operation 'RgM_multosym'", x,y);764M = cgetg(ly, t_MAT);765for (j=1; j<ly; j++)766{767GEN z = cgetg(ly,t_COL), yj = gel(y,j);768long i;769for (i=1; i<j; i++) gel(z,i) = gcoeff(M,j,i);770for (i=j; i<ly; i++)gel(z,i) = RgMrow_RgC_mul_i(x,yj,i,lx);771gel(M,j) = z;772}773return M;774}775/* x~ * y, assuming result is symmetric */776GEN777RgM_transmultosym(GEN x, GEN y)778{779long i, j, l, ly = lg(y);780GEN M;781if (ly == 1) return cgetg(1,t_MAT);782if (lg(x) != ly) pari_err_OP("operation 'RgM_transmultosym'", x,y);783l = lgcols(y);784if (lgcols(x) != l) pari_err_OP("operation 'RgM_transmultosym'", x,y);785M = cgetg(ly, t_MAT);786for (i=1; i<ly; i++)787{788GEN xi = gel(x,i), c = cgetg(ly,t_COL);789gel(M,i) = c;790for (j=1; j<i; j++)791gcoeff(M,i,j) = gel(c,j) = RgV_dotproduct_i(xi,gel(y,j),l);792gel(c,i) = RgV_dotproduct_i(xi,gel(y,i),l);793}794return M;795}796/* x~ * y */797GEN798RgM_transmul(GEN x, GEN y)799{800long i, j, l, lx, ly = lg(y);801GEN M;802if (ly == 1) return cgetg(1,t_MAT);803lx = lg(x);804l = lgcols(y);805if (lgcols(x) != l) pari_err_OP("operation 'RgM_transmul'", x,y);806M = cgetg(ly, t_MAT);807for (i=1; i<ly; i++)808{809GEN yi = gel(y,i), c = cgetg(lx,t_COL);810gel(M,i) = c;811for (j=1; j<lx; j++) gel(c,j) = RgV_dotproduct_i(yi,gel(x,j),l);812}813return M;814}815816GEN817gram_matrix(GEN x)818{819long i,j, l, lx = lg(x);820GEN M;821if (!is_matvec_t(typ(x))) pari_err_TYPE("gram",x);822if (lx == 1) return cgetg(1,t_MAT);823l = lgcols(x);824M = cgetg(lx,t_MAT);825for (i=1; i<lx; i++)826{827GEN xi = gel(x,i), c = cgetg(lx,t_COL);828gel(M,i) = c;829for (j=1; j<i; j++)830gcoeff(M,i,j) = gel(c,j) = RgV_dotproduct_i(xi,gel(x,j),l);831gel(c,i) = RgV_dotsquare(xi);832}833return M;834}835836static GEN837_RgM_add(void *E, GEN x, GEN y) { (void)E; return RgM_add(x, y); }838839static GEN840_RgM_sub(void *E, GEN x, GEN y) { (void)E; return RgM_sub(x, y); }841842static GEN843_RgM_cmul(void *E, GEN P, long a, GEN x) { (void)E; return RgM_Rg_mul(x,gel(P,a+2)); }844845static GEN846_RgM_sqr(void *E, GEN x) { (void) E; return RgM_sqr(x); }847848static GEN849_RgM_mul(void *E, GEN x, GEN y) { (void) E; return RgM_mul(x, y); }850851static GEN852_RgM_one(void *E) { long *n = (long*) E; return matid(*n); }853854static GEN855_RgM_zero(void *E) { long *n = (long*) E; return zeromat(*n,*n); }856857static GEN858_RgM_red(void *E, GEN x) { (void)E; return x; }859860static struct bb_algebra RgM_algebra = { _RgM_red, _RgM_add, _RgM_sub,861_RgM_mul, _RgM_sqr, _RgM_one, _RgM_zero };862863/* generates the list of powers of x of degree 0,1,2,...,l*/864GEN865RgM_powers(GEN x, long l)866{867long n = lg(x)-1;868return gen_powers(x,l,1,(void *) &n, &_RgM_sqr, &_RgM_mul, &_RgM_one);869}870871GEN872RgX_RgMV_eval(GEN Q, GEN x)873{874long n = lg(x)>1 ? lg(gel(x,1))-1:0;875return gen_bkeval_powers(Q,degpol(Q),x,(void*)&n,&RgM_algebra,&_RgM_cmul);876}877878GEN879RgX_RgM_eval(GEN Q, GEN x)880{881long n = lg(x)-1;882return gen_bkeval(Q,degpol(Q),x,1,(void*)&n,&RgM_algebra,&_RgM_cmul);883}884885GEN886RgC_Rg_div(GEN x, GEN y)887{ pari_APPLY_type(t_COL, gdiv(gel(x,i),y)) }888889GEN890RgC_Rg_mul(GEN x, GEN y)891{ pari_APPLY_type(t_COL, gmul(gel(x,i),y)) }892893GEN894RgV_Rg_mul(GEN x, GEN y)895{ pari_APPLY_type(t_VEC, gmul(gel(x,i),y)) }896897GEN898RgM_Rg_div(GEN X, GEN c) {899long i, j, h, l = lg(X);900GEN A = cgetg(l, t_MAT);901if (l == 1) return A;902h = lgcols(X);903for (j=1; j<l; j++)904{905GEN a = cgetg(h, t_COL), x = gel(X, j);906for (i = 1; i < h; i++) gel(a,i) = gdiv(gel(x,i), c);907gel(A,j) = a;908}909return A;910}911GEN912RgM_Rg_mul(GEN X, GEN c) {913long i, j, h, l = lg(X);914GEN A = cgetg(l, t_MAT);915if (l == 1) return A;916h = lgcols(X);917for (j=1; j<l; j++)918{919GEN a = cgetg(h, t_COL), x = gel(X, j);920for (i = 1; i < h; i++) gel(a,i) = gmul(gel(x,i), c);921gel(A,j) = a;922}923return A;924}925926/********************************************************************/927/* */928/* SCALAR TO MATRIX/VECTOR */929/* */930/********************************************************************/931/* fill the square nxn matrix equal to t*Id */932static void933fill_scalmat(GEN y, GEN t, long n)934{935long i;936for (i = 1; i <= n; i++)937{938gel(y,i) = zerocol(n);939gcoeff(y,i,i) = t;940}941}942943GEN944scalarmat(GEN x, long n) {945GEN y = cgetg(n+1, t_MAT);946if (!n) return y;947fill_scalmat(y, gcopy(x), n); return y;948}949GEN950scalarmat_shallow(GEN x, long n) {951GEN y = cgetg(n+1, t_MAT);952fill_scalmat(y, x, n); return y;953}954GEN955scalarmat_s(long x, long n) {956GEN y = cgetg(n+1, t_MAT);957if (!n) return y;958fill_scalmat(y, stoi(x), n); return y;959}960GEN961matid(long n) {962GEN y;963if (n < 0) pari_err_DOMAIN("matid", "size", "<", gen_0, stoi(n));964y = cgetg(n+1, t_MAT);965fill_scalmat(y, gen_1, n); return y;966}967968INLINE GEN969scalarcol_i(GEN x, long n, long c)970{971long i;972GEN y = cgetg(n+1,t_COL);973if (!n) return y;974gel(y,1) = c? gcopy(x): x;975for (i=2; i<=n; i++) gel(y,i) = gen_0;976return y;977}978979GEN980scalarcol(GEN x, long n) { return scalarcol_i(x,n,1); }981982GEN983scalarcol_shallow(GEN x, long n) { return scalarcol_i(x,n,0); }984985int986RgM_isscalar(GEN x, GEN s)987{988long i, j, lx = lg(x);989990if (lx == 1) return 1;991if (lx != lgcols(x)) return 0;992if (!s) s = gcoeff(x,1,1);993994for (j=1; j<lx; j++)995{996GEN c = gel(x,j);997for (i=1; i<j; )998if (!gequal0(gel(c,i++))) return 0;999/* i = j */1000if (!gequal(gel(c,i++),s)) return 0;1001for ( ; i<lx; )1002if (!gequal0(gel(c,i++))) return 0;1003}1004return 1;1005}10061007int1008RgM_isidentity(GEN x)1009{1010long i,j, lx = lg(x);10111012if (lx == 1) return 1;1013if (lx != lgcols(x)) return 0;1014for (j=1; j<lx; j++)1015{1016GEN c = gel(x,j);1017for (i=1; i<j; )1018if (!gequal0(gel(c,i++))) return 0;1019/* i = j */1020if (!gequal1(gel(c,i++))) return 0;1021for ( ; i<lx; )1022if (!gequal0(gel(c,i++))) return 0;1023}1024return 1;1025}10261027long1028RgC_is_ei(GEN x)1029{1030long i, j = 0, l = lg(x);1031for (i = 1; i < l; i++)1032{1033GEN c = gel(x,i);1034if (gequal0(c)) continue;1035if (!gequal1(c) || j) return 0;1036j = i;1037}1038return j;1039}10401041int1042RgM_isdiagonal(GEN x)1043{1044long i,j, lx = lg(x);1045if (lx == 1) return 1;1046if (lx != lgcols(x)) return 0;10471048for (j=1; j<lx; j++)1049{1050GEN c = gel(x,j);1051for (i=1; i<j; i++)1052if (!gequal0(gel(c,i))) return 0;1053for (i++; i<lx; i++)1054if (!gequal0(gel(c,i))) return 0;1055}1056return 1;1057}1058int1059isdiagonal(GEN x) { return (typ(x)==t_MAT) && RgM_isdiagonal(x); }10601061GEN1062RgM_det_triangular(GEN mat)1063{1064long i,l = lg(mat);1065pari_sp av;1066GEN s;10671068if (l<3) return l<2? gen_1: gcopy(gcoeff(mat,1,1));1069av = avma; s = gcoeff(mat,1,1);1070for (i=2; i<l; i++) s = gmul(s,gcoeff(mat,i,i));1071return av==avma? gcopy(s): gerepileupto(av,s);1072}10731074GEN1075RgV_kill0(GEN v)1076{1077long i, l;1078GEN w = cgetg_copy(v, &l);1079for (i = 1; i < l; i++)1080{1081GEN a = gel(v,i);1082gel(w,i) = gequal0(a) ? NULL: a;1083}1084return w;1085}108610871088