[BACK]Return to gen1.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / basemath

Annotation of OpenXM_contrib/pari-2.2/src/basemath/gen1.c, Revision 1.2

1.2     ! noro        1: /* $Id: gen1.c,v 1.53 2002/09/08 10:41:22 karim Exp $
1.1       noro        2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /********************************************************************/
                     17: /**                                                                **/
                     18: /**                      GENERIC OPERATIONS                        **/
                     19: /**                         (first part)                           **/
                     20: /**                                                                **/
                     21: /********************************************************************/
                     22: #include "pari.h"
                     23:
                     24: #define swapspec(x,y, nx,ny) {long _a=nx;GEN _z=x; nx=ny; ny=_a; x=y; y=_z;}
                     25: #define fix_frac(z) if (signe(z[2])<0)\
                     26: {\
                     27:   setsigne(z[1],-signe(z[1]));\
                     28:   setsigne(z[2],1);\
                     29: }
                     30:
                     31: /* assume z[1] was created last */
                     32: #define fix_frac_if_int(z) if (is_pm1(z[2]))\
1.2     ! noro       33:   z = gerepileupto((gpmem_t)(z+3), (GEN)z[1]);
1.1       noro       34:
                     35: /* assume z[1] was created last */
                     36: #define fix_frac_if_int_GC(z,tetpil) { if (is_pm1(z[2]))\
1.2     ! noro       37:   z = gerepileupto((gpmem_t)(z+3), (GEN)z[1]);\
1.1       noro       38: else\
1.2     ! noro       39:   gerepilemanyvec((gpmem_t)z, tetpil, z+1, 2); }
1.1       noro       40:
                     41: GEN quickmul(GEN a, GEN b, long na, long nb);
                     42:
                     43: #define cpifstack(x) isonstack(x)?gcopy(x):x
                     44: /* y is a polmod, f is gadd or gmul */
                     45: static GEN
                     46: op_polmod(GEN f(GEN,GEN), GEN x, GEN y, long tx)
                     47: {
                     48:   GEN mod,k,l, z=cgetg(3,t_POLMOD);
1.2     ! noro       49:   gpmem_t av, tetpil;
1.1       noro       50:
                     51:   l=(GEN)y[1];
                     52:   if (tx==t_POLMOD)
                     53:   {
                     54:     k=(GEN)x[1];
                     55:     if (gegal(k,l))
                     56:       { mod=cpifstack(k); x=(GEN)x[2]; y=(GEN)y[2]; }
                     57:     else
                     58:     {
                     59:       long vx=varn(k), vy=varn(l);
                     60:       if (vx==vy) { mod=srgcd(k,l); x=(GEN)x[2]; y=(GEN)y[2]; }
                     61:       else
                     62:         if (vx<vy) { mod=cpifstack(k); x=(GEN)x[2]; }
                     63:         else       { mod=cpifstack(l); y=(GEN)y[2]; }
                     64:     }
                     65:   }
                     66:   else
                     67:   {
                     68:     mod=cpifstack(l); y=(GEN)y[2];
                     69:     if (is_scalar_t(tx))
                     70:     {
                     71:       z[2] = (long)f(x,y);
                     72:       z[1] = (long)mod; return z;
                     73:     }
                     74:   }
                     75:   av=avma; x = f(x,y); tetpil=avma;
                     76:   z[2] = lpile(av,tetpil,gmod(x,mod));
                     77:   z[1] = (long)mod; return z;
                     78: }
                     79: #undef cpifstack
                     80:
                     81: /*******************************************************************/
                     82: /*                                                                 */
                     83: /*                          REDUCTION                              */
                     84: /*          transform  t_FRACN/t_RFRACN --> t_FRAC/t_RFRAC         */
                     85: /*                                                                 */
                     86: /* (static routines are not memory clean, but OK for gerepileupto) */
                     87: /*******************************************************************/
                     88: static GEN
                     89: gred_rfrac_copy(GEN x1, GEN x2)
                     90: {
                     91:   GEN y = cgetg(3,t_RFRAC);
                     92:   y[1] = lcopy(x1);
                     93:   y[2] = lcopy(x2); return y;
                     94: }
                     95:
                     96: /* x[1] is scalar, non-zero */
                     97: static GEN
                     98: gred_rfrac_simple(GEN x1, GEN x2)
                     99: {
                    100:   GEN y, c = content(x2);
                    101:
                    102:   if (gcmp1(c)) return gred_rfrac_copy(x1,x2);
                    103:   x1 = gdiv(x1, c);
                    104:   x2 = gdiv(x2, c);
                    105:
                    106:   c = denom(x1);
                    107:   y = cgetg(3,t_RFRAC);
1.2     ! noro      108:   y[1] = lmul(x1,c);
1.1       noro      109:   y[2] = lmul(x2,c); return y;
                    110: }
                    111:
                    112: static GEN
                    113: gred_rfrac2_i(GEN x1, GEN x2)
                    114: {
                    115:   GEN y,p1,xx1,xx2,x3;
                    116:   long tx,ty;
                    117:
                    118:   if (gcmp0(x1)) return gcopy(x1);
1.2     ! noro      119:   x1 = simplify_i(x1); tx = typ(x1);
        !           120:   x2 = simplify_i(x2); ty = typ(x2);
1.1       noro      121:   if (ty!=t_POL)
                    122:   {
                    123:     if (tx!=t_POL) return gred_rfrac_copy(x1,x2);
                    124:     if (gvar2(x2) > varn(x1)) return gdiv(x1,x2);
                    125:     err(talker,"incompatible variables in gred");
                    126:   }
                    127:   if (tx!=t_POL)
                    128:   {
                    129:     if (varn(x2) < gvar2(x1)) return gred_rfrac_simple(x1,x2);
                    130:     err(talker,"incompatible variables in gred");
                    131:   }
                    132:   if (varn(x2) < varn(x1)) return gred_rfrac_simple(x1,x2);
                    133:   if (varn(x2) > varn(x1)) return gdiv(x1,x2);
                    134:
                    135:   /* now x1 and x2 are polynomials with the same variable */
                    136:   xx1=content(x1); if (!gcmp1(xx1)) x1=gdiv(x1,xx1);
                    137:   xx2=content(x2); if (!gcmp1(xx2)) x2=gdiv(x2,xx2);
                    138:   x3=gdiv(xx1,xx2);
                    139:   y = poldivres(x1,x2,&p1);
                    140:   if (!signe(p1)) return gmul(x3,y);
                    141:
                    142:   p1 = ggcd(x2,p1);
                    143:   if (!isscalar(p1)) { x1=gdeuc(x1,p1); x2=gdeuc(x2,p1); }
                    144:   if (typ(x3) == t_POL)
                    145:   {
                    146:     xx2 = denom(content(x3));
                    147:     xx1 = gmul(x3, xx2);
                    148:   }
                    149:   else
                    150:   {
                    151:     xx1 = numer(x3);
                    152:     xx2 = denom(x3);
                    153:   }
                    154:   p1=cgetg(3,t_RFRAC);
                    155:   p1[1]=lmul(x1,xx1);
                    156:   p1[2]=lmul(x2,xx2); return p1;
                    157: }
                    158:
                    159: static GEN
                    160: gred_rfrac_i(GEN x)
                    161: {
                    162:   return gred_rfrac2_i((GEN)x[1], (GEN)x[2]);
                    163: }
                    164:
                    165: GEN
                    166: gred_rfrac2(GEN x1, GEN x2)
                    167: {
1.2     ! noro      168:   gpmem_t av = avma;
1.1       noro      169:   return gerepileupto(av, gred_rfrac2_i(x1, x2));
                    170: }
                    171:
                    172: GEN
                    173: gred_rfrac(GEN x)
                    174: {
                    175:   return gred_rfrac2((GEN)x[1], (GEN)x[2]);
                    176: }
                    177:
                    178: /* x1,x2 t_INT, return x1/x2 in reduced form */
                    179: GEN
                    180: gred_frac2(GEN x1, GEN x2)
                    181: {
                    182:   GEN p1, y = dvmdii(x1,x2,&p1);
1.2     ! noro      183:   gpmem_t av;
1.1       noro      184:
                    185:   if (p1 == gzero) return y; /* gzero intended */
                    186:   av = avma;
                    187:   p1 = mppgcd(x2,p1);
                    188:   if (is_pm1(p1))
                    189:   {
                    190:     avma = av; y = cgetg(3,t_FRAC);
                    191:     y[1] = licopy(x1);
                    192:     y[2] = licopy(x2);
                    193:   }
                    194:   else
                    195:   {
                    196:     p1 = gclone(p1);
                    197:     avma = av; y = cgetg(3,t_FRAC);
                    198:     y[1] = (long)diviiexact(x1,p1);
                    199:     y[2] = (long)diviiexact(x2,p1);
                    200:     gunclone(p1);
                    201:   }
                    202:   fix_frac(y); return y;
                    203: }
                    204:
                    205: /* must NEVER returns a FRACN or a RFRACN */
                    206: GEN
                    207: gred(GEN x)
                    208: {
                    209:   long tx = typ(x);
                    210:   if (is_frac_t(tx))  return gred_frac2((GEN)x[1], (GEN)x[2]);
                    211:   if (is_rfrac_t(tx)) return gred_rfrac(x);
                    212:   return gcopy(x);
                    213: }
                    214:
                    215: /********************************************************************/
                    216: /**                                                                **/
                    217: /**                          SUBTRACTION                           **/
                    218: /**                                                                **/
                    219: /********************************************************************/
                    220:
                    221: GEN
                    222: gsub(GEN x, GEN y)
                    223: {
1.2     ! noro      224:   gpmem_t tetpil, av = avma;
1.1       noro      225:   y=gneg_i(y); tetpil=avma;
                    226:   return gerepile(av,tetpil,gadd(x,y));
                    227: }
                    228:
                    229: /********************************************************************/
                    230: /**                                                                **/
                    231: /**                           ADDITION                             **/
                    232: /**                                                                **/
                    233: /********************************************************************/
                    234:
                    235: static GEN
                    236: addpadic(GEN x, GEN y)
                    237: {
1.2     ! noro      238:   gpmem_t av = avma;
        !           239:   long c,d,e,r,rx,ry;
        !           240:   GEN u,z,p,mod;
        !           241:
        !           242:   (void)new_chunk(5+lgefint(x[3])+lgefint(y[3]));
        !           243:   e = valp(x);
        !           244:   r = valp(y); d = r-e;
        !           245:   if (d < 0) { GEN p1=x; x=y; y=p1; e = r; d = -d; }
        !           246:   rx = precp(x); p = (GEN)x[2];
        !           247:   ry = precp(y);
        !           248:   if (d) /* v(x) < v(y) */
        !           249:   {
        !           250:     r = d+ry; z = gpowgs(p,d);
        !           251:     if (r < rx) mod = mulii(z,(GEN)y[3]); else { r = rx; mod = (GEN)x[3]; }
        !           252:     u = addii((GEN)x[4], mulii(z,(GEN)y[4]));
        !           253:   }
        !           254:   else
        !           255:   {
        !           256:     if (ry < rx) { r=ry; mod = (GEN)x[3]; } else { r=rx; mod = (GEN)y[3]; }
        !           257:     u = addii((GEN)x[4], (GEN)y[4]);
        !           258:     if (!signe(u) || (c = pvaluation(u,p,&u)) >= r)
1.1       noro      259:     {
1.2     ! noro      260:       avma = av; return padiczero(p, e+r);
1.1       noro      261:     }
1.2     ! noro      262:     if (c)
1.1       noro      263:     {
1.2     ! noro      264:       mod = divii(mod, gpowgs(p,c));
        !           265:       r -= c;
        !           266:       e += c;
1.1       noro      267:     }
                    268:   }
1.2     ! noro      269:   avma = av; z = cgetg(5,t_PADIC);
        !           270:   z[1] = evalprecp(r) | evalvalp(e);
        !           271:   z[3] = licopy(mod);
        !           272:   z[4] = lmodii(u,(GEN)z[3]);
        !           273:   icopyifstack(p, z[2]); return z;
1.1       noro      274: }
                    275:
                    276: /* return x + y, where x is t_INT or t_FRAC(N), y t_PADIC */
                    277: static GEN
                    278: gaddpex(GEN x, GEN y)
                    279: {
1.2     ! noro      280:   gpmem_t av;
        !           281:   long tx,vy,py,d,r,e;
        !           282:   GEN z,q,p,p1,p2,mod,u;
1.1       noro      283:
                    284:   if (gcmp0(x)) return gcopy(y);
                    285:
1.2     ! noro      286:   av = avma; p = (GEN)y[2]; tx = typ(x);
        !           287:   e = (tx == t_INT)? pvaluation(x,p,&p1)
1.1       noro      288:                     : pvaluation((GEN)x[1],p,&p1) -
                    289:                       pvaluation((GEN)x[2],p,&p2);
1.2     ! noro      290:   vy = valp(y); d = vy - e; py = precp(y); r = d + py;
        !           291:   if (r <= 0) { avma = av; return gcopy(y); }
        !           292:   mod = (GEN)y[3];
        !           293:   u   = (GEN)y[4];
        !           294:   (void)new_chunk(5 + lgefint(mod) + lgefint(p)*labs(d));
        !           295:
        !           296:   if (d > 0)
        !           297:   {
        !           298:     q = gpowgs(p,d);
        !           299:     mod = mulii(mod, q);
        !           300:     u   = mulii(u, q);
        !           301:     if (tx != t_INT && !is_pm1(p2)) p1 = mulii(p1, mpinvmod(p2,mod));
        !           302:     u = addii(u, p1);
        !           303:   }
        !           304:   else if (d < 0)
        !           305:   {
        !           306:     q = gpowgs(p,-d);
        !           307:     if (tx != t_INT && !is_pm1(p2)) p1 = mulii(p1, mpinvmod(p2,mod));
        !           308:     p1 = mulii(p1, q);
        !           309:     u = addii(u, p1);
        !           310:     r = py; e = vy;
1.1       noro      311:   }
                    312:   else
                    313:   {
1.2     ! noro      314:     long c;
        !           315:     if (tx != t_INT && !is_pm1(p2)) p1 = mulii(p1, mpinvmod(p2,mod));
        !           316:     u = addii(u, p1);
        !           317:     if (!signe(u) || (c = pvaluation(u,p,&u)) >= r)
        !           318:     {
        !           319:       avma = av; return padiczero(p,e+r);
        !           320:     }
        !           321:     if (c)
        !           322:     {
        !           323:       mod = divii(mod, gpowgs(p,c));
        !           324:       r -= c;
        !           325:       e += c;
        !           326:     }
1.1       noro      327:   }
1.2     ! noro      328:   avma = av; z = cgetg(5,t_PADIC);
        !           329:   z[1] = evalprecp(r) | evalvalp(e);
        !           330:   z[3] = licopy(mod);
        !           331:   z[4] = lmodii(u,(GEN)z[3]);
        !           332:   icopyifstack(p, z[2]); return z;
1.1       noro      333: }
                    334:
                    335: static long
                    336: kro_quad(GEN x, GEN y)
                    337: {
1.2     ! noro      338:   long k;
        !           339:   gpmem_t av=avma;
1.1       noro      340:
                    341:   x = subii(sqri((GEN)x[3]), shifti((GEN)x[2],2));
                    342:   k = kronecker(x,y); avma=av; return k;
                    343: }
                    344:
                    345: static GEN
                    346: addfrac(GEN x, GEN y)
                    347: {
                    348:   GEN x1 = (GEN)x[1], x2 = (GEN)x[2];
                    349:   GEN y1 = (GEN)y[1], y2 = (GEN)y[2], p1,p2,n,d,delta,z;
                    350:
                    351:   z = cgetg(3,t_FRAC);
                    352:   (void)new_chunk((lgefint(x1) + lgefint(x2) + /* HACK: >= lg(num) + lg(den) */
                    353:                    lgefint(y1) + lgefint(y2)) << 1);
                    354:   delta = mppgcd(x2,y2);
                    355:   if (is_pm1(delta))
                    356:   {
                    357:     p1 = mulii(x1,y2);
1.2     ! noro      358:     p2 = mulii(y1,x2); avma = (gpmem_t)z;
1.1       noro      359:     z[1] = laddii(p1,p2);
                    360:     z[2] = lmulii(x2,y2); return z;
                    361:   }
                    362:   x2 = divii(x2,delta);
                    363:   y2 = divii(y2,delta);
                    364:   n = addii(mulii(x1,y2), mulii(y1,x2));
1.2     ! noro      365:   if (!signe(n)) { avma = (gpmem_t)(z+3); return gzero; }
1.1       noro      366:   d = mulii(x2, y2);
                    367:   p1 = dvmdii(n, delta, &p2);
                    368:   if (p2 == gzero)
                    369:   {
1.2     ! noro      370:     if (is_pm1(d)) { avma = (gpmem_t)(z+3); return icopy(p1); }
        !           371:     avma = (gpmem_t)z;
1.1       noro      372:     z[1] = licopy(p1);
                    373:     z[2] = licopy(d); return z;
                    374:   }
                    375:   p1 = mppgcd(delta, p2);
                    376:   if (!is_pm1(p1))
                    377:   {
                    378:     delta = divii(delta, p1);
                    379:     n = divii(n, p1);
                    380:   }
                    381:   d = mulii(d,delta);
1.2     ! noro      382:   avma = (gpmem_t)z;
1.1       noro      383:   z[1] = licopy(n);
                    384:   z[2] = licopy(d); return z;
                    385: }
                    386:
                    387: static GEN
                    388: addrfrac(GEN x, GEN y)
                    389: {
                    390:   GEN z = cgetg(3,t_RFRAC);
                    391:   GEN x1 = (GEN)x[1], x2 = (GEN)x[2];
                    392:   GEN y1 = (GEN)y[1], y2 = (GEN)y[2], p1,p2,n,d,delta;
1.2     ! noro      393:   gpmem_t tetpil;
1.1       noro      394:
                    395:   delta = ggcd(x2,y2);
                    396:   if (gcmp1(delta))
                    397:   {
                    398:     p1 = gmul(x1,y2);
                    399:     p2 = gmul(y1,x2);
                    400:     tetpil = avma; /* numerator is non-zero */
1.2     ! noro      401:     z[1] = lpile((gpmem_t)z,tetpil, gadd(p1,p2));
1.1       noro      402:     z[2] = lmul(x2, y2); return z;
                    403:   }
                    404:   x2 = gdeuc(x2,delta);
                    405:   y2 = gdeuc(y2,delta);
                    406:   n = gadd(gmul(x1,y2), gmul(y1,x2));
1.2     ! noro      407:   if (gcmp0(n)) return gerepileupto((gpmem_t)(z+3), n);
1.1       noro      408:   tetpil = avma; d = gmul(x2, y2);
                    409:   p1 = poldivres(n, delta, &p2); /* we want gcd(n,delta) */
1.2     ! noro      410:   if (gcmp0(p2))
1.1       noro      411:   {
                    412:     if (lgef(d) == 3) /* "constant" denominator */
                    413:     {
                    414:       d = (GEN)d[2];
                    415:            if (gcmp_1(d)) p1 = gneg(p1);
                    416:       else if (!gcmp1(d)) p1 = gdiv(p1, d);
1.2     ! noro      417:       return gerepileupto((gpmem_t)(z+3), p1);
1.1       noro      418:     }
                    419:     z[1]=(long)p1; z[2]=(long)d;
1.2     ! noro      420:     gerepilemanyvec((gpmem_t)z,tetpil,z+1,2); return z;
1.1       noro      421:   }
                    422:   p1 = ggcd(delta, p2);
                    423:   if (gcmp1(p1))
                    424:   {
                    425:     tetpil = avma;
                    426:     z[1] = lcopy(n);
                    427:   }
                    428:   else
                    429:   {
                    430:     delta = gdeuc(delta, p1);
                    431:     tetpil = avma;
                    432:     z[1] = ldeuc(n,p1);
                    433:   }
                    434:   z[2] = lmul(d,delta);
1.2     ! noro      435:   gerepilemanyvec((gpmem_t)z,tetpil,z+1,2); return z;
1.1       noro      436: }
                    437:
                    438: static GEN
                    439: addscalrfrac(GEN x, GEN y)
                    440: {
                    441:   GEN p1,num, z = cgetg(3,t_RFRAC);
1.2     ! noro      442:   gpmem_t tetpil, av;
1.1       noro      443:
                    444:   p1 = gmul(x,(GEN)y[2]); tetpil = avma;
                    445:   num = gadd(p1,(GEN)y[1]);
                    446:   av = avma;
                    447:   p1 = content((GEN)y[2]);
                    448:   if (!gcmp1(p1))
                    449:   {
                    450:     p1 = ggcd(p1, content(num));
                    451:     if (!gcmp1(p1))
                    452:     {
                    453:       tetpil = avma;
                    454:       z[1] = ldiv(num, p1);
                    455:       z[2] = ldiv((GEN)y[2], p1);
1.2     ! noro      456:       gerepilemanyvec((gpmem_t)z,tetpil,z+1,2); return z;
1.1       noro      457:     }
                    458:   }
                    459:   avma = av;
1.2     ! noro      460:   z[1]=lpile((gpmem_t)z,tetpil, num);
1.1       noro      461:   z[2]=lcopy((GEN)y[2]); return z;
                    462: }
                    463:
                    464: /* assume gvar(x) = varn(mod) */
                    465: GEN
                    466: to_polmod(GEN x, GEN mod)
                    467: {
                    468:   long tx = typ(x);
                    469:   GEN z = cgetg(3, t_POLMOD);
                    470:
                    471:   if (tx == t_RFRACN) { x = gred_rfrac_i(x); tx = t_RFRAC; }
                    472:   if (tx == t_RFRAC) x = gmul((GEN)x[1], ginvmod((GEN)x[2],mod));
                    473:   z[1] = (long)mod;
                    474:   z[2] = (long)x;
                    475:   return z;
                    476: }
                    477:
                    478: GEN
                    479: gadd(GEN x, GEN y)
                    480: {
1.2     ! noro      481:   long tx = typ(x), ty = typ(y), vx, vy, lx, ly, i, j, k, l;
        !           482:   gpmem_t av, tetpil;
1.1       noro      483:   GEN z,p1,p2;
                    484:
                    485:   if (is_const_t(tx) && is_const_t(ty))
                    486:   {
                    487:     if (tx>ty) { p1=x; x=y; y=p1; i=tx; tx=ty; ty=i; }
                    488:     switch(tx)
                    489:     {
                    490:       case t_INT:
                    491:         switch(ty)
                    492:        {
                    493:          case t_INT:  return addii(x,y);
                    494:           case t_REAL: return addir(x,y);
                    495:
                    496:          case t_INTMOD: z=cgetg(3,t_INTMOD); p2=(GEN)y[1];
                    497:            (void)new_chunk(lgefint(p2)+1); /* HACK */
1.2     ! noro      498:             p1 = addii(modii(x,p2),(GEN)y[2]); avma = (gpmem_t)z;
1.1       noro      499:             z[2] = (cmpii(p1,p2) >=0)? lsubii(p1,p2): licopy(p1);
                    500:            icopyifstack(p2,z[1]); return z;
                    501:
                    502:          case t_FRAC: case t_FRACN: z=cgetg(3,ty);
                    503:             (void)new_chunk(lgefint(x)+lgefint(y[1])+lgefint(y[2])+1); /*HACK*/
1.2     ! noro      504:             p1 = mulii((GEN)y[2],x); avma = (gpmem_t)z;
1.1       noro      505:            z[1] = laddii((GEN)y[1], p1);
                    506:            z[2] = licopy((GEN)y[2]); return z;
                    507:
                    508:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
                    509:            z[1]=ladd(x,(GEN)y[1]);
                    510:            z[2]=lcopy((GEN)y[2]); return z;
                    511:
                    512:          case t_PADIC:
                    513:            return gaddpex(x,y);
                    514:
                    515:          case t_QUAD: z=cgetg(4,t_QUAD);
                    516:            copyifstack(y[1], z[1]);
                    517:            z[2]=ladd(x,(GEN)y[2]);
                    518:            z[3]=lcopy((GEN)y[3]); return z;
                    519:        }
                    520:
                    521:       case t_REAL:
                    522:         switch(ty)
                    523:        {
                    524:          case t_REAL: return addrr(x,y);
                    525:
                    526:          case t_FRAC: case t_FRACN:
                    527:            if (!signe(y[1])) return rcopy(x);
                    528:             if (!signe(x))
                    529:             {
                    530:               lx = expi((GEN)y[1]) - expi((GEN)y[2]) - expo(x);
                    531:               if (lx < 0) return rcopy(x);
                    532:               lx >>= TWOPOTBITS_IN_LONG;
                    533:               z=cgetr(lx+3); diviiz((GEN)y[1],(GEN)y[2],z);
                    534:               return z;
                    535:             }
                    536:             av=avma; z=addir((GEN)y[1],mulir((GEN)y[2],x)); tetpil=avma;
                    537:             return gerepile(av,tetpil,divri(z,(GEN)y[2]));
                    538:
                    539:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
                    540:            z[1]=ladd(x,(GEN)y[1]);
                    541:            z[2]=lcopy((GEN)y[2]); return z;
                    542:
                    543:          case t_QUAD:
                    544:            if (gcmp0(y)) return rcopy(x);
                    545:
                    546:            av=avma; i=gexpo(y)-expo(x);
                    547:            if (i<=0) i=0; else i >>= TWOPOTBITS_IN_LONG;
                    548:            p1=co8(y,lg(x)+i); tetpil=avma;
                    549:            return gerepile(av,tetpil,gadd(p1,x));
                    550:
1.2     ! noro      551:          case t_INTMOD: case t_PADIC: err(operf,"+",x,y);
1.1       noro      552:        }
                    553:
                    554:       case t_INTMOD:
                    555:         switch(ty)
                    556:        {
                    557:          case t_INTMOD: z=cgetg(3,t_INTMOD); p2=(GEN)x[1]; p1=(GEN)y[1];
                    558:            if (p1==p2 || egalii(p1,p2))
                    559:             {
                    560:               icopyifstack(p2,z[1]);
                    561:               if (!is_bigint(p2))
                    562:               {
                    563:                 z[2] = lstoi(addssmod(itos((GEN)x[2]),itos((GEN)y[2]), p2[2]));
                    564:                 return z;
                    565:               }
                    566:             }
                    567:             else
                    568:             { p2 = mppgcd(p1,p2); z[1] = (long)p2; }
                    569:            av=avma; (void)new_chunk((lgefint(p1)<<1) + lgefint(x[1]));/*HACK*/
                    570:             p1=addii((GEN)x[2],(GEN)y[2]); avma=av;
                    571:            z[2]=lmodii(p1,p2); return z;
                    572:
                    573:          case t_FRAC: case t_FRACN: z=cgetg(3,t_INTMOD); p2=(GEN)x[1];
                    574:            (void)new_chunk(lgefint(p2)<<2); /* HACK */
                    575:             p1 = mulii((GEN)y[1], mpinvmod((GEN)y[2],p2));
1.2     ! noro      576:             p1 = addii(modii(p1,p2), (GEN)x[2]); avma=(gpmem_t)z;
1.1       noro      577:             z[2]=lmodii(p1,p2); icopyifstack(p2,z[1]); return z;
                    578:
                    579:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
                    580:            z[1]=ladd(x,(GEN)y[1]);
                    581:             z[2]=lcopy((GEN)y[2]); return z;
                    582:
                    583:          case t_PADIC:
1.2     ! noro      584:            av=avma; p1=cgetg(3,t_INTMOD);
1.1       noro      585:            p1[1]=x[1]; p1[2]=lgeti(lgefint(x[1]));
                    586:            gaffect(y,p1); tetpil=avma;
1.2     ! noro      587:            return gerepile(av,tetpil,gadd(p1,x));
1.1       noro      588:
                    589:          case t_QUAD: z=cgetg(4,t_QUAD);
                    590:             copyifstack(y[1], z[1]);
                    591:            z[2]=ladd(x,(GEN)y[2]);
                    592:             z[3]=lcopy((GEN)y[3]); return z;
                    593:        }
                    594:
                    595:       case t_FRAC: case t_FRACN:
                    596:         switch (ty)
                    597:        {
                    598:          case t_FRAC: return addfrac(x,y);
1.2     ! noro      599:          case t_FRACN: z=cgetg(3,t_FRACN); av=avma;
1.1       noro      600:            p1=mulii((GEN)x[1],(GEN)y[2]);
                    601:            p2=mulii((GEN)x[2],(GEN)y[1]);
1.2     ! noro      602:            tetpil=avma; z[1]=lpile(av,tetpil,addii(p1,p2));
1.1       noro      603:            z[2]=lmulii((GEN)x[2],(GEN)y[2]);
                    604:            return z;
                    605:
                    606:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
                    607:            z[1]=ladd((GEN)y[1],x);
                    608:            z[2]=lcopy((GEN)y[2]); return z;
                    609:
                    610:          case t_PADIC:
                    611:            return gaddpex(x,y);
                    612:
                    613:          case t_QUAD: z=cgetg(4,t_QUAD);
                    614:            z[1]=lcopy((GEN)y[1]);
                    615:            z[2]=ladd((GEN)y[2],x);
                    616:            z[3]=lcopy((GEN)y[3]); return z;
                    617:        }
                    618:
                    619:       case t_COMPLEX:
                    620:         switch(ty)
                    621:        {
                    622:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
                    623:            z[1]=ladd((GEN)x[1],(GEN)y[1]);
                    624:            z[2]=ladd((GEN)x[2],(GEN)y[2]); return z;
                    625:
                    626:          case t_PADIC:
                    627:            if (krosg(-1,(GEN)y[2])== -1)
                    628:            {
                    629:              z=cgetg(3,t_COMPLEX);
                    630:               z[1]=ladd((GEN)x[1],y);
                    631:              z[2]=lcopy((GEN)x[2]); return z;
                    632:            }
                    633:            av=avma; l = signe(y[4])? precp(y): 1;
                    634:            p1=cvtop(x,(GEN)y[2], l + valp(y)); tetpil=avma;
                    635:             return gerepile(av,tetpil,gadd(p1,y));
                    636:
                    637:          case t_QUAD:
1.2     ! noro      638:            lx=precision(x); if (!lx) err(operi,"+",x,y);
1.1       noro      639:            if (gcmp0(y)) return gcopy(x);
                    640:
                    641:            av=avma; i=gexpo(y)-gexpo(x);
                    642:            if (i<=0) i=0; else i >>= TWOPOTBITS_IN_LONG;
                    643:            p1=co8(y,lx+i); tetpil=avma;
                    644:            return gerepile(av,tetpil,gadd(p1,x));
                    645:        }
                    646:
                    647:       case t_PADIC:
                    648:         switch(ty)
                    649:        {
                    650:          case t_PADIC:
1.2     ! noro      651:             if (!egalii((GEN)x[2],(GEN)y[2])) err(operi,"+",x,y);
1.1       noro      652:             return addpadic(x,y);
                    653:
                    654:          case t_QUAD:
                    655:            if (kro_quad((GEN)y[1],(GEN)x[2]) == -1)
                    656:            {
                    657:              z=cgetg(4,t_QUAD);
                    658:              copyifstack(y[1], z[1]);
                    659:              z[2]=ladd((GEN)y[2],x);
                    660:              z[3]=lcopy((GEN)y[3]); return z;
                    661:            }
                    662:            av=avma; l = signe(x[4])? precp(x): 1;
                    663:            p1=cvtop(y,(GEN)x[2],valp(x)+l); tetpil=avma;
                    664:            return gerepile(av,tetpil,gadd(p1,x));
                    665:        }
                    666:
                    667:       case t_QUAD: z=cgetg(4,t_QUAD); k=x[1]; l=y[1];
1.2     ! noro      668:         if (!gegal((GEN)k,(GEN)l)) err(operi,"+",x,y);
1.1       noro      669:         copyifstack(l, z[1]);
                    670:         z[2]=ladd((GEN)x[2],(GEN)y[2]);
                    671:         z[3]=ladd((GEN)x[3],(GEN)y[3]); return z;
                    672:     }
                    673:     err(bugparier,"gadd");
                    674:   }
                    675:
                    676:   vx=gvar(x); vy=gvar(y);
                    677:   if (vx<vy || (vx==vy && tx>ty))
                    678:   {
                    679:     p1=x; x=y; y=p1;
                    680:     i=tx; tx=ty; ty=i;
                    681:     i=vx; vx=vy; vy=i;
                    682:   }
                    683:   if (ty==t_POLMOD) return op_polmod(gadd,x,y,tx);
                    684:
                    685:   /* here !isscalar(y) and vx >= vy */
                    686:   if ( (vx>vy && (!is_matvec_t(tx) || !is_matvec_t(ty)))
                    687:     || (vx==vy && is_scalar_t(tx)) )
                    688:   {
                    689:     if (tx == t_POLMOD && vx == vy && ty != t_SER)
                    690:     {
                    691:       av = avma;
                    692:       return gerepileupto(av, op_polmod(gadd, x, to_polmod(y,(GEN)x[1]), tx));
                    693:     }
                    694:
                    695:     switch(ty)
                    696:     {
                    697:       case t_POL: ly=lgef(y);
                    698:        if (ly==2) return isexactzero(x)? zeropol(vy): scalarpol(x,vy);
                    699:
                    700:        z = cgetg(ly,t_POL); z[1] = y[1];
                    701:         z[2] = ladd(x,(GEN)y[2]);
                    702:         for (i=3; i<ly; i++) z[i]=lcopy((GEN)y[i]);
                    703:        return normalizepol_i(z, ly);
                    704:
                    705:       case t_SER: l=valp(y); ly=lg(y);
                    706:         if (l<3-ly) return gcopy(y);
                    707:        if (l<0)
                    708:        {
                    709:          z=cgetg(ly,t_SER); z[1]=y[1];
                    710:          for (i=2; i<=1-l; i++) z[i]=lcopy((GEN)y[i]);
                    711:          for (i=3-l; i<ly; i++) z[i]=lcopy((GEN)y[i]);
                    712:          z[2-l]=ladd(x,(GEN)y[2-l]); return z;
                    713:        }
                    714:        if (l>0)
                    715:        {
                    716:          if (gcmp0(x)) return gcopy(y);
                    717:          if (gcmp0(y)) ly=2;
                    718:
                    719:           ly += l; z=cgetg(ly,t_SER);
                    720:          z[1]=evalsigne(1) | evalvalp(0) | evalvarn(vy);
                    721:          for (i=3; i<=l+1; i++) z[i]=zero;
                    722:          for (   ; i<ly; i++) z[i]=lcopy((GEN)y[i-l]);
                    723:          z[2]=lcopy(x); return z;
                    724:        }
                    725:        av=avma; z=cgetg(ly,t_SER);
                    726:        p1=signe(y)? gadd(x,(GEN)y[2]): x;
                    727:        if (!isexactzero(p1))
                    728:         {
                    729:           z[1] = evalvalp(0) | evalvarn(vy);
                    730:           if (signe(y))
                    731:           {
                    732:             z[1] |= evalsigne(1); z[2]=(long)p1;
                    733:             for (i=3; i<ly; i++) z[i]=lcopy((GEN)y[i]);
                    734:           }
                    735:           return z;
                    736:         }
                    737:         avma=av; /* first coeff is 0 */
                    738:         i=3; while (i<ly && gcmp0((GEN)y[i])) i++;
                    739:         if (i==ly) return zeroser(vy,i-2);
                    740:
                    741:         z=cgetg(ly-i+2,t_SER); z[1]=evalvalp(i-2)|evalvarn(vy)|evalsigne(1);
                    742:         for (j=2; j<=ly-i+1; j++) z[j]=lcopy((GEN)y[j+i-2]);
                    743:         return z;
                    744:
                    745:       case t_RFRAC: return addscalrfrac(x,y);
                    746:       case t_RFRACN: z=cgetg(3,t_RFRACN);
                    747:         av=avma; p1=gmul(x,(GEN)y[2]); tetpil=avma;
                    748:         z[1]=lpile(av,tetpil, gadd(p1,(GEN)y[1]));
                    749:         z[2]=lcopy((GEN)y[2]); return z;
                    750:
                    751:       case t_VEC: case t_COL: case t_MAT:
                    752:        if (isexactzero(x)) return gcopy(y);
                    753:        if (ty == t_MAT) return gaddmat(x,y);
                    754:         /* fall through */
1.2     ! noro      755:       case t_QFR: case t_QFI: err(operf,"+",x,y);
1.1       noro      756:     }
1.2     ! noro      757:     err(operf,"+",x,y);
1.1       noro      758:   }
                    759:
                    760:   /* here !isscalar(x) && isscalar(y) && (vx=vy || ismatvec(x and y)) */
                    761:   if (tx>ty) { p1=x; x=y; y=p1; i=tx; tx=ty; ty=i; }
                    762:   switch(tx)
                    763:   {
                    764:     case t_POL:
                    765:       switch (ty)
                    766:       {
                    767:        case t_POL:
                    768:           lx = lgef(x); ly = lgef(y); if (lx < ly) swapspec(x,y, lx,ly);
                    769:           z = cgetg(lx,t_POL); z[1] = x[1];
                    770:           for (i=2; i<ly; i++) z[i]=ladd((GEN)x[i],(GEN)y[i]);
                    771:           for (   ; i<lx; i++) z[i]=lcopy((GEN)x[i]);
                    772:           (void)normalizepol_i(z, lx);
1.2     ! noro      773:           if (lgef(z) == 2) { avma = (gpmem_t)(z + lx); z = zeropol(vx); }
1.1       noro      774:           return z;
                    775:
                    776:        case t_SER:
                    777:          if (gcmp0(x)) return gcopy(y);
                    778:           ly = signe(y)? lg(y): 3;
                    779:          i = ly+valp(y)-gval(x,vx);
                    780:          if (i<3) return gcopy(y);
                    781:
                    782:          p1=greffe(x,i,0); y=gadd(p1,y);
                    783:           free(p1); return y;
                    784:
                    785:         case t_RFRAC: return addscalrfrac(x,y);
                    786:         case t_RFRACN: z=cgetg(3,t_RFRACN);
                    787:           av=avma; p1=gmul(x,(GEN)y[2]); tetpil=avma;
                    788:           z[1]=lpile(av,tetpil, gadd(p1,(GEN)y[1]));
                    789:           z[2]=lcopy((GEN)y[2]); return z;
                    790:
1.2     ! noro      791:        default: err(operf,"+",x,y);
1.1       noro      792:       }
                    793:
                    794:     case t_SER:
                    795:       switch(ty)
                    796:       {
                    797:        case t_SER:
                    798:          l=valp(y)-valp(x);
                    799:          if (l<0) { l= -l; p1=x; x=y; y=p1; }
                    800:          if (gcmp0(x)) return gcopy(x);
                    801:           lx = lg(x);
                    802:           ly = signe(y)? lg(y): 2;
                    803:          ly += l; if (lx<ly) ly=lx;
                    804:          av = avma;
                    805:           z=cgetg(ly,t_SER);
                    806:          if (l)
                    807:          {
                    808:            if (l>=ly-2)
                    809:              for (i=2; i<ly; i++) z[i]=lcopy((GEN)x[i]);
                    810:             else
                    811:            {
                    812:              for (i=2; i<=l+1; i++) z[i]=lcopy((GEN)x[i]);
                    813:              for (   ; i<ly; i++) z[i]=ladd((GEN)x[i],(GEN)y[i-l]);
                    814:            }
                    815:            z[1]=x[1]; return z;
                    816:          }
                    817:           if (ly>2)
                    818:           {
                    819:             tetpil = avma;
                    820:             for (i=2; i<ly; i++)
                    821:             {
                    822:               p1 = gadd((GEN)x[i],(GEN)y[i]);
                    823:               if (!isexactzero(p1))
                    824:               {
                    825:                 l = i-2; stackdummy(z,l); z += l;
                    826:                 z[0]=evaltyp(t_SER) | evallg(ly-l);
                    827:                 z[1]=evalvalp(valp(x)+i-2) | evalsigne(1) | evalvarn(vx);
                    828:                 for (j=i+1; j<ly; j++)
                    829:                   z[j-l]=ladd((GEN)x[j],(GEN)y[j]);
                    830:                 z[2]=(long)p1; return z;
                    831:               }
                    832:               avma = tetpil;
                    833:             }
                    834:           }
                    835:           avma = av;
                    836:           return zeroser(vx,ly-2+valp(y));
                    837:
                    838:        case t_RFRAC: case t_RFRACN:
                    839:          if (gcmp0(y)) return gcopy(x);
                    840:
                    841:          l = valp(x)-gval(y,vy); l += gcmp0(x)? 3: lg(x);
                    842:          if (l<3) return gcopy(x);
                    843:
                    844:          av=avma; ty=typ(y[2]);
                    845:           p1 = is_scalar_t(ty)? (GEN)y[2]: greffe((GEN)y[2],l,1);
                    846:           p1 = gdiv((GEN)y[1], p1); tetpil=avma;
                    847:           return gerepile(av,tetpil,gadd(p1,x));
                    848:
1.2     ! noro      849:        default: err(operf,"+",x,y);
1.1       noro      850:       }
                    851:
                    852:     case t_RFRAC:
1.2     ! noro      853:       if (!is_rfrac_t(ty)) err(operi,"+",x,y);
1.1       noro      854:       return addrfrac(x,y);
                    855:     case t_RFRACN:
1.2     ! noro      856:       if (!is_rfrac_t(ty)) err(operi,"+",x,y);
1.1       noro      857:       z=cgetg(3,t_RFRACN); av=avma;
                    858:       p1=gmul((GEN)x[1],(GEN)y[2]);
                    859:       p2=gmul((GEN)x[2],(GEN)y[1]); tetpil=avma;
                    860:       z[1]=lpile(av,tetpil, gadd(p1,p2));
                    861:       z[2]=lmul((GEN)x[2],(GEN)y[2]); return z;
                    862:
                    863:     case t_VEC: case t_COL: case t_MAT:
                    864:       lx = lg(x); ly = lg(y);
1.2     ! noro      865:       if (lx!=ly || tx!=ty) err(operi,"+",x,y);
1.1       noro      866:       z=cgetg(ly,ty);
                    867:       for (i=1; i<ly; i++)
                    868:        z[i]=ladd((GEN)x[i],(GEN)y[i]);
                    869:       return z;
                    870:   }
1.2     ! noro      871:   err(operf,"+",x,y);
1.1       noro      872:   return NULL; /* not reached */
                    873: }
                    874:
                    875: /********************************************************************/
                    876: /**                                                                **/
                    877: /**                        MULTIPLICATION                          **/
                    878: /**                                                                **/
                    879: /********************************************************************/
                    880: GEN
                    881: fix_rfrac_if_pol(GEN x, GEN y)
                    882: {
1.2     ! noro      883:   gpmem_t av = avma;
        !           884:   y = simplify(y);
        !           885:   if (gcmp1(y)) { avma = av; return x; }
1.1       noro      886:   if (typ(y) != t_POL)
                    887:   {
                    888:     if (typ(x) != t_POL || gvar2(y) > varn(x))
                    889:       return gdiv(x,y);
                    890:   }
                    891:   else if (varn(y) > varn(x)) return gdiv(x,y);
1.2     ! noro      892:   avma = av; return NULL;
1.1       noro      893: }
                    894:
                    895: static long
                    896: mingvar(GEN x, GEN y)
                    897: {
                    898:   long i = gvar(x);
                    899:   long j = gvar(y);
                    900:   return min(i,j);
                    901: }
                    902:
                    903: static GEN
                    904: to_primitive(GEN x, GEN *cx)
                    905: {
                    906:   if (typ(x) != t_POL)
                    907:     { *cx = x; x = gun; }
                    908:   else if (lgef(x) == 3)
                    909:     { *cx = (GEN)x[2]; x = gun; }
                    910:   else
                    911:     { *cx = content(x); if (!gcmp1(*cx)) x = gdiv(x,*cx); }
                    912:   return x;
                    913: }
                    914:
                    915: GEN
                    916: mulscalrfrac(GEN x, GEN y)
                    917: {
                    918:   GEN p1,z,y1,y2,cx,cy1,cy2;
1.2     ! noro      919:   long tx;
        !           920:   gpmem_t tetpil;
1.1       noro      921:
                    922:   if (gcmp0(x)) return gcopy(x);
                    923:
                    924:   y1=(GEN)y[1]; if (gcmp0(y1)) return gcopy(y1);
                    925:   y2=(GEN)y[2]; tx = typ(x);
                    926:   z = cgetg(3, t_RFRAC);
                    927:   if (is_const_t(tx) || varn(x) > mingvar(y1,y2)) { cx = x; x = gun; }
                    928:   else
                    929:   {
                    930:     p1 = ggcd(x,y2); if (isnonscalar(p1)) { x=gdeuc(x,p1); y2=gdeuc(y2,p1); }
                    931:     x = to_primitive(x, &cx);
                    932:   }
                    933:   y1 = to_primitive(y1, &cy1);
                    934:   y2 = to_primitive(y2, &cy2);
                    935:   if (x != gun) y1 = gmul(y1,x);
                    936:   x = gdiv(gmul(cx,cy1), cy2);
                    937:   if (typ(x) == t_POL)
                    938:   {
                    939:     cy2 = denom(content(x));
                    940:     cy1 = gmul(x, cy2);
                    941:   }
                    942:   else
                    943:   {
                    944:     cy1 = numer(x);
                    945:     cy2 = denom(x);
                    946:   }
                    947:   tetpil = avma;
                    948:   z[2] = lmul(y2, cy2);
                    949:   z[1] = lmul(y1, cy1);
                    950:   p1 = fix_rfrac_if_pol((GEN)z[1],(GEN)z[2]);
1.2     ! noro      951:   if (p1) return gerepileupto((gpmem_t)(z+3), p1);
        !           952:   gerepilemanyvec((gpmem_t)z,tetpil,z+1,2); return z;
1.1       noro      953: }
                    954:
                    955: static GEN
                    956: mulrfrac(GEN x, GEN y)
                    957: {
                    958:   GEN z = cgetg(3,t_RFRAC), p1;
                    959:   GEN x1 = (GEN)x[1], x2 = (GEN)x[2];
                    960:   GEN y1 = (GEN)y[1], y2 = (GEN)y[2];
1.2     ! noro      961:   gpmem_t tetpil;
1.1       noro      962:
                    963:   p1 = ggcd(x1, y2); if (!gcmp1(p1)) { x1 = gdiv(x1,p1); y2 = gdiv(y2,p1); }
                    964:   p1 = ggcd(x2, y1); if (!gcmp1(p1)) { x2 = gdiv(x2,p1); y1 = gdiv(y1,p1); }
                    965:   tetpil = avma;
                    966:   z[2] = lmul(x2,y2);
                    967:   z[1] = lmul(x1,y1);
                    968:   p1 = fix_rfrac_if_pol((GEN)z[1],(GEN)z[2]);
1.2     ! noro      969:   if (p1) return gerepileupto((gpmem_t)(z+3), p1);
        !           970:   gerepilemanyvec((gpmem_t)z,tetpil,z+1,2); return z;
1.1       noro      971: }
                    972:
                    973: GEN
                    974: to_Kronecker(GEN P, GEN Q)
                    975: {
                    976:   /* P(X) = sum Mod(.,Q(Y)) * X^i, lift then set X := Y^(2n-1) */
                    977:   long i,j,k,l, lx = lgef(P), N = (degpol(Q)<<1) + 1, vQ = varn(Q);
                    978:   GEN p1, y = cgetg((N-2)*(lx-2) + 2, t_POL);
                    979:   for (k=i=2; i<lx; i++)
                    980:   {
                    981:     p1 = (GEN)P[i];
                    982:     if ((l=typ(p1)) == t_POLMOD) { p1 = (GEN)p1[2]; l = typ(p1); }
                    983:     if (is_scalar_t(l) || varn(p1)<vQ) { y[k++] = (long)p1; j = 3; }
                    984:     else
                    985:     {
                    986:       l = lgef(p1);
                    987:       for (j=2; j < l; j++) y[k++] = p1[j];
                    988:     }
                    989:     if (i == lx-1) break;
                    990:     for (   ; j < N; j++) y[k++] = zero;
                    991:   }
                    992:   y[1] = evalsigne(1)|evalvarn(vQ)|evallgef(k);
                    993:   return y;
                    994: }
                    995:
                    996: int
                    997: ff_poltype(GEN *x, GEN *p, GEN *pol)
                    998: {
                    999:   GEN Q, P = *x, pr,p1,p2,y;
                   1000:   long i, lx;
                   1001:
                   1002:   if (!signe(P)) return 0;
                   1003:   lx = lgef(P); Q = *pol;
                   1004:   for (i=2; i<lx; i++)
                   1005:   {
                   1006:     p1 = (GEN)P[i]; if (typ(p1) != t_POLMOD) {Q=NULL;break;}
                   1007:     p2 = (GEN)p1[1];
                   1008:     if (Q==NULL) Q = p2;
                   1009:     else if (p2 != Q)
                   1010:     {
                   1011:       if (!gegal(p2, Q))
                   1012:       {
                   1013:         if (DEBUGMEM) err(warner,"different modulus in ff_poltype");
                   1014:         return 0;
                   1015:       }
                   1016:       if (DEBUGMEM > 2) err(warner,"different pointers in ff_poltype");
                   1017:     }
                   1018:   }
                   1019:   if (Q) {
                   1020:     *x = P = to_Kronecker(P, Q);
                   1021:     *pol = Q; lx = lgef(P);
                   1022:   }
                   1023:   pr = *p; y = cgetg(lx, t_POL);
                   1024:   for (i=lx-1; i>1; i--)
                   1025:   {
                   1026:     p1 = (GEN)P[i];
                   1027:     switch(typ(p1))
                   1028:     {
                   1029:       case t_INTMOD: break;
                   1030:       case t_INT:
                   1031:         if (*p) p1 = modii(p1, *p);
                   1032:         y[i] = (long)p1; continue;
                   1033:       default:
                   1034:         return (Q && !pr)? 1: 0;
                   1035:     }
                   1036:     p2 = (GEN)p1[1];
                   1037:     if (pr==NULL) pr = p2;
                   1038:     else if (p2 != pr)
                   1039:     {
                   1040:       if (!egalii(p2, pr))
                   1041:       {
                   1042:         if (DEBUGMEM) err(warner,"different modulus in ff_poltype");
                   1043:         return 0;
                   1044:       }
                   1045:       if (DEBUGMEM > 2) err(warner,"different pointers in ff_poltype");
                   1046:     }
                   1047:     y[i] = p1[2];
                   1048:   }
                   1049:   y[1] = evalsigne(1)|evalvarn(varn(P))|evallgef(lx);
                   1050:   *x = y; *p = pr; return (Q || pr);
                   1051: }
                   1052:
                   1053: static GEN
                   1054: gmul_err(GEN x, GEN y, long tx, long ty)
                   1055: {
                   1056:   long i,l;
                   1057:   GEN z;
                   1058:   if (tx==ty)
                   1059:     switch(tx)
                   1060:     {
                   1061:       case t_QFI: return compimag(x,y);
                   1062:       case t_QFR: return compreal(x,y);
                   1063:       case t_VECSMALL:
                   1064:         l = lg(x); z = cgetg(l, t_VECSMALL);
1.2     ! noro     1065:         if (l != lg(y)) err(operf,"*",x,y);
        !          1066:         for (i=1; i<l; i++)
        !          1067:        {
        !          1068:          long yi=y[i];
        !          1069:          if (yi<1 || yi>=l) err(operf,"*",x,y);
        !          1070:          z[i]=x[y[i]];
        !          1071:        }
1.1       noro     1072:         return z;
                   1073:     }
1.2     ! noro     1074:   err(operf,"*",x,y);
1.1       noro     1075:   return NULL; /* not reached */
                   1076: }
                   1077:
                   1078: GEN
                   1079: gmul(GEN x, GEN y)
                   1080: {
1.2     ! noro     1081:   long tx, ty, lx, ly, vx, vy, i, j, k, l;
        !          1082:   gpmem_t av, tetpil;
1.1       noro     1083:   GEN z,p1,p2,p3,p4;
                   1084:
                   1085:   if (x == y) return gsqr(x);
                   1086:   if (y == gun) return gcopy(x);
                   1087:
                   1088:   tx = typ(x); ty = typ(y);
                   1089:   if (is_const_t(tx) && is_const_t(ty))
                   1090:   {
                   1091:     if (tx>ty) { p1=x; x=y; y=p1; i=tx; tx=ty; ty=i; }
                   1092:     switch(tx)
                   1093:     {
                   1094:       case t_INT:
                   1095:         switch(ty)
                   1096:        {
                   1097:          case t_INT:  return mulii(x,y);
                   1098:          case t_REAL: return mulir(x,y);
                   1099:
                   1100:          case t_INTMOD: z=cgetg(3,t_INTMOD); p2=(GEN)y[1];
                   1101:            (void)new_chunk(lgefint(p2)<<2); /* HACK */
1.2     ! noro     1102:             p1=mulii(modii(x,p2),(GEN)y[2]); avma=(gpmem_t)z;
1.1       noro     1103:            z[2]=lmodii(p1,p2); icopyifstack(p2,z[1]); return z;
                   1104:
                   1105:          case t_FRAC:
                   1106:             if (!signe(x)) return gzero;
                   1107:             z=cgetg(3,t_FRAC);
                   1108:             p1 = mppgcd(x,(GEN)y[2]);
                   1109:             if (is_pm1(p1))
                   1110:             {
1.2     ! noro     1111:               avma = (gpmem_t)z;
1.1       noro     1112:               z[2] = licopy((GEN)y[2]);
                   1113:               z[1] = lmulii((GEN)y[1], x);
                   1114:             }
                   1115:             else
                   1116:             {
                   1117:               x = divii(x,p1); tetpil = avma;
                   1118:               z[2] = ldivii((GEN)y[2], p1);
                   1119:               z[1] = lmulii((GEN)y[1], x);
                   1120:               fix_frac_if_int_GC(z,tetpil);
                   1121:             }
                   1122:             return z;
                   1123:
                   1124:           case t_FRACN: z=cgetg(3,t_FRACN);
                   1125:            z[1]=lmulii(x,(GEN)y[1]);
                   1126:            z[2]=licopy((GEN)y[2]); return z;
                   1127:
                   1128:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
                   1129:            z[1]=lmul(x,(GEN)y[1]);
                   1130:            z[2]=lmul(x,(GEN)y[2]); return z;
                   1131:
                   1132:          case t_PADIC:
                   1133:            if (!signe(x)) return gzero;
1.2     ! noro     1134:            av=avma; p1=cgetp(y); gaffect(x,p1); tetpil=avma;
        !          1135:            return gerepile(av,tetpil,gmul(p1,y));
1.1       noro     1136:
                   1137:          case t_QUAD: z=cgetg(4,t_QUAD);
                   1138:            copyifstack(y[1], z[1]);
                   1139:            z[2]=lmul(x,(GEN)y[2]);
                   1140:            z[3]=lmul(x,(GEN)y[3]); return z;
                   1141:        }
                   1142:
                   1143:       case t_REAL:
                   1144:         switch(ty)
                   1145:        {
                   1146:          case t_REAL: return mulrr(x,y);
                   1147:
                   1148:          case t_FRAC: case t_FRACN:
1.2     ! noro     1149:            av=avma; p1=mulri(x,(GEN)y[1]); tetpil=avma;
        !          1150:             return gerepile(av, tetpil, divri(p1, (GEN)y[2]));
1.1       noro     1151:
                   1152:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
                   1153:            z[1]=lmul(x,(GEN)y[1]);
                   1154:            z[2]=lmul(x,(GEN)y[2]); return z;
                   1155:
                   1156:          case t_QUAD:
1.2     ! noro     1157:            av=avma; p1=co8(y,lg(x)); tetpil=avma;
        !          1158:            return gerepile(av,tetpil,gmul(p1,x));
1.1       noro     1159:
1.2     ! noro     1160:          default: err(operf,"*",x,y);
1.1       noro     1161:        }
                   1162:
                   1163:       case t_INTMOD:
                   1164:         switch(ty)
                   1165:        {
                   1166:          case t_INTMOD: z=cgetg(3,t_INTMOD); p2=(GEN)x[1]; p1=(GEN)y[1];
                   1167:            if (p1==p2 || egalii(p1,p2))
                   1168:             {
                   1169:               icopyifstack(p2,z[1]);
                   1170:               if (!is_bigint(p2))
                   1171:               {
                   1172:                 z[2] = lstoi(mulssmod(itos((GEN)x[2]),itos((GEN)y[2]), p2[2]));
                   1173:                 return z;
                   1174:               }
                   1175:             }
                   1176:             else
                   1177:             { p2 = mppgcd(p1,p2); z[1] = (long)p2; }
                   1178:             av=avma;
                   1179:             (void)new_chunk(lgefint(x[1]) + (lgefint(p1)<<1)); /* HACK */
                   1180:            p1=mulii((GEN)x[2],(GEN)y[2]); avma=av;
                   1181:            z[2]=lmodii(p1,p2); return z;
                   1182:
                   1183:          case t_FRAC: case t_FRACN: z=cgetg(3,t_INTMOD); p2=(GEN)x[1];
                   1184:             (void)new_chunk(lgefint(p2)<<2); /* HACK */
                   1185:             p1 = mulii((GEN)y[1], mpinvmod((GEN)y[2],p2));
1.2     ! noro     1186:             p1 = mulii(modii(p1,p2),(GEN)x[2]); avma=(gpmem_t)z;
1.1       noro     1187:             z[2] = lmodii(p1,p2); icopyifstack(p2,z[1]); return z;
                   1188:
                   1189:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
                   1190:            z[1]=lmul(x,(GEN)y[1]);
                   1191:            z[2]=lmul(x,(GEN)y[2]); return z;
                   1192:
                   1193:          case t_PADIC:
1.2     ! noro     1194:            av=avma; p1=cgetg(3,t_INTMOD);
1.1       noro     1195:            p1[1]=x[1]; p1[2]=lgeti(lg(x[1]));
                   1196:            gaffect(y,p1); tetpil=avma;
1.2     ! noro     1197:            return gerepile(av,tetpil,gmul(x,p1));
1.1       noro     1198:
                   1199:          case t_QUAD: z=cgetg(4,t_QUAD);
                   1200:             copyifstack(y[1], z[1]);
                   1201:            z[2]=lmul(x,(GEN)y[2]);
                   1202:             z[3]=lmul(x,(GEN)y[3]); return z;
                   1203:        }
                   1204:
                   1205:       case t_FRAC: case t_FRACN:
                   1206:         switch(ty)
                   1207:        {
                   1208:          case t_FRAC:
                   1209:           {
                   1210:             GEN x1 = (GEN)x[1], x2 = (GEN)x[2];
                   1211:             GEN y1 = (GEN)y[1], y2 = (GEN)y[2];
                   1212:             z=cgetg(3,t_FRAC);
                   1213:             p1 = mppgcd(x1, y2);
                   1214:             if (!is_pm1(p1)) { x1 = divii(x1,p1); y2 = divii(y2,p1); }
                   1215:             p1 = mppgcd(x2, y1);
                   1216:             if (!is_pm1(p1)) { x2 = divii(x2,p1); y1 = divii(y1,p1); }
                   1217:             tetpil = avma;
                   1218:             z[2] = lmulii(x2,y2);
                   1219:             z[1] = lmulii(x1,y1);
                   1220:             fix_frac_if_int_GC(z,tetpil); return z;
                   1221:           }
                   1222:          case t_FRACN: z=cgetg(3,t_FRACN);
                   1223:            z[1]=lmulii((GEN)x[1],(GEN)y[1]);
                   1224:            z[2]=lmulii((GEN)x[2],(GEN)y[2]); return z;
                   1225:
                   1226:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
                   1227:            z[1]=lmul((GEN)y[1],x);
                   1228:            z[2]=lmul((GEN)y[2],x); return z;
                   1229:
                   1230:          case t_PADIC:
                   1231:            if (!signe(x[1])) return gzero;
1.2     ! noro     1232:            av=avma; p1=cgetp(y); gaffect(x,p1); tetpil=avma;
        !          1233:             return gerepile(av,tetpil,gmul(p1,y));
1.1       noro     1234:
                   1235:          case t_QUAD: z=cgetg(4,t_QUAD);
                   1236:            copyifstack(y[1], z[1]);
                   1237:            z[2]=lmul((GEN)y[2],x);
                   1238:            z[3]=lmul((GEN)y[3],x); return z;
                   1239:        }
                   1240:
                   1241:       case t_COMPLEX:
                   1242:         switch(ty)
                   1243:        {
1.2     ! noro     1244:          case t_COMPLEX: z=cgetg(3,t_COMPLEX); av=avma;
1.1       noro     1245:             p1=gmul((GEN)x[1],(GEN)y[1]);
                   1246:             p2=gmul((GEN)x[2],(GEN)y[2]);
                   1247:            x=gadd((GEN)x[1],(GEN)x[2]);
                   1248:             y=gadd((GEN)y[1],(GEN)y[2]);
                   1249:            y=gmul(x,y); x=gadd(p1,p2);
                   1250:            tetpil=avma; z[1]=lsub(p1,p2); z[2]=lsub(y,x);
1.2     ! noro     1251:            gerepilemanyvec(av,tetpil,z+1,2); return z;
1.1       noro     1252:
                   1253:          case t_PADIC:
                   1254:            if (krosg(-1,(GEN)y[2]))
                   1255:            {
                   1256:              z=cgetg(3,t_COMPLEX);
                   1257:              z[1]=lmul((GEN)x[1],y);
                   1258:              z[2]=lmul((GEN)x[2],y); return z;
                   1259:            }
                   1260:            av=avma;
                   1261:             if (signe(y[4])) l=precp(y);
                   1262:             else
                   1263:             {
                   1264:               l=valp(y)+1; if (l<=0) l=1;
                   1265:             }
                   1266:             p1=cvtop(x,(GEN)y[2],l); tetpil=avma;
                   1267:             return gerepile(av,tetpil,gmul(p1,y));
                   1268:
                   1269:          case t_QUAD:
1.2     ! noro     1270:            lx=precision(x); if (!lx) err(operi,"*",x,y);
        !          1271:            av=avma; p1=co8(y,lx); tetpil=avma;
        !          1272:            return gerepile(av,tetpil,gmul(p1,x));
1.1       noro     1273:        }
                   1274:
                   1275:       case t_PADIC:
                   1276:         switch(ty)
                   1277:        {
                   1278:          case t_PADIC:
1.2     ! noro     1279:            if (!egalii((GEN)x[2],(GEN)y[2])) err(operi,"*",x,y);
1.1       noro     1280:             l = valp(x)+valp(y);
                   1281:            if (!signe(x[4])) { z=gcopy(x); setvalp(z,l); return z; }
                   1282:            if (!signe(y[4])) { z=gcopy(y); setvalp(z,l); return z; }
                   1283:
                   1284:            p1 = (precp(x) > precp(y))? y: x;
                   1285:            z=cgetp(p1); setvalp(z,l); av=avma;
                   1286:            modiiz(mulii((GEN)x[4],(GEN)y[4]),(GEN)p1[3],(GEN)z[4]);
                   1287:            avma=av; return z;
                   1288:
                   1289:          case t_QUAD:
                   1290:            if (kro_quad((GEN)y[1],(GEN)x[2])== -1)
                   1291:            {
                   1292:              z=cgetg(4,t_QUAD);
                   1293:              copyifstack(y[1], z[1]);
                   1294:              z[2]=lmul((GEN)y[2],x);
                   1295:              z[3]=lmul((GEN)y[3],x); return z;
                   1296:            }
                   1297:             l = signe(x[4])? precp(x): valp(x)+1;
                   1298:            av=avma; p1=cvtop(y,(GEN)x[2],l); tetpil=avma;
                   1299:             return gerepile(av,tetpil,gmul(p1,x));
                   1300:        }
                   1301:
                   1302:       case t_QUAD: z=cgetg(4,t_QUAD);
                   1303:         p1=(GEN)x[1]; p2=(GEN)y[1];
1.2     ! noro     1304:         if (!gegal(p1,p2)) err(operi,"*",x,y);
1.1       noro     1305:
1.2     ! noro     1306:         copyifstack(p2, z[1]); av=avma;
1.1       noro     1307:         p2=gmul((GEN)x[2],(GEN)y[2]);
                   1308:         p3=gmul((GEN)x[3],(GEN)y[3]);
                   1309:         p4=gmul(gneg_i((GEN)p1[2]),p3);
                   1310:
                   1311:         if (gcmp0((GEN)p1[3]))
                   1312:         {
                   1313:           tetpil=avma;
1.2     ! noro     1314:           z[2]=lpile(av,tetpil,gadd(p4,p2)); av=avma;
1.1       noro     1315:           p2=gmul((GEN)x[2],(GEN)y[3]);
                   1316:           p3=gmul((GEN)x[3],(GEN)y[2]); tetpil=avma;
1.2     ! noro     1317:           z[3]=lpile(av,tetpil,gadd(p2,p3)); return z;
1.1       noro     1318:         }
                   1319:
                   1320:         p1 = gadd(gmul((GEN)x[2],(GEN)y[3]), gmul((GEN)x[3],(GEN)y[2]));
                   1321:         tetpil=avma;
                   1322:         z[2]=ladd(p2,p4);
                   1323:         z[3]=ladd(p1,p3);
1.2     ! noro     1324:         gerepilemanyvec(av,tetpil,z+2,2); return z;
1.1       noro     1325:     }
                   1326:     err(bugparier,"multiplication");
                   1327:   }
                   1328:
                   1329:   vx=gvar(x); vy=gvar(y);
                   1330:   if (!is_matvec_t(ty))
                   1331:     if (is_matvec_t(tx) || vx<vy || (vx==vy && tx>ty))
                   1332:     {
                   1333:       p1=x; x=y; y=p1;
                   1334:       i=tx; tx=ty; ty=i;
                   1335:       i=vx; vx=vy; vy=i;
                   1336:     }
                   1337:   if (ty==t_POLMOD) return op_polmod(gmul,x,y,tx);
                   1338:   if (is_noncalc_t(tx) || is_noncalc_t(ty)) return gmul_err(x,y,tx,ty);
                   1339:
                   1340:   /* here !isscalar(y) */
                   1341:   if (is_matvec_t(ty))
                   1342:   {
                   1343:     ly=lg(y);
                   1344:     if (!is_matvec_t(tx))
                   1345:     {
                   1346:       z=cgetg(ly,ty);
                   1347:       for (i=1; i<ly; i++) z[i]=lmul(x,(GEN)y[i]);
                   1348:       return z;
                   1349:     }
                   1350:     lx=lg(x);
                   1351:
                   1352:     switch(tx)
                   1353:     {
                   1354:       case t_VEC:
                   1355:         switch(ty)
                   1356:         {
                   1357:           case t_COL:
1.2     ! noro     1358:             if (lx!=ly) err(operi,"*",x,y);
        !          1359:             z=gzero; av=avma;
1.1       noro     1360:             for (i=1; i<lx; i++)
                   1361:             {
                   1362:               p1=gmul((GEN)x[i],(GEN)y[i]);
                   1363:               z=gadd(z,p1);
                   1364:             }
1.2     ! noro     1365:             return gerepileupto(av,z);
1.1       noro     1366:
                   1367:           case t_MAT:
                   1368:             if (ly==1) return cgetg(1,t_VEC);
1.2     ! noro     1369:             l=lg(y[1]); if (lx!=l) err(operi,"*",x,y);
1.1       noro     1370:
                   1371:             z=cgetg(ly,tx);
                   1372:             for (i=1; i<ly; i++)
                   1373:             {
                   1374:               p1=gzero; av=avma;
                   1375:               for (j=1; j<lx; j++)
                   1376:               {
                   1377:                 p2=gmul((GEN)x[j],gcoeff(y,j,i));
                   1378:                 p1=gadd(p1,p2);
                   1379:               }
                   1380:               z[i]=lpileupto(av,p1);
                   1381:             }
                   1382:             return z;
                   1383:
1.2     ! noro     1384:           default: err(operf,"*",x,y);
1.1       noro     1385:         }
                   1386:
                   1387:       case t_COL:
                   1388:         switch(ty)
                   1389:         {
                   1390:           case t_VEC:
                   1391:             z=cgetg(ly,t_MAT);
                   1392:             for (i=1; i<ly; i++)
                   1393:             {
                   1394:               p1 = gmul((GEN)y[i],x);
1.2     ! noro     1395:               if (typ(p1) != t_COL) err(operi,"*",x,y);
1.1       noro     1396:               z[i]=(long)p1;
                   1397:             }
                   1398:             return z;
                   1399:
                   1400:           case t_MAT:
1.2     ! noro     1401:             if (ly!=1 && lg(y[1])!=2) err(operi,"*",x,y);
1.1       noro     1402:
                   1403:             z=cgetg(ly,t_MAT);
                   1404:             for (i=1; i<ly; i++) z[i]=lmul(gcoeff(y,1,i),x);
                   1405:             return z;
                   1406:
1.2     ! noro     1407:           default: err(operf,"*",x,y);
1.1       noro     1408:         }
                   1409:
                   1410:       case t_MAT:
                   1411:         switch(ty)
                   1412:         {
                   1413:           case t_VEC:
1.2     ! noro     1414:             if (lx!=2) err(operi,"*",x,y);
1.1       noro     1415:             z=cgetg(ly,t_MAT);
                   1416:             for (i=1; i<ly; i++) z[i]=lmul((GEN)y[i],(GEN)x[1]);
                   1417:             return z;
                   1418:
                   1419:           case t_COL:
1.2     ! noro     1420:             if (lx!=ly) err(operi,"*",x,y);
1.1       noro     1421:             if (lx==1) return gcopy(y);
                   1422:
                   1423:             lx=lg(x[1]); z=cgetg(lx,t_COL);
                   1424:             for (i=1; i<lx; i++)
                   1425:             {
1.2     ! noro     1426:               p1=gzero; av=avma;
1.1       noro     1427:               for (j=1; j<ly; j++)
                   1428:               {
                   1429:                 p2=gmul(gcoeff(x,i,j),(GEN)y[j]);
                   1430:                 p1=gadd(p1,p2);
                   1431:               }
1.2     ! noro     1432:               z[i]=lpileupto(av,p1);
1.1       noro     1433:             }
                   1434:             return z;
                   1435:
                   1436:           case t_MAT:
                   1437:             if (ly==1) return cgetg(ly,t_MAT);
1.2     ! noro     1438:             if (lx != lg(y[1])) err(operi,"*",x,y);
1.1       noro     1439:             z=cgetg(ly,t_MAT);
                   1440:             if (lx==1)
                   1441:             {
                   1442:               for (i=1; i<ly; i++) z[i]=lgetg(1,t_COL);
                   1443:               return z;
                   1444:             }
                   1445:             l=lg(x[1]);
                   1446:             for (j=1; j<ly; j++)
                   1447:             {
                   1448:               z[j] = lgetg(l,t_COL);
                   1449:               for (i=1; i<l; i++)
                   1450:               {
                   1451:                 p1=gzero; av=avma;
                   1452:                 for (k=1; k<lx; k++)
                   1453:                 {
                   1454:                   p2=gmul(gcoeff(x,i,k),gcoeff(y,k,j));
                   1455:                   p1=gadd(p1,p2);
                   1456:                 }
                   1457:                 coeff(z,i,j)=lpileupto(av,p1);
                   1458:               }
                   1459:             }
                   1460:             return z;
                   1461:         }
                   1462:     }
                   1463:     err(bugparier,"multiplication");
                   1464:   }
                   1465:   /* now !ismatvec(x and y) */
                   1466:
                   1467:   if (vx>vy || (vx==vy && is_scalar_t(tx)))
                   1468:   {
                   1469:     if (isexactzero(x))
                   1470:     {
1.2     ! noro     1471:       if (vy == BIGINT) err(operf,"*",x,y);
1.1       noro     1472:       return zeropol(vy);
                   1473:     }
                   1474:     if (tx == t_INT && is_pm1(x))
                   1475:       return (signe(x)>0) ? gcopy(y): gneg(y);
                   1476:     if (tx == t_POLMOD && vx == vy && ty != t_SER)
                   1477:     {
                   1478:       av = avma;
                   1479:       return gerepileupto(av, op_polmod(gmul, x, to_polmod(y,(GEN)x[1]), tx));
                   1480:     }
                   1481:     switch(ty)
                   1482:     {
                   1483:       case t_POL:
                   1484:        if (isexactzero(y)) return zeropol(vy);
                   1485:         ly = lgef(y); z = cgetg(ly,t_POL); z[1]=y[1];
                   1486:         for (i=2; i<ly; i++) z[i]=lmul(x,(GEN)y[i]);
                   1487:         return normalizepol_i(z,ly);
                   1488:
                   1489:       case t_SER:
                   1490:        if (!signe(y)) return gcopy(y);
                   1491:        ly=lg(y); z=cgetg(ly,t_SER);
                   1492:        for (i=2; i<ly; i++) z[i]=lmul(x,(GEN)y[i]);
                   1493:        z[1]=y[1]; return normalize(z);
                   1494:
                   1495:       case t_RFRAC: return mulscalrfrac(x,y);
                   1496:       case t_RFRACN: av=avma; z=cgetg(3,t_RFRACN);
                   1497:         z[1]=lmul(x,(GEN)y[1]);
                   1498:         z[2]=lcopy((GEN)y[2]); return z;
1.2     ! noro     1499:       default: err(operf,"*",x,y);
1.1       noro     1500:     }
                   1501:   }
                   1502:
                   1503:   if (tx>ty) { p1=x; x=y; y=p1; i=tx; tx=ty; ty=i; }
                   1504:   switch(tx)
                   1505:   {
                   1506:     case t_POL:
                   1507:       switch (ty)
                   1508:       {
                   1509:        case t_POL:
                   1510:         {
                   1511: #if 0
                   1512: /* Too dangerous / cumbersome to correct here. Don't use t_POLMODS of
                   1513:  * t_INTMODs to represent elements of finite fields. Implement a finite
                   1514:  * field type instead and compute with polynomials with integer coeffs in
                   1515:  * Kronecker form...
                   1516:  * For gsqr, it's still idiotic to let ff_poltype correct bad implementations,
                   1517:  * but less dangerous.
                   1518:  */
                   1519:           GEN a = x,b = y
                   1520:           GEN p = NULL, pol = NULL;
1.2     ! noro     1521:           gpmem_t av = avma;
1.1       noro     1522:           if (ff_poltype(&x,&p,&pol) && ff_poltype(&y,&p,&pol))
                   1523:           {
                   1524:             /* fprintferr("HUM"); */
                   1525:             if (pol && varn(x) != varn(y))
                   1526:               x = to_Kronecker(x,pol);
                   1527:             z = quickmul(x+2, y+2, lgef(x)-2, lgef(y)-2);
                   1528:             if (p) z = FpX(z,p);
                   1529:             if (pol) z = from_Kronecker(z,pol);
                   1530:             z = gerepileupto(av, z);
                   1531:           }
                   1532:           else
                   1533:           {
                   1534:             avma = av;
                   1535:             z = quickmul(a+2, b+2, lgef(a)-2, lgef(b)-2);
                   1536:           }
                   1537: #else
                   1538:           z = quickmul(x+2, y+2, lgef(x)-2, lgef(y)-2);
                   1539: #endif
                   1540:           setvarn(z,vx); return z;
                   1541:         }
                   1542:        case t_SER:
                   1543:          if (gcmp0(x)) return zeropol(vx);
                   1544:          if (gcmp0(y)) return zeroser(vx, valp(y)+gval(x,vx));
                   1545:          p1=greffe(x,lg(y),0); p2=gmul(p1,y);
                   1546:           free(p1); return p2;
                   1547:
                   1548:         case t_RFRAC: return mulscalrfrac(x,y);
                   1549:         case t_RFRACN: av=avma; z=cgetg(3,t_RFRACN);
                   1550:           z[1]=lmul(x,(GEN)y[1]);
                   1551:           z[2]=lcopy((GEN)y[2]); return z;
                   1552:
1.2     ! noro     1553:        default: err(operf,"*",x,y);
1.1       noro     1554:       }
                   1555:
                   1556:     case t_SER:
                   1557:       switch (ty)
                   1558:       {
                   1559:        case t_SER:
1.2     ! noro     1560:         {
        !          1561:           long mix, miy;
1.1       noro     1562:          if (gcmp0(x) || gcmp0(y)) return zeroser(vx, valp(x)+valp(y));
                   1563:           lx=lg(x); ly=lg(y);
                   1564:          if (lx>ly) { k=ly; ly=lx; lx=k; p1=y; y=x; x=p1; }
                   1565:           z = cgetg(lx,t_SER);
                   1566:          z[1] = evalvalp(valp(x)+valp(y)) | evalvarn(vx) | evalsigne(1);
                   1567:           x += 2; y += 2; z += 2; lx -= 3;
                   1568:           p2 = (GEN)gpmalloc((lx+1)*sizeof(long));
1.2     ! noro     1569:           p3 = (GEN)gpmalloc((ly+1)*sizeof(long));
        !          1570:           mix = miy = 0;
1.1       noro     1571:          for (i=0; i<=lx; i++)
                   1572:           {
1.2     ! noro     1573:            p2[i] = !isexactzero((GEN)y[i]); if (p2[i]) miy = i;
        !          1574:            p3[i] = !isexactzero((GEN)x[i]); if (p3[i]) mix = i;
1.1       noro     1575:             p1 = gzero; av = avma;
1.2     ! noro     1576:             for (j=i-mix; j<=min(i,miy); j++)
        !          1577:               if (p2[j]) p1 = gadd(p1, gmul((GEN)y[j],(GEN)x[i-j]));
1.1       noro     1578:             z[i] = lpileupto(av,p1);
                   1579:           }
                   1580:           z -= 2; /* back to normalcy */
1.2     ! noro     1581:           free(p2);
        !          1582:           free(p3); return normalize(z);
        !          1583:         }
1.1       noro     1584:
                   1585:        case t_RFRAC: case t_RFRACN:
                   1586:          if (gcmp0(y)) return zeropol(vx);
                   1587:          if (gcmp0(x)) return zeroser(vx, valp(x)+gval(y,vx));
1.2     ! noro     1588:          av=avma; p1=gmul((GEN)y[1],x); tetpil=avma;
        !          1589:           return gerepile(av,tetpil,gdiv(p1,(GEN)y[2]));
1.1       noro     1590:
1.2     ! noro     1591:        default: err(operf,"*",x,y);
1.1       noro     1592:       }
                   1593:
                   1594:     /* (tx,ty) == t_RFRAC <==> ty == t_RFRAC */
                   1595:     case t_RFRAC: return mulrfrac(x,y);
                   1596:     case t_RFRACN:
1.2     ! noro     1597:       if (!is_rfrac_t(ty)) err(operf,"*",x,y);
1.1       noro     1598:       av=avma; z=cgetg(3,ty);
                   1599:       z[1]=lmul((GEN)x[1],(GEN)y[1]);
                   1600:       z[2]=lmul((GEN)x[2],(GEN)y[2]); return z;
                   1601:   }
                   1602:   return gmul_err(x,y,tx,ty);
                   1603: }
                   1604:
                   1605: GEN
                   1606: gsqr(GEN x)
                   1607: {
1.2     ! noro     1608:   long tx=typ(x), lx, i, j, k, l;
        !          1609:   gpmem_t av, tetpil;
1.1       noro     1610:   GEN z,p1,p2,p3,p4;
                   1611:
                   1612:   if (is_scalar_t(tx))
                   1613:     switch(tx)
                   1614:     {
                   1615:       case t_INT:
                   1616:        return sqri(x);
                   1617:
                   1618:       case t_REAL:
                   1619:        return mulrr(x,x);
                   1620:
                   1621:       case t_INTMOD: z=cgetg(3,t_INTMOD); p2=(GEN)x[1];
                   1622:         (void)new_chunk(lgefint(p2)<<2); /* HACK */
1.2     ! noro     1623:         p1=sqri((GEN)x[2]); avma=(gpmem_t)z;
1.1       noro     1624:         z[2]=lmodii(p1,p2); icopyifstack(p2,z[1]); return z;
                   1625:
                   1626:       case t_FRAC: case t_FRACN:
                   1627:        z=cgetg(3,tx);
                   1628:        z[1]=lsqri((GEN)x[1]);
                   1629:        z[2]=lsqri((GEN)x[2]);
                   1630:        return z;
                   1631:
                   1632:       case t_COMPLEX:
1.2     ! noro     1633:        z=cgetg(3,t_COMPLEX); av=avma;
1.1       noro     1634:        p1=gadd((GEN)x[1],(GEN)x[2]);
                   1635:        p2=gadd((GEN)x[1],gneg_i((GEN)x[2]));
                   1636:        p3=gmul((GEN)x[1],(GEN)x[2]);
                   1637:        tetpil=avma;
                   1638:        z[1]=lmul(p1,p2); z[2]=lshift(p3,1);
1.2     ! noro     1639:        gerepilemanyvec(av,tetpil,z+1,2);
1.1       noro     1640:        return z;
                   1641:
                   1642:       case t_PADIC:
                   1643:        z = cgetg(5,t_PADIC);
                   1644:        i = (egalii((GEN)x[2], gdeux) && signe(x[4]))? 1: 0;
                   1645:         if (i && precp(x) == 1) i = 2; /* (1 + O(2))^2 = 1 + O(2^3) */
                   1646:         z[1] = evalprecp(precp(x)+i) | evalvalp(2*valp(x));
                   1647:        icopyifstack(x[2], z[2]);
                   1648:         z[3] = lshifti((GEN)x[3], i); av = avma;
1.2     ! noro     1649:        z[4] = lpileuptoint(av, modii(sqri((GEN)x[4]), (GEN)z[3]));
1.1       noro     1650:        return z;
                   1651:
                   1652:       case t_QUAD:
1.2     ! noro     1653:        p1=(GEN)x[1]; z=cgetg(4,t_QUAD); av=avma;
1.1       noro     1654:        p2=gsqr((GEN)x[2]); p3=gsqr((GEN)x[3]);
                   1655:        p4=gmul(gneg_i((GEN)p1[2]),p3);
                   1656:
                   1657:        if (gcmp0((GEN)p1[3]))
                   1658:        {
                   1659:          tetpil=avma;
1.2     ! noro     1660:          z[2]=lpile(av,tetpil,gadd(p4,p2));
        !          1661:          av=avma; p2=gmul((GEN)x[2],(GEN)x[3]); tetpil=avma;
        !          1662:          z[3]=lpile(av,tetpil,gmul2n(p2,1));
1.1       noro     1663:          copyifstack(p1,z[1]); return z;
                   1664:        }
                   1665:
                   1666:        p1=gmul((GEN)x[2],(GEN)x[3]);
                   1667:        p1=gmul2n(p1,1); tetpil=avma;
                   1668:        z[2]=ladd(p2,p4); z[3]=ladd(p1,p3);
1.2     ! noro     1669:        gerepilemanyvec(av,tetpil,z+2,2);
1.1       noro     1670:        copyifstack(x[1],z[1]); return z;
                   1671:
                   1672:       case t_POLMOD:
1.2     ! noro     1673:         z=cgetg(3,t_POLMOD); copyifstack(x[1],z[1]);
        !          1674:        av=avma; p1=gsqr((GEN)x[2]); tetpil=avma;
        !          1675:         z[2]=lpile(av,tetpil, gres(p1,(GEN)z[1]));
1.1       noro     1676:        return z;
                   1677:     }
                   1678:
                   1679:   switch(tx)
                   1680:   {
                   1681:     case t_POL:
                   1682:     {
                   1683:       GEN a = x, p = NULL, pol = NULL;
                   1684:       long vx = varn(x);
                   1685:       av = avma;
                   1686:       if (ff_poltype(&x,&p,&pol))
                   1687:       {
                   1688:         z = quicksqr(x+2, lgef(x)-2);
                   1689:         if (p) z = FpX(z,p);
                   1690:         if (pol) z = from_Kronecker(z,pol);
                   1691:         z = gerepileupto(av, z);
                   1692:       }
                   1693:       else
                   1694:       {
                   1695:         avma = av;
                   1696:         z = quicksqr(a+2, lgef(a)-2);
                   1697:       }
                   1698:       setvarn(z, vx); return z;
                   1699:     }
                   1700:
                   1701:     case t_SER:
1.2     ! noro     1702:     {
        !          1703:       long mi;
1.1       noro     1704:       if (gcmp0(x)) return zeroser(varn(x), 2*valp(x));
                   1705:       lx = lg(x); z = cgetg(lx,tx);
                   1706:       z[1] = evalsigne(1) | evalvalp(2*valp(x)) | evalvarn(varn(x));
                   1707:       x += 2; z += 2; lx -= 3;
                   1708:       p2 = (GEN)gpmalloc((lx+1)*sizeof(long));
1.2     ! noro     1709:       mi = 0;
1.1       noro     1710:       for (i=0; i<=lx; i++)
                   1711:       {
1.2     ! noro     1712:        p2[i] = !isexactzero((GEN)x[i]); if (p2[i]) mi = i;
        !          1713:         p1=gzero; av=avma; l=((i+1)>>1) - 1;
        !          1714:         for (j=i-mi; j<=min(l,mi); j++)
        !          1715:           if (p2[j] && p2[i-j]) p1 = gadd(p1, gmul((GEN)x[j],(GEN)x[i-j]));
1.1       noro     1716:         p1 = gshift(p1,1);
                   1717:         if ((i&1) == 0 && p2[i>>1])
                   1718:           p1 = gadd(p1, gsqr((GEN)x[i>>1]));
                   1719:         z[i] = lpileupto(av,p1);
                   1720:       }
                   1721:       z -= 2; free(p2); return normalize(z);
1.2     ! noro     1722:     }
1.1       noro     1723:     case t_RFRAC: case t_RFRACN:
                   1724:       z=cgetg(3,tx);
                   1725:       z[1]=lsqr((GEN)x[1]);
                   1726:       z[2]=lsqr((GEN)x[2]); return z;
                   1727:
                   1728:     case t_MAT:
                   1729:       lx=lg(x);
                   1730:       if (lx==1) return cgetg(1,tx);
1.2     ! noro     1731:       if (lx != lg(x[1])) err(operi,"*",x,x);
1.1       noro     1732:       z=cgetg(lx,tx);
                   1733:       for (j=1; j<lx; j++)
                   1734:       {
                   1735:         z[j]=lgetg(lx,t_COL);
                   1736:         for (i=1; i<lx; i++)
                   1737:         {
1.2     ! noro     1738:           p1=gzero; av=avma;
1.1       noro     1739:           for (k=1; k<lx; k++)
                   1740:             p1 = gadd(p1, gmul(gcoeff(x,i,k),gcoeff(x,k,j)));
1.2     ! noro     1741:           coeff(z,i,j)=lpileupto(av,p1);
1.1       noro     1742:         }
                   1743:       }
                   1744:       return z;
                   1745:
                   1746:     case t_QFR: return sqcompreal(x);
                   1747:     case t_QFI: return sqcompimag(x);
                   1748:   }
                   1749:   return gmul_err(x,x,tx,tx);
                   1750: }
                   1751:
                   1752: /********************************************************************/
                   1753: /**                                                                **/
                   1754: /**                           DIVISION                             **/
                   1755: /**                                                                **/
                   1756: /********************************************************************/
                   1757:
                   1758: static
                   1759: GEN divrfracscal(GEN x, GEN y)
                   1760: {
                   1761:   long Y[3]; Y[1]=un; Y[2]=(long)y;
                   1762:   return mulrfrac(x,Y);
                   1763: }
                   1764:
                   1765: static
                   1766: GEN divscalrfrac(GEN x, GEN y)
                   1767: {
                   1768:   long Y[3]; Y[1]=y[2]; Y[2]=y[1];
                   1769:   return mulscalrfrac(x,Y);
                   1770: }
                   1771:
                   1772: static
                   1773: GEN divrfrac(GEN x, GEN y)
                   1774: {
                   1775:   long Y[3]; Y[1]=y[2]; Y[2]=y[1];
                   1776:   return mulrfrac(x,Y);
                   1777: }
                   1778:
                   1779: GEN
                   1780: gdiv(GEN x, GEN y)
                   1781: {
1.2     ! noro     1782:   long tx = typ(x), ty = typ(y), lx, ly, vx, vy, i, j, k, l;
        !          1783:   gpmem_t av, tetpil;
1.1       noro     1784:   GEN z,p1,p2,p3;
                   1785:
                   1786:   if (y == gun) return gcopy(x);
                   1787:   if (tx==t_INT && is_const_t(ty))
                   1788:   {
                   1789:     switch (signe(x))
                   1790:     {
                   1791:       case 0:
                   1792:         if (gcmp0(y)) err(gdiver2);
                   1793:         if (ty != t_INTMOD) return gzero;
                   1794:         z = cgetg(3,t_INTMOD); icopyifstack(y[1],z[1]); z[2]=zero;
                   1795:         return z;
                   1796:       case  1:
                   1797:         if (is_pm1(x)) return ginv(y);
                   1798:         break;
                   1799:       case -1:
                   1800:         if (is_pm1(x)) { av = avma; return gerepileupto(av, ginv(gneg(y))); }
                   1801:     }
                   1802:     switch(ty)
                   1803:     {
                   1804:       case t_INT:
                   1805:         return gred_frac2(x,y);
                   1806:       case t_REAL:
                   1807:         return divir(x,y);
                   1808:
                   1809:       case t_INTMOD:
                   1810:         z=cgetg(3,t_INTMOD); p2=(GEN)y[1];
                   1811:         (void)new_chunk(lgefint(p2)<<2); /* HACK */
1.2     ! noro     1812:         p1=mulii(modii(x,p2), mpinvmod((GEN)y[2],p2)); avma=(gpmem_t)z;
1.1       noro     1813:         z[2]=lmodii(p1,p2); icopyifstack(p2,z[1]); return z;
                   1814:
                   1815:       case t_FRAC:
                   1816:         z=cgetg(3,t_FRAC);
                   1817:         p1 = mppgcd(x,(GEN)y[1]);
                   1818:         if (is_pm1(p1))
                   1819:         {
1.2     ! noro     1820:           avma = (gpmem_t)z; tetpil = 0;
1.1       noro     1821:           z[2] = licopy((GEN)y[1]);
                   1822:         }
                   1823:         else
                   1824:         {
                   1825:           x = divii(x,p1); tetpil = avma;
                   1826:           z[2] = ldivii((GEN)y[1], p1);
                   1827:         }
                   1828:         z[1] = lmulii((GEN)y[2], x);
                   1829:         fix_frac(z);
                   1830:         if (tetpil)
                   1831:         { fix_frac_if_int_GC(z,tetpil); }
                   1832:         else
                   1833:           fix_frac_if_int(z);
                   1834:         return z;
                   1835:
                   1836:       case t_FRACN:
                   1837:         z=cgetg(3,t_FRACN);
                   1838:         z[1]=lmulii((GEN)y[2], x);
                   1839:         z[2]=licopy((GEN)y[1]);
                   1840:         fix_frac(z); return z;
                   1841:
                   1842:       case t_PADIC:
1.2     ! noro     1843:         av=avma; p1=cgetp(y); gaffect(x,p1); tetpil=avma;
        !          1844:         return gerepile(av,tetpil,gdiv(p1,y));
1.1       noro     1845:
                   1846:       case t_COMPLEX: case t_QUAD:
1.2     ! noro     1847:         av=avma; p1=gnorm(y); p2=gmul(x,gconj(y)); tetpil=avma;
        !          1848:         return gerepile(av,tetpil,gdiv(p2,p1));
1.1       noro     1849:     }
                   1850:   }
                   1851:   if (gcmp0(y) && ty != t_MAT) err(gdiver2);
                   1852:
                   1853:   if (is_const_t(tx) && is_const_t(ty))
                   1854:   {
                   1855:     switch(tx)
                   1856:     {
                   1857:       case t_REAL:
                   1858:        switch(ty)
                   1859:        {
                   1860:          case t_INT:
                   1861:            return divri(x,y);
                   1862:
                   1863:          case t_REAL:
                   1864:            return divrr(x,y);
                   1865:
                   1866:          case t_FRAC: case t_FRACN:
1.2     ! noro     1867:            av=avma; p1=mulri(x,(GEN)y[2]); tetpil=avma;
        !          1868:            return gerepile(av, tetpil, divri(p1,(GEN)y[1]));
1.1       noro     1869:
                   1870:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
1.2     ! noro     1871:             av=avma; p1=gnorm(y);
1.1       noro     1872:            p2=gmul(x,(GEN)y[1]);
                   1873:             p3=gmul(x,(GEN)y[2]);
                   1874:            if (!gcmp0(p3)) p3 = gneg_i(p3);
                   1875:             tetpil=avma;
                   1876:            z[1]=ldiv(p2,p1);
                   1877:             z[2]=ldiv(p3,p1);
1.2     ! noro     1878:            gerepilemanyvec(av,tetpil,z+1,2); return z;
1.1       noro     1879:
                   1880:          case t_QUAD:
1.2     ! noro     1881:            av=avma; p1=co8(y,lg(x)); tetpil=avma;
        !          1882:            return gerepile(av,tetpil,gdiv(x,p1));
1.1       noro     1883:
1.2     ! noro     1884:          case t_INTMOD: case t_PADIC: err(operf,"/",x,y);
1.1       noro     1885:        }
                   1886:
                   1887:       case t_INTMOD:
                   1888:        switch(ty)
                   1889:        {
                   1890:          case t_INT: z=cgetg(3,t_INTMOD); p2=(GEN)x[1];
                   1891:            (void)new_chunk(lgefint(p2)<<2); /* HACK */
1.2     ! noro     1892:            p1=mulii((GEN)x[2], mpinvmod(y,p2)); avma=(gpmem_t)z;
1.1       noro     1893:             z[2]=lmodii(p1,p2); icopyifstack(p2,z[1]); return z;
                   1894:
                   1895:          case t_INTMOD: z=cgetg(3,t_INTMOD); p2=(GEN)x[1]; p1=(GEN)y[1];
                   1896:            if (p1==p2 || egalii(p1,p2))
1.2     ! noro     1897:               icopyifstack(p2,z[1]);
1.1       noro     1898:             else
                   1899:             { p2 = mppgcd(p1,p2); z[1] = (long)p2; }
                   1900:             av=avma; (void)new_chunk(lgefint(x[1])+(lgefint(p1)<<1)); /* HACK */
                   1901:            p1=mulii((GEN)x[2], mpinvmod((GEN)y[2],p2)); avma=av;
                   1902:             z[2]=lmodii(p1,p2); return z;
                   1903:
                   1904:          case t_FRAC: z=cgetg(3,t_INTMOD); p2=(GEN)x[1];
                   1905:             (void)new_chunk(lgefint(p2)<<2); /* HACK */
                   1906:             p1=mulii((GEN)y[2], mpinvmod((GEN)y[1],p2));
1.2     ! noro     1907:             p1=mulii(modii(p1,p2),(GEN)x[2]); avma=(gpmem_t)z;
1.1       noro     1908:             z[2]=lmodii(p1,p2); icopyifstack(p2,z[1]); return z;
                   1909:
                   1910:          case t_FRACN:
1.2     ! noro     1911:            av=avma; p1=gred(y); tetpil=avma;
        !          1912:            return gerepile(av,tetpil,gdiv(x,p1));
1.1       noro     1913:
                   1914:          case t_COMPLEX: case t_QUAD:
1.2     ! noro     1915:            av=avma; p1=gnorm(y); p2=gmul(x,gconj(y)); tetpil=avma;
        !          1916:            return gerepile(av,tetpil,gdiv(p2,p1));
1.1       noro     1917:
                   1918:          case t_PADIC:
1.2     ! noro     1919:            av=avma; p1=cgetg(3,t_INTMOD); p1[1]=x[1]; p1[2]=lgeti(lg(x[1]));
        !          1920:            gaffect(y,p1); tetpil=avma; return gerepile(av,tetpil,gdiv(x,p1));
1.1       noro     1921:
1.2     ! noro     1922:          case t_REAL: err(operf,"/",x,y);
1.1       noro     1923:        }
                   1924:
                   1925:       case t_FRAC: case t_FRACN:
                   1926:        switch(ty)
                   1927:        {
                   1928:          case t_INT:
                   1929:           z = cgetg(3, tx);
                   1930:          if (tx == t_FRAC)
                   1931:           {
                   1932:             p1 = mppgcd(y,(GEN)x[1]);
                   1933:             if (is_pm1(p1))
                   1934:             {
1.2     ! noro     1935:               avma = (gpmem_t)z; tetpil = 0;
1.1       noro     1936:               z[1] = licopy((GEN)x[1]);
                   1937:             }
                   1938:             else
                   1939:             {
                   1940:               y = divii(y,p1); tetpil = avma;
                   1941:               z[1] = ldivii((GEN)x[1], p1);
                   1942:             }
                   1943:           }
                   1944:           else
                   1945:           {
                   1946:             tetpil = 0;
                   1947:             z[1] = licopy((GEN)x[1]);
                   1948:           }
                   1949:           z[2] = lmulii((GEN)x[2],y);
                   1950:           fix_frac(z);
                   1951:           if (tetpil) fix_frac_if_int_GC(z,tetpil);
                   1952:           return z;
                   1953:
                   1954:          case t_REAL:
1.2     ! noro     1955:            av=avma; p1=mulri(y,(GEN)x[2]); tetpil=avma;
        !          1956:             return gerepile(av, tetpil, divir((GEN)x[1], p1));
1.1       noro     1957:
                   1958:          case t_INTMOD: z=cgetg(3,t_INTMOD); p2=(GEN)y[1];
                   1959:             (void)new_chunk(lgefint(p2)<<2); /* HACK */
                   1960:            p1=mulii((GEN)y[2],(GEN)x[2]);
1.2     ! noro     1961:            p1=mulii(mpinvmod(p1,p2), modii((GEN)x[1],p2)); avma=(gpmem_t)z;
1.1       noro     1962:            z[2]=lmodii(p1,p2); icopyifstack(p2,z[1]); return z;
                   1963:
                   1964:          case t_FRAC: if (tx == t_FRACN) ty=t_FRACN;
                   1965:           case t_FRACN:
                   1966:            z = cgetg(3,ty);
                   1967:             if (ty == t_FRAC)
                   1968:             {
                   1969:               GEN x1 = (GEN)x[1], x2 = (GEN)x[2];
                   1970:               GEN y1 = (GEN)y[1], y2 = (GEN)y[2];
                   1971:               p1 = mppgcd(x1, y1);
                   1972:               if (!is_pm1(p1)) { x1 = divii(x1,p1); y1 = divii(y1,p1); }
                   1973:               p1 = mppgcd(x2, y2);
                   1974:               if (!is_pm1(p1)) { x2 = divii(x2,p1); y2 = divii(y2,p1); }
                   1975:               tetpil = avma;
                   1976:               z[2] = lmulii(x2,y1);
                   1977:               z[1] = lmulii(x1,y2);
                   1978:               fix_frac(z);
                   1979:               fix_frac_if_int_GC(z,tetpil);
                   1980:             }
                   1981:             else
                   1982:             {
                   1983:               z[1]=lmulii((GEN)x[1],(GEN)y[2]);
                   1984:               z[2]=lmulii((GEN)x[2],(GEN)y[1]);
                   1985:               fix_frac(z);
                   1986:             }
                   1987:             return z;
                   1988:
                   1989:          case t_COMPLEX: z=cgetg(3,t_COMPLEX);
1.2     ! noro     1990:             av=avma; p1=gnorm(y);
1.1       noro     1991:            p2=gmul(x,(GEN)y[1]);
                   1992:            p3=gmul(x,(GEN)y[2]);
                   1993:             if(!gcmp0(p3)) p3 = gneg_i(p3);
                   1994:            tetpil=avma;
                   1995:            z[1]=ldiv(p2,p1); z[2]=ldiv(p3,p1);
1.2     ! noro     1996:            gerepilemanyvec(av,tetpil,z+1,2); return z;
1.1       noro     1997:
                   1998:          case t_PADIC:
                   1999:            if (!signe(x[1])) return gzero;
                   2000:
1.2     ! noro     2001:            av=avma; p1=cgetp(y); gaffect(x,p1);
        !          2002:            tetpil=avma; return gerepile(av,tetpil,gdiv(p1,y));
1.1       noro     2003:
                   2004:          case t_QUAD:
1.2     ! noro     2005:            av=avma; p1=gnorm(y); p2=gmul(x,gconj(y)); tetpil=avma;
        !          2006:            return gerepile(av,tetpil,gdiv(p2,p1));
1.1       noro     2007:        }
                   2008:
                   2009:       case t_COMPLEX:
                   2010:        switch(ty)
                   2011:        {
                   2012:          case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_FRACN:
                   2013:            z=cgetg(3,t_COMPLEX);
                   2014:            z[1]=ldiv((GEN)x[1],y);
                   2015:            z[2]=ldiv((GEN)x[2],y); return z;
                   2016:
                   2017:          case t_COMPLEX:
1.2     ! noro     2018:            av=avma; p1=gnorm(y); p2=gconj(y); p2=gmul(x,p2); tetpil=avma;
        !          2019:            return gerepile(av,tetpil, gdiv(p2,p1));
1.1       noro     2020:
                   2021:          case t_PADIC:
                   2022:            if (krosg(-1,(GEN)y[2])== -1)
                   2023:            {
                   2024:              z=cgetg(3,t_COMPLEX);
                   2025:              z[1]=ldiv((GEN)x[1],y);
                   2026:              z[2]=ldiv((GEN)x[2],y); return z;
                   2027:            }
                   2028:            av=avma; p1=cvtop(x,(GEN)y[2],precp(y)); tetpil=avma;
                   2029:            return gerepile(av,tetpil,gdiv(p1,y));
                   2030:
                   2031:          case t_QUAD:
1.2     ! noro     2032:            lx=precision(x); if (!lx) err(operi,"/",x,y);
        !          2033:            av=avma; p1=co8(y,lx); tetpil=avma;
        !          2034:            return gerepile(av,tetpil,gdiv(x,p1));
1.1       noro     2035:        }
                   2036:
                   2037:       case t_PADIC:
                   2038:        switch(ty)
                   2039:        {
                   2040:          case t_INT: case t_FRAC: case t_FRACN:
1.2     ! noro     2041:            av=avma;
1.1       noro     2042:            if (signe(x[4])) { p1=cgetp(x); gaffect(y,p1); }
                   2043:            else p1=cvtop(y,(GEN)x[2],(valp(x)>0)?valp(x):1);
1.2     ! noro     2044:            tetpil=avma; return gerepile(av,tetpil,gdiv(x,p1));
1.1       noro     2045:
                   2046:          case t_INTMOD:
1.2     ! noro     2047:            av=avma; p1=cgetg(3,t_INTMOD);
1.1       noro     2048:            p1[1]=y[1]; p1[2]=lgeti(lg(y[1]));
                   2049:            gaffect(x,p1); tetpil=avma;
1.2     ! noro     2050:            return gerepile(av,tetpil,gdiv(p1,y));
1.1       noro     2051:
                   2052:          case t_PADIC:
1.2     ! noro     2053:            if (!egalii((GEN)x[2],(GEN)y[2])) err(operi,"/",x,y);
1.1       noro     2054:            if (!signe(x[4]))
                   2055:            {
                   2056:              z=gcopy(x); setvalp(z,valp(x)-valp(y));
                   2057:              return z;
                   2058:            }
                   2059:
                   2060:            p1=(precp(x)>precp(y)) ? y : x;
1.2     ! noro     2061:            z=cgetp(p1); av=avma;
1.1       noro     2062:            setvalp(z,valp(x)-valp(y));
                   2063:            p2=mpinvmod((GEN)y[4],(GEN)p1[3]);
                   2064:            modiiz(mulii((GEN)x[4],p2),(GEN)p1[3],(GEN)z[4]);
1.2     ! noro     2065:            avma=av; return z;
1.1       noro     2066:
                   2067:          case t_COMPLEX: case t_QUAD:
1.2     ! noro     2068:            av=avma; p1=gmul(x,gconj(y)); p2=gnorm(y); tetpil=avma;
        !          2069:            return gerepile(av,tetpil,gdiv(p1,p2));
1.1       noro     2070:
                   2071:          case t_REAL:
1.2     ! noro     2072:            err(operf,"/",x,y);
1.1       noro     2073:        }
                   2074:
                   2075:       case t_QUAD:
                   2076:        switch (ty)
                   2077:        {
                   2078:          case t_INT: case t_INTMOD: case t_FRAC: case t_FRACN:
                   2079:            z=cgetg(4,t_QUAD);
                   2080:            copyifstack(x[1], z[1]);
                   2081:            for (i=2; i<4; i++) z[i]=ldiv((GEN)x[i],y);
                   2082:            return z;
                   2083:
                   2084:          case t_REAL:
1.2     ! noro     2085:            av=avma; p1=co8(x,lg(y)); tetpil=avma;
        !          2086:            return gerepile(av,tetpil,gdiv(p1,y));
1.1       noro     2087:
                   2088:          case t_PADIC:
1.2     ! noro     2089:            av=avma; p1=cvtop(x,(GEN)y[2],precp(y));
        !          2090:            tetpil=avma; return gerepile(av,tetpil,gdiv(p1,y));
1.1       noro     2091:
                   2092:          case t_COMPLEX:
1.2     ! noro     2093:            ly=precision(y); if (!ly) err(operi,"/",x,y);
        !          2094:            av=avma; p1=co8(x,ly); tetpil=avma;
        !          2095:            return gerepile(av,tetpil,gdiv(p1,y));
1.1       noro     2096:
                   2097:          case t_QUAD:
                   2098:            k=x[1]; l=y[1];
1.2     ! noro     2099:            if (!gegal((GEN)k,(GEN)l)) err(operi,"/",x,y);
        !          2100:            av=avma; p1=gnorm(y); p2=gmul(x,gconj(y)); tetpil=avma;
        !          2101:            return gerepile(av,tetpil,gdiv(p2,p1));
1.1       noro     2102:        }
                   2103:     }
                   2104:     err(bugparier,"division");
                   2105:   }
                   2106:
                   2107:   vx=gvar(x); vy=gvar(y);
                   2108:   if (ty == t_POLMOD || ty == t_INTMOD)
                   2109:   {
                   2110:     av = avma;
                   2111:     return gerepileupto(av, gmul(x, ginv(y)));
                   2112:   }
                   2113:   if (tx == t_POLMOD && vx<=vy)
                   2114:   {
                   2115:     av = avma;
                   2116:     if (vx == vy)
                   2117:       y = gmul(y, gmodulsg(1, (GEN)x[1]));
                   2118:     else if (is_extscalar_t(ty))
                   2119:     {
                   2120:       z=cgetg(3,t_POLMOD);
                   2121:       copyifstack(x[1],z[1]);
                   2122:       z[2]=ldiv((GEN)x[2],y); return z;
                   2123:     }
                   2124:     return gerepileupto(av, gmul(x, ginv(y)));
                   2125:   }
1.2     ! noro     2126:   if (is_noncalc_t(tx) || is_noncalc_t(ty)) err(operf,"/",x,y);
1.1       noro     2127:   /* now x and y are not both is_scalar_t */
                   2128:
                   2129:   lx = lg(x);
                   2130:   if ((vx<vy && (!is_matvec_t(tx) || !is_matvec_t(ty)))
                   2131:      || (vx==vy && is_scalar_t(ty)) || (is_matvec_t(tx) && !is_matvec_t(ty)))
                   2132:   {
                   2133:     if (tx == t_RFRAC) return divrfracscal(x,y);
                   2134:     z = cgetg(lx,tx);
                   2135:     if (tx == t_RFRACN)
                   2136:     {
                   2137:       z[2]=lmul((GEN)x[2],y);
                   2138:       z[1]=lcopy((GEN)x[1]); return z;
                   2139:     }
                   2140:     switch(tx)
                   2141:     {
                   2142:       case t_POL: lx = lgef(x);
                   2143:       case t_SER: z[1] = x[1];
                   2144:       case t_VEC: case t_COL: case t_MAT:
                   2145:         for (i=lontyp[tx]; i<lx; i++) z[i]=ldiv((GEN)x[i],y);
                   2146:         return z;
                   2147:     }
1.2     ! noro     2148:     err(operf,"/",x,y);
1.1       noro     2149:   }
                   2150:
                   2151:   ly=lg(y);
                   2152:   if (vy<vx || (vy==vx && is_scalar_t(tx)))
                   2153:   {
                   2154:     switch(ty)
                   2155:     {
                   2156:       case t_POL:
                   2157:        if (lgef(y)==3) return gdiv(x,(GEN)y[2]);
                   2158:         if (isexactzero(x)) return zeropol(vy);
                   2159:         return gred_rfrac2(x,y);
                   2160:
                   2161:       case t_SER:
                   2162:        if (gcmp0(x))
                   2163:        {
1.2     ! noro     2164:           av=avma; p1=ginv(y); tetpil=avma; /* a ameliorer !!!! */
        !          2165:          return gerepile(av,tetpil,gmul(x,p1));
1.1       noro     2166:        }
                   2167:         p1 = (GEN)gpmalloc(ly*sizeof(long));
                   2168:         p1[0] = evaltyp(t_SER) | evallg(ly);
                   2169:        p1[1] = evalsigne(1) | evalvalp(0) | evalvarn(vy);
                   2170:         p1[2] = (long)x; for (i=3; i<ly; i++) p1[i]=zero;
                   2171:         y = gdiv(p1,y); free(p1); return y;
                   2172:
                   2173:       case t_RFRAC: return divscalrfrac(x,y);
                   2174:       case t_RFRACN: z=cgetg(ly,t_RFRACN);
                   2175:         z[1]=lmul(x,(GEN)y[2]);
                   2176:         z[2]=lcopy((GEN)y[1]); return z;
                   2177:
                   2178:       case t_MAT:
1.2     ! noro     2179:        av=avma; p1=invmat(y); tetpil=avma;
        !          2180:        return gerepile(av,tetpil,gmul(x,p1));
1.1       noro     2181:
1.2     ! noro     2182:       case t_VEC: case t_COL: err(operf,"/",x,y);
1.1       noro     2183:     }
1.2     ! noro     2184:     err(operf,"/",x,y);
1.1       noro     2185:   }
                   2186:
                   2187:   /* ici vx=vy et tx>=10 et ty>=10*/
                   2188:   switch(tx)
                   2189:   {
                   2190:     case t_POL:
                   2191:       switch(ty)
                   2192:       {
                   2193:        case t_POL:
                   2194:           if (lgef(y)==3) return gdiv(x,(GEN)y[2]);
                   2195:           if (isexactzero(x)) return zeropol(vy);
                   2196:           return gred_rfrac2(x,y);
                   2197:
                   2198:        case t_SER:
                   2199:          if (gcmp0(x)) return zeropol(vx);
                   2200:          p1=greffe(x,ly,0); p2=gdiv(p1,y);
                   2201:           free(p1); return p2;
                   2202:
                   2203:         case t_RFRAC: return divscalrfrac(x,y);
                   2204:         case t_RFRACN: z=cgetg(ly,t_RFRACN);
                   2205:          z[1]=lmul(x,(GEN)y[2]);
                   2206:          z[2]=lcopy((GEN)y[1]); return z;
                   2207:
1.2     ! noro     2208:        default: err(operf,"/",x,y);
1.1       noro     2209:       }
                   2210:
                   2211:     case t_SER:
                   2212:       switch(ty)
                   2213:       {
                   2214:        case t_POL:
                   2215:          p1=greffe(y,lg(x),0); p2=gdiv(x,p1);
                   2216:           free(p1); return p2;
                   2217:
                   2218:        case t_SER:
                   2219:         {
                   2220:           GEN y_lead;
                   2221:
                   2222:           l = valp(x) - valp(y);
                   2223:          if (gcmp0(x)) return zeroser(vx,l);
                   2224:           y_lead = (GEN)y[2];
                   2225:           if (gcmp0(y_lead)) /* normalize denominator if leading term is 0 */
                   2226:           {
                   2227:             err(warner,"normalizing a series with 0 leading term");
                   2228:             for (i=3,y++; i<ly; i++,y++)
                   2229:             {
                   2230:               y_lead = (GEN)y[2]; ly--; l--;
                   2231:               if (!gcmp0(y_lead)) break;
                   2232:             }
                   2233:             if (i>=ly) err(gdiver2);
                   2234:           }
                   2235:          if (ly < lx) lx = ly;
                   2236:          p2 = (GEN)gpmalloc(lx*sizeof(long));
                   2237:          for (i=3; i<lx; i++)
                   2238:           {
                   2239:             p1 = (GEN)y[i];
                   2240:             if (isexactzero(p1)) p2[i] = 0;
                   2241:             else
                   2242:             {
                   2243:               av = avma; p2[i] = lclone(gneg_i(p1));
                   2244:               avma = av;
                   2245:             }
                   2246:           }
                   2247:          z = cgetg(lx,t_SER);
                   2248:           z[1] = evalvalp(l) | evalvarn(vx) | evalsigne(1);
                   2249:          z[2] = ldiv((GEN)x[2], y_lead);
                   2250:          for (i=3; i<lx; i++)
                   2251:          {
                   2252:            av=avma; p1 = (GEN)x[i];
                   2253:            for (j=2; j<i; j++)
                   2254:             {
                   2255:               l = i-j+2;
                   2256:               if (p2[l])
                   2257:                 p1 = gadd(p1, gmul((GEN)z[j], (GEN)p2[l]));
                   2258:             }
                   2259:             p1 = gdiv(p1, y_lead);
                   2260:            tetpil=avma; z[i]=lpile(av,tetpil, forcecopy(p1));
                   2261:          }
                   2262:           for (i=3; i<lx; i++)
                   2263:             if (p2[i]) gunclone((GEN)p2[i]);
                   2264:           free(p2); return z;
                   2265:         }
                   2266:
                   2267:        case t_RFRAC: case t_RFRACN:
1.2     ! noro     2268:          av=avma; p2=gmul(x,(GEN)y[2]); tetpil=avma;
        !          2269:          return gerepile(av,tetpil,gdiv(p2,(GEN)y[1]));
1.1       noro     2270:
1.2     ! noro     2271:        default: err(operf,"/",x,y);
1.1       noro     2272:       }
                   2273:
                   2274:     case t_RFRAC: case t_RFRACN:
                   2275:       switch(ty)
                   2276:       {
                   2277:        case t_POL:
                   2278:           if (tx==t_RFRAC) return  divrfracscal(x,y);
                   2279:           z=cgetg(3,t_RFRACN);
                   2280:           z[2]=lmul((GEN)x[2],y);
                   2281:          z[1]=lcopy((GEN)x[1]); return z;
                   2282:
                   2283:        case t_SER:
1.2     ! noro     2284:          av=avma; p2=gmul((GEN)x[2],y); tetpil=avma;
        !          2285:          return gerepile(av,tetpil, gdiv((GEN)x[1],p2));
1.1       noro     2286:
                   2287:        case t_RFRAC: case t_RFRACN:
                   2288:          if (tx == t_RFRACN) ty=t_RFRACN;
                   2289:           if (ty != t_RFRACN) return divrfrac(x,y);
                   2290:          z=cgetg(3,t_RFRACN);
                   2291:          z[1]=lmul((GEN)x[1],(GEN)y[2]);
                   2292:           z[2]=lmul((GEN)x[2],(GEN)y[1]); return z;
                   2293:
1.2     ! noro     2294:        default: err(operf,"/",x,y);
1.1       noro     2295:       }
                   2296:
                   2297:     case t_VEC: case t_COL: case t_MAT:
                   2298:       if (!is_matvec_t(ty))
                   2299:       {
                   2300:        z=cgetg(lx,tx);
                   2301:        for (i=1; i<lx; i++) z[i]=ldiv((GEN)x[i],y);
                   2302:        return z;
                   2303:       }
1.2     ! noro     2304:       if (ty!=t_MAT || ly==1 || lg(y[1])!=ly) err(operi,"/",x,y);
        !          2305:       av=avma; p1=invmat(y); tetpil=avma;
        !          2306:       return gerepile(av,tetpil,gmul(x,p1));
1.1       noro     2307:      case t_QFI:case t_QFR:
                   2308:        break;
1.2     ! noro     2309:      default: err(operf,"/",x,y);
1.1       noro     2310:   }
                   2311:   /*Here tx==t_QFI || tx==t_QFR*/
                   2312:   if (tx==ty)
                   2313:   {
                   2314:     l=signe(y[2]); setsigne(y[2],-l);
                   2315:     switch(tx)
                   2316:     {
                   2317:       case t_QFI: z = compimag(x,y);
                   2318:         setsigne(y[2],l); return z;
                   2319:       case t_QFR:
                   2320:         k=signe(y[4]); setsigne(y[4],-k); z=compreal(x,y);
                   2321:         setsigne(y[2],l); setsigne(y[4],k); return z;
                   2322:     }
                   2323:   }
1.2     ! noro     2324:   err(operf,"/",x,y);
1.1       noro     2325:   return NULL; /* not reached */
                   2326: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>