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

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

1.2     ! noro        1: /* $Id: base3.c,v 1.87 2002/09/08 17:09:39 karim Exp $
1.1       noro        2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /*******************************************************************/
                     17: /*                                                                 */
                     18: /*                       BASIC NF OPERATIONS                       */
                     19: /*                                                                 */
                     20: /*******************************************************************/
                     21: #include "pari.h"
1.2     ! noro       22: extern GEN u_FpM_deplin(GEN x, ulong p);
        !            23: extern GEN u_FpM_inv(GEN a, ulong p);
1.1       noro       24: extern GEN famat_ideallog(GEN nf, GEN g, GEN e, GEN bid);
                     25: extern GEN famat_to_nf_modidele(GEN nf, GEN g, GEN e, GEN bid);
                     26: extern GEN vconcat(GEN A, GEN B);
                     27:
                     28: /*******************************************************************/
                     29: /*                                                                 */
                     30: /*                OPERATIONS OVER NUMBER FIELD ELEMENTS.           */
                     31: /*     These are always represented as column vectors over the     */
                     32: /*     integral basis nf[7]                                        */
                     33: /*                                                                 */
                     34: /*******************************************************************/
                     35:
                     36: int
                     37: isnfscalar(GEN x)
                     38: {
                     39:   long lx=lg(x),i;
                     40:
1.2     ! noro       41:   if (typ(x) != t_COL) return 0;
1.1       noro       42:   for (i=2; i<lx; i++)
                     43:     if (!gcmp0((GEN)x[i])) return 0;
                     44:   return 1;
                     45: }
                     46:
                     47: static GEN
                     48: scal_mul(GEN nf, GEN x, GEN y, long ty)
                     49: {
1.2     ! noro       50:   gpmem_t av=avma, tetpil;
1.1       noro       51:   GEN p1;
                     52:
                     53:   if (!is_extscalar_t(ty))
                     54:   {
                     55:     if (ty!=t_COL) err(typeer,"nfmul");
                     56:     y = gmul((GEN)nf[7],y);
                     57:   }
                     58:   p1 = gmul(x,y); tetpil=avma;
                     59:   return gerepile(av,tetpil,algtobasis(nf,p1));
                     60: }
                     61:
                     62: static GEN
                     63: get_tab(GEN nf, long *N)
                     64: {
                     65:   GEN tab = (typ(nf) == t_MAT)? nf: (GEN)nf[9];
                     66:   *N = lg(tab[1])-1; return tab;
                     67: }
                     68:
                     69: GEN
1.2     ! noro       70: mul_by_tab(GEN tab, GEN x, GEN y)
1.1       noro       71: {
1.2     ! noro       72:   gpmem_t av;
        !            73:   long i,j,k,N;
        !            74:   GEN s,v,c,p1;
1.1       noro       75:
1.2     ! noro       76:   N = lg(x)-1;
1.1       noro       77:   v=cgetg(N+1,t_COL); av=avma;
                     78:   for (k=1; k<=N; k++)
                     79:   {
                     80:     if (k == 1)
                     81:       s = gmul((GEN)x[1],(GEN)y[1]);
                     82:     else
                     83:       s = gadd(gmul((GEN)x[1],(GEN)y[k]),
                     84:                gmul((GEN)x[k],(GEN)y[1]));
                     85:     for (i=2; i<=N; i++)
                     86:     {
                     87:       c=gcoeff(tab,k,(i-1)*N+i);
                     88:       if (signe(c))
                     89:       {
                     90:         p1 = gmul((GEN)x[i],(GEN)y[i]);
                     91:        if (!gcmp1(c)) p1 = gmul(p1,c);
                     92:        s = gadd(s, p1);
                     93:       }
                     94:       for (j=i+1; j<=N; j++)
                     95:       {
                     96:        c=gcoeff(tab,k,(i-1)*N+j);
                     97:        if (signe(c))
                     98:        {
                     99:           p1 = gadd(gmul((GEN)x[i],(GEN)y[j]),
                    100:                     gmul((GEN)x[j],(GEN)y[i]));
                    101:          if (!gcmp1(c)) p1 = gmul(p1,c);
                    102:           s = gadd(s, p1);
                    103:        }
                    104:       }
                    105:     }
                    106:     v[k]=(long)gerepileupto(av,s); av=avma;
                    107:   }
                    108:   return v;
                    109: }
                    110:
1.2     ! noro      111: /* product of x and y in nf */
        !           112: GEN
        !           113: element_mul(GEN nf, GEN x, GEN y)
        !           114: {
        !           115:   long N,tx,ty;
        !           116:   GEN tab;
        !           117:
        !           118:   if (x == y) return element_sqr(nf,x);
        !           119:
        !           120:   tx=typ(x); ty=typ(y);
        !           121:   nf=checknf(nf);
        !           122:   if (tx==t_POLMOD) x=checknfelt_mod(nf,x,"element_mul");
        !           123:   if (ty==t_POLMOD) y=checknfelt_mod(nf,y,"element_mul");
        !           124:   if (is_extscalar_t(tx)) return scal_mul(nf,x,y,ty);
        !           125:   if (is_extscalar_t(ty)) return scal_mul(nf,y,x,tx);
        !           126:   if (tx != t_COL || ty != t_COL) err(typeer,"element_mul");
        !           127:   if (isnfscalar(x)) return gmul((GEN)x[1],y);
        !           128:   if (isnfscalar(y)) return gmul((GEN)y[1],x);
        !           129:
        !           130:   tab = get_tab(nf, &N);
        !           131:   return mul_by_tab(tab,x,y);
        !           132: }
        !           133:
1.1       noro      134: /* inverse of x in nf */
                    135: GEN
                    136: element_inv(GEN nf, GEN x)
                    137: {
1.2     ! noro      138:   gpmem_t av=avma;
        !           139:   long i,N,tx=typ(x);
1.1       noro      140:   GEN p1,p;
                    141:
                    142:   nf=checknf(nf); N=degpol(nf[1]);
                    143:   if (is_extscalar_t(tx))
                    144:   {
1.2     ! noro      145:     if (tx==t_POLMOD) (void)checknfelt_mod(nf,x,"element_inv");
1.1       noro      146:     else if (tx==t_POL) x=gmodulcp(x,(GEN)nf[1]);
                    147:     return gerepileupto(av, algtobasis(nf, ginv(x)));
                    148:   }
                    149:   if (isnfscalar(x))
                    150:   {
                    151:     p1=cgetg(N+1,t_COL); p1[1]=linv((GEN)x[1]);
                    152:     for (i=2; i<=N; i++) p1[i]=lcopy((GEN)x[i]);
                    153:     return p1;
                    154:   }
1.2     ! noro      155:   if (tx != t_COL) err(typeer,"element_inv");
1.1       noro      156:   p = NULL;
                    157:   for (i=1; i<=N; i++)
                    158:     if (typ(x[i])==t_INTMOD)
                    159:     {
                    160:       p = gmael(x,i,1);
                    161:       x = lift(x); break;
                    162:     }
1.2     ! noro      163:   p1 = QX_invmod(gmul((GEN)nf[7],x), (GEN)nf[1]);
        !           164:   p1 = algtobasis_i(nf,p1);
1.1       noro      165:
                    166:   if (p) p1 = FpV(p1, p);
                    167:   return gerepileupto(av,p1);
                    168: }
                    169:
                    170: /* quotient of x and y in nf */
                    171: GEN
                    172: element_div(GEN nf, GEN x, GEN y)
                    173: {
1.2     ! noro      174:   gpmem_t av=avma;
        !           175:   long i,N,tx=typ(x),ty=typ(y);
1.1       noro      176:   GEN p1,p;
                    177:
                    178:   nf=checknf(nf); N=degpol(nf[1]);
1.2     ! noro      179:   if (tx==t_POLMOD) (void)checknfelt_mod(nf,x,"element_div");
1.1       noro      180:   else if (tx==t_POL) x=gmodulcp(x,(GEN)nf[1]);
                    181:
1.2     ! noro      182:   if (ty==t_POLMOD) (void)checknfelt_mod(nf,y,"element_div");
1.1       noro      183:   else if (ty==t_POL) y=gmodulcp(y,(GEN)nf[1]);
                    184:
                    185:   if (is_extscalar_t(tx))
                    186:   {
                    187:     if (is_extscalar_t(ty)) p1=gdiv(x,y);
                    188:     else
                    189:     {
                    190:       if (ty!=t_COL) err(typeer,"nfdiv");
                    191:       p1=gdiv(x,gmodulcp(gmul((GEN)nf[7],y),(GEN)nf[1]));
                    192:     }
                    193:     return gerepileupto(av, algtobasis(nf,p1));
                    194:   }
                    195:   if (is_extscalar_t(ty))
                    196:   {
                    197:     if (tx!=t_COL) err(typeer,"nfdiv");
                    198:     p1=gdiv(gmodulcp(gmul((GEN)nf[7],x),(GEN)nf[1]),y);
                    199:     return gerepileupto(av, algtobasis(nf,p1));
                    200:   }
1.2     ! noro      201:   if (tx != t_COL || ty != t_COL) err(typeer,"element_div");
1.1       noro      202:
                    203:   if (isnfscalar(y)) return gdiv(x,(GEN)y[1]);
                    204:   if (isnfscalar(x))
                    205:   {
                    206:     p1=element_inv(nf,y);
                    207:     return gerepileupto(av, gmul((GEN)x[1],p1));
                    208:   }
                    209:
                    210:   p = NULL;
                    211:   for (i=1; i<=N; i++)
                    212:     if (typ(x[i])==t_INTMOD)
                    213:     {
                    214:       p = gmael(x,i,1);
                    215:       x = lift(x); break;
                    216:     }
                    217:   for (i=1; i<=N; i++)
                    218:     if (typ(y[i])==t_INTMOD)
                    219:     {
                    220:       p1 = gmael(y,i,1);
                    221:       if (p && !egalii(p,p1))
                    222:         err(talker,"inconsistant prime moduli in element_inv");
                    223:       y = lift(y); break;
                    224:     }
                    225:
1.2     ! noro      226:   p1 = gmul(gmul((GEN)nf[7],x), QX_invmod(gmul((GEN)nf[7],y), (GEN)nf[1]));
        !           227:   p1 = algtobasis_i(nf, gres(p1, (GEN)nf[1]));
1.1       noro      228:   if (p) p1 = FpV(p1,p);
                    229:   return gerepileupto(av,p1);
                    230: }
                    231:
                    232: /* product of INTEGERS (i.e vectors with integral coeffs) x and y in nf */
                    233: GEN
                    234: element_muli(GEN nf, GEN x, GEN y)
                    235: {
1.2     ! noro      236:   gpmem_t av;
        !           237:   long i,j,k,N;
1.1       noro      238:   GEN p1,s,v,c,tab;
                    239:
                    240:   tab = get_tab(nf, &N);
1.2     ! noro      241:   if (typ(x) != t_COL || lg(x) != N+1
        !           242:    || typ(y) != t_COL || lg(y) != N+1) err(typeer,"element_muli");
1.1       noro      243:   v=cgetg(N+1,t_COL); av=avma;
                    244:   for (k=1; k<=N; k++)
                    245:   {
                    246:     if (k == 1)
                    247:       s = mulii((GEN)x[1],(GEN)y[1]);
                    248:     else
                    249:       s = addii(mulii((GEN)x[1],(GEN)y[k]),
                    250:                 mulii((GEN)x[k],(GEN)y[1]));
                    251:     for (i=2; i<=N; i++)
                    252:     {
                    253:       c=gcoeff(tab,k,(i-1)*N+i);
                    254:       if (signe(c))
                    255:       {
                    256:         p1 = mulii((GEN)x[i],(GEN)y[i]);
                    257:         if (!gcmp1(c)) p1 = mulii(p1,c);
                    258:        s = addii(s,p1);
                    259:       }
                    260:       for (j=i+1; j<=N; j++)
                    261:       {
                    262:        c=gcoeff(tab,k,(i-1)*N+j);
                    263:        if (signe(c))
                    264:        {
                    265:           p1 = addii(mulii((GEN)x[i],(GEN)y[j]),
                    266:                      mulii((GEN)x[j],(GEN)y[i]));
                    267:           if (!gcmp1(c)) p1 = mulii(p1,c);
                    268:          s = addii(s,p1);
                    269:        }
                    270:       }
                    271:     }
1.2     ! noro      272:     v[k] = lpileuptoint(av,s); av = avma;
1.1       noro      273:   }
                    274:   return v;
                    275: }
                    276:
                    277: /* product of INTEGERS (i.e vectors with integral coeffs) x and y in nf */
                    278: GEN
                    279: element_sqri(GEN nf, GEN x)
                    280: {
                    281:   GEN p1,s,v,c,tab;
1.2     ! noro      282:   gpmem_t av;
        !           283:   long i,j,k,N;
1.1       noro      284:
                    285:   tab = get_tab(nf, &N);
                    286:
                    287:   v=cgetg(N+1,t_COL); av=avma;
                    288:   for (k=1; k<=N; k++)
                    289:   {
                    290:     if (k == 1)
                    291:       s = sqri((GEN)x[1]);
                    292:     else
                    293:       s = shifti(mulii((GEN)x[1],(GEN)x[k]), 1);
                    294:     for (i=2; i<=N; i++)
                    295:     {
                    296:       c=gcoeff(tab,k,(i-1)*N+i);
                    297:       if (signe(c))
                    298:       {
                    299:         p1 = sqri((GEN)x[i]);
                    300:         if (!gcmp1(c)) p1 = mulii(p1,c);
                    301:        s = addii(s,p1);
                    302:       }
                    303:       for (j=i+1; j<=N; j++)
                    304:       {
                    305:        c=gcoeff(tab,k,(i-1)*N+j);
                    306:        if (signe(c))
                    307:        {
                    308:           p1 = shifti(mulii((GEN)x[i],(GEN)x[j]),1);
                    309:           if (!gcmp1(c)) p1 = mulii(p1,c);
                    310:          s = addii(s,p1);
                    311:        }
                    312:       }
                    313:     }
1.2     ! noro      314:     v[k] = lpileuptoint(av,s); av = avma;
1.1       noro      315:   }
                    316:   return v;
                    317: }
                    318:
                    319: GEN
1.2     ! noro      320: sqr_by_tab(GEN tab, GEN x)
1.1       noro      321: {
1.2     ! noro      322:   gpmem_t av = avma;
        !           323:   long i,j,k,N;
        !           324:   GEN p1,s,v,c;
1.1       noro      325:
1.2     ! noro      326:   N = lg(x)-1;
1.1       noro      327:   if (isnfscalar(x))
                    328:   {
                    329:     s=cgetg(N+1,t_COL); s[1]=lsqr((GEN)x[1]);
                    330:     for (i=2; i<=N; i++) s[i]=lcopy((GEN)x[i]);
                    331:     return s;
                    332:   }
                    333:   v=cgetg(N+1,t_COL); av = avma;
                    334:   for (k=1; k<=N; k++)
                    335:   {
                    336:     if (k == 1)
                    337:       s = gsqr((GEN)x[1]);
                    338:     else
                    339:       s = gmul2n(gmul((GEN)x[1],(GEN)x[k]), 1);
                    340:     for (i=2; i<=N; i++)
                    341:     {
                    342:       c=gcoeff(tab,k,(i-1)*N+i);
                    343:       if (signe(c))
                    344:       {
                    345:         p1 = gsqr((GEN)x[i]);
                    346:        if (!gcmp1(c)) p1 = gmul(p1,c);
                    347:         s = gadd(s,p1);
                    348:       }
                    349:       for (j=i+1; j<=N; j++)
                    350:       {
                    351:        c=gcoeff(tab,k,(i-1)*N+j);
                    352:        if (signe(c))
                    353:        {
                    354:           p1 = gmul((GEN)x[i],(GEN)x[j]);
1.2     ! noro      355:          p1 = gmul2n(p1,1);
        !           356:           if (!gcmp1(c)) p1 = gmul(p1, c);
1.1       noro      357:          s = gadd(s,p1);
                    358:        }
                    359:       }
                    360:     }
                    361:     v[k]=(long)gerepileupto(av,s); av=avma;
                    362:   }
                    363:   return v;
                    364: }
                    365:
1.2     ! noro      366: /* square of x in nf */
        !           367: GEN
        !           368: element_sqr(GEN nf, GEN x)
        !           369: {
        !           370:   long N, tx = typ(x);
        !           371:   GEN tab;
        !           372:
        !           373:   nf = checknf(nf);
        !           374:   if (tx==t_POLMOD) x=checknfelt_mod(nf,x,"element_sqr");
        !           375:   if (is_extscalar_t(tx))
        !           376:   {
        !           377:     gpmem_t av = avma;
        !           378:     return gerepileupto(av, algtobasis(nf, gsqr(x)));
        !           379:   }
        !           380:   if (tx != t_COL) err(typeer,"element_sqr");
        !           381:
        !           382:   tab = get_tab(nf, &N);
        !           383:   return sqr_by_tab(tab,x);
        !           384: }
        !           385:
        !           386: static GEN
        !           387: _mul(void *data, GEN x, GEN y) { return element_mul((GEN)data,x,y); }
        !           388: static GEN
        !           389: _sqr(void *data, GEN x) { return element_sqr((GEN)data,x); }
        !           390:
1.1       noro      391: /* Compute x^n in nf, left-shift binary powering */
                    392: GEN
                    393: element_pow(GEN nf, GEN x, GEN n)
                    394: {
1.2     ! noro      395:   gpmem_t av = avma;
        !           396:   long s,N;
        !           397:   GEN y, cx;
1.1       noro      398:
                    399:   if (typ(n)!=t_INT) err(talker,"not an integer exponent in nfpow");
                    400:   nf=checknf(nf); N=degpol(nf[1]);
                    401:   s=signe(n); if (!s) return gscalcol_i(gun,N);
1.2     ! noro      402:   if (typ(x) != t_COL)
        !           403:   {
        !           404:     x = algtobasis(nf,x);
        !           405:     if (typ(x) != t_COL) err(typeer,"element_pow");
        !           406:   }
1.1       noro      407:
                    408:   if (isnfscalar(x))
                    409:   {
                    410:     y = gscalcol_i(gun,N);
                    411:     y[1] = (long)powgi((GEN)x[1],n); return y;
                    412:   }
1.2     ! noro      413:   x = primitive_part(x, &cx);
        !           414:   y = leftright_pow(x, n, (void*)nf, _sqr, _mul);
1.1       noro      415:   if (s<0) y = element_inv(nf, y);
                    416:   if (cx) y = gmul(y, powgi(cx, n));
                    417:   return av==avma? gcopy(y): gerepileupto(av,y);
                    418: }
                    419:
1.2     ! noro      420: typedef struct {
        !           421:   GEN nf, p;
        !           422:   long I;
        !           423: } eltmod_muldata;
        !           424:
        !           425: static GEN
        !           426: _mulidmod(void *data, GEN x, GEN y)
        !           427: {
        !           428:   eltmod_muldata *D = (eltmod_muldata*)data;
        !           429:   (void)y; /* ignored */
        !           430:   return FpV_red(element_mulid(D->nf, x, D->I), D->p);
        !           431: }
        !           432: static GEN
        !           433: _sqrmod(void *data, GEN x)
1.1       noro      434: {
1.2     ! noro      435:   eltmod_muldata *D = (eltmod_muldata*)data;
        !           436:   return FpV_red(element_sqri(D->nf, x), D->p);
1.1       noro      437: }
                    438:
                    439: /* x = I-th vector of the Z-basis of Z_K, in Z^n, compute lift(x^n mod p) */
                    440: GEN
                    441: element_powid_mod_p(GEN nf, long I, GEN n, GEN p)
                    442: {
1.2     ! noro      443:   gpmem_t av = avma;
        !           444:   eltmod_muldata D;
        !           445:   long s,N;
        !           446:   GEN y;
1.1       noro      447:
                    448:   if (typ(n)!=t_INT) err(talker,"not an integer exponent in nfpow");
                    449:   nf=checknf(nf); N=degpol(nf[1]);
                    450:   s=signe(n);
                    451:   if (!s || I == 1) return gscalcol_i(gun,N);
                    452:   y = zerocol(N); y[I] = un;
1.2     ! noro      453:   D.nf = nf;
        !           454:   D.p = p;
        !           455:   D.I = I;
        !           456:   y = leftright_pow(y,n, (void*)&D, &_sqrmod, &_mulidmod);
        !           457:   if (s < 0) y = FpV_red(element_inv(nf,y), p);
1.1       noro      458:   return av==avma? gcopy(y): gerepileupto(av,y);
                    459: }
                    460:
1.2     ! noro      461: GEN
        !           462: element_mulidid(GEN nf, long i, long j)
        !           463: {
        !           464:   long N;
        !           465:   GEN tab = get_tab(nf, &N);
        !           466:   tab += (i-1)*N; return (GEN)tab[j];
        !           467: }
        !           468:
1.1       noro      469: /* Outputs x.w_i, where w_i is the i-th elt of the integral basis */
                    470: GEN
                    471: element_mulid(GEN nf, GEN x, long i)
                    472: {
1.2     ! noro      473:   gpmem_t av;
        !           474:   long j,k,N;
1.1       noro      475:   GEN s,v,c,p1, tab;
                    476:
                    477:   if (i==1) return gcopy(x);
                    478:   tab = get_tab(nf, &N);
                    479:   if (typ(x) != t_COL || lg(x) != N+1) err(typeer,"element_mulid");
                    480:   tab += (i-1)*N;
                    481:   v=cgetg(N+1,t_COL); av=avma;
                    482:   for (k=1; k<=N; k++)
                    483:   {
                    484:     s = gzero;
                    485:     for (j=1; j<=N; j++)
                    486:       if (signe(c = gcoeff(tab,k,j)) && !gcmp0(p1 = (GEN)x[j]))
                    487:       {
                    488:         if (!gcmp1(c)) p1 = gmul(p1,c);
                    489:        s = gadd(s,p1);
                    490:       }
                    491:     v[k]=lpileupto(av,s); av=avma;
                    492:   }
                    493:   return v;
                    494: }
                    495:
1.2     ! noro      496: /* table of multiplication by wi in ZK = Z[w1,..., wN] */
        !           497: GEN
        !           498: eltmulid_get_table(GEN nf, long i)
        !           499: {
        !           500:   long k,N;
        !           501:   GEN m, tab;
        !           502:
        !           503:   tab = get_tab(nf, &N);
        !           504:   tab += (i-1)*N;
        !           505:   m = cgetg(N+1,t_COL);
        !           506:   for (k=1; k<=N; k++) m[k] = tab[k];
        !           507:   return m;
        !           508: }
        !           509:
        !           510: /* table of multiplication by x in ZK = Z[w1,..., wN] */
        !           511: GEN
        !           512: eltmul_get_table(GEN nf, GEN x)
        !           513: {
        !           514:   long i, N = degpol(nf[1]);
        !           515:   GEN mul = cgetg(N+1,t_MAT);
        !           516:   if (typ(x) != t_COL) x = algtobasis(nf,x);
        !           517:   mul[1] = (long)x; /* assume w_1 = 1 */
        !           518:   for (i=2; i<=N; i++) mul[i] = (long)element_mulid(nf,x,i);
        !           519:   return mul;
        !           520: }
        !           521:
1.1       noro      522: /* valuation of integer x, with resp. to prime ideal P above p.
                    523:  * p.P^(-1) = b Z_K, v >= val_p(norm(x)), and N = deg(nf)
                    524:  * [b may be given as the 'multiplication by b' matrix]
                    525:  */
                    526: long
1.2     ! noro      527: int_elt_val(GEN nf, GEN x, GEN p, GEN b, GEN *newx)
1.1       noro      528: {
                    529:   long i,k,w, N = degpol(nf[1]);
                    530:   GEN r,a,y,mul;
                    531:
1.2     ! noro      532:   mul = (typ(b) == t_MAT)? b: eltmul_get_table(nf, b);
1.1       noro      533:   y = cgetg(N+1, t_COL); /* will hold the new x */
                    534:   x = dummycopy(x);
1.2     ! noro      535:   for(w=0;; w++)
1.1       noro      536:   {
                    537:     for (i=1; i<=N; i++)
                    538:     { /* compute (x.b)_i */
                    539:       a = mulii((GEN)x[1], gcoeff(mul,i,1));
                    540:       for (k=2; k<=N; k++) a = addii(a, mulii((GEN)x[k], gcoeff(mul,i,k)));
                    541:       /* is it divisible by p ? */
                    542:       y[i] = ldvmdii(a,p,&r);
1.2     ! noro      543:       if (signe(r))
        !           544:       {
        !           545:         if (newx) *newx = x;
        !           546:         return w;
        !           547:       }
1.1       noro      548:     }
                    549:     r=x; x=y; y=r;
                    550:   }
                    551: }
                    552:
                    553: long
                    554: element_val(GEN nf, GEN x, GEN vp)
                    555: {
1.2     ! noro      556:   gpmem_t av = avma;
        !           557:   long N,w,vcx,e;
1.1       noro      558:   GEN cx,p;
                    559:
                    560:   if (gcmp0(x)) return VERYBIGINT;
                    561:   nf=checknf(nf); N=degpol(nf[1]);
                    562:   checkprimeid(vp); p=(GEN)vp[1]; e=itos((GEN)vp[3]);
                    563:   switch(typ(x))
                    564:   {
                    565:     case t_INT: case t_FRAC: case t_FRACN:
                    566:       return ggval(x,p)*e;
                    567:     case t_POLMOD: x = (GEN)x[2]; /* fall through */
                    568:     case t_POL:
1.2     ! noro      569:       x = algtobasis_i(nf,x); break;
1.1       noro      570:     case t_COL:
                    571:       if (lg(x)==N+1) break;
                    572:     default: err(typeer,"element_val");
                    573:   }
                    574:   if (isnfscalar(x)) return ggval((GEN)x[1],p)*e;
                    575:
                    576:   cx = content(x);
                    577:   if (gcmp1(cx)) vcx=0; else { x = gdiv(x,cx); vcx = ggval(cx,p); }
1.2     ! noro      578:   w = int_elt_val(nf,x,p,(GEN)vp[5],NULL);
1.1       noro      579:   avma=av; return w + vcx*e;
                    580: }
                    581:
                    582: /* polegal without comparing variables */
                    583: long
                    584: polegal_spec(GEN x, GEN y)
                    585: {
                    586:   long i = lgef(x);
                    587:
                    588:   if (i != lgef(y)) return 0;
                    589:   for (i--; i > 1; i--)
                    590:     if (!gegal((GEN)x[i],(GEN)y[i])) return 0;
                    591:   return 1;
                    592: }
                    593:
                    594: GEN
                    595: basistoalg(GEN nf, GEN x)
                    596: {
1.2     ! noro      597:   long tx=typ(x),lx=lg(x),i,j,l;
1.1       noro      598:   GEN z;
                    599:
                    600:   nf=checknf(nf);
                    601:   switch(tx)
                    602:   {
                    603:     case t_COL:
                    604:       for (i=1; i<lx; i++)
                    605:       {
                    606:         long t = typ(x[i]);
                    607:        if (is_matvec_t(t)) break;
                    608:       }
                    609:       if (i==lx)
                    610:       {
                    611:         z = cgetg(3,t_POLMOD);
                    612:         z[1] = lcopy((GEN)nf[1]);
                    613:        z[2] = lmul((GEN)nf[7],x); return z;
                    614:       }
                    615:       /* fall through */
                    616:
1.2     ! noro      617:     case t_VEC: z=cgetg(lx,tx);
1.1       noro      618:       for (i=1; i<lx; i++) z[i]=(long)basistoalg(nf,(GEN)x[i]);
                    619:       return z;
1.2     ! noro      620:     case t_MAT: z=cgetg(lx,t_MAT);
        !           621:       if (lx == 1) return z;
        !           622:       l = lg(x[1]);
        !           623:       for (j=1; j<lx; j++)
        !           624:       {
        !           625:         z[j] = lgetg(l,t_COL);
        !           626:         for (i=1; i<l; i++) coeff(z,i,j) = (long)basistoalg(nf,gcoeff(x,i,j));
        !           627:       }
        !           628:       return z;
1.1       noro      629:
                    630:     case t_POLMOD:
                    631:       if (!polegal_spec((GEN)nf[1],(GEN)x[1]))
                    632:        err(talker,"not the same number field in basistoalg");
                    633:       return gcopy(x);
                    634:     default: z=cgetg(3,t_POLMOD);
                    635:       z[1]=lcopy((GEN)nf[1]);
                    636:       z[2]=lmul(x,polun[varn(nf[1])]); return z;
                    637:   }
                    638: }
                    639:
1.2     ! noro      640: /* gmul(A, pol_to_vec(x)), A t_MAT (or t_VEC) of compatible dimensions */
1.1       noro      641: GEN
                    642: mulmat_pol(GEN A, GEN x)
                    643: {
                    644:   long i,l;
                    645:   GEN z;
1.2     ! noro      646:   if (typ(x) != t_POL) return gmul(x,(GEN)A[1]); /* scalar */
        !           647:   l=lgef(x)-1; if (l == 1) return typ(A)==t_VEC? gzero: zerocol(lg(A[1])-1);
1.1       noro      648:   x++; z = gmul((GEN)x[1], (GEN)A[1]);
                    649:   for (i=2; i<l ; i++)
                    650:     if (!gcmp0((GEN)x[i])) z = gadd(z, gmul((GEN)x[i], (GEN)A[i]));
                    651:   return z;
                    652: }
                    653:
                    654: /* valid for scalars and polynomial, degree less than N.
1.2     ! noro      655:  * No garbage collecting. No check.  */
1.1       noro      656: GEN
1.2     ! noro      657: algtobasis_i(GEN nf, GEN x)
1.1       noro      658: {
                    659:   GEN P = (GEN)nf[1];
                    660:   long tx = typ(x), N = degpol(P);
                    661:
                    662:   if (tx==t_POLMOD) { x=(GEN)x[2]; tx=typ(x); }
                    663:   if (tx==t_POL)
                    664:   {
                    665:     if (varn(x) != varn(P))
                    666:       err(talker,"incompatible variables in algtobasis");
                    667:     if (degpol(x) >= N) x = gres(x,P);
                    668:     return mulmat_pol((GEN)nf[8], x);
                    669:   }
                    670:   return gscalcol(x,N);
                    671: }
                    672:
                    673: GEN
                    674: algtobasis(GEN nf, GEN x)
                    675: {
1.2     ! noro      676:   long tx=typ(x),lx=lg(x),i,N;
        !           677:   gpmem_t av=avma;
1.1       noro      678:   GEN z;
                    679:
                    680:   nf=checknf(nf);
                    681:   switch(tx)
                    682:   {
                    683:     case t_VEC: case t_COL: case t_MAT:
                    684:       z=cgetg(lx,tx);
                    685:       for (i=1; i<lx; i++) z[i]=(long)algtobasis(nf,(GEN)x[i]);
                    686:       return z;
                    687:     case t_POLMOD:
                    688:       if (!polegal_spec((GEN)nf[1],(GEN)x[1]))
                    689:        err(talker,"not the same number field in algtobasis");
                    690:       x = (GEN)x[2]; /* fall through */
                    691:     case t_POL:
1.2     ! noro      692:       return gerepileupto(av,algtobasis_i(nf,x));
1.1       noro      693:
                    694:     default: N=degpol(nf[1]); return gscalcol(x,N);
                    695:   }
                    696: }
                    697:
                    698: /* Given a and b in nf, gives an algebraic integer y in nf such that a-b.y
                    699:  * is "small"
                    700:  */
                    701: GEN
                    702: nfdiveuc(GEN nf, GEN a, GEN b)
                    703: {
1.2     ! noro      704:   gpmem_t av=avma, tetpil;
1.1       noro      705:   a = element_div(nf,a,b); tetpil=avma;
                    706:   return gerepile(av,tetpil,ground(a));
                    707: }
                    708:
                    709: /* Given a and b in nf, gives a "small" algebraic integer r in nf
                    710:  * of the form a-b.y
                    711:  */
                    712: GEN
                    713: nfmod(GEN nf, GEN a, GEN b)
                    714: {
1.2     ! noro      715:   gpmem_t av=avma,tetpil;
1.1       noro      716:   GEN p1=gneg_i(element_mul(nf,b,ground(element_div(nf,a,b))));
                    717:   tetpil=avma; return gerepile(av,tetpil,gadd(a,p1));
                    718: }
                    719:
                    720: /* Given a and b in nf, gives a two-component vector [y,r] in nf such
                    721:  * that r=a-b.y is "small".
                    722:  */
                    723: GEN
                    724: nfdivres(GEN nf, GEN a, GEN b)
                    725: {
1.2     ! noro      726:   gpmem_t av=avma,tetpil;
1.1       noro      727:   GEN p1,z, y = ground(element_div(nf,a,b));
                    728:
                    729:   p1=gneg_i(element_mul(nf,b,y)); tetpil=avma;
                    730:   z=cgetg(3,t_VEC); z[1]=lcopy(y); z[2]=ladd(a,p1);
                    731:   return gerepile(av,tetpil,z);
                    732: }
                    733:
                    734: /*************************************************************************/
                    735: /**                                                                    **/
                    736: /**                          (Z_K/I)^*                                 **/
                    737: /**                                                                    **/
                    738: /*************************************************************************/
1.2     ! noro      739: /* return sign(sigma_k(x)), x t_COL (integral, primitive) */
        !           740: static long
        !           741: eval_sign(GEN M, GEN x, long k)
        !           742: {
        !           743:   long i, l = lg(x);
        !           744:   GEN z = mpmul(gcoeff(M,k,1), (GEN)x[1]);
        !           745:   for (i = 2; i < l; i++)
        !           746:     z = mpadd(z, mpmul(gcoeff(M,k,i), (GEN)x[i]));
        !           747:   if (lg(z) < DEFAULTPREC) err(precer,"zsigne");
        !           748:   return signe(z);
        !           749: }
        !           750:
        !           751: static void
        !           752: const_sign(GEN v, GEN arch, GEN s)
        !           753: {
        !           754:   long i,j, l = lg(v);
        !           755:   for (j=i=1; i<l; i++)
        !           756:     if (signe(arch[i])) v[j++] = (long)s;
        !           757:   setlg(v, j);
        !           758: }
1.1       noro      759:
                    760: /* return (column) vector of R1 signatures of x (coeff modulo 2)
1.2     ! noro      761:  * if arch = NULL, assume arch = [0,..0] */
1.1       noro      762: GEN
                    763: zsigne(GEN nf,GEN x,GEN arch)
                    764: {
1.2     ! noro      765:   GEN _0, _1, M, vecsign;
        !           766:   long i,j,l,s;
        !           767:   gpmem_t av0, av;
1.1       noro      768:
                    769:   if (!arch) return cgetg(1,t_COL);
                    770:   av0 = avma;
                    771:   l = lg(arch); vecsign = cgetg(l,t_COL);
                    772:   _0 = gmodulss(0,2);
                    773:   _1 = gmodulss(1,2); av = avma;
1.2     ! noro      774:   nf = checknf(nf);
        !           775:   M = gmael(nf,5,1);
1.1       noro      776:   switch(typ(x))
                    777:   {
                    778:     case t_MAT: /* factorisation */
                    779:     {
1.2     ! noro      780:       GEN g = (GEN)x[1], e = (GEN)x[2];
        !           781:       const_sign(vecsign, arch, _0);
        !           782:       if (lg(vecsign)==1) { avma = av0; return cgetg(1, t_COL); }
        !           783:       for (i=1; i<lg(g); i++)
        !           784:         if (mpodd((GEN)e[i]))
        !           785:           vecsign = gadd(vecsign, zsigne(nf,(GEN)g[i],arch));
1.1       noro      786:       return gerepileupto(av0, vecsign);
                    787:     }
1.2     ! noro      788:     case t_POLMOD: x = (GEN)x[2];      /* fall through */
        !           789:     case t_POL: x = algtobasis(nf, x); /* fall through */
        !           790:     case t_COL: if (!isnfscalar(x)) break;
        !           791:                 x = (GEN)x[1];         /* fall through */
        !           792:     case t_INT: case t_FRAC:
        !           793:     {
        !           794:       s = gsigne(x); if (!s) err(talker,"zero element in zsigne");
        !           795:       const_sign(vecsign, arch, (s > 0)? _0: _1);
        !           796:       return vecsign;
        !           797:     }
1.1       noro      798:   }
1.2     ! noro      799:   x = Q_primpart(x);
1.1       noro      800:   for (j=i=1; i<l; i++)
                    801:     if (signe(arch[i]))
1.2     ! noro      802:       vecsign[j++] = (eval_sign(M, x, i) > 0)? (long)_0: (long)_1;
1.1       noro      803:   avma = av; setlg(vecsign,j); return vecsign;
                    804: }
                    805:
1.2     ! noro      806: /* return the t_COL vector of signs of x; the matrix of such if x is a vector
        !           807:  * of nf elements */
        !           808: GEN
        !           809: zsigns(GEN nf, GEN x)
        !           810: {
        !           811:   long r1, i, l;
        !           812:   GEN arch, S;
        !           813:
        !           814:   nf = checknf(nf); r1 = nf_get_r1(nf);
        !           815:   arch = cgetg(r1+1,t_VEC); for (i=1; i<=r1; i++) arch[i] = un;
        !           816:   if (typ(x) != t_VEC) return zsigne(nf, x, arch);
        !           817:   l = lg(x); S = cgetg(l, t_MAT);
        !           818:   for (i=1; i<l; i++) S[i] = (long)zsigne(nf, (GEN)x[i], arch);
        !           819:   return S;
        !           820: }
        !           821:
1.1       noro      822: GEN
                    823: lllreducemodmatrix(GEN x,GEN y)
                    824: {
1.2     ! noro      825:   gpmem_t av = avma;
        !           826:   GEN z = lllint_ip(y,4);
1.1       noro      827:   return gerepileupto(av, reducemodinvertible(x, z));
                    828: }
                    829:
                    830: /* for internal use...reduce x modulo (invertible) y */
                    831: GEN
                    832: reducemodinvertible(GEN x, GEN y)
                    833: {
                    834:   return gadd(x, gneg(gmul(y, ground(gauss(y,x)))));
                    835: }
                    836:
                    837: /* Reduce column x modulo y in HNF */
                    838: GEN
1.2     ! noro      839: colreducemodHNF(GEN x, GEN y, GEN *Q)
1.1       noro      840: {
                    841:   long i, l = lg(x);
                    842:   GEN q;
                    843:
                    844:   if (Q) *Q = cgetg(l,t_COL);
                    845:   if (l == 1) return cgetg(1,t_COL);
                    846:   for (i = l-1; i>0; i--)
                    847:   {
1.2     ! noro      848:     q = negi(diviiround((GEN)x[i], gcoeff(y,i,i)));
1.1       noro      849:     if (Q) (*Q)[i] = (long)q;
                    850:     if (signe(q)) x = gadd(x, gmul(q, (GEN)y[i]));
                    851:   }
                    852:   return x;
                    853: }
                    854:
                    855: /* for internal use...Reduce matrix x modulo matrix y */
                    856: GEN
                    857: reducemodmatrix(GEN x, GEN y)
                    858: {
                    859:   return reducemodHNF(x, hnfmod(y,detint(y)), NULL);
                    860: }
                    861:
                    862: /* x = y Q + R */
                    863: GEN
                    864: reducemodHNF(GEN x, GEN y, GEN *Q)
                    865: {
                    866:   long lx = lg(x), i;
                    867:   GEN R = cgetg(lx, t_MAT);
                    868:   if (Q)
                    869:   {
                    870:     GEN q = cgetg(lx, t_MAT); *Q = q;
1.2     ! noro      871:     for (i=1; i<lx; i++) R[i] = (long)colreducemodHNF((GEN)x[i],y,(GEN*)(q+i));
1.1       noro      872:   }
                    873:   else
                    874:     for (i=1; i<lx; i++)
                    875:     {
1.2     ! noro      876:       gpmem_t av = avma;
        !           877:       R[i] = lpileupto(av, colreducemodHNF((GEN)x[i],y,NULL));
1.1       noro      878:     }
                    879:   return R;
                    880: }
                    881:
1.2     ! noro      882: /* For internal use. Reduce x modulo ideal (assumed non-zero, in HNF). We
        !           883:  * want a non-zero result */
        !           884: GEN
        !           885: nfreducemodideal_i(GEN x0,GEN ideal)
        !           886: {
        !           887:   GEN x = colreducemodHNF(x0, ideal, NULL);
        !           888:   if (gcmp0(x)) return (GEN)ideal[1];
        !           889:   return x == x0? gcopy(x) : x;
        !           890: }
1.1       noro      891: GEN
                    892: nfreducemodideal(GEN nf,GEN x0,GEN ideal)
                    893: {
1.2     ! noro      894:   return nfreducemodideal_i(x0, idealhermite(nf,ideal));
1.1       noro      895: }
                    896:
                    897: /* multiply y by t = 1 mod^* f such that sign(x) = sign(y) at arch = idele[2].
                    898:  * If x == NULL, make y >> 0 at sarch */
                    899: GEN
                    900: set_sign_mod_idele(GEN nf, GEN x, GEN y, GEN idele, GEN sarch)
                    901: {
                    902:   GEN s,arch,gen;
                    903:   long nba,i;
                    904:   if (!sarch) return y;
                    905:   gen = (GEN)sarch[2]; nba = lg(gen);
                    906:   if (nba == 1) return y;
                    907:
                    908:   arch = (GEN)idele[2];
                    909:   s = zsigne(nf,y,arch);
                    910:   if (x) s = gadd(s, zsigne(nf,x,arch));
                    911:   s = lift_intern(gmul((GEN)sarch[3],s));
                    912:   for (i=1; i<nba; i++)
                    913:     if (signe(s[i])) y = element_mul(nf,y,(GEN)gen[i]);
                    914:   return y;
                    915: }
                    916:
                    917: /* compute elt = x mod idele, with sign(elt) = sign(x) at arch */
                    918: GEN
                    919: nfreducemodidele(GEN nf,GEN x,GEN idele,GEN sarch)
                    920: {
                    921:   GEN y;
                    922:
                    923:   if (gcmp0(x)) return gcopy(x);
                    924:   if (!sarch || typ(idele)!=t_VEC || lg(idele)!=3)
                    925:     return nfreducemodideal(nf,x,idele);
                    926:
                    927:   y = nfreducemodideal(nf,x,(GEN)idele[1]);
                    928:   y = set_sign_mod_idele(nf, x, y, idele, sarch);
                    929:   return (gexpo(y) > gexpo(x))? x: y;
                    930: }
                    931:
                    932: GEN
                    933: element_powmodideal(GEN nf,GEN x,GEN k,GEN ideal)
                    934: {
                    935:   GEN y = gscalcol_i(gun,degpol(nf[1]));
                    936:   for(;;)
                    937:   {
                    938:     if (mpodd(k)) y=element_mulmodideal(nf,x,y,ideal);
                    939:     k=shifti(k,-1); if (!signe(k)) return y;
                    940:     x = element_sqrmodideal(nf,x,ideal);
                    941:   }
                    942: }
                    943:
                    944: GEN
                    945: element_powmodidele(GEN nf,GEN x,GEN k,GEN idele,GEN sarch)
                    946: {
                    947:   GEN y = element_powmodideal(nf,x,k,idele);
                    948:   if (mpodd(k))
                    949:   { if (!gcmp1(k)) y = set_sign_mod_idele(nf, x, y, idele, sarch); }
                    950:   else
                    951:   { if (!gcmp0(k)) y = set_sign_mod_idele(nf, NULL, y, idele, sarch); }
                    952:   return y;
                    953: }
                    954:
                    955: /* H relation matrix among row of generators g.  Let URV = D its SNF, newU R
                    956:  * newV = newD its clean SNF (no 1 in Dnew). Return the diagonal of newD,
                    957:  * newU and newUi such that  1/U = (newUi, ?).
                    958:  * Rationale: let (G,0) = g Ui be the new generators then
                    959:  * 0 = G U R --> G D = 0,  g = G newU  and  G = g newUi */
                    960: GEN
                    961: smithrel(GEN H, GEN *newU, GEN *newUi)
                    962: {
1.2     ! noro      963:   GEN U,Ui,D,p1;
1.1       noro      964:   long l,c;
                    965:
1.2     ! noro      966:   D = smithall(H, &U, NULL);
        !           967:   l = lg(D);
1.1       noro      968:   for (c=1; c<l; c++)
                    969:   {
                    970:     p1 = gcoeff(D,c,c);
                    971:     if (is_pm1(p1)) break;
                    972:   }
                    973:   if (newU) *newU = rowextract_i(U, 1, c-1);
                    974:   if (newUi) {
                    975:     Ui = ginv(U); setlg(Ui, c);
                    976:     *newUi = reducemodHNF(Ui, H, NULL);
                    977:   }
                    978:   setlg(D, c); return mattodiagonal_i(D);
                    979: }
                    980:
                    981: /* given 2 integral ideals x, y in HNF s.t x | y | x^2, compute the quotient
                    982:    (1+x)/(1+y) in the form [[cyc],[gen],ux^-1]. */
                    983: static GEN
                    984: zidealij(GEN x, GEN y)
                    985: {
                    986:   GEN U,R,G,p1,cyc,z,xi;
                    987:   long j,N;
                    988:
                    989:   xi = ginv(x); R = gmul(xi, y); /* relations between the 1 + x_i (HNF) */
                    990:   cyc = smithrel(R, &U, &G);
                    991:   N = lg(cyc); G = gmul(x,G); settyp(G, t_VEC); /* new generators */
                    992:   for (j=1; j<N; j++)
                    993:   {
                    994:     p1 = (GEN)G[j];
                    995:     p1[1] = laddsi(1, (GEN)p1[1]); /* 1 + g_j */
                    996:   }
                    997:   z = cgetg(4,t_VEC);
                    998:   z[1] = (long)cyc;
                    999:   z[2] = (long)G;
                   1000:   z[3] = lmul(U,xi); return z;
                   1001: }
                   1002:
                   1003: /* smallest integer n such that g0^n=x modulo p prime. Assume g0 has order q
                   1004:  * (p-1 if q = NULL) */
                   1005: GEN
                   1006: Fp_shanks(GEN x,GEN g0,GEN p, GEN q)
                   1007: {
1.2     ! noro     1008:   gpmem_t av=avma,av1,lim;
        !          1009:   long lbaby,i,k,c;
1.1       noro     1010:   GEN p1,smalltable,giant,perm,v,g0inv;
                   1011:
                   1012:   x = modii(x,p);
                   1013:   if (is_pm1(x) || egalii(p,gdeux)) { avma = av; return gzero; }
                   1014:   p1 = addsi(-1, p); if (!q) q = p1;
                   1015:   if (egalii(p1,x)) { avma = av; return shifti(q,-1); }
                   1016:   p1 = racine(q);
                   1017:   if (cmpis(p1,LGBITS) >= 0) err(talker,"module too large in Fp_shanks");
                   1018:   lbaby=itos(p1)+1; smalltable=cgetg(lbaby+1,t_VEC);
                   1019:   g0inv = mpinvmod(g0, p); p1 = x;
                   1020:
                   1021:   c = 3 * lgefint(p);
                   1022:   for (i=1;;i++)
                   1023:   {
                   1024:     av1 = avma;
                   1025:     if (is_pm1(p1)) { avma=av; return stoi(i-1); }
                   1026:     smalltable[i]=(long)p1; if (i==lbaby) break;
1.2     ! noro     1027:     (void)new_chunk(c); p1 = mulii(p1,g0inv); /* HACK */
1.1       noro     1028:     avma = av1; p1 = resii(p1, p);
                   1029:   }
                   1030:   giant = resii(mulii(x, mpinvmod(p1,p)), p);
                   1031:   p1=cgetg(lbaby+1,t_VEC);
                   1032:   perm = gen_sort(smalltable, cmp_IND | cmp_C, cmpii);
                   1033:   for (i=1; i<=lbaby; i++) p1[i]=smalltable[perm[i]];
                   1034:   smalltable=p1; p1=giant;
                   1035:
                   1036:   av1 = avma; lim=stack_lim(av1,2);
                   1037:   for (k=1;;k++)
                   1038:   {
                   1039:     i=tablesearch(smalltable,p1,cmpii);
                   1040:     if (i)
                   1041:     {
                   1042:       v=addis(mulss(lbaby-1,k),perm[i]);
                   1043:       return gerepileuptoint(av,addsi(-1,v));
                   1044:     }
                   1045:     p1 = resii(mulii(p1,giant), p);
                   1046:
                   1047:     if (low_stack(lim, stack_lim(av1,2)))
                   1048:     {
                   1049:       if(DEBUGMEM>1) err(warnmem,"Fp_shanks, k = %ld", k);
                   1050:       p1 = gerepileuptoint(av1, p1);
                   1051:     }
                   1052:   }
                   1053: }
                   1054:
                   1055: /* Pohlig-Hellman */
                   1056: GEN
                   1057: Fp_PHlog(GEN a, GEN g, GEN p, GEN ord)
                   1058: {
1.2     ! noro     1059:   gpmem_t av = avma;
1.1       noro     1060:   GEN v,t0,a0,b,q,g_q,n_q,ginv0,qj,ginv;
                   1061:   GEN fa, ex;
                   1062:   long e,i,j,l;
                   1063:
                   1064:   if (!ord) ord = subis(p,1);
                   1065:   if (typ(ord) == t_MAT)
                   1066:   {
                   1067:     fa = ord;
                   1068:     ord= factorback(fa,NULL);
                   1069:   }
                   1070:   else
                   1071:     fa = decomp(ord);
                   1072:   if (typ(g) == t_INTMOD) g = lift_intern(g);
                   1073:   ex = (GEN)fa[2];
                   1074:   fa = (GEN)fa[1];
                   1075:   l = lg(fa);
                   1076:   ginv = mpinvmod(g,p);
                   1077:   v = cgetg(l, t_VEC);
                   1078:   for (i=1; i<l; i++)
                   1079:   {
                   1080:     q = (GEN)fa[i];
                   1081:     e = itos((GEN)ex[i]);
                   1082:     if (DEBUGLEVEL>5)
                   1083:       fprintferr("Pohlig-Hellman: DL mod %Z^%ld\n",q,e);
                   1084:     qj = new_chunk(e+1); qj[0] = un;
                   1085:     for (j=1; j<=e; j++) qj[j] = lmulii((GEN)qj[j-1], q);
                   1086:     t0 = divii(ord, (GEN)qj[e]);
                   1087:     a0 = powmodulo(a, t0, p);
                   1088:     ginv0 = powmodulo(ginv, t0, p); /* order q^e */
                   1089:     g_q = powmodulo(g, divii(ord,q), p); /* order q */
                   1090:     n_q = gzero;
                   1091:     for (j=0; j<e; j++)
                   1092:     {
                   1093:       b = modii(mulii(a0, powmodulo(ginv0, n_q, p)), p);
                   1094:       b = powmodulo(b, (GEN)qj[e-1-j], p);
                   1095:       b = Fp_shanks(b, g_q, p, q);
                   1096:       n_q = addii(n_q, mulii(b, (GEN)qj[j]));
                   1097:     }
                   1098:     v[i] = lmodulcp(n_q, (GEN)qj[e]);
                   1099:   }
                   1100:   return gerepileuptoint(av, lift(chinese(v,NULL)));
                   1101: }
                   1102:
1.2     ! noro     1103: /* discrete log in Fq for a in Fp^*, g primitive root in Fq^* */
        !          1104: static GEN
        !          1105: ff_PHlog_Fp(GEN a, GEN g, GEN T, GEN p)
        !          1106: {
        !          1107:   gpmem_t av = avma;
        !          1108:   GEN q,n_q,ord,ordp;
        !          1109:
        !          1110:   if (gcmp1(a) || egalii(p, gdeux)) { avma = av; return gzero; }
        !          1111:
        !          1112:   ordp = subis(p, 1);
        !          1113:   ord = T? subis(gpowgs(p,degpol(T)), 1): p;
        !          1114:   if (egalii(a, ordp)) /* -1 */
        !          1115:     return gerepileuptoint(av, shifti(ord,-1));
        !          1116:
        !          1117:   if (!T) q = NULL;
        !          1118:   else
        !          1119:   { /* we want < g > = Fp^* */
        !          1120:     q = divii(ord,ordp);
        !          1121:     g = FpXQ_pow(g,q,T,p);
        !          1122:     if (typ(g) == t_POL) g = constant_term(g);
        !          1123:   }
        !          1124:   n_q = Fp_PHlog(a,g,p,NULL);
        !          1125:   if (q) n_q = mulii(q, n_q);
        !          1126:   return gerepileuptoint(av, n_q);
        !          1127: }
        !          1128:
1.1       noro     1129: /* smallest n >= 0 such that g0^n=x modulo pr, assume g0 reduced
1.2     ! noro     1130:  * q = order of g0 is prime (and != p) */
1.1       noro     1131: static GEN
1.2     ! noro     1132: ffshanks(GEN x, GEN g0, GEN q, GEN T, GEN p)
1.1       noro     1133: {
1.2     ! noro     1134:   gpmem_t av = avma, av1, lim;
        !          1135:   long lbaby,i,k;
        !          1136:   GEN p1,smalltable,giant,perm,v,g0inv;
        !          1137:
        !          1138:   if (!degpol(x)) x = constant_term(x);
        !          1139:   if (typ(x) == t_INT)
        !          1140:   {
        !          1141:     if (!gcmp1(modii(p,q))) return gzero;
        !          1142:     /* g0 in Fp^*, order q | (p-1) */
        !          1143:     if (typ(g0) == t_POL) g0 = constant_term(g0);
        !          1144:     return Fp_PHlog(x,g0,p,q);
        !          1145:   }
        !          1146:
        !          1147:   p1 = racine(q);
        !          1148:   if (cmpis(p1,LGBITS) >= 0) err(talker,"module too large in ffshanks");
        !          1149:   lbaby = itos(p1)+1; smalltable = cgetg(lbaby+1,t_VEC);
        !          1150:   g0inv = FpXQ_inv(g0,T,p);
1.1       noro     1151:   p1 = x;
                   1152:
                   1153:   for (i=1;;i++)
                   1154:   {
1.2     ! noro     1155:     if (gcmp1(p1)) { avma = av; return stoi(i-1); }
1.1       noro     1156:
                   1157:     smalltable[i]=(long)p1; if (i==lbaby) break;
1.2     ! noro     1158:     p1 = FpXQ_mul(p1,g0inv, T,p);
1.1       noro     1159:   }
1.2     ! noro     1160:   giant = FpXQ_div(x,p1,T,p);
        !          1161:   perm = gen_sort(smalltable, cmp_IND | cmp_C, cmp_pol);
        !          1162:   smalltable = vecextract_p(smalltable, perm);
        !          1163:   p1 = giant;
1.1       noro     1164:
                   1165:   av1 = avma; lim=stack_lim(av1,2);
                   1166:   for (k=1;;k++)
                   1167:   {
1.2     ! noro     1168:     i = tablesearch(smalltable,p1,cmp_pol);
1.1       noro     1169:     if (i)
                   1170:     {
1.2     ! noro     1171:       v = addis(mulss(lbaby-1,k), perm[i]);
        !          1172:       return gerepileuptoint(av, addsi(-1,v));
1.1       noro     1173:     }
1.2     ! noro     1174:     p1 = FpXQ_mul(p1, giant, T,p);
1.1       noro     1175:
                   1176:     if (low_stack(lim, stack_lim(av1,2)))
                   1177:     {
1.2     ! noro     1178:       if(DEBUGMEM>1) err(warnmem,"ffshanks");
1.1       noro     1179:       p1 = gerepileupto(av1, p1);
                   1180:     }
                   1181:   }
                   1182: }
                   1183:
1.2     ! noro     1184: /* same in Fp[X]/T */
1.1       noro     1185: GEN
1.2     ! noro     1186: ff_PHlog(GEN a, GEN g, GEN T, GEN p)
1.1       noro     1187: {
1.2     ! noro     1188:   gpmem_t av = avma;
1.1       noro     1189:   GEN v,t0,a0,b,q,g_q,n_q,ginv0,qj,ginv,ord,fa,ex;
                   1190:   long e,i,j,l;
                   1191:
1.2     ! noro     1192:   if (typ(a) == t_INT)
        !          1193:     return gerepileuptoint(av, ff_PHlog_Fp(a,g,T,p));
        !          1194:   /* f > 1 ==> T != NULL */
        !          1195:   ord = subis(gpowgs(p, degpol(T)), 1);
        !          1196:   fa = factor(ord);
        !          1197:   ex = (GEN)fa[2];
1.1       noro     1198:   fa = (GEN)fa[1];
                   1199:   l = lg(fa);
1.2     ! noro     1200:   ginv = FpXQ_inv(g,T,p);
1.1       noro     1201:   v = cgetg(l, t_VEC);
                   1202:   for (i=1; i<l; i++)
                   1203:   {
                   1204:     q = (GEN)fa[i];
                   1205:     e = itos((GEN)ex[i]);
1.2     ! noro     1206:     if (DEBUGLEVEL>5) fprintferr("nf_Pohlig-Hellman: DL mod %Z^%ld\n",q,e);
1.1       noro     1207:     qj = new_chunk(e+1); qj[0] = un;
                   1208:     for (j=1; j<=e; j++) qj[j] = lmulii((GEN)qj[j-1], q);
                   1209:     t0 = divii(ord, (GEN)qj[e]);
1.2     ! noro     1210:     a0 = FpXQ_pow(a, t0, T,p);
        !          1211:     ginv0 = FpXQ_pow(ginv, t0, T,p); /* order q^e */
        !          1212:     g_q = FpXQ_pow(g, divii(ord,q), T,p); /* order q */
        !          1213:
1.1       noro     1214:     n_q = gzero;
                   1215:     for (j=0; j<e; j++)
                   1216:     {
1.2     ! noro     1217:       b = FpXQ_mul(a0, FpXQ_pow(ginv0, n_q, T,p), T,p);
        !          1218:       b = FpXQ_pow(b, (GEN)qj[e-1-j], T,p);
        !          1219:       b = ffshanks(b, g_q, q, T,p);
1.1       noro     1220:       n_q = addii(n_q, mulii(b, (GEN)qj[j]));
                   1221:     }
                   1222:     v[i] = lmodulcp(n_q, (GEN)qj[e]);
                   1223:   }
                   1224:   return gerepileuptoint(av, lift(chinese(v,NULL)));
                   1225: }
                   1226:
1.2     ! noro     1227: /* same in nf.zk / pr */
        !          1228: GEN
        !          1229: nf_PHlog(GEN nf, GEN a, GEN g, GEN pr)
        !          1230: {
        !          1231:   gpmem_t av = avma;
        !          1232:   GEN T,p, modpr = nf_to_ff_init(nf, &pr, &T, &p);
        !          1233:   GEN A = nf_to_ff(nf,a,modpr);
        !          1234:   GEN G = nf_to_ff(nf,g,modpr);
        !          1235:   return gerepileuptoint(av, ff_PHlog(A,G,T,p));
        !          1236: }
        !          1237:
1.1       noro     1238: GEN
                   1239: znlog(GEN x, GEN g0)
                   1240: {
1.2     ! noro     1241:   gpmem_t av=avma;
1.1       noro     1242:   GEN p = (GEN)g0[1];
                   1243:   if (typ(g0) != t_INTMOD)
                   1244:     err(talker,"not an element of (Z/pZ)* in znlog");
                   1245:   switch(typ(x))
                   1246:   {
                   1247:     case t_INT: break;
                   1248:     default: x = gmul(x, gmodulsg(1,p));
                   1249:     if (typ(x) != t_INTMOD)
                   1250:       err(talker,"not an element of (Z/pZ)* in znlog");
                   1251:     case t_INTMOD: x = (GEN)x[2]; break;
                   1252:   }
                   1253:   return gerepileuptoint(av, Fp_PHlog(x,(GEN)g0[2],p,NULL));
                   1254: }
                   1255:
                   1256: GEN
                   1257: dethnf(GEN mat)
                   1258: {
                   1259:   long i,l = lg(mat);
1.2     ! noro     1260:   gpmem_t av;
1.1       noro     1261:   GEN s;
                   1262:
                   1263:   if (l<3) return l<2? gun: icopy(gcoeff(mat,1,1));
                   1264:   av = avma; s = gcoeff(mat,1,1);
                   1265:   for (i=2; i<l; i++) s = gmul(s,gcoeff(mat,i,i));
                   1266:   return av==avma? gcopy(s): gerepileupto(av,s);
                   1267: }
                   1268:
                   1269: GEN
                   1270: dethnf_i(GEN mat)
                   1271: {
1.2     ! noro     1272:   gpmem_t av;
        !          1273:   long i,l = lg(mat);
1.1       noro     1274:   GEN s;
                   1275:
                   1276:   if (l<3) return l<2? gun: icopy(gcoeff(mat,1,1));
                   1277:   av = avma; s = gcoeff(mat,1,1);
                   1278:   for (i=2; i<l; i++) s = mulii(s,gcoeff(mat,i,i));
                   1279:   return gerepileuptoint(av,s);
                   1280: }
                   1281:
                   1282: /* as above with cyc = diagonal(mat) */
                   1283: GEN
                   1284: detcyc(GEN cyc)
                   1285: {
1.2     ! noro     1286:   gpmem_t av;
        !          1287:   long i,l = lg(cyc);
1.1       noro     1288:   GEN s;
                   1289:
                   1290:   if (l<3) return l<2? gun: icopy((GEN)cyc[1]);
                   1291:   av = avma; s = (GEN)cyc[1];
                   1292:   for (i=2; i<l; i++) s = mulii(s,(GEN)cyc[i]);
                   1293:   return gerepileuptoint(av,s);
                   1294: }
                   1295:
                   1296: /* (U,V) = 1. Return y = x mod U, = 1 mod V (uv: u + v = 1, u in U, v in V) */
1.2     ! noro     1297: GEN
1.1       noro     1298: makeprimetoideal(GEN nf,GEN UV,GEN uv,GEN x)
                   1299: {
                   1300:   GEN y = gadd((GEN)uv[1], element_mul(nf,x,(GEN)uv[2]));
1.2     ! noro     1301:   return nfreducemodideal_i(y,UV);
1.1       noro     1302: }
                   1303:
                   1304: static GEN
                   1305: makeprimetoidealvec(GEN nf,GEN UV,GEN uv,GEN gen)
                   1306: {
                   1307:   long i, lx = lg(gen);
                   1308:   GEN y = cgetg(lx,t_VEC);
                   1309:   for (i=1; i<lx; i++)
                   1310:     y[i] = (long)makeprimetoideal(nf,UV,uv,(GEN)gen[i]);
                   1311:   return y;
                   1312: }
                   1313:
1.2     ! noro     1314: GEN
        !          1315: FpXQ_gener(GEN T, GEN p)
        !          1316: {
        !          1317:   long i,j, k, vT = varn(T), f = degpol(T);
        !          1318:   GEN g, list, pf_1 = subis(gpowgs(p, f), 1);
        !          1319:   gpmem_t av0 = avma, av;
        !          1320:
        !          1321:   list = (GEN)factor(pf_1)[1];
        !          1322:   k = lg(list)-1;
        !          1323:
        !          1324:   for (i=1; i<=k; i++) list[i] = (long)diviiexact(pf_1, (GEN)list[i]);
        !          1325:   for (av = avma;; avma = av)
        !          1326:   {
        !          1327:     g = FpX_rand(f, vT, p);
        !          1328:     if (degpol(g) < 1) continue;
        !          1329:     for (j=1; j<=k; j++)
        !          1330:       if (gcmp1(FpXQ_pow(g, (GEN)list[j], T, p))) break;
        !          1331:     if (j > k) return gerepilecopy(av0, g);
        !          1332:   }
        !          1333: }
        !          1334:
1.1       noro     1335: /* Given an ideal pr^ep, and an integral ideal x (in HNF form) compute a list
                   1336:  * of vectors, each with 5 components as follows :
                   1337:  * [[clh],[gen1],[gen2],[signat2],U.X^-1]. Each component corresponds to
                   1338:  * d_i,g_i,g'_i,s_i.  Generators g_i are not necessarily prime to x, the
                   1339:  * generators g'_i are. signat2 is the (horizontal) vector made of the
                   1340:  * signatures (column vectors) of the g'_i. If x = NULL, the original ideal
                   1341:  * was a prime power
                   1342:  */
                   1343: static GEN
                   1344: zprimestar(GEN nf,GEN pr,GEN ep,GEN x,GEN arch)
                   1345: {
1.2     ! noro     1346:   gpmem_t av = avma, av1, tetpil;
        !          1347:   long N, f, i, e, a, b;
1.1       noro     1348:   GEN prh,p,pf_1,list,v,p1,p3,p4,prk,uv,g0,newgen,pra,prb;
                   1349:   GEN *gptr[2];
                   1350:
                   1351:   if(DEBUGLEVEL>3) { fprintferr("treating pr = %Z ^ %Z\n",pr,ep); flusherr(); }
1.2     ! noro     1352:   prh = prime_to_ideal(nf,pr); N = degpol(nf[1]);
        !          1353:   f = itos((GEN)pr[4]);
        !          1354:   p = (GEN)pr[1];
1.1       noro     1355:
                   1356:   pf_1 = addis(gpowgs(p,f), -1);
1.2     ! noro     1357:   if (f==1)
        !          1358:   {
        !          1359:     v = zerocol(N);
        !          1360:     v[1] = gener(p)[2];
        !          1361:   }
1.1       noro     1362:   else
                   1363:   {
1.2     ! noro     1364:     GEN T, modpr = zk_to_ff_init(nf, &pr, &T, &p);
        !          1365:     v = ff_to_nf(FpXQ_gener(T,p), modpr);
        !          1366:     v = algtobasis(nf, v);
1.1       noro     1367:   }
                   1368:   /* v generates  (Z_K / pr)^* */
1.2     ! noro     1369:   if(DEBUGLEVEL>3) fprintferr("v computed\n");
1.1       noro     1370:   e = itos(ep); prk=(e==1)? pr: idealpow(nf,pr,ep);
1.2     ! noro     1371:   if(DEBUGLEVEL>3) fprintferr("prk computed\n");
1.1       noro     1372:   g0 = v;
                   1373:   uv = NULL; /* gcc -Wall */
                   1374:   if (x)
                   1375:   {
1.2     ! noro     1376:     uv = idealaddtoone(nf,prk, idealdivpowprime(nf,x,pr,ep));
1.1       noro     1377:     g0 = makeprimetoideal(nf,x,uv,v);
1.2     ! noro     1378:     if(DEBUGLEVEL>3) fprintferr("g0 computed\n");
1.1       noro     1379:   }
                   1380:
                   1381:   p1 = cgetg(6,t_VEC); list = _vec(p1);
                   1382:   p1[1] = (long)_vec(pf_1);
                   1383:   p1[2] = (long)_vec(v);
                   1384:   p1[3] = (long)_vec(g0);
                   1385:   p1[4] = (long)_vec(zsigne(nf,g0,arch));
                   1386:   p1[5] = un;
                   1387:   if (e==1) return gerepilecopy(av, list);
                   1388:
                   1389:   a=1; b=2; av1=avma;
                   1390:   pra = prh; prb = (e==2)? prk: idealpow(nf,pr,gdeux);
                   1391:   for(;;)
                   1392:   {
1.2     ! noro     1393:     if(DEBUGLEVEL>3) fprintferr("  treating a = %ld, b = %ld\n",a,b);
1.1       noro     1394:     p1 = zidealij(pra,prb);
                   1395:     newgen = dummycopy((GEN)p1[2]);
                   1396:     p3 = cgetg(lg(newgen),t_VEC);
1.2     ! noro     1397:     if(DEBUGLEVEL>3) fprintferr("zidealij done\n");
1.1       noro     1398:     for (i=1; i<lg(newgen); i++)
                   1399:     {
                   1400:       if (x) newgen[i]=(long)makeprimetoideal(nf,x,uv,(GEN)newgen[i]);
                   1401:       p3[i]=(long)zsigne(nf,(GEN)newgen[i],arch);
                   1402:     }
                   1403:     p4 = cgetg(6,t_VEC);
                   1404:     p4[1] = p1[1];
                   1405:     p4[2] = p1[2];
                   1406:     p4[3] = (long)newgen;
                   1407:     p4[4] = (long)p3;
                   1408:     p4[5] = p1[3]; p4 = _vec(p4);
                   1409:
                   1410:     a=b; b=min(e,b<<1); tetpil = avma;
                   1411:     list = concat(list, p4);
                   1412:     if (a==b) return gerepile(av,tetpil,list);
                   1413:
                   1414:     pra = gcopy(prb);
                   1415:     gptr[0]=&pra; gptr[1]=&list;
                   1416:     gerepilemanysp(av1,tetpil,gptr,2);
1.2     ! noro     1417:     prb = (b==(a<<1))? idealpows(nf,pr,b): prk;
1.1       noro     1418:   }
                   1419: }
                   1420:
1.2     ! noro     1421: /* x integral ideal, compute elements in 1+x whose sign matrix is invertible */
1.1       noro     1422: GEN
                   1423: zarchstar(GEN nf,GEN x,GEN arch,long nba)
                   1424: {
1.2     ! noro     1425:   long limr, N, i, j, k, r, rr, zk, lgmat;
        !          1426:   gpmem_t av;
1.1       noro     1427:   GEN p1,y,bas,genarch,mat,lambda,nfun,vun;
                   1428:
1.2     ! noro     1429:   if (nba < 0)
        !          1430:   {
        !          1431:     nba = 0;
        !          1432:     for (i=1; i<lg(arch); i++)
        !          1433:       if (signe(arch[i])) nba++;
        !          1434:   }
1.1       noro     1435:   y = cgetg(4,t_VEC);
                   1436:   if (!nba)
                   1437:   {
                   1438:     y[1]=lgetg(1,t_VEC);
                   1439:     y[2]=lgetg(1,t_VEC);
                   1440:     y[3]=lgetg(1,t_MAT); return y;
                   1441:   }
                   1442:   N = degpol(nf[1]);
                   1443:   p1 = cgetg(nba+1,t_VEC); for (i=1; i<=nba; i++) p1[i] = deux;
                   1444:   y[1] = (long)p1; av = avma;
                   1445:   if (N == 1)
                   1446:   {
                   1447:     p1 = gerepileuptoint(av, subsi(1, shifti(gcoeff(x,1,1),1)));
                   1448:     y[2] = (long)_vec(_col(p1));
                   1449:     y[3] = (long)gscalmat(gun,1); return y;
                   1450:   }
1.2     ! noro     1451:   zk = gcmp1(gcoeff(x,1,1));
1.1       noro     1452:   genarch = cgetg(nba+1,t_VEC);
                   1453:   mat = cgetg(nba+1,t_MAT); setlg(mat,2);
1.2     ! noro     1454:   for (i=1; i<=nba; i++) mat[i] = lgetg(nba+1, t_VECSMALL);
1.1       noro     1455:   lambda = cgetg(N+1, t_VECSMALL);
                   1456:
                   1457:   bas = dummycopy(gmael(nf,5,1)); r = lg(arch);
                   1458:   for (k=1,i=1; i<r; i++)
                   1459:     if (signe(arch[i]))
                   1460:     {
                   1461:       if (k < i)
                   1462:         for (j=1; j<=N; j++) coeff(bas,k,j) = coeff(bas,i,j);
                   1463:       k++;
                   1464:     }
                   1465:   r = nba+1; for (i=1; i<=N; i++) setlg(bas[i], r);
                   1466:   if (!zk)
                   1467:   {
1.2     ! noro     1468:     x = lllint_ip(x,4);
1.1       noro     1469:     bas = gmul(bas, x);
                   1470:   }
                   1471:
                   1472:   vun = cgetg(nba+1, t_COL);
                   1473:   for (i=1; i<=nba; i++) vun[i] = un;
                   1474:   nfun = gscalcol(gun, N); lgmat = 1;
                   1475:   for (r=1, rr=3; ; r<<=1, rr=(r<<1)+1)
                   1476:   {
                   1477:     if (DEBUGLEVEL>5) fprintferr("zarchstar: r = %ld\n",r);
                   1478:     p1 = gpowgs(stoi(rr),N);
1.2     ! noro     1479:     limr = (cmpis(p1,BIGINT) >= 0)? BIGINT: p1[2];
1.1       noro     1480:     limr = (limr-1)>>1;
                   1481:     k = zk? rr: 1; /* to avoid 0 */
                   1482:     for ( ; k<=limr; k++)
                   1483:     {
1.2     ! noro     1484:       gpmem_t av1=avma;
        !          1485:       long kk = k;
1.1       noro     1486:       GEN alpha = vun;
                   1487:       for (i=1; i<=N; i++)
                   1488:       {
                   1489:         lambda[i] = (kk+r)%rr - r; kk/=rr;
                   1490:         if (lambda[i])
                   1491:           alpha = gadd(alpha, gmulsg(lambda[i],(GEN)bas[i]));
                   1492:       }
                   1493:       p1 = (GEN)mat[lgmat];
                   1494:       for (i=1; i<=nba; i++)
1.2     ! noro     1495:         p1[i] = (gsigne((GEN)alpha[i]) < 0)? 1: 0;
1.1       noro     1496:
1.2     ! noro     1497:       if (u_FpM_deplin(mat, 2)) avma = av1;
1.1       noro     1498:       else
                   1499:       { /* new vector indep. of previous ones */
                   1500:         avma = av1; alpha = nfun;
                   1501:         for (i=1; i<=N; i++)
                   1502:           if (lambda[i])
                   1503:             alpha = gadd(alpha, gmulsg(lambda[i],(GEN)x[i]));
                   1504:        genarch[lgmat++] = (long)alpha;
                   1505:        if (lgmat > nba)
                   1506:        {
                   1507:           GEN *gptr[2];
1.2     ! noro     1508:           mat = small_to_mat( u_FpM_inv(mat, 2) );
        !          1509:           gptr[0]=&genarch; gptr[1]=&mat;
1.1       noro     1510:           gerepilemany(av,gptr,2);
                   1511:          y[2]=(long)genarch;
                   1512:           y[3]=(long)mat; return y;
                   1513:        }
                   1514:         setlg(mat,lgmat+1);
                   1515:       }
                   1516:     }
                   1517:   }
                   1518: }
                   1519:
                   1520: GEN
                   1521: zinternallog_pk(GEN nf, GEN a0, GEN y, GEN pr, GEN prk, GEN list, GEN *psigne)
                   1522: {
                   1523:   GEN a = a0, L,e,p1,cyc,gen;
                   1524:   long i,j, llist = lg(list)-1;
                   1525:
                   1526:   e = gzero; /* gcc -Wall */
                   1527:   for (j=1; j<=llist; j++)
                   1528:   {
                   1529:     L = (GEN)list[j]; cyc=(GEN)L[1]; gen=(GEN)L[2];
                   1530:     if (j==1)
1.2     ! noro     1531:       p1 = nf_PHlog(nf,a,(GEN)gen[1],pr);
1.1       noro     1532:     else
                   1533:     {
                   1534:       p1 = (GEN)a[1]; a[1] = laddsi(-1,(GEN)a[1]);
                   1535:       e = gmul((GEN)L[5],a); a[1] = (long)p1;
                   1536:       /* here lg(e) == lg(cyc) */
                   1537:       p1 = (GEN)e[1];
                   1538:     }
                   1539:     for (i=1; i<lg(cyc); i++, p1 = (GEN)e[i])
                   1540:     {
                   1541:       p1 = modii(negi(p1), (GEN)cyc[i]);
                   1542:       *++y = lnegi(p1);
                   1543:       if (!signe(p1)) continue;
                   1544:
                   1545:       if (psigne && mpodd(p1)) *psigne = gadd(*psigne,gmael(L,4,i));
                   1546:       if (j == llist) continue;
                   1547:
                   1548:       if (DEBUGLEVEL>5) fprintferr("do element_powmodideal\n");
                   1549:       p1 = element_powmodideal(nf,(GEN)gen[i],p1,prk);
                   1550:       a = element_mulmodideal(nf,a,p1,prk);
                   1551:     }
                   1552:   }
                   1553:   return y;
                   1554: }
                   1555:
                   1556: /* Retourne la decomposition de a sur les nbgen generateurs successifs
                   1557:  * contenus dans list_set et si index !=0 on ne fait ce calcul que pour
                   1558:  * l'ideal premier correspondant a cet index en mettant a 0 les autres
                   1559:  * composantes
                   1560:  */
                   1561: static GEN
                   1562: zinternallog(GEN nf,GEN a,GEN list_set,long nbgen,GEN arch,GEN fa,long index)
                   1563: {
                   1564:   GEN prlist,ep,y0,y,ainit,list,pr,prk,cyc,psigne,p1,p2;
1.2     ! noro     1565:   gpmem_t av;
        !          1566:   long nbp,i,j,k;
1.1       noro     1567:
                   1568:   y0 = y = cgetg(nbgen+1,t_COL); av=avma;
                   1569:   prlist=(GEN)fa[1]; ep=(GEN)fa[2]; nbp=lg(ep)-1;
                   1570:   i=typ(a); if (is_extscalar_t(i)) a = algtobasis(nf,a);
                   1571:   if (DEBUGLEVEL>3)
                   1572:   {
                   1573:     fprintferr("entering zinternallog, "); flusherr();
                   1574:     if (DEBUGLEVEL>5) fprintferr("with a = %Z\n",a);
                   1575:   }
                   1576:   ainit = a; psigne = zsigne(nf,ainit,arch);
                   1577:   p2 = NULL; /* gcc -Wall */
                   1578:   for (k=1; k<=nbp; k++)
                   1579:   {
                   1580:     list = (GEN)list_set[k];
                   1581:     if (index && index!=k)
                   1582:     {
                   1583:       for (j=1; j<lg(list); j++)
                   1584:       {
                   1585:         cyc = gmael(list,j,1);
                   1586:         for (i=1; i<lg(cyc); i++) *++y = zero;
                   1587:       }
                   1588:       continue;
                   1589:     }
                   1590:     pr = (GEN)prlist[k]; prk = idealpow(nf,pr,(GEN)ep[k]);
                   1591:     y = zinternallog_pk(nf, ainit, y, pr, prk, list, &psigne);
                   1592:   }
                   1593:   p1 = lift_intern(gmul(gmael(list_set,k,3), psigne));
                   1594:   avma=av; for (i=1; i<lg(p1); i++) *++y = p1[i];
                   1595:   if (DEBUGLEVEL>3) { fprintferr("leaving\n"); flusherr(); }
                   1596:   for (i=1; i<=nbgen; i++) y0[i] = licopy((GEN)y0[i]);
                   1597:   return y0;
                   1598: }
                   1599:
                   1600: static GEN
                   1601: compute_gen(GEN nf, GEN u1, GEN gen, GEN bid)
                   1602: {
                   1603:   long i, c = lg(u1);
                   1604:   GEN basecl = cgetg(c,t_VEC);
                   1605:
                   1606:   for (i=1; i<c; i++)
                   1607:     basecl[i] = (long)famat_to_nf_modidele(nf, gen, (GEN)u1[i], bid);
                   1608:   return basecl;
                   1609: }
                   1610:
                   1611: /* Compute [[ideal,arch], [h,[cyc],[gen]], idealfact, [liste], U]
                   1612:    gen not computed unless add_gen != 0 */
                   1613: GEN
                   1614: zidealstarinitall(GEN nf, GEN ideal,long add_gen)
                   1615: {
1.2     ! noro     1616:   gpmem_t av = avma;
        !          1617:   long i,j,k,nba,nbp,R1,nbgen,cp;
1.1       noro     1618:   GEN p1,y,h,cyc,U,u1,fa,fa2,ep,x,arch,list,sarch,gen;
                   1619:
                   1620:   nf = checknf(nf); R1=itos(gmael(nf,2,1));
                   1621:   if (typ(ideal)==t_VEC && lg(ideal)==3)
                   1622:   {
                   1623:     arch=(GEN)ideal[2]; ideal = (GEN)ideal[1];
                   1624:     i = typ(arch);
                   1625:     if (!is_vec_t(i) || lg(arch) != R1+1)
                   1626:       err(talker,"incorrect archimedean component in zidealstarinit");
                   1627:     for (nba=0,i=1; i<=R1; i++)
                   1628:       if (signe(arch[i])) nba++;
                   1629:   }
                   1630:   else
                   1631:   {
                   1632:     arch=cgetg(R1+1,t_VEC);
                   1633:     for (nba=0,i=1; i<=R1; i++) arch[i]=zero;
                   1634:   }
                   1635:   x = idealhermite(nf,ideal);
                   1636:   if (!gcmp1(denom(x)))
                   1637:     err(talker,"zidealstarinit needs an integral ideal: %Z",x);
                   1638:   p1=cgetg(3,t_VEC); ideal=p1;
                   1639:   p1[1]=(long)x;
                   1640:   p1[2]=(long)arch;
                   1641:
                   1642:   fa=idealfactor(nf,x); list=(GEN)fa[1]; ep=(GEN)fa[2];
                   1643:   nbp=lg(list)-1; fa2=cgetg(nbp+2,t_VEC);
                   1644:
                   1645:   gen = cgetg(1,t_VEC);
                   1646:   p1 = (nbp==1)? (GEN)NULL: x;
                   1647:   for (i=1; i<=nbp; i++)
                   1648:   {
                   1649:     GEN L = zprimestar(nf,(GEN)list[i],(GEN)ep[i],p1,arch);
                   1650:     fa2[i] = (long)L;
                   1651:     for (j=1; j<lg(L); j++) gen = concatsp(gen,gmael(L,j,3));
                   1652:   }
                   1653:   sarch = zarchstar(nf,x,arch,nba);
                   1654:   fa2[i]=(long)sarch;
                   1655:   gen = concatsp(gen,(GEN)sarch[2]);
                   1656:
                   1657:   nbgen = lg(gen)-1;
                   1658:   h=cgetg(nbgen+1,t_MAT); cp=0;
                   1659:   for (i=1; i<=nbp; i++)
                   1660:   {
                   1661:     list = (GEN)fa2[i];
                   1662:     for (j=1; j<lg(list); j++)
                   1663:     {
                   1664:       GEN a, L = (GEN)list[j], e = (GEN)L[1], g = (GEN)L[3];
                   1665:       for (k=1; k<lg(g); k++)
                   1666:       {
                   1667:        a = element_powmodidele(nf,(GEN)g[k],(GEN)e[k],ideal,sarch);
                   1668:        h[++cp] = lneg(zinternallog(nf,a,fa2,nbgen,arch,fa,i));
                   1669:        coeff(h,cp,cp) = e[k];
                   1670:       }
                   1671:     }
                   1672:   }
                   1673:   for (j=1; j<=nba; j++) { h[++cp]=(long)zerocol(nbgen); coeff(h,cp,cp)=deux; }
                   1674:   if (cp!=nbgen) err(talker,"bug in zidealstarinit");
                   1675:   h = hnfall_i(h,NULL,0);
                   1676:   cyc = smithrel(h, &U, add_gen? &u1: NULL);
                   1677:   p1 = cgetg(add_gen? 4: 3, t_VEC);
                   1678:   p1[1] = (long)detcyc(cyc);
                   1679:   p1[2] = (long)cyc;
                   1680:
                   1681:   y = cgetg(6,t_VEC);
                   1682:   y[1] = (long)ideal;
                   1683:   y[2] = (long)p1;
                   1684:   y[3] = (long)fa;
                   1685:   y[4] = (long)fa2;
                   1686:   y[5] = (long)U;
                   1687:   if (add_gen) p1[3] = (long)compute_gen(nf,u1,gen, y);
                   1688:   return gerepilecopy(av, y);
                   1689: }
                   1690:
                   1691: GEN
                   1692: zidealstarinitgen(GEN nf, GEN ideal)
                   1693: {
                   1694:   return zidealstarinitall(nf,ideal,1);
                   1695: }
                   1696:
                   1697: GEN
                   1698: zidealstarinit(GEN nf, GEN ideal)
                   1699: {
                   1700:   return zidealstarinitall(nf,ideal,0);
                   1701: }
                   1702:
                   1703: GEN
                   1704: zidealstar(GEN nf, GEN ideal)
                   1705: {
1.2     ! noro     1706:   gpmem_t av = avma;
1.1       noro     1707:   GEN y = zidealstarinitall(nf,ideal,1);
                   1708:   return gerepilecopy(av,(GEN)y[2]);
                   1709: }
                   1710:
                   1711: GEN
                   1712: idealstar0(GEN nf, GEN ideal,long flag)
                   1713: {
                   1714:   switch(flag)
                   1715:   {
                   1716:     case 0: return zidealstar(nf,ideal);
                   1717:     case 1: return zidealstarinit(nf,ideal);
                   1718:     case 2: return zidealstarinitgen(nf,ideal);
                   1719:     default: err(flagerr,"idealstar");
                   1720:   }
                   1721:   return NULL; /* not reached */
                   1722: }
                   1723:
                   1724: void
                   1725: check_nfelt(GEN x, GEN *den)
                   1726: {
                   1727:   long l = lg(x), i;
                   1728:   GEN t, d = NULL;
                   1729:   if (typ(x) != t_COL) err(talker,"%Z not a nfelt", x);
                   1730:   for (i=1; i<l; i++)
                   1731:   {
                   1732:     t = (GEN)x[i];
                   1733:     switch (typ(t))
                   1734:     {
                   1735:       case t_INT: case t_INTMOD: break;
                   1736:       case t_FRACN: case t_FRAC:
                   1737:         if (!d) d = (GEN)t[2]; else d = mpppcm(d, (GEN)t[2]);
                   1738:         break;
                   1739:       default: err(talker,"%Z not a nfelt", x);
                   1740:     }
                   1741:   }
                   1742:   *den = d;
                   1743: }
                   1744:
                   1745: /* Given x (not necessarily integral), and bid as output by zidealstarinit,
                   1746:  * compute the vector of components on the generators bid[2].
                   1747:  * Assume (x,bid) = 1 */
                   1748: GEN
                   1749: zideallog(GEN nf, GEN x, GEN bid)
                   1750: {
1.2     ! noro     1751:   gpmem_t av;
        !          1752:   long l,i,N,c;
1.1       noro     1753:   GEN fa,fa2,ideal,arch,den,p1,cyc,y;
                   1754:
                   1755:   nf=checknf(nf); checkbid(bid);
                   1756:   cyc=gmael(bid,2,2); c=lg(cyc);
                   1757:   y=cgetg(c,t_COL); av=avma;
                   1758:   N = degpol(nf[1]); ideal = (GEN) bid[1];
                   1759:   if (typ(ideal)==t_VEC && lg(ideal)==3)
                   1760:     arch = (GEN)ideal[2];
                   1761:   else
                   1762:     arch = NULL;
                   1763:   switch(typ(x))
                   1764:   {
                   1765:     case t_INT: case t_FRAC: case t_FRACN:
                   1766:       x = gscalcol_i(x,N); break;
                   1767:     case t_POLMOD: case t_POL:
                   1768:       x = algtobasis(nf,x); break;
                   1769:     case t_MAT:
1.2     ! noro     1770:       if (lg(x) == 1) return zerocol(c-1);
1.1       noro     1771:       return famat_ideallog(nf,(GEN)x[1],(GEN)x[2],bid);
                   1772:     case t_COL: break;
                   1773:     default: err(talker,"not an element in zideallog");
                   1774:   }
                   1775:   if (lg(x) != N+1) err(talker,"not an element in zideallog");
                   1776:   check_nfelt(x, &den);
                   1777:   if (den)
                   1778:   {
                   1779:     GEN g = cgetg(3, t_COL);
                   1780:     GEN e = cgetg(3, t_COL);
1.2     ! noro     1781:     g[1] = (long)Q_muli_to_int(x,den); e[1] = un;
        !          1782:     g[2] = (long)den;                  e[2] = lstoi(-1);
1.1       noro     1783:     p1 = famat_ideallog(nf, g, e, bid);
                   1784:   }
                   1785:   else
                   1786:   {
                   1787:     l=lg(bid[5])-1; fa=(GEN)bid[3]; fa2=(GEN)bid[4];
                   1788:     p1 = zinternallog(nf,x,fa2,l,arch,fa,0);
                   1789:     p1 = gmul((GEN)bid[5],p1); /* apply smith */
                   1790:   }
                   1791:   if (lg(p1)!=c) err(bugparier,"zideallog");
                   1792:   for (i=1; i<c; i++)
                   1793:     y[i] = lmodii((GEN)p1[i],(GEN)cyc[i]);
                   1794:   avma=av; /* following line does a gerepile ! */
                   1795:   for (i=1; i<c; i++)
                   1796:     y[i] = (long)icopy((GEN)y[i]);
                   1797:   return y;
                   1798: }
                   1799:
                   1800: /* bid1, bid2: output from 'zidealstarinit' for coprime modules m1 and m2
                   1801:  * (without arch. part).
                   1802:  * Output: zidealstarinit [[ideal,arch],[h,[cyc],[gen]],idealfact,[liste],U]
                   1803:  * associated to m1 m2 */
                   1804: GEN
                   1805: zidealstarinitjoin(GEN nf, GEN bid1, GEN bid2, long add_gen)
                   1806: {
1.2     ! noro     1807:   gpmem_t av=avma;
        !          1808:   long i,nbp,nbgen,lx1,lx2,l1,l2,lx;
1.1       noro     1809:   GEN module1,module2,struct1,struct2,fact1,fact2,liste1,liste2;
                   1810:   GEN module,liste,fact,U,U1,U2,cyc,cyc1,cyc2,uv;
                   1811:   GEN p1,p2,y,u1,x,fa1,fa2, gen = add_gen? gun: NULL;
                   1812:
                   1813:   nf = checknf(nf); checkbid(bid1); checkbid(bid2);
                   1814:   module1 = (GEN)bid1[1]; struct1 = (GEN)bid1[2]; fact1 = (GEN)bid1[3];
                   1815:   module2 = (GEN)bid2[1]; struct2 = (GEN)bid2[2]; fact2 = (GEN)bid2[3];
                   1816:   x = idealmul(nf,(GEN)module1[1],(GEN)module2[1]);
                   1817:   module = cgetg(3,t_VEC);
                   1818:   module[1] = (long)x;
                   1819:   module[2] = module1[2];
                   1820:   if (!gcmp0((GEN)module1[2]) || !gcmp0((GEN)module2[2]))
                   1821:     err(talker,"non-0 Archimedian components in zidealstarinitjoin");
                   1822:
                   1823:   fa1 = (GEN)fact1[1]; lx1 = lg(fa1);
                   1824:   fa2 = (GEN)fact2[1]; lx2 = lg(fa2);
                   1825:   fact = cgetg(3,t_MAT);
                   1826:   fact[1] = (long)concatsp(fa1,fa2);
                   1827:   fact[2] = (long)concatsp((GEN)fact1[2],(GEN)fact2[2]);
                   1828:   for (i=1; i<lx1; i++)
                   1829:     if (isinvector(fa2,(GEN)fa1[i],lx2-1))
                   1830:       err(talker,"noncoprime ideals in zidealstarinitjoin");
                   1831:
                   1832:   liste1 = (GEN)bid1[4]; lx1 = lg(liste1);
                   1833:   liste2 = (GEN)bid2[4]; lx2 = lg(liste2);
                   1834:   /* concat (liste1 - last elt [zarchstar]) + liste2 */
                   1835:   lx = lx1+lx2-2; liste = cgetg(lx,t_VEC);
                   1836:   for (i=1; i<lx1-1; i++) liste[i] = liste1[i];
                   1837:   for (   ; i<lx; i++)    liste[i] = liste2[i-lx1+2];
                   1838:
                   1839:   U1 = (GEN)bid1[5]; cyc1 = (GEN)struct1[2]; l1 = lg(cyc1);
                   1840:   U2 = (GEN)bid2[5]; cyc2 = (GEN)struct2[2]; l2 = lg(cyc2);
                   1841:   nbgen = l1+l2-2;
                   1842:   cyc = diagonal(concatsp(cyc1,cyc2));
                   1843:   cyc = smithrel(cyc, &U, gen? &u1: NULL);
                   1844:
                   1845:   if (nbgen)
                   1846:     U = concatsp(
                   1847:       gmul(vecextract_i(U, 1,   l1-1), U1) ,
                   1848:       gmul(vecextract_i(U, l1, nbgen), U2)
                   1849:     );
                   1850:
                   1851:   if (gen)
                   1852:   {
                   1853:     if (lg(struct1)<=3 || lg(struct2)<=3)
                   1854:       err(talker,"please apply idealstar(,,2) and not idealstar(,,1)");
                   1855:
                   1856:     uv = idealaddtoone(nf,(GEN)module1[1],(GEN)module2[1]);
                   1857:     p1 = makeprimetoidealvec(nf,x,uv,(GEN)struct1[3]);
                   1858:     p2 = (GEN)uv[1]; uv[1] = uv[2]; uv[2] = (long)p2;
                   1859:     p2 = makeprimetoidealvec(nf,x,uv,(GEN)struct2[3]);
                   1860:     gen = concatsp(p1,p2);
                   1861:     nbp = lg((GEN)fact[1])-1;
                   1862:   }
                   1863:   p1 = cgetg(gen? 4: 3,t_VEC);
                   1864:   p1[1] = (long)detcyc(cyc);
                   1865:   p1[2] = (long)cyc;
                   1866:
                   1867:   y = cgetg(6,t_VEC);
                   1868:   y[1] = (long)module;
                   1869:   y[2] = (long)p1;
                   1870:   y[3] = (long)fact;
                   1871:   y[4] = (long)liste;
                   1872:   y[5] = (long)U;
                   1873:   if (gen) p1[3] = (long)compute_gen(nf,u1,gen, y);
                   1874:   return gerepilecopy(av,y);
                   1875: }
                   1876:
                   1877: /* bid1: output from 'zidealstarinit' for module m1 (without arch. part)
                   1878:  * arch: archimedean part.
                   1879:  * Output: zidealstarinit [[ideal,arch],[h,[cyc],[gen]],idealfact,[liste],U]
                   1880:  * associated to m1.arch */
                   1881: GEN
                   1882: zidealstarinitjoinarch(GEN nf, GEN bid1, GEN arch, long nba, long add_gen)
                   1883: {
1.2     ! noro     1884:   gpmem_t av=avma;
        !          1885:   long i,nbp,lx1;
1.1       noro     1886:   GEN module1,struct1,fact1,liste1,U1,U;
                   1887:   GEN module,liste,cyc,p1,y,u1,x,sarch, gen = add_gen? gun: NULL;
                   1888:
                   1889:   nf = checknf(nf); checkbid(bid1);
                   1890:   module1 = (GEN)bid1[1]; struct1 = (GEN)bid1[2]; fact1 = (GEN)bid1[3];
                   1891:   x = (GEN)module1[1];
                   1892:   module = cgetg(3,t_VEC);
                   1893:   module[1] = (long)x;
                   1894:   module[2] = (long)arch;
                   1895:   if (!gcmp0((GEN)module1[2]))
                   1896:     err(talker,"non-0 Archimedian components in zidealstarinitjoinarch");
                   1897:
                   1898:   sarch = zarchstar(nf,x,arch,nba);
                   1899:   liste1 = (GEN)bid1[4]; lx1 = lg(liste1);
                   1900:   liste = cgetg(lx1,t_VEC);
                   1901:   for (i=1; i<lx1-1; i++) liste[i]=liste1[i];
                   1902:   liste[i] = (long)sarch;
                   1903:
                   1904:   U1 = (GEN)bid1[5]; lx1 = lg(U1);
                   1905:   cyc = diagonal(concatsp((GEN)struct1[2],(GEN)sarch[1]));
                   1906:   cyc = smithrel(cyc, &U, gen? &u1: NULL);
                   1907:
                   1908:   if (gen)
                   1909:   {
                   1910:     if (lg(struct1)<=3)
                   1911:       err(talker,"please apply idealstar(,,2) and not idealstar(,,1)");
                   1912:     gen = concatsp((GEN)struct1[3],(GEN)sarch[2]);
                   1913:     nbp = lg((GEN)fact1[1])-1;
                   1914:   }
                   1915:   p1 = cgetg(gen? 4: 3, t_VEC);
                   1916:   p1[1] = (long)detcyc(cyc);
                   1917:   p1[2] = (long)cyc;
                   1918:
                   1919:   y = cgetg(6,t_VEC);
                   1920:   y[1] = (long)module;
                   1921:   y[2] = (long)p1;
                   1922:   y[3] = (long)fact1;
                   1923:   y[4] = (long)liste;
                   1924:   y[5] = (long)U;
                   1925:   if (gen) p1[3] = (long)compute_gen(nf,u1,gen, y);
                   1926:   return gerepilecopy(av,y);
                   1927: }
                   1928:
                   1929: /* calcule la matrice des zinternallog des unites */
                   1930: GEN
                   1931: logunitmatrix(GEN nf,GEN funits,GEN racunit,GEN bid)
                   1932: {
                   1933:   long R,j,sizeh;
                   1934:   GEN m,fa2,fa,arch;
                   1935:
                   1936:   R=lg(funits)-1; m=cgetg(R+2,t_MAT);
                   1937:   fa2=(GEN)bid[4]; sizeh=lg(bid[5])-1; arch=gmael(bid,1,2);
                   1938:   fa=(GEN)bid[3];
                   1939:   m[1]=(long)zinternallog(nf,racunit,fa2,sizeh,arch,fa,0);
                   1940:   for (j=2; j<=R+1; j++)
                   1941:     m[j]=(long)zinternallog(nf,(GEN)funits[j-1],fa2,sizeh,arch,fa,0);
                   1942:   return m;
                   1943: }
                   1944:
                   1945: /* calcule la matrice des zinternallog des unites */
                   1946: static GEN
                   1947: logunitmatrixarch(GEN nf,GEN funits,GEN racunit,GEN bid)
                   1948: {
                   1949:   long R,j;
                   1950:   GEN m,liste,structarch,arch;
                   1951:
                   1952:   R=lg(funits)-1; m=cgetg(R+2,t_MAT); arch=gmael(bid,1,2);
                   1953:   liste=(GEN)bid[4]; structarch=(GEN)liste[lg(liste)-1];
                   1954:   m[1]=(long)zsigne(nf,racunit,arch);
                   1955:   for (j=2; j<=R+1; j++)
                   1956:     m[j]=(long)zsigne(nf,(GEN)funits[j-1],arch);
                   1957:   return lift_intern(gmul((GEN)structarch[3],m));
                   1958: }
                   1959:
                   1960: static void
                   1961: init_units(GEN bnf, GEN *funits, GEN *racunit)
                   1962: {
                   1963:   GEN p1;
                   1964:   bnf = checkbnf(bnf); p1=(GEN)bnf[8];
                   1965:   if (lg(p1)==5) *funits=(GEN)buchfu(bnf)[1];
                   1966:   else
                   1967:   {
                   1968:     if (lg(p1)!=7) err(talker,"incorrect big number field");
                   1969:     *funits=(GEN)p1[5];
                   1970:   }
                   1971:   *racunit=gmael(p1,4,2);
                   1972: }
                   1973:
                   1974: /*  flag &1 : generateurs, sinon non
                   1975:  *  flag &2 : unites, sinon pas.
                   1976:  *  flag &4 : ideaux, sinon zidealstar.
                   1977:  */
                   1978: static GEN
                   1979: ideallistzstarall(GEN bnf,long bound,long flag)
                   1980: {
                   1981:   byteptr ptdif=diffptr;
1.2     ! noro     1982:   gpmem_t lim,av0=avma,av;
        !          1983:   long i,j,k,l,q2,lp1,q;
1.1       noro     1984:   long do_gen = flag & 1, do_units = flag & 2, big_id = !(flag & 4);
                   1985:   GEN y,nf,p,z,z2,p1,p2,p3,fa,pr,ideal,lu,lu2,funits,racunit,embunit;
                   1986:
                   1987:   nf = checknf(bnf);
                   1988:   if (bound <= 0) return cgetg(1,t_VEC);
                   1989:   z = cgetg(bound+1,t_VEC);
                   1990:   for (i=2; i<=bound; i++) z[i] = lgetg(1,t_VEC);
                   1991:
                   1992:   ideal = idmat(degpol(nf[1]));
                   1993:   if (big_id) ideal = zidealstarinitall(nf,ideal,do_gen);
                   1994:   z[1] = (long)_vec(ideal);
                   1995:   if (do_units)
                   1996:   {
                   1997:     init_units(bnf,&funits,&racunit);
                   1998:     lu = cgetg(bound+1,t_VEC);
                   1999:     for (i=2; i<=bound; i++) lu[i]=lgetg(1,t_VEC);
                   2000:     lu[1] = (long)_vec(logunitmatrix(nf,funits,racunit,ideal));
                   2001:   }
                   2002:
                   2003:   p=cgeti(3); p[1]=evalsigne(1) | evallgefint(3);
                   2004:   av=avma; lim=stack_lim(av,1);
                   2005:   lu2 = embunit = NULL; /* gcc -Wall */
                   2006:   if (bound > (long)maxprime()) err(primer1);
                   2007:   for (p[2]=0; p[2]<=bound; )
                   2008:   {
1.2     ! noro     2009:     NEXT_PRIME_VIADIFF(p[2], ptdif);
1.1       noro     2010:     if (DEBUGLEVEL>1) { fprintferr("%ld ",p[2]); flusherr(); }
                   2011:     fa = primedec(nf,p);
                   2012:     for (j=1; j<lg(fa); j++)
                   2013:     {
                   2014:       pr = (GEN)fa[j]; p1 = powgi(p,(GEN)pr[4]);
                   2015:       if (is_bigint(p1) || (q = itos(p1)) > bound) continue;
                   2016:
                   2017:       q2=q; ideal=pr; z2=dummycopy(z);
                   2018:       if (do_units) lu2=dummycopy(lu);
                   2019:       for (l=2; ;l++)
                   2020:       {
                   2021:         if (big_id) ideal = zidealstarinitall(nf,ideal,do_gen);
                   2022:         if (do_units) embunit = logunitmatrix(nf,funits,racunit,ideal);
                   2023:         for (i=q; i<=bound; i+=q)
                   2024:         {
                   2025:           p1 = (GEN)z[i/q]; lp1 = lg(p1);
                   2026:           if (lp1 == 1) continue;
                   2027:
                   2028:           p2 = cgetg(lp1,t_VEC);
                   2029:           for (k=1; k<lp1; k++)
                   2030:             if (big_id)
                   2031:               p2[k] = (long)zidealstarinitjoin(nf,(GEN)p1[k],ideal,do_gen);
                   2032:             else
                   2033:               p2[k] = (long)idealmul(nf,(GEN)p1[k],ideal);
                   2034:           z2[i] = (long)concatsp((GEN)z2[i],p2);
                   2035:           if (do_units)
                   2036:           {
                   2037:             p1 = (GEN)lu[i/q];
                   2038:             p2 = cgetg(lp1,t_VEC);
                   2039:             for (k=1; k<lp1; k++)
                   2040:               p2[k] = (long)vconcat((GEN)p1[k],embunit);
                   2041:             lu2[i] = (long)concatsp((GEN)lu2[i],p2);
                   2042:           }
                   2043:         }
                   2044:         q *= q2; if ((ulong)q > (ulong)bound) break;
                   2045:         ideal = idealpows(nf,pr,l);
                   2046:       }
                   2047:       z = z2; if (do_units) lu = lu2;
                   2048:     }
                   2049:     if (low_stack(lim, stack_lim(av,1)))
                   2050:     {
                   2051:       GEN *gptr[2]; gptr[0]=&z; gptr[1]=&lu;
                   2052:       if(DEBUGMEM>1) err(warnmem,"ideallistzstarall");
                   2053:       gerepilemany(av,gptr,do_units?2:1);
                   2054:     }
                   2055:   }
                   2056:   if (!do_units) return gerepilecopy(av0, z);
                   2057:   y = cgetg(3,t_VEC);
                   2058:   y[1] = lcopy(z);
                   2059:   lu2 = cgetg(lg(z),t_VEC);
                   2060:   for (i=1; i<lg(z); i++)
                   2061:   {
                   2062:     p1=(GEN)z[i]; p2=(GEN)lu[i]; lp1=lg(p1);
                   2063:     p3=cgetg(lp1,t_VEC); lu2[i]=(long)p3;
                   2064:     for (j=1; j<lp1; j++) p3[j] = lmul(gmael(p1,j,5),(GEN)p2[j]);
                   2065:   }
                   2066:   y[2]=(long)lu2; return gerepileupto(av0, y);
                   2067: }
                   2068:
                   2069: GEN
                   2070: ideallist0(GEN bnf,long bound, long flag)
                   2071: {
                   2072:   if (flag<0 || flag>4) err(flagerr,"ideallist");
                   2073:   return ideallistzstarall(bnf,bound,flag);
                   2074: }
                   2075:
                   2076: GEN
                   2077: ideallistzstar(GEN nf,long bound)
                   2078: {
                   2079:   return ideallistzstarall(nf,bound,0);
                   2080: }
                   2081:
                   2082: GEN
                   2083: ideallistzstargen(GEN nf,long bound)
                   2084: {
                   2085:   return ideallistzstarall(nf,bound,1);
                   2086: }
                   2087:
                   2088: GEN
                   2089: ideallistunit(GEN nf,long bound)
                   2090: {
                   2091:   return ideallistzstarall(nf,bound,2);
                   2092: }
                   2093:
                   2094: GEN
                   2095: ideallistunitgen(GEN nf,long bound)
                   2096: {
                   2097:   return ideallistzstarall(nf,bound,3);
                   2098: }
                   2099:
                   2100: GEN
                   2101: ideallist(GEN bnf,long bound)
                   2102: {
                   2103:   return ideallistzstarall(bnf,bound,4);
                   2104: }
                   2105:
                   2106: static GEN
                   2107: ideallist_arch(GEN nf,GEN list,GEN arch,long flun)
                   2108: {
                   2109:   long nba,i,j,lx,ly;
                   2110:   GEN p1,z,p2;
                   2111:
1.2     ! noro     2112:   if (typ(arch) != t_VEC) err(typeer,"ideallistarch");
1.1       noro     2113:   nba=0; for (i=1; i<lg(arch); i++) if (signe(arch[i])) nba++;
                   2114:   lx=lg(list); z=cgetg(lx,t_VEC);
                   2115:   for (i=1; i<lx; i++)
                   2116:   {
                   2117:     p2=(GEN)list[i]; checkbid(p2); ly=lg(p2);
                   2118:     p1=cgetg(ly,t_VEC); z[i]=(long)p1;
                   2119:     for (j=1; j<ly; j++)
                   2120:       p1[j]=(long)zidealstarinitjoinarch(nf,(GEN)p2[j],arch,nba,flun);
                   2121:   }
                   2122:   return z;
                   2123: }
                   2124:
                   2125: static GEN
                   2126: ideallistarchall(GEN bnf,GEN list,GEN arch,long flag)
                   2127: {
1.2     ! noro     2128:   gpmem_t av;
1.1       noro     2129:   long i,j,lp1, do_units = flag & 2;
                   2130:   GEN nf = checknf(bnf), p1,p2,p3,racunit,funits,lu2,lu,embunit,z,y;
                   2131:
                   2132:   if (typ(list) != t_VEC || (do_units && lg(list) != 3))
                   2133:     err(typeer, "ideallistarch");
                   2134:   if (lg(list) == 1) return cgetg(1,t_VEC);
                   2135:   if (do_units)
                   2136:   {
                   2137:     y = cgetg(3,t_VEC);
                   2138:     z = (GEN)list[1];
                   2139:     lu= (GEN)list[2]; if (typ(lu) != t_VEC) err(typeer, "ideallistarch");
                   2140:   }
                   2141:   else
                   2142:   {
                   2143:     z = list;
                   2144:     y = lu = NULL; /* gcc -Wall */
                   2145:   }
                   2146:   if (typ(z) != t_VEC) err(typeer, "ideallistarch");
                   2147:   z = ideallist_arch(nf,z,arch, flag & 1);
                   2148:   if (!do_units) return z;
                   2149:
                   2150:   y[1]=(long)z; av=avma;
                   2151:   init_units(bnf,&funits,&racunit);
                   2152:   lu2=cgetg(lg(z),t_VEC);
                   2153:   for (i=1; i<lg(z); i++)
                   2154:   {
                   2155:     p1=(GEN)z[i]; p2=(GEN)lu[i]; lp1=lg(p1);
                   2156:     p3=cgetg(lp1,t_VEC); lu2[i]=(long)p3;
                   2157:     for (j=1; j<lp1; j++)
                   2158:     {
                   2159:       embunit = logunitmatrixarch(nf,funits,racunit,(GEN)p1[j]);
                   2160:       p3[j] = lmul(gmael(p1,j,5), vconcat((GEN)p2[j],embunit));
                   2161:     }
                   2162:   }
                   2163:   y[2]=lpilecopy(av,lu2); return y;
                   2164: }
                   2165:
                   2166: GEN
                   2167: ideallistarch(GEN nf, GEN list, GEN arch)
                   2168: {
                   2169:   return ideallistarchall(nf,list,arch,0);
                   2170: }
                   2171:
                   2172: GEN
                   2173: ideallistarchgen(GEN nf, GEN list, GEN arch)
                   2174: {
                   2175:   return ideallistarchall(nf,list,arch,1);
                   2176: }
                   2177:
                   2178: GEN
                   2179: ideallistunitarch(GEN bnf,GEN list,GEN arch)
                   2180: {
                   2181:   return ideallistarchall(bnf,list,arch,2);
                   2182: }
                   2183:
                   2184: GEN
                   2185: ideallistunitarchgen(GEN bnf,GEN list,GEN arch)
                   2186: {
                   2187:   return ideallistarchall(bnf,list,arch,3);
                   2188: }
                   2189:
                   2190: GEN
                   2191: ideallistarch0(GEN nf, GEN list, GEN arch,long flag)
                   2192: {
                   2193:   if (!arch) arch=cgetg(1,t_VEC);
                   2194:   if (flag<0 || flag>3) err(flagerr,"ideallistarch");
                   2195:   return ideallistarchall(nf,list,arch,flag);
                   2196: }

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