=================================================================== RCS file: /home/cvs/OpenXM_contrib/pari-2.2/src/basemath/Attic/buch2.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- OpenXM_contrib/pari-2.2/src/basemath/Attic/buch2.c 2001/10/02 11:17:03 1.1 +++ OpenXM_contrib/pari-2.2/src/basemath/Attic/buch2.c 2002/09/11 07:26:50 1.2 @@ -1,4 +1,4 @@ -/* $Id: buch2.c,v 1.1 2001/10/02 11:17:03 noro Exp $ +/* $Id: buch2.c,v 1.2 2002/09/11 07:26:50 noro Exp $ Copyright (C) 2000 The PARI group. @@ -21,23 +21,28 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, /*******************************************************************/ #include "pari.h" #include "parinf.h" +extern GEN gscal(GEN x,GEN y); +extern GEN nfbasic_to_nf(nfbasic_t *T, GEN ro, long prec); +extern GEN get_nfindex(GEN bas); +extern GEN sqred1_from_QR(GEN x, long prec); +extern GEN computeGtwist(GEN nf, GEN vdir); +extern GEN famat_mul(GEN f, GEN g); +extern GEN famat_to_nf(GEN nf, GEN f); +extern GEN famat_to_arch(GEN nf, GEN fa, long prec); extern GEN to_famat_all(GEN x, GEN y); extern int addcolumntomatrix(GEN V, GEN invp, GEN L); extern double check_bach(double cbach, double B); extern GEN gmul_mat_smallvec(GEN x, GEN y); extern GEN gmul_mati_smallvec(GEN x, GEN y); +extern GEN get_arch(GEN nf,GEN x,long prec); extern GEN get_arch_real(GEN nf,GEN x,GEN *emb,long prec); -extern GEN get_roots(GEN x,long r1,long ru,long prec); -extern void get_nf_matrices(GEN nf, long small); -extern long int_elt_val(GEN nf, GEN x, GEN p, GEN b, GEN *t, long v); -extern GEN init_idele(GEN nf); +extern GEN get_roots(GEN x,long r1,long prec); +extern long int_elt_val(GEN nf, GEN x, GEN p, GEN b, GEN *t); extern GEN norm_by_embed(long r1, GEN x); extern void minim_alloc(long n,double ***q,long **x,double **y,double **z,double **v); -extern GEN idealmulpowprime(GEN nf, GEN x, GEN vp, GEN n); extern GEN arch_mul(GEN x, GEN y); -extern GEN vecdiv(GEN x, GEN y); -extern GEN vecmul(GEN x, GEN y); -extern GEN mul_real(GEN x, GEN y); +extern void wr_rel(GEN col); +extern void dbg_rel(long s, GEN col); #define SFB_MAX 2 #define SFB_STEP 2 @@ -48,132 +53,161 @@ static const int CBUCHG = (1<= KC) - * - * KCZ = number of rational primes under ideals counted by KC - * KCZ2= same for KC2 - */ + * KCZ = # of rational primes under ideals counted by KC + * KCZ2= same for KC2 */ +typedef struct { + GEN FB; /* FB[i] = i-th rational prime used in factor base */ + GEN LP; /* vector of all prime ideals in FB */ + GEN *LV; /* LV[p] = vector of P|p, NP <= n2 + * isclone() is set for LV[p] iff all P|p are in FB + * LV[i], i not prime or i > n2, is undefined! */ + GEN iLP; /* iLP[p] = i such that LV[p] = [LP[i],...] */ + long KC, KCZ, KCZ2; + GEN subFB; /* LP o subFB = part of FB used to build random relations */ + GEN powsubFB; /* array of [P^0,...,P^CBUCHG], P in LP o subFB */ + GEN perm; /* permutation of LP used to represent relations [updated by + hnfspec/hnfadd: dense rows come first] */ +} FB_t; /* x a t_VECSMALL */ static long ccontent(GEN x) { - long i, l = lg(x), s=labs(x[1]); - for (i=2; i1; i++) s = cgcd(x[i],s); + long i, l = lg(x), s = labs(x[1]); + for (i=2; i1) { y1[i]=zero; s=0; z++; } else { y1[i]=y2[i]; s += ef; } +/* don't take P|p if P ramified, or all other Q|p already there */ +static int +ok_subFB(FB_t *F, long t, GEN D) +{ + GEN LP, P = (GEN)F->LP[t]; + long p = itos((GEN)P[1]); + LP = F->LV[p]; + return smodis(D,p) && (!isclone(LP) || t != F->iLP[p] + lg(LP)-1); +} - i++; Q = (GEN)vectbase[i]; - if (i == lv || !egalii((GEN)P[1], (GEN)Q[1])) - { /* don't take all P above a given p (delete the last one) */ - if (s == N) { y1[i-1]=zero; z++; } - if (s1== N) ss++; - if (i == lv) break; - s = s1 = 0; - } +/* set subFB, reset F->powsubFB + * Fill F->perm (if != NULL): primes ideals sorted by increasing norm (except + * the ones in subFB come first [dense rows for hnfspec]) */ +static int +subFBgen(FB_t *F, GEN nf, double PROD, long minsFB) +{ + GEN y, perm, yes, no, D = (GEN)nf[3]; + long i, j, k, iyes, ino, lv = F->KC + 1; + double prod; + const int init = (F->perm == NULL); + gpmem_t av; + + if (init) + { + F->LP = cgetg(lv, t_VEC); + F->perm = cgetg(lv, t_VECSMALL); } - if (z+minsFB >= lv) return NULL; - prod = 1.0; - perm = sindexsort(y1) + z; /* skip "zeroes" (excluded ideals) */ - for(;;) + av = avma; + y = cgetg(lv,t_COL); /* Norm P */ + for (k=0, i=1; i <= F->KCZ; i++) { - if (++n > minsFB && (z+n >= lv || prod > m + 0.5)) break; - prod *= gtodouble((GEN)y1[perm[n]]); + GEN LP = F->LV[F->FB[i]]; + long l = lg(LP); + for (j = 1; j < l; j++) + { + GEN P = (GEN)LP[j]; + k++; + y[k] = (long)powgi((GEN)P[1], (GEN)P[4]); + F->LP[k] = (long)P; /* noop if init = 1 */ + } } - if (prod < m) return NULL; - n--; + /* perm sorts LP by increasing norm */ + perm = sindexsort(y); + no = cgetg(lv, t_VECSMALL); ino = 1; + yes = cgetg(lv, t_VECSMALL); iyes = 1; + prod = 1.0; + for (i = 1; i < lv; i++) + { + long t = perm[i]; + if (!ok_subFB(F, t, D)) { no[ino++] = t; continue; } - /* take the first (non excluded) n ideals (wrt norm), put them first, and - * sort the rest by increasing norm */ - for (j=1; j<=n; j++) y2[perm[j]] = zero; - perm1 = sindexsort(y2); avma = av; - - subFB = cgetg(n+1, t_VECSMALL); - if (vperm) + yes[iyes++] = t; + prod *= (double)itos((GEN)y[t]); + if (iyes > minsFB && prod > PROD) break; + } + if (i == lv) return 0; + avma = av; /* HACK: gcopy(yes) still safe */ + if (init) { - for (j=1; j<=n; j++) vperm[j] = perm[j]; - for ( ; jperm; + for (j=1; jsubFB = gcopy(yes); + F->powsubFB = NULL; return 1; +} +static int +subFBgen_increase(FB_t *F, GEN nf, long step) +{ + GEN yes, D = (GEN)nf[3]; + long i, iyes, lv = F->KC + 1, minsFB = lg(F->subFB)-1 + step; - if (DEBUGLEVEL) + yes = cgetg(minsFB+1, t_VECSMALL); iyes = 1; + for (i = 1; i < lv; i++) { - if (DEBUGLEVEL>3) - { - fprintferr("\n***** IDEALS IN FACTORBASE *****\n\n"); - for (i=1; i<=KC; i++) fprintferr("no %ld = %Z\n",i,vectbase[i]); - fprintferr("\n***** IDEALS IN SUB FACTORBASE *****\n\n"); - outerr(vecextract_p(vectbase,subFB)); - fprintferr("\n***** INITIAL PERMUTATION *****\n\n"); - fprintferr("vperm = %Z\n\n",vperm); - } - msgtimer("sub factorbase (%ld elements)",n); + long t = F->perm[i]; + if (!ok_subFB(F, t, D)) continue; + + yes[iyes++] = t; + if (iyes > minsFB) break; } - powsubFB = NULL; - *ptss = ss; return subFB; + if (i == lv) return 0; + F->subFB = yes; + F->powsubFB = NULL; return 1; } static GEN mulred(GEN nf,GEN x, GEN I, long prec) { - ulong av = avma; + gpmem_t av = avma; GEN y = cgetg(3,t_VEC); y[1] = (long)idealmulh(nf,I,(GEN)x[1]); @@ -185,22 +219,21 @@ mulred(GEN nf,GEN x, GEN I, long prec) /* Compute powers of prime ideals (P^0,...,P^a) in subFB (a > 1) * powsubFB[j][i] contains P_i^j in LLL form + archimedean part in - * MULTIPLICATIVE form (logs are expensive) - */ + * MULTIPLICATIVE form (logs are expensive) */ static void -powsubFBgen(GEN nf,GEN subFB,long a,long prec) +powsubFBgen(FB_t *F, GEN nf, long a, long prec) { - long i,j, n = lg(subFB), RU = lg(nf[6]); + long i,j, n = lg(F->subFB), RU = lg(nf[6]); GEN *pow, arch0 = cgetg(RU,t_COL); for (i=1; ipowsubFB = cgetg(n, t_VEC); for (i=1; iLP[ F->subFB[i] ]; GEN z = cgetg(3,t_VEC); z[1]=vp[1]; z[2]=vp[2]; - pow = (GEN*)cgetg(a+1,t_VEC); powsubFB[i] = (long)pow; + pow = (GEN*)cgetg(a+1,t_VEC); F->powsubFB[i] = (long)pow; pow[1]=cgetg(3,t_VEC); pow[1][1] = (long)z; pow[1][2] = (long)arch0; @@ -215,273 +248,276 @@ powsubFBgen(GEN nf,GEN subFB,long a,long prec) if (DEBUGLEVEL) msgtimer("powsubFBgen"); } -/* Compute FB, numFB, idealbase, vectbase, numideal. +/* Compute FB, LV, iLP + KC*. Reset perm * n2: bound for norm of tested prime ideals (includes be_honest()) - * n : bound for prime ideals used to build relations (Bach cst) ( <= n2 ) + * n : bound for p, such that P|p (NP <= n2) used to build relations * Return prod_{p<=n2} (1-1/p) / prod_{Norm(P)<=n2} (1-1/Norm(P)), - * close to residue of zeta_K at 1 = 2^r1 (2pi)^r2 h R / (w D) - */ + * close to residue of zeta_K at 1 = 2^r1 (2pi)^r2 h R / (w D) */ static GEN -FBgen(GEN nf,long n2,long n) +FBgen(FB_t *F, GEN nf,long n2,long n) { - byteptr delta=diffptr; - long KC2,i,j,k,p,lon,ip,nor, N = degpol(nf[1]); - GEN p2,p1,NormP,lfun; - long prim[] = { evaltyp(t_INT)|m_evallg(3), evalsigne(1)|evallgefint(3),0 }; + byteptr delta = diffptr; + long i, p, ip; + GEN prim, Res; - numFB = cgetg(n2+1,t_VECSMALL); - FB = cgetg(n2+1,t_VECSMALL); - numideal = cgetg(n2+1,t_VECSMALL); - idealbase= (GEN*)cgetg(n2+1,t_VEC); + if (maxprime() < n2) err(primer1); + F->FB = cgetg(n2+1, t_VECSMALL); + F->iLP = cgetg(n2+1, t_VECSMALL); + F->LV = (GEN*)new_chunk(n2+1); - lfun=realun(DEFAULTPREC); - p=*delta++; i=0; ip=0; KC=0; - while (p<=n2) + Res = realun(DEFAULTPREC); + prim = icopy(gun); + i = ip = 0; + F->KC = F->KCZ = 0; + for (p = 0;;) /* p <= n2 */ { - long av = avma, av1; - if (DEBUGLEVEL>=2) { fprintferr(" %ld",p); flusherr(); } - prim[2] = p; p1 = primedec(nf,prim); lon=lg(p1); - av1 = avma; - divrsz(mulsr(p-1,lfun),p,lfun); - if (itos(gmael(p1,1,4)) == N) /* p inert */ + gpmem_t av = avma, av1; + long k, l; + GEN P, a, b; + + NEXT_PRIME_VIADIFF(p, delta); + if (!F->KC && p > n) { F->KCZ = i; F->KC = ip; } + if (p > n2) break; + + if (DEBUGLEVEL>1) { fprintferr(" %ld",p); flusherr(); } + prim[2] = p; P = primedec(nf,prim); l = lg(P); + + /* a/b := (p-1)/p * prod_{P|p, NP <= n2} NP / (NP-1) */ + av1 = avma; a = b = NULL; + for (k=1; k n2) break; + GEN NormP = powgi(prim, gmael(P,k,4)); + long nor; + if (is_bigint(NormP) || (nor=NormP[2]) > n2) break; - divrsz(mulsr(nor,lfun),nor-1, lfun); - } - /* keep all ideals with Norm <= n2 */ - avma = av1; - if (k == lon) - setisclone(p1); /* flag it: all prime divisors in FB */ - else - { setlg(p1,k); p1 = gerepilecopy(av,p1); } - idealbase[i] = p1; + if (a) { a = mului(nor, a); b = mului(nor-1, b); } + else { a = utoi(nor / p); b = utoi((nor-1) / (p-1)); } } - if (!*delta) err(primer1); - p += *delta++; - if (KC == 0 && p>n) { KCZ=i; KC=ip; } - } - if (!KC) return NULL; - KCZ2=i; KC2=ip; MAXRELSUP = min(50,4*KC); + if (a) affrr(divri(mulir(a,Res),b), Res); + else affrr(divrs(mulsr(p-1,Res),p), Res); + avma = av1; + if (l == 2 && itos(gmael(P,1,3)) == 1) continue; /* p inert */ - setlg(FB,KCZ2); - setlg(numFB,KCZ2); - setlg(numideal,KCZ2); - setlg(idealbase,KCZ2); - vectbase=cgetg(KC+1,t_COL); - for (i=1; i<=KCZ; i++) - { - p1 = idealbase[i]; k=lg(p1); - p2 = vectbase + numideal[FB[i]]; - for (j=1; jFB[++i]= p; + F->LV[p] = P; + F->iLP[p] = ip; ip += k-1; } + if (! F->KC) return NULL; + setlg(F->FB, F->KCZ+1); F->KCZ2 = i; if (DEBUGLEVEL) { if (DEBUGLEVEL>1) fprintferr("\n"); if (DEBUGLEVEL>6) { fprintferr("########## FACTORBASE ##########\n\n"); - fprintferr("KC2=%ld, KC=%ld, KCZ=%ld, KCZ2=%ld, MAXRELSUP=%ld\n", - KC2, KC, KCZ, KCZ2, MAXRELSUP); - for (i=1; i<=KCZ; i++) - fprintferr("++ idealbase[%ld] = %Z",i,idealbase[i]); + fprintferr("KC2=%ld, KC=%ld, KCZ=%ld, KCZ2=%ld\n", + ip, F->KC, F->KCZ, F->KCZ2); + for (i=1; i<=F->KCZ; i++) fprintferr("++ LV[%ld] = %Z",i,F->LV[F->FB[i]]); } msgtimer("factor base"); } - return lfun; + F->perm = NULL; return Res; } -/* can we factor I / m ? (m pseudo minimum, computed in ideallllredpart1) */ -static long -factorgen(GEN nf,GEN idealvec,long kcz,long limp) +/* SMOOTH IDEALS */ +static void +store(long i, long e) { - long i,j,n1,ip,v,p,k,lo,ifinal; - GEN x,q,r,P,p1,listexpo; - GEN I = (GEN)idealvec[1]; - GEN m = (GEN)idealvec[2]; - GEN Nm= absi( subres(gmul((GEN)nf[7],m), (GEN)nf[1]) ); /* |Nm| */ + primfact[++primfact[0]] = i; /* index */ + exprimfact[primfact[0]] = e; /* exponent */ +} - x = divii(Nm, dethnf_i(I)); /* m in I, so NI | Nm */ - if (is_pm1(x)) { primfact[0]=0; return 1; } - listexpo = new_chunk(kcz+1); - for (i=1; ; i++) +/* divide out x by all P|p, where x as in can_factor(). k = v_p(Nx) */ +static int +divide_p_elt(FB_t *F, long p, long k, GEN nf, GEN m) +{ + GEN P, LP = F->LV[p]; + long j, v, l = lg(LP), ip = F->iLP[p]; + for (j=1; j 0 */ + k -= v * itos((GEN)P[4]); + if (!k) return 1; } - if (cmpis(x,limp) > 0) return 0; - - ifinal = i; lo = 0; - for (i=1; i<=ifinal; i++) + return 0; +} +static int +divide_p_id(FB_t *F, long p, long k, GEN nf, GEN I) +{ + GEN P, LP = F->LV[p]; + long j, v, l = lg(LP), ip = F->iLP[p]; + for (j=1; j 0 */ + k -= v * itos((GEN)P[4]); + if (!k) return 1; } - if (is_pm1(x)) { primfact[0]=lo; return 1; } - - p = itos(x); p1 = idealbase[numFB[p]]; - n1 = lg(p1); ip = numideal[p]; - for (k=1,j=1; jLV[p]; + long j, v, l = lg(LP), ip = F->iLP[p]; + for (j=1; j 0 a smooth rational integer wrt F ? (put the exponents in *ex) */ +static int +smooth_int(FB_t *F, GEN *N, GEN *ex) { - long i,j,n1,ip,v,p,k,lo,ifinal; - GEN q,r,P,p1,listexpo; + GEN q, r, FB = F->FB; + const long KCZ = F->KCZ; + const long limp = FB[KCZ]; /* last p in FB */ + long i, p, k; - if (is_pm1(Nx)) { primfact[0]=0; return 1; } - listexpo = new_chunk(kcz+1); + *ex = new_chunk(KCZ+1); for (i=1; ; i++) { - p=FB[i]; q=dvmdis(Nx,p,&r); - for (k=0; !signe(r); k++) { Nx=q; q=dvmdis(Nx,p,&r); } - listexpo[i] = k; - if (cmpis(q,p)<=0) break; - if (i==kcz) return 0; + p = FB[i]; q = dvmdis(*N,p,&r); + for (k=0; !signe(r); k++) { *N = q; q = dvmdis(*N, p, &r); } + (*ex)[i] = k; + if (cmpis(q,p) <= 0) break; + if (i == KCZ) return 0; } - if (cmpis(Nx,limp) > 0) return 0; + (*ex)[0] = i; + return (cmpis(*N,limp) <= 0); +} - if (cbase) x = gmul(cbase,x); - ifinal=i; lo = 0; - for (i=1; i<=ifinal; i++) - { - k = listexpo[i]; - if (k) - { - p = FB[i]; p1 = idealbase[numFB[p]]; - n1 = lg(p1); ip = numideal[p]; - for (j=1; j 0 */ +static long +can_factor(FB_t *F, GEN nf, GEN I, GEN m, GEN N) +{ + GEN ex; + long i; + primfact[0] = 0; + if (is_pm1(N)) return 1; + if (!smooth_int(F, &N, &ex)) return 0; + for (i=1; i<=ex[0]; i++) + if (ex[i] && !divide_p(F, F->FB[i], ex[i], nf, I, m)) return 0; + return is_pm1(N) || divide_p(F, itos(N), 1, nf, I, m); +} + +/* can we factor I/m ? [m in I from pseudomin] */ +static long +factorgen(FB_t *F, GEN nf, GEN I, GEN m) +{ + GEN Nm = absi( subres(gmul((GEN)nf[7],m), (GEN)nf[1]) ); /* |Nm| */ + GEN N = diviiexact(Nm, dethnf_i(I)); /* N(m / I) */ + return can_factor(F, nf, I, m, N); +} + +/* FUNDAMENTAL UNITS */ + +/* a, m real. Return (Re(x) + a) + I * (Im(x) % m) */ +static GEN +addRe_modIm(GEN x, GEN a, GEN m) +{ + GEN re, im, z; + if (typ(x) == t_COMPLEX) { - P = (GEN)p1[j]; - v = int_elt_val(nf,x,(GEN)P[1],(GEN)P[5], NULL, k); - if (v) + re = gadd((GEN)x[1], a); + im = gmod((GEN)x[2], m); + if (gcmp0(im)) z = re; + else { - primfact[++lo]=ip+j; expoprimfact[lo]=v; - k -= v*itos((GEN)P[4]); - if (!k) { primfact[0]=lo; return 1; } + z = cgetg(3,t_COMPLEX); + z[1] = (long)re; + z[2] = (long)im; } } - return 0; + else + z = gadd(x, a); + return z; } +/* clean archimedean components */ static GEN -cleancol(GEN x,long N,long PRECREG) +cleanarch(GEN x, long N, long prec) { - long i,j,av,tetpil,tx=typ(x),R1,RU; - GEN s,s2,re,pi4,im,y; + long i, R1, RU, tx = typ(x); + GEN s, y, pi2; - if (tx==t_MAT) + if (tx == t_MAT) { - y=cgetg(lg(x),tx); - for (j=1; jR1)? gmul2n(s,1): NULL; - pi4=gmul2n(mppi(PRECREG),2); - tetpil=avma; y=cgetg(RU+1,tx); - for (i=1; i<=RU; i++) + if (!is_vec_t(tx)) err(talker,"not a vector/matrix in cleanarch"); + RU = lg(x)-1; R1 = (RU<<1)-N; + s = gdivgs(sum(greal(x), 1, RU), -N); /* -log |norm(x)| / N */ + y = cgetg(RU+1,tx); + pi2 = Pi2n(1, prec); + for (i=1; i<=R1; i++) y[i] = (long)addRe_modIm((GEN)x[i], s, pi2); + if (i <= RU) { - GEN p1=cgetg(3,t_COMPLEX); y[i]=(long)p1; - p1[1] = ladd((GEN)re[i], (i<=R1)?s:s2); - p1[2] = lmod((GEN)im[i], pi4); + GEN pi4 = Pi2n(2, prec), s2 = gmul2n(s, 1); + for ( ; i<=RU; i++) y[i] = (long)addRe_modIm((GEN)x[i], s2, pi4); } - return gerepile(av,tetpil,y); + return y; } -#define RELAT 0 -#define LARGE 1 -#define PRECI 2 +enum { RELAT, LARGE, PRECI }; + static GEN -not_given(long av, long flun, long reason) +not_given(gpmem_t av, long fl, long reason) { - if (labs(flun)==2) + if (! (fl & nf_FORCE)) { char *s; switch(reason) { - case RELAT: s = "not enough relations for fundamental units"; break; case LARGE: s = "fundamental units too large"; break; case PRECI: s = "insufficient precision for fundamental units"; break; default: s = "unknown problem with fundamental units"; } err(warner,"%s, not given",s); } - avma=av; return cgetg(1,t_MAT); + avma = av; return cgetg(1,t_MAT); } /* check whether exp(x) will get too big */ static long expgexpo(GEN x) { - long i,j,e, E = -HIGHEXPOBIT; + long i,j,e, E = - (long)HIGHEXPOBIT; GEN p1; for (i=1; i>1; if (RU==1) { *pte=BIGINT; return cgetg(1,t_VEC); } - *pte = 0; xarch = *ptxarch; - if (gexpo(reg) < -8) return not_given(av,flun,RELAT); - + *pte = 0; A = *ptA; matep = cgetg(RU,t_MAT); for (j=1; j 20) { *pte = BIGINT; return not_given(av,flun,LARGE); } + if (expgexpo(p1) > 20) { *pte = BIGINT; return not_given(av,fl,LARGE); } matep = gexp(p1,prec); y = grndtoi(gauss_realimag(nf,matep), &e); *pte = -e; - if (e>=0) return not_given(av,flun,PRECI); + if (e >= 0) return not_given(av,fl,PRECI); for (j=1; j 0 */ y = gmul((GEN)nf[7], y); - vec = cgetg(RU+1,t_COL); p2 = mppi(prec); - p1 = pureimag(p2); - p2 = pureimag(gmul2n(p2,1)); - for (i=1; i<=R1; i++) vec[i]=(long)p1; - for ( ; i<=RU; i++) vec[i]=(long)p2; + vec = cgetg(RU+1,t_COL); + p1 = PiI2n(0,prec); for (i=1; i<=R1; i++) vec[i] = (long)p1; + p2 = PiI2n(1,prec); for ( ; i<=RU; i++) vec[i] = (long)p2; for (j=1; j pmax) pmax = p; + } + L = cgetg(pmax+1, t_VEC); + for (p=1; p<=pmax; p++) L[p] = 0; + if (list_pr) + { + for (i=1; iKCZ = i; + F->FB = FB; setlg(FB, i+1); + F->LV = (GEN*)LV; + F->iLP= iLP; return L; } +static GEN +init_famat(GEN x) +{ + GEN y = cgetg(3, t_VEC); + y[1] = (long)x; + y[2] = lgetg(1,t_MAT); return y; +} + +/* add v^e to factorization */ static void -init_sub(long l, GEN perm, GEN *v, GEN *ex) +add_to_fact(long v, long e) { - long i; - *v = cgetg(l,t_VECSMALL); - *ex= cgetg(l,t_VECSMALL); - for (i=1; iiLP[p] + pr_index(F->LV[p], pr); +} + +/* return famat y (principal ideal) such that x / y is smooth [wrt Vbase] */ static GEN -split_ideal(GEN nf, GEN x0, long prec, GEN vperm) +SPLIT(FB_t *F, GEN nf, GEN x, GEN Vbase) { - GEN p1,vdir,id,z,v,ex,y, x = (GEN)x0[1]; - long nbtest_lim,nbtest,bou,i,ru, lgsub; + GEN vdir, id, z, ex, y, x0; + long nbtest_lim, nbtest, bou, i, ru, lgsub; int flag = (gexpo(gcoeff(x,1,1)) < 100); - y = x0; - if (flag && factorgensimple(nf,y)) return y; + /* try without reduction if x is small */ + if (flag && can_factor(F, nf, x, NULL, dethnf_i(x))) return NULL; - y = ideallllred(nf,x0,NULL,prec); - if (flag && ((!x0[2] && gegal((GEN)y[1], (GEN)x[1])) - || (x0[2] && gcmp0((GEN)y[2])))) flag = 0; /* y == x0 */ - if (flag && factorgensimple(nf,y)) return y; + /* if reduction fails (y scalar), do not retry can_factor */ + y = idealred_elt(nf,x); + if ((!flag || !isnfscalar(y)) && factorgen(F, nf, x, y)) return y; - z = init_idele(nf); ru = lg(z[2]); - if (!x0[2]) { z[2] = 0; x0 = x; } /* stop cheating */ - vdir = cgetg(ru,t_VEC); - for (i=2; i2) fprintferr("# ideals tried = %ld\n",nbtest); id = x0; for (i=1; i> randshift; if (ex[i]) - { /* don't let id become too large as lgsub gets bigger: avoid - prec problems */ - if (non0) id = ideallllred(nf,id,NULL,prec); - non0++; - z[1]=vectbase[v[i]]; p1=idealpowred(nf,z,stoi(ex[i]),prec); - id = idealmulh(nf,id,p1); + { /* avoid prec pb: don't let id become too large as lgsub increases */ + if (id != x0) id = ideallllred(nf,id,NULL,0); + z[1] = Vbase[i]; + id = idealmulh(nf, id, idealpowred(nf,z,stoi(ex[i]),0)); } } if (id == x0) continue; - for (i=1; i> randshift); + for (i=1; i> randshift; for (bou=1; bou1) + y = ideallllred_elt(nf, (GEN)id[1], vdir); + if (factorgen(F, nf, (GEN)id[1], y)) { - for (i=1; i2) - fprintferr("nbtest = %ld, ideal = %Z\n",nbtest,y[1]); - if (factorgensimple(nf,y)) - { - long l = primfact[0]; - for (i=1; i nbtest_lim) + avma = av; + if (++nbtest > nbtest_lim) { nbtest = 0; - if (lgsub < 7) + if (++lgsub < 7) { - lgsub++; nbtest_lim <<= 2; - init_sub(lgsub, vperm, &v, &ex); + nbtest_lim <<= 1; + ex = cgetg(lgsub, t_VECSMALL); } else nbtest_lim = VERYBIGINT; /* don't increase further */ - if (DEBUGLEVEL) - fprintferr("split_ideal: increasing factor base [%ld]\n",lgsub); + if (DEBUGLEVEL) fprintferr("SPLIT: increasing factor base [%ld]\n",lgsub); } } } -static void -get_split_expo(GEN xalpha, GEN yalpha, GEN vperm) +static GEN +split_ideal(GEN nf, GEN x, GEN Vbase) { - long i, colW = lg(xalpha)-1; - GEN vinvperm = new_chunk(lg(vectbase)); - for (i=1; i (p,j) */ + long q,k,t, C = primfact[i]; + for (t=1; t1) + fprintferr("PHASE 1: check primes to Zimmert bound = %ld\n\n",bound); + dK= (GEN)nf[3]; + f = (GEN)nf[4]; + if (!gcmp1(f)) { - long k = vinvperm[primfact[i]]; - long l = k - colW; - if (l <= 0) xalpha[k]=lstoi(expoprimfact[i]); - else yalpha[l]=lstoi(expoprimfact[i]); + GEN D = gmael(nf,5,5); + if (DEBUGLEVEL>1) fprintferr("**** Testing Different = %Z\n",D); + p1 = isprincipalall(bnf, D, nf_FORCE); + if (DEBUGLEVEL>1) fprintferr(" is %Z\n", p1); } + /* sort factorbase for tablesearch */ + fb = gen_sort((GEN)bnf[5], 0, &cmp_prime_ideal); + p1 = gmael(fb, lg(fb)-1, 1); /* largest p in factorbase */ + pmax = is_bigint(p1)? VERYBIGINT: itos(p1); + if ((ulong)bound > maxprime()) err(primer1); + Vbase = get_Vbase(bnf); + (void)recover_partFB(&F, Vbase, degpol(nf[1])); + av = avma; + for (p = 0; p < bound; ) + { + NEXT_PRIME_VIADIFF(p, d); + if (DEBUGLEVEL>1) fprintferr("*** p = %ld\n",p); + vP = primedec(bnf, stoi(p)); + nbideal = lg(vP)-1; + /* loop through all P | p if ramified, all but one otherwise */ + if (!smodis(dK,p)) nbideal++; + for (i=1; i1) fprintferr(" Testing P = %Z\n",P); + if (cmpis(idealnorm(bnf,P), bound) >= 0) + { + if (DEBUGLEVEL>1) fprintferr(" Norm(P) > Zimmert bound\n"); + continue; + } + if (p <= pmax && (k = tablesearch(fb, P, &cmp_prime_ideal))) + { if (DEBUGLEVEL>1) fprintferr(" #%ld in factor base\n",k); } + else if (DEBUGLEVEL>1) + fprintferr(" is %Z\n", isprincipal(bnf,P)); + else /* faster: don't compute result */ + SPLIT(&F, nf, prime_to_ideal(nf,P), Vbase); + } + avma = av; + } + if (DEBUGLEVEL>1) { fprintferr("End of PHASE 1.\n\n"); flusherr(); } + avma = av0; } GEN @@ -897,7 +1010,7 @@ red_mod_units(GEN col, GEN z, long prec) RU = lg(mat); x = cgetg(RU+1,t_COL); for (i=1; i= l */ - z = cgetg(l, t_VEC); - for (i=1; i>1; - col = cleancol(col,N,prec); settyp(col, t_COL); + col = cleanarch(col,N,prec); settyp(col, t_COL); if (RU > 1) { /* reduce mod units */ GEN u, z = init_red_mod_units(bnf,prec); @@ -1001,59 +1121,64 @@ isprincipalarch(GEN bnf, GEN col, GEN kNx, GEN e, GEN static int fact_ok(GEN nf, GEN y, GEN C, GEN g, GEN e) { + gpmem_t av = avma; long i, c = lg(e); GEN z = C? C: gun; for (i=1; i> TWOPOTBITS_IN_LONG) + (MEDDEFAULTPREC-2); @@ -1088,8 +1219,11 @@ isprincipalall0(GEN bnf, GEN x, long *ptprec, long fla e = 0; } y = cgetg(4,t_VEC); + if (!xc) xc = gun; + col = e? gmul(xc,col): cgetg(1,t_COL); + if (flag & nf_GEN_IF_PRINCIPAL) return col; y[1] = lcopy(ex); - y[2] = e? lmul(xc,col): lgetg(1,t_COL); + y[2] = (long)col; y[3] = lstoi(-e); return y; } @@ -1097,18 +1231,20 @@ static GEN triv_gen(GEN nf, GEN x, long c, long flag) { GEN y; - if (!(flag & nf_GEN)) return zerocol(c); + if (flag & nf_GEN_IF_PRINCIPAL) + return (typ(x) == t_COL)? gcopy(x): algtobasis(nf,x); + if (!(flag & (nf_GEN|nf_GENMAT))) return zerocol(c); y = cgetg(4,t_VEC); y[1] = (long)zerocol(c); - x = (typ(x) == t_COL)? gcopy(x): algtobasis(nf,x); - y[2] = (long)x; + y[2] = (long)((typ(x) == t_COL)? gcopy(x): algtobasis(nf,x)); y[3] = lstoi(BIGINT); return y; } GEN isprincipalall(GEN bnf,GEN x,long flag) { - long av = avma,c,pr, tx = typ(x); + long c, pr, tx = typ(x); + gpmem_t av = avma; GEN nf; bnf = checkbnf(bnf); nf = (GEN)bnf[7]; @@ -1118,26 +1254,26 @@ isprincipalall(GEN bnf,GEN x,long flag) err(talker,"not the same number field in isprincipal"); x = (GEN)x[2]; tx = t_POL; } - if (tx == t_POL || tx == t_COL) + if (tx == t_POL || tx == t_COL || tx == t_INT || tx == t_FRAC) { if (gcmp0(x)) err(talker,"zero ideal in isprincipal"); return triv_gen(nf, x, lg(mael3(bnf,8,1,2))-1, flag); } x = idealhermite(nf,x); if (lg(x)==1) err(talker,"zero ideal in isprincipal"); - if (lgef(nf[1])==4) + if (degpol(nf[1]) == 1) return gerepileupto(av, triv_gen(nf, gcoeff(x,1,1), 0, flag)); pr = prec_arch(bnf); /* precision of unit matrix */ c = getrand(); for (;;) { - long av1 = avma; - GEN y = isprincipalall0(bnf,x,&pr,flag); + gpmem_t av1 = avma; + GEN y = _isprincipal(bnf,x,&pr,flag); if (y) return gerepileupto(av,y); - if (DEBUGLEVEL) err(warnprec,"isprincipalall0",pr); - avma = av1; bnf = bnfnewprec(bnf,pr); setrand(c); + if (DEBUGLEVEL) err(warnprec,"isprincipal",pr); + avma = av1; bnf = bnfnewprec(bnf,pr); (void)setrand(c); } } @@ -1145,9 +1281,10 @@ isprincipalall(GEN bnf,GEN x,long flag) GEN isprincipalfact(GEN bnf,GEN P, GEN e, GEN C, long flag) { - long av = avma, l = lg(e), i,prec,c; + long l = lg(e), i, prec, c; + gpmem_t av = avma; GEN id,id2, nf = checknf(bnf), z = NULL; /* gcc -Wall */ - int gen = flag & (nf_GEN | nf_GENMAT); + int gen = flag & (nf_GEN|nf_GENMAT); prec = prec_arch(bnf); if (gen) @@ -1163,28 +1300,30 @@ isprincipalfact(GEN bnf,GEN P, GEN e, GEN C, long flag id2 = idealpowred(bnf,z, (GEN)e[i],prec); id = id? idealmulred(nf,id,id2,prec): id2; } - if (id == C) + if (id == C) /* e = 0 */ { - if (!C) id = gun; - return isprincipalall(bnf, id, flag); + if (!C) return isprincipalall(bnf, gun, flag); + C = idealhermite(nf,C); id = z; + if (gen) id[1] = (long)C; else id = C; } c = getrand(); for (;;) { - long av1 = avma; - GEN y = isprincipalall0(bnf, gen? (GEN)id[1]: id,&prec,flag); + gpmem_t av1 = avma; + GEN y = _isprincipal(bnf, gen? (GEN)id[1]: id,&prec,flag); if (y) { - if (gen && typ(y) == t_VEC) + GEN u = (GEN)y[2]; + if (!gen || typ(y) != t_VEC) return gerepileupto(av,y); + if (flag & nf_GENMAT) + y[2] = (isnfscalar(u) && gcmp1((GEN)u[1]))? id[2] + :(long)arch_mul((GEN)id[2],u); + else { - GEN u = lift_intern(basistoalg(nf, (GEN)y[2])); - if (flag & nf_GENMAT) - y[2] = (gcmp1(u)&&lg(id[2])>1)? id[2]: (long)arch_mul((GEN)id[2], u); - else - y[2] = (long)algtobasis(nf, gmul((GEN)id[2], u)); - y = gcopy(y); + u = lift_intern(basistoalg(nf, u)); + y[2] = (long)algtobasis(nf, gmul((GEN)id[2], u)); } - return gerepileupto(av,y); + return gerepilecopy(av, y); } if (flag & nf_GIVEPREC) @@ -1193,15 +1332,15 @@ isprincipalfact(GEN bnf,GEN P, GEN e, GEN C, long flag err(warner,"insufficient precision for generators, not given"); avma = av; return stoi(prec); } - if (DEBUGLEVEL) err(warnprec,"isprincipalall0",prec); - avma = av1; bnf = bnfnewprec(bnf,prec); setrand(c); + if (DEBUGLEVEL) err(warnprec,"isprincipal",prec); + avma = av1; bnf = bnfnewprec(bnf,prec); (void)setrand(c); } } GEN isprincipal(GEN bnf,GEN x) { - return isprincipalall(bnf,x,nf_REGULAR); + return isprincipalall(bnf,x,0); } GEN @@ -1222,91 +1361,114 @@ isprincipalgenforce(GEN bnf,GEN x) return isprincipalall(bnf,x,nf_GEN | nf_FORCE); } +static GEN +rational_unit(GEN x, long n, long RU) +{ + GEN y; + if (!gcmp1(x) && !gcmp_1(x)) return cgetg(1,t_COL); + y = zerocol(RU); + y[RU] = (long)gmodulss((gsigne(x)>0)? 0: n>>1, n); + return y; +} + +/* if x a famat, assume it is an algebraic integer (very costly to check) */ GEN isunit(GEN bnf,GEN x) { - long av=avma,tetpil,tx = typ(x),i,R1,RU,n; - GEN p1,logunit,y,ex,nf,z,pi2_sur_w,gn,emb; + long tx = typ(x), i, R1, RU, n, prec; + gpmem_t av = avma; + GEN p1, v, rlog, logunit, ex, nf, z, pi2_sur_w, gn, emb; bnf = checkbnf(bnf); nf=(GEN)bnf[7]; - logunit=(GEN)bnf[3]; RU=lg(logunit); + logunit = (GEN)bnf[3]; RU = lg(logunit); p1 = gmael(bnf,8,4); /* roots of 1 */ gn = (GEN)p1[1]; n = itos(gn); - z = (GEN)p1[2]; + z = algtobasis(nf, (GEN)p1[2]); switch(tx) { case t_INT: case t_FRAC: case t_FRACN: - if (!gcmp1(x) && !gcmp_1(x)) return cgetg(1,t_COL); - y = zerocol(RU); i = (gsigne(x) > 0)? 0: n>>1; - y[RU] = (long)gmodulss(i, n); return y; + return rational_unit(x, n, RU); - case t_POLMOD: - if (!gegal((GEN)nf[1],(GEN)x[1])) - err(talker,"not the same number field in isunit"); - x = (GEN)x[2]; /* fall through */ - case t_POL: - p1 = x; x = algtobasis(bnf,x); break; + case t_MAT: /* famat */ + if (lg(x) != 3 || lg(x[1]) != lg(x[2])) + err(talker, "not a factorization matrix in isunit"); + break; case t_COL: - if (lgef(nf[1])-2 == lg(x)) { p1 = basistoalg(nf,x); break; } + if (degpol(nf[1]) != lg(x)-1) + err(talker,"not an algebraic number in isunit"); + break; - default: - err(talker,"not an algebraic number in isunit"); + default: x = algtobasis(nf, x); + break; } - if (!gcmp1(denom(x))) { avma = av; return cgetg(1,t_COL); } - if (typ(p1) != t_POLMOD) p1 = gmodulcp(p1,(GEN)nf[1]); - p1 = gnorm(p1); - if (!is_pm1(p1)) { avma = av; return cgetg(1,t_COL); } + /* assume a famat is integral */ + if (tx != t_MAT && !gcmp1(denom(x))) { avma = av; return cgetg(1,t_COL); } + if (isnfscalar(x)) return gerepileupto(av, rational_unit((GEN)x[1],n,RU)); - R1 = itos(gmael(nf,2,1)); p1 = cgetg(RU+1,t_COL); - for (i=1; i<=R1; i++) p1[i] = un; - for ( ; i<=RU; i++) p1[i] = deux; - logunit = concatsp(logunit,p1); + R1 = nf_get_r1(nf); v = cgetg(RU+1,t_COL); + for (i=1; i<=R1; i++) v[i] = un; + for ( ; i<=RU; i++) v[i] = deux; + logunit = concatsp(logunit, v); /* ex = fundamental units exponents */ + rlog = greal(logunit); + prec = nfgetprec(nf); + for (i=1;;) { - GEN rx, rlog = greal(logunit); - long e, prec = nfgetprec(nf); - for (i=1;;) + GEN logN, rx = get_arch_real(nf,x,&emb, MEDDEFAULTPREC); + long e; + if (rx) { - rx = get_arch_real(nf,x,&emb, MEDDEFAULTPREC); - if (rx) + logN = sum(rx, 1, RU); /* log(Nx), should be ~ 0 */ + if (gexpo(logN) > -20) { - ex = grndtoi(gauss(rlog, rx), &e); - if (gcmp0((GEN)ex[RU]) && e < -4) break; + long p = 2 + max(1, (nfgetprec(nf)-2) / 2); + if (typ(logN) != t_REAL || gprecision(rx) > p) + { avma = av; return cgetg(1,t_COL); } /* not a precision problem */ + rx = NULL; } - - if (++i > 4) err(precer,"isunit"); + } + if (rx) + { + ex = grndtoi(gauss(rlog, rx), &e); + if (gcmp0((GEN)ex[RU]) && e < -4) break; + } + if (i == 1) + prec = MEDDEFAULTPREC + (gexpo(x) >> TWOPOTBITS_IN_LONG); + else + { + if (i > 4) err(precer,"isunit"); prec = (prec-1)<<1; - if (DEBUGLEVEL) err(warnprec,"isunit",prec); - nf = nfnewprec(nf, prec); } + i++; + if (DEBUGLEVEL) err(warnprec,"isunit",prec); + nf = nfnewprec(nf, prec); } setlg(ex, RU); - setlg(p1, RU); settyp(p1, t_VEC); - for (i=1; i>1); + pi2_sur_w = divrs(mppi(prec), n>>1); /* 2pi / n */ p1 = ground(gdiv(p1, pi2_sur_w)); if (n > 2) { - GEN ro = gmael(nf,6,1); - GEN p2 = ground(gdiv(garg(poleval(z,ro), DEFAULTPREC), pi2_sur_w)); + GEN ro = gmul(row(gmael(nf,5,1), 1), z); + GEN p2 = ground(gdiv(garg(ro, prec), pi2_sur_w)); p1 = mulii(p1, mpinvmod(p2, gn)); } - tetpil = avma; y = cgetg(RU+1,t_COL); - for (i=1; iKC; noideal; noideal--) { - long nbrelideal=0, dependent = 0; - GEN IDEAL, ideal = (GEN)vectbase[noideal]; - GEN normideal = idealnorm(nf,ideal); + gpmem_t av0 = avma; + long nbrelideal=0, dependent = 0, try_factor = 0, oldcglob = cglob; + GEN IDEAL, ideal = (GEN)F->LP[noideal]; - if (alldep > 2*N) break; - if (DEBUGLEVEL>1) fprintferr("\n*** Ideal no %ld: %Z\n", noideal, ideal); ideal = prime_to_ideal(nf,ideal); - IDEAL = invcbase? gmul(invcbase, ideal): ideal; - IDEAL = gmul(IDEAL, lllint(IDEAL)); /* should be almost T2-reduced */ - r = red_ideal(&IDEAL,T2vec,prvec); + IDEAL = lllint_ip(ideal,4); /* should be almost T2-reduced */ + r = red_ideal(&IDEAL,Gvec,prvec); if (!r) return -1; /* precision problem */ for (k=1; k<=N; k++) { v[k]=gtodouble(gcoeff(r,k,k)); for (j=1; j3) fprintferr("v[%ld]=%.0f ",k,v[k]); + if (DEBUGLEVEL>3) fprintferr("v[%ld]=%.4g ",k,v[k]); } - BOUND = MINKOVSKI_BOUND * pow(gtodouble(normideal),2./(double)N); + BOUND = v[2] + v[1] * q[1][2] * q[1][2]; + if (BOUND < v[1]) BOUND = v[1]; + BOUND *= 2; /* at most twice larger than smallest known vector */ if (DEBUGLEVEL>1) { if (DEBUGLEVEL>3) fprintferr("\n"); - fprintferr("BOUND = %.0f\n",BOUND); flusherr(); + fprintferr("BOUND = %.4g\n",BOUND); flusherr(); } - BOUND += eps; av2=avma; limpile = stack_lim(av2,1); + BOUND *= 1 + eps; av2=avma; limpile = stack_lim(av2,1); k = N; y[N]=z[N]=0; x[N]= (long) sqrt(BOUND/v[N]); for(;; x[1]--) { - ulong av3 = avma; + gpmem_t av3 = avma; double p; GEN col; @@ -1489,16 +1632,17 @@ small_norm_for_buchall(long cglob,GEN *mat,GEN matarch } if (k==1) /* element complete */ { - if (!x[1] && y[1]<=eps) goto ENDIDEAL; + if (y[1]<=eps) goto ENDIDEAL; /* skip all scalars: [*,0...0] */ if (ccontent(x)==1) /* primitive */ { GEN Nx, gx = gmul_mati_smallvec(IDEAL,x); - long av4; + gpmem_t av4; if (!isnfscalar(gx)) { xembed = gmul(M,gx); av4 = avma; nbsmallnorm++; + if (++try_factor > maxtry_FACT) goto ENDIDEAL; Nx = ground(norm_by_embed(R1,xembed)); setsigne(Nx, 1); - if (factorelt(nf,cbase,gx,Nx,KCZ,LIMC)) { avma = av4; break; } + if (can_factor(F, nf, NULL, gx, Nx)) { avma = av4; break; } if (DEBUGLEVEL > 1) { fprintferr("."); flusherr(); } } avma = av3; @@ -1507,24 +1651,20 @@ small_norm_for_buchall(long cglob,GEN *mat,GEN matarch } } cglob++; col = mat[cglob]; - set_fact(col); - if (cglob > 1 && cglob <= KC && ! addcolumntomatrix(col,invp,L)) + set_fact(col, first_nz, cglob); + /* make sure we get maximal rank first, then allow all relations */ + if (cglob > 1 && cglob <= F->KC && ! addcolumntomatrix(col,invp,L)) { /* Q-dependent from previous ones: forget it */ cglob--; unset_fact(col); if (DEBUGLEVEL>1) { fprintferr("*"); flusherr(); } - if (++dependent > MAXTRY) { alldep++; break; } + if (++dependent > maxtry_DEP) break; avma = av3; continue; } /* record archimedean part */ set_log_embed((GEN)matarch[cglob], xembed, R1, PRECREG); - alldep = dependent = 0; + dependent = 0; - if (DEBUGLEVEL) - { - if (DEBUGLEVEL==1) fprintferr("%4ld",cglob); - else { fprintferr("cglob = %ld. ",cglob); wr_rel(mat[cglob]); } - flusherr(); nbfact++; - } + if (DEBUGLEVEL) { nbfact++; dbg_rel(cglob, mat[cglob]); } if (cglob >= nbrel) goto END; /* we have enough */ if (++nbrelideal == nbrelpid) break; @@ -1535,56 +1675,34 @@ small_norm_for_buchall(long cglob,GEN *mat,GEN matarch } } ENDIDEAL: - invp = gerepilecopy(av1, invp); + if (cglob == oldcglob) avma = av0; else invp = gerepilecopy(av1, invp); if (DEBUGLEVEL>1) msgtimer("for this ideal"); } END: if (DEBUGLEVEL) { - fprintferr("\n"); - msgtimer("small norm relations"); - if (DEBUGLEVEL>1) - { - GEN p1,tmp=cgetg(cglob+1,t_MAT); - - fprintferr("Elements of small norm gave %ld relations.\n",cglob); - fprintferr("Computing rank: "); flusherr(); - for(j=1;j<=cglob;j++) - { - p1=cgetg(KC+1,t_COL); tmp[j]=(long)p1; - for(i=1;i<=KC;i++) p1[i]=lstoi(mat[j][i]); - } - tmp = (GEN)sindexrank(tmp)[2]; k=lg(tmp)-1; - fprintferr("%ld; independent columns: %Z\n",k,tmp); - } - if(nbsmallnorm) - fprintferr("\nnb. fact./nb. small norm = %ld/%ld = %.3f\n", + fprintferr("\n"); msgtimer("small norm relations"); + fprintferr(" small norms gave %ld relations, rank = %ld.\n", + cglob, rank(small_to_mat_i((GEN)mat, F->KC))); + if (nbsmallnorm) + fprintferr(" nb. fact./nb. small norm = %ld/%ld = %.3f\n", nbfact,nbsmallnorm,((double)nbfact)/nbsmallnorm); - else - fprintferr("\nnb. small norm = 0\n"); } avma = av; return cglob; } -#undef MAXTRY -/* I assumed to be integral HNF, T2 a weighted T2 matrix */ +/* I assumed to be integral HNF, G the Cholesky form of a weighted T2 matrix. + * Return an irrational m in I with T2(m) small */ static GEN -ideallllredpart1(GEN I, GEN T2, long prec) +pseudomin(GEN I, GEN G) { - GEN y,m,idealpro; - - y = lllgramintern(qf_base_change(T2,I,1),100,1,prec+1); + GEN m, y = lllintern(gmul(G, I), 100,1, 0); if (!y) return NULL; - /* I, m, y integral */ m = gmul(I,(GEN)y[1]); if (isnfscalar(m)) m = gmul(I,(GEN)y[2]); - - idealpro = cgetg(3,t_VEC); - idealpro[1] = (long)I; - idealpro[2] = (long)m; /* irrational element of small T2 norm in I */ - if (DEBUGLEVEL>5) fprintferr("\nidealpro = %Z\n",idealpro); - return idealpro; + if (DEBUGLEVEL>5) fprintferr("\nm = %Z\n",m); + return m; } static void @@ -1605,70 +1723,52 @@ dbg_newrel(long jideal, long jdir, long phase, long cg static void dbg_cancelrel(long jideal,long jdir,long phase, long *col) { - fprintferr("rel. cancelled. phase %ld: %ld ",phase); + fprintferr("rel. cancelled. phase %ld: ",phase); if (DEBUGLEVEL>3) fprintferr("(jideal=%ld,jdir=%ld)",jideal,jdir); wr_rel(col); flusherr(); } static void -dbg_outrel(long phase,long cglob, GEN vperm,GEN *mat,GEN maarch) +dbg_outrel(long cglob, GEN *mat,GEN maarch) { - long i,j; - GEN p1,p2; + gpmem_t av = avma; + GEN p1; + long j; - if (phase == 0) + p1 = cgetg(cglob+1, t_MAT); + for (j=1; j<=cglob; j++) p1[j] = (long)small_to_col(mat[j]); + fprintferr("\nRank = %ld\n", rank(p1)); + if (DEBUGLEVEL>3) { - ulong av = avma; p2=cgetg(cglob+1,t_MAT); - for (j=1; j<=cglob; j++) - { - p1=cgetg(KC+1,t_COL); p2[j]=(long)p1; - for (i=1; i<=KC; i++) p1[i]=lstoi(mat[j][i]); - } - fprintferr("\nRank = %ld\n", rank(p2)); - if (DEBUGLEVEL>3) - { - fprintferr("relations = \n"); - for (j=1; j <= cglob; j++) wr_rel(mat[j]); - fprintferr("\nmatarch = %Z\n",maarch); - } - avma = av; + fprintferr("relations = \n"); + for (j=1; j <= cglob; j++) wr_rel(mat[j]); + fprintferr("\nmatarch = %Z\n",maarch); } - else if (DEBUGLEVEL>6) - { - fprintferr("before hnfadd:\nvectbase[vperm[]] = \n"); - fprintferr("["); - for (i=1; i<=KC; i++) - { - bruterr((GEN)vectbase[vperm[i]],'g',-1); - if (i KC) return s; /* zero relation */ + bs = 1; while (bs < l && !cols[bs]) bs++; + if (bs == l) return s; /* zero relation */ - for (l=s-1; l; l--) + for (i=s-1; i; i--) { - coll = mat[l]; - if (bs == coll[0]) /* = index of first non zero elt in coll */ + if (bs == first_nz[i]) /* = index of first non zero elt in cols */ { + GEN coll = mat[i]; long b = bs; - do b++; while (b<=KC && cols[b] == coll[b]); - if (b > KC) return l; + do b++; while (b < l && cols[b] == coll[b]); + if (b == l) return i; } } - cols[0] = bs; return 0; + first_nz[s] = bs; return 0; } /* I integral ideal in HNF form */ @@ -1676,71 +1776,79 @@ static GEN remove_content(GEN I) { long N = lg(I)-1; - if (!gcmp1(gcoeff(I,N,N))) { GEN y=content(I); if (!gcmp1(y)) I=gdiv(I,y); } + if (!gcmp1(gcoeff(I,N,N))) I = Q_primpart(I); return I; } /* if phase != 1 re-initialize static variables. If <0 return immediately */ static long -random_relation(long phase,long cglob,long LIMC,long PRECLLL,long PRECREG, - GEN nf,GEN subFB,GEN vecT2,GEN *mat,GEN matarch,GEN list_jideal) +random_relation(long phase,long cglob,long LIMC,long PRECREG,long MAXRELSUP, + GEN nf,GEN vecG,GEN *mat,GEN first_nz,GEN matarch, + GEN list_jideal, FB_t *F) { static long jideal, jdir; - long lim,i,av,av1,cptzer,nbT2,lgsub,r1, jlist = 1; - GEN arch,col,colarch,ideal,idealpro,P,ex; + long i, maxcglob, cptlist, cptzer, nbG, lgsub, r1, jlist = 1; + gpmem_t av, av1; + GEN arch,col,colarch,ideal,m,P,ex; if (phase != 1) { jideal=jdir=1; if (phase<0) return 0; } r1 = nf_get_r1(nf); - lim = lg(mat)-1; /* requested number of relations */ - nbT2 = lg(vecT2)-1; - lgsub = lg(subFB); ex = cgetg(lgsub, t_VECSMALL); - cptzer = 0; + maxcglob = lg(mat)-1; /* requested # of relations */ + nbG = lg(vecG)-1; + lgsub = lg(F->subFB); ex = cgetg(lgsub, t_VECSMALL); + cptzer = cptlist = 0; if (DEBUGLEVEL && list_jideal) fprintferr("looking hard for %Z\n",list_jideal); P = NULL; /* gcc -Wall */ for (av = avma;;) { - if (list_jideal && jlist < lg(list_jideal) && jdir <= nbT2) - jideal = list_jideal[jlist++]; - if (!list_jideal || jdir <= nbT2) + if (list_jideal && jlist < lg(list_jideal) && jdir <= nbG) { + jideal = list_jideal[jlist++]; cptlist = 0; + } + if (!list_jideal || jdir <= nbG) + { avma = av; - P = prime_to_ideal(nf, (GEN)vectbase[jideal]); + P = prime_to_ideal(nf, (GEN)F->LP[jideal]); } + else + { + if (++cptlist > 300) return -1; + } ideal = P; do { for (i=1; i>randshift; - if (ex[i]) ideal = idealmulh(nf,ideal, gmael3(powsubFB,i,ex[i],1)); + if (ex[i]) ideal = idealmulh(nf,ideal, gmael3(F->powsubFB,i,ex[i],1)); } } while (ideal == P); /* If ex = 0, try another */ ideal = remove_content(ideal); if (phase != 1) jdir = 1; else phase = 2; - for (av1 = avma; jdir <= nbT2; jdir++, avma = av1) + for (av1 = avma; jdir <= nbG; jdir++, avma = av1) { /* reduce along various directions */ if (DEBUGLEVEL>2) fprintferr("phase=%ld,jideal=%ld,jdir=%ld,rand=%ld\n", phase,jideal,jdir,getrand()); - idealpro = ideallllredpart1(ideal,(GEN)vecT2[jdir],PRECLLL); - if (!idealpro) return -2; - if (!factorgen(nf,idealpro,KCZ,LIMC)) + m = pseudomin(ideal,(GEN)vecG[jdir]); + if (!m) return -2; + if (!factorgen(F,nf,ideal,m)) { if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); } continue; } /* can factor ideal, record relation */ cglob++; col = mat[cglob]; - set_fact(col); col[jideal]--; - for (i=1; isubFB[i] ] -= ex[i]; + if (already_found_relation(mat, cglob, first_nz)) { /* Already known: forget it */ if (DEBUGLEVEL>1) dbg_cancelrel(jideal,jdir,phase,col); cglob--; unset_fact(col); col[jideal] = 0; - for (i=1; isubFB[i] ] = 0; if (++cptzer > MAXRELSUP) { @@ -1755,23 +1863,23 @@ random_relation(long phase,long cglob,long LIMC,long P for (i=1; ipowsubFB,i,ex[i],2); arch = arch? vecmul(arch, p1): p1; } colarch = (GEN)matarch[cglob]; /* arch = archimedean component (MULTIPLICATIVE form) of ideal */ - arch = vecdiv(arch, gmul(gmael(nf,5,1), (GEN)idealpro[2])); + arch = vecdiv(arch, gmul(gmael(nf,5,1), m)); set_log_embed(colarch, arch, r1, PRECREG); - if (DEBUGLEVEL) dbg_newrel(jideal,jdir,phase,cglob,col,colarch,lim); + if (DEBUGLEVEL) dbg_newrel(jideal,jdir,phase,cglob,col,colarch,maxcglob); /* Need more, try next P */ - if (cglob < lim) break; + if (cglob < maxcglob) break; /* We have found enough. Return */ if (phase) { jdir = 1; - if (jideal == KC) jideal=1; else jideal++; + if (jideal == F->KC) jideal=1; else jideal++; } if (DEBUGLEVEL>2) fprintferr("Upon exit: jideal=%ld,jdir=%ld\n",jideal,jdir); @@ -1779,61 +1887,69 @@ random_relation(long phase,long cglob,long LIMC,long P } if (!list_jideal) { - if (jideal == KC) jideal=1; else jideal++; + if (jideal == F->KC) jideal=1; else jideal++; } } } -static long -be_honest(GEN nf,GEN subFB,long PRECLLL) +/* remark: F->KCZ changes if be_honest() fails */ +static int +be_honest(FB_t *F, GEN nf, long PRECLLL) { - ulong av; - GEN MC = gmael(nf,5,2), M = gmael(nf,5,1), D = (GEN)nf[3]; - long ex,i,j,J,k,iz,nbtest, lgsub = lg(subFB), ru = lg(MC); - GEN P,ideal,idealpro, exu = cgetg(ru, t_VECSMALL), MCtw= cgetg(ru, t_MAT); + long ex, i, j, J, k, iz, nbtest, ru, lgsub = lg(F->subFB), KCZ0 = F->KCZ; + GEN G, M, P, ideal, m, vdir; + gpmem_t av; + if (F->KCZ2 <= F->KCZ) return 1; if (DEBUGLEVEL) { - fprintferr("Be honest for primes from %ld to %ld\n", FB[KCZ+1],FB[KCZ2]); + fprintferr("Be honest for primes from %ld to %ld\n", + F->FB[ F->KCZ+1 ], F->FB[ F->KCZ2 ]); flusherr(); } + if (!F->powsubFB) powsubFBgen(F, nf, CBUCHG+1, 0); + M = gprec_w(gmael(nf,5,1), PRECLLL); + G = gprec_w(gmael(nf,5,2), PRECLLL); + ru = lg(nf[6]); + vdir = cgetg(ru, t_VECSMALL); av = avma; - for (iz=KCZ+1; iz<=KCZ2; iz++, avma = av) + for (iz=F->KCZ+1; iz<=F->KCZ2; iz++, avma = av) { - if (DEBUGLEVEL>1) fprintferr("%ld ", FB[iz]); - P = idealbase[numFB[FB[iz]]]; J = lg(P); - /* if unramified, check all but 1 */ - if (J > 1 && !divise(D, gmael(P,1,1))) J--; + long p = F->FB[iz]; + if (DEBUGLEVEL>1) fprintferr("%ld ", p); + P = F->LV[p]; J = lg(P); + /* all P|p in FB + last is unramified --> check all but last */ + if (isclone(P) && itou(gmael(P,J-1,3)) == 1UL /* e = 1 */) J--; + for (j=1; j>randshift; - if (ex) ideal = idealmulh(nf,ideal,gmael3(powsubFB,i,ex,1)); + if (ex) ideal = idealmulh(nf,ideal,gmael3(F->powsubFB,i,ex,1)); } ideal = remove_content(ideal); + for (i=1; i>randshift; for (k=1; k>randshift; - else - { - for (i=1; i 50) + { + err(warner,"be_honest() failure on prime %Z\n", P[j]); + return 0; + } } + F->KCZ++; /* SUCCESS, "enlarge" factorbase */ } } if (DEBUGLEVEL) @@ -1841,6 +1957,7 @@ be_honest(GEN nf,GEN subFB,long PRECLLL) if (DEBUGLEVEL>1) fprintferr("\n"); msgtimer("be honest"); } + F->KCZ = KCZ0; avma = av; return 1; } @@ -1851,20 +1968,20 @@ trunc_error(GEN x) && (expo(x)>>TWOPOTBITS_IN_LONG) + 3 > lg(x); } -/* xarch = complex logarithmic embeddings of units (u_j) found so far */ +/* A = complex logarithmic embeddings of units (u_j) found so far */ static GEN -compute_multiple_of_R(GEN xarch,long RU,long N,GEN *ptsublambda) +compute_multiple_of_R(GEN A,long RU,long N,GEN *ptlambda) { - GEN v,mdet,mdet_t,Im_mdet,kR,sublambda,lambda,xreal; - GEN *gptr[2]; - long av = avma, i,j, sreg = lg(xarch)-1, R1 = 2*RU - N; + GEN T,v,mdet,mdet_t,Im_mdet,kR,xreal,lambda; + long i, zc = lg(A)-1, R1 = 2*RU - N; + gpmem_t av = avma; - if (DEBUGLEVEL) { fprintferr("\n#### Computing regulator\n"); flusherr(); } - xreal=greal(xarch); v=cgetg(RU+1,t_COL); /* xreal = (log |sigma_i(u_j)|) */ - for (i=1; i<=R1; i++) v[i]=un; - for ( ; i<=RU; i++) v[i]=deux; - mdet=cgetg(sreg+2,t_MAT); mdet[1]=(long)v; - for (j=2; j<=sreg+1; j++) mdet[j]=xreal[j-1]; /* det(Span(mdet)) = N * R */ + if (DEBUGLEVEL) fprintferr("\n#### Computing regulator multiple\n"); + xreal = greal(A); /* = (log |sigma_i(u_j)|) */ + T = cgetg(RU+1,t_COL); + for (i=1; i<=R1; i++) T[i] = un; + for ( ; i<=RU; i++) T[i] = deux; + mdet = concatsp(xreal,T); /* det(Span(mdet)) = N * R */ i = gprecision(mdet); /* truncate to avoid "near dependant" vectors */ mdet_t = (i <= 4)? mdet: gprec_w(mdet,i-1); @@ -1874,55 +1991,74 @@ compute_multiple_of_R(GEN xarch,long RU,long N,GEN *pt Im_mdet = vecextract_p(mdet,v); /* integral multiple of R: the cols we picked form a Q-basis, they have an - * index in the full lattice */ + * index in the full lattice. Last column is T */ kR = gdivgs(det2(Im_mdet), N); /* R > 0.2 uniformly */ if (gexpo(kR) < -3) { avma=av; return NULL; } kR = mpabs(kR); - sublambda = cgetg(sreg+1,t_MAT); - lambda = gauss(Im_mdet,xreal); /* rational entries */ - for (i=1; i<=sreg; i++) - { - GEN p1 = cgetg(RU,t_COL), p2 = (GEN)lambda[i]; - sublambda[i] = (long)p1; - for (j=1; j 0) + D = gmul2n(gmul(*ptkR,z), 1); /* bound for denom(lambda) */ + lambda = bestappr_noer(lambda,D); + if (!lambda) { - if (DEBUGLEVEL) fprintferr("c = %Z\nden = %Z\n",c,den); - avma=av; return NULL; + if (DEBUGLEVEL) fprintferr("truncation error in bestappr\n"); + return PRECI; } + den = denom(lambda); + if (gcmp(den,D) > 0) + { + if (DEBUGLEVEL) fprintferr("D = %Z\nden = %Z\n",D,den); + return PRECI; + } + L = Q_muli_to_int(lambda, den); + H = hnfall_i(L, NULL, 1); r = lg(H)-1; - p1 = gmul(sublambda,den); tetpil=avma; - *parch = lllint(p1); - - av2=avma; p1 = det2(gmul(sublambda,*parch)); - affrr(mpabs(gmul(R,p1)), R); avma=av2; - - if (DEBUGLEVEL) msgtimer("bestappr/regulator"); - *parch = gerepile(av,tetpil,*parch); return gmul(R,z); + /* tentative regulator */ + R = mpabs( gmul(*ptkR, gdiv(dethnf_i(H), gpowgs(den, r))) ); + c = gtodouble(gmul(R,z)); /* should be n (= 1 if we are done) */ + if (DEBUGLEVEL) + { + msgtimer("bestappr/regulator"); + fprintferr("\n ***** check = %f\n",c); + } + if (c < 0.75 || c > 1.5) { avma = av; return RELAT; } + *ptkR = R; *ptL = L; return LARGE; } /* find the smallest (wrt norm) among I, I^-1 and red(I^-1) */ @@ -1930,18 +2066,15 @@ static GEN inverse_if_smaller(GEN nf, GEN I, long prec) { GEN J, d, dmin, I1; - int inv; + J = (GEN)I[1]; dmin = dethnf_i(J); I1 = idealinv(nf,I); J = (GEN)I1[1]; J = gmul(J,denom(J)); I1[1] = (long)J; - d = dethnf_i(J); - if (cmpii(d,dmin) < 0) {inv=1; I=I1; dmin=d;} - else inv=0; + d = dethnf_i(J); if (cmpii(d,dmin) < 0) {I=I1; dmin=d;} /* try reducing (often _increases_ the norm) */ I1 = ideallllred(nf,I1,NULL,prec); J = (GEN)I1[1]; - d = dethnf_i(J); - if (cmpii(d,dmin) < 0) {inv=1; I=I1;} + d = dethnf_i(J); if (cmpii(d,dmin) < 0) I=I1; return I; } @@ -1962,17 +2095,16 @@ setlg_col(GEN U, long l) /* compute class group (clg1) + data for isprincipal (clg2) */ static void -class_group_gen(GEN nf,GEN W,GEN C,GEN vperm,GEN *ptclg1,GEN *ptclg2,long prec) +class_group_gen(GEN nf,GEN W,GEN C,GEN Vbase,long prec, GEN nf0, + GEN *ptclg1,GEN *ptclg2) { - GEN z,G,Ga,ga,GD,cyc,X,Y,D,U,V,Ur,Ui,Uir,I,J,Vbase; - long i,j,s,lo,lo0; + GEN z,G,Ga,ga,GD,cyc,X,Y,D,U,V,Ur,Ui,Uir,I,J; + long i,j,lo,lo0; if (DEBUGLEVEL) - { fprintferr("\n#### Computing class group generators\n"); timer2(); } - z = smith2(W); /* U W V = D, D diagonal, G = g Ui (G=new gens, g=old) */ - U = (GEN)z[1]; Ui = ginv(U); - V = (GEN)z[2]; - D = (GEN)z[3]; + { fprintferr("\n#### Computing class group generators\n"); (void)timer2(); } + D = smithall(W,&U,&V); /* UWV = D, D diagonal, G = g Ui (G=new gens, g=old) */ + Ui = ginv(U); lo0 = lo = lg(D); /* we could set lo = lg(cyc) and truncate all matrices below * setlg_col(D && U && Y, lo) + setlg(D && V && X && Ui, lo) @@ -1987,39 +2119,32 @@ class_group_gen(GEN nf,GEN W,GEN C,GEN vperm,GEN *ptcl * P invertible diagonal matrix (\pm 1) which is only implicitly defined * G = g Uir P + [Ga], Uir = Ui + WX * g = G P Ur + [ga], Ur = U + DY */ - Vbase = cgetg(lo0,t_VEC); - if (typ(vperm) == t_VECSMALL) - for (i=1; i prec) + { + M = gprec_w(M,prec); + G = gprec_w(G,prec); + } + Gtw = gmul2n(G, 10); + for (ind=j=1; j<=n; j++) + for (i=1; i<=j; i++) vecG[ind++] = (long)shift_G(G,Gtw,i,j,r1,r2); + if (DEBUGLEVEL) msgtimer("weighted G matrices"); + return vecG; } /* cf. relationrank() @@ -2129,12 +2268,13 @@ addcolumntomatrix(GEN V, GEN invp, GEN L) * Starting from the identity (canonical basis of Q^n), we obtain a base * change matrix P by taking the independant columns of A and vectors from * the canonical basis. Update invp = 1/P, and L in {0,1}^n, with L[i] = 0 - * of P[i] = e_i, and 1 if P[i] = A_i (i-th column of A) + * if P[i] = e_i, and 1 if P[i] = A_i (i-th column of A) */ static GEN relationrank(GEN *A, long r, GEN L) { - long i, n = lg(L)-1, av = avma, lim = stack_lim(av,1); + long i, n = lg(L)-1; + gpmem_t av = avma, lim = stack_lim(av, 1); GEN invp = idmat(n); if (!r) return invp; @@ -2152,32 +2292,51 @@ relationrank(GEN *A, long r, GEN L) return gerepilecopy(av, invp); } +/* SMALLBUCHINIT */ + static GEN -codeprime(GEN bnf, GEN pr) +decode_pr_lists(GEN nf, GEN pfc) { - long j,av=avma,tetpil; - GEN p,al,fa,p1; + long i, p, pmax, n = degpol(nf[1]), l = lg(pfc); + GEN t, L; - p=(GEN)pr[1]; al=(GEN)pr[2]; fa=primedec(bnf,p); - for (j=1; j pmax) pmax = p; + } + L = cgetg(pmax+1, t_VEC); + for (p=1; p<=pmax; p++) L[p] = 0; + for (i=1; i1) fprintferr("%ld ",j); @@ -2284,7 +2434,7 @@ makematal(GEN bnf) prec = itos(y); j--; if (DEBUGLEVEL) err(warnprec,"makematal",prec); nf = nfnewprec(nf,prec); - bnf = bnfinit0(nf,1,NULL,prec); setrand(c); + bnf = bnfinit0(nf,1,NULL,prec); (void)setrand(c); } if (DEBUGLEVEL>1) fprintferr("\n"); return ma; @@ -2316,7 +2466,7 @@ check_and_build_cycgen(GEN bnf) GEN cycgen = get_cycgen((GEN)bnf[10]); if (!cycgen) { - long av = avma; + gpmem_t av = avma; if (DEBUGLEVEL) err(warner,"completing bnf (building cycgen)"); bnfinsert(bnf, makecycgen(bnf), 2); avma = av; cycgen = get_cycgen((GEN)bnf[10]); @@ -2330,168 +2480,120 @@ check_and_build_matal(GEN bnf) GEN matal = get_matal((GEN)bnf[10]); if (!matal) { - long av = avma; + gpmem_t av = avma; if (DEBUGLEVEL) err(warner,"completing bnf (building matal)"); bnfinsert(bnf, makematal(bnf), 1); avma = av; matal = get_matal((GEN)bnf[10]); } return matal; } - + GEN smallbuchinit(GEN pol,GEN gcbach,GEN gcbach2,GEN gRELSUP,GEN gborne,long nbrelpid,long minsFB,long prec) { - long av=avma,av1,k; - GEN y,bnf,pFB,vp,nf,mas,res,uni,v1,v2,v3; + GEN y, bnf, nf, res, p1; + gpmem_t av = avma; if (typ(pol)==t_VEC) bnf = checkbnf(pol); else { - bnf=buchall(pol,gcbach,gcbach2,gRELSUP,gborne,nbrelpid,minsFB,-3,prec); + const long fl = nf_INIT | nf_UNITS | nf_FORCE; + bnf = buchall(pol,gcbach,gcbach2,gRELSUP,gborne,nbrelpid,minsFB,fl,prec); bnf = checkbnf_discard(bnf); } - pFB=(GEN)bnf[5]; vp=(GEN)bnf[6]; nf=(GEN)bnf[7]; - mas=(GEN)nf[5]; res=(GEN)bnf[8]; uni=(GEN)res[5]; + nf = (GEN)bnf[7]; + res = (GEN)bnf[8]; - y=cgetg(13,t_VEC); y[1]=lcopy((GEN)nf[1]); y[2]=lcopy(gmael(nf,2,1)); - y[3]=lcopy((GEN)nf[3]); y[4]=lcopy((GEN)nf[7]); - y[5]=lcopy((GEN)nf[6]); y[6]=lcopy((GEN)mas[5]); - y[7]=lcopy((GEN)bnf[1]); y[8]=lcopy((GEN)bnf[2]); - v1=cgetg(lg(pFB),t_VEC); y[9]=(long)v1; - for (k=1; k prec0) x = gprec_w(x,prec0); - return glog(x, prec0); -} + long k,N, la = lg(x); + GEN M = cgetg(la,t_MAT); -/* return corrected archimedian components - * (= log(sigma_i(x)) - log(|Nx|)/[K:Q]) for a (matrix of elements) */ -static GEN -get_arch2_i(GEN nf, GEN a, long prec, int units) -{ - GEN M,N, ro = dummycopy((GEN)nf[6]); - long j,k, la = lg(a), ru = lg(ro), r1 = nf_get_r1(nf); - - M = cgetg(la,t_MAT); if (la == 1) return M; - if (typ(a[1]) == t_COL) a = gmul((GEN)nf[7], a); - if (units) N = NULL; /* no correction necessary */ - else - { - GEN pol = (GEN)nf[1]; - N = cgetg(la,t_VEC); - for (k=1; k> 1; - pl1 = (ru == 1 && r1 == 0)? 0: gexpo(funits); - pl2 = gexpo(ro); + nf_get_sign(nf, &r1, &r2); + funits = algtobasis(nf, check_units(bnf,"bnfnewprec")); + prec1 = prec; - prec += ((ru + r2 - 1) * (pl1 + (ru + r2) * pl2)) >> TWOPOTBITS_IN_LONG; - nf = nfnewprec((GEN)bnf[7],prec); - res = cgetg(7,t_VEC); - ro = (GEN)nf[6]; - mun = get_arch2(nf,funits,prec,1); + if (r2 > 1 || r1 != 0) + prec += 1 + (gexpo(funits) >> TWOPOTBITS_IN_LONG); + nf = nfnewprec(nf0,prec); + mun = get_archclean(nf,funits,prec,1); if (prec != prec1) { mun = gprec_w(mun,prec1); prec = prec1; } - res[2]=(long)get_regulator(mun,prec); - p1 = (GEN)bnf[8]; - res[3]=lcopy((GEN)p1[3]); - res[4]=lcopy((GEN)p1[4]); - res[5]=lcopy((GEN)p1[5]); - res[6]=lcopy((GEN)p1[6]); - - y[1]=lcopy((GEN)bnf[1]); - y[2]=lcopy((GEN)bnf[2]); - y[3]=(long)mun; matal = check_and_build_matal(bnf); - y[4]=(long)get_arch2(nf,matal,prec,0); - y[5]=lcopy((GEN)bnf[5]); - y[6]=lcopy((GEN)bnf[6]); - y[7]=(long)nf; - y[8]=(long)res; - my_class_group_gen(y,&clgp,&clgp2,prec); - res[1]=(long)clgp; - y[9]=(long)clgp2; - y[10]=lcopy((GEN)bnf[10]); return y; + + y = dummycopy(bnf); + y[3] = (long)mun; + y[4] = (long)get_archclean(nf,matal,prec,0); + y[7] = (long)nf; + my_class_group_gen(y,prec,nf0, &clgp,&clgp2); + res = dummycopy((GEN)bnf[8]); + res[1] = (long)clgp; + res[2] = (long)get_regulator(mun); + y[8] = (long)res; + y[9] = (long)clgp2; return gerepilecopy(av, y); } GEN @@ -2505,72 +2607,82 @@ bnrnewprec(GEN bnr, long prec) return y; } +static void +nfbasic_from_sbnf(GEN sbnf, nfbasic_t *T) +{ + T->x = (GEN)sbnf[1]; + T->dK = (GEN)sbnf[3]; + T->bas = (GEN)sbnf[4]; + T->index= get_nfindex(T->bas); + T->r1 = itos((GEN)sbnf[2]); + T->dx = NULL; + T->lead = NULL; + T->basden = NULL; +} + +static GEN +get_clfu(GEN clgp, GEN reg, GEN c1, GEN zu, GEN fu, long k) +{ + GEN z = cgetg(7, t_VEC); + z[1]=(long)clgp; z[2]=(long)reg; z[3]=(long)c1; + z[4]=(long)zu; z[5]=(long)fu; z[6]=lstoi(k); return z; +} + GEN bnfmake(GEN sbnf, long prec) { - long av = avma, j,k,n,r1,r2,ru,lpf; - GEN p1,x,bas,ro,nf,mun,funits,index; - GEN pfc,vp,mc,clgp,clgp2,res,y,W,racu,reg,matal; + long j, k, l, n; + gpmem_t av = avma; + GEN p1, bas, ro, nf, mun, fu, L; + GEN pfc, mc, clgp, clgp2, res, y, W, zu, reg, matal, Vbase; + nfbasic_t T; - if (typ(sbnf)!=t_VEC || lg(sbnf)!=13) - err(talker,"incorrect sbnf in bnfmake"); - x=(GEN)sbnf[1]; bas=(GEN)sbnf[4]; n=lg(bas)-1; - r1=itos((GEN)sbnf[2]); r2=(n-r1)>>1; ru=r1+r2; - ro=(GEN)sbnf[5]; - if (prec > gprecision(ro)) ro=get_roots(x,r1,ru,prec); - index = gun; - for (j=2; j<=n; j++) index = mulii(index, denom(leading_term(bas[j]))); + if (typ(sbnf) != t_VEC || lg(sbnf) != 13) err(typeer,"bnfmake"); + if (prec < DEFAULTPREC) prec = DEFAULTPREC; - nf=cgetg(10,t_VEC); - nf[1]=sbnf[1]; p1=cgetg(3,t_VEC); p1[1]=lstoi(r1); p1[2]=lstoi(r2); - nf[2]=(long)p1; - nf[3]=sbnf[3]; - nf[4]=(long)index; - nf[6]=(long)ro; - nf[7]=(long)bas; - get_nf_matrices(nf, 0); + nfbasic_from_sbnf(sbnf, &T); + ro = (GEN)sbnf[5]; + if (prec > gprecision(ro)) ro = get_roots(T.x,T.r1,prec); + nf = nfbasic_to_nf(&T, ro, prec); + bas = (GEN)nf[7]; - funits=cgetg(ru,t_VEC); p1 = (GEN)sbnf[11]; - for (k=1; k < lg(p1); k++) - funits[k] = lmul(bas,(GEN)p1[k]); - mun = get_arch2_i(nf,funits,prec,1); + p1 = (GEN)sbnf[11]; l = lg(p1); fu = cgetg(l, t_VEC); + for (k=1; k < l; k++) fu[k] = lmul(bas, (GEN)p1[k]); + mun = get_archclean(nf,fu,prec,1); - prec=gprecision(ro); if (prec1? 11: fl? 9: 8; - GEN p1,z, RES = cgetg(11,t_COL); + long l = (fl & nf_UNITS)? 7 + : (fl & nf_ROOT1)? 5: 4; + GEN p1, z; - setlg(RES,l); - RES[5]=(long)clg1; - RES[6]=(long)reg; - RES[7]=(long)c_1; - RES[8]=(long)zu; - RES[9]=(long)fu; - RES[10]=lstoi(k); - if (fl>=0) + setlg(res, l); + if (! (fl & nf_INIT)) { - RES[1]=nf[1]; - RES[2]=nf[2]; p1=cgetg(3,t_VEC); p1[1]=nf[3]; p1[2]=nf[4]; - RES[3]=(long)p1; - RES[4]=nf[7]; - z=cgetg(2,t_MAT); z[1]=lcopy(RES); return z; + GEN x = cgetg(5, t_VEC); + x[1]=nf[1]; + x[2]=nf[2]; p1=cgetg(3,t_VEC); p1[1]=nf[3]; p1[2]=nf[4]; + x[3]=(long)p1; + x[4]=nf[7]; + z=cgetg(2,t_MAT); z[1]=(long)concatsp(x, res); return z; } z=cgetg(11,t_VEC); z[1]=(long)W; z[2]=(long)B; - z[3]=(long)xarch; + z[3]=(long)A; z[4]=(long)matarch; - z[5]=(long)vectbase; - for (i=lg(vperm)-1; i>0; i--) vperm[i]=lstoi(vperm[i]); - settyp(vperm, t_VEC); - z[6]=(long)vperm; - z[7]=(long)nf; RES+=4; RES[0]=evaltyp(t_VEC) | evallg(l-4); - z[8]=(long)RES; + z[5]=(long)Vbase; + z[6]=zero; + z[7]=(long)nf; + z[8]=(long)res; z[9]=(long)clg2; z[10]=zero; /* dummy: we MUST have lg(bnf) != lg(nf) */ if (CHANGE) { p1=cgetg(3,t_VEC); p1[1]=(long)z; p1[2]=(long)CHANGE; z=p1; } - return gcopy(z); + return z; } static GEN buchall_for_degree_one_pol(GEN nf, GEN CHANGE, long flun) { - long av = avma, k = EXP220; - GEN W,B,xarch,matarch,vectbase,vperm; - GEN fu=cgetg(1,t_VEC), reg=gun, c_1=gun, zu=cgetg(3,t_VEC); + gpmem_t av = avma; + GEN W,B,A,matarch,Vbase,res; + GEN fu=cgetg(1,t_VEC), R=gun, c1=gun, zu=cgetg(3,t_VEC); GEN clg1=cgetg(4,t_VEC), clg2=cgetg(4,t_VEC); - clg1[1]=un; clg1[2]=clg1[3]=clg2[3]=lgetg(1,t_VEC); - clg2[1]=clg2[2]=lgetg(1,t_MAT); + clg1[1]=un; clg1[2]=clg1[3]=clg2[2]=clg2[3]=lgetg(1,t_VEC); + clg2[1]=lgetg(1,t_MAT); zu[1]=deux; zu[2]=lnegi(gun); - W=B=xarch=matarch=cgetg(1,t_MAT); - vectbase=cgetg(1,t_COL); vperm=cgetg(1,t_VEC); + W=B=A=matarch=cgetg(1,t_MAT); + Vbase=cgetg(1,t_COL); - return gerepileupto(av, buchall_end(nf,CHANGE,flun,k,fu,clg1,clg2,reg,c_1,zu,W,B,xarch,matarch,vectbase,vperm)); + res = get_clfu(clg1, R, c1, zu, fu, EXP220); + return gerepilecopy(av, buchall_end(nf,CHANGE,flun,res,clg2,W,B,A,matarch,Vbase)); } -static GEN -get_LLLnf(GEN nf, long prec) +/* return (small set of) indices of columns generating the same lattice as x. + * Assume HNF(x) is inexpensive (few rows, many columns). + * Dichotomy approach since interesting columns may be at the very end */ +GEN +extract_full_lattice(GEN x) { - GEN M = gmael(nf,5,1); - GEN T2 = gmael(nf,5,3); - GEN cbase = lllgramintern(T2,100,1,prec); - GEN v = cgetg(5,t_VEC); - if (!cbase) return NULL; - if (gegal(cbase, idmat(lg(T2)-1))) cbase = NULL; - v[1] = (long) (cbase? qf_base_change(T2, cbase, 1): T2); - v[2] = (long) (cbase? gmul(M, cbase): M); - v[3] = (long) cbase; - v[4] = (long) (cbase? ZM_inv(cbase,gun): NULL); return v; + long dj, j, k, l = lg(x); + GEN h, h2, H, v; + + if (l < 200) return NULL; /* not worth it */ + + v = cgetg(l, t_VECSMALL); + setlg(v, 1); + H = hnfall_i(x, NULL, 1); + h = cgetg(1, t_MAT); + dj = 1; + for (j = 1; j < l; ) + { + gpmem_t av = avma; + long lv = lg(v); + + for (k = 0; k < dj; k++) v[lv+k] = j+k; + setlg(v, lv + dj); + h2 = hnfall_i(vecextract_p(x, v), NULL, 1); + if (gegal(h, h2)) + { /* these dj columns can be eliminated */ + avma = av; setlg(v, lv); + j += dj; + if (j >= l) break; /* shouldn't occur */ + dj <<= 1; + if (j + dj >= l) dj = (l - j) >> 1; + } + else if (dj > 1) + { /* at least one interesting column, try with first half of this set */ + avma = av; setlg(v, lv); + dj >>= 1; + } + else + { /* this column should be kept */ + if (gegal(h2, H)) break; + h = h2; j++; + } + } + return v; } GEN buchall(GEN P,GEN gcbach,GEN gcbach2,GEN gRELSUP,GEN gborne,long nbrelpid, long minsFB,long flun,long prec) { - ulong av = avma,av0,av1,limpile; - long N,R1,R2,RU,PRECREG,PRECLLL,KCCO,RELSUP,LIMC,LIMC2,lim; - long nlze,sreg,nrelsup,nreldep,phase,matmax,i,j,k,ss,cglob; - long first=1, sfb_increase=0, sfb_trials=0, precdouble=0, precadd=0; - double cbach,cbach2,drc,LOGD2; - GEN p1,vecT2,fu,zu,nf,LLLnf,D,xarch,W,reg,lfun,z,clh,vperm,subFB; - GEN B,C,c1,sublambda,pdep,parch,liste,invp,clg1,clg2, *mat; - GEN CHANGE=NULL, extramat=NULL, extraC=NULL, list_jideal=NULL; + gpmem_t av = avma, av0, av1, limpile; + long N,R1,R2,RU,PRECREG,PRECLLL,PRECLLLadd,KCCO,RELSUP,LIMC,LIMC2,lim; + long nlze,zc,nrelsup,nreldep,phase,matmax,i,j,k,seed,MAXRELSUP; + long sfb_increase, sfb_trials, precdouble=0, precadd=0; + long cglob; /* # of relations found so far */ + double cbach, cbach2, drc, LOGD2; + GEN vecG,fu,zu,nf,D,A,W,R,Res,z,h,list_jideal; + GEN res,L,resc,B,C,lambda,pdep,liste,invp,clg1,clg2,Vbase; + GEN *mat; /* raw relations found (as VECSMALL, not HNF-reduced) */ + GEN first_nz; /* first_nz[i] = index of 1st non-0 entry in mat[i] */ + GEN CHANGE=NULL, extramat=NULL, extraC=NULL; char *precpb = NULL; + FB_t F; - if (DEBUGLEVEL) timer2(); + if (DEBUGLEVEL) (void)timer2(); - if (typ(P)==t_POL) nf = NULL; else { nf = checknf(P); P = (GEN)nf[1]; } + P = get_nfpol(P, &nf); if (typ(gRELSUP) != t_INT) gRELSUP = gtrunc(gRELSUP); RELSUP = itos(gRELSUP); if (RELSUP<=0) err(talker,"not enough relations in bnfxxx"); /* Initializations */ fu = NULL; /* gcc -Wall */ - N = degpol(P); PRECREG = max(BIGDEFAULTPREC,prec); + N = degpol(P); + PRECREG = max(BIGDEFAULTPREC,prec); + PRECLLLadd = DEFAULTPREC; if (!nf) { - nf = initalgall0(P, nf_REGULAR, PRECREG); + nf = initalg(P, PRECREG); /* P was non-monic and nfinit changed it ? */ if (lg(nf)==3) { CHANGE = (GEN)nf[2]; nf = (GEN)nf[1]; } } - if (N<=1) return buchall_for_degree_one_pol(nf,CHANGE,flun); + if (N <= 1) return buchall_for_degree_one_pol(nf,CHANGE,flun); zu = rootsof1(nf); zu[2] = lmul((GEN)nf[7],(GEN)zu[2]); if (DEBUGLEVEL) msgtimer("initalg & rootsof1"); - R1 = itos(gmael(nf,2,1)); R2 = (N-R1)>>1; RU = R1+R2; + nf_get_sign(nf, &R1, &R2); RU = R1+R2; D = (GEN)nf[3]; drc = fabs(gtodouble(D)); LOGD2 = log(drc); LOGD2 = LOGD2*LOGD2; lim = (long) (exp(-(double)N) * sqrt(2*PI*N*drc) * pow(4/PI,(double)R2)); if (lim < 3) lim = 3; cbach = min(12., gtodouble(gcbach)); cbach /= 2; + if (cbach == 0.) err(talker,"Bach constant = 0 in bnfxxx"); + if (nbrelpid <= 0) gborne = gzero; + cbach2 = gtodouble(gcbach2); + /* resc ~ sqrt(D) w / 2^r1 (2pi)^r2 = hR / Res(zeta_K, s=1) */ + resc = gdiv(mulri(gsqrt(absi(D),DEFAULTPREC), (GEN)zu[1]), + gmul2n(gpowgs(Pi2n(1,DEFAULTPREC), R2), R1)); if (DEBUGLEVEL) - { - fprintferr("N = %ld, R1 = %ld, R2 = %ld, RU = %ld\n",N,R1,R2,RU); - fprintferr("D = %Z\n",D); - } - av0 = avma; mat = NULL; FB = NULL; + fprintferr("N = %ld, R1 = %ld, R2 = %ld\nD = %Z\n",N,R1,R2,D); + av0 = avma; mat = NULL; first_nz = NULL; START: - avma = av0; - if (first) first = 0; else desallocate(&mat); + seed = getrand(); + avma = av0; desallocate(&mat, &first_nz); if (precpb) { precdouble++; @@ -2829,74 +2975,88 @@ START: cbach = check_bach(cbach,12.); precadd = 0; - /* T2-LLL-reduce nf.zk */ - LLLnf = get_LLLnf(nf, PRECREG); - if (!LLLnf) { precpb = "LLLnf"; goto START; } - - LIMC = (long)(cbach*LOGD2); if (LIMC < 20) LIMC = 20; + LIMC = (long)(cbach*LOGD2); + if (LIMC < 20) { LIMC = 20; cbach = LIMC / LOGD2; } LIMC2= max(3 * N, (long)(cbach2*LOGD2)); if (LIMC2 < LIMC) LIMC2 = LIMC; if (DEBUGLEVEL) { fprintferr("LIMC = %ld, LIMC2 = %ld\n",LIMC,LIMC2); } - /* initialize FB, [sub]vperm */ - lfun = FBgen(nf,LIMC2,LIMC); - if (!lfun) goto START; - vperm = cgetg(lg(vectbase), t_VECSMALL); + Res = FBgen(&F, nf, LIMC2, LIMC); + if (!Res || !subFBgen(&F, nf, min(lim,LIMC2) + 0.5, minsFB)) goto START; + + if (DEBUGLEVEL) + { + if (DEBUGLEVEL>3) + { + fprintferr("\n***** IDEALS IN FACTORBASE *****\n\n"); + for (i=1; i<=F.KC; i++) fprintferr("no %ld = %Z\n",i,F.LP[i]); + fprintferr("\n***** IDEALS IN SUB FACTORBASE *****\n\n"); + outerr(vecextract_p(F.LP,F.subFB)); + fprintferr("\n***** INITIAL PERMUTATION *****\n\n"); + fprintferr("perm = %Z\n\n",F.perm); + } + msgtimer("sub factorbase (%ld elements)",lg(F.subFB)-1); + } sfb_trials = sfb_increase = 0; - subFB = subFBgen(N,min(lim,LIMC2), minsFB, vperm, &ss); - if (!subFB) goto START; nreldep = nrelsup = 0; /* PRECLLL = prec for LLL-reductions (idealred) * PRECREG = prec for archimedean components */ - PRECLLL = DEFAULTPREC - + ((expi(D)*(lg(subFB)-2)+((N*N)>>2))>>TWOPOTBITS_IN_LONG); + PRECLLL = PRECLLLadd + + ((expi(D)*(lg(F.subFB)-2) + ((N*N)>>2)) >> TWOPOTBITS_IN_LONG); if (!precdouble) PRECREG = prec+1; - if (PRECREG < PRECLLL) PRECREG = PRECLLL; - KCCO = KC+RU-1 + max(ss,RELSUP); /* expected number of needed relations */ + if (PRECREG < PRECLLL) + { /* very rare */ + PRECREG = PRECLLL; + nf = nfnewprec(nf,PRECREG); av0 = avma; + } + KCCO = F.KC+RU-1 + RELSUP; /* expected # of needed relations */ if (DEBUGLEVEL) - fprintferr("relsup = %ld, ss = %ld, KCZ = %ld, KC = %ld, KCCO = %ld\n", - RELSUP,ss,KCZ,KC,KCCO); + fprintferr("relsup = %ld, KCZ = %ld, KC = %ld, KCCO = %ld\n", + RELSUP, F.KCZ, F.KC, KCCO); + MAXRELSUP = min(50, 4*F.KC); matmax = 10*KCCO + MAXRELSUP; /* make room for lots of relations */ - mat = (GEN*)gpmalloc(sizeof(GEN)*(matmax + 1)); + reallocate(matmax, (GEN*)&mat, &first_nz); setlg(mat, KCCO+1); C = cgetg(KCCO+1,t_MAT); /* trivial relations (p) = prod P^e */ cglob = 0; z = zerocol(RU); - for (i=1; i<=KCZ; i++) + for (i=1; i<=F.KCZ; i++) { - GEN P = idealbase[i]; - if (isclone(P)) - { /* all prime divisors in FB */ - unsetisclone(P); cglob++; - C[cglob] = (long)z; /* 0 */ - mat[cglob] = p1 = col_0(KC); - k = numideal[FB[i]]; - p1[0] = k+1; /* for already_found_relation */ - p1 += k; - for (j=lg(P)-1; j; j--) p1[j] = itos(gmael(P,j,3)); - } + long p = F.FB[i]; + GEN c, P = F.LV[p]; + if (!isclone(P)) continue; + + /* all prime divisors in FB */ + cglob++; + C[cglob] = (long)z; /* 0 */ + mat[cglob] = c = col_0(F.KC); + k = F.iLP[p]; + first_nz[cglob] = k+1; + c += k; + for (j=lg(P)-1; j; j--) c[j] = itos(gmael(P,j,3)); } if (DEBUGLEVEL) fprintferr("After trivial relations, cglob = %ld\n",cglob); /* initialize for other relations */ for (i=cglob+1; i<=KCCO; i++) { - mat[i] = col_0(KC); + mat[i] = col_0(F.KC); C[i] = (long)cgetc_col(RU,PRECREG); } - av1 = avma; liste = cgetg(KC+1,t_VECSMALL); - for (i=1; i<=KC; i++) liste[i] = 0; + av1 = avma; liste = vecsmall_const(F.KC, 0); invp = relationrank(mat,cglob,liste); /* relations through elements of small norm */ - cglob = small_norm_for_buchall(cglob,mat,C,(long)LIMC,PRECREG, - nf,gborne,nbrelpid,invp,liste,LLLnf); + if (gsigne(gborne) > 0) + cglob = small_norm_for_buchall(cglob,mat,first_nz,C,(long)LIMC,PRECREG,&F, + nf,nbrelpid,invp,liste); if (cglob < 0) { precpb = "small_norm"; goto START; } avma = av1; limpile = stack_lim(av1,1); phase = 0; - nlze = matmax = 0; /* for lint */ - vecT2 = NULL; + nlze = 0; /* for lint */ + vecG = NULL; + list_jideal = NULL; /* random relations */ if (cglob == KCCO) /* enough rels, but init random_relations just in case */ @@ -2904,6 +3064,7 @@ START: else { GEN matarch; + long ss; if (DEBUGLEVEL) fprintferr("\n#### Looking for random relations\n"); MORE: @@ -2911,55 +3072,57 @@ MORE: { if (DEBUGLEVEL) fprintferr("*** Increasing sub factor base\n"); sfb_increase = 0; - if (++sfb_trials >= SFB_MAX) goto START; - subFB = subFBgen(N,min(lim,LIMC2), lg(subFB)-1+SFB_STEP,NULL,&ss); - if (!subFB) goto START; + if (++sfb_trials > SFB_MAX || !subFBgen_increase(&F, nf, SFB_STEP)) + goto START; nreldep = nrelsup = 0; } if (phase == 0) matarch = C; else { /* reduced the relation matrix at least once */ - long lgex = max(nlze, MIN_EXTRA); /* number of new relations sought */ - long slim; /* total number of relations (including lgex new ones) */ + long lgex = max(nlze, MIN_EXTRA); /* # of new relations sought */ + long slim; /* total # of relations (including lgex new ones) */ setlg(extraC, lgex+1); setlg(extramat,lgex+1); /* were allocated after hnfspec */ slim = cglob+lgex; if (slim > matmax) { - mat = (long**)gprealloc(mat, (2*slim+1) * sizeof(long*), - (matmax+1) * sizeof(long*)); matmax = 2 * slim; + reallocate(matmax, (GEN*)&mat, &first_nz); } setlg(mat, slim+1); if (DEBUGLEVEL) fprintferr("\n(need %ld more relation%s)\n", lgex, (lgex==1)?"":"s"); - for (j=cglob+1; j<=slim; j++) mat[j] = col_0(KC); + for (j=cglob+1; j<=slim; j++) mat[j] = col_0(F.KC); matarch = extraC - cglob; /* start at 0, the others at cglob */ } - if (!vecT2) + if (!vecG) { - vecT2 = compute_vecT2(RU,nf); + vecG = compute_vecG(nf,PRECLLL); av1 = avma; } - if (!powsubFB) + if (!F.powsubFB) { - powsubFBgen(nf,subFB,CBUCHG+1,PRECREG); + powsubFBgen(&F, nf, CBUCHG+1, PRECREG); av1 = avma; } - ss = random_relation(phase,cglob,(long)LIMC,PRECLLL,PRECREG, - nf,subFB,vecT2,mat,matarch,list_jideal); + ss = random_relation(phase,cglob,(long)LIMC,PRECREG,MAXRELSUP, + nf,vecG,mat,first_nz,matarch,list_jideal,&F); if (ss < 0) { /* could not find relations */ - if (ss != -1) precpb = "random_relation"; /* precision pb */ + if (ss != -1) + { + precpb = "random_relation"; /* precision pb */ + PRECLLLadd = (PRECLLLadd<<1) - 2; + } goto START; } - if (DEBUGLEVEL > 2) dbg_outrel(phase,cglob,vperm,mat,matarch); - if (phase) + if (DEBUGLEVEL > 2 && phase == 0) dbg_outrel(cglob,mat,matarch); + if (phase) for (j=lg(extramat)-1; j>0; j--) { GEN c = mat[cglob+j], *g = (GEN*) extramat[j]; - for (k=1; k<=KC; k++) g[k] = stoi(c[vperm[k]]); + for (k=1; k<=F.KC; k++) g[k] = stoi(c[F.perm[k]]); } cglob = ss; } @@ -2968,21 +3131,17 @@ MORE: if (phase == 0) { /* never reduced before */ long lgex; - W = hnfspec(mat,vperm,&pdep,&B,&C, lg(subFB)-1); + W = hnfspec(mat,F.perm,&pdep,&B,&C, lg(F.subFB)-1); phase = 1; nlze = lg(pdep)>1? lg(pdep[1])-1: lg(B[1])-1; - if (nlze) - { - list_jideal = cgetg(nlze+1, t_VECSMALL); - for (i=1; i<=nlze; i++) list_jideal[i] = vperm[i]; - } + if (nlze) list_jideal = vecextract_i(F.perm, 1, nlze); lgex = max(nlze, MIN_EXTRA); /* set lgex > 0, in case regulator is 0 */ /* allocate now, reduce dimension later (setlg) when lgex goes down */ extramat= cgetg(lgex+1,t_MAT); extraC = cgetg(lgex+1,t_MAT); for (j=1; j<=lgex; j++) { - extramat[j]=lgetg(KC+1,t_COL); + extramat[j]=lgetg(F.KC+1,t_COL); extraC[j] = (long)cgetc_col(RU,PRECREG); } } @@ -2990,94 +3149,76 @@ MORE: { if (low_stack(limpile, stack_lim(av1,1))) { - GEN *gptr[6]; if(DEBUGMEM>1) err(warnmem,"buchall"); - gptr[0]=&W; gptr[1]=&C; gptr[2]=&B; gptr[3]=&pdep; - gptr[4]=&extramat; gptr[5]=&extraC; gerepilemany(av1,gptr,6); + gerepileall(av1,6, &W,&C,&B,&pdep,&extramat,&extraC); } list_jideal = NULL; - W = hnfadd(W,vperm,&pdep,&B,&C, extramat,extraC); + W = hnfadd(W,F.perm,&pdep,&B,&C, extramat,extraC); nlze = lg(pdep)>1? lg(pdep[1])-1: lg(B[1])-1; if (nlze && ++nreldep > MAXRELSUP) { sfb_increase=1; goto MORE; } } if (nlze) goto MORE; /* dependent rows */ /* first attempt at regulator for the check */ - sreg = (lg(mat)-1) - (lg(B)-1) - (lg(W)-1); /* = zc (cf hnffinal) */ - xarch = cgetg(sreg+1,t_MAT); /* cols corresponding to units */ - for (j=1; j<=sreg; j++) xarch[j] = C[j]; - reg = compute_multiple_of_R(xarch,RU,N,&sublambda); - if (!reg) + zc = (lg(mat)-1) - (lg(B)-1) - (lg(W)-1); + A = vecextract_i(C, 1, zc); /* cols corresponding to units */ + R = compute_multiple_of_R(A,RU,N,&lambda); + if (!R) { /* not full rank for units */ if (DEBUGLEVEL) fprintferr("regulator is zero.\n"); if (++nrelsup > MAXRELSUP) goto START; nlze = MIN_EXTRA; goto MORE; } /* anticipate precision problems */ - if (!sublambda) { precpb = "bestappr"; goto START; } + if (!lambda) { precpb = "bestappr"; goto START; } - /* class number */ - clh = dethnf_i(W); - if (DEBUGLEVEL) fprintferr("\n#### Tentative class number: %Z\n", clh); + h = dethnf_i(W); + if (DEBUGLEVEL) fprintferr("\n#### Tentative class number: %Z\n", h); - /* check */ - z = mulrr(lfun,gmul(gmul2n(gpuigs(shiftr(mppi(DEFAULTPREC),1),-R2),-R1), - gsqrt(absi(D),DEFAULTPREC))); - z = mulri(z,(GEN)zu[1]); - /* z = Res (zeta_K, s = 1) * w D^(1/2) / [ 2^r1 (2pi)^r2 ] = h R */ - p1 = gmul2n(divir(clh,z), 1); - /* c1 should be close to 2, and not much smaller */ - c1 = compute_check(sublambda,p1,&parch,®); - /* precision problems? */ - if (!c1 || gcmpgs(gmul2n(c1,1),3) < 0) - { /* has to be a precision problem unless we cheat on Bach constant */ - if (!precdouble) precpb = "compute_check"; - goto START; - } - if (gcmpgs(c1,3) > 0) + z = mulrr(Res, resc); /* ~ hR if enough relations, a multiple otherwise */ + switch (compute_R(lambda, divir(h,z), &L, &R)) { - if (++nrelsup <= MAXRELSUP) - { - if (DEBUGLEVEL) fprintferr("\n ***** check = %f\n",gtodouble(c1)/2); - nlze = MIN_EXTRA; goto MORE; - } - if (cbach < 11.99) { sfb_increase = 1; goto MORE; } - err(warner,"suspicious check. Try to increase extra relations"); + case PRECI: /* precision problem unless we cheat on Bach constant */ + if (!precdouble) precpb = "compute_R"; + goto START; + case RELAT: /* not enough relations */ + if (++nrelsup <= MAXRELSUP) nlze = MIN_EXTRA; else sfb_increase = 1; + goto MORE; } + /* DONE */ - if (KCZ2 > KCZ) - { /* "be honest" */ - if (!powsubFB) powsubFBgen(nf,subFB,CBUCHG+1,PRECREG); - if (!be_honest(nf,subFB,PRECLLL)) goto START; - } + if (!be_honest(&F, nf, PRECLLL)) goto START; /* fundamental units */ - if (flun < 0 || flun > 1) + if (flun & nf_INIT || flun & nf_UNITS) { - xarch = cleancol(gmul(xarch,parch),N,PRECREG); - if (DEBUGLEVEL) msgtimer("cleancol"); + GEN v = extract_full_lattice(L); /* L may be very large */ + if (v) + { + A = vecextract_p(A, v); + L = vecextract_p(L, v); + } + /* arch. components of fund. units */ + A = cleanarch(gmul(A,lllint(L)), N, PRECREG); + if (DEBUGLEVEL) msgtimer("cleanarch"); } - if (labs(flun) > 1) + if (flun & nf_UNITS) { - fu = getfu(nf,&xarch,reg,flun,&k,PRECREG); - if (k <= 0 && labs(flun) > 2) + fu = getfu(nf,&A,R,flun,&k,PRECREG); + if (k <= 0 && flun & nf_FORCE) { - if (k < 0) - { - precadd = (DEFAULTPREC-2) + ((-k) >> TWOPOTBITS_IN_LONG); - if (precadd <= 0) precadd = (DEFAULTPREC-2); - } + if (k < 0) precadd = (DEFAULTPREC-2) + ((-k) >> TWOPOTBITS_IN_LONG); + (void)setrand(seed); precpb = "getfu"; goto START; } } + desallocate(&mat, &first_nz); /* class group generators */ - i = lg(C)-sreg; C += sreg; C[0] = evaltyp(t_MAT)|evallg(i); - C = cleancol(C,N,PRECREG); - class_group_gen(nf,W,C,vperm, &clg1, &clg2, PRECREG); - - c1 = gdiv(gmul(reg,clh), z); - desallocate(&mat); - - return gerepileupto(av, buchall_end(nf,CHANGE,flun,k,fu,clg1,clg2,reg,c1,zu,W,B,xarch,C,vectbase,vperm)); + i = lg(C)-zc; C += zc; C[0] = evaltyp(t_MAT)|evallg(i); + C = cleanarch(C,N,PRECREG); + Vbase = vecextract_p(F.LP, F.perm); + class_group_gen(nf,W,C,Vbase,PRECREG,NULL, &clg1, &clg2); + res = get_clfu(clg1, R, gdiv(mpmul(R,h), z), zu, fu, k); + return gerepilecopy(av, buchall_end(nf,CHANGE,flun,res,clg2,W,B,A,C,Vbase)); }