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

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

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

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