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

Annotation of OpenXM_contrib/pari-2.2/src/basemath/arith1.c, Revision 1.1

1.1     ! noro        1: /* $Id: arith1.c,v 1.54 2001/10/01 12:11:28 karim Exp $
        !             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: /**                     ARITHMETIC FUNCTIONS                        **/
        !            19: /**                         (first part)                            **/
        !            20: /**                                                                 **/
        !            21: /*********************************************************************/
        !            22: #include "pari.h"
        !            23:
        !            24: /*********************************************************************/
        !            25: /**                                                                 **/
        !            26: /**                  ARITHMETIC FUNCTION PROTOTYPES                 **/
        !            27: /**                                                                 **/
        !            28: /*********************************************************************/
        !            29: GEN
        !            30: garith_proto(GEN f(GEN), GEN x, int do_error)
        !            31: {
        !            32:   long tx=typ(x),lx,i;
        !            33:   GEN y;
        !            34:
        !            35:   if (is_matvec_t(tx))
        !            36:   {
        !            37:     lx=lg(x); y=cgetg(lx,tx);
        !            38:     for (i=1; i<lx; i++) y[i] = (long) garith_proto(f,(GEN) x[i], do_error);
        !            39:     return y;
        !            40:   }
        !            41:   if (tx != t_INT && do_error) err(arither1);
        !            42:   return f(x);
        !            43: }
        !            44:
        !            45: GEN
        !            46: arith_proto(long f(GEN), GEN x, int do_error)
        !            47: {
        !            48:   long tx=typ(x),lx,i;
        !            49:   GEN y;
        !            50:
        !            51:   if (is_matvec_t(tx))
        !            52:   {
        !            53:     lx=lg(x); y=cgetg(lx,tx);
        !            54:     for (i=1; i<lx; i++) y[i] = (long) arith_proto(f,(GEN) x[i], do_error);
        !            55:     return y;
        !            56:   }
        !            57:   if (tx != t_INT && do_error) err(arither1);
        !            58:   return stoi(f(x));
        !            59: }
        !            60:
        !            61: GEN
        !            62: arith_proto2(long f(GEN,GEN), GEN x, GEN n)
        !            63: {
        !            64:   long l,i,tx = typ(x);
        !            65:   GEN y;
        !            66:
        !            67:   if (is_matvec_t(tx))
        !            68:   {
        !            69:     l=lg(x); y=cgetg(l,tx);
        !            70:     for (i=1; i<l; i++) y[i] = (long) arith_proto2(f,(GEN) x[i],n);
        !            71:     return y;
        !            72:   }
        !            73:   if (tx != t_INT) err(arither1);
        !            74:   tx=typ(n);
        !            75:   if (is_matvec_t(tx))
        !            76:   {
        !            77:     l=lg(n); y=cgetg(l,tx);
        !            78:     for (i=1; i<l; i++) y[i] = (long) arith_proto2(f,x,(GEN) n[i]);
        !            79:     return y;
        !            80:   }
        !            81:   if (tx != t_INT) err(arither1);
        !            82:   return stoi(f(x,n));
        !            83: }
        !            84:
        !            85: static GEN
        !            86: arith_proto2gs(long f(GEN,long), GEN x, long y)
        !            87: {
        !            88:   long l,i,tx = typ(x);
        !            89:   GEN t;
        !            90:
        !            91:   if (is_matvec_t(tx))
        !            92:   {
        !            93:     l=lg(x); t=cgetg(l,tx);
        !            94:     for (i=1; i<l; i++) t[i]= (long) arith_proto2gs(f,(GEN) x[i],y);
        !            95:     return t;
        !            96:   }
        !            97:   if (tx != t_INT) err(arither1);
        !            98:   return stoi(f(x,y));
        !            99: }
        !           100:
        !           101: GEN
        !           102: garith_proto2gs(GEN f(GEN,long), GEN x, long y)
        !           103: {
        !           104:   long l,i,tx = typ(x);
        !           105:   GEN t;
        !           106:
        !           107:   if (is_matvec_t(tx))
        !           108:   {
        !           109:     l=lg(x); t=cgetg(l,tx);
        !           110:     for (i=1; i<l; i++) t[i]= (long) garith_proto2gs(f,(GEN) x[i],y);
        !           111:     return t;
        !           112:   }
        !           113:   if (tx != t_INT) err(arither1);
        !           114:   return f(x,y);
        !           115: }
        !           116:
        !           117: GEN
        !           118: gassoc_proto(GEN f(GEN,GEN), GEN x, GEN y)
        !           119: {
        !           120:   int tx=typ(x);
        !           121:   if (!y)
        !           122:   {
        !           123:     ulong av=avma;
        !           124:     if (tx!=t_VEC && tx!=t_COL)
        !           125:       err(typeer,"association");
        !           126:     return gerepileupto(av,divide_conquer_prod(x,f));
        !           127:   }
        !           128:   return f(x,y);
        !           129: }
        !           130:
        !           131: /*********************************************************************/
        !           132: /**                                                                 **/
        !           133: /**               ORDER of INTEGERMOD x  in  (Z/nZ)*                **/
        !           134: /**                                                                 **/
        !           135: /*********************************************************************/
        !           136:
        !           137: GEN
        !           138: order(GEN x)
        !           139: {
        !           140:   long av=avma,av1,i,e;
        !           141:   GEN o,m,p;
        !           142:
        !           143:   if (typ(x) != t_INTMOD || !gcmp1(mppgcd((GEN) x[1],(GEN) x[2])))
        !           144:     err(talker,"not an element of (Z/nZ)* in order");
        !           145:   o=phi((GEN) x[1]); m=decomp(o);
        !           146:   for (i = lg(m[1])-1; i; i--)
        !           147:   {
        !           148:     p=gcoeff(m,i,1); e=itos(gcoeff(m,i,2));
        !           149:     do
        !           150:     {
        !           151:       GEN o1=divii(o,p), y=powgi(x,o1);
        !           152:       if (!gcmp1((GEN)y[2])) break;
        !           153:       e--; o = o1;
        !           154:     }
        !           155:     while (e);
        !           156:   }
        !           157:   av1=avma; return gerepile(av,av1,icopy(o));
        !           158: }
        !           159:
        !           160: /******************************************************************/
        !           161: /*                                                                */
        !           162: /*                 GENERATOR of (Z/mZ)*                           */
        !           163: /*                                                                */
        !           164: /******************************************************************/
        !           165:
        !           166: GEN
        !           167: ggener(GEN m)
        !           168: {
        !           169:   return garith_proto(gener,m,1);
        !           170: }
        !           171:
        !           172: GEN
        !           173: gener(GEN m)
        !           174: {
        !           175:   long av=avma,av1,k,i,e;
        !           176:   GEN x,t,q,p;
        !           177:
        !           178:   if (typ(m) != t_INT) err(arither1);
        !           179:   e = signe(m);
        !           180:   if (!e) err(talker,"zero modulus in znprimroot");
        !           181:   if (is_pm1(m)) { avma=av; return gmodulss(0,1); }
        !           182:   if (e<0) m = absi(m);
        !           183:
        !           184:   e = mod4(m);
        !           185:   if (e == 0) /* m = 0 mod 4 */
        !           186:   {
        !           187:     if (cmpis(m,4)) err(generer); /* m != 4, non cyclic */
        !           188:     return gmodulsg(3,m);
        !           189:   }
        !           190:   if (e == 2) /* m = 0 mod 2 */
        !           191:   {
        !           192:     q=shifti(m,-1); x = (GEN) gener(q)[2];
        !           193:     if (!mod2(x)) x = addii(x,q);
        !           194:     av1=avma; return gerepile(av,av1,gmodulcp(x,m));
        !           195:   }
        !           196:
        !           197:   t=decomp(m); if (lg(t[1]) != 2) err(generer);
        !           198:   p=gcoeff(t,1,1); e=itos(gcoeff(t,1,2)); q=subis(p,1);
        !           199:   if (e>=2)
        !           200:   {
        !           201:     x = (GEN) gener(p)[2];
        !           202:     if (gcmp1(powmodulo(x,q, sqri(p)))) x = addii(x,p);
        !           203:     av1=avma; return gerepile(av,av1,gmodulcp(x,m));
        !           204:   }
        !           205:
        !           206:   p=(GEN)decomp(q)[1]; k=lg(p)-1; x=stoi(1);
        !           207:   for(;;)
        !           208:   {
        !           209:     x[2]++;
        !           210:     if (gcmp1(mppgcd(m,x)))
        !           211:     {
        !           212:       for (i=k; i; i--)
        !           213:        if (gcmp1(powmodulo(x, divii(q,(GEN)p[i]), m))) break;
        !           214:       if (!i) break;
        !           215:     }
        !           216:   }
        !           217:   av1=avma; return gerepile(av,av1,gmodulcp(x,m));
        !           218: }
        !           219:
        !           220: GEN
        !           221: znstar(GEN n)
        !           222: {
        !           223:   GEN p1,z,q,u,v,d,list,ep,h,gen,moduli,p,a;
        !           224:   long i,j,nbp,sizeh;
        !           225:   ulong av;
        !           226:
        !           227:   if (typ(n) != t_INT) err(arither1);
        !           228:   if (!signe(n))
        !           229:   {
        !           230:     z=cgetg(4,t_VEC);
        !           231:     z[1]=deux; p1=cgetg(2,t_VEC);
        !           232:     z[2]=(long)p1; p1[1]=deux; p1=cgetg(2,t_VEC);
        !           233:     z[3]=(long)p1; p1[1]=lneg(gun);
        !           234:     return z;
        !           235:   }
        !           236:   av=avma; n=absi(n);
        !           237:   if (cmpis(n,2)<=0)
        !           238:   {
        !           239:     avma=av; z=cgetg(4,t_VEC);
        !           240:     z[1]=un;
        !           241:     z[2]=lgetg(1,t_VEC);
        !           242:     z[3]=lgetg(1,t_VEC);
        !           243:     return z;
        !           244:   }
        !           245:   list=factor(n); ep=(GEN)list[2]; list=(GEN)list[1]; nbp=lg(list)-1;
        !           246:   h      = cgetg(nbp+2,t_VEC);
        !           247:   gen    = cgetg(nbp+2,t_VEC);
        !           248:   moduli = cgetg(nbp+2,t_VEC);
        !           249:   switch(mod8(n))
        !           250:   {
        !           251:     case 0:
        !           252:       h[1] = lmul2n(gun,itos((GEN)ep[1])-2); h[2] = deux;
        !           253:       gen[1] = lstoi(5); gen[2] = laddis(gmul2n((GEN)h[1],1),-1);
        !           254:       moduli[1] = moduli[2] = lmul2n(gun,itos((GEN)ep[1]));
        !           255:       sizeh = nbp+1; i=3; j=2; break;
        !           256:     case 4:
        !           257:       h[1] = deux;
        !           258:       gen[1] = lstoi(3);
        !           259:       moduli[1] = lmul2n(gun,itos((GEN)ep[1]));
        !           260:       sizeh = nbp; i=j=2; break;
        !           261:     case 2: case 6:
        !           262:       sizeh = nbp-1; i=1; j=2; break;
        !           263:     default: /* 1, 3, 5, 7 */
        !           264:       sizeh = nbp; i=j=1;
        !           265:   }
        !           266:   for ( ; j<=nbp; i++,j++)
        !           267:   {
        !           268:     p = (GEN)list[j]; q = gpuigs(p, itos((GEN)ep[j])-1);
        !           269:     h[i] = lmulii(addis(p,-1),q); p1 = mulii(p,q);
        !           270:     gen[i] = gener(p1)[2];
        !           271:     moduli[i] = (long)p1;
        !           272:   }
        !           273: #if 0
        !           274:   if (nbp == 1 && is_pm1(ep[1]))
        !           275:     gen[1] = lmodulcp((GEN)gen[1],n);
        !           276:   else
        !           277: #endif
        !           278:     for (i=1; i<=sizeh; i++)
        !           279:     {
        !           280:       q = (GEN)moduli[i]; a = (GEN)gen[i];
        !           281:       u = mpinvmod(q,divii(n,q));
        !           282:       gen[i] = lmodulcp(addii(a,mulii(mulii(subsi(1,a),u),q)), n);
        !           283:     }
        !           284:
        !           285:   for (i=sizeh; i>=2; i--)
        !           286:     for (j=i-1; j>=1; j--)
        !           287:       if (!divise((GEN)h[j],(GEN)h[i]))
        !           288:       {
        !           289:        d=bezout((GEN)h[i],(GEN)h[j],&u,&v);
        !           290:         q=divii((GEN)h[j],d);
        !           291:        h[j]=(long)mulii((GEN)h[i],q); h[i]=(long)d;
        !           292:        gen[j]=ldiv((GEN)gen[j], (GEN)gen[i]);
        !           293:        gen[i]=lmul((GEN)gen[i], powgi((GEN)gen[j], mulii(v,q)));
        !           294:       }
        !           295:   q=gun; for (i=1; i<=sizeh && !gcmp1((GEN)h[i]); i++) q=mulii(q,(GEN)h[i]);
        !           296:   setlg(h,i); setlg(gen,i); z=cgetg(4,t_VEC);
        !           297:   z[1]=(long)q; z[2]=(long)h; z[3]=(long)gen;
        !           298:   return gerepilecopy(av,z);
        !           299: }
        !           300:
        !           301: /*********************************************************************/
        !           302: /**                                                                 **/
        !           303: /**                     INTEGRAL SQUARE ROOT                        **/
        !           304: /**                                                                 **/
        !           305: /*********************************************************************/
        !           306: extern ulong mpsqrtl(GEN a);
        !           307:
        !           308: GEN
        !           309: gracine(GEN a)
        !           310: {
        !           311:   return garith_proto(racine,a,1); /* hm. --GN */
        !           312: }
        !           313:
        !           314: /* Use l as lgefint(a) [a may have more digits] */
        !           315: static GEN
        !           316: racine_r(GEN a, long l)
        !           317: {
        !           318:   long av,s;
        !           319:   GEN x,y,z;
        !           320:
        !           321:   if (l <= 4) return utoi(mpsqrtl(a));
        !           322:   av = avma;
        !           323:   s = 2 + ((l-1) >> 1);
        !           324:   setlgefint(a, s);
        !           325:   x = addis(racine_r(a, s), 1); setlgefint(a, l);
        !           326:   /* x = good approx (from above) of sqrt(a): about l/2 correct bits */
        !           327:   x = shifti(x, (l - s)*(BITS_IN_LONG/2));
        !           328:   do
        !           329:   { /* one or two iterations should do the trick */
        !           330:     z = shifti(addii(x,divii(a,x)), -1);
        !           331:     y = x; x = z;
        !           332:   }
        !           333:   while (cmpii(x,y) < 0);
        !           334:   avma = (long)y;
        !           335:   return gerepileuptoint(av,y);
        !           336: }
        !           337:
        !           338: GEN
        !           339: racine_i(GEN a, int roundup)
        !           340: {
        !           341:   long k,m,l = lgefint(a), av = avma;
        !           342:   GEN x = racine_r(a, l);
        !           343:   if (roundup && signe(x))
        !           344:   {
        !           345:     m = modBIL(x);
        !           346:     k = (m * m != a[l-1] || !egalii(sqri(x),a));
        !           347:     avma = (long)x;
        !           348:     if (k) x = gerepileuptoint(av, addis(x,1));
        !           349:   }
        !           350:   return x;
        !           351: }
        !           352:
        !           353: GEN
        !           354: racine(GEN a)
        !           355: {
        !           356:   if (typ(a) != t_INT) err(arither1);
        !           357:   switch (signe(a))
        !           358:   {
        !           359:     case 1: return racine_i(a,0);
        !           360:     case 0: return gzero;
        !           361:     case -1:
        !           362:     {
        !           363:       GEN x = cgetg(3,t_COMPLEX);
        !           364:       x[1] = zero;
        !           365:       x[2] = (long)racine_i(a,0); return x;
        !           366:     }
        !           367:   }
        !           368:   return NULL; /* not reached */
        !           369: }
        !           370:
        !           371: /*********************************************************************/
        !           372: /**                                                                 **/
        !           373: /**                      PERFECT SQUARE                             **/
        !           374: /**                                                                 **/
        !           375: /*********************************************************************/
        !           376: extern ulong usqrtsafe(ulong a);
        !           377:
        !           378: static int
        !           379: carremod(ulong A)
        !           380: {
        !           381:   static int carresmod64[]={
        !           382:     1,1,0,0,1,0,0,0,0,1, 0,0,0,0,0,0,1,1,0,0, 0,0,0,0,0,1,0,0,0,0,
        !           383:     0,0,0,1,0,0,1,0,0,0, 0,1,0,0,0,0,0,0,0,1, 0,0,0,0,0,0,0,1,0,0, 0,0,0,0};
        !           384:   static int carresmod63[]={
        !           385:     1,1,0,0,1,0,0,1,0,1, 0,0,0,0,0,0,1,0,1,0, 0,0,1,0,0,1,0,0,1,0,
        !           386:     0,0,0,0,0,0,1,1,0,0, 0,0,0,1,0,0,1,0,0,1, 0,0,0,0,0,0,0,0,1,0, 0,0,0};
        !           387:   static int carresmod65[]={
        !           388:     1,1,0,0,1,0,0,0,0,1, 1,0,0,0,1,0,1,0,0,0, 0,0,0,0,0,1,1,0,0,1,
        !           389:     1,0,0,0,0,1,1,0,0,1, 1,0,0,0,0,0,0,0,0,1, 0,1,0,0,0,1,1,0,0,0, 0,1,0,0,1};
        !           390:   static int carresmod11[]={1,1,0,1,1,1,0,0,0,1, 0};
        !           391:   return (carresmod64[A & 0x3fUL]
        !           392:     && carresmod63[A % 63UL]
        !           393:     && carresmod65[A % 65UL]
        !           394:     && carresmod11[A % 11UL]);
        !           395: }
        !           396:
        !           397: /* emulate carrecomplet on single-word positive integers */
        !           398: ulong
        !           399: ucarrecomplet(ulong A)
        !           400: {
        !           401:   if (carremod(A))
        !           402:   {
        !           403:     ulong a = usqrtsafe(A);
        !           404:     if (a * a == A) return a;
        !           405:   }
        !           406:   return 0;
        !           407: }
        !           408:
        !           409: long
        !           410: carrecomplet(GEN x, GEN *pt)
        !           411: {
        !           412:   long av;
        !           413:   GEN y;
        !           414:
        !           415:   switch(signe(x))
        !           416:   {
        !           417:     case -1: return 0;
        !           418:     case 0: if (pt) *pt=gzero; return 1;
        !           419:   }
        !           420:   if (lgefint(x) == 3)
        !           421:   {
        !           422:     long a = ucarrecomplet((ulong)x[2]);
        !           423:     if (!a) return 0;
        !           424:     if (pt) *pt = stoi(a);
        !           425:     return 1;
        !           426:   }
        !           427:   if (!carremod((ulong)smodis(x, 64*63*65*11))) return 0;
        !           428:   av=avma; y = racine(x);
        !           429:   if (!egalii(sqri(y),x)) { avma=av; return 0; }
        !           430:   if (pt) { *pt = y; avma=(long)y; } else avma=av;
        !           431:   return 1;
        !           432: }
        !           433:
        !           434: static GEN
        !           435: polcarrecomplet(GEN x, GEN *pt)
        !           436: {
        !           437:   long i,l,av,av2;
        !           438:   GEN y,a,b;
        !           439:
        !           440:   if (!signe(x)) return gun;
        !           441:   l=lgef(x); if ((l&1) == 0) return gzero; /* odd degree */
        !           442:   i=2; while (isexactzero((GEN)x[i])) i++;
        !           443:   if (i&1) return gzero;
        !           444:   av2 = avma; a = (GEN)x[i];
        !           445:   switch (typ(a))
        !           446:   {
        !           447:     case t_POL: case t_INT:
        !           448:       y = gcarrecomplet(a,&b); break;
        !           449:     default:
        !           450:       y = gcarreparfait(a); b = NULL; break;
        !           451:   }
        !           452:   if (y == gzero) { avma = av2; return gzero; }
        !           453:   av = avma; x = gdiv(x,a);
        !           454:   y = gtrunc(gsqrt(greffe(x,l,1),0)); av2 = avma;
        !           455:   if (!gegal(gsqr(y), x)) { avma=av; return gzero; }
        !           456:   if (pt)
        !           457:   {
        !           458:     avma = av2;
        !           459:     if (!gcmp1(a))
        !           460:     {
        !           461:       if (!b) b = gsqrt(a,DEFAULTPREC);
        !           462:       y = gmul(b,y);
        !           463:     }
        !           464:     *pt = gerepileupto(av,y);
        !           465:   }
        !           466:   else avma = av;
        !           467:   return gun;
        !           468: }
        !           469:
        !           470: GEN
        !           471: gcarrecomplet(GEN x, GEN *pt)
        !           472: {
        !           473:   long tx = typ(x),l,i;
        !           474:   GEN z,y,p,t;
        !           475:
        !           476:   if (!pt) return gcarreparfait(x);
        !           477:   if (is_matvec_t(tx))
        !           478:   {
        !           479:     l=lg(x); y=cgetg(l,tx); z=cgetg(l,tx);
        !           480:     for (i=1; i<l; i++)
        !           481:     {
        !           482:       t=gcarrecomplet((GEN)x[i],&p);
        !           483:       y[i] = (long)t;
        !           484:       z[i] = gcmp0(t)? zero: (long)p;
        !           485:     }
        !           486:     *pt=z; return y;
        !           487:   }
        !           488:   if (tx == t_POL) return polcarrecomplet(x,pt);
        !           489:   if (tx != t_INT) err(arither1);
        !           490:   return stoi(carrecomplet(x,pt));
        !           491: }
        !           492:
        !           493: GEN
        !           494: gcarreparfait(GEN x)
        !           495: {
        !           496:   GEN p1,a,p;
        !           497:   long tx=typ(x),l,i,av,v;
        !           498:
        !           499:   switch(tx)
        !           500:   {
        !           501:     case t_INT:
        !           502:       return carreparfait(x)? gun: gzero;
        !           503:
        !           504:     case t_REAL:
        !           505:       return (signe(x)>=0)? gun: gzero;
        !           506:
        !           507:     case t_INTMOD:
        !           508:     {
        !           509:       GEN b, q, e;
        !           510:       long w;
        !           511:       a = (GEN)x[2]; if (!signe(a)) return gun;
        !           512:       av = avma;
        !           513:       q = absi((GEN)x[1]); v = vali(q);
        !           514:       if (v) /* > 0 */
        !           515:       {
        !           516:         long dv;
        !           517:         w = vali(a); dv = v - w;
        !           518:         if (dv > 0)
        !           519:         {
        !           520:           if (w & 1) { avma = av; return gzero; }
        !           521:           if (dv >= 2)
        !           522:           {
        !           523:             b = w? shifti(a,-w): a;
        !           524:             if ((dv>=3 && mod8(b) != 1) ||
        !           525:                 (dv==2 && mod4(b) != 1)) { avma = av; return gzero; }
        !           526:           }
        !           527:         }
        !           528:         q = shifti(q, -v);
        !           529:       }
        !           530:       /* q is now odd */
        !           531:       i = kronecker(a,q);
        !           532:       if (i < 0) { avma = av; return gzero; }
        !           533:       if (i==0)
        !           534:       {
        !           535:         GEN d = mppgcd(a,q);
        !           536:         p1 = factor(d);
        !           537:         p = (GEN)p1[1];
        !           538:         e = (GEN)p1[2]; l = lg(e);
        !           539:         for (i=1; i<l; i++)
        !           540:         {
        !           541:           v = pvaluation(a,(GEN)p[i],&p1);
        !           542:           w = itos((GEN)e[i]);
        !           543:           if (v < w && (v&1 || kronecker(p1,(GEN)p[i]) == -1))
        !           544:             { avma = av; return gzero; }
        !           545:           q = diviiexact(q, gpowgs((GEN)p[i], w));
        !           546:         }
        !           547:         if (kronecker(a,q) == -1) { avma = av; return gzero; }
        !           548:       }
        !           549:       /* kro(a,q) = 1, q odd: need to factor q */
        !           550:       p1 = factor(q);
        !           551:       p = (GEN)p1[1];
        !           552:       e = (GEN)p1[2]; l = lg(e) - 1;
        !           553:       /* kro(a,q) = 1, check all p|q but the last (product formula) */
        !           554:       for (i=1; i<l; i++)
        !           555:         if (kronecker(a,(GEN)p[i]) == -1) { avma = av; return gzero; }
        !           556:       return gun;
        !           557:     }
        !           558:
        !           559:     case t_FRAC: case t_FRACN:
        !           560:       av=avma; l=carreparfait(mulii((GEN)x[1],(GEN)x[2]));
        !           561:       avma=av; return l? gun: gzero;
        !           562:
        !           563:     case t_COMPLEX:
        !           564:       return gun;
        !           565:
        !           566:     case t_PADIC:
        !           567:       a = (GEN)x[4]; if (!signe(a)) return gun;
        !           568:       if (valp(x)&1) return gzero;
        !           569:       p = (GEN)x[2];
        !           570:       if (!egalii(p, gdeux))
        !           571:         return (kronecker(a,p)== -1)? gzero: gun;
        !           572:
        !           573:       v = precp(x); /* here p=2, a is odd */
        !           574:       if ((v>=3 && mod8(a) != 1 ) ||
        !           575:           (v==2 && mod4(a) != 1)) return gzero;
        !           576:       return gun;
        !           577:
        !           578:     case t_POL:
        !           579:       return polcarrecomplet(x,NULL);
        !           580:
        !           581:     case t_SER:
        !           582:       if (!signe(x)) return gun;
        !           583:       if (valp(x)&1) return gzero;
        !           584:       return gcarreparfait((GEN)x[2]);
        !           585:
        !           586:     case t_RFRAC: case t_RFRACN:
        !           587:       av=avma;
        !           588:       l=itos(gcarreparfait(gmul((GEN)x[1],(GEN)x[2])));
        !           589:       avma=av; return stoi(l);
        !           590:
        !           591:     case t_QFR: case t_QFI:
        !           592:       return gcarreparfait((GEN)x[1]);
        !           593:
        !           594:     case t_VEC: case t_COL: case t_MAT:
        !           595:       l=lg(x); p1=cgetg(l,tx);
        !           596:       for (i=1; i<l; i++) p1[i]=(long)gcarreparfait((GEN)x[i]);
        !           597:       return p1;
        !           598:   }
        !           599:   err(typeer,"issquare");
        !           600:   return NULL; /* not reached */
        !           601: }
        !           602:
        !           603: /*********************************************************************/
        !           604: /**                                                                 **/
        !           605: /**                        KRONECKER SYMBOL                         **/
        !           606: /**                                                                 **/
        !           607: /*********************************************************************/
        !           608: /* u = 3,5 mod 8 ?  (= 2 not a square mod u) */
        !           609: #define  ome(t) (labs(((t)&7)-4) == 1)
        !           610: #define gome(t) (ome(modBIL(t)))
        !           611:
        !           612: GEN
        !           613: gkronecker(GEN x, GEN y)
        !           614: {
        !           615:   return arith_proto2(kronecker,x,y);
        !           616: }
        !           617:
        !           618: long
        !           619: kronecker(GEN x, GEN y)
        !           620: {
        !           621:   GEN z;
        !           622:   long av,r,s=1;
        !           623:
        !           624:   av=avma;
        !           625:   switch (signe(y))
        !           626:   {
        !           627:     case -1: y=negi(y); if (signe(x)<0) s= -1; break;
        !           628:     case 0: return is_pm1(x);
        !           629:   }
        !           630:   r=vali(y);
        !           631:   if (r)
        !           632:   {
        !           633:     if (mpodd(x))
        !           634:     {
        !           635:       if (odd(r) && gome(x)) s= -s;
        !           636:       y=shifti(y,-r);
        !           637:     }
        !           638:     else { avma=av; return 0; }
        !           639:   }
        !           640:   x=modii(x,y);
        !           641:   while (signe(x))
        !           642:   {
        !           643:     r=vali(x);
        !           644:     if (r)
        !           645:     {
        !           646:       if (odd(r) && gome(y)) s= -s;
        !           647:       x=shifti(x,-r);
        !           648:     }
        !           649:     /* x=3 mod 4 && y=3 mod 4 ? (both are odd here) */
        !           650:     if (modBIL(x) & modBIL(y) & 2) s = -s;
        !           651:     z=resii(y,x); y=x; x=z;
        !           652:   }
        !           653:   avma=av; return is_pm1(y)? s: 0;
        !           654: }
        !           655:
        !           656: GEN
        !           657: gkrogs(GEN x, long y)
        !           658: {
        !           659:   return arith_proto2gs(krogs,x,y);
        !           660: }
        !           661:
        !           662: long
        !           663: krogs(GEN x, long y)
        !           664: {
        !           665:   long av,r,s=1,x1,z;
        !           666:
        !           667:   av=avma;
        !           668:   if (y<=0)
        !           669:   {
        !           670:     if (y) { y = -y; if (signe(x)<0) s = -1; }
        !           671:     else  return is_pm1(x);
        !           672:   }
        !           673:   r=vals(y);
        !           674:   if (r)
        !           675:   {
        !           676:     if (mpodd(x))
        !           677:     {
        !           678:       if (odd(r) && gome(x)) s= -s;
        !           679:       y>>=r;
        !           680:     }
        !           681:     else return 0;
        !           682:   }
        !           683:   x1=smodis(x,y); avma = av;
        !           684:   while (x1)
        !           685:   {
        !           686:     r=vals(x1);
        !           687:     if (r)
        !           688:     {
        !           689:       if (odd(r) && ome(y)) s= -s;
        !           690:       x1>>=r;
        !           691:     }
        !           692:     if (x1 & y & 2) s= -s;
        !           693:     z=y%x1; y=x1; x1=z;
        !           694:   }
        !           695:   return (y==1)? s: 0;
        !           696: }
        !           697:
        !           698: long
        !           699: krosg(long s, GEN x)
        !           700: {
        !           701:   long av = avma, y = kronecker(stoi(s),x);
        !           702:   avma = av; return y;
        !           703: }
        !           704:
        !           705: long
        !           706: kross(long x, long y)
        !           707: {
        !           708:   long r,s=1,x1,z;
        !           709:
        !           710:   if (y<=0)
        !           711:   {
        !           712:     if (y) { y= -y; if (x<0) s = -1; }
        !           713:     else  return (labs(x)==1);
        !           714:   }
        !           715:   r=vals(y);
        !           716:   if (r)
        !           717:   {
        !           718:     if (odd(x))
        !           719:     {
        !           720:       if (odd(r) && ome(x)) s = -s;
        !           721:       y>>=r;
        !           722:     }
        !           723:     else return 0;
        !           724:   }
        !           725:   x1=x%y; if (x1<0) x1+=y;
        !           726:   while (x1)
        !           727:   {
        !           728:     r=vals(x1);
        !           729:     if (r)
        !           730:     {
        !           731:       if (odd(r) && ome(y)) s = -s;
        !           732:       x1>>=r;
        !           733:     }
        !           734:     if (x1 & y & 2) s = -s;
        !           735:     z=y%x1; y=x1; x1=z;
        !           736:   }
        !           737:   return (y==1)? s: 0;
        !           738: }
        !           739:
        !           740: long
        !           741: hil0(GEN x, GEN y, GEN p)
        !           742: {
        !           743:   return hil(x,y, p? p: gzero);
        !           744: }
        !           745:
        !           746: #define eps(t) (((signe(t)*(modBIL(t)))&3)==3)
        !           747: long
        !           748: hil(GEN x, GEN y, GEN p)
        !           749: {
        !           750:   long a,b,av,tx,ty,z;
        !           751:   GEN p1,p2,u,v;
        !           752:
        !           753:   if (gcmp0(x) || gcmp0(y)) return 0;
        !           754:   av=avma; tx=typ(x); ty=typ(y);
        !           755:   if (tx>ty) { p1=x; x=y; y=p1; a=tx,tx=ty; ty=a; }
        !           756:   switch(tx)
        !           757:   {
        !           758:     case t_INT:
        !           759:       switch(ty)
        !           760:       {
        !           761:        case t_INT:
        !           762:          if (signe(p)<=0)
        !           763:            return (signe(x)<0 && signe(y)<0)? -1: 1;
        !           764:          a = odd(pvaluation(x,p,&u));
        !           765:           b = odd(pvaluation(y,p,&v));
        !           766:          if (egalii(p,gdeux))
        !           767:           {
        !           768:            z = (eps(u) && eps(v))? -1: 1;
        !           769:            if (a && gome(v)) z= -z;
        !           770:            if (b && gome(u)) z= -z;
        !           771:           }
        !           772:           else
        !           773:          {
        !           774:            z = (a && b && eps(p))? -1: 1;
        !           775:            if (a && kronecker(v,p)<0) z= -z;
        !           776:            if (b && kronecker(u,p)<0) z= -z;
        !           777:          }
        !           778:          avma=av; return z;
        !           779:        case t_REAL:
        !           780:          return (signe(x)<0 && signe(y)<0)? -1: 1;
        !           781:        case t_INTMOD:
        !           782:          if (egalii(gdeux,(GEN)y[1])) err(hiler1);
        !           783:          return hil(x,(GEN)y[2],(GEN)y[1]);
        !           784:        case t_FRAC: case t_FRACN:
        !           785:          p1=mulii((GEN)y[1],(GEN)y[2]); z=hil(x,p1,p);
        !           786:          avma=av; return z;
        !           787:        case t_PADIC:
        !           788:          if (egalii(gdeux,(GEN)y[2]) && precp(y) <= 2) err(hiler1);
        !           789:          p1 = odd(valp(y))? mulii((GEN)y[2],(GEN)y[4]): (GEN)y[4];
        !           790:          z=hil(x,p1,(GEN)y[2]); avma=av; return z;
        !           791:       }
        !           792:       break;
        !           793:
        !           794:     case t_REAL:
        !           795:       if (! is_frac_t(ty)) break;
        !           796:       if (signe(x) > 0) return 1;
        !           797:       return signe(y[1])*signe(y[2]);
        !           798:
        !           799:     case t_INTMOD:
        !           800:       if (egalii(gdeux,(GEN)y[1])) err(hiler1);
        !           801:       switch(ty)
        !           802:       {
        !           803:         case t_INTMOD:
        !           804:           if (!egalii((GEN)x[1],(GEN)y[1])) break;
        !           805:           return hil((GEN)x[2],(GEN)y[2],(GEN)x[1]);
        !           806:         case t_FRAC: case t_FRACN:
        !           807:          return hil((GEN)x[2],y,(GEN)x[1]);
        !           808:         case t_PADIC:
        !           809:           if (!egalii((GEN)x[1],(GEN)y[2])) break;
        !           810:           return hil((GEN)x[2],y,(GEN)x[1]);
        !           811:       }
        !           812:       break;
        !           813:
        !           814:     case t_FRAC: case t_FRACN:
        !           815:       p1=mulii((GEN)x[1],(GEN)x[2]);
        !           816:       switch(ty)
        !           817:       {
        !           818:        case t_FRAC: case t_FRACN:
        !           819:          p2=mulii((GEN)y[1],(GEN)y[2]);
        !           820:          z=hil(p1,p2,p); avma=av; return z;
        !           821:        case t_PADIC:
        !           822:          z=hil(p1,y,NULL); avma=av; return z;
        !           823:       }
        !           824:       break;
        !           825:
        !           826:     case t_PADIC:
        !           827:       if (ty != t_PADIC || !egalii((GEN)x[2],(GEN)y[2])) break;
        !           828:       p1 = odd(valp(x))? mulii((GEN)x[2],(GEN)x[4]): (GEN)x[4];
        !           829:       p2 = odd(valp(y))? mulii((GEN)y[2],(GEN)y[4]): (GEN)y[4];
        !           830:       z=hil(p1,p2,(GEN)x[2]); avma=av; return z;
        !           831:   }
        !           832:   err(talker,"forbidden or incompatible types in hil");
        !           833:   return 0; /* not reached */
        !           834: }
        !           835: #undef eps
        !           836: #undef ome
        !           837: #undef gome
        !           838:
        !           839: /*******************************************************************/
        !           840: /*                                                                 */
        !           841: /*                       SQUARE ROOT MODULO p                      */
        !           842: /*                                                                 */
        !           843: /*******************************************************************/
        !           844:
        !           845: #define sqrmod(x,p) (resii(sqri(x),p))
        !           846:
        !           847: /* Assume p is prime. return NULL if (a,p) = -1 */
        !           848: GEN
        !           849: mpsqrtmod(GEN a, GEN p)
        !           850: {
        !           851:   long av = avma, av1,lim,i,k,e;
        !           852:   GEN p1,q,v,y,w,m;
        !           853:
        !           854:   if (typ(a) != t_INT || typ(p) != t_INT) err(arither1);
        !           855:   if (signe(p) <= 0 || is_pm1(p)) err(talker,"not a prime in mpsqrtmod");
        !           856:   p1 = addsi(-1,p); e = vali(p1);
        !           857:   if (e == 0) /* p = 2 */
        !           858:   {
        !           859:     avma = av;
        !           860:     if (!egalii(p, gdeux))
        !           861:       err(talker,"composite modulus in mpsqrtmod: %Z",p);
        !           862:     if (!signe(a) || !mod2(a)) return gzero;
        !           863:     return gun;
        !           864:   }
        !           865:   q = shifti(p1,-e); /* q = (p-1)/2^oo is odd */
        !           866:   if (e == 1) y = p1;
        !           867:   else /* look for an odd power of a primitive root */
        !           868:     for (k=2; ; k++)
        !           869:     { /* loop terminates for k < p (even if p composite) */
        !           870:
        !           871:       i = krosg(k,p);
        !           872:       if (i >= 0)
        !           873:       {
        !           874:         if (i) continue;
        !           875:         err(talker,"composite modulus in mpsqrtmod: %Z",p);
        !           876:       }
        !           877:       av1 = avma;
        !           878:       y = m = powmodulo(stoi(k),q,p);
        !           879:       for (i=1; i<e; i++)
        !           880:        if (gcmp1(m = sqrmod(m,p))) break;
        !           881:       if (i == e) break; /* success */
        !           882:       avma = av1;
        !           883:     }
        !           884:
        !           885:   p1 = powmodulo(a, shifti(q,-1), p); /* a ^ [(q-1)/2] */
        !           886:   if (!signe(p1)) { avma=av; return gzero; }
        !           887:   v = modii(mulii(a, p1), p);
        !           888:   w = modii(mulii(v, p1), p);
        !           889:   lim = stack_lim(av,1);
        !           890:   while (!gcmp1(w))
        !           891:   { /* a*w = v^2, y primitive 2^e-th root of 1
        !           892:        a square --> w even power of y, hence w^(2^(e-1)) = 1 */
        !           893:     p1 = sqrmod(w,p);
        !           894:     for (k=1; !gcmp1(p1) && k < e; k++) p1 = sqrmod(p1,p);
        !           895:     if (k == e) { avma=av; return NULL; } /* p composite or (a/p) != 1 */
        !           896:     /* w ^ (2^k) = 1 --> w = y ^ (u * 2^(e-k)), u odd */
        !           897:     p1 = y;
        !           898:     for (i=1; i < e-k; i++) p1 = sqrmod(p1,p);
        !           899:     y = sqrmod(p1, p); e = k;
        !           900:     w = modii(mulii(y, w), p);
        !           901:     v = modii(mulii(v, p1), p);
        !           902:     if (low_stack(lim, stack_lim(av,1)))
        !           903:     {
        !           904:       GEN *gptr[3]; gptr[0]=&y; gptr[1]=&w; gptr[2]=&v;
        !           905:       if(DEBUGMEM>1) err(warnmem,"mpsqrtmod");
        !           906:       gerepilemany(av,gptr,3);
        !           907:     }
        !           908:   }
        !           909:   av1 = avma;
        !           910:   p1 = subii(p,v); if (cmpii(v,p1) > 0) v = p1; else avma = av1;
        !           911:   return gerepileuptoint(av, v);
        !           912: }
        !           913:
        !           914: /*******************************************************************/
        !           915: /*                                                                 */
        !           916: /*                       n-th ROOT MODULO p                        */
        !           917: /*                                                                 */
        !           918: /*******************************************************************/
        !           919:
        !           920: /* UNCLEAN
        !           921:  * p-1=l^e*r
        !           922:  * l doit etre premier
        !           923:  * q=p-1
        !           924:  * q=(l^e)*r
        !           925:  * e>=1
        !           926:  * pgcd(r,l)=1
        !           927:  * return a non l-power residue and set zeta to a primitive l root of unity.
        !           928:  */
        !           929:
        !           930: static GEN
        !           931: mplgenmod(GEN l, long e, GEN r,GEN p,GEN *zeta)
        !           932: {
        !           933:   ulong av1;
        !           934:   GEN m,m1;
        !           935:   long k,i;
        !           936:   av1 = avma;
        !           937:   for (k=1; ; k++)
        !           938:   {
        !           939:     m1 = m = powmodulo(stoi(k+1),r,p);
        !           940:     for (i=1; i<e; i++)
        !           941:       if (gcmp1(m=powmodulo(m,l,p))) break;
        !           942:     if (i==e) break;
        !           943:     avma = av1;
        !           944:   }
        !           945:   *zeta=m;
        !           946:   return m1;
        !           947: }
        !           948: /* resoud x^l=a mod (p)
        !           949:  * l doit etre premier
        !           950:  * q=p-1
        !           951:  * q=(l^e)*r
        !           952:  * e>=1
        !           953:  * pgcd(r,l)=1
        !           954:  * m=y^(q/l)
        !           955:  * y n'est pas une puissance l-ieme
        !           956:  * m!=1
        !           957:  * ouf!
        !           958:  */
        !           959: GEN Fp_shanks(GEN x,GEN g0,GEN p, GEN q);
        !           960: static GEN
        !           961: mpsqrtlmod(GEN a, GEN l, GEN p, GEN q,long e, GEN r, GEN y, GEN m)
        !           962: {
        !           963:   ulong av = avma, tetpil,lim;
        !           964:   long k;
        !           965:   GEN p1,u1,u2,v,w,z,dl;
        !           966:   /* y contient un generateur de (Z/pZ)^* eleve a la puis (p-1)/(l^e) */
        !           967:   bezout(r,l,&u1,&u2);
        !           968:   v=powmodulo(a,u2,p);
        !           969:   w=powmodulo(a,modii(mulii(negi(u1),r),q),p);
        !           970:   lim = stack_lim(av,1);
        !           971:   while (!gcmp1(w))
        !           972:   {
        !           973:     /* if p is not prime, next loop will not end */
        !           974:     k=0;
        !           975:     p1=w;
        !           976:     do
        !           977:     {
        !           978:       z=p1;
        !           979:       p1=powmodulo(p1,l,p);
        !           980:       k++;
        !           981:     }while(!gcmp1(p1));
        !           982:     if (k==e) { avma=av; return NULL; }
        !           983:     dl=Fp_shanks(mpinvmod(z,p),m,p,l);
        !           984:     p1=powmodulo(y,modii(mulii(dl,gpowgs(l,e-k-1)),q),p);
        !           985:     m=powmodulo(m,dl,p);
        !           986:     e = k;
        !           987:     v = modii(mulii(p1,v),p);
        !           988:     y = powmodulo(p1,l,p);
        !           989:     w = modii(mulii(y,w),p);
        !           990:     if (low_stack(lim, stack_lim(av,1)))
        !           991:     {
        !           992:       GEN *gptr[4];
        !           993:       if(DEBUGMEM>1) err(warnmem,"mpsqrtlmod");
        !           994:       gptr[0]=&y; gptr[1]=&v; gptr[2]=&w; gptr[3]=&m;
        !           995:       gerepilemany(av,gptr,4);
        !           996:     }
        !           997:   }
        !           998:   tetpil=avma; return gerepile(av,tetpil,icopy(v));
        !           999: }
        !          1000: /* a and n are integers, p is prime
        !          1001:
        !          1002: return a solution of
        !          1003:
        !          1004: x^n=a mod p
        !          1005:
        !          1006: 1)If there is no solution return NULL and if zetan is not NULL set zetan to gzero.
        !          1007:
        !          1008: 2) If there is solution there are exactly  m=gcd(p-1,n) of them.
        !          1009:
        !          1010: If zetan is not NULL, zetan is set to a primitive mth root of unity so that
        !          1011: the set of solutions is {x*zetan^k;k=0 to m-1}
        !          1012:
        !          1013: If a=0 ,return 0 and if zetan is not NULL zetan is set to gun
        !          1014: */
        !          1015: GEN
        !          1016: mpsqrtnmod(GEN a, GEN n, GEN p, GEN *zetan)
        !          1017: {
        !          1018:   ulong ltop=avma,lbot=0,av1,lim;
        !          1019:   GEN m,u1,u2;
        !          1020:   GEN q,z;
        !          1021:   GEN *gptr[2];
        !          1022:   if (typ(a) != t_INT || typ(n) != t_INT || typ(p)!=t_INT)
        !          1023:     err(typeer,"mpsqrtnmod");
        !          1024:   if(!signe(n))
        !          1025:     err(talker,"1/0 exponent in mpsqrtnmod");
        !          1026:   if(gcmp1(n)) {if (zetan) *zetan=gun;return gcopy(a);}
        !          1027:   a=modii(a,p);
        !          1028:   if(gcmp0(a)) {if (zetan) *zetan=gun;avma=ltop;return gzero;}
        !          1029:   q=addsi(-1,p);
        !          1030:   m=bezout(n,q,&u1,&u2);
        !          1031:   if (zetan) z=gun;
        !          1032:   lim=stack_lim(ltop,1);
        !          1033:   if (!gcmp1(m))
        !          1034:   {
        !          1035:     GEN F=decomp(m);
        !          1036:     long i,j,e;
        !          1037:     GEN r,zeta,y,l;
        !          1038:     av1=avma;
        !          1039:     for (i = lg(F[1])-1; i; i--)
        !          1040:     {
        !          1041:       l=gcoeff(F,i,1); j=itos(gcoeff(F,i,2));
        !          1042:       e=pvaluation(q,l,&r);
        !          1043:       y=mplgenmod(l,e,r,p,&zeta);
        !          1044:       if (zetan) z=modii(mulii(z,powmodulo(y,gpowgs(l,e-j),p)),p);
        !          1045:       do
        !          1046:       {
        !          1047:        lbot=avma;
        !          1048:        if (!is_pm1(a) || signe(a)<0)
        !          1049:          a=mpsqrtlmod(a,l,p,q,e,r,y,zeta);
        !          1050:        else
        !          1051:          a=icopy(a);
        !          1052:        if (!a){avma=ltop;if (zetan)  *zetan=gzero;return NULL;}
        !          1053:        j--;
        !          1054:       }while (j);
        !          1055:       if (low_stack(lim, stack_lim(ltop,1)))
        !          1056:        /* n can have lots of prime factors*/
        !          1057:       {
        !          1058:        if(DEBUGMEM>1) err(warnmem,"mpsqrtnmod");
        !          1059:        if (zetan)
        !          1060:        {
        !          1061:          z=gcopy(z);
        !          1062:          gptr[0]=&a;gptr[1]=&z;
        !          1063:          gerepilemanysp(av1,lbot,gptr,2);
        !          1064:        }
        !          1065:        else
        !          1066:          a=gerepile(av1,lbot,a);
        !          1067:        lbot=av1;
        !          1068:       }
        !          1069:     }
        !          1070:   }
        !          1071:   if (cmpii(m,n))
        !          1072:   {
        !          1073:     GEN b=modii(u1,q);
        !          1074:     lbot=avma;
        !          1075:     a=powmodulo(a,b,p);
        !          1076:   }
        !          1077:   if (zetan)
        !          1078:   {
        !          1079:     *zetan=gcopy(z);
        !          1080:     gptr[0]=&a;gptr[1]=zetan;
        !          1081:     gerepilemanysp(ltop,lbot,gptr,2);
        !          1082:   }
        !          1083:   else
        !          1084:     a=gerepile(ltop,lbot,a);
        !          1085:   return a;
        !          1086: }
        !          1087:
        !          1088: /*********************************************************************/
        !          1089: /**                                                                 **/
        !          1090: /**                        GCD & BEZOUT                             **/
        !          1091: /**                                                                 **/
        !          1092: /*********************************************************************/
        !          1093:
        !          1094: /* Ultra-fast private ulong gcd for trial divisions.  Called with y odd;
        !          1095:    x can be arbitrary (but will most of the time be smaller than y).
        !          1096:    Will also be used from inside ifactor2.c, so it's `semi-private' really.
        !          1097:    --GN */
        !          1098:
        !          1099: /* Gotos are Harmful, and Programming is a Science.  E.W.Dijkstra. */
        !          1100: ulong
        !          1101: ugcd(ulong x, ulong y)         /* assume y&1==1, y > 1 */
        !          1102: {
        !          1103:   if (!x) return y;
        !          1104:   /* fix up x */
        !          1105:   while (!(x&1)) x>>=1;
        !          1106:   if (x==1) return 1;
        !          1107:   if (x==y) return y;
        !          1108:   else if (x>y) goto xislarger;/* will be rare, given how we'll use this */
        !          1109:   /* loop invariants: x,y odd and distinct. */
        !          1110:  yislarger:
        !          1111:   if ((x^y)&2)                 /* ...01, ...11 or vice versa */
        !          1112:     y=(x>>2)+(y>>2)+1;         /* ==(x+y)>>2 except it can't overflow */
        !          1113:   else                         /* ...01,...01 or ...11,...11 */
        !          1114:     y=(y-x)>>2;                /* now y!=0 in either case */
        !          1115:   while (!(y&1)) y>>=1;        /* kill any windfall-gained powers of 2 */
        !          1116:   if (y==1) return 1;          /* comparand == return value... */
        !          1117:   if (x==y) return y;          /* this and the next is just one comparison */
        !          1118:   else if (x<y) goto yislarger;/* else fall through to xislarger */
        !          1119:
        !          1120:  xislarger:                    /* same as above, seen through a mirror */
        !          1121:   if ((x^y)&2)
        !          1122:     x=(x>>2)+(y>>2)+1;
        !          1123:   else
        !          1124:     x=(x-y)>>2;                /* x!=0 */
        !          1125:   while (!(x&1)) x>>=1;
        !          1126:   if (x==1) return 1;
        !          1127:   if (x==y) return y;
        !          1128:   else if (x>y) goto xislarger;/* again, a decent [g]cc should notice that
        !          1129:                                   it can re-use the comparison */
        !          1130:   goto yislarger;
        !          1131: }
        !          1132: /* Gotos are useful, and Programming is an Art.  D.E.Knuth. */
        !          1133: /* PS: Of course written with Dijkstra's lessons firmly in mind... --GN */
        !          1134:
        !          1135: /* modified right shift binary algorithm with at most one division */
        !          1136: long
        !          1137: cgcd(long a,long b)
        !          1138: {
        !          1139:   long v;
        !          1140:   a=labs(a); if (!b) return a;
        !          1141:   b=labs(b); if (!a) return b;
        !          1142:   if (a>b) { a %= b; if (!a) return b; }
        !          1143:   else { b %= a; if (!b) return a; }
        !          1144:   v=vals(a|b); a>>=v; b>>=v;
        !          1145:   if (a==1 || b==1) return 1L<<v;
        !          1146:   if (b&1)
        !          1147:     return ((long)ugcd((ulong)a, (ulong)b)) << v;
        !          1148:   else
        !          1149:     return ((long)ugcd((ulong)b, (ulong)a)) << v;
        !          1150: }
        !          1151: long
        !          1152: clcm(long a,long b)
        !          1153: {
        !          1154:   long d;
        !          1155:   if(!a) return 0;
        !          1156:   d=cgcd(a,b);
        !          1157:   if(d!=1) return a*(b/d);
        !          1158:   return a*b;
        !          1159: }
        !          1160:
        !          1161: /* assume a>b>0, return gcd(a,b) as a GEN (for mppgcd) */
        !          1162: static GEN
        !          1163: mppgcd_cgcd(ulong a, ulong b)
        !          1164: {
        !          1165:   GEN r = cgeti(3);
        !          1166:   long v;
        !          1167:
        !          1168:   r[1] = evalsigne(1)|evallgefint(3);
        !          1169:   a %= b; if (!a) { r[2]=(long)b; return r; }
        !          1170:   v=vals(a|b); a>>=v; b>>=v;
        !          1171:   if (a==1 || b==1) { r[2]=(long)(1UL<<v); return r; }
        !          1172:   if (b&1)
        !          1173:     r[2] = (long)(ugcd((ulong)a, (ulong)b) << v);
        !          1174:   else
        !          1175:     r[2] = (long)(ugcd((ulong)b, (ulong)a) << v);
        !          1176:   return r;
        !          1177: }
        !          1178:
        !          1179: void mppgcd_plus_minus(GEN x, GEN y, GEN t);
        !          1180: ulong mppgcd_resiu(GEN y, ulong x);
        !          1181:
        !          1182: /* uses modified right-shift binary algorithm now --GN 1998Jul23 */
        !          1183: GEN
        !          1184: mppgcd(GEN a, GEN b)
        !          1185: {
        !          1186:   long av,v,w;
        !          1187:   GEN t, p1;
        !          1188:
        !          1189:   if (typ(a) != t_INT || typ(b) != t_INT) err(arither1);
        !          1190:   switch (absi_cmp(a,b))
        !          1191:   {
        !          1192:     case 0: return absi(a);
        !          1193:     case -1: t=b; b=a; a=t;
        !          1194:   }
        !          1195:   if (!signe(b)) return absi(a);
        !          1196:   /* here |a|>|b|>0. Try single precision first */
        !          1197:   if (lgefint(a)==3)
        !          1198:     return mppgcd_cgcd((ulong)a[2], (ulong)b[2]);
        !          1199:   if (lgefint(b)==3)
        !          1200:   {
        !          1201:     ulong u = mppgcd_resiu(a,(ulong)b[2]);
        !          1202:     if (!u) return absi(b);
        !          1203:     return mppgcd_cgcd((ulong)b[2], u);
        !          1204:   }
        !          1205:
        !          1206:   /* larger than gcd: "avma=av" gerepile (erasing t) is valid */
        !          1207:   av = avma; new_chunk(lgefint(b)); /* HACK */
        !          1208:   t = resii(a,b);
        !          1209:   if (!signe(t)) { avma=av; return absi(b); }
        !          1210:
        !          1211:   a = b; b = t;
        !          1212:   v = vali(a); a = shifti(a,-v); setsigne(a,1);
        !          1213:   w = vali(b); b = shifti(b,-w); setsigne(b,1);
        !          1214:   if (w < v) v = w;
        !          1215:   switch(absi_cmp(a,b))
        !          1216:   {
        !          1217:     case  0: avma=av; a=shifti(a,v); return a;
        !          1218:     case -1: p1=b; b=a; a=p1;
        !          1219:   }
        !          1220:   if (is_pm1(b)) { avma=av; return shifti(gun,v); }
        !          1221:
        !          1222:   /* we have three consecutive memory locations: a,b,t.
        !          1223:    * All computations are done in place */
        !          1224:
        !          1225:   /* a and b are odd now, and a>b>1 */
        !          1226:   while (lgefint(a) > 3)
        !          1227:   {
        !          1228:     /* if a=b mod 4 set t=a-b, otherwise t=a+b, then strip powers of 2 */
        !          1229:     /* so that t <= (a+b)/4 < a/2 */
        !          1230:     mppgcd_plus_minus(a,b, t);
        !          1231:     if (is_pm1(t)) { avma=av; return shifti(gun,v); }
        !          1232:     switch(absi_cmp(t,b))
        !          1233:     {
        !          1234:       case -1: p1 = a; a = b; b = t; t = p1; break;
        !          1235:       case  1: p1 = a; a = t; t = p1; break;
        !          1236:       case  0: avma = av; b=shifti(b,v); return b;
        !          1237:     }
        !          1238:   }
        !          1239:   {
        !          1240:     long r[] = {evaltyp(t_INT)|m_evallg(3), evalsigne(1)|evallgefint(3), 0};
        !          1241:     r[2] = (long) ugcd((ulong)b[2], (ulong)a[2]);
        !          1242:     avma = av; return shifti(r,v);
        !          1243:   }
        !          1244: }
        !          1245:
        !          1246: GEN
        !          1247: mpppcm(GEN x, GEN y)
        !          1248: {
        !          1249:   ulong av;
        !          1250:   GEN p1,p2;
        !          1251:   if (typ(x) != t_INT || typ(y) != t_INT) err(arither1);
        !          1252:   if (!signe(x)) return gzero;
        !          1253:   av = avma;
        !          1254:   p1 = mppgcd(x,y); if (!is_pm1(p1)) y = divii(y,p1);
        !          1255:   p2 = mulii(x,y);
        !          1256:   if (signe(p2) < 0) setsigne(p2,1);
        !          1257:   return gerepileuptoint(av, p2);
        !          1258: }
        !          1259:
        !          1260: /*********************************************************************/
        !          1261: /**                                                                 **/
        !          1262: /**                      CHINESE REMAINDERS                         **/
        !          1263: /**                                                                 **/
        !          1264: /*********************************************************************/
        !          1265:
        !          1266: /*  P.M. & M.H.
        !          1267:  *
        !          1268:  *  Chinese Remainder Theorem.  x and y must have the same type (integermod,
        !          1269:  *  polymod, or polynomial/vector/matrix recursively constructed with these
        !          1270:  *  as coefficients). Creates (with the same type) a z in the same residue
        !          1271:  *  class as x and the same residue class as y, if it is possible.
        !          1272:  *
        !          1273:  *  We also allow (during recursion) two identical objects even if they are
        !          1274:  *  not integermod or polymod. For example, if
        !          1275:  *
        !          1276:  *    x = [1. mod(5, 11), mod(X + mod(2, 7), X^2 + 1)]
        !          1277:  *    y = [1, mod(7, 17), mod(X + mod(0, 3), X^2 + 1)],
        !          1278:  *
        !          1279:  *  then chinois(x, y) returns
        !          1280:  *
        !          1281:  *    [1, mod(16, 187), mod(X + mod(9, 21), X^2 + 1)]
        !          1282:  *
        !          1283:  *  Someone else may want to allow power series, complex numbers, and
        !          1284:  *  quadratic numbers.
        !          1285:  */
        !          1286:
        !          1287: GEN chinese(GEN x, GEN y)
        !          1288: {
        !          1289:   return gassoc_proto(chinois,x,y);
        !          1290: }
        !          1291:
        !          1292: GEN
        !          1293: chinois(GEN x, GEN y)
        !          1294: {
        !          1295:   ulong av,tetpil, tx = typ(x);
        !          1296:   long i,lx,vx;
        !          1297:   GEN z,p1,p2,d,u,v;
        !          1298:
        !          1299:   if (gegal(x,y)) return gcopy(x);
        !          1300:   if (tx == typ(y)) switch(tx)
        !          1301:   {
        !          1302:     case t_POLMOD:
        !          1303:       if (gegal((GEN)x[1],(GEN)y[1]))  /* same modulus */
        !          1304:       {
        !          1305:        z=cgetg(3,tx);
        !          1306:        z[1]=lcopy((GEN)x[1]);
        !          1307:        z[2]=(long)chinois((GEN)x[2],(GEN)y[2]);
        !          1308:         return z;
        !          1309:       }  /* fall through */
        !          1310:     case t_INTMOD:
        !          1311:       z=cgetg(3,tx); av=avma;
        !          1312:       d=gbezout((GEN)x[1],(GEN)y[1],&u,&v);
        !          1313:       if (!gegal(gmod((GEN)x[2],d), gmod((GEN)y[2],d))) break;
        !          1314:       p1 = gdiv((GEN)x[1],d);
        !          1315:       p2 = gadd((GEN)x[2], gmul(gmul(u,p1), gadd((GEN)y[2],gneg((GEN)x[2]))));
        !          1316:
        !          1317:       tetpil=avma; z[1]=lmul(p1,(GEN)y[1]); z[2]=lmod(p2,(GEN)z[1]);
        !          1318:       gerepilemanyvec(av,tetpil,z+1,2); return z;
        !          1319:
        !          1320:     case t_POL:
        !          1321:       lx=lgef(x); vx=varn(x); z=cgetg(lx,tx);
        !          1322:       if (lx!=lgef(y) || vx!=varn(y)) break;
        !          1323:       z[1]=evalsigne(1)|evallgef(lx)|evalvarn(vx);
        !          1324:       for (i=2; i<lx; i++) z[i]=(long)chinois((GEN)x[i],(GEN)y[i]);
        !          1325:       return z;
        !          1326:
        !          1327:     case t_VEC: case t_COL: case t_MAT:
        !          1328:       lx=lg(x); z=cgetg(lx,tx); if (lx!=lg(y)) break;
        !          1329:       for (i=1; i<lx; i++) z[i]=(long)chinois((GEN)x[i],(GEN)y[i]);
        !          1330:       return z;
        !          1331:   }
        !          1332:   err(talker,"incompatible arguments in chinois");
        !          1333:   return NULL; /* not reached */
        !          1334: }
        !          1335:
        !          1336: /* return lift(chinois(x2 mod x1, y2 mod y1))
        !          1337:  * assume(x1,y1)=1, xi,yi integers and z1 = x1*y1
        !          1338:  */
        !          1339: GEN
        !          1340: chinois_int_coprime(GEN x2, GEN y2, GEN x1, GEN y1, GEN z1)
        !          1341: {
        !          1342:   ulong av = avma;
        !          1343:   GEN ax,p1;
        !          1344:   (void)new_chunk((lgefint(z1)<<1)+lgefint(x1)+lgefint(y1)); /* HACK */
        !          1345:   ax = mulii(mpinvmod(x1,y1), x1);
        !          1346:   p1 = addii(x2, mulii(ax, subii(y2,x2)));
        !          1347:   avma = av; return modii(p1,z1);
        !          1348: }
        !          1349:
        !          1350: /*********************************************************************/
        !          1351: /**                                                                 **/
        !          1352: /**                      INVERSE MODULO b                           **/
        !          1353: /**                                                                 **/
        !          1354: /*********************************************************************/
        !          1355:
        !          1356: GEN
        !          1357: mpinvmod(GEN a, GEN m)
        !          1358: {
        !          1359:   GEN res;
        !          1360:   if (! invmod(a,m,&res))
        !          1361:     err(invmoder,"%Z",gmodulcp(res,m));
        !          1362:   return res;
        !          1363: }
        !          1364:
        !          1365: /*********************************************************************/
        !          1366: /**                                                                 **/
        !          1367: /**                   POWERING MODULO (A^N mod M)                   **/
        !          1368: /**                                                                 **/
        !          1369: /*********************************************************************/
        !          1370: GEN resiimul(GEN x, GEN y);
        !          1371: GEN resmod2n(GEN x, long y);
        !          1372: GEN _resii(GEN x, GEN y) { return resii(x,y); }
        !          1373:
        !          1374: GEN
        !          1375: init_remainder(GEN M)
        !          1376: {
        !          1377:   GEN sM = cgetg(3, t_VEC);
        !          1378:   GEN Mr = cgetr(lgefint(M) + 1);
        !          1379:   affir(M, Mr);
        !          1380:   sM[1] = (long)M;
        !          1381:   sM[2] = (long)linv(Mr);
        !          1382:   return sM;
        !          1383: }
        !          1384:
        !          1385: /* optimal on UltraSPARC */
        !          1386: static long RESIIMUL_LIMIT = 150;
        !          1387:
        !          1388: void
        !          1389: setresiilimit(long n) { RESIIMUL_LIMIT = n; }
        !          1390:
        !          1391: GEN
        !          1392: powmodulo(GEN A, GEN N, GEN M)
        !          1393: {
        !          1394:   GEN y;
        !          1395:   long av = avma,av1,lim,man,k,nb,s, *p;
        !          1396:   GEN (*mul)(GEN,GEN) = mulii;
        !          1397:   GEN (*res)(GEN,GEN) = _resii;
        !          1398:
        !          1399:   if (typ(A) != t_INT || typ(N) != t_INT || typ(M) != t_INT) err(arither1);
        !          1400:   s = signe(N);
        !          1401:   if (!s)
        !          1402:   {
        !          1403:     k = signe(resii(A,M)); avma=av;
        !          1404:     return k? gun: gzero;
        !          1405:   }
        !          1406:   if (s < 0) { A = mpinvmod(A,M); N = absi(N); }
        !          1407:   else
        !          1408:   {
        !          1409:     A = modii(A,M);
        !          1410:     if (!signe(A)) { avma=av; return gzero; }
        !          1411:   }
        !          1412:   y = A;
        !          1413:   if (lgefint(y)==3) switch(y[2])
        !          1414:   {
        !          1415:     case 1: /* y = 1 */
        !          1416:       avma=av; return gun;
        !          1417:     case 2: /* y = 2, use shifti not mulii */
        !          1418:     mul = (GEN (*)(GEN,GEN))shifti; A = (GEN)1L;
        !          1419:   }
        !          1420:
        !          1421:   /* TODO: Move this out of here and use for general modular computations */
        !          1422:   if ((k = vali(M)) && k == expi(M))
        !          1423:   { /* M is a power of 2 */
        !          1424:     M = (GEN)k;
        !          1425:     res = (GEN(*)(GEN,GEN))resmod2n;
        !          1426:   }
        !          1427:   else if (lgefint(M) > RESIIMUL_LIMIT && (lgefint(N) > 3 || N[2] > 4))
        !          1428:   { /* compute x % M using multiplication by 1./M */
        !          1429:     M = init_remainder(M);
        !          1430:     res = (GEN(*)(GEN,GEN))resiimul;
        !          1431:   }
        !          1432:
        !          1433:   p = N+2; man = *p; /* see puissii */
        !          1434:   k = 1+bfffo(man); man<<=k; k = BITS_IN_LONG-k;
        !          1435:   av1=avma; lim=stack_lim(av1,1);
        !          1436:   for (nb=lgefint(N)-2;;)
        !          1437:   {
        !          1438:     for (; k; man<<=1,k--)
        !          1439:     {
        !          1440:       y = res(sqri(y), M);
        !          1441:       if (man < 0) y = res(mul(y,A), M);
        !          1442:       if (low_stack(lim, stack_lim(av1,1)))
        !          1443:       {
        !          1444:         if (DEBUGMEM>1) err(warnmem,"powmodulo");
        !          1445:         y = gerepileuptoint(av1,y);
        !          1446:       }
        !          1447:     }
        !          1448:     if (--nb == 0) break;
        !          1449:     man = *++p, k = BITS_IN_LONG;
        !          1450:   }
        !          1451:   return gerepileupto(av,y);
        !          1452: }
        !          1453:
        !          1454: /*********************************************************************/
        !          1455: /**                                                                 **/
        !          1456: /**                NEXT / PRECEDING (PSEUDO) PRIME                  **/
        !          1457: /**                                                                 **/
        !          1458: /*********************************************************************/
        !          1459: GEN
        !          1460: gnextprime(GEN n)
        !          1461: {
        !          1462:   return garith_proto(nextprime,n,0);
        !          1463: }
        !          1464:
        !          1465: GEN
        !          1466: gprecprime(GEN n)
        !          1467: {
        !          1468:   return garith_proto(precprime,n,0);
        !          1469: }
        !          1470:
        !          1471: GEN
        !          1472: gisprime(GEN x, long flag)
        !          1473: {
        !          1474:   switch (flag)
        !          1475:   {
        !          1476:   case 0:
        !          1477:     return arith_proto(isprime,x,1);
        !          1478:   case 1:
        !          1479:     return garith_proto2gs(plisprime,x,0);
        !          1480:   case 2:
        !          1481:     return garith_proto2gs(plisprime,x,1);
        !          1482:   }
        !          1483:   err(flagerr,"gisprime");
        !          1484:   return 0;
        !          1485: }
        !          1486:
        !          1487: long
        !          1488: isprime(GEN x)
        !          1489: {
        !          1490:   return millerrabin(x,10);
        !          1491: }
        !          1492:
        !          1493: GEN
        !          1494: gispsp(GEN x)
        !          1495: {
        !          1496:   return arith_proto(ispsp,x,1);
        !          1497: }
        !          1498:
        !          1499: long
        !          1500: ispsp(GEN x)
        !          1501: {
        !          1502:   return millerrabin(x,1);
        !          1503: }
        !          1504:
        !          1505: GEN
        !          1506: gmillerrabin(GEN n, long k)
        !          1507: {
        !          1508:   return arith_proto2gs(millerrabin,n,k);
        !          1509: }
        !          1510:
        !          1511: /*********************************************************************/
        !          1512: /**                                                                 **/
        !          1513: /**                    FUNDAMENTAL DISCRIMINANTS                    **/
        !          1514: /**                                                                 **/
        !          1515: /*********************************************************************/
        !          1516:
        !          1517: /* gissquarefree, issquarefree moved into arith2.c with the other
        !          1518:    basic arithmetic functions (issquarefree is the square of the
        !          1519:    Moebius mu function, after all...) --GN */
        !          1520:
        !          1521: GEN
        !          1522: gisfundamental(GEN x)
        !          1523: {
        !          1524:   return arith_proto(isfundamental,x,1);
        !          1525: }
        !          1526:
        !          1527: long
        !          1528: isfundamental(GEN x)
        !          1529: {
        !          1530:   long av,r;
        !          1531:   GEN p1;
        !          1532:
        !          1533:   if (gcmp0(x)) return 0;
        !          1534:   r=mod4(x);
        !          1535:   if (!r)
        !          1536:   {
        !          1537:     av=avma; p1=shifti(x,-2);
        !          1538:     r=mod4(p1); if (!r) return 0;
        !          1539:     if (signe(x)<0) r=4-r;
        !          1540:     r = (r==1)? 0: issquarefree(p1);
        !          1541:     avma=av; return r;
        !          1542:   }
        !          1543:   if (signe(x)<0) r=4-r;
        !          1544:   return (r==1) ? issquarefree(x) : 0;
        !          1545: }
        !          1546:
        !          1547: GEN
        !          1548: quaddisc(GEN x)
        !          1549: {
        !          1550:   long av=avma,tetpil=avma,i,r,tx=typ(x);
        !          1551:   GEN p1,p2,f,s;
        !          1552:
        !          1553:   if (tx != t_INT && ! is_frac_t(tx)) err(arither1);
        !          1554:   f=factor(x); p1=(GEN)f[1]; p2=(GEN)f[2];
        !          1555:   s=gun;
        !          1556:   for (i=1; i<lg(p1); i++)
        !          1557:     if ( odd(mael(p2,i,2)) ) { tetpil=avma; s=gmul(s,(GEN)p1[i]); }
        !          1558:   r=mod4(s); if (gsigne(x)<0) r=4-r;
        !          1559:   if (r>1) { tetpil=avma; s=shifti(s,2); }
        !          1560:   return gerepile(av,tetpil,s);
        !          1561: }
        !          1562:
        !          1563: /*********************************************************************/
        !          1564: /**                                                                 **/
        !          1565: /**                              FACTORIAL                          **/
        !          1566: /**                                                                 **/
        !          1567: /*********************************************************************/
        !          1568: GEN muluu(ulong x, ulong y);
        !          1569:
        !          1570: GEN
        !          1571: mpfact(long n)
        !          1572: {
        !          1573:   long lx,k,l, av = avma;
        !          1574:   GEN x;
        !          1575:
        !          1576:   if (n<2)
        !          1577:   {
        !          1578:     if (n<0) err(facter);
        !          1579:     return gun;
        !          1580:   }
        !          1581:   if (n < 60)
        !          1582:   {
        !          1583:     x = gdeux;
        !          1584:     for (k=3; k<=n; k++) x = mulsi(k,x);
        !          1585:     return gerepileuptoint(av,x);
        !          1586:   }
        !          1587:   lx = 1; x = cgetg(1 + n/2, t_VEC);
        !          1588:   for (k=2;; k++)
        !          1589:   {
        !          1590:     l = n+2-k; if (l <= k) break;
        !          1591:     x[lx++] = (long)muluu(k,l);
        !          1592:   }
        !          1593:   if (l == k) x[lx++] = lstoi(k);
        !          1594:   setlg(x, lx);
        !          1595:   return gerepileuptoint(av, divide_conquer_prod(x, mulii));
        !          1596: }
        !          1597:
        !          1598: GEN
        !          1599: mpfactr(long n, long prec)
        !          1600: {
        !          1601:   long av = avma, lim,k;
        !          1602:   GEN f = cgetr(prec);
        !          1603:
        !          1604:   affsr(1,f);
        !          1605:   if (n<2)
        !          1606:   {
        !          1607:     if (n<0) err(facter);
        !          1608:     return f;
        !          1609:   }
        !          1610:   lim = stack_lim(av,1);
        !          1611:   for (k=2; k<=n; k++)
        !          1612:   {
        !          1613:     f = mulsr(k,f);
        !          1614:     if (low_stack(lim, stack_lim(av,1)))
        !          1615:     {
        !          1616:       if(DEBUGMEM>1) err(warnmem,"mpfactr k=%ld",k);
        !          1617:       f = gerepileuptoleaf(av,f);
        !          1618:     }
        !          1619:   }
        !          1620:   return gerepileuptoleaf(av,f);
        !          1621: }
        !          1622:
        !          1623: /*******************************************************************/
        !          1624: /**                                                               **/
        !          1625: /**                      LUCAS & FIBONACCI                        **/
        !          1626: /**                                                               **/
        !          1627: /*******************************************************************/
        !          1628:
        !          1629: void
        !          1630: lucas(long n, GEN *ln, GEN *ln1)
        !          1631: {
        !          1632:   long taille,av;
        !          1633:   GEN z,t;
        !          1634:
        !          1635:   if (!n) { *ln=stoi(2); *ln1=stoi(1); return; }
        !          1636:
        !          1637:   taille=(long)(pariC3*(1+labs(n))+3);
        !          1638:   *ln=cgeti(taille); *ln1=cgeti(taille);
        !          1639:   av=avma; lucas(n/2,&z,&t);
        !          1640:   switch(n % 4)
        !          1641:   {
        !          1642:     case -3:
        !          1643:       addsiz(2,sqri(z),*ln1);
        !          1644:       subiiz(addsi(1,mulii(z,t)),*ln1,*ln); break;
        !          1645:     case -2:
        !          1646:       addsiz(2,sqri(z),*ln); addsiz(1,mulii(z,t),*ln1); break;
        !          1647:     case -1:
        !          1648:       subisz(sqri(z),2,*ln1);
        !          1649:       subiiz(subis(mulii(z,t),1),*ln1,*ln); break;
        !          1650:     case  0: subisz(sqri(z),2,*ln); subisz(mulii(z,t),1,*ln1); break;
        !          1651:     case  1: subisz(mulii(z,t),1,*ln); addsiz(2,sqri(t),*ln1); break;
        !          1652:     case  2: addsiz(2,sqri(z),*ln); addsiz(1,mulii(z,t),*ln1); break;
        !          1653:     case  3: addsiz(1,mulii(z,t),*ln); subisz(sqri(t),2,*ln1);
        !          1654:   }
        !          1655:   avma=av;
        !          1656: }
        !          1657:
        !          1658: GEN
        !          1659: fibo(long n)
        !          1660: {
        !          1661:   long av = avma;
        !          1662:   GEN ln,ln1;
        !          1663:
        !          1664:   lucas(n-1,&ln,&ln1);
        !          1665:   return gerepileupto(av, divis(addii(shifti(ln,1),ln1), 5));
        !          1666: }
        !          1667:
        !          1668: /*******************************************************************/
        !          1669: /*                                                                 */
        !          1670: /*                      CONTINUED FRACTIONS                        */
        !          1671: /*                                                                 */
        !          1672: /*******************************************************************/
        !          1673: static GEN sfcont2(GEN b, GEN x, long k);
        !          1674:
        !          1675: GEN
        !          1676: gcf(GEN x)
        !          1677: {
        !          1678:   return sfcont(x,x,0);
        !          1679: }
        !          1680:
        !          1681: GEN
        !          1682: gcf2(GEN b, GEN x)
        !          1683: {
        !          1684:   return contfrac0(x,b,0);
        !          1685: }
        !          1686:
        !          1687: GEN
        !          1688: gboundcf(GEN x, long k)
        !          1689: {
        !          1690:   return sfcont(x,x,k);
        !          1691: }
        !          1692:
        !          1693: GEN
        !          1694: contfrac0(GEN x, GEN b, long flag)
        !          1695: {
        !          1696:   long lb,tb,i;
        !          1697:   GEN y;
        !          1698:
        !          1699:   if (!b || gcmp0(b)) return sfcont(x,x,flag);
        !          1700:   tb = typ(b);
        !          1701:   if (tb == t_INT) return sfcont(x,x,itos(b));
        !          1702:   if (! is_matvec_t(tb)) err(typeer,"contfrac0");
        !          1703:
        !          1704:   lb=lg(b); if (lb==1) return cgetg(1,t_VEC);
        !          1705:   if (tb != t_MAT) return sfcont2(b,x,flag);
        !          1706:   if (lg(b[1])==1) return sfcont(x,x,flag);
        !          1707:   y = (GEN) gpmalloc(lb*sizeof(long));
        !          1708:   for (i=1; i<lb; i++) y[i]=coeff(b,1,i);
        !          1709:   x = sfcont2(y,x,flag); free(y); return x;
        !          1710: }
        !          1711:
        !          1712: GEN
        !          1713: sfcont(GEN x, GEN x1, long k)
        !          1714: {
        !          1715:   long  av,lx=lg(x),tx=typ(x),e,i,j,l,l1,lx1,tetpil,f;
        !          1716:   GEN   y,p1,p2,p3,p4,yp;
        !          1717:
        !          1718:   if (is_scalar_t(tx))
        !          1719:   {
        !          1720:     if (gcmp0(x)) { y=cgetg(2,t_VEC); y[1]=zero; return y; }
        !          1721:     switch(tx)
        !          1722:     {
        !          1723:       case t_INT:
        !          1724:         y=cgetg(2,t_VEC); y[1]=lcopy(x); return y;
        !          1725:       case t_REAL:
        !          1726:         l=avma; p1=cgetg(3,t_FRACN);
        !          1727:        p2 = rcopy(x); settyp(p2,t_INT); setlgefint(p2,lx);
        !          1728:        p1[1] = (long) p2; e = bit_accuracy(lx)-1-expo(x);
        !          1729:        if (e<0) err(talker,"integral part not significant in scfont");
        !          1730:
        !          1731:        l1 = (e>>TWOPOTBITS_IN_LONG)+3; p2=cgeti(l1);
        !          1732:        p2[1]= evalsigne(1)|evallgefint(l1);
        !          1733:        p2[2]= (1L<<(e&(BITS_IN_LONG-1)));
        !          1734:        for (i=3; i<l1; i++) p2[i]=0;
        !          1735:        p1[2]=(long) p2; p3=cgetg(3,t_FRACN);
        !          1736:        p3[2]=lcopy(p2);
        !          1737:        p3[1]=laddsi(signe(x),(GEN)p1[1]);
        !          1738:        p1=sfcont(p1,p1,k); tetpil=avma;
        !          1739:        return gerepile(l,tetpil,sfcont(p3,p1,k));
        !          1740:
        !          1741:       case t_FRAC: case t_FRACN:
        !          1742:         l=avma; lx1=lgefint(x[2]);
        !          1743:        l1 = (long) ((double) BYTES_IN_LONG/4.0*46.093443*(lx1-2)+3);
        !          1744:         if (k>0 && ++k > 0 && l1 > k) l1 = k; /* beware overflow */
        !          1745:        if ((ulong)l1>LGBITS) l1=LGBITS;
        !          1746:        if (lgefint(x[1]) >= lx1) p1=icopy((GEN)x[1]);
        !          1747:        else affii((GEN)x[1],p1=cgeti(lx1));
        !          1748:        p2=icopy((GEN)x[2]); lx1=lg(x1);
        !          1749:        y=cgetg(l1,t_VEC); f=(x!=x1); i=0;
        !          1750:        while (!gcmp0(p2) && i<=l1-2)
        !          1751:        {
        !          1752:          i++; y[i]=ldvmdii(p1,p2,&p3);
        !          1753:          if (signe(p3)>=0) affii(p3,p1);
        !          1754:           else
        !          1755:          {
        !          1756:            p4=addii(p3,p2); affii(p4,p1); cgiv(p4);
        !          1757:            y[1]=laddsi(-1,(GEN)y[1]);
        !          1758:          }
        !          1759:          cgiv(p3); p4=p1; p1=p2; p2=p4;
        !          1760:          if (f)
        !          1761:           {
        !          1762:            if (i>=lx1) { i--; break; }
        !          1763:             if (!egalii((GEN)y[i],(GEN)x1[i]))
        !          1764:             {
        !          1765:               av=avma;
        !          1766:               if (gcmp1(absi(subii((GEN)x1[i],(GEN)y[i]))))
        !          1767:               {
        !          1768:                 if (i>=lx1-1 || !gcmp1((GEN)x1[i+1]))
        !          1769:                   affii((GEN)x1[i],(GEN)y[i]);
        !          1770:               }
        !          1771:               else i--;
        !          1772:               avma=av; break;
        !          1773:             }
        !          1774:           }
        !          1775:        }
        !          1776:        if (i>=2 && gcmp1((GEN)y[i]))
        !          1777:        {
        !          1778:          cgiv((GEN)y[i]); --i; cgiv((GEN)y[i]);
        !          1779:          y[i]=laddsi(1,(GEN)y[i]);
        !          1780:        }
        !          1781:        setlg(y,i+1); return gerepileupto(l, y);
        !          1782:     }
        !          1783:     err(typeer,"sfcont");
        !          1784:   }
        !          1785:
        !          1786:   switch(tx)
        !          1787:   {
        !          1788:     case t_POL:
        !          1789:       y=cgetg(2,t_VEC); y[1]=lcopy(x); break;
        !          1790:     case t_SER:
        !          1791:       av=avma; p1=gtrunc(x); tetpil=avma;
        !          1792:       y=gerepile(av,tetpil,sfcont(p1,p1,k)); break;
        !          1793:     case t_RFRAC:
        !          1794:     case t_RFRACN:
        !          1795:       av=avma; l1=lgef(x[1]); if (lgef(x[2])>l1) l1=lgef(x[2]);
        !          1796:       if (k>0 && l1>k+1) l1=k+1;
        !          1797:       yp=cgetg(l1,t_VEC); p1=(GEN)x[1]; i=0; p2=(GEN)x[2];
        !          1798:       while (!gcmp0(p2) && i<=l1-2)
        !          1799:       {
        !          1800:        i++; yp[i]=ldivres(p1,p2,&p3);
        !          1801:        p1=p2; p2=p3;
        !          1802:       }
        !          1803:       tetpil=avma; y=cgetg(i+1,t_VEC);
        !          1804:       for (j=1; j<=i; j++) y[j]=lcopy((GEN)yp[j]);
        !          1805:       y=gerepile(av,tetpil,y); break;
        !          1806:     default: err(typeer,"sfcont");
        !          1807:       return NULL; /* not reached */
        !          1808:   }
        !          1809:   return y;
        !          1810: }
        !          1811:
        !          1812: static GEN
        !          1813: sfcont2(GEN b, GEN x, long k)
        !          1814: {
        !          1815:   ulong av = avma;
        !          1816:   long l1 = lg(b), tx = typ(x), i;
        !          1817:   GEN y,p1;
        !          1818:
        !          1819:   if (k)
        !          1820:   {
        !          1821:     if (k>=l1) err(typeer,"sfcont2");
        !          1822:     l1 = k+1;
        !          1823:   }
        !          1824:   y=cgetg(l1,t_VEC);
        !          1825:   if (l1==1) return y;
        !          1826:   if (is_scalar_t(tx))
        !          1827:   {
        !          1828:     if (!is_intreal_t(tx) && !is_frac_t(tx)) err(typeer,"sfcont2");
        !          1829:   }
        !          1830:   else if (tx == t_SER) x = gtrunc(x);
        !          1831:
        !          1832:   if (!gcmp1((GEN)b[1])) x = gmul((GEN)b[1],x);
        !          1833:   i = 2; y[1] = lfloor(x); p1 = gsub(x,(GEN)y[1]);
        !          1834:   for (  ; i<l1 && !gcmp0(p1); i++)
        !          1835:   {
        !          1836:     x = gdiv((GEN)b[i],p1);
        !          1837:     if (tx == t_REAL)
        !          1838:     {
        !          1839:       long e = expo(x);
        !          1840:       if (e>0 && (e>>TWOPOTBITS_IN_LONG)+3 > lg(x)) break;
        !          1841:     }
        !          1842:     y[i] = lfloor(x);
        !          1843:     p1 = gsub(x,(GEN)y[i]);
        !          1844:   }
        !          1845:   setlg(y,i);
        !          1846:   return gerepilecopy(av,y);
        !          1847: }
        !          1848:
        !          1849: GEN
        !          1850: pnqn(GEN x)
        !          1851: {
        !          1852:   long av=avma,tetpil,lx,ly,tx=typ(x),i;
        !          1853:   GEN y,p0,p1,q0,q1,a,b,p2,q2;
        !          1854:
        !          1855:   if (! is_matvec_t(tx)) err(typeer,"pnqn");
        !          1856:   lx=lg(x); if (lx==1) return idmat(2);
        !          1857:   p0=gun; q0=gzero;
        !          1858:   if (tx != t_MAT)
        !          1859:   {
        !          1860:     p1=(GEN)x[1]; q1=gun;
        !          1861:     for (i=2; i<lx; i++)
        !          1862:     {
        !          1863:       a=(GEN)x[i];
        !          1864:       p2=gadd(gmul(a,p1),p0); p0=p1; p1=p2;
        !          1865:       q2=gadd(gmul(a,q1),q0); q0=q1; q1=q2;
        !          1866:     }
        !          1867:   }
        !          1868:   else
        !          1869:   {
        !          1870:     ly=lg(x[1]);
        !          1871:     if (ly==2)
        !          1872:     {
        !          1873:       p1=cgetg(lx,t_VEC); for (i=1; i<lx; i++) p1[i]=mael(x,i,1);
        !          1874:       tetpil=avma; return gerepile(av,tetpil,pnqn(p1));
        !          1875:     }
        !          1876:     if (ly!=3) err(talker,"incorrect size in pnqn");
        !          1877:     p1=gcoeff(x,2,1); q1=gcoeff(x,1,1);
        !          1878:     for (i=2; i<lx; i++)
        !          1879:     {
        !          1880:       a=gcoeff(x,2,i); b=gcoeff(x,1,i);
        !          1881:       p2=gadd(gmul(a,p1),gmul(b,p0)); p0=p1; p1=p2;
        !          1882:       q2=gadd(gmul(a,q1),gmul(b,q0)); q0=q1; q1=q2;
        !          1883:     }
        !          1884:   }
        !          1885:   tetpil=avma; y=cgetg(3,t_MAT);
        !          1886:   p2=cgetg(3,t_COL); y[1]=(long)p2; p2[1]=lcopy(p1); p2[2]=lcopy(q1);
        !          1887:   p2=cgetg(3,t_COL); y[2]=(long)p2; p2[1]=lcopy(p0); p2[2]=lcopy(q0);
        !          1888:   return gerepile(av,tetpil,y);
        !          1889: }
        !          1890:
        !          1891: /* x t_INTMOD. Look for coprime integers a<=A and b<=B, such that a/b = x */
        !          1892: GEN
        !          1893: bestappr_mod(GEN x, GEN A, GEN B)
        !          1894: {
        !          1895:   long i,lx,tx;
        !          1896:   GEN y;
        !          1897:   tx = typ(x);
        !          1898:   switch(tx)
        !          1899:   {
        !          1900:     case t_INTMOD:
        !          1901:     {
        !          1902:       ulong av = avma;
        !          1903:       GEN a,b,d, t = cgetg(3, t_FRAC);
        !          1904:       if (! ratlift((GEN)x[2], (GEN)x[1], &a,&b,A,B)) return NULL;
        !          1905:       if (is_pm1(b)) return icopy_av(a, (GEN)av);
        !          1906:       d = mppgcd(a,b);
        !          1907:       if (!is_pm1(d)) { avma = av; return NULL; }
        !          1908:       cgiv(d);
        !          1909:       t[1] = (long)a;
        !          1910:       t[2] = (long)b; return t;
        !          1911:     }
        !          1912:     case t_COMPLEX: case t_POL: case t_SER: case t_RFRAC:
        !          1913:     case t_RFRACN: case t_VEC: case t_COL: case t_MAT:
        !          1914:       lx = (tx==t_POL)? lgef(x): lg(x); y=cgetg(lx,tx);
        !          1915:       for (i=1; i<lontyp[tx]; i++) y[i]=x[i];
        !          1916:       for (   ; i<lx; i++)
        !          1917:       {
        !          1918:         GEN t = bestappr_mod((GEN)x[i],A,B);
        !          1919:         if (!t) return NULL;
        !          1920:         y[i] = (long)t;
        !          1921:       }
        !          1922:       return y;
        !          1923:   }
        !          1924:   err(typeer,"bestappr0");
        !          1925:   return NULL; /* not reached */
        !          1926: }
        !          1927:
        !          1928: GEN
        !          1929: bestappr(GEN x, GEN k)
        !          1930: {
        !          1931:   ulong av = avma, tetpil;
        !          1932:   long tx,tk=typ(k),lx,i,e;
        !          1933:   GEN p0,p1,p,q0,q1,q,a,y;
        !          1934:
        !          1935:   if (tk != t_INT)
        !          1936:   {
        !          1937:     if (tk != t_REAL && !is_frac_t(tk))
        !          1938:       err(talker,"incorrect bound type in bestappr");
        !          1939:     k = gcvtoi(k,&e);
        !          1940:   }
        !          1941:   if (signe(k) <= 0) k=gun;
        !          1942:   tx=typ(x); if (tx == t_FRACN) x = gred(x);
        !          1943:   switch(tx)
        !          1944:   {
        !          1945:     case t_INT:
        !          1946:       if (av==avma) return icopy(x);
        !          1947:       tetpil=avma; return gerepile(av,tetpil,icopy(x));
        !          1948:
        !          1949:     case t_FRAC:
        !          1950:       if (cmpii((GEN)x[2],k) <= 0)
        !          1951:       {
        !          1952:         if (av==avma) return gcopy(x);
        !          1953:         return gerepilecopy(av,x);
        !          1954:       }
        !          1955:
        !          1956:     case t_REAL:
        !          1957:       p1=gun; p0=gfloor(x); q1=gzero; q0=gun; a=p0;
        !          1958:       while (gcmp(q0,k)<=0)
        !          1959:       {
        !          1960:        x = gsub(x,a);
        !          1961:        if (gcmp0(x)) { p1=p0; q1=q0; break; }
        !          1962:
        !          1963:        x = ginv(x); a = (gcmp(x,k)<0)? gfloor(x): k;
        !          1964:        p = addii(mulii(a,p0),p1); p1=p0; p0=p;
        !          1965:         q = addii(mulii(a,q0),q1); q1=q0; q0=q;
        !          1966:       }
        !          1967:       tetpil=avma; return gerepile(av,tetpil,gdiv(p1,q1));
        !          1968:
        !          1969:    case t_COMPLEX: case t_POL: case t_SER: case t_RFRAC:
        !          1970:    case t_RFRACN: case t_VEC: case t_COL: case t_MAT:
        !          1971:       lx = (tx==t_POL)? lgef(x): lg(x); y=cgetg(lx,tx);
        !          1972:       for (i=1; i<lontyp[tx]; i++) y[i]=x[i];
        !          1973:       for (   ; i<lx; i++) y[i]=(long)bestappr((GEN)x[i],k);
        !          1974:       return y;
        !          1975:   }
        !          1976:   err(typeer,"bestappr");
        !          1977:   return NULL; /* not reached */
        !          1978: }
        !          1979:
        !          1980: GEN
        !          1981: bestappr0(GEN x, GEN a, GEN b)
        !          1982: {
        !          1983:   ulong av;
        !          1984:   GEN t;
        !          1985:   if (!b) return bestappr(x,a);
        !          1986:   av = avma;
        !          1987:   t = bestappr_mod(x,a,b);
        !          1988:   if (!t) { avma = av; return stoi(-1); }
        !          1989:   return t;
        !          1990: }
        !          1991:
        !          1992: /***********************************************************************/
        !          1993: /**                                                                   **/
        !          1994: /**         FUNDAMENTAL UNIT AND REGULATOR (QUADRATIC FIELDS)         **/
        !          1995: /**                                                                   **/
        !          1996: /***********************************************************************/
        !          1997:
        !          1998: GEN
        !          1999: gfundunit(GEN x)
        !          2000: {
        !          2001:   return garith_proto(fundunit,x,1);
        !          2002: }
        !          2003:
        !          2004: static GEN
        !          2005: get_quad(GEN f, GEN pol, long r)
        !          2006: {
        !          2007:   GEN y, c=(GEN)f[2], p1=(GEN)c[1], q1=(GEN)c[2];
        !          2008:   y=cgetg(4,t_QUAD); y[1]=(long)pol;
        !          2009:   y[2]=r? lsubii(p1,q1): (long)p1;
        !          2010:   y[3]=(long)q1; return y;
        !          2011: }
        !          2012:
        !          2013: /* replace f by f * [a,1; 1,0] */
        !          2014: static void
        !          2015: update_f(GEN f, GEN a)
        !          2016: {
        !          2017:   GEN p1;
        !          2018:   p1=gcoeff(f,1,1);
        !          2019:   coeff(f,1,1)=laddii(mulii(a,p1), gcoeff(f,1,2));
        !          2020:   coeff(f,1,2)=(long)p1;
        !          2021:
        !          2022:   p1=gcoeff(f,2,1);
        !          2023:   coeff(f,2,1)=laddii(mulii(a,p1), gcoeff(f,2,2));
        !          2024:   coeff(f,2,2)=(long)p1;
        !          2025: }
        !          2026:
        !          2027: GEN
        !          2028: fundunit(GEN x)
        !          2029: {
        !          2030:   long av = avma, av2,tetpil,lim,r,flp,flq;
        !          2031:   GEN pol,y,a,u,v,u1,v1,sqd,f;
        !          2032:
        !          2033:   if (typ(x) != t_INT) err(arither1);
        !          2034:   if (signe(x)<=0) err(arither2);
        !          2035:   r=mod4(x); if (r==2 || r==3) err(funder2,"fundunit");
        !          2036:
        !          2037:   sqd=racine(x); av2=avma; lim=stack_lim(av2,2);
        !          2038:   a = shifti(addsi(r,sqd),-1);
        !          2039:   f=cgetg(3,t_MAT); f[1]=lgetg(3,t_COL); f[2]=lgetg(3,t_COL);
        !          2040:   coeff(f,1,1)=(long)a; coeff(f,1,2)=un;
        !          2041:   coeff(f,2,1)=un;      coeff(f,2,2)=zero;
        !          2042:   v = gdeux; u = stoi(r);
        !          2043:   for(;;)
        !          2044:   {
        !          2045:     u1=subii(mulii(a,v),u);       flp=egalii(u,u1); u=u1;
        !          2046:     v1=divii(subii(x,sqri(u)),v); flq=egalii(v,v1); v=v1;
        !          2047:     if (flq) break; a = divii(addii(sqd,u),v);
        !          2048:     if (flp) break; update_f(f,a);
        !          2049:     if (low_stack(lim, stack_lim(av2,2)))
        !          2050:     {
        !          2051:       GEN *gptr[4]; gptr[0]=&a; gptr[1]=&f; gptr[2]=&u; gptr[3]=&v;
        !          2052:       if(DEBUGMEM>1) err(warnmem,"fundunit");
        !          2053:       gerepilemany(av2,gptr,4);
        !          2054:     }
        !          2055:   }
        !          2056:   pol = quadpoly(x); y = get_quad(f,pol,r);
        !          2057:   if (!flq) v1 = y; else { update_f(f,a); v1 = get_quad(f,pol,r); }
        !          2058:
        !          2059:   u1=gconj(y); tetpil=avma; y=gdiv(v1,u1);
        !          2060:   if (signe(y[3]) < 0) { tetpil=avma; y=gneg(y); }
        !          2061:   return gerepile(av,tetpil,y);
        !          2062: }
        !          2063:
        !          2064: GEN
        !          2065: gregula(GEN x, long prec)
        !          2066: {
        !          2067:   return garith_proto2gs(regula,x,prec);
        !          2068: }
        !          2069:
        !          2070: GEN
        !          2071: regula(GEN x, long prec)
        !          2072: {
        !          2073:   long av = avma,av2,lim,r,fl,rexp;
        !          2074:   GEN reg,rsqd,y,u,v,u1,v1, sqd = racine(x);
        !          2075:
        !          2076:   if (signe(x)<=0) err(arither2);
        !          2077:   r=mod4(x); if (r==2 || r==3) err(funder2,"regula");
        !          2078:
        !          2079:   rsqd = gsqrt(x,prec);
        !          2080:   if (egalii(sqri(sqd),x)) err(talker,"square argument in regula");
        !          2081:
        !          2082:   rexp=0; reg=cgetr(prec); affsr(2,reg);
        !          2083:   av2=avma; lim = stack_lim(av2,2);
        !          2084:   u = stoi(r); v = gdeux;
        !          2085:   for(;;)
        !          2086:   {
        !          2087:     u1 = subii(mulii(divii(addii(u,sqd),v), v), u);
        !          2088:     v1 = divii(subii(x,sqri(u1)),v); fl = egalii(v,v1);
        !          2089:     if (fl || egalii(u,u1)) break;
        !          2090:     reg = mulrr(reg, divri(addir(u1,rsqd),v));
        !          2091:     rexp += expo(reg); setexpo(reg,0);
        !          2092:     u = u1; v = v1;
        !          2093:     if (rexp & ~EXPOBITS) err(muler4);
        !          2094:     if (low_stack(lim, stack_lim(av2,2)))
        !          2095:     {
        !          2096:       GEN *gptr[3]; gptr[0]=&reg; gptr[1]=&u; gptr[2]=&v;
        !          2097:       if(DEBUGMEM>1) err(warnmem,"regula");
        !          2098:       gerepilemany(av2,gptr,3);
        !          2099:     }
        !          2100:   }
        !          2101:   reg = gsqr(reg); setexpo(reg,expo(reg)-1);
        !          2102:   if (fl) reg = mulrr(reg, divri(addir(u1,rsqd),v));
        !          2103:   y = mplog(divri(reg,v));
        !          2104:   if (rexp)
        !          2105:   {
        !          2106:     u1 = mulsr(rexp, glog(gdeux, prec));
        !          2107:     setexpo(u1, expo(u1)+1);
        !          2108:     y = addrr(y,u1);
        !          2109:   }
        !          2110:   return gerepileupto(av, y);
        !          2111: }
        !          2112:
        !          2113: /*************************************************************************/
        !          2114: /**                                                                     **/
        !          2115: /**                            CLASS NUMBER                             **/
        !          2116: /**                                                                     **/
        !          2117: /*************************************************************************/
        !          2118:
        !          2119: static GEN
        !          2120: gclassno(GEN x)
        !          2121: {
        !          2122:   return garith_proto(classno,x,1);
        !          2123: }
        !          2124:
        !          2125: static GEN
        !          2126: gclassno2(GEN x)
        !          2127: {
        !          2128:   return garith_proto(classno2,x,1);
        !          2129: }
        !          2130:
        !          2131: GEN
        !          2132: qfbclassno0(GEN x,long flag)
        !          2133: {
        !          2134:   switch(flag)
        !          2135:   {
        !          2136:     case 0: return gclassno(x);
        !          2137:     case 1: return gclassno2(x);
        !          2138:     default: err(flagerr,"qfbclassno");
        !          2139:   }
        !          2140:   return NULL; /* not reached */
        !          2141: }
        !          2142:
        !          2143: /* f^h = 1, return order(f) */
        !          2144: static GEN
        !          2145: find_order(GEN f, GEN h)
        !          2146: {
        !          2147:   GEN fh, p,e;
        !          2148:   long i,j,lim;
        !          2149:
        !          2150:   p = decomp(h);
        !          2151:   e =(GEN)p[2];
        !          2152:   p =(GEN)p[1];
        !          2153:   for (i=1; i<lg(p); i++)
        !          2154:   {
        !          2155:     lim = itos((GEN)e[i]);
        !          2156:     for (j=1; j<=lim; j++)
        !          2157:     {
        !          2158:       GEN p1 = divii(h,(GEN)p[i]);
        !          2159:       fh = powgi(f,p1);
        !          2160:       if (!is_pm1(fh[1])) break;
        !          2161:       h = p1;
        !          2162:     }
        !          2163:   }
        !          2164:   return h;
        !          2165: }
        !          2166:
        !          2167: static GEN
        !          2168: end_classno(GEN h, GEN hin, GEN forms, long lform)
        !          2169: {
        !          2170:   long i,com;
        !          2171:   GEN a,b,p1,q,fh,fg, f = (GEN)forms[0];
        !          2172:
        !          2173:   h = find_order(f,h); /* H = <f> */
        !          2174:   q = ground(gdiv(hin,h)); /* approximate order of G/H */
        !          2175:   for (i=1; i < lform; i++)
        !          2176:   {
        !          2177:     long av = avma;
        !          2178:     fg = powgi((GEN)forms[i], h);
        !          2179:     fh = powgi(fg, q);
        !          2180:     a = (GEN)fh[1];
        !          2181:     if (is_pm1(a)) continue;
        !          2182:     b = (GEN)fh[2]; p1 = fg;
        !          2183:     for (com=1; ; com++)
        !          2184:     {
        !          2185:       if (egalii((GEN)p1[1], a) && absi_equal((GEN)p1[2], b)) break;
        !          2186:       p1 = gmul(p1,fg);
        !          2187:     }
        !          2188:     if (signe(p1[2]) == signe(b)) com = -com;
        !          2189:     /* f_i ^ h(q+com) = 1 */
        !          2190:     avma = av; q = addsi(com,q);
        !          2191:   }
        !          2192:   return mulii(q,h);
        !          2193: }
        !          2194:
        !          2195: static GEN
        !          2196: to_form(GEN x, long f)
        !          2197: {
        !          2198:   return redimag(primeform(x, stoi(f), 0));
        !          2199: }
        !          2200:
        !          2201: static long
        !          2202: two_rank(GEN x)
        !          2203: {
        !          2204:   GEN p = (GEN)decomp(absi(x))[1];
        !          2205:   long l = lg(p)-1;
        !          2206: #if 0 /* positive disc not needed */
        !          2207:   if (signe(x) > 0)
        !          2208:   {
        !          2209:     long i;
        !          2210:     for (i=1; i<=l; i++)
        !          2211:       if (mod4((GEN)p[i]) == 3) { l--; break; }
        !          2212:   }
        !          2213: #endif
        !          2214:   return l-1;
        !          2215: }
        !          2216:
        !          2217: #define MAXFORM 11
        !          2218: #define _low(x) (__x=(GEN)x, modBIL(__x))
        !          2219:
        !          2220: /* h(x) for x<0 using Baby Step/Giant Step.
        !          2221:  * Assumes G is not too far from being cyclic.
        !          2222:  *
        !          2223:  * Compute G^2 instead of G so as to kill most of the non-cyclicity */
        !          2224: GEN
        !          2225: classno(GEN x)
        !          2226: {
        !          2227:   long av = avma, av2,c,lforms,k,l,i,j,j1,j2,lim,com,s, forms[MAXFORM];
        !          2228:   long r2;
        !          2229:   GEN a,b,count,index,tabla,tablb,hash,p1,p2,hin,h,f,fh,fg,ftest;
        !          2230:   GEN __x;
        !          2231:   byteptr p = diffptr;
        !          2232:
        !          2233:   if (typ(x) != t_INT) err(arither1);
        !          2234:   s=signe(x); if (s>=0) return classno2(x);
        !          2235:
        !          2236:   k=mod4(x); if (k==1 || k==2) err(funder2,"classno");
        !          2237:   if (gcmpgs(x,-12) >= 0) return gun;
        !          2238:
        !          2239:   p2 = gsqrt(absi(x),DEFAULTPREC);
        !          2240:   p1 = divrr(p2,mppi(DEFAULTPREC));
        !          2241:   p2 = gtrunc(shiftr(gsqrt(p2,DEFAULTPREC),1));
        !          2242:   s = 1000;
        !          2243:   if (signe(p2))
        !          2244:   {
        !          2245:     if (is_bigint(p2)) err(talker,"discriminant too big in classno");
        !          2246:     s = itos(p2); if (s < 1000) s = 1000;
        !          2247:   }
        !          2248:   r2 = two_rank(x);
        !          2249:   c=lforms=0;
        !          2250:   while (c <= s && *p)
        !          2251:   {
        !          2252:     c += *p++; k = krogs(x,c);
        !          2253:     if (!k) continue;
        !          2254:
        !          2255:     av2 = avma;
        !          2256:     if (k > 0)
        !          2257:     {
        !          2258:       divrsz(mulsr(c,p1),c-1, p1);
        !          2259:       if (lforms < MAXFORM && c > 2) forms[lforms++] = c;
        !          2260:     }
        !          2261:     else divrsz(mulsr(c,p1),c+1, p1);
        !          2262:     avma = av2;
        !          2263:   }
        !          2264:   h = hin = shifti(ground(p1), -r2);
        !          2265:   s = 2*itos(gceil(gpui(p1,ginv(stoi(4)),DEFAULTPREC)));
        !          2266:   if (s>=10000) s=10000;
        !          2267:
        !          2268:   count = new_chunk(256); for (i=0; i<=255; i++) count[i]=0;
        !          2269:   index = new_chunk(257);
        !          2270:   tabla = new_chunk(10000);
        !          2271:   tablb = new_chunk(10000);
        !          2272:   hash  = new_chunk(10000);
        !          2273:   f = gsqr(to_form(x, forms[0]));
        !          2274:   p1 = fh = powgi(f, h);
        !          2275:   for (i=0; i<s; i++)
        !          2276:   {
        !          2277:     tabla[i] = _low(p1[1]);
        !          2278:     tablb[i] = _low(p1[2]);
        !          2279:     count[tabla[i]&255]++; p1=compimag(p1,f);
        !          2280:   }
        !          2281:   index[0]=0; for (i=0; i<=254; i++) index[i+1] = index[i]+count[i];
        !          2282:   for (i=0; i<s; i++) hash[index[tabla[i]&255]++]=i;
        !          2283:   index[0]=0; for (i=0; i<=255; i++) index[i+1] = index[i]+count[i];
        !          2284:
        !          2285:   fg=gpuigs(f,s); av2=avma; lim=stack_lim(av2,2);
        !          2286:   ftest=gpuigs(p1,0);
        !          2287:   for (com=0; ; com++)
        !          2288:   {
        !          2289:     a = (GEN)ftest[1]; k = _low(a);
        !          2290:     b = (GEN)ftest[2]; l = _low(b); j = k&255;
        !          2291:     for (j1=index[j]; j1 < index[j+1]; j1++)
        !          2292:     {
        !          2293:       j2 = hash[j1];
        !          2294:       if (tabla[j2] == k && tablb[j2] == l)
        !          2295:       {
        !          2296:         p1 = gmul(gpuigs(f,j2),fh);
        !          2297:         if (egalii((GEN)p1[1], a) && absi_equal((GEN)p1[2], b))
        !          2298:         { /* p1 = ftest or ftest^(-1), we are done */
        !          2299:           if (signe(p1[2]) == signe(b)) com = -com;
        !          2300:           h = addii(addis(h,j2), mulss(s,com));
        !          2301:           forms[0] = (long)f;
        !          2302:           for (i=1; i<lforms; i++)
        !          2303:             forms[i] = (long)gsqr(to_form(x, forms[i]));
        !          2304:           h = end_classno(h,hin,forms,lforms);
        !          2305:           return gerepileuptoint(av, shifti(h, r2));
        !          2306:         }
        !          2307:       }
        !          2308:     }
        !          2309:     ftest = gmul(ftest,fg);
        !          2310:     if (is_pm1(ftest[1])) err(impl,"classno with too small order");
        !          2311:     if (low_stack(lim, stack_lim(av2,2))) ftest = gerepileupto(av2,ftest);
        !          2312:   }
        !          2313: }
        !          2314:
        !          2315: /* use Euler products */
        !          2316: GEN
        !          2317: classno2(GEN x)
        !          2318: {
        !          2319:   long av=avma,tetpil,n,i,k,s=signe(x),fl2;
        !          2320:   GEN p1,p2,p3,p4,p5,p7,p8,pi4,reg,logd,d,fd;
        !          2321:
        !          2322:   if (typ(x) != t_INT) err(arither1);
        !          2323:   if (!s) err(arither2);
        !          2324:   if (s<0 && gcmpgs(x,-12) >= 0) return gun;
        !          2325:
        !          2326:   p1=auxdecomp(absi(x),1); p2=(GEN)p1[2]; p1=(GEN)p1[1];
        !          2327:   n=lg(p1); d=gun;
        !          2328:   for (i=1; i<n; i++)
        !          2329:     if (mod2((GEN)p2[i])) d=mulii(d,(GEN)p1[i]);
        !          2330:   fl2 = (mod4(x)==0); /* 4 | x */
        !          2331:   if (mod4(d) != 2-s)
        !          2332:   {
        !          2333:     if (!fl2) err(funder2,"classno2");
        !          2334:     d = shifti(d,2);
        !          2335:   }
        !          2336:   else fl2=0;
        !          2337:   p8=gun; fd = (s<0)? negi(d): d; /* d = abs(fd) */
        !          2338:   for (i=1; i<n; i++)
        !          2339:   {
        !          2340:     k=itos((GEN)p2[i]); p4=(GEN)p1[i];
        !          2341:     if (fl2 && i==1) k -= 2; /* p4 = 2 */
        !          2342:     if (k>=2)
        !          2343:     {
        !          2344:       p8=mulii(p8,subis(p4,kronecker(fd,p4)));
        !          2345:       if (k>=4) p8=mulii(p8,gpuigs(p4,(k>>1)-1));
        !          2346:     }
        !          2347:   }
        !          2348:   if (s<0 && lgefint(d)==3)
        !          2349:   {
        !          2350:     switch(d[2])
        !          2351:     {
        !          2352:       case 4: p8=gdivgs(p8,2); break;
        !          2353:       case 3: p8=gdivgs(p8,3); break;
        !          2354:     }
        !          2355:     if (d[2] < 12) /* |fd| < 12*/
        !          2356:       { tetpil=avma; return gerepile(av,tetpil,icopy(p8)); }
        !          2357:   }
        !          2358:
        !          2359:   pi4 = mppi(DEFAULTPREC); logd = glog(d,DEFAULTPREC);
        !          2360:   p1 = gsqrt(gdiv(gmul(d,logd),gmul2n(pi4,1)),DEFAULTPREC);
        !          2361:   p4 = divri(pi4,d); p7 = ginv(mpsqrt(pi4));
        !          2362:   if (s > 0)
        !          2363:   {
        !          2364:     reg = regula(d,DEFAULTPREC);
        !          2365:     p2 = gsubsg(1, gmul2n(gdiv(glog(reg,DEFAULTPREC),logd),1));
        !          2366:     p3 = gsqrt(gdivsg(2,logd),DEFAULTPREC);
        !          2367:     if (gcmp(p2,p3)>=0) p1 = gmul(p2,p1);
        !          2368:   }
        !          2369:   else reg = NULL; /* for gcc -Wall */
        !          2370:   p1 = gtrunc(p1); n=p1[2];
        !          2371:   if (lgefint(p1)!=3 || n<0)
        !          2372:     err(talker,"discriminant too large in classno");
        !          2373:
        !          2374:   p1 = gsqrt(d,DEFAULTPREC); p3 = gzero;
        !          2375:   if (s > 0)
        !          2376:   {
        !          2377:     for (i=1; i<=n; i++)
        !          2378:     {
        !          2379:       k=krogs(fd,i);
        !          2380:       if (k)
        !          2381:       {
        !          2382:        p2 = mulir(mulss(i,i),p4);
        !          2383:        p5 = subsr(1,mulrr(p7,incgam3(ghalf,p2,DEFAULTPREC)));
        !          2384:        p5 = addrr(divrs(mulrr(p1,p5),i),eint1(p2,DEFAULTPREC));
        !          2385:        p3 = (k>0)? addrr(p3,p5): subrr(p3,p5);
        !          2386:       }
        !          2387:     }
        !          2388:     p3 = shiftr(divrr(p3,reg),-1);
        !          2389:     if (!egalii(x,fd)) /* x != p3 */
        !          2390:       p8 = gdiv(p8,ground(gdiv(regula(x,DEFAULTPREC),reg)));
        !          2391:   }
        !          2392:   else
        !          2393:   {
        !          2394:     p1 = gdiv(p1,pi4);
        !          2395:     for (i=1; i<=n; i++)
        !          2396:     {
        !          2397:       k=krogs(fd,i);
        !          2398:       if (k)
        !          2399:       {
        !          2400:        p2=mulir(mulss(i,i),p4);
        !          2401:        p5=subsr(1,mulrr(p7,incgam3(ghalf,p2,DEFAULTPREC)));
        !          2402:        p5=addrr(p5,divrr(divrs(p1,i),mpexp(p2)));
        !          2403:        p3 = (k>0)? addrr(p3,p5): subrr(p3,p5);
        !          2404:       }
        !          2405:     }
        !          2406:   }
        !          2407:   p3=ground(p3); tetpil=avma;
        !          2408:   return gerepile(av,tetpil,mulii(p8,p3));
        !          2409: }
        !          2410:
        !          2411: GEN
        !          2412: hclassno(GEN x)
        !          2413: {
        !          2414:   long d,a,b,h,b2,f;
        !          2415:
        !          2416:   d= -itos(x); if (d>0 || (d & 3) > 1) return gzero;
        !          2417:   if (!d) return gdivgs(gun,-12);
        !          2418:   if (-d > (VERYBIGINT>>1))
        !          2419:     err(talker,"discriminant too big in hclassno. Use quadclassunit");
        !          2420:   h=0; b=d&1; b2=(b-d)>>2; f=0;
        !          2421:   if (!b)
        !          2422:   {
        !          2423:     for (a=1; a*a<b2; a++)
        !          2424:       if (b2%a == 0) h++;
        !          2425:     f = (a*a==b2); b=2; b2=(4-d)>>2;
        !          2426:   }
        !          2427:   while (b2*3+d<0)
        !          2428:   {
        !          2429:     if (b2%b == 0) h++;
        !          2430:     for (a=b+1; a*a<b2; a++)
        !          2431:       if (b2%a == 0) h+=2;
        !          2432:     if (a*a==b2) h++;
        !          2433:     b+=2; b2=(b*b-d)>>2;
        !          2434:   }
        !          2435:   if (b2*3+d==0)
        !          2436:   {
        !          2437:     GEN y = cgetg(3,t_FRAC);
        !          2438:     y[1]=lstoi(3*h+1); y[2]=lstoi(3); return y;
        !          2439:   }
        !          2440:   if (f) return gaddsg(h,ghalf);
        !          2441:   return stoi(h);
        !          2442: }

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