/********************************************************************/ /** **/ /** GENERIC OPERATIONS **/ /** (second part) **/ /** **/ /********************************************************************/ /* $Id: gen2.c,v 1.3 1999/09/23 17:50:56 karim Exp $ */ #include "pari.h" /*******************************************************************/ /* */ /* OPERATIONS BY VALUE */ /* f is a pointer to the function called. */ /* result is gaffect-ed to last parameter */ /* */ /*******************************************************************/ void gop1z(GEN (*f)(GEN), GEN x, GEN y) { long av=avma; gaffect(f(x),y); avma=av; } void gop2z(GEN (*f)(GEN, GEN), GEN x, GEN y, GEN z) { long av=avma; gaffect(f(x,y),z); avma=av; } void gops2gsz(GEN (*f)(GEN, long), GEN x, long s, GEN z) { long av=avma; gaffect(f(x,s),z); avma=av; } void gops2sgz(GEN (*f)(long, GEN), long s, GEN y, GEN z) { long av=avma; gaffect(f(s,y),z); avma=av; } void gops2ssz(GEN (*f)(long, long), long s, long y, GEN z) { long av=avma; gaffect(f(s,y),z); avma=av; } /*******************************************************************/ /* */ /* OPERATIONS USING SMALL INTEGERS */ /* */ /*******************************************************************/ /* small int prototype */ static long court_p[] = { evaltyp(t_INT) | m_evallg(3),0,0 }; GEN gopsg2(GEN (*f)(GEN, GEN), long s, GEN y) { affsi(s,court_p); return f(court_p,y); } GEN gopgs2(GEN (*f)(GEN, GEN), GEN y, long s) { affsi(s,court_p); return f(y,court_p); } long opgs2(int (*f)(GEN, GEN), GEN y, long s) { affsi(s,court_p); return f(y,court_p); } void gopsg2z(GEN (*f)(GEN, GEN), long s, GEN y, GEN z) { long av=avma; affsi(s,court_p); gaffect(f(court_p,y),z); avma=av; } void gopgs2z(GEN (*f)(GEN, GEN), GEN y, long s, GEN z) { long av=avma; affsi(s,court_p); gaffect(f(y,court_p),z); avma=av; } /*******************************************************************/ /* */ /* CREATION OF A P-ADIC GEN */ /* */ /*******************************************************************/ GEN cgetp(GEN x) { GEN y = cgetg(5,t_PADIC); y[1] = evalprecp(precp(x)) | evalvalp(0); icopyifstack(x[2], y[2]); y[3] = licopy((GEN)x[3]); y[4] = lgeti(lgefint(x[3])); return y; } /* y[4] not filled */ GEN cgetp2(GEN x, long v) { GEN y = cgetg(5,t_PADIC); y[1] = evalprecp(precp(x)) | evalvalp(v); icopyifstack(x[2], y[2]); y[3] = licopy((GEN)x[3]); return y; } /*******************************************************************/ /* */ /* CLONING & COPY */ /* Replicate an existing GEN */ /* */ /*******************************************************************/ /* lontyp = 0 means non recursive type * otherwise: * lontyp = number of codewords * if not in stack, we don't copy the words in [lontyp,lontyp2[ */ const long lontyp[] = { 0,0,0,1,1,1,1,2,1,1, 2,2,0,1,1,1,1,1,1,1, 2,0,0 }; static long lontyp2[] = { 0,0,0,2,1,1,1,3,2,2, 2,2,0,1,1,1,1,1,1,1, 2,0,0 }; /* can't do a memcpy there: avma and x may overlap. memmove is slower */ GEN gcopy(GEN x) { long tx=typ(x),lx,i; GEN y; if (tx == t_SMALL) return x; lx = lg(x); y=new_chunk(lx); if (! is_recursive_t(tx)) for (i=lx-1; i>=0; i--) y[i]=x[i]; else { if (tx==t_POL || tx==t_LIST) lx=lgef(x); for (i=0; i0; i--) y[i]=x[i]; else { for (i=1; i=0; i--) y[i]=x[i]; else { if (tx==t_POL || tx==t_LIST) lx=lgef(x); for (i=0; i= 0) z[lx] = x[lx]; return z; } long taille(GEN x) { long i,n,lx=lg(x),tx=typ(x); n = lx; if (is_recursive_t(tx)) { if (tx==t_POL || tx==t_LIST) lx = lgef(x); for (i=lontyp[tx]; ik) { y[i]=zero; i--; } while (i>=2) { y[i]=x[i+e]; i--; } return y; } /*******************************************************************/ /* */ /* CONVERSION GEN --> long */ /* */ /*******************************************************************/ long gtolong(GEN x) { long y,tx=typ(x),av=avma; switch(tx) { case t_INT: return itos(x); case t_REAL: case t_FRAC: case t_FRACN: y=itos(ground(x)); avma=av; return y; case t_COMPLEX: if (gcmp0((GEN)x[2])) return gtolong((GEN)x[1]); break; case t_QUAD: if (gcmp0((GEN)x[3])) return gtolong((GEN)x[2]); break; } err(typeer,"gtolong"); return 0; /* not reached */ } /*******************************************************************/ /* */ /* COMPARE TO ZERO */ /* returns 1 whenever the GEN x is 0, and 0 otherwise */ /* */ /*******************************************************************/ int gcmp0(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_POL: case t_SER: return !signe(x); case t_INTMOD: case t_POLMOD: return gcmp0((GEN)x[2]); case t_FRAC: case t_FRACN: return !signe(x[1]); case t_COMPLEX: /* is 0 iff norm(x) would be 0 (can happen with Re(x) and Im(x) != 0 * only if Re(x) and Im(x) are of type t_REAL). See mp.c:addrr(). */ if (gcmp0((GEN)x[1])) { if (gcmp0((GEN)x[2])) return 1; if (typ(x[1])!=t_REAL || typ(x[2])!=t_REAL) return 0; return (expo(x[1])>expo(x[2])); } if (gcmp0((GEN)x[2])) { if (typ(x[1])!=t_REAL || typ(x[2])!=t_REAL) return 0; return (expo(x[2])>expo(x[1])); } return 0; case t_PADIC: return !signe(x[4]); case t_QUAD: return gcmp0((GEN)x[2]) && gcmp0((GEN)x[3]); case t_RFRAC: case t_RFRACN: return gcmp0((GEN)x[1]); case t_VEC: case t_COL: case t_MAT: { long i; for (i=lg(x)-1; i; i--) if (!gcmp0((GEN)x[i])) return 0; return 1; } } return 0; } /*******************************************************************/ /* */ /* COMPARE TO 1 and -1 */ /* returns 1 whenever the GEN x is 1 (resp. -1), 0 otherwise */ /* */ /*******************************************************************/ int gcmp1(GEN x) { switch(typ(x)) { case t_INT: return is_pm1(x) && signe(x)==1; case t_REAL: if (signe(x) > 0 && expo(x)==0 && x[2]==HIGHBIT) { long i,lx = lg(x); for (i=3; i2)? -1:0; } lx=lg(x); if (!is_matvec_t(ty)) { if (lx==1) return -1; fl = lexcmp(y,(GEN)x[1]); if (fl) return -fl; return (lx>2)? 1:0; } /* x and y are matvec_t */ if (ly==1) return (lx==1)?0:1; if (lx==1) return -1; if (ty==t_MAT) { if (tx != t_MAT) { fl = lexcmp(x,(GEN)y[1]); if (fl) return fl; return (ly>2)?-1:0; } } else if (tx==t_MAT) { fl = lexcmp(y,(GEN)x[1]); if (fl) return -fl; return (ly>2)?1:0; } /* tx = ty = t_MAT, or x and y are both vect_t */ l=min(lx,ly); for (i=1; i 3)) return 0; for (i = 2; i < lx; i++) if (!gegal((GEN)x[i],(GEN)y[i])) return 0; return 1; } #define MASK(x) (((ulong)(x)) & (TYPBITS | LGBITS)) static int vecegal(GEN x, GEN y) { long i, tx = typ(x); if (!is_matvec_t(tx)) return gegal(x,y); if (MASK(x[0]) != MASK(y[0])) return 0; i = lg(x)-1; if (tx != t_MAT) { for ( ; i; i--) if (! gegal((GEN)x[i],(GEN)y[i]) ) return 0; return 1; } for ( ; i; i--) if (! vecegal((GEN)x[i],(GEN)y[i]) ) return 0; return 1; } #undef MASK #define MASK(x) (((ulong)(x)) & (LGEFINTBITS | SIGNBITS)) int egalii(GEN x, GEN y) { long i; if (MASK(x[1]) != MASK(y[1])) return 0; i = lgefint(x)-1; while (i>1 && x[i]==y[i]) i--; return i==1; } #undef MASK int gegal(GEN x, GEN y) { long av,i,tx,ty; if (x == y) return 1; tx = typ(x); ty = typ(y); if (tx!=ty) { if (tx == t_STR || ty == t_STR) return 0; } else switch(tx) { case t_INT: return egalii(x,y); case t_POL: return polegal(x,y); case t_COMPLEX: return gegal((GEN)x[1],(GEN)y[1]) && gegal((GEN)x[2],(GEN)y[2]); case t_INTMOD: case t_POLMOD: return gegal((GEN)x[2],(GEN)y[2]) && (x[1]==y[1] || gegal((GEN)x[1],(GEN)y[1])); case t_QFR: if (!gegal((GEN)x[4],(GEN)y[4])) return 0; /* fall through */ case t_QUAD: case t_QFI: return gegal((GEN)x[1],(GEN)y[1]) && gegal((GEN)x[2],(GEN)y[2]) && gegal((GEN)x[3],(GEN)y[3]); case t_FRAC: return gegal((GEN)x[1], (GEN)y[1]) && gegal((GEN)x[2], (GEN)y[2]); case t_FRACN: case t_RFRAC: case t_RFRACN: av=avma; i=gegal(gmul((GEN)x[1],(GEN)y[2]),gmul((GEN)x[2],(GEN)y[1])); avma=av; return i; case t_STR: return !strcmp(GSTR(x),GSTR(y)); case t_VEC: case t_COL: case t_MAT: return vecegal(x,y); } av=avma; y=gneg_i(y); i=gcmp0(gadd(x,y)); avma=av; return i; } /*******************************************************************/ /* */ /* VALUATION */ /* p is either an int or a polynomial. */ /* returns the largest exponent of p dividing x when this makes */ /* sense : error for types real, integermod and polymod if p does */ /* not divide the modulus, q-adic if q!=p. */ /* */ /*******************************************************************/ static long minval(GEN x, GEN p, long first, long lx) { long i,k, val = VERYBIGINT; for (i=first; i=(GEN)polx && p <= (GEN)(polx+MAXVARN)) || ismonome(p)) { i=2; while (isexactzero((GEN)x[i])) i++; return i-2; } av = avma; limit=stack_lim(av,1); for (val=0; ; val++) { if (!poldivis(x,p,&x)) break; if (low_stack(limit, stack_lim(av,1))) { if(DEBUGMEM>1) err(warnmem,"ggval"); x = gerepileupto(av, gcopy(x)); } } avma = av; return val; } if (vx > v) return 0; } else { if (tp!=t_INT) break; i=2; while (isexactzero((GEN)x[i])) i++; } return minval(x,p,i,lgef(x)); case t_SER: if (tp!=t_POL && tp!=t_SER && tp!=t_INT) break; v=gvar(p); vx=varn(x); if (vx==v) return (long)(valp(x)/ggval(p,polx[v])); if (vx>v) return 0; return minval(x,p,2,lg(x)); case t_FRAC: case t_FRACN: case t_RFRAC: case t_RFRACN: return ggval((GEN)x[1],p) - ggval((GEN)x[2],p); case t_COMPLEX: case t_QUAD: case t_VEC: case t_COL: case t_MAT: return minval(x,p,1,lg(x)); } err(talker,"forbidden or conflicting type in gval"); return 0; /* not reached */ } /* x is non-zero */ long svaluation(ulong x, ulong p, long *py) { ulong v = 0; for(;;) { if (x%p) { *py = x; return v; } v++; x/=p; } } /* x is a non-zero integer */ long pvaluation(GEN x, GEN p, GEN *py) { long av,v; GEN p1,p2; if (!is_bigint(x)) { long y; if (!is_bigint(p)) { v = svaluation(x[2],p[2], &y); if (signe(x) < 0) y = -y; *py = stoi(y); } else { v = 0; *py = icopy(x); } return v; } av = avma; v = 0; (void)new_chunk(lgefint(x)); for(;;) { p1 = dvmdii(x,p,&p2); if (p2 != gzero) { avma=av; *py = icopy(x); return v; } v++; x = p1; } } /*******************************************************************/ /* */ /* NEGATION: Create -x */ /* */ /*******************************************************************/ GEN gneg(GEN x) { long tx=typ(x),lx,i; GEN y; if (gcmp0(x)) return gcopy(x); switch(tx) { case t_INT: case t_REAL: return mpneg(x); case t_INTMOD: y=cgetg(3,t_INTMOD); icopyifstack(x[1],y[1]); y[2] = lsubii((GEN)y[1],(GEN)x[2]); break; case t_POLMOD: y=cgetg(3,t_POLMOD); copyifstack(x[1],y[1]); y[2]=lneg((GEN)x[2]); break; case t_FRAC: case t_FRACN: case t_RFRAC: case t_RFRACN: y=cgetg(3,tx); y[1]=lneg((GEN)x[1]); y[2]=lcopy((GEN)x[2]); break; case t_PADIC: y=cgetp2(x,valp(x)); y[4]=lsubii((GEN)x[3],(GEN)x[4]); break; case t_QUAD: y=cgetg(4,t_QUAD); copyifstack(x[1],y[1]); y[2]=lneg((GEN)x[2]); y[3]=lneg((GEN)x[3]); break; case t_COMPLEX: case t_VEC: case t_COL: case t_MAT: lx=lg(x); y=cgetg(lx,tx); for (i=1; i0) y=x; return gcopy(y); } GEN gmin(GEN x, GEN y) { if (gcmp(x,y)<0) y=x; return gcopy(y); } GEN vecmax(GEN x) { long tx=typ(x),lx,lx2,i,j; GEN *p1,s; if (!is_matvec_t(tx)) return gcopy(x); lx=lg(x); if (lx==1) return stoi(-VERYBIGINT); if (tx!=t_MAT) { s=(GEN)x[1]; for (i=2; i 0) s=(GEN)x[i]; } else { lx2 = lg(x[1]); if (lx2==1) return stoi(-VERYBIGINT); s=gmael(x,1,1); i=2; for (j=1; j 0) s=p1[i]; i=1; } } return gcopy(s); } GEN vecmin(GEN x) { long tx=typ(x),lx,lx2,i,j; GEN *p1,s; if (!is_matvec_t(tx)) return gcopy(x); lx=lg(x); if (lx==1) return stoi(VERYBIGINT); if (tx!=t_MAT) { s=(GEN)x[1]; for (i=2; i GEN */ /* affect long s to GEN x. Useful for initialization. */ /* */ /*******************************************************************/ static void padicaff0(GEN x) { if (signe(x[4])) { setvalp(x, valp(x)|precp(x)); affsi(0,(GEN)x[4]); } } void gaffsg(long s, GEN x) { long l,i,v; GEN p; switch(typ(x)) { case t_INT: affsi(s,x); break; case t_REAL: affsr(s,x); break; case t_INTMOD: modsiz(s,(GEN)x[1],(GEN)x[2]); break; case t_FRAC: case t_FRACN: affsi(s,(GEN)x[1]); affsi(1,(GEN)x[2]); break; case t_COMPLEX: gaffsg(s,(GEN)x[1]); gaffsg(0,(GEN)x[2]); break; case t_PADIC: if (!s) { padicaff0(x); break; } p = (GEN)x[2]; v = (is_bigint(p))? 0: svaluation(s,p[2], &i); setvalp(x,v); modsiz(i,(GEN)x[3],(GEN)x[4]); break; case t_QUAD: gaffsg(s,(GEN)x[2]); gaffsg(0,(GEN)x[3]); break; case t_POLMOD: gaffsg(s,(GEN)x[2]); break; case t_POL: v=varn(x); if (!s) x[1]=evallgef(2) | evalvarn(v); else { x[1]=evalsigne(1) | evallgef(3) | evalvarn(v); gaffsg(s,(GEN)x[2]); } break; case t_SER: v=varn(x); gaffsg(s,(GEN)x[2]); l=lg(x); if (!s) x[1] = evalvalp(l-2) | evalvarn(v); else x[1] = evalsigne(1) | evalvalp(0) | evalvarn(v); for (i=3; i k) err(assigneri,tx,ty); modiiz(gtrunc(x),(GEN)y[1],(GEN)y[2]); avma=av; break; case t_PADIC: if (!egalii((GEN)x[2],(GEN)y[2])) err(assigneri,tx,ty); modiiz((GEN)x[4],(GEN)y[3],(GEN)y[4]); setvalp(y,valp(x)); break; case t_POLMOD: gaffect(x,(GEN)y[2]); break; case t_INT: case t_REAL: case t_FRAC: case t_FRACN: case t_COMPLEX: case t_QUAD: err(assignerf,tx,ty); default: err(typeer,"gaffect"); } break; case t_QUAD: switch(ty) { case t_INT: case t_INTMOD: case t_FRAC: case t_FRACN: case t_PADIC: if (!gcmp0((GEN)x[3])) err(assigneri,tx,ty); gaffect((GEN)x[2],y); break; case t_REAL: av=avma; p1=co8(x,ly); gaffect(p1,y); avma=av; break; case t_COMPLEX: ly=precision(y); if (ly) { av=avma; p1=co8(x,ly); gaffect(p1,y); avma=av; } else { if (!gcmp0((GEN)x[3])) err(assigneri,tx,ty); gaffect((GEN)x[2],y); } break; case t_QUAD: if (! gegal((GEN)x[1],(GEN)y[1])) err(assigneri,tx,ty); affii((GEN)x[2],(GEN)y[2]); affii((GEN)x[3],(GEN)y[3]); break; case t_POLMOD: gaffect(x,(GEN)y[2]); break; default: err(typeer,"gaffect"); } break; case t_POLMOD: if (ty!=t_POLMOD) err(assignerf,tx,ty); if (! gdivise((GEN)x[1],(GEN)y[1])) err(assigneri,tx,ty); gmodz((GEN)x[2],(GEN)y[1],(GEN)y[2]); break; default: err(typeer,"gaffect"); } return; } /* here y is not scalar */ switch(ty) { case t_POL: v=varn(y); if (y==polun[v] || y==polx[v]) err(talker,"trying to overwrite a universal polynomial"); gaffect(x,(GEN)y[2]); for (i=3; ivalue != (void*)initial_value(var)) { gaffect(geval(x),y); return; } } else if (is_rfrac_t(tx)) { GEN num = (GEN)x[1], den = (GEN)x[2]; entree *varnum = varentries[ordvar[varn(num)]]; entree *varden = varentries[ordvar[varn(den)]]; /* Are bound expressions, thus should not loop: */ if (varnum && varnum->value != (void*)initial_value(varnum) && varden && varden->value != (void*)initial_value(varden)) { gaffect(geval(x),y); return; } } #undef initial_value err(assignerf,tx,ty); } switch(tx) { case t_POL: v=varn(x); switch(ty) { case t_POL: vy=varn(y); if (vy>v) err(assignerf,tx,ty); if (vy==v) { l=lgef(x); if (l>ly) err(assigneri,tx,ty); y[1]=x[1]; for (i=2; iv) err(assignerf,tx,ty); if (!signe(x)) { gaffsg(0,y); return; } if (vy==v) { i=gval(x,v); y[1]=evalvarn(v) | evalvalp(i) | evalsigne(1); k=lgef(x)-i; if (k>ly) k=ly; for (j=2; jv) err(assignerf,tx,ty); if (vy==v) { y[1]=x[1]; k=lx; if (k>ly) k=ly; for (i=2; i< k; i++) gaffect((GEN)x[i],(GEN)y[i]); for ( ; i REAL, COMPLEX OR P-ADIC */ /* */ /*******************************************************************/ GEN co8(GEN x, long prec) { long av=avma,tetpil; GEN p1, p = (GEN) x[1]; p1 = subii(sqri((GEN)p[3]), shifti((GEN)p[2],2)); if (signe(p1) > 0) { p1 = subri(gsqrt(p1,prec), (GEN)p[3]); setexpo(p1, expo(p1)-1); } else { p1 = gsub(gsqrt(p1,prec), (GEN)p[3]); p1[1] = lmul2n((GEN)p1[1],-1); setexpo(p1[2], expo(p1[2])-1); }/* p1 = (-b + sqrt(D)) / 2 */ p1 = gmul((GEN)x[3],p1); tetpil=avma; return gerepile(av,tetpil,gadd((GEN)x[2],p1)); } GEN cvtop(GEN x, GEN p, long l) { GEN p1,p2,p3; long av,tetpil,n; if (typ(p)!=t_INT) err(talker,"not an integer modulus in cvtop or gcvtop"); if (gcmp0(x)) return ggrandocp(p,l); switch(typ(x)) { case t_INT: return gadd(x,ggrandocp(p,ggval(x,p)+l)); case t_INTMOD: n=ggval((GEN)x[1],p); if (n>l) n=l; return gadd((GEN)x[2],ggrandocp(p,n)); case t_FRAC: case t_FRACN: n = ggval((GEN)x[1],p) - ggval((GEN)x[2],p); return gadd(x,ggrandocp(p,n+l)); case t_COMPLEX: av=avma; p1=gsqrt(gaddgs(ggrandocp(p,l),-1),0); p1=gmul(p1,(GEN)x[2]); tetpil=avma; return gerepile(av,tetpil,gadd(p1,(GEN)x[1])); case t_PADIC: return gprec(x,l); case t_QUAD: av=avma; p1=(GEN)x[1]; p3=gmul2n((GEN)p1[3],-1); p2=gsub(gsqr(p3),(GEN)p1[2]); switch(typ(p2)) { case t_INT: n=ggval(p2,p); p2=gadd(p2,ggrandocp(p,n+l)); break; case t_INTMOD: case t_PADIC: break; case t_FRAC: case t_FRACN: n = ggval((GEN)p2[1],p) - ggval((GEN)p2[2],p); p2=gadd(p2,ggrandocp(p,n+l)); break; default: err(assigneri,t_QUAD,t_QUAD); } p2=gsqrt(p2,0); p1=gmul((GEN)x[3],gsub(p2,p3)); tetpil=avma; return gerepile(av,tetpil,gadd((GEN)x[2],p1)); } err(typeer,"cvtop"); return NULL; /* not reached */ } GEN gcvtop(GEN x, GEN p, long r) { long i,lx, tx=typ(x); GEN y; if (is_const_t(tx)) return cvtop(x,p,r); switch(tx) { case t_POL: lx=lgef(x); y=cgetg(lx,t_POL); y[1]=x[1]; for (i=2; iy) y=e; } return y; } err(typeer,"gexpo"); return 0; /* not reached */ } long gsize(GEN x) { return gcmp0(x)? 0: (long) ((gexpo(x)+1) * L2SL10) + 1; } /* Normalize series x in place. * Assumption: x,x[2],...,x[lg(x)-1] have been created in that order. * All intermediate objects will be destroyed. */ GEN normalize(GEN x) { long i,j, lx = lg(x); if (typ(x)!=t_SER) err(typeer,"normalize"); if (lx==2) { setsigne(x,0); avma = (long) x; return x; } if (! isexactzero((GEN)x[2])) { setsigne(x,1); return x; } for (i=3; i1; i--) if (! isexactzero((GEN)x[i])) break; setlgef(x,i+1); for (; i>1; i--) if (! gcmp0((GEN)x[i]) ) { setsigne(x,1); return x; } setsigne(x,0); return x; } /* Normalize polynomial x in place. See preceding comment */ GEN normalizepol(GEN x) { if (typ(x)!=t_POL) err(typeer,"normalizepol"); return normalizepol_i(x, lgef(x)); } int gsigne(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: return signe(x); case t_FRAC: case t_FRACN: return (signe(x[2])>0) ? signe(x[1]) : -signe(x[1]); } err(typeer,"gsigne"); return 0; /* not reached */ } int ff_poltype(GEN *x, GEN *p, GEN *pol); GEN gsqr(GEN x) { long tx=typ(x),lx,i,j,k,l,av,tetpil; GEN z,p1,p2,p3,p4; if (is_scalar_t(tx)) switch(tx) { case t_INT: return sqri(x); case t_REAL: return mulrr(x,x); case t_INTMOD: z=cgetg(3,t_INTMOD); p2=(GEN)x[1]; (void)new_chunk(lgefint(p2)<<2); p1=sqri((GEN)x[2]); avma=(long)z; z[2]=lmodii(p1,p2); icopyifstack(p2,z[1]); return z; case t_FRAC: case t_FRACN: z=cgetg(3,tx); z[1]=lsqri((GEN)x[1]); z[2]=lsqri((GEN)x[2]); return z; /* reduction is useless ! */ case t_COMPLEX: z=cgetg(lg(x),tx); l=avma; p1=gadd((GEN)x[1],(GEN)x[2]); p2=gadd((GEN)x[1],gneg_i((GEN)x[2])); p3=gmul((GEN)x[1],(GEN)x[2]); tetpil=avma; z[1]=lmul(p1,p2); z[2]=lshift(p3,1); gerepilemanyvec(l,tetpil,z+1,2); return z; case t_PADIC: z=cgetg(5,t_PADIC); z[2] = lcopy((GEN)x[2]); if (!cmpsi(2,(GEN)x[2])) { i=precp(x)+1; av=avma; p1=addii((GEN)x[3],shifti((GEN)x[4],1)); if (!gcmp0(p1)) { j=vali(p1); if (j>1; for (j=0; j>1]) p1 = gadd(p1, gsqr((GEN)x[i>>1])); z[i] = lpileupto(av,p1); } z -= 2; free(p2); return normalize(z); case t_RFRAC: case t_RFRACN: z=cgetg(3,tx); z[1]=lsqr((GEN)x[1]); z[2]=lsqr((GEN)x[2]); return z; case t_QFR: return sqcompreal(x); case t_QFI: return sqcompimag(x); case t_MAT: lx=lg(x); if (lx==1) return cgetg(1,tx); if (lx != lg(x[1])) err(gmuleri,tx,tx); z=cgetg(lx,tx); for (j=1; j= lx-1) { index = lx-1; lx++; if (lx > lg(list)) err(talker,"no more room in this list (size %ld)", lg(list)-2); } listaffect(list,index+1,object); list[1]=evallgef(lx); return (GEN)list[index+1]; } GEN listinsert(GEN list, GEN object, long index) { long lx = lgef(list), i; if (typ(list)!=t_LIST) err(typeer,"listinsert"); if (index <= 0 || index > lx-1) err(talker,"bad index in listinsert"); lx++; if (lx > lg(list)) err(talker,"no more room in this list"); for (i=lx-2; i > index; i--) list[i+1]=list[i]; list[index+1] = lclone(object); list[1] = evallgef(lx); return (GEN)list[index+1]; } GEN gtolist(GEN x) { long tx,lx,i; GEN list; if (!x) { list = cgetg(2, t_LIST); list[1] = evallgef(2); return list; } tx = typ(x); lx = (tx==t_LIST)? lgef(x): lg(x); switch(tx) { case t_VEC: case t_COL: lx++; x--; /* fall through */ case t_LIST: list = cgetg(lx,t_LIST); for (i=2; i