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

Annotation of OpenXM_contrib/pari/src/basemath/polarit3.c, Revision 1.1

1.1     ! maekawa     1: /***********************************************************************/
        !             2: /**                                                                   **/
        !             3: /**               ARITHMETIC OPERATIONS ON POLYNOMIALS                **/
        !             4: /**                         (third part)                              **/
        !             5: /**                                                                   **/
        !             6: /***********************************************************************/
        !             7: /* $Id: polarit3.c,v 1.1.1.1 1999/09/16 13:47:36 karim Exp $ */
        !             8: #include "pari.h"
        !             9:
        !            10: /*******************************************************************/
        !            11: /*                                                                 */
        !            12: /*                  KARATSUBA (for polynomials)                    */
        !            13: /*                                                                 */
        !            14: /*******************************************************************/
        !            15: #define swapspec(x,y, nx,ny) {long _a=nx;GEN _z=x; nx=ny; ny=_a; x=y; y=_z;}
        !            16:
        !            17: #if 1 /* for tunings */
        !            18: long SQR_LIMIT = 6;
        !            19: long MUL_LIMIT = 10;
        !            20:
        !            21: void
        !            22: setsqpol(long a) { SQR_LIMIT=a; }
        !            23: void
        !            24: setmulpol(long a) { MUL_LIMIT=a; }
        !            25:
        !            26: GEN
        !            27: specpol(GEN x, long nx)
        !            28: {
        !            29:   GEN z = cgetg(nx+2,t_POL);
        !            30:   long i;
        !            31:   for (i=0; i<nx; i++) z[i+2] = x[i];
        !            32:   z[1]=evalsigne(1)|evallgef(nx+2);
        !            33:   return z;
        !            34: }
        !            35: #else
        !            36: #  define SQR_LIMIT 6
        !            37: #  define MUL_LIMIT 10
        !            38: #endif
        !            39:
        !            40: static GEN
        !            41: addpol(GEN x, GEN y, long lx, long ly)
        !            42: {
        !            43:   long i,lz;
        !            44:   GEN z;
        !            45:
        !            46:   if (ly>lx) swapspec(x,y, lx,ly);
        !            47:   lz = lx+2; z = cgetg(lz,t_POL) + 2;
        !            48:   for (i=0; i<ly; i++) z[i]=ladd((GEN)x[i],(GEN)y[i]);
        !            49:   for (   ; i<lx; i++) z[i]=x[i];
        !            50:   z -= 2; z[1]=0; return normalizepol_i(z, lz);
        !            51: }
        !            52:
        !            53: static GEN
        !            54: addpolcopy(GEN x, GEN y, long lx, long ly)
        !            55: {
        !            56:   long i,lz;
        !            57:   GEN z;
        !            58:
        !            59:   if (ly>lx) swapspec(x,y, lx,ly);
        !            60:   lz = lx+2; z = cgetg(lz,t_POL) + 2;
        !            61:   for (i=0; i<ly; i++) z[i]=ladd((GEN)x[i],(GEN)y[i]);
        !            62:   for (   ; i<lx; i++) z[i]=lcopy((GEN)x[i]);
        !            63:   z -= 2; z[1]=0; return normalizepol_i(z, lz);
        !            64: }
        !            65:
        !            66: #ifdef INLINE
        !            67: INLINE
        !            68: #endif
        !            69: GEN
        !            70: mulpol_limb(GEN x, GEN y, char *ynonzero, long a, long b)
        !            71: {
        !            72:   GEN p1 = NULL;
        !            73:   long i,av = avma;
        !            74:   for (i=a; i<b; i++)
        !            75:     if (ynonzero[i])
        !            76:     {
        !            77:       GEN p2 = gmul((GEN)y[i],(GEN)x[-i]);
        !            78:       p1 = p1 ? gadd(p1, p2): p2;
        !            79:     }
        !            80:   return p1 ? gerepileupto(av, p1): gzero;
        !            81: }
        !            82:
        !            83: static GEN
        !            84: mulpol(GEN x, GEN y, long nx, long ny)
        !            85: {
        !            86:   long i,lz,nz;
        !            87:   GEN z;
        !            88:   char *p1;
        !            89:
        !            90:   if (!ny) return zeropol(0);
        !            91:   lz = nx+ny+1; nz = lz-2;
        !            92:   z = cgetg(lz, t_POL) + 2; /* x:y:z [i] = term of degree i */
        !            93:   p1 = gpmalloc(ny);
        !            94:   for (i=0; i<ny; i++)
        !            95:   {
        !            96:     p1[i] = !isexactzero((GEN)y[i]);
        !            97:     z[i] = (long)mulpol_limb(x+i,y,p1,0,i+1);
        !            98:   }
        !            99:   for (  ; i<nx; i++) z[i] = (long)mulpol_limb(x+i,y,p1,0,ny);
        !           100:   for (  ; i<nz; i++) z[i] = (long)mulpol_limb(x+i,y,p1,i-nx+1,ny);
        !           101:   free(p1); z -= 2; z[1]=0; return normalizepol_i(z, lz);
        !           102: }
        !           103:
        !           104: /* return (x * X^d) + y. Assume d > 0, x > 0 and y >= 0 */
        !           105: GEN
        !           106: addshiftw(GEN x, GEN y, long d)
        !           107: {
        !           108:   GEN xd,yd,zd = (GEN)avma;
        !           109:   long a,lz,ny = lgef(y)-2, nx = lgef(x)-2;
        !           110:
        !           111:   x += 2; y += 2; a = ny-d;
        !           112:   if (a <= 0)
        !           113:   {
        !           114:     lz = (a>nx)? ny+2: nx+d+2;
        !           115:     (void)new_chunk(lz); xd = x+nx; yd = y+ny;
        !           116:     while (xd > x) *--zd = *--xd;
        !           117:     x = zd + a;
        !           118:     while (zd > x) *--zd = zero;
        !           119:   }
        !           120:   else
        !           121:   {
        !           122:     xd = new_chunk(d); yd = y+d;
        !           123:     x = addpol(x,yd, nx,a);
        !           124:     lz = (a>nx)? ny+2: lgef(x)+d;
        !           125:     x += 2; while (xd > x) *--zd = *--xd;
        !           126:   }
        !           127:   while (yd > y) *--zd = *--yd;
        !           128:   *--zd = evalsigne(1) | evallgef(lz);
        !           129:   *--zd = evaltyp(t_POL) | evallg(lz); return zd;
        !           130: }
        !           131:
        !           132: GEN
        !           133: addshiftpol(GEN x, GEN y, long d)
        !           134: {
        !           135:   long v = varn(x);
        !           136:   if (!signe(x)) return y;
        !           137:   x = addshiftw(x,y,d);
        !           138:   setvarn(x,v); return x;
        !           139: }
        !           140:
        !           141: /* as above, producing a clean stack */
        !           142: static GEN
        !           143: addshiftwcopy(GEN x, GEN y, long d)
        !           144: {
        !           145:   GEN xd,yd,zd = (GEN)avma;
        !           146:   long a,lz,ny = lgef(y)-2, nx = lgef(x)-2;
        !           147:
        !           148:   x += 2; y += 2; a = ny-d;
        !           149:   if (a <= 0)
        !           150:   {
        !           151:     lz = nx+d+2;
        !           152:     (void)new_chunk(lz); xd = x+nx; yd = y+ny;
        !           153:     while (xd > x) *--zd = lcopy((GEN)*--xd);
        !           154:     x = zd + a;
        !           155:     while (zd > x) *--zd = zero;
        !           156:   }
        !           157:   else
        !           158:   {
        !           159:     xd = new_chunk(d); yd = y+d;
        !           160:     x = addpolcopy(x,yd, nx,a);
        !           161:     lz = (a>nx)? ny+2: lgef(x)+d;
        !           162:     x += 2; while (xd > x) *--zd = *--xd;
        !           163:   }
        !           164:   while (yd > y) *--zd = lcopy((GEN)*--yd);
        !           165:   *--zd = evalsigne(1) | evallgef(lz);
        !           166:   *--zd = evaltyp(t_POL) | evallg(lz); return zd;
        !           167: }
        !           168:
        !           169: /* fast product (Karatsuba) of polynomials a,b. These are not real GENs, a+2,
        !           170:  * b+2 were sent instead. na, nb = number of terms of a, b.
        !           171:  * Only c, c0, c1, c2 are genuine GEN.
        !           172:  */
        !           173: GEN
        !           174: quickmul(GEN a, GEN b, long na, long nb)
        !           175: {
        !           176:   GEN a0,c,c0;
        !           177:   long av,n0,n0a,i;
        !           178:
        !           179:   if (na < nb) swapspec(a,b, na,nb);
        !           180:   if (nb < MUL_LIMIT) return mulpol(a,b,na,nb);
        !           181:   i=(na>>1); n0=na-i; na=i;
        !           182:   av=avma; a0=a+n0; n0a=n0;
        !           183:   while (n0a && isexactzero((GEN)a[n0a-1])) n0a--;
        !           184:
        !           185:   if (nb > n0)
        !           186:   {
        !           187:     GEN b0,c1,c2;
        !           188:     long n0b;
        !           189:
        !           190:     nb -= n0; b0 = b+n0; n0b = n0;
        !           191:     while (n0b && isexactzero((GEN)b[n0b-1])) n0b--;
        !           192:     c = quickmul(a,b,n0a,n0b);
        !           193:     c0 = quickmul(a0,b0, na,nb);
        !           194:
        !           195:     c2 = addpol(a0,a, na,n0a);
        !           196:     c1 = addpol(b0,b, nb,n0b);
        !           197:
        !           198:     c1 = quickmul(c1+2,c2+2, lgef(c1)-2,lgef(c2)-2);
        !           199:     c2 = gneg_i(gadd(c0,c));
        !           200:     c0 = addshiftw(c0, gadd(c1,c2), n0);
        !           201:   }
        !           202:   else
        !           203:   {
        !           204:     c = quickmul(a,b,n0a,nb);
        !           205:     c0 = quickmul(a0,b,na,nb);
        !           206:   }
        !           207:   c0 = addshiftwcopy(c0,c,n0);
        !           208:   return gerepileupto(av,c0);
        !           209: }
        !           210:
        !           211: GEN
        !           212: sqrpol(GEN x, long nx)
        !           213: {
        !           214:   long av,i,j,l,lz,nz;
        !           215:   GEN p1,z;
        !           216:   char *p2;
        !           217:
        !           218:   if (!nx) return zeropol(0);
        !           219:   lz = (nx << 1) + 1, nz = lz-2;
        !           220:   z = cgetg(lz,t_POL) + 2;
        !           221:   p2 = gpmalloc(nx);
        !           222:   for (i=0; i<nx; i++)
        !           223:   {
        !           224:     p2[i] = !isexactzero((GEN)x[i]);
        !           225:     p1=gzero; av=avma; l=(i+1)>>1;
        !           226:     for (j=0; j<l; j++)
        !           227:       if (p2[j] && p2[i-j])
        !           228:         p1 = gadd(p1, gmul((GEN)x[j],(GEN)x[i-j]));
        !           229:     p1 = gshift(p1,1);
        !           230:     if ((i&1) == 0 && p2[i>>1])
        !           231:       p1 = gadd(p1, gsqr((GEN)x[i>>1]));
        !           232:     z[i] = lpileupto(av,p1);
        !           233:   }
        !           234:   for (  ; i<nz; i++)
        !           235:   {
        !           236:     p1=gzero; av=avma; l=(i+1)>>1;
        !           237:     for (j=i-nx+1; j<l; j++)
        !           238:       if (p2[j] && p2[i-j])
        !           239:         p1 = gadd(p1, gmul((GEN)x[j],(GEN)x[i-j]));
        !           240:     p1 = gshift(p1,1);
        !           241:     if ((i&1) == 0 && p2[i>>1])
        !           242:       p1 = gadd(p1, gsqr((GEN)x[i>>1]));
        !           243:     z[i] = lpileupto(av,p1);
        !           244:   }
        !           245:   free(p2); z -= 2; z[1]=0; return normalizepol_i(z,lz);
        !           246: }
        !           247:
        !           248: GEN
        !           249: quicksqr(GEN a, long na)
        !           250: {
        !           251:   GEN a0,c,c0,c1;
        !           252:   long av,n0,n0a,i;
        !           253:
        !           254:   if (na<SQR_LIMIT) return sqrpol(a,na);
        !           255:   i=(na>>1); n0=na-i; na=i;
        !           256:   av=avma; a0=a+n0; n0a=n0;
        !           257:   while (n0a && isexactzero((GEN)a[n0a-1])) n0a--;
        !           258:
        !           259:   c = quicksqr(a,n0a);
        !           260:   c0 = quicksqr(a0,na);
        !           261:   c1 = gmul2n(quickmul(a0,a, na,n0a), 1);
        !           262:   c0 = addshiftw(c0,c1, n0);
        !           263:   c0 = addshiftwcopy(c0,c,n0);
        !           264:   return gerepileupto(av,c0);
        !           265: }
        !           266:
        !           267: /* x,pol in Z[X], p in Z, n in N, compute lift(x^n mod (p, pol)) */
        !           268: GEN
        !           269: Fp_pow_mod_pol(GEN x, GEN n, GEN pol, GEN p)
        !           270: {
        !           271:   long m,i,j,av=avma, lim=stack_lim(av,1), vx = varn(x);
        !           272:   GEN p1 = n+2, y = x, z;
        !           273:   if (!signe(n)) return polun[vx];
        !           274:   if (is_pm1(n)) return gcopy(x);
        !           275:   m = *p1;
        !           276:   j=1+bfffo(m); m<<=j; j = BITS_IN_LONG-j;
        !           277:   for (i=lgefint(n)-2;;)
        !           278:   {
        !           279:     for (; j; m<<=1,j--)
        !           280:     {
        !           281:       z = quicksqr(y+2, lgef(y)-2);
        !           282:       y = Fp_pol_red(z, p);
        !           283:       y = Fp_res(y,pol, p);
        !           284:       if (low_stack(lim, stack_lim(av,1)))
        !           285:       {
        !           286:         if(DEBUGMEM>1) err(warnmem,"[1]: Fp_pow_mod_pol");
        !           287:         y = gerepileupto(av, y);
        !           288:       }
        !           289:       if (m<0)
        !           290:       {
        !           291:         z = quickmul(y+2, x+2, lgef(y)-2, lgef(x)-2);
        !           292:         y = Fp_pol_red(z, p);
        !           293:         y = Fp_res(y,pol, p);
        !           294:       }
        !           295:       if (low_stack(lim, stack_lim(av,1)))
        !           296:       {
        !           297:         if(DEBUGMEM>1) err(warnmem,"[2]: Fp_pow_mod_pol");
        !           298:         y = gerepileupto(av, y);
        !           299:       }
        !           300:     }
        !           301:     if (--i == 0) break;
        !           302:     m = *++p1, j = BITS_IN_LONG;
        !           303:   }
        !           304:   setvarn(y,vx); return gerepileupto(av,y);
        !           305: }
        !           306:
        !           307: int ff_poltype(GEN *x, GEN *p, GEN *pol);
        !           308:
        !           309: /* z in Z[X], return z * Mod(1,p), normalized*/
        !           310: GEN
        !           311: Fp_pol(GEN z, GEN p)
        !           312: {
        !           313:   long i,l = lgef(z);
        !           314:   GEN a,x = cgetg(l,t_POL);
        !           315:   if (isonstack(p)) p = icopy(p);
        !           316:   for (i=2; i<l; i++)
        !           317:   {
        !           318:     a = cgetg(3,t_INTMOD); x[i] = (long)a;
        !           319:     a[1] = (long)p;
        !           320:     a[2] = lmodii((GEN)z[i],p);
        !           321:   }
        !           322:   x[1] = z[1]; return normalizepol_i(x,l);
        !           323: }
        !           324:
        !           325: /* z in Z^n, return z * Mod(1,p), normalized*/
        !           326: GEN
        !           327: Fp_vec(GEN z, GEN p)
        !           328: {
        !           329:   long i,l = lg(z);
        !           330:   GEN a,x = cgetg(l,typ(z));
        !           331:   if (isonstack(p)) p = icopy(p);
        !           332:   for (i=1; i<l; i++)
        !           333:   {
        !           334:     a = cgetg(3,t_INTMOD); x[i] = (long)a;
        !           335:     a[1] = (long)p;
        !           336:     a[2] = lmodii((GEN)z[i],p);
        !           337:   }
        !           338:   return x;
        !           339: }
        !           340:
        !           341: /* z in Z[X], return lift(z * Mod(1,p)), normalized*/
        !           342: GEN
        !           343: Fp_pol_red(GEN z, GEN p)
        !           344: {
        !           345:   long i,l = lgef(z);
        !           346:   GEN x = cgetg(l,t_POL);
        !           347:   for (i=2; i<l; i++) x[i] = lmodii((GEN)z[i],p);
        !           348:   x[1] = z[1]; return normalizepol_i(x,l);
        !           349: }
        !           350:
        !           351: /* z in Z^n, return lift(z * Mod(1,p)) */
        !           352: GEN
        !           353: Fp_vec_red(GEN z, GEN p)
        !           354: {
        !           355:   long i,l = lg(z);
        !           356:   GEN x = cgetg(l,typ(z));
        !           357:   for (i=1; i<l; i++) x[i] = lmodii((GEN)z[i],p);
        !           358:   return x;
        !           359: }
        !           360:
        !           361: /* no garbage collection, divide by leading coeff, mod p */
        !           362: GEN
        !           363: normalize_mod_p(GEN z, GEN p)
        !           364: {
        !           365:   long l = lgef(z)-1;
        !           366:   GEN p1 = (GEN)z[l]; /* leading term */
        !           367:   if (gcmp1(p1)) return z;
        !           368:   z = gmul(z, mpinvmod(p1,p));
        !           369:   return Fp_pol_red(z, p);
        !           370: }
        !           371:
        !           372: /* as above, p is guaranteed small, and coeffs of z are C longs in [0,p-1],
        !           373:  * coeffs are in z[0..l-1] (instead of z[2] for regular pols)
        !           374:  * Set varn(z) = 0
        !           375:  */
        !           376: GEN
        !           377: Fp_pol_small(GEN z, GEN p, long l)
        !           378: {
        !           379:   long i;
        !           380:   GEN a,x = cgetg(l,t_POL);
        !           381:   if (isonstack(p)) p = icopy(p);
        !           382:   if (is_bigint(p)) err(talker, "not a small prime in Fp_pol_small");
        !           383:   z -= 2;
        !           384:   for (i=2; i<l; i++) {
        !           385:     a = cgetg(3,t_INTMOD); x[i] = (long)a;
        !           386:     a[1] = (long)p;
        !           387:     a[2] = lstoi(z[i]);
        !           388:   }
        !           389:   return normalizepol_i(x,l);
        !           390: }
        !           391:
        !           392: /* assume z[i] % p has been done. But we may have z[i] < 0 */
        !           393: GEN
        !           394: small_to_pol(GEN z, long l, long p)
        !           395: {
        !           396:   GEN x = cgetg(l,t_POL);
        !           397:   long i;
        !           398:   z -= 2; for (i=2; i<l; i++) x[i] = lstoi(z[i]<0? p+z[i]: z[i]);
        !           399:   return normalizepol_i(x,l);
        !           400: }
        !           401:
        !           402: /* z in ?[X,Y] mod Q(Y) in Kronecker form ((subst(lift(z), x, y^(2deg(z)-1)))
        !           403:  * Recover the "real" z, normalized */
        !           404: GEN
        !           405: from_Kronecker(GEN z, GEN pol)
        !           406: {
        !           407:   long i,j,lx,l = lgef(z), N = ((lgef(pol)-3)<<1) + 1;
        !           408:   GEN a,x, t = cgetg(N,t_POL);
        !           409:   t[1] = pol[1] & VARNBITS;
        !           410:   lx = (l-2) / (N-2); x = cgetg(lx+3,t_POL);
        !           411:   if (isonstack(pol)) pol = gcopy(pol);
        !           412:   for (i=2; i<lx+2; i++)
        !           413:   {
        !           414:     a = cgetg(3,t_POLMOD); x[i] = (long)a;
        !           415:     a[1] = (long)pol;
        !           416:     for (j=2; j<N; j++) t[j] = z[j];
        !           417:     z += (N-2);
        !           418:     a[2] = lres(normalizepol_i(t,N), pol);
        !           419:   }
        !           420:   a = cgetg(3,t_POLMOD); x[i] = (long)a;
        !           421:   a[1] = (long)pol;
        !           422:   N = (l-2) % (N-2) + 2;
        !           423:   for (j=2; j<N; j++) t[j] = z[j];
        !           424:   a[2] = lres(normalizepol_i(t,N), pol);
        !           425:   return normalizepol_i(x, i+1);
        !           426: }
        !           427:
        !           428: /*******************************************************************/
        !           429: /*                                                                 */
        !           430: /*                          MODULAR GCD                            */
        !           431: /*                                                                 */
        !           432: /*******************************************************************/
        !           433: static GEN
        !           434: maxnorm(GEN p)
        !           435: {
        !           436:   long i,n=lgef(p)-3,ltop=avma,lbot;
        !           437:   GEN x, m = gzero;
        !           438:
        !           439:   p += 2;
        !           440:   for (i=0; i<n; i++)
        !           441:   {
        !           442:     x = (GEN)p[i];
        !           443:     if (absi_cmp(x,m) > 0) m = absi(x);
        !           444:   }
        !           445:   m = divii(m, absi((GEN)p[n])); lbot = avma;
        !           446:   return gerepile(ltop,lbot,addis(m,1));
        !           447: }
        !           448:
        !           449: /* return x[0 .. dx] mod p as C-long in a malloc'ed array */
        !           450: static GEN
        !           451: Fp_to_pol_long(GEN x, long dx, long p, long *d)
        !           452: {
        !           453:   long i, m;
        !           454:   GEN a;
        !           455:
        !           456:   for (i=dx; i>=0; i--)
        !           457:   {
        !           458:     m = smodis((GEN)x[i],p);
        !           459:     if (m) break;
        !           460:   }
        !           461:   if (i < 0) { *d = -1; return NULL; }
        !           462:   a = (GEN) gpmalloc((i+1)*sizeof(long));
        !           463:   *d = i; a[i] = m;
        !           464:   for (i--; i>=0; i--) a[i] = smodis((GEN)x[i],p);
        !           465:   return a;
        !           466: }
        !           467:
        !           468: /* idem as Fp_poldivres but working only on C-long types
        !           469:  * ASSUME pr != ONLY_DIVIDES (TODO ???)
        !           470:  */
        !           471: static long *
        !           472: Fp_poldivres_long(long *x,long *y,long p,long dx, long dy, long *dc, GEN *pr)
        !           473: {
        !           474:   long dz,i,j,p1,*z,*c,inv;
        !           475:
        !           476:   if (!dy) { *dc=-1; return NULL; }
        !           477:   dz=dx-dy;
        !           478:   if (dz<0)
        !           479:   {
        !           480:     if (pr)
        !           481:     {
        !           482:       c=(long *) gpmalloc((dx+1)*sizeof(long));
        !           483:       for (i=0; i<=dx; i++) c[i]=x[i];
        !           484:       *dc = dx;
        !           485:       if (pr == ONLY_REM) return c;
        !           486:       *pr = c;
        !           487:     }
        !           488:     return NULL;
        !           489:   }
        !           490:   z=(long *) gpmalloc((dz+1)*sizeof(long));
        !           491:   inv = y[dy];
        !           492:   if (inv!=1)
        !           493:   {
        !           494:     long av = avma;
        !           495:     GEN res = mpinvmod(stoi(y[dy]),stoi(p));
        !           496:     inv = itos(res); avma = av;
        !           497:   }
        !           498:
        !           499:   z[dz]=(inv*x[dx])%p;
        !           500:   for (i=dx-1; i>=dy; --i)
        !           501:   {
        !           502:     p1=x[i];
        !           503:     for (j=i-dy+1; j<=i && j<=dz; j++)
        !           504:     {
        !           505:       p1 -= z[j]*y[i-j];
        !           506:       if (p1 & (HIGHBIT>>1)) p1=p1%p;
        !           507:     }
        !           508:     z[i-dy]=((p1%p)*inv)%p;
        !           509:   }
        !           510:   if (!pr) return z;
        !           511:
        !           512:   c=(long *) gpmalloc(dy*sizeof(long));
        !           513:   for (i=0; i<dy; i++)
        !           514:   {
        !           515:     p1=z[0]*y[i];
        !           516:     for (j=1; j<=i && j<=dz; j++)
        !           517:     {
        !           518:       p1 += z[j]*y[i-j];
        !           519:       if (p1 & (HIGHBIT>>1)) p1=p1%p;
        !           520:     }
        !           521:     c[i]=(x[i]-p1)%p;
        !           522:   }
        !           523:
        !           524:   i=dy-1; while (i>=0 && c[i]==0) i--;
        !           525:   *dc=i;
        !           526:   if (pr == ONLY_REM) { free(z); return c; }
        !           527:   *pr = c; return z;
        !           528: }
        !           529:
        !           530: /* x and y in Z[X] */
        !           531: GEN
        !           532: Fp_poldivres(GEN x, GEN y, GEN p, GEN *pr)
        !           533: {
        !           534:   long vx,dx,dy,dz,i,j,av0,av,tetpil,sx,lrem;
        !           535:   GEN z,p1,rem,lead;
        !           536:
        !           537:   if (!signe(y)) err(talker,"division by zero in Fp_poldivres");
        !           538:   vx=varn(x); dy=lgef(y)-3; dx=lgef(x)-3;
        !           539:   if (dx < dy)
        !           540:   {
        !           541:     if (pr)
        !           542:     {
        !           543:       av0 = avma; x = Fp_pol_red(x, p);
        !           544:       if (pr == ONLY_DIVIDES) { avma=av0; return signe(x)? NULL: gzero; }
        !           545:       if (pr == ONLY_REM) return x;
        !           546:       *pr = x;
        !           547:     }
        !           548:     return zeropol(vx);
        !           549:   }
        !           550:   lead = leading_term(y);
        !           551:   if (!dy) /* y is constant */
        !           552:   {
        !           553:     if (pr && pr != ONLY_DIVIDES)
        !           554:     {
        !           555:       if (pr == ONLY_REM) return zeropol(vx);
        !           556:       *pr = zeropol(vx);
        !           557:     }
        !           558:     if (gcmp1(lead)) return gcopy(x);
        !           559:     av0 = avma; x = gmul(x, mpinvmod(lead,p)); tetpil = avma;
        !           560:     return gerepile(av0,tetpil,Fp_pol_red(x,p));
        !           561:   }
        !           562:   av0 = avma; dz = dx-dy;
        !           563:   if (2*expi(p)+6<BITS_IN_LONG)
        !           564:   { /* assume ab != 0 mod p */
        !           565:     long *a, *b, *zz, da,db,dr, pp = p[2];
        !           566:     a = Fp_to_pol_long(x+2, dx, pp, &da);
        !           567:     b = Fp_to_pol_long(y+2, dy, pp, &db);
        !           568:     zz = Fp_poldivres_long(a,b,pp,da,db, &dr, pr);
        !           569:     if (pr == ONLY_REM) dz = dr;
        !           570:     else if (pr && pr != ONLY_DIVIDES)
        !           571:     {
        !           572:       rem = small_to_pol(*pr, dr+3, pp);
        !           573:       free(*pr); setvarn(rem, vx); *pr = rem;
        !           574:     }
        !           575:     z = small_to_pol(zz, dz+3, pp);
        !           576:     free(zz); free(a); free(b); setvarn(z, vx); return z;
        !           577:   }
        !           578:   lead = gcmp1(lead)? NULL: gclone(mpinvmod(lead,p));
        !           579:   avma = av0;
        !           580:   z=cgetg(dz+3,t_POL);
        !           581:   z[1]=evalsigne(1) | evallgef(dz+3) | evalvarn(vx);
        !           582:   x += 2; y += 2; z += 2;
        !           583:
        !           584:   p1 = (GEN)x[dx]; av = avma;
        !           585:   z[dz] = lead? lpileupto(av, modii(mulii(p1,lead), p)): licopy(p1);
        !           586:   for (i=dx-1; i>=dy; i--)
        !           587:   {
        !           588:     av=avma; p1=(GEN)x[i];
        !           589:     for (j=i-dy+1; j<=i && j<=dz; j++)
        !           590:       p1 = subii(p1, mulii((GEN)z[j],(GEN)y[i-j]));
        !           591:     if (lead) p1 = mulii(p1,lead);
        !           592:     tetpil=avma; z[i-dy] = lpile(av,tetpil,modii(p1, p));
        !           593:   }
        !           594:   if (!pr) { if (lead) gunclone(lead); return z-2; }
        !           595:
        !           596:   rem = (GEN)avma; av = (long)new_chunk(dx+3);
        !           597:   for (sx=0; ; i--)
        !           598:   {
        !           599:     p1 = (GEN)x[i];
        !           600:     for (j=0; j<=i && j<=dz; j++)
        !           601:       p1 = subii(p1, mulii((GEN)z[j],(GEN)y[i-j]));
        !           602:     tetpil=avma; p1 = modii(p1,p); if (signe(p1)) { sx = 1; break; }
        !           603:     if (!i) break;
        !           604:     avma=av;
        !           605:   }
        !           606:   if (pr == ONLY_DIVIDES)
        !           607:   {
        !           608:     if (lead) gunclone(lead);
        !           609:     if (sx) { avma=av0; return NULL; }
        !           610:     avma = (long)rem; return z-2;
        !           611:   }
        !           612:   lrem=i+3; rem -= lrem;
        !           613:   rem[0]=evaltyp(t_POL) | evallg(lrem);
        !           614:   rem[1]=evalsigne(1) | evalvarn(vx) | evallgef(lrem);
        !           615:   p1 = gerepile((long)rem,tetpil,p1);
        !           616:   rem += 2; rem[i]=(long)p1;
        !           617:   for (i--; i>=0; i--)
        !           618:   {
        !           619:     av=avma; p1 = (GEN)x[i];
        !           620:     for (j=0; j<=i && j<=dz; j++)
        !           621:       p1 = subii(p1, mulii((GEN)z[j],(GEN)y[i-j]));
        !           622:     tetpil=avma; rem[i]=lpile(av,tetpil, modii(p1,p));
        !           623:   }
        !           624:   rem -= 2;
        !           625:   if (lead) gunclone(lead);
        !           626:   if (!sx) normalizepol_i(rem, lrem);
        !           627:   if (pr == ONLY_REM) return gerepileupto(av0,rem);
        !           628:   *pr = rem; return z-2;
        !           629: }
        !           630:
        !           631: static GEN
        !           632: Fp_pol_gcd_long(GEN x, GEN y, GEN p)
        !           633: {
        !           634:   long *a,*b,*c,da,db,dc, pp = (long)p[2];
        !           635:   GEN z;
        !           636:
        !           637:   a = Fp_to_pol_long(x+2, lgef(x)-3, pp, &da);
        !           638:   if (!a) return Fp_pol_red(y,p);
        !           639:   b = Fp_to_pol_long(y+2, lgef(y)-3, pp, &db);
        !           640:   while (db>=0)
        !           641:   {
        !           642:     c = Fp_poldivres_long(a,b, pp, da,db,&dc, ONLY_REM);
        !           643:     free(a); a=b; da=db; b=c; db=dc;
        !           644:   }
        !           645:   if (b) free(b);
        !           646:   z = small_to_pol(a, da+3, pp);
        !           647:   setvarn(z, varn(x));
        !           648:   free(a); return z;
        !           649: }
        !           650:
        !           651: /* x and y in Z[X], return lift(gcd(x mod p, y mod p)) */
        !           652: GEN
        !           653: Fp_pol_gcd(GEN x, GEN y, GEN p)
        !           654: {
        !           655:   GEN a,b,c;
        !           656:   long av0,av;
        !           657:
        !           658:   if (2*expi(p)+6<BITS_IN_LONG) return Fp_pol_gcd_long(x,y,p);
        !           659:   av0=avma;
        !           660:   a = Fp_pol_red(x, p); av = avma;
        !           661:   b = Fp_pol_red(y, p);
        !           662:   while (signe(b))
        !           663:   {
        !           664:     av = avma; c = Fp_res(a,b,p); a=b; b=c;
        !           665:   }
        !           666:   avma = av; return gerepileupto(av0, a);
        !           667: }
        !           668:
        !           669: /* x and y in Z[X], return lift(gcd(x mod p, y mod p)). Set u and v st
        !           670:  * ux + vy = gcd (mod p)
        !           671:  */
        !           672: GEN
        !           673: Fp_pol_extgcd(GEN x, GEN y, GEN p, GEN *ptu, GEN *ptv)
        !           674: {
        !           675:   GEN a,b,q,r,u,v,d,d1,v1;
        !           676:   long ltop,lbot;
        !           677:
        !           678: #if 0 /* TODO */
        !           679:   if (2*expi(p)+6<BITS_IN_LONG) return Fp_pol_extgcd_long(x,y,p);
        !           680: #endif
        !           681:   ltop=avma;
        !           682:   a = Fp_pol_red(x, p);
        !           683:   b = Fp_pol_red(y, p);
        !           684:   d = a; d1 = b; v = gzero; v1 = gun;
        !           685:   while (signe(d1))
        !           686:   {
        !           687:     q = Fp_poldivres(d,d1,p, &r);
        !           688:     v = gadd(v, gneg_i(gmul(q,v1)));
        !           689:     v = Fp_pol_red(v,p);
        !           690:     u=v; v=v1; v1=u;
        !           691:     u=r; d=d1; d1=u;
        !           692:   }
        !           693:   u = gadd(d, gneg_i(gmul(b,v)));
        !           694:   u = Fp_pol_red(u, p);
        !           695:   lbot = avma;
        !           696:   u = Fp_deuc(u,a,p);
        !           697:   d = gcopy(d);
        !           698:   v = gcopy(v);
        !           699:   {
        !           700:     GEN *gptr[3]; gptr[0] = &d; gptr[1] = &u; gptr[2] = &v;
        !           701:     gerepilemanysp(ltop,lbot,gptr,3);
        !           702:   }
        !           703:   *ptu = u; *ptv = v; return d;
        !           704: }
        !           705:
        !           706: GEN chinois_int_coprime(GEN x2, GEN y2, GEN x1, GEN y1, GEN z1);
        !           707:
        !           708: /* a and b in Q[X] */
        !           709: GEN
        !           710: modulargcd(GEN a, GEN b)
        !           711: {
        !           712:   GEN D,A,B,Cp,p,q,H,g,limit,ma,mb,p1;
        !           713:   long av=avma,avlim=stack_lim(av,1), m,n,nA,nB,av2,lbot,i;
        !           714:   long prime[]={evaltyp(t_INT)|m_evallg(3),evalsigne(1)|evallgefint(3),0};
        !           715:   byteptr d = diffptr;
        !           716:
        !           717:   if (typ(a)!=t_POL || typ(b)!=t_POL) err(notpoler,"modulargcd");
        !           718:   if (!signe(a)) return gcopy(b);
        !           719:   if (!signe(b)) return gcopy(a);
        !           720:   A = content(a);
        !           721:   B = content(b); D = ggcd(A,B);
        !           722:   A = gcmp1(A)? a: gdiv(a,A); nA=lgef(A)-3;
        !           723:   B = gcmp1(B)? b: gdiv(b,B); nB=lgef(B)-3;
        !           724:   g = mppgcd((GEN)A[nA+2], (GEN)B[nB+2]);
        !           725:   av2=avma; n=1+min(nA,nB);
        !           726:   ma=maxnorm(A); mb=maxnorm(B);
        !           727:   if (cmpii(ma,mb) > 0) limit=mb; else limit=ma;
        !           728:   limit = shifti(mulii(limit,g), n+1);
        !           729:
        !           730:   /* initial p could be 1 << (BITS_IN_LONG/2-6), but diffptr is nice */
        !           731:   prime[2] = 1021; d += 172; /* p = prime(172) = precprime(1<<10) */
        !           732:   p = prime; H = NULL;
        !           733:   for(;;)
        !           734:   {
        !           735:     do
        !           736:     {
        !           737:       if (*d) p[2] += *d++;
        !           738:       else p = nextprime(addis(p,1)); /* never used */
        !           739:     }
        !           740:     while (!signe(resii(g,p)));
        !           741:     Cp = Fp_pol_gcd(A,B,p);
        !           742:     m = lgef(Cp)-3;
        !           743:     if (m==0) return gerepileupto(av,gmul(D,polun[varn(A)]));
        !           744:     if (gcmp1(g))
        !           745:       Cp = normalize_mod_p(Cp, p);
        !           746:     else
        !           747:     { /* very rare */
        !           748:       p1 = mulii(g, mpinvmod((GEN)Cp[m+2],p));
        !           749:       Cp = Fp_pol_red(gmul(p1,Cp), p);
        !           750:     }
        !           751:     if (m<n) { q=icopy(p); H=Cp; limit=shifti(limit,m-n); n=m; }
        !           752:     else
        !           753:       if (m==n && H)
        !           754:       {
        !           755:         GEN q2 = mulii(q,p);
        !           756:         for (i=2; i<=n+2; i++)
        !           757:           H[i]=(long) chinois_int_coprime((GEN)H[i],(GEN)Cp[i],q,p,q2);
        !           758:         q = q2;
        !           759:        if (cmpii(limit,q) <= 0)
        !           760:        {
        !           761:          GEN limit2=shifti(limit,-1);
        !           762:          for (i=2; i<=n+2; i++)
        !           763:          {
        !           764:            p1 = (GEN)H[i];
        !           765:            if (cmpii(p1,limit2) > 0) H[i]=lsubii(p1,q);
        !           766:          }
        !           767:           p1 = content(H); if (!gcmp1(p1)) H = gdiv(H,p1);
        !           768:          if (!signe(gres(A,H)) && !signe(gres(B,H)))
        !           769:          {
        !           770:            lbot=avma;
        !           771:            return gerepile(av,lbot,gmul(D,H));
        !           772:          }
        !           773:          H = NULL; /* failed */
        !           774:        }
        !           775:       }
        !           776:     if (low_stack(avlim, stack_lim(av,1)))
        !           777:     {
        !           778:       GEN *gptr[4]; gptr[0]=&H; gptr[1]=&p; gptr[2]=&q; gptr[3]=&limit;
        !           779:       if (DEBUGMEM>1) err(warnmem,"modulargcd");
        !           780:       gerepilemany(av2,gptr,4);
        !           781:     }
        !           782:   }
        !           783: }
        !           784:
        !           785: /* returns a polynomial in variable v, whose coeffs correspond to the digits
        !           786:  * of m (in base p)
        !           787:  */
        !           788: GEN
        !           789: stopoly(long m, long p, long v)
        !           790: {
        !           791:   GEN y = cgetg(BITS_IN_LONG + 2, t_POL);
        !           792:   long l=2;
        !           793:
        !           794:   do { y[l++] = lstoi(m%p); m=m/p; } while (m);
        !           795:   y[1] = evalsigne(1)|evallgef(l)|evalvarn(v);
        !           796:   return y;
        !           797: }
        !           798:
        !           799: GEN
        !           800: stopoly_gen(GEN m, GEN p, long v)
        !           801: {
        !           802:   GEN y = cgetg(bit_accuracy(lgefint(m))+2, t_POL);
        !           803:   long l=2;
        !           804:
        !           805:   do { y[l++] = lmodii(m,p); m=divii(m,p); } while (signe(m));
        !           806:   y[1] = evalsigne(1)|evallgef(l)|evalvarn(v);
        !           807:   return y;
        !           808: }
        !           809:

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