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

Annotation of OpenXM_contrib/pari-2.2/src/modules/nffactor.c, Revision 1.2

1.2     ! noro        1: /* $Id: nffactor.c,v 1.104 2002/09/07 13:37:18 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: /*            POLYNOMIAL FACTORIZATION IN A NUMBER FIELD           */
                     19: /*                                                                 */
                     20: /*******************************************************************/
                     21: #include "pari.h"
                     22: #include "parinf.h"
                     23:
1.2     ! noro       24: extern void init_dalloc();
        !            25: extern double *dalloc(size_t n);
        !            26: extern GEN gmul_mati_smallvec(GEN x, GEN y);
        !            27: extern GEN GS_norms(GEN B, long prec);
        !            28: extern GEN RXQX_divrem(GEN x, GEN y, GEN T, GEN *pr);
        !            29: extern GEN RXQX_red(GEN P, GEN T);
        !            30: extern GEN apply_kummer(GEN nf,GEN pol,GEN e,GEN p);
        !            31: extern GEN centermod_i(GEN x, GEN p, GEN ps2);
        !            32: extern GEN dim1proj(GEN prh);
1.1       noro       33: extern GEN hensel_lift_fact(GEN pol, GEN fact, GEN T, GEN p, GEN pev, long e);
1.2     ! noro       34: extern GEN initgaloisborne(GEN T, GEN dn, long prec, GEN *ptL, GEN *ptprep, GEN *ptdis);
        !            35: extern GEN max_modulus(GEN p, double tau);
        !            36: extern GEN mulmat_pol(GEN A, GEN x);
        !            37: extern GEN nfgcd(GEN P, GEN Q, GEN nf, GEN den);
        !            38: extern GEN polsym_gen(GEN P, GEN y0, long n, GEN T, GEN N);
1.1       noro       39: extern GEN sort_factor(GEN y, int (*cmp)(GEN,GEN));
1.2     ! noro       40: extern GEN special_pivot(GEN x);
        !            41: extern GEN trivfact(void);
        !            42: extern GEN vandermondeinverse(GEN L, GEN T, GEN den, GEN prep);
        !            43: extern GEN vconcat(GEN A, GEN B);
        !            44: extern int cmbf_precs(GEN q, GEN A, GEN B, long *a, long *b, GEN *qa, GEN *qb);
        !            45: extern int isrational(GEN x);
        !            46: extern GEN LLL_check_progress(GEN Bnorm, long n0, GEN m, int final, pari_timer *T, long *ti_LLL);
        !            47: extern void remake_GM(GEN nf, nffp_t *F, long prec);
        !            48: #define RXQX_div(x,y,T) RXQX_divrem((x),(y),(T),NULL)
        !            49: #define RXQX_rem(x,y,T) RXQX_divrem((x),(y),(T),ONLY_REM)
1.1       noro       50:
                     51: static GEN nfsqff(GEN nf,GEN pol,long fl);
                     52:
1.2     ! noro       53: /* for nf_bestlift: reconstruction of algebraic integers known mod \wp^k */
        !            54: /* FIXME: assume \wp has degree 1 for now */
        !            55: typedef struct {
        !            56:   long k;    /* input known mod \wp^k */
        !            57:   GEN pk;    /* p^k = Norm(\wp^k)*/
        !            58:   GEN den;   /* denom(prk^-1) = p^k */
        !            59:   GEN prk;   /* |.|^2 LLL-reduced basis (b_i) of \wp^k  (NOT T2-reduced) */
        !            60:   GEN iprk;  /* den * prk^-1 */
        !            61:   GEN GSmin; /* min |b_i^*|^2 */
        !            62:   GEN ZpProj;/* projector to Zp / \wp^k = Z/p^k  (\wp unramified, degree 1) */
        !            63:   GEN tozk;
        !            64:   GEN topow;
        !            65: } nflift_t;
        !            66:
        !            67: typedef struct /* for use in nfsqff */
        !            68: {
        !            69:   nflift_t *L;
        !            70:   GEN nf, pol, fact, res, bound, pr, pk, Br, ZC, dn, polbase, BS_2;
        !            71:   long hint;
        !            72: } nfcmbf_t;
        !            73:
        !            74: GEN
        !            75: RXQX_mul(GEN x, GEN y, GEN T)
1.1       noro       76: {
1.2     ! noro       77:   return RXQX_red(gmul(x,y), T);
        !            78: }
1.1       noro       79:
                     80: static GEN
                     81: unifpol0(GEN nf,GEN pol,long flag)
                     82: {
                     83:   static long n = 0;
                     84:   static GEN vun = NULL;
                     85:   GEN f = (GEN) nf[1];
1.2     ! noro       86:   long i = degpol(f);
        !            87:   gpmem_t av;
1.1       noro       88:
                     89:   if (i != n)
                     90:   {
                     91:     n=i; if (vun) free(vun);
                     92:     vun = (GEN) gpmalloc((n+1)*sizeof(long));
                     93:     vun[0] = evaltyp(t_COL) | evallg(n+1); vun[1]=un;
                     94:     for ( ; i>=2; i--) vun[i]=zero;
                     95:   }
                     96:
                     97:   av = avma;
                     98:   switch(typ(pol))
                     99:   {
                    100:     case t_INT: case t_FRAC: case t_RFRAC:
1.2     ! noro      101:       if (flag) return gcopy(pol);
1.1       noro      102:       pol = gmul(pol,vun); break;
                    103:
                    104:     case t_POL:
1.2     ! noro      105:       if (flag && !degpol(pol)) return gcopy(constant_term(pol));
1.1       noro      106:       pol = gmodulcp(pol,f); /* fall through */
                    107:     case t_POLMOD:
                    108:       pol = algtobasis(nf,pol);
                    109:   }
                    110:   if (flag) pol = basistoalg(nf, lift(pol));
                    111:   return gerepileupto(av,pol);
                    112: }
                    113:
                    114: /* Let pol be a polynomial with coefficients in Z or nf (vectors or polymods)
                    115:  * return the same polynomial with coefficients expressed:
                    116:  *  if flag=0: as vectors (on the integral basis).
                    117:  *  if flag=1: as polymods.
                    118:  */
                    119: GEN
                    120: unifpol(GEN nf,GEN pol,long flag)
                    121: {
                    122:   if (typ(pol)==t_POL && varn(pol) < varn(nf[1]))
                    123:   {
                    124:     long i, d = lgef(pol);
                    125:     GEN p1 = pol;
                    126:
                    127:     pol=cgetg(d,t_POL); pol[1]=p1[1];
                    128:     for (i=2; i<d; i++)
                    129:       pol[i] = (long) unifpol0(nf,(GEN) p1[i],flag);
                    130:
                    131:     return pol;
                    132:   }
                    133:   return unifpol0(nf,(GEN) pol, flag);
                    134: }
                    135:
1.2     ! noro      136: /* factorization of x modulo pr. Assume x already reduced */
        !           137: GEN
        !           138: FqX_factor(GEN x, GEN T, GEN p)
1.1       noro      139: {
1.2     ! noro      140:   GEN rep;
        !           141:   if (!T)
        !           142:   {
        !           143:     rep = factmod0(x, p);
        !           144:     rep[2] = (long)small_to_vec((GEN)rep[2]);
        !           145:   }
        !           146:   else
1.1       noro      147:   {
1.2     ! noro      148:     rep = factmod9(x, p, T);
        !           149:     rep = lift_intern(lift_intern(rep));
1.1       noro      150:   }
1.2     ! noro      151:   return rep;
1.1       noro      152: }
                    153:
1.2     ! noro      154: GEN
        !           155: nffactormod(GEN nf, GEN x, GEN pr)
1.1       noro      156: {
1.2     ! noro      157:   long j, l, vx = varn(x), vn;
        !           158:   gpmem_t av = avma;
        !           159:   GEN z, rep, xrd, modpr, T, p;
        !           160:
        !           161:   nf = checknf(nf);
        !           162:   vn = varn((GEN)nf[1]);
        !           163:   if (typ(x)!=t_POL) err(typeer,"nffactormod");
        !           164:   if (vx >= vn)
        !           165:     err(talker,"polynomial variable must have highest priority in nffactormod");
1.1       noro      166:
1.2     ! noro      167:   modpr = nf_to_ff_init(nf, &pr, &T, &p);
        !           168:   xrd = modprX(x, nf, modpr);
        !           169:   rep = FqX_factor(xrd,T,p);
        !           170:   z = (GEN)rep[1]; l = lg(z);
        !           171:   for (j = 1; j < l; j++) z[j] = (long)modprX_lift((GEN)z[j], modpr);
        !           172:   return gerepilecopy(av, rep);
1.1       noro      173: }
                    174:
1.2     ! noro      175: /* If p doesn't divide bad and has a divisor of degree 1, return the latter. */
1.1       noro      176: static GEN
1.2     ! noro      177: choose_prime(GEN nf, GEN bad, GEN *p, byteptr *PT)
1.1       noro      178: {
1.2     ! noro      179:   GEN  q = icopy(gun), r, x = (GEN)nf[1];
        !           180:   ulong pp = *p? itou(*p): 0;
        !           181:   byteptr pt = *PT;
        !           182:   gpmem_t av = avma;
        !           183:   for (;;)
        !           184:   {
        !           185:     NEXT_PRIME_VIADIFF_CHECK(pp, pt);
        !           186:     if (! smodis(bad,pp)) continue;
        !           187:     affui(pp, q);
        !           188:     r = rootmod(x, q); if (lg(r) > 1) break;
        !           189:     avma = av;
        !           190:   }
        !           191:   r = gsub(polx[varn(x)], lift_intern((GEN)r[1]));
        !           192:   *p = q;
        !           193:   *PT = pt; return apply_kummer(nf,r,gun,q);
1.1       noro      194: }
                    195:
                    196: static GEN
1.2     ! noro      197: QXQ_normalize(GEN P, GEN T)
1.1       noro      198: {
1.2     ! noro      199:   GEN t = leading_term(P);
        !           200:   if (!gcmp1(t))
        !           201:   {
        !           202:     if (is_rational_t(typ(t)))
        !           203:       P = gdiv(P, t);
        !           204:     else
        !           205:       P = RXQX_mul(QX_invmod(t,T), P, T);
        !           206:   }
        !           207:   return P;
1.1       noro      208: }
                    209:
1.2     ! noro      210: /* return the roots of pol in nf */
        !           211: GEN
        !           212: nfroots(GEN nf,GEN pol)
1.1       noro      213: {
1.2     ! noro      214:   gpmem_t av = avma;
        !           215:   int d = degpol(pol);
        !           216:   GEN A,g, T;
        !           217:
        !           218:   nf = checknf(nf); T = (GEN)nf[1];
        !           219:   if (typ(pol) != t_POL) err(notpoler,"nfroots");
        !           220:   if (varn(pol) >= varn(T))
        !           221:     err(talker,"polynomial variable must have highest priority in nfroots");
        !           222:   if (d == 0) return cgetg(1,t_VEC);
        !           223:   if (d == 1)
        !           224:   {
        !           225:     A = gneg_i(gdiv((GEN)pol[2],(GEN)pol[3]));
        !           226:     return gerepilecopy(av, _vec( basistoalg(nf,A) ));
        !           227:   }
        !           228:   A = fix_relative_pol(nf,pol,0);
        !           229:   A = primpart( lift_intern(A) );
        !           230:   if (DEBUGLEVEL>3) fprintferr("test if polynomial is square-free\n");
        !           231:   g = nfgcd(A, derivpol(A), T, NULL);
1.1       noro      232:
1.2     ! noro      233:   if (degpol(g))
        !           234:   { /* not squarefree */
        !           235:     g = QXQ_normalize(g, T);
        !           236:     A = RXQX_div(A,g,T);
        !           237:   }
        !           238:   A = QXQ_normalize(A, T);
        !           239:   A = primpart(A);
        !           240:   A = nfsqff(nf,A,1);
        !           241:   return gerepileupto(av, gen_sort(A, 0, cmp_pol));
1.1       noro      242: }
                    243:
1.2     ! noro      244: int
        !           245: nfissplit(GEN nf, GEN x)
1.1       noro      246: {
1.2     ! noro      247:   gpmem_t av = avma;
        !           248:   long l = lg(nfsqff(checknf(nf), x, 2));
        !           249:   avma = av; return l != 1;
1.1       noro      250: }
                    251:
1.2     ! noro      252: /* nf = K[y] / (P). Galois over K ? */
        !           253: int
        !           254: nfisgalois(GEN nf, GEN P)
1.1       noro      255: {
1.2     ! noro      256:   return degpol(P) <= 2 || nfissplit(nf, P);
1.1       noro      257: }
                    258:
1.2     ! noro      259: /* return a minimal lift of elt modulo id */
1.1       noro      260: static GEN
1.2     ! noro      261: nf_bestlift(GEN elt, GEN bound, nflift_t *T)
1.1       noro      262: {
1.2     ! noro      263:   GEN u;
        !           264:   long i,l = lg(T->prk), t = typ(elt);
        !           265:   if (t != t_INT)
        !           266:   {
        !           267:     if (t == t_POL) elt = mulmat_pol(T->tozk, elt);
        !           268:     u = gmul(T->iprk,elt);
        !           269:     for (i=1; i<l; i++) u[i] = (long)diviiround((GEN)u[i], T->pk);
1.1       noro      270:   }
1.2     ! noro      271:   else
1.1       noro      272:   {
1.2     ! noro      273:     u = gmul(elt, (GEN)T->iprk[1]);
        !           274:     for (i=1; i<l; i++) u[i] = (long)diviiround((GEN)u[i], T->pk);
        !           275:     elt = gscalcol(elt, l-1);
1.1       noro      276:   }
1.2     ! noro      277:   u = gsub(elt, gmul(T->prk, u));
        !           278:   if (bound && gcmp(QuickNormL2(u,DEFAULTPREC), bound) > 0) u = NULL;
        !           279:   return u;
1.1       noro      280: }
                    281:
                    282: static GEN
1.2     ! noro      283: nf_bestlift_to_pol(GEN elt, GEN bound, nflift_t *T)
1.1       noro      284: {
1.2     ! noro      285:   GEN u = nf_bestlift(elt,bound,T);
        !           286:   if (u) u = gmul(T->topow, u);
        !           287:   return u;
1.1       noro      288: }
                    289:
1.2     ! noro      290: /* return the lift of pol with coefficients of T2-norm <= C (if possible) */
1.1       noro      291: static GEN
1.2     ! noro      292: nf_pol_lift(GEN pol, GEN bound, nfcmbf_t *T)
1.1       noro      293: {
1.2     ! noro      294:   long i, d = lgef(pol);
        !           295:   GEN x = cgetg(d,t_POL);
        !           296:   nflift_t *L = T->L;
1.1       noro      297:
1.2     ! noro      298:   x[1] = pol[1];
        !           299:   for (i=2; i<d; i++)
1.1       noro      300:   {
1.2     ! noro      301:     x[i] = (long)nf_bestlift_to_pol((GEN)pol[i], bound, L);
        !           302:     if (!x[i]) return NULL;
1.1       noro      303:   }
1.2     ! noro      304:   return x;
1.1       noro      305: }
                    306:
1.2     ! noro      307: /* return the factorization of x in nf */
        !           308: GEN
        !           309: nffactor(GEN nf,GEN pol)
1.1       noro      310: {
1.2     ! noro      311:   GEN A,g,y,p1,rep,T;
        !           312:   long l, j, d = degpol(pol);
        !           313:   gpmem_t av;
        !           314:   if (DEBUGLEVEL>3) (void)timer2();
        !           315:
        !           316:   nf = checknf(nf); T = (GEN)nf[1];
        !           317:   if (typ(pol) != t_POL) err(notpoler,"nffactor");
        !           318:   if (varn(pol) >= varn(T))
        !           319:     err(talker,"polynomial variable must have highest priority in nffactor");
1.1       noro      320:
1.2     ! noro      321:   if (d == 0) return trivfact();
        !           322:   rep = cgetg(3, t_MAT); av = avma;
        !           323:   if (d == 1)
        !           324:   {
        !           325:     rep[1] = (long)_col( gcopy(pol) );
        !           326:     rep[2] = (long)_col( gun );
        !           327:     return rep;
        !           328:   }
1.1       noro      329:
1.2     ! noro      330:   A = fix_relative_pol(nf,pol,0);
        !           331:   if (degpol(nf[1]) == 1)
        !           332:     return gerepileupto(av, factpol(simplify(pol), 0));
        !           333:
        !           334:   A = primpart( lift_intern(A) );
        !           335:   if (DEBUGLEVEL>3) fprintferr("test if polynomial is square-free\n");
        !           336:   g = nfgcd(A, derivpol(A), T, NULL);
        !           337:
        !           338:   A = QXQ_normalize(A, T);
        !           339:   A = primpart(A);
        !           340:
        !           341:   if (degpol(g))
        !           342:   { /* not squarefree */
        !           343:     gpmem_t av1;
        !           344:     GEN ex;
        !           345:     g = QXQ_normalize(g, T);
        !           346:     A = RXQX_div(A,g, T);
        !           347:
        !           348:     y = nfsqff(nf,A,0); av1 = avma;
        !           349:     l = lg(y);
        !           350:     ex=(GEN)gpmalloc(l * sizeof(long));
        !           351:     for (j=l-1; j>=1; j--)
1.1       noro      352:     {
1.2     ! noro      353:       GEN fact = lift((GEN)y[j]), quo = g, q;
        !           354:       long e = 0;
        !           355:       for(e = 1;; e++)
        !           356:       {
        !           357:         q = RXQX_divrem(quo,fact,T, ONLY_DIVIDES);
        !           358:         if (!q) break;
        !           359:         quo = q;
        !           360:       }
        !           361:       ex[j] = e;
1.1       noro      362:     }
1.2     ! noro      363:     avma = av1; y = gerepileupto(av, y);
        !           364:     p1 = cgetg(l, t_COL); for (j=l-1; j>=1; j--) p1[j] = lstoi(ex[j]);
        !           365:     free(ex);
1.1       noro      366:   }
1.2     ! noro      367:   else
        !           368:   {
        !           369:     y = gerepileupto(av, nfsqff(nf,A,0));
        !           370:     l = lg(y);
        !           371:     p1 = cgetg(l, t_COL); for (j=l-1; j>=1; j--) p1[j] = un;
        !           372:   }
        !           373:   if (DEBUGLEVEL>3)
        !           374:     fprintferr("number of factor(s) found: %ld\n", lg(y)-1);
        !           375:   rep[1] = (long)y;
        !           376:   rep[2] = (long)p1; return sort_factor(rep, cmp_pol);
        !           377: }
        !           378:
        !           379: /* return a bound for T_2(P), P | polbase in C[X]
        !           380:  * NB: Mignotte bound: A | S ==>
        !           381:  *  |a_i| <= binom(d-1, i-1) || S ||_2 + binom(d-1, i) lc(S)
        !           382:  *
        !           383:  * Apply to sigma(S) for all embeddings sigma, then take the L_2 norm over
        !           384:  * sigma, then take the sup over i.
        !           385:  **/
        !           386: static GEN
        !           387: nf_Mignotte_bound(GEN nf, GEN polbase)
        !           388: {
        !           389:   GEN G = gmael(nf,5,2), lS = leading_term(polbase); /* t_INT */
        !           390:   GEN p1, C, N2, matGS, binlS, bin;
        !           391:   long prec, i, j, d = degpol(polbase), n = degpol(nf[1]), r1 = nf_get_r1(nf);
        !           392:
        !           393:   if (typ(lS) == t_COL) lS = (GEN)lS[1];
        !           394:   binlS = bin = vecbinome(d-1);
        !           395:   if (!gcmp1(lS)) binlS = gmul(lS, bin);
1.1       noro      396:
1.2     ! noro      397:   N2 = cgetg(n+1, t_VEC);
        !           398:   prec = gprecision(G);
        !           399:   for (;;)
        !           400:   {
        !           401:     nffp_t F;
1.1       noro      402:
1.2     ! noro      403:     matGS = cgetg(d+2, t_MAT);
        !           404:     for (j=0; j<=d; j++) matGS[j+1] = lmul(G, (GEN)polbase[j+2]);
        !           405:     matGS = gtrans_i(matGS);
        !           406:     for (j=1; j <= r1; j++) /* N2[j] = || sigma_j(S) ||_2 */
        !           407:     {
        !           408:       N2[j] = lsqrt( QuickNormL2((GEN)matGS[j], DEFAULTPREC), DEFAULTPREC );
        !           409:       if (lg(N2[j]) < DEFAULTPREC) goto PRECPB;
        !           410:     }
        !           411:     for (   ; j <= n; j+=2)
        !           412:     {
        !           413:       GEN q1 = QuickNormL2((GEN)matGS[j  ], DEFAULTPREC);
        !           414:       GEN q2 = QuickNormL2((GEN)matGS[j+1], DEFAULTPREC);
        !           415:       p1 = gmul2n(mpadd(q1, q2), -1);
        !           416:       N2[j] = N2[j+1] = lsqrt( p1, DEFAULTPREC );
        !           417:       if (lg(N2[j]) < DEFAULTPREC) goto PRECPB;
        !           418:     }
        !           419:     if (j > n) break; /* done */
        !           420: PRECPB:
        !           421:     prec = (prec<<1)-2;
        !           422:     remake_GM(nf, &F, prec); G = F.G;
        !           423:     if (DEBUGLEVEL>1) err(warnprec, "nf_factor_bound", prec);
        !           424:   }
1.1       noro      425:
1.2     ! noro      426:   /* Take sup over 0 <= i <= d of
        !           427:    * sum_sigma | binom(d-1, i-1) ||sigma(S)||_2 + binom(d-1,i) lc(S) |^2 */
1.1       noro      428:
1.2     ! noro      429:   /* i = 0: n lc(S)^2 */
        !           430:   C = mulsi(n, sqri(lS));
        !           431:   /* i = d: sum_sigma ||sigma(S)||_2^2 */
        !           432:   p1 = gnorml2(N2); if (gcmp(C, p1) < 0) C = p1;
        !           433:   for (i = 1; i < d; i++)
1.1       noro      434:   {
1.2     ! noro      435:     GEN s = gzero;
        !           436:     for (j = 1; j <= n; j++)
1.1       noro      437:     {
1.2     ! noro      438:       p1 = mpadd( mpmul((GEN)bin[i], (GEN)N2[j]), (GEN)binlS[i+1] );
        !           439:       s = mpadd(s, gsqr(p1));
1.1       noro      440:     }
1.2     ! noro      441:     if (gcmp(C, s) < 0) C = s;
1.1       noro      442:   }
1.2     ! noro      443:   return C;
1.1       noro      444: }
                    445:
1.2     ! noro      446: /* return a bound for T_2(P), P | polbase
        !           447:  * max |b_i|^2 <= 3^{3/2 + d} / (4 \pi d) [P]_2,
        !           448:  * where [P]_2 is Bombieri's 2-norm
        !           449:  * Sum over conjugates
        !           450: */
        !           451: static GEN
        !           452: nf_Beauzamy_bound(GEN nf, GEN polbase)
1.1       noro      453: {
1.2     ! noro      454:   GEN lt,C,run,s, G = gmael(nf,5,2), POL, bin;
        !           455:   long i,prec,precnf, d = degpol(polbase), n = degpol(nf[1]);
1.1       noro      456:
1.2     ! noro      457:   precnf = gprecision(G);
        !           458:   prec   = MEDDEFAULTPREC;
        !           459:   bin = vecbinome(d);
        !           460:   POL = polbase + 2;
        !           461:   /* compute [POL]_2 */
        !           462:   for (;;)
1.1       noro      463:   {
1.2     ! noro      464:     run= realun(prec);
        !           465:     s = realzero(prec);
        !           466:     for (i=0; i<=d; i++)
        !           467:     {
        !           468:       GEN p1 = gnorml2(gmul(G, gmul(run, (GEN)POL[i]))); /* T2(POL[i]) */
        !           469:       if (!signe(p1)) continue;
        !           470:       if (lg(p1) == 3) break;
        !           471:       /* s += T2(POL[i]) / binomial(d,i) */
        !           472:       s = addrr(s, gdiv(p1, (GEN)bin[i+1]));
1.1       noro      473:     }
1.2     ! noro      474:     if (i > d) break;
1.1       noro      475:
1.2     ! noro      476:     prec = (prec<<1)-2;
        !           477:     if (prec > precnf)
1.1       noro      478:     {
1.2     ! noro      479:       nffp_t F; remake_GM(nf, &F, prec); G = F.G;
        !           480:       if (DEBUGLEVEL>1) err(warnprec, "nf_factor_bound", prec);
1.1       noro      481:     }
1.2     ! noro      482:   }
        !           483:   lt = (GEN)leading_term(polbase)[1];
        !           484:   s = gmul(s, mulis(sqri(lt), n));
        !           485:   C = gpow(stoi(3), dbltor(1.5 + d), DEFAULTPREC); /* 3^{3/2 + d} */
        !           486:   return gdiv(gmul(C, s), gmulsg(d, mppi(DEFAULTPREC)));
1.1       noro      487: }
                    488:
                    489: static GEN
1.2     ! noro      490: nf_factor_bound(GEN nf, GEN polbase)
1.1       noro      491: {
1.2     ! noro      492:   gpmem_t av = avma;
        !           493:   GEN a = nf_Mignotte_bound(nf, polbase);
        !           494:   GEN b = nf_Beauzamy_bound(nf, polbase);
        !           495:   if (DEBUGLEVEL>2)
1.1       noro      496:   {
1.2     ! noro      497:     fprintferr("Mignotte bound: %Z\n",a);
        !           498:     fprintferr("Beauzamy bound: %Z\n",b);
1.1       noro      499:   }
1.2     ! noro      500:   return gerepileupto(av, gmin(a, b));
1.1       noro      501: }
                    502:
1.2     ! noro      503: static long
        !           504: ZXY_get_prec(GEN P)
1.1       noro      505: {
1.2     ! noro      506:   long i, j, z, prec = 0;
        !           507:   for (i=2; i<lgef(P); i++)
1.1       noro      508:   {
1.2     ! noro      509:     GEN p = (GEN)P[i];
        !           510:     if (typ(p) == t_INT)
        !           511:     {
        !           512:       z = lgefint(p);
        !           513:       if (z > prec) prec = z;
        !           514:     }
        !           515:     else
        !           516:     {
        !           517:       for (j=2; j<lgef(p); j++)
        !           518:       {
        !           519:         z = lgefint(p[j]);
        !           520:         if (z > prec) prec = z;
        !           521:       }
        !           522:     }
        !           523:   }
        !           524:   return prec + 1;
1.1       noro      525: }
                    526:
1.2     ! noro      527: long
        !           528: ZM_get_prec(GEN x)
1.1       noro      529: {
1.2     ! noro      530:   long i, j, l, k = 2, lx = lg(x);
1.1       noro      531:
1.2     ! noro      532:   for (j=1; j<lx; j++)
1.1       noro      533:   {
1.2     ! noro      534:     GEN c = (GEN)x[j];
        !           535:     for (i=1; i<lx; i++) { l = lgefint(c[i]); if (l > k) k = l; }
1.1       noro      536:   }
1.2     ! noro      537:   return k;
1.1       noro      538: }
1.2     ! noro      539: long
        !           540: ZX_get_prec(GEN x)
1.1       noro      541: {
1.2     ! noro      542:   long j, l, k = 2, lx = lgef(x);
1.1       noro      543:
1.2     ! noro      544:   for (j=2; j<lx; j++)
1.1       noro      545:   {
1.2     ! noro      546:     l = lgefint(x[j]); if (l > k) k = l;
1.1       noro      547:   }
1.2     ! noro      548:   return k;
1.1       noro      549: }
                    550:
1.2     ! noro      551: static GEN
        !           552: complex_bound(GEN P)
1.1       noro      553: {
1.2     ! noro      554:   return gmul(max_modulus(P, 0.01), dbltor(1.0101)); /* exp(0.01) = 1.0100 */
1.1       noro      555: }
                    556:
1.2     ! noro      557: /* return Bs: if r a root of sigma_i(P), |r| < Bs[i] */
        !           558: static GEN
        !           559: nf_root_bounds(GEN P, GEN T)
1.1       noro      560: {
1.2     ! noro      561:   long lR, i, j, l, prec;
        !           562:   GEN Ps, R, V, nf;
1.1       noro      563:
1.2     ! noro      564:   if (isrational(P)) return complex_bound(P);
1.1       noro      565:
1.2     ! noro      566:   T = get_nfpol(T, &nf);
1.1       noro      567:
1.2     ! noro      568:   prec = ZXY_get_prec(P);
        !           569:   l = lgef(P);
        !           570:   if (nf && nfgetprec(nf) >= prec)
        !           571:     R = (GEN)nf[6];
        !           572:   else
        !           573:     R = roots(T, prec);
        !           574:   lR = lg(R);
        !           575:   V = cgetg(lR, t_VEC);
        !           576:   Ps = cgetg(l, t_POL); /* sigma (P) */
        !           577:   Ps[1] = P[1];
        !           578:   for (j=1; j<lg(R); j++)
1.1       noro      579:   {
1.2     ! noro      580:     GEN r = (GEN)R[j];
        !           581:     for (i=2; i<l; i++) Ps[i] = (long)poleval((GEN)P[i], r);
        !           582:     V[j] = (long)complex_bound(Ps);
1.1       noro      583:   }
1.2     ! noro      584:   return V;
1.1       noro      585: }
                    586:
1.2     ! noro      587: /* return B such that if x in O_K, K = Z[X]/(T), then the L2-norm of the
        !           588:  * coordinates of the numerator of x [on the power, resp. integral, basis if T
        !           589:  * is a polynomial, resp. an nf] is  <= B T_2(x)
        !           590:  * *ptden = multiplicative bound for denom(x) */
1.1       noro      591: static GEN
1.2     ! noro      592: L2_bound(GEN T, GEN tozk, GEN *ptden)
1.1       noro      593: {
1.2     ! noro      594:   GEN nf, M, L, prep, den, u;
        !           595:   long prec;
        !           596:
        !           597:   T = get_nfpol(T, &nf);
        !           598:   u = NULL; /* gcc -Wall */
1.1       noro      599:
1.2     ! noro      600:   prec = ZX_get_prec(T) + ZM_get_prec(tozk);
        !           601:   den = nf? gun: NULL;
        !           602:   den = initgaloisborne(T, den, prec, &L, &prep, NULL);
        !           603:   M = vandermondeinverse(L, gmul(T, realun(prec)), den, prep);
        !           604:   if (nf) M = gmul(tozk, M);
        !           605:   if (gcmp1(den)) den = NULL;
        !           606:   *ptden = den;
        !           607:   return QuickNormL2(M, DEFAULTPREC);
1.1       noro      608: }
                    609:
1.2     ! noro      610: /* || L ||_p^p in dimension n (L may be a scalar) */
1.1       noro      611: static GEN
1.2     ! noro      612: normlp(GEN L, long p, long n)
1.1       noro      613: {
1.2     ! noro      614:   long i,l, t = typ(L);
        !           615:   GEN z;
1.1       noro      616:
1.2     ! noro      617:   if (!is_vec_t(t)) return gmulsg(n, gpowgs(L, p));
1.1       noro      618:
1.2     ! noro      619:   l = lg(L); z = gzero;
        !           620:   /* assert(n == l-1); */
        !           621:   for (i=1; i<l; i++)
        !           622:     z = gadd(z, gpowgs((GEN)L[i], p));
        !           623:   return z;
1.1       noro      624: }
                    625:
1.2     ! noro      626: /* S = S0 + qS1, P = P0 + qP1 (Euclidean div. by q integer). For a true
        !           627:  * factor (vS, vP), we have:
        !           628:  *    | S vS + P vP |^2 < Btra
        !           629:  * This implies | S1 vS + P1 vP |^2 < Blow, assuming q > sqrt(Btra).
        !           630:  * d = dimension of low part (= [nf:Q])
        !           631:  * n0 = bound for |vS|^2
        !           632:  * */
        !           633: static double
        !           634: get_Blow(long n0, long d, GEN q)
        !           635: {
        !           636: #if 0
        !           637:   double sqrtn0 = sqrt((double)n0);
        !           638:   double t = sqrtn0 + sqrt((double)d) * (sqrtn0 + 1);
        !           639: #else
        !           640:   double sqrtd = sqrt((double)d);
        !           641:   double t, aux;
        !           642:
        !           643:   if (gexpo(q)>30)
        !           644:     aux = 1.0001;
        !           645:   else
1.1       noro      646:   {
1.2     ! noro      647:     aux = gtodouble(q);
        !           648:     aux = sqrt(1 + 4/(aux*aux));
1.1       noro      649:   }
1.2     ! noro      650:   t = n0*sqrtd + sqrtd/2 * aux * (sqrtd * (n0+1)); /* assume pr degree 1 */
        !           651: #endif
        !           652:   t = 1. + 0.5 * t;
        !           653:   return t * t;
        !           654: }
        !           655:
        !           656: typedef struct {
        !           657:   GEN d;
        !           658:   GEN dPinvS;   /* d P^(-1) S   [ integral ] */
        !           659:   double **PinvSdbl; /* P^(-1) S as double */
        !           660:   GEN S1, P1;   /* S = S0 + S1 q, idem P */
        !           661: } trace_data;
        !           662:
        !           663: /* S1 * u - P1 * round(P^-1 S u). K non-zero coords in u given by ind */
        !           664: static GEN
        !           665: get_trace(GEN ind, trace_data *T)
        !           666: {
        !           667:   long i, j, l, K = lg(ind)-1;
        !           668:   GEN z, s, v;
        !           669:
        !           670:   s = (GEN)T->S1[ ind[1] ];
        !           671:   if (K == 1) return s;
        !           672:
        !           673:   /* compute s = S1 u */
        !           674:   for (j=2; j<=K; j++) s = gadd(s, (GEN)T->S1[ ind[j] ]);
        !           675:
        !           676:   /* compute v := - round(P^1 S u) */
        !           677:   l = lg(s);
        !           678:   v = cgetg(l, t_VECSMALL);
        !           679:   for (i=1; i<l; i++)
        !           680:   {
        !           681:     double r, t = 0.;
        !           682:     /* quick approximate computation */
        !           683:     for (j=1; j<=K; j++) t += T->PinvSdbl[ ind[j] ][i];
        !           684:     r = floor(t + 0.5);
        !           685:     if (fabs(t + 0.5 - r) < 0.01)
        !           686:     { /* dubious, compute exactly */
        !           687:       z = gzero;
        !           688:       for (j=1; j<=K; j++) z = addii(z, ((GEN**)T->dPinvS)[ ind[j] ][i]);
        !           689:       v[i] = - itos( diviiround(z, T->d) );
        !           690:     }
        !           691:     else
        !           692:       v[i] = - (long)r;
1.1       noro      693:   }
1.2     ! noro      694:   return gadd(s, gmul_mati_smallvec(T->P1, v));
        !           695: }
1.1       noro      696:
1.2     ! noro      697: static trace_data *
        !           698: init_trace(trace_data *T, GEN S, nflift_t *L, GEN q)
        !           699: {
        !           700:   long e = gexpo((GEN)S), i,j, l,h;
        !           701:   GEN qgood, S1, invd;
        !           702:
        !           703:   if (e < 0) return NULL; /* S = 0 */
1.1       noro      704:
1.2     ! noro      705:   qgood = shifti(gun, e - 32); /* single precision check */
        !           706:   if (cmpii(qgood, q) > 0) q = qgood;
1.1       noro      707:
1.2     ! noro      708:   S1 = gdivround(S, q);
        !           709:   if (gcmp0(S1)) return NULL;
1.1       noro      710:
1.2     ! noro      711:   invd = ginv(itor(L->den, DEFAULTPREC));
1.1       noro      712:
1.2     ! noro      713:   T->dPinvS = gmul(L->iprk, S);
        !           714:   l = lg(S);
        !           715:   h = lg(T->dPinvS[1]);
        !           716:   T->PinvSdbl = (double**)cgetg(l, t_MAT);
        !           717:   init_dalloc();
        !           718:   for (j = 1; j < l; j++)
1.1       noro      719:   {
1.2     ! noro      720:     double *t = dalloc(h * sizeof(double));
        !           721:     GEN c = (GEN)T->dPinvS[j];
        !           722:     T->PinvSdbl[j] = t;
        !           723:     for (i=1; i < h; i++) t[i] = rtodbl(gmul(invd, (GEN)c[i]));
        !           724:   }
        !           725:
        !           726:   T->d  = L->den;
        !           727:   T->P1 = gdivround(L->prk, q);
        !           728:   T->S1 = S1; return T;
        !           729: }
        !           730:
        !           731: static void
        !           732: update_trace(trace_data *T, long k, long i)
        !           733: {
        !           734:   if (!T) return;
        !           735:   T->S1[k]       = T->S1[i];
        !           736:   T->dPinvS[k]   = T->dPinvS[i];
        !           737:   T->PinvSdbl[k] = T->PinvSdbl[i];
        !           738: }
        !           739:
        !           740: /* Naive recombination of modular factors: combine up to maxK modular
        !           741:  * factors, degree <= klim and divisible by hint
        !           742:  *
        !           743:  * target = polynomial we want to factor
        !           744:  * famod = array of modular factors.  Product should be congruent to
        !           745:  * target/lc(target) modulo p^a
        !           746:  * For true factors: S1,S2 <= p^b, with b <= a and p^(b-a) < 2^31 */
        !           747: static GEN
        !           748: nfcmbf(nfcmbf_t *T, GEN p, long a, long maxK, long klim)
        !           749: {
        !           750:   long Sbound;
        !           751:   GEN pol = T->pol, nf = T->nf, famod = T->fact;
        !           752:   GEN bound = T->bound;
        !           753:   GEN nfpol = (GEN)nf[1];
        !           754:   long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1, dnf = degpol(nfpol);
        !           755:   GEN lc, lcpol;
        !           756:   GEN pk = gpowgs(p,a), pas2 = shifti(pk,-1);
        !           757:
        !           758:   GEN trace1   = cgetg(lfamod+1, t_MAT);
        !           759:   GEN trace2   = cgetg(lfamod+1, t_MAT);
        !           760:   GEN ind      = cgetg(lfamod+1, t_VECSMALL);
        !           761:   GEN degpol   = cgetg(lfamod+1, t_VECSMALL);
        !           762:   GEN degsofar = cgetg(lfamod+1, t_VECSMALL);
        !           763:   GEN listmod  = cgetg(lfamod+1, t_COL);
        !           764:   GEN fa       = cgetg(lfamod+1, t_COL);
        !           765:   GEN res = cgetg(3, t_VEC);
        !           766:   GEN q = ceil_safe(mpsqrt(T->BS_2));
        !           767:   const double Blow = get_Blow(lfamod, dnf, q);
        !           768:   trace_data _T1, _T2, *T1, *T2;
        !           769:
        !           770:   if (maxK < 0) maxK = lfamod-1;
        !           771:
        !           772:   lc = absi(leading_term(pol));
        !           773:   if (gcmp1(lc)) lc = NULL;
        !           774:   lcpol = lc? gmul(lc,pol): pol;
1.1       noro      775:
                    776:   {
1.2     ! noro      777:     GEN t1,t2, lc2 = lc? sqri(lc): NULL;
1.1       noro      778:
1.2     ! noro      779:     for (i=1; i <= lfamod; i++)
        !           780:     {
        !           781:       GEN P = (GEN)famod[i];
        !           782:       long d = degpol(P);
1.1       noro      783:
1.2     ! noro      784:       degpol[i] = d; P += 2;
        !           785:       t1 = (GEN)P[d-1];/* = - S_1 */
        !           786:       t2 = sqri(t1);
        !           787:       if (d > 1) t2 = subii(t2, shifti((GEN)P[d-2],1));
        !           788:       t2 = modii(t2, pk); /* = S_2 Newton sum */
        !           789:       if (lc)
        !           790:       {
        !           791:         t1 = modii(mulii(lc, t1), pk);
        !           792:         t2 = modii(mulii(lc2,t2), pk);
        !           793:       }
        !           794:       trace1[i] = (long)nf_bestlift(t1, NULL, T->L);
        !           795:       trace2[i] = (long)nf_bestlift(t2, NULL, T->L);
        !           796:     }
1.1       noro      797:
1.2     ! noro      798:     T1 = init_trace(&_T1, trace1, T->L, q);
        !           799:     T2 = init_trace(&_T2, trace2, T->L, q);
        !           800:   }
        !           801:   degsofar[0] = 0; /* sentinel */
1.1       noro      802:
1.2     ! noro      803:   /* ind runs through strictly increasing sequences of length K,
        !           804:    * 1 <= ind[i] <= lfamod */
        !           805: nextK:
        !           806:   if (K > maxK || 2*K > lfamod) goto END;
        !           807:   if (DEBUGLEVEL > 3)
        !           808:     fprintferr("\n### K = %d, %Z combinations\n", K,binome(stoi(lfamod), K));
        !           809:   setlg(ind, K+1); ind[1] = 1;
        !           810:   Sbound = ((K+1)>>1);
        !           811:   i = 1; curdeg = degpol[ind[1]];
        !           812:   for(;;)
        !           813:   { /* try all combinations of K factors */
        !           814:     for (j = i; j < K; j++)
1.1       noro      815:     {
1.2     ! noro      816:       degsofar[j] = curdeg;
        !           817:       ind[j+1] = ind[j]+1; curdeg += degpol[ind[j+1]];
        !           818:     }
        !           819:     if (curdeg <= klim && curdeg % T->hint == 0) /* trial divide */
        !           820:     {
        !           821:       GEN t, y, q, list;
        !           822:       gpmem_t av;
        !           823:
        !           824:       av = avma;
        !           825:       /* d - 1 test */
        !           826:       if (T1)
        !           827:       {
        !           828:         t = get_trace(ind, T1);
        !           829:         if (rtodbl(QuickNormL2(t,DEFAULTPREC)) > Blow)
        !           830:         {
        !           831:           if (DEBUGLEVEL>6) fprintferr(".");
        !           832:           avma = av; goto NEXT;
        !           833:         }
        !           834:       }
        !           835:       /* d - 2 test */
        !           836:       if (T2)
        !           837:       {
        !           838:         t = get_trace(ind, T2);
        !           839:         if (rtodbl(QuickNormL2(t,DEFAULTPREC)) > Blow)
        !           840:         {
        !           841:           if (DEBUGLEVEL>3) fprintferr("|");
        !           842:           avma = av; goto NEXT;
        !           843:         }
        !           844:       }
        !           845:       avma = av;
        !           846:       y = lc; /* full computation */
        !           847:       for (i=1; i<=K; i++)
        !           848:       {
        !           849:         GEN q = (GEN)famod[ind[i]];
        !           850:         if (y) q = gmul(y, q);
        !           851:         y = centermod_i(q, pk, pas2);
        !           852:       }
        !           853:       y = nf_pol_lift(y, bound, T);
        !           854:       if (!y)
        !           855:       {
        !           856:         if (DEBUGLEVEL>3) fprintferr("@");
        !           857:         avma = av; goto NEXT;
        !           858:       }
        !           859:       /* try out the new combination: y is the candidate factor */
        !           860:       q = RXQX_divrem(lcpol,y, nfpol, ONLY_DIVIDES);
        !           861:       if (!q)
        !           862:       {
        !           863:         if (DEBUGLEVEL>3) fprintferr("*");
        !           864:         avma = av; goto NEXT;
        !           865:       }
1.1       noro      866:
1.2     ! noro      867:       /* found a factor */
        !           868:       list = cgetg(K+1, t_VEC);
        !           869:       listmod[cnt] = (long)list;
        !           870:       for (i=1; i<=K; i++) list[i] = famod[ind[i]];
        !           871:
        !           872:       y = primpart(y);
        !           873:       fa[cnt++] = (long)QXQ_normalize(y, nfpol);
        !           874:       /* fix up pol */
        !           875:       pol = q;
        !           876:       if (lc) pol = primpart(pol);
        !           877:       for (i=j=k=1; i <= lfamod; i++)
        !           878:       { /* remove used factors */
        !           879:         if (j <= K && i == ind[j]) j++;
        !           880:         else
        !           881:         {
        !           882:           famod[k] = famod[i];
        !           883:           update_trace(T1, k, i);
        !           884:           update_trace(T2, k, i);
        !           885:           degpol[k] = degpol[i]; k++;
        !           886:         }
        !           887:       }
        !           888:       lfamod -= K;
        !           889:       if (lfamod < 2*K) goto END;
        !           890:       i = 1; curdeg = degpol[ind[1]];
        !           891:       if (lc) lc = absi(leading_term(pol));
        !           892:       lcpol = lc? gmul(lc,pol): pol;
        !           893:       if (DEBUGLEVEL > 2)
1.1       noro      894:       {
1.2     ! noro      895:         fprintferr("\n"); msgtimer("to find factor %Z",y);
        !           896:         fprintferr("remaining modular factor(s): %ld\n", lfamod);
        !           897:       }
        !           898:       continue;
        !           899:     }
        !           900:
        !           901: NEXT:
        !           902:     for (i = K+1;;)
        !           903:     {
        !           904:       if (--i == 0) { K++; goto nextK; }
        !           905:       if (++ind[i] <= lfamod - K + i)
        !           906:       {
        !           907:         curdeg = degsofar[i-1] + degpol[ind[i]];
        !           908:         if (curdeg <= klim) break;
1.1       noro      909:       }
                    910:     }
                    911:   }
1.2     ! noro      912: END:
        !           913:   if (degpol(pol) > 0)
        !           914:   { /* leftover factor */
        !           915:     if (signe(leading_term(pol)) < 0) pol = gneg_i(pol);
        !           916:
        !           917:     if (lc && lfamod < 2*K) pol = QXQ_normalize(primpart(pol), nfpol);
        !           918:     setlg(famod, lfamod+1);
        !           919:     listmod[cnt] = (long)dummycopy(famod);
        !           920:     fa[cnt++] = (long)pol;
        !           921:   }
        !           922:   if (DEBUGLEVEL>6) fprintferr("\n");
        !           923:   setlg(listmod, cnt); setlg(fa, cnt);
        !           924:   res[1] = (long)fa;
        !           925:   res[2] = (long)listmod; return res;
1.1       noro      926: }
                    927:
1.2     ! noro      928: static GEN
        !           929: nf_check_factors(nfcmbf_t *T, GEN P, GEN M_L, GEN famod, GEN pk)
        !           930: {
        !           931:   GEN nf = T->nf, bound = T->bound;
        !           932:   GEN nfT = (GEN)nf[1];
        !           933:   long i, j, r, n0;
        !           934:   GEN pol = P, lcpol, lc, list, piv, y, pas2;
        !           935:
        !           936:   piv = special_pivot(M_L);
        !           937:   if (!piv) return NULL;
        !           938:   if (DEBUGLEVEL>3) fprintferr("special_pivot output:\n%Z\n",piv);
        !           939:
        !           940:   pas2 = shifti(pk,-1);
        !           941:   r  = lg(piv)-1;
        !           942:   n0 = lg(piv[1])-1;
        !           943:   list = cgetg(r+1, t_COL);
        !           944:   lc = absi(leading_term(pol));
        !           945:   if (is_pm1(lc)) lc = NULL;
        !           946:   lcpol = lc? gmul(lc, pol): pol;
        !           947:   for (i=1; i<r; i++)
        !           948:   {
        !           949:     GEN c = (GEN)piv[i];
        !           950:     if (DEBUGLEVEL) fprintferr("nf_LLL_cmbf: checking factor %ld\n",i);
        !           951:
        !           952:     y = lc;
        !           953:     for (j=1; j<=n0; j++)
        !           954:       if (signe(c[j]))
        !           955:       {
        !           956:         GEN q = (GEN)famod[j];
        !           957:         if (y) q = gmul(y, q);
        !           958:         y = centermod_i(q, pk, pas2);
        !           959:       }
        !           960:     y = nf_pol_lift(y, bound, T);
        !           961:     if (!y) return NULL;
        !           962:
        !           963:     /* y is the candidate factor */
        !           964:     pol = RXQX_divrem(lcpol,y,nfT, ONLY_DIVIDES);
        !           965:     if (!pol) return NULL;
1.1       noro      966:
1.2     ! noro      967:     y = primpart(y);
        !           968:     if (lc)
        !           969:     {
        !           970:       pol = primpart(pol);
        !           971:       lc = absi(leading_term(pol));
        !           972:     }
        !           973:     lcpol = lc? gmul(lc, pol): pol;
        !           974:     list[i] = (long)QXQ_normalize(y, nfT);
1.1       noro      975:   }
1.2     ! noro      976:   y = primpart(pol);
        !           977:   list[i] = (long)QXQ_normalize(y, nfT); return list;
1.1       noro      978: }
                    979:
                    980: static GEN
1.2     ! noro      981: nf_to_Zp(GEN x, GEN pk, GEN pas2, GEN ffproj)
1.1       noro      982: {
1.2     ! noro      983:   return centermodii(gmul(ffproj, x), pk, pas2);
        !           984: }
1.1       noro      985:
1.2     ! noro      986: /* assume lc(pol) != 0 mod prh. Reduce P to Zp[X] mod p^a */
        !           987: static GEN
        !           988: ZpX(GEN P, GEN pk, GEN ffproj)
        !           989: {
        !           990:   long i, l;
        !           991:   GEN z, pas2 = shifti(pk,-1);
1.1       noro      992:
1.2     ! noro      993:   if (typ(P)!=t_POL) return nf_to_Zp(P,pk,pas2,ffproj);
        !           994:   l = lgef(P);
        !           995:   z = cgetg(l,t_POL); z[1] = P[1];
        !           996:   for (i=2; i<l; i++) z[i] = (long)nf_to_Zp((GEN)P[i],pk,pas2,ffproj);
        !           997:   return normalizepol(z);
        !           998: }
        !           999:
        !          1000: /* We want to be able to reconstruct x, |x|^2 < C, from x mod pr^k
        !          1001:  * We want B := min B_i >= C. Let alpha the LLL parameter,
        !          1002:  * y = 1/(alpha-1/4) > 4/3, the theoretical guaranteed bound follows from
        !          1003:  *    (Npr)^(2k/n) = det(L)^(2/n) <= 1/n sum B_i
        !          1004:  *                                <= 1/n B sum y^i
        !          1005:  *                                <= 1/n B y^(n-1) / (y-1)
        !          1006:  *
        !          1007:  *  Hence log(B/n) >= 2k/n log(Npr) - (n-1)log(y) + log(y-1)
        !          1008:  *                 >= log(C/n), provided
        !          1009:  *   k >= [ log(C/n) + (n-1)log(y) - log(y-1) ] * n/(2log(Npr))
        !          1010:  */
        !          1011: static double
        !          1012: bestlift_bound(GEN C, long n, double alpha, GEN Npr)
        !          1013: {
        !          1014:   const double y = 1 / (alpha - 0.25); /* = 2 if alpha = 3/4 */
        !          1015:   double t;
        !          1016:   if (typ(C) != t_REAL) C = gmul(C, realun(DEFAULTPREC));
        !          1017:   setlg(C, DEFAULTPREC);
        !          1018:   t = rtodbl(mplog(divrs(C,n))) + (n-1) * log(y) - log(y-1);
        !          1019:   return ceil((t * n) / (2.* log(gtodouble(Npr))));
        !          1020: }
        !          1021:
        !          1022: static void
        !          1023: bestlift_init(long a, GEN nf, GEN pr, GEN C, nflift_t *T)
        !          1024: {
        !          1025:   const int D = 4;
        !          1026:   const double alpha = ((double)D-1) / D; /* LLL parameter */
        !          1027:   gpmem_t av = avma;
        !          1028:   GEN prk, PRK, B, GSmin, pk;
        !          1029:
        !          1030:   if (!a) a = (long)bestlift_bound(C, degpol(nf[1]), alpha, idealnorm(nf,pr));
        !          1031:
        !          1032:   for (;; avma = av, a<<=1)
        !          1033:   {
        !          1034:     if (DEBUGLEVEL>2) fprintferr("exponent: %ld\n",a);
        !          1035:     prk = idealpows(nf, pr, a);
        !          1036:     pk = gcoeff(prk,1,1);
        !          1037:     PRK = hnfmodid(prk, pk);
        !          1038:
        !          1039:     PRK = lllint_i(PRK, D, 0, NULL, NULL, &B);
        !          1040:     GSmin = vecmin(GS_norms(B, DEFAULTPREC));
        !          1041:     if (gcmp(GSmin, C) >= 0) break;
        !          1042:   }
        !          1043:   if (DEBUGLEVEL>2) fprintferr("for this exponent, GSmin = %Z\n",GSmin);
        !          1044:   T->k = a;
        !          1045:   T->pk = T->den = pk;
        !          1046:   T->prk = PRK;
        !          1047:   T->iprk = ZM_inv(PRK, pk);
        !          1048:   T->GSmin= GSmin;
        !          1049:   T->ZpProj = dim1proj(prk); /* nf --> Zp */
        !          1050: }
        !          1051:
        !          1052: /* assume pr has degree 1 */
        !          1053: static GEN
        !          1054: nf_LLL_cmbf(nfcmbf_t *T, GEN p, long k, long rec)
        !          1055: {
        !          1056:   nflift_t *L = T->L;
        !          1057:   GEN pk = L->pk, PRK = L->prk, PRKinv = L->iprk, GSmin = L->GSmin;
        !          1058:
        !          1059:   GEN famod = T->fact, nf = T->nf, ZC = T->ZC, Br = T->Br;
        !          1060:   GEN Pbase = T->polbase, P = T->pol, dn = T->dn;
        !          1061:   GEN nfT = (GEN)nf[1];
        !          1062:   GEN Btra;
        !          1063:   long dnf = degpol(nfT), dP = degpol(P);
        !          1064:
        !          1065:   double BitPerFactor = 0.5; /* nb bits / modular factor */
        !          1066:   long i, C, tmax, n0;
        !          1067:   GEN lP, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO;
        !          1068:   double Blow;
        !          1069:   gpmem_t av, av2, lim;
        !          1070:   long ti_LLL = 0, ti_CF = 0;
        !          1071:   pari_timer ti, ti2, TI;
        !          1072:
        !          1073:   if (DEBUGLEVEL>2) (void)TIMER(&ti);
        !          1074:
        !          1075:   lP = absi(leading_term(P));
        !          1076:   if (is_pm1(lP)) lP = NULL;
        !          1077:
        !          1078:   n0 = lg(famod) - 1;
        !          1079:  /* Lattice: (S PRK), small vector (vS vP). To find k bound for the image,
        !          1080:   * write S = S1 q + S0, P = P1 q + P0
        !          1081:   * |S1 vS + P1 vP|^2 <= Blow for all (vS,vP) assoc. to true factors */
        !          1082:   Btra = mulrr(ZC, mulsr(dP*dP, normlp(Br, 2, dnf)));
        !          1083:   Blow = get_Blow(n0, dnf, gceil(Btra));
        !          1084:   C = (long)ceil(sqrt(Blow/n0)) + 1; /* C^2 n0 ~ Blow */
        !          1085:   Bnorm = dbltor( n0 * C * C + Blow );
        !          1086:   ZERO = zeromat(n0, dnf);
        !          1087:
        !          1088:   av = avma; lim = stack_lim(av, 1);
        !          1089:   TT = cgetg(n0+1, t_VEC);
        !          1090:   Tra  = cgetg(n0+1, t_MAT);
        !          1091:   for (i=1; i<=n0; i++) TT[i] = 0;
        !          1092:   CM_L = gscalsmat(C, n0);
        !          1093:   /* tmax = current number of traces used (and computed so far) */
        !          1094:   for(tmax = 0;; tmax++)
        !          1095:   {
        !          1096:     long a, b, bmin, bgood, delta, tnew = tmax + 1, r = lg(CM_L)-1;
        !          1097:     GEN oldCM_L, M_L, q, S1, P1, VV;
        !          1098:     int first = 1;
        !          1099:
        !          1100:     /* bound for f . S_k(genuine factor) = ZC * bound for T_2(S_tnew) */
        !          1101:     Btra = mulrr(ZC, mulsr(dP*dP, normlp(Br, 2*tnew, dnf)));
        !          1102:     bmin = logint(ceil_safe(mpsqrt(Btra)), gdeux, NULL);
        !          1103:     if (DEBUGLEVEL>2)
        !          1104:       fprintferr("\nLLL_cmbf: %ld potential factors (tmax = %ld, bmin = %ld)\n",
        !          1105:                  r, tmax, bmin);
1.1       noro     1106:
1.2     ! noro     1107:     /* compute Newton sums (possibly relifting first) */
        !          1108:     if (gcmp(GSmin, Btra) < 0)
        !          1109:     {
        !          1110:       nflift_t L1;
        !          1111:       GEN polred;
1.1       noro     1112:
1.2     ! noro     1113:       bestlift_init(k<<1, nf, T->pr, Btra, &L1);
        !          1114:       k      = L1.k;
        !          1115:       pk     = L1.pk;
        !          1116:       PRK    = L1.prk;
        !          1117:       PRKinv = L1.iprk;
        !          1118:       GSmin  = L1.GSmin;
        !          1119:
        !          1120:       polred = ZpX(Pbase, pk, L1.ZpProj);
        !          1121:       famod = hensel_lift_fact(polred,famod,NULL,p,pk,k);
        !          1122:       for (i=1; i<=n0; i++) TT[i] = 0;
        !          1123:     }
        !          1124:     for (i=1; i<=n0; i++)
1.1       noro     1125:     {
1.2     ! noro     1126:       GEN p1, lPpow;
        !          1127:       GEN p2 = polsym_gen((GEN)famod[i], (GEN)TT[i], tnew, NULL, pk);
        !          1128:       TT[i] = (long)p2;
        !          1129:       p1 = (GEN)p2[tnew+1];
        !          1130:       /* make Newton sums integral */
        !          1131:       if (lP)
        !          1132:       {
        !          1133:         lPpow = gpowgs(lP, tnew);
        !          1134:         p1 = mulii(p1, lPpow); /* assume pr has degree 1 */
        !          1135:       }
        !          1136:       if (dn) p1 = mulii(p1,dn);
        !          1137:       if (dn || lP) p1 = modii(p1, pk);
        !          1138:       Tra[i] = (long)nf_bestlift(p1, NULL, L); /* S_tnew(famod) */
        !          1139:     }
1.1       noro     1140:
1.2     ! noro     1141:     /* compute truncation parameter */
        !          1142:     if (DEBUGLEVEL>2) { TIMERstart(&ti2); TIMERstart(&TI); }
        !          1143:     oldCM_L = CM_L;
        !          1144:     av2 = avma;
        !          1145:     b = delta = 0; /* -Wall */
        !          1146: AGAIN:
        !          1147:     M_L = gdivexact(CM_L, stoi(C));
        !          1148:     T2 = gmul(Tra, M_L);
        !          1149:     VV = gdivround(gmul(PRKinv, T2), pk);
        !          1150:     T2 = gsub(T2, gmul(PRK, VV));
        !          1151:
        !          1152:     if (first)
        !          1153:     { /* initialize lattice, using few p-adic digits for traces */
        !          1154:       a = gexpo(T2);
        !          1155:       bgood = (long)(a - max(32, BitPerFactor * r));
        !          1156:       b = max(bmin, bgood);
        !          1157:       delta = a - b;
1.1       noro     1158:     }
1.2     ! noro     1159:     else
        !          1160:     { /* add more p-adic digits and continue reduction */
        !          1161:       long b0 = gexpo(T2);
        !          1162:       if (b0 < b) b = b0;
        !          1163:       b = max(b-delta, bmin);
        !          1164:       if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */
        !          1165:     }
        !          1166:
        !          1167:     /* restart with truncated entries */
        !          1168:     q = shifti(gun, b);
        !          1169:     P1 = gdivround(PRK, q);
        !          1170:     S1 = gdivround(Tra, q);
        !          1171:     T2 = gsub(gmul(S1, M_L), gmul(P1, VV));
        !          1172:     m = vconcat( CM_L, T2 );
        !          1173:     if (first)
        !          1174:     {
        !          1175:       first = 0;
        !          1176:       m = concatsp( m, vconcat(ZERO, P1) );
        !          1177:       /*     [ C M_L   0  ]
        !          1178:        * m = [            ]   square matrix
        !          1179:        *     [  T2'   PRK ]   T2' = Tra * M_L  truncated
        !          1180:        */
        !          1181:     }
        !          1182:     CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti, &ti_LLL);
        !          1183:     if (DEBUGLEVEL>2)
        !          1184:       fprintferr("LLL_cmbf: b =%4ld; r =%3ld -->%3ld, time = %ld\n",
        !          1185:                  b, lg(m)-1, CM_L? lg(CM_L)-1: 1, TIMER(&TI));
        !          1186:     if (!CM_L) { list = _col(QXQ_normalize(P,nfT)); break; }
        !          1187:     if (b > bmin)
        !          1188:     {
        !          1189:       CM_L = gerepilecopy(av2, CM_L);
        !          1190:       goto AGAIN;
        !          1191:     }
        !          1192:     if (DEBUGLEVEL>2) msgTIMER(&ti2, "for this trace");
        !          1193:
        !          1194:     i = lg(CM_L) - 1;
        !          1195:     if (i == r && gegal(CM_L, oldCM_L))
1.1       noro     1196:     {
1.2     ! noro     1197:       CM_L = oldCM_L;
        !          1198:       avma = av2; continue;
1.1       noro     1199:     }
                   1200:
1.2     ! noro     1201:     if (i <= r && i*rec < n0)
        !          1202:     {
        !          1203:       if (DEBUGLEVEL>2) (void)TIMER(&ti);
        !          1204:       list = nf_check_factors(T, P, M_L, famod, pk);
        !          1205:       if (DEBUGLEVEL>2) ti_CF += TIMER(&ti);
        !          1206:       if (list) break;
        !          1207:       CM_L = gerepilecopy(av2, CM_L);
        !          1208:     }
        !          1209:     if (low_stack(lim, stack_lim(av,1)))
1.1       noro     1210:     {
1.2     ! noro     1211:       if(DEBUGMEM>1) err(warnmem,"nf_LLL_cmbf");
        !          1212:       gerepileall(av, 8, &CM_L,&TT,&Tra,&famod,&pk,&GSmin,&PRK,&PRKinv);
1.1       noro     1213:     }
                   1214:   }
1.2     ! noro     1215:   if (DEBUGLEVEL>2)
        !          1216:     fprintferr("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF);
        !          1217:   return list;
1.1       noro     1218: }
                   1219:
                   1220: static GEN
1.2     ! noro     1221: nf_combine_factors(nfcmbf_t *T, GEN polred, GEN p, long a, long klim)
1.1       noro     1222: {
1.2     ! noro     1223:   GEN z, res, L, listmod, famod = T->fact, nf = T->nf;
        !          1224:   long i, m, l, maxK = 3, nft = lg(famod)-1;
1.1       noro     1225:
1.2     ! noro     1226:   T->fact = hensel_lift_fact(polred,famod,NULL,p,T->pk,a);
        !          1227:   if (nft < 11) maxK = -1; /* few modular factors: try all posibilities */
        !          1228:   if (DEBUGLEVEL>3) msgtimer("Hensel lift");
1.1       noro     1229:
1.2     ! noro     1230:   /* FIXME: neither nfcmbf nor LLL_cmbf can handle the non-nf case */
1.1       noro     1231:
1.2     ! noro     1232:   T->res      = cgetg(nft+1,t_VEC);
        !          1233:   L = nfcmbf(T, p, a, maxK, klim);
1.1       noro     1234:
1.2     ! noro     1235:   res     = (GEN)L[1];
        !          1236:   listmod = (GEN)L[2]; l = lg(listmod)-1;
        !          1237:   famod = (GEN)listmod[l];
        !          1238:   if (maxK >= 0 && lg(famod)-1 > 2*maxK)
1.1       noro     1239:   {
1.2     ! noro     1240:     if (l > 1) T->polbase = unifpol(nf, (GEN)res[l], 0);
        !          1241:     L = nf_LLL_cmbf(T, p, a, maxK);
        !          1242:     /* remove last elt, possibly unfactored. Add all new ones. */
        !          1243:     setlg(res, l); res = concatsp(res, L);
1.1       noro     1244:   }
1.2     ! noro     1245:   if (DEBUGLEVEL>3) msgtimer("computation of the factors");
1.1       noro     1246:
1.2     ! noro     1247:   m = lg(res); z = cgetg(m, t_VEC);
        !          1248:   for (i=1;i<m; i++) z[i] = (long)unifpol(nf,(GEN)res[i],1);
        !          1249:   return z;
        !          1250: }
1.1       noro     1251:
1.2     ! noro     1252: /* return the factorization of the square-free polynomial x.
        !          1253:    The coeff of x are in Z_nf and its leading term is a rational integer.
        !          1254:    deg(x) > 1, deg(nfpol) > 1
        !          1255:    If fl = 1, return only the roots of x in nf
        !          1256:    If fl = 2, as fl=1 if pol splits, [] otherwise */
        !          1257: static GEN
        !          1258: nfsqff(GEN nf, GEN pol, long fl)
        !          1259: {
        !          1260:   long i, m, n, nbf, ct, dpol = degpol(pol);
        !          1261:   gpmem_t av = avma;
        !          1262:   GEN pr, C0, C, dk, bad, polbase, pk;
        !          1263:   GEN N2, rep, p, ap, polmod, polred, lt, nfpol;
        !          1264:   byteptr pt=diffptr;
        !          1265:   nfcmbf_t T;
        !          1266:   nflift_t L;
1.1       noro     1267:
1.2     ! noro     1268:   if (DEBUGLEVEL>3) msgtimer("square-free");
        !          1269:   nfpol = (GEN)nf[1]; n = degpol(nfpol);
        !          1270:   polbase = unifpol(nf,pol,0);
        !          1271:   polmod  = unifpol(nf,pol,1);
        !          1272:   /* heuristic */
        !          1273: #if 1
        !          1274:   if (dpol*4 < n)
1.1       noro     1275:   {
1.2     ! noro     1276:     if (DEBUGLEVEL>2) fprintferr("Using Trager's method\n");
        !          1277:     return gerepilecopy(av, (GEN)polfnf(polmod, nfpol)[1]);
1.1       noro     1278:   }
1.2     ! noro     1279: #endif
1.1       noro     1280:
1.2     ! noro     1281:   pol = simplify_i(lift(polmod));
        !          1282:   lt  = (GEN)leading_term(polbase)[1]; /* t_INT */
1.1       noro     1283:
1.2     ! noro     1284:   dk = absi((GEN)nf[3]);
        !          1285:   bad = mulii(mulii(dk,(GEN)nf[4]), lt);
1.1       noro     1286:
1.2     ! noro     1287:   p = polred = pr = NULL; /* gcc -Wall */
        !          1288:   nbf = 0; ap = NULL;
        !          1289:   for (ct = 5;;)
        !          1290:   {
        !          1291:     GEN apr = choose_prime(nf, bad, &ap, &pt);
        !          1292:     GEN modpr = zkmodprinit(nf, apr);
        !          1293:     long anbf;
1.1       noro     1294:
1.2     ! noro     1295:     polred = modprX(polbase, nf, modpr);
        !          1296:     if (!FpX_is_squarefree(polred,ap)) continue;
1.1       noro     1297:
1.2     ! noro     1298:     anbf = fl? FpX_nbroots(polred,ap): FpX_nbfact(polred,ap);
        !          1299:     if (!nbf || anbf < nbf)
1.1       noro     1300:     {
1.2     ! noro     1301:       nbf = anbf; pr = apr; p = ap;
        !          1302:       if (DEBUGLEVEL>3)
        !          1303:         fprintferr("%3ld %s at prime ideal above %Z\n",
        !          1304:                    nbf, fl?"roots": "factors", p);
        !          1305:       if (fl == 2 && nbf < dpol) return cgetg(1,t_VEC);
        !          1306:       if (nbf <= 1)
1.1       noro     1307:       {
1.2     ! noro     1308:         if (!fl) /* irreducible */
        !          1309:           return gerepilecopy(av, _vec(QXQ_normalize(polmod, nfpol)));
        !          1310:         if (!nbf) return cgetg(1,t_VEC); /* no root */
1.1       noro     1311:       }
                   1312:     }
1.2     ! noro     1313:     if (--ct <= 0) break;
1.1       noro     1314:   }
1.2     ! noro     1315:   if (DEBUGLEVEL>3) {
        !          1316:     msgtimer("choice of a prime ideal");
        !          1317:     fprintferr("Prime ideal chosen: %Z\n", pr);
        !          1318:   }
        !          1319:
        !          1320:   L.tozk = (GEN)nf[8];
        !          1321:   L.topow= (GEN)nf[7];
        !          1322:   T.ZC = L2_bound(nf, L.tozk, &(T.dn));
        !          1323:   T.Br = gmul(lt, nf_root_bounds(pol, nf));
        !          1324:
        !          1325:   if (fl) C0 = normlp(T.Br, 2, n);
        !          1326:   else    C0 = nf_factor_bound(nf, polbase); /* bound for T_2(Q_i), Q | P */
        !          1327:   C = mulrr(T.ZC, C0); /* bound for |Q_i|^2 in Z^n on chosen Z-basis */
        !          1328:   T.bound = C;
        !          1329:
        !          1330:   N2 = mulsr(dpol*dpol, normlp(T.Br, 4, n)); /* bound for T_2(lt * S_2) */
        !          1331:   T.BS_2 = mulrr(T.ZC, N2); /* bound for |S_2|^2 on chosen Z-basis */
        !          1332:
        !          1333:   if (DEBUGLEVEL>2) {
        !          1334:     msgtimer("bound computation");
        !          1335:     fprintferr("  1) T_2 bound for %s: %Z\n", fl?"root":"factor", C0);
        !          1336:     fprintferr("  2) Conversion from T_2 --> | |^2 bound : %Z\n", T.ZC);
        !          1337:     fprintferr("  3) Final bound: %Z\n", C);
1.1       noro     1338:   }
                   1339:
1.2     ! noro     1340:   if (fl)
        !          1341:     (void)logint(C, p, &pk);
        !          1342: #if 0 /* overkill */
        !          1343:   else
        !          1344:   { /* overlift needed for d-1/d-2 tests? */
        !          1345:     GEN pb; long b; /* junk */
        !          1346:     if (cmbf_precs(p, C, T.BS_2, &a, &b, &pk, &pb))
        !          1347:     { /* Rare */
        !          1348:       if (DEBUGLEVEL) err(warner,"nffactor: overlift for d-1/d-2 test");
        !          1349:       C = itor(pk, DEFAULTPREC);
        !          1350:     }
1.1       noro     1351:   }
1.2     ! noro     1352: #endif
1.1       noro     1353:
1.2     ! noro     1354:   bestlift_init(0, nf, pr, C, &L);
        !          1355:   T.pr = pr;
        !          1356:   T.L  = &L;
        !          1357:
        !          1358:   /* polred is monic */
        !          1359:   pk = L.pk;
        !          1360:   polred = ZpX(gmul(mpinvmod(lt,pk), polbase), pk, L.ZpProj);
1.1       noro     1361:
                   1362:   if (fl)
1.2     ! noro     1363:   { /* roots only */
        !          1364:     long x_r[] = { evaltyp(t_POL)|_evallg(4), 0,0,0 };
        !          1365:     rep = rootpadicfast(polred, p, L.k);
        !          1366:     x_r[1] = evalsigne(1) | evalvarn(varn(pol)) | evallgef(4);
        !          1367:     x_r[3] = un;
1.1       noro     1368:     for (m=1,i=1; i<lg(rep); i++)
                   1369:     {
1.2     ! noro     1370:       GEN q, r = (GEN)rep[i];
1.1       noro     1371:
1.2     ! noro     1372:       r = nf_bestlift_to_pol(gmul(lt,r), NULL, &L);
        !          1373:       r = gdiv(r,lt);
        !          1374:       x_r[2] = lneg(r); /* check P(r) == 0 */
        !          1375:       q = RXQX_divrem(pol, x_r, nfpol, ONLY_DIVIDES);
        !          1376:       if (q) { pol = q; rep[m++] = (long)r; }
        !          1377:       else if (fl == 2) return cgetg(1, t_VEC);
1.1       noro     1378:     }
1.2     ! noro     1379:     rep[0] = evaltyp(t_VEC) | evallg(m);
        !          1380:     return gerepilecopy(av, rep);
1.1       noro     1381:   }
                   1382:
1.2     ! noro     1383:   T.polbase = polbase;
        !          1384:   T.pol   = pol;
        !          1385:   T.nf    = nf;
        !          1386:   T.fact  = (GEN)factmod0(polred,p)[1];
        !          1387:   T.hint  = 1; /* useless */
1.1       noro     1388:
1.2     ! noro     1389:   rep = nf_combine_factors(&T, polred, p, L.k, dpol-1);
        !          1390:   return gerepileupto(av, rep);
1.1       noro     1391: }
                   1392:
1.2     ! noro     1393: /* return the characteristic polynomial of alpha over nf, where alpha
1.1       noro     1394:    is an element of the algebra nf[X]/(T) given as a polynomial in X */
                   1395: GEN
                   1396: rnfcharpoly(GEN nf,GEN T,GEN alpha,int v)
                   1397: {
1.2     ! noro     1398:   long vnf, vT, lT;
        !          1399:   gpmem_t av = avma;
1.1       noro     1400:   GEN p1;
                   1401:
                   1402:   nf=checknf(nf); vnf = varn(nf[1]);
                   1403:   if (v<0) v = 0;
                   1404:   T = fix_relative_pol(nf,T,1);
                   1405:   if (typ(alpha) == t_POLMOD) alpha = lift_to_pol(alpha);
                   1406:   lT = lgef(T);
                   1407:   if (typ(alpha) != t_POL || varn(alpha) == vnf)
                   1408:     return gerepileupto(av, gpowgs(gsub(polx[v], alpha), lT - 3));
                   1409:   vT = varn(T);
                   1410:   if (varn(alpha) != vT || v >= vnf)
                   1411:     err(talker,"incorrect variables in rnfcharpoly");
                   1412:   if (lgef(alpha) >= lT) alpha = gmod(alpha,T);
                   1413:   if (lT <= 4)
                   1414:     return gerepileupto(av, gsub(polx[v], alpha));
                   1415:   p1 = caract2(unifpol(nf,T,1), unifpol(nf,alpha,1), v);
                   1416:   return gerepileupto(av, unifpol(nf,p1,1));
                   1417: }

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