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

Annotation of OpenXM_contrib/pari/src/basemath/arith1.c, Revision 1.1.1.1

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

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