=================================================================== RCS file: /home/cvs/OpenXM_contrib/pari-2.2/src/basemath/Attic/buch3.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/buch3.c 2001/10/02 11:17:03 1.1 +++ OpenXM_contrib/pari-2.2/src/basemath/Attic/buch3.c 2002/09/11 07:26:50 1.2 @@ -1,4 +1,4 @@ -/* $Id: buch3.c,v 1.1 2001/10/02 11:17:03 noro Exp $ +/* $Id: buch3.c,v 1.2 2002/09/11 07:26:50 noro Exp $ Copyright (C) 2000 The PARI group. @@ -21,33 +21,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, #include "pari.h" #include "parinf.h" -extern GEN concatsp3(GEN x, GEN y, GEN z); +extern void testprimes(GEN bnf, long bound); +extern GEN Fp_PHlog(GEN a, GEN g, GEN p, GEN ord); +extern GEN FqX_factor(GEN x, GEN T, GEN p); +extern GEN anti_unif_mod_f(GEN nf, GEN pr, GEN sqf); +extern GEN arch_mul(GEN x, GEN y); extern GEN check_and_build_cycgen(GEN bnf); +extern GEN colreducemodHNF(GEN x, GEN y, GEN *Q); +extern GEN detcyc(GEN cyc); +extern GEN famat_reduce(GEN fa); +extern GEN famat_to_nf_modideal_coprime(GEN nf, GEN g, GEN e, GEN id); +extern GEN famat_to_nf_modidele(GEN nf, GEN g, GEN e, GEN bid); extern GEN gmul_mat_smallvec(GEN x, GEN y); +extern GEN idealaddtoone_i(GEN nf, GEN x, GEN y); +extern GEN idealprodprime(GEN nf, GEN L); extern GEN ideleaddone_aux(GEN nf,GEN x,GEN ideal); +extern GEN isprincipalfact(GEN bnf,GEN P, GEN e, GEN C, long flag); extern GEN logunitmatrix(GEN nf,GEN funits,GEN racunit,GEN bid); -extern GEN vconcat(GEN Q1, GEN Q2); -extern void minim_alloc(long n, double ***q, GEN *x, double **y, double **z, double **v); +extern GEN make_integral(GEN nf, GEN L0, GEN f, GEN *listpr, GEN *ptd1); +extern GEN sqred1_from_QR(GEN x, long prec); +extern GEN subgroupcondlist(GEN cyc, GEN bound, GEN listKer); +extern GEN to_Fp_simple(GEN nf, GEN x, GEN ffproj); extern GEN to_famat_all(GEN x, GEN y); extern GEN trivfact(void); -extern GEN arch_mul(GEN x, GEN y); -extern GEN isprincipalfact(GEN bnf,GEN P, GEN e, GEN C, long flag); -extern GEN idealaddtoone_i(GEN nf, GEN x, GEN y); -extern GEN ideallllred_elt(GEN nf, GEN I); +extern GEN unif_mod_f(GEN nf, GEN pr, GEN sqf); +extern GEN vconcat(GEN Q1, GEN Q2); +extern long FqX_is_squarefree(GEN P, GEN T, GEN p); +extern long int_elt_val(GEN nf, GEN x, GEN p, GEN b, GEN *newx); +extern void minim_alloc(long n, double ***q, GEN *x, double **y, double **z, double **v); +extern void rowselect_p(GEN A, GEN B, GEN p, long init); -/* U W V = D, Ui = U^(-1) */ -GEN -compute_class_number(GEN W, GEN *D,GEN *Ui,GEN *V) -{ - GEN S = smith2(W); - - *Ui= ginv((GEN)S[1]); - if (V) *V = (GEN)S[2]; - *D = (GEN)S[3]; - if (DEBUGLEVEL>=4) msgtimer("smith/class group"); - return dethnf_i(*D); -} - /* FIXME: obsolete, see zarchstar (which is much slower unfortunately). */ static GEN get_full_rank(GEN nf, GEN v, GEN _0, GEN _1, GEN gen, long ngen, long rankmax) @@ -63,7 +66,7 @@ get_full_rank(GEN nf, GEN v, GEN _0, GEN _1, GEN gen, limr = (limr-1)>>1; for (k=rr; k<=limr; k++) { - long av1=avma; + gpmem_t av1=avma; alpha = gzero; for (kk=k,i=1; i<=N; i++,kk/=rr) { @@ -75,13 +78,12 @@ get_full_rank(GEN nf, GEN v, GEN _0, GEN _1, GEN gen, vecsign[i] = (gsigne(gsubst(alpha,va,(GEN)rac[i])) > 0)? (long)_0 : (long)_1; v1 = concatsp(v, vecsign); - if (rank(v1) == rankinit) avma=av1; - else - { - v=v1; rankinit++; ngen++; - gen[ngen] = (long) alpha; - if (rankinit == rankmax) return ginv(v); /* full rank */ - } + if (rank(v1) == rankinit) { avma = av1; continue; } + + v=v1; rankinit++; ngen++; + gen[ngen] = (long) alpha; + if (rankinit == rankmax) return ginv(v); /* full rank */ + vecsign = cgetg(rankmax+1,t_COL); } } } @@ -91,9 +93,9 @@ GEN buchnarrow(GEN bnf) { GEN nf,_0,_1,cyc,gen,v,matsign,arch,cycgen,logs; - GEN dataunit,p1,p2,h,clh,basecl,met,u1; + GEN dataunit,p1,p2,h,basecl,met,u1; long r1,R,i,j,ngen,sizeh,t,lo,c; - ulong av = avma; + gpmem_t av = avma; bnf = checkbnf(bnf); nf = checknf(bnf); r1 = nf_get_r1(nf); @@ -134,12 +136,12 @@ buchnarrow(GEN bnf) vconcat(diagonal(cyc), logs), vconcat(zeromat(ngen, r1-t), gscalmat(gdeux,r1-t)) ); - clh = compute_class_number(h,&met,&u1,NULL); - lo = lg(met)-1; - for (c=1; c<=lo; c++) - if (gcmp1(gcoeff(met,c,c))) break; + + lo = lg(h)-1; + met = smithrel(h,NULL,&u1); + c = lg(met); + if (DEBUGLEVEL>3) msgtimer("smith/class group"); - u1 = reducemodmatrix(u1,h); basecl = cgetg(c,t_VEC); for (j=1; j 1 */ - y = ideallllred_elt(nf, idealmullll(nf,x,id)); - p1 = ground(element_div(nf,alp,y)); - alp = gsub(alp, element_mul(nf,p1,y)); - return gcmp0(alp)? y: alp; + basecl = cgetg(l,t_VEC); + prec = nfgetprec(nf); + G = cgetg(3,t_VEC); + G[2] = lgetg(1,t_MAT); + + for (j=1; j 0) { avma=av; return x; } - p1=(GEN)sarch[2]; l=lg(p1); - if (l > 1) - { - b=bet; p2=lift_intern(gmul((GEN)sarch[3],zsigne(nf,bet,arch))); - for (i=1; i 0) { avma=av; return x; } - } - return idealmul(nf,bet,x); + G = redideal(nf, x, f); + D = redideal(nf, idealdiv(nf,G,x), f); + A = element_div(nf,D,G); + if (too_big(nf,A) > 0) { avma = av; return x; } + a = set_sign_mod_idele(nf, NULL, A, idele, sarch); + if (a != A && too_big(nf,A) > 0) { avma = av; return x; } + return idealmul(nf, a, x); } -static GEN -idealmulmodidele(GEN nf,GEN x,GEN y, GEN ideal,GEN sarch,GEN arch) +GEN +idealmodidele(GEN bnr, GEN x) { - return idealmodidele(nf,idealmul(nf,x,y),ideal,sarch,arch); + GEN bid = (GEN)bnr[2], fa2 = (GEN)bid[4]; + GEN idele = (GEN)bid[1]; + GEN sarch = (GEN)fa2[lg(fa2)-1]; + return _idealmodidele(checknf(bnr), x, idele, sarch); } -/* assume n > 0 */ -/* FIXME: should compute x^n = a I using idealred, then reduce a mod idele */ +/* v_pr(L0 * cx). tau = pr[5] or (more efficient) mult. table for pr[5] */ +static long +fast_val(GEN nf,GEN L0,GEN cx,GEN pr,GEN tau) +{ + GEN p = (GEN)pr[1]; + long v = int_elt_val(nf,L0,p,tau,NULL); + if (cx) + { + long w = ggval(cx, p); + if (w) v += w * itos((GEN)pr[3]); + } + return v; +} + static GEN -idealpowmodidele(GEN nf,GEN x,GEN n, GEN ideal,GEN sarch,GEN arch) +compute_raygen(GEN nf, GEN u1, GEN gen, GEN bid) { - long i,m,av=avma; - GEN y; - ulong j; + GEN f, fZ, basecl, module, fa, fa2, *listpr, *listep, *vecinvpi, *vectau; + GEN pr, t, sqf, EX, sarch, cyc; + long i,j,l,lp; - if (cmpis(n, 16) < 0) + /* basecl = generators in factored form */ + basecl = compute_fact(nf,u1,gen); + + module = (GEN)bid[1]; + cyc = gmael(bid,2,2); EX = (GEN)cyc[1]; /* exponent of (O/f)^* */ + f = (GEN)module[1]; fZ = gcoeff(f,1,1); + fa = (GEN)bid[3]; + fa2 = (GEN)bid[4]; sarch = (GEN)fa2[lg(fa2)-1]; + listpr = (GEN*)fa[1]; + listep = (GEN*)fa[2]; + + lp = lg(listpr); + /* sqf = squarefree kernel of f */ + sqf = lp <= 2? NULL: idealprodprime(nf, (GEN)listpr); + + vecinvpi = (GEN*)cgetg(lp, t_VEC); + vectau = (GEN*)cgetg(lp, t_VEC); + for (i=1; i>=1; - y = x; - for (j>>=1; j; j>>=1) + l = lg(basecl); + for (i=1; i=2; i--) - for (m=n[i],j=HIGHBIT; j; j>>=1) + GEN d, invpi, mulI, G, I, A, e, L, newL; + long la, v, k; + /* G = [I, A=famat(L,e)] is a generator, I integral */ + G = (GEN)basecl[i]; + I = (GEN)G[1]; + A = (GEN)G[2]; + L = (GEN)A[1]; + e = (GEN)A[2]; + /* if no reduction took place in compute_fact, everybody is still coprime + * to f + no denominators */ + if (!I) { - y = idealmul(nf,y,y); - if (m&j) y = idealmul(nf,y,x); - y = idealmodidele(nf,y,ideal,sarch,arch); + basecl[i] = (long)famat_to_nf_modidele(nf, L, e, bid); + continue; } - return gerepileupto(av,y); + if (lg(A) == 1) + { + basecl[i] = (long)I; + continue; + } + + /* compute mulI so that mulI * I coprime to f + * FIXME: use idealcoprime ??? (Less efficient. Fix idealcoprime!) */ + mulI = NULL; + for (j=1; j 0) op = + else { op = − p1 = negi(p1); } - p1 = idealpowmodidele(nf,(GEN)genplus[i],p1,x,sarch,arch); - *op = *op==Id? p1 - : idealmulmodidele(nf,*op,p1,x,sarch,arch); - } - if (minus == Id) p1 = plus; - else - { - p2 = ideleaddone_aux(nf,minus,module); - p1 = idealdivexact(nf,idealmul(nf,p2,plus),minus); - p1 = idealmodidele(nf,p1,x,sarch,arch); - } - genray[j]=lpileupto(av1,p1); - } - clg = cgetg(4,t_VEC); clg[3] = lcopy(genray); - } else clg = cgetg(3,t_VEC); - clg[1] = licopy(clh); setlg(met,c); - clg[2] = (long)mattodiagonal(met); - if (!(flag & nf_INIT)) return gerepileupto(av,clg); - u2 = cgetg(Ri+1,t_MAT); u1 = cgetg(RU+1,t_MAT); u = (GEN)hmatu[2]; for (j=1; j<=RU; j++) { u1[j]=u[j]; setlg(u[j],RU+1); } u += RU; for (j=1; j<=Ri; j++) { u2[j]=u[j]; setlg(u[j],RU+1); } - p1 = lllint(u1); p2 = ginv(hmat); + y = cgetg(7,t_VEC); - y[1] = lcopy(bnf); - y[2] = lcopy(bid); - y[3] = lcopy(vecel); - y[4] = linv(u1old); - y[5] = lcopy(clg); u = cgetg(3,t_VEC); + y[1] = (long)bnf; + y[2] = (long)bid; + y[3] = (long)vecel; + y[4] = (long)U; + y[5] = (long)clg; u = cgetg(3,t_VEC); y[6] = (long)u; - u[1] = lmul(u2,p2); - u[2] = lmul(u1,p1); - return gerepileupto(av,y); + u[1] = lmul(u2, ginv(hmat)); + u[2] = (long)lllint_ip(u1,100); + return gerepilecopy(av,y); } GEN @@ -445,7 +574,7 @@ rayclassno(GEN bnf,GEN ideal) { GEN nf,h,dataunit,racunit,bigres,bid,cycbid,funits,H; long RU,i; - ulong av = avma; + gpmem_t av = avma; bnf = checkbnf(bnf); nf = (GEN)bnf[7]; bigres = (GEN)bnf[8]; h = gmael(bigres,1,1); /* class number */ @@ -470,7 +599,7 @@ quick_isprincipalgen(GEN bnf, GEN x) GEN z = cgetg(3, t_VEC), gen = gmael3(bnf,8,1,3); GEN idep, ep = isprincipal(bnf,x); /* x \prod g[i]^(-ep[i]) = factorisation of principal ideal */ - idep = isprincipalfact(bnf, gen, gneg(ep), x, nf_GENMAT | nf_GEN); + idep = isprincipalfact(bnf, gen, gneg(ep), x, nf_GENMAT|nf_FORCE); z[1] = (long)ep; z[2] = idep[2]; return z; } @@ -478,8 +607,9 @@ quick_isprincipalgen(GEN bnf, GEN x) GEN isprincipalrayall(GEN bnr, GEN x, long flag) { - long av=avma,i,j,c; - GEN bnf,nf,bid,matu,vecel,ep,p1,beta,idep,y,rayclass; + long i, j, c; + gpmem_t av=avma; + GEN bnf,nf,bid,matu,vecel,ep,p1,beta,idep,ex,rayclass; GEN divray,genray,alpha,alphaall,racunit,res,funit; checkbnr(bnr); @@ -488,6 +618,9 @@ isprincipalrayall(GEN bnr, GEN x, long flag) vecel=(GEN)bnr[3]; matu =(GEN)bnr[4]; rayclass=(GEN)bnr[5]; + divray = (GEN)rayclass[2]; c = lg(divray)-1; + ex = cgetg(c+1,t_COL); + if (c == 0 && !(flag & nf_GEN)) return ex; if (typ(x) == t_VEC && lg(x) == 3) { idep = (GEN)x[2]; x = (GEN)x[1]; } /* precomputed */ @@ -495,16 +628,14 @@ isprincipalrayall(GEN bnr, GEN x, long flag) idep = quick_isprincipalgen(bnf, x); ep = (GEN)idep[1]; beta= (GEN)idep[2]; - c = lg(ep); - for (i=1; i vecel.gen (coprime to bid) */ + j = lg(ep); + for (i=1; i vecel.gen (coprime to bid) */ if (typ(vecel[i]) != t_INT && signe(ep[i])) /* <==> != 1 */ beta = arch_mul(to_famat_all((GEN)vecel[i], negi((GEN)ep[i])), beta); p1 = gmul(matu, concatsp(ep, zideallog(nf,beta,bid))); - divray = (GEN)rayclass[2]; c = lg(divray); - y = cgetg(c,t_COL); - for (i=1; i1) - fprintferr("PHASE 1: check primes to Zimmert bound = %ld\n\n",minkowski); - f=(GEN)nf[4]; dK=(GEN)nf[3]; - if (!gcmp1(f)) - { - GEN different = gmael(nf,5,5); - if (DEBUGLEVEL>1) - fprintferr("**** Testing Different = %Z\n",different); - p1 = isprincipalall(bnf,different,nf_FORCE); - if (DEBUGLEVEL>1) fprintferr(" is %Z\n",p1); - } - fb=(GEN)bnf[5]; - p1 = gmael(fb, lg(fb)-1, 1); /* largest p in factorbase */ - pp = 0; pmax = is_bigint(p1)? VERYBIGINT: itos(p1); - if ((ulong)minkowski > maxprime()) err(primer1); - while (pp < minkowski) - { - pp += *delta++; - if (DEBUGLEVEL>1) fprintferr("*** p = %ld\n",pp); - vectpp=primedec(bnf,stoi(pp)); nbideal=lg(vectpp)-1; - /* loop through all P | p if ramified, all but one otherwise */ - if (!smodis(dK,pp)) nbideal++; - for (i=1; i1) - fprintferr(" Testing P = %Z\n",P); - if (cmpis(idealnorm(bnf,P), minkowski) < 1) - { - if (pp <= pmax && (k = tablesearch(fb, P, cmp_prime_ideal))) - { - if (DEBUGLEVEL>1) fprintferr(" #%ld in factor base\n",k); - } - else - { - p1 = isprincipal(bnf,P); - if (DEBUGLEVEL>1) fprintferr(" is %Z\n",p1); - } - } - else if (DEBUGLEVEL>1) - fprintferr(" Norm(P) > Zimmert bound\n"); - } - avma = av; - } - if (DEBUGLEVEL>1) { fprintferr("End of PHASE 1.\n\n"); flusherr(); } -} - /* return \gamma_n^n if known, an upper bound otherwise */ static GEN hermiteconstant(long n) { GEN h,h1; - long av; + gpmem_t av; switch(n) { @@ -694,7 +770,7 @@ hermiteconstant(long n) case 8: return stoi(256); } av = avma; - h = gpuigs(divsr(2,mppi(DEFAULTPREC)), n); + h = gpowgs(divsr(2,mppi(DEFAULTPREC)), n); h1 = gsqr(ggamma(gdivgs(stoi(n+4),2),DEFAULTPREC)); return gerepileupto(av, gmul(h,h1)); } @@ -731,33 +807,31 @@ isprimitive(GEN nf) } static GEN +dft_bound() +{ + if (DEBUGLEVEL>1) fprintferr("Default bound for regulator: 0.2\n"); + return dbltor(0.2); +} + +static GEN regulatorbound(GEN bnf) { - long N,R1,R2,R; - GEN nf,dKa,bound,p1,c1; + long N, R1, R2, R; + GEN nf, dKa, p1, c1; nf = (GEN)bnf[7]; N = degpol(nf[1]); - bound = dbltor(0.2); - if (!isprimitive(nf)) - { - if (DEBUGLEVEL>1) fprintferr("Default bound for regulator: 0.2\n"); - return bound; - } + if (!isprimitive(nf)) return dft_bound(); + dKa = absi((GEN)nf[3]); - R1 = itos(gmael(nf,2,1)); - R2 = itos(gmael(nf,2,2)); R = R1+R2-1; - if (!R2 && N<12) c1 = gpuigs(stoi(4),N>>1); else c1 = gpuigs(stoi(N),N); - if (cmpii(dKa,c1) <= 0) - { - if (DEBUGLEVEL>1) fprintferr("Default bound for regulator: 0.2\n"); - return bound; - } + nf_get_sign(nf, &R1, &R2); R = R1+R2-1; + if (!R2 && N<12) c1 = gpowgs(stoi(4),N>>1); else c1 = gpowgs(stoi(N),N); + if (cmpii(dKa,c1) <= 0) return dft_bound(); + p1 = gsqr(glog(gdiv(dKa,c1),DEFAULTPREC)); - p1 = gdivgs(gmul2n(gpuigs(gdivgs(gmulgs(p1,3),N*(N*N-1)-6*R2),R),R2),N); - p1 = gsqrt(gdiv(p1, hermiteconstant(R)), DEFAULTPREC); - if (gcmp(p1,bound) > 0) bound = p1; + p1 = divrs(gmul2n(gpowgs(divrs(mulrs(p1,3),N*(N*N-1)-6*R2),R),R2), N); + p1 = mpsqrt(gdiv(p1, hermiteconstant(R))); if (DEBUGLEVEL>1) fprintferr("Mahler bound for regulator: %Z\n",p1); - return bound; + return gmax(p1, dbltor(0.2)); } /* x given by its embeddings */ @@ -780,23 +854,23 @@ norm_by_embed(long r1, GEN x) static int is_unit(GEN M, long r1, GEN x) { - long av = avma; + gpmem_t av = avma; GEN Nx = ground( norm_by_embed(r1, gmul_mat_smallvec(M,x)) ); int ok = is_pm1(Nx); avma = av; return ok; } -#define NBMAX 5000 /* FIXME: should use smallvectors */ static GEN -minimforunits(GEN nf, long BORNE, long stockmax) +minimforunits(GEN nf, long BORNE, GEN w) { const long prec = MEDDEFAULTPREC; - long av = avma,n,i,j,k,s,norme,normax,*x,cmpt,r1; - GEN u,r,S,a,M,p1; - double p; + long n, i, j, k, s, *x, r1, cnt = 0; + gpmem_t av = avma; + GEN u,r,a,M; + double p, norme, normin, normax; double **q,*v,*y,*z; - double eps=0.000001, BOUND = BORNE + eps; + double eps=0.000001, BOUND = BORNE * 1.00001; if (DEBUGLEVEL>=2) { @@ -804,23 +878,18 @@ minimforunits(GEN nf, long BORNE, long stockmax) if (DEBUGLEVEL>2) fprintferr(" BOUND = %ld\n",BOUND); flusherr(); } - r1 = nf_get_r1(nf); - a = gmael(nf,5,3); n = lg(a); - minim_alloc(n, &q, &x, &y, &z, &v); - n--; - u = lllgram(a,prec); - M = gmul(gmael(nf,5,1), u); /* embeddings of T2-reduced basis */ - M = gprec_w(M, prec); - a = gmul(qf_base_change(a,u,1), realun(prec)); - r = sqred1(a); + r1 = nf_get_r1(nf); n = degpol(nf[1]); + minim_alloc(n+1, &q, &x, &y, &z, &v); + M = gprec_w(gmael(nf,5,1), prec); + a = gmul(gmael(nf,5,2), realun(prec)); + r = sqred1_from_QR(a, prec); for (j=1; j<=n; j++) { v[j] = rtodbl(gcoeff(r,j,j)); for (i=1; i1); if (!x[1] && y[1]<=eps) break; - if (++cmpt > NBMAX) { av=avma; return NULL; } if (DEBUGLEVEL>8){ fprintferr("."); flusherr(); } - p = x[1]+z[1]; norme = (long)(y[1] + p*p*v[1] + eps); + if (++cnt == 5000) return NULL; /* too expensive */ + + p = x[1]+z[1]; norme = y[1] + p*p*v[1] + eps; if (norme > normax) normax = norme; - if (is_unit(M,r1, x)) + if (is_unit(M,r1, x) + && (norme > 2*n /* exclude roots of unity */ + || !isnfscalar(element_pow(nf, small_to_col(x), w)))) { + if (norme < normin) normin = norme; if (DEBUGLEVEL>=2) { fprintferr("*"); flusherr(); } - cmpt = 0; - if (++s <= stockmax) - { - p1 = cgetg(n+1,t_COL); - for (i=1; i<=n; i++) p1[i]=lstoi(x[i]); - S[s] = lmul(u,p1); - } } x[k]--; } if (DEBUGLEVEL>=2){ fprintferr("\n"); flusherr(); } - k = (s>1; for (n2=n1; n2<=m2; n2++) { - long av = avma; n3=N-n1-n2; prec=PREC; + gpmem_t av = avma; n3=N-n1-n2; prec=PREC; if (n1==n2 && n1==n3) /* n1 = n2 = n3 = m1 = N/3 */ { p1=gdivgs(M_star,m1); @@ -924,8 +989,8 @@ compute_M0(GEN M_star,long N) { /* n3 > N/3 >= n1 */ k = n2; kk = N-2*k; p2=gsub(M_star,gmulgs(X,k)); - p3=gmul(gpuigs(stoi(kk),kk),gpuigs(gsubgs(gmul(M_star,p2),kk*kk),k)); - pol=gsub(p3,gmul(gmul(gpuigs(stoi(k),k),gpuigs(X,k)),gpuigs(p2,N-k))); + p3=gmul(gpowgs(stoi(kk),kk),gpowgs(gsubgs(gmul(M_star,p2),kk*kk),k)); + pol=gsub(p3,gmul(gmul(gpowgs(stoi(k),k),gpowgs(X,k)),gpowgs(p2,N-k))); prec=gprecision(pol); if (!prec) prec = MEDDEFAULTPREC; r=roots(pol,prec); lr = lg(r); for (i=1; i2) @@ -961,7 +1026,7 @@ compute_M0(GEN M_star,long N) f2 = gadd(f2,gmulsg(n2,gmul(X,Z))); f2 = gadd(f2,gmulsg(n3,gmul(X,Y))); f2 = gsub(f2,gmul(M,gmul(X,gmul(Y,Z)))); - f3 = gsub(gmul(gpuigs(X,n1),gmul(gpuigs(Y,n2),gpuigs(Z,n3))), gun); + f3 = gsub(gmul(gpowgs(X,n1),gmul(gpowgs(Y,n2),gpowgs(Z,n3))), gun); /* f1 = n1 X + n2 Y + n3 Z - M */ /* f2 = n1 YZ + n2 XZ + n3 XY */ /* f3 = X^n1 Y^n2 Z^n3 - 1*/ @@ -1019,85 +1084,70 @@ compute_M0(GEN M_star,long N) if (!M0) avma = av; else M0 = gerepilecopy(av, M0); } } - for (i=1;i<=4;i++) delete_var(); + for (i=1;i<=4;i++) (void)delete_var(); return M0? M0: gzero; } static GEN lowerboundforregulator_i(GEN bnf) { - long N,R1,R2,RU,i,nbrootsofone,nbmin; - GEN rootsofone,nf,M0,M,m,col,T2,bound,minunit,newminunit; - GEN vecminim,colalg,p1,pol,y; + long N,R1,R2,RU,i; + GEN nf,M0,M,G,bound,minunit,newminunit; + GEN vecminim,p1,pol,y; GEN units = check_units(bnf,"bnfcertify"); - rootsofone=gmael(bnf,8,4); nbrootsofone=itos((GEN)rootsofone[1]); - nf=(GEN)bnf[7]; T2=gmael(nf,5,3); N=degpol(nf[1]); - R1=itos(gmael(nf,2,1)); R2=itos(gmael(nf,2,2)); RU=R1+R2-1; - if (RU==0) return gun; + nf = (GEN)bnf[7]; N = degpol(nf[1]); + nf_get_sign(nf, &R1, &R2); RU = R1+R2-1; + if (!RU) return gun; - units=algtobasis(bnf,units); minunit=qfeval(T2,(GEN)units[1]); + G = gmael(nf,5,2); + units = algtobasis(bnf,units); + minunit = gnorml2(gmul(G, (GEN)units[1])); /* T2(units[1]) */ for (i=2; i<=RU; i++) { - newminunit=qfeval(T2,(GEN)units[i]); - if (gcmp(newminunit,minunit)<0) minunit=newminunit; + newminunit = gnorml2(gmul(G, (GEN)units[i])); + if (gcmp(newminunit,minunit) < 0) minunit = newminunit; } - if (gcmpgs(minunit,1000000000)>0) return NULL; + if (gexpo(minunit) > 30) return NULL; - vecminim = minimforunits(nf,itos(gceil(minunit)),10000); + vecminim = minimforunits(nf, itos(gceil(minunit)), gmael3(bnf,8,4,1)); if (!vecminim) return NULL; - m=(GEN)vecminim[3]; nbmin=lg(m)-1; - if (nbmin==10000) return NULL; - bound=gaddgs(minunit,1); - for (i=1; i<=nbmin; i++) - { - col=(GEN)m[i]; colalg=basistoalg(nf,col); - if (!gcmp1(lift_intern(gpuigs(colalg,nbrootsofone)))) - { - newminunit=qfeval(T2,col); - if (gcmp(newminunit,bound)<0) bound=newminunit; - } - } - if (gcmp(bound,minunit)>0) err(talker,"bug in lowerboundforregulator"); + bound = (GEN)vecminim[3]; + i = gexpo(gsub(bound,minunit)); + if (i > -5) err(bugparier,"lowerboundforregulator"); + if (DEBUGLEVEL>1) { - fprintferr("M* = %Z\n",gprec_w(bound,3)); + fprintferr("M* = %Z\n", bound); if (DEBUGLEVEL>2) { - p1=polx[0]; pol=gaddgs(gsub(gpuigs(p1,N),gmul(bound,p1)),N-1); + p1=polx[0]; pol=gaddgs(gsub(gpowgs(p1,N),gmul(bound,p1)),N-1); p1 = roots(pol,DEFAULTPREC); if (N&1) y=greal((GEN)p1[3]); else y=greal((GEN)p1[2]); M0 = gmul2n(gmulsg(N*(N-1),gsqr(glog(y,DEFAULTPREC))),-2); fprintferr("pol = %Z\n",pol); fprintferr("old method: y = %Z, M0 = %Z\n",y,gprec_w(M0,3)); } - flusherr(); } M0 = compute_M0(bound,N); if (DEBUGLEVEL>1) { fprintferr("M0 = %Z\n",gprec_w(M0,3)); flusherr(); } - M = gmul2n(gdivgs(gdiv(gpuigs(M0,RU),hermiteconstant(RU)),N),R2); - if (gcmp(M,dbltor(0.04))<0) return NULL; + M = gmul2n(gdivgs(gdiv(gpowgs(M0,RU),hermiteconstant(RU)),N),R2); + if (gcmp(M, dbltor(0.04)) < 0) return NULL; M = gsqrt(M,DEFAULTPREC); if (DEBUGLEVEL>1) - { fprintferr("(lower bound for regulator) M = %Z\n",gprec_w(M,3)); - flusherr(); - } return M; } static GEN lowerboundforregulator(GEN bnf) { - long av = avma; + gpmem_t av = avma; GEN x = lowerboundforregulator_i(bnf); if (!x) { avma = av; x = regulatorbound(bnf); } return x; } -extern GEN to_Fp_simple(GEN x, GEN prh); -extern GEN Fp_PHlog(GEN a, GEN g, GEN p, GEN ord); - /* Compute a square matrix of rank length(beta) associated to a family * (P_i), 1<=i<=length(beta), of primes s.t. N(P_i) = 1 mod pp, and * (P_i,beta[j]) = 1 for all i,j */ @@ -1105,7 +1155,7 @@ static void primecertify(GEN bnf,GEN beta,long pp,GEN big) { long i,j,qq,nbcol,lb,nbqq,ra,N; - GEN nf,mat,mat1,qgen,decqq,newcol,Qh,Q,g,ord; + GEN nf,mat,mat1,qgen,decqq,newcol,Q,g,ord,modpr; ord = NULL; /* gcc -Wall */ nbcol = 0; nf = (GEN)bnf[7]; N = degpol(nf[1]); @@ -1126,11 +1176,11 @@ primecertify(GEN bnf,GEN beta,long pp,GEN big) g = lift_intern(gener(qgen)); /* primitive root */ ord = decomp(stoi(qq-1)); } - Qh = prime_to_ideal(nf,Q); + modpr = zkmodprinit(nf, Q); newcol = cgetg(lb+1,t_COL); for (j=1; j<=lb; j++) { - GEN t = to_Fp_simple((GEN)beta[j], Qh); + GEN t = to_Fp_simple(nf, (GEN)beta[j], modpr); newcol[j] = (long)Fp_PHlog(t,g,qgen,ord); } if (DEBUGLEVEL>3) @@ -1143,7 +1193,7 @@ primecertify(GEN bnf,GEN beta,long pp,GEN big) mat1 = concatsp(mat,newcol); ra = rank(mat1); if (ra==nbcol) continue; - if (DEBUGLEVEL>2) fprintferr(" new rank: %ld\n\n",ra); + if (DEBUGLEVEL>2) fprintferr(" new rank: %ld\n",ra); if (++nbcol == lb) return; mat = mat1; } @@ -1153,7 +1203,7 @@ primecertify(GEN bnf,GEN beta,long pp,GEN big) static void check_prime(long p, GEN bnf, GEN cyc, GEN cycgen, GEN fu, GEN mu, GEN big) { - ulong av = avma; + gpmem_t av = avma; long i,b, lc = lg(cyc), w = itos((GEN)mu[1]), lf = lg(fu); GEN beta = cgetg(lf+lc, t_VEC); @@ -1178,16 +1228,16 @@ check_prime(long p, GEN bnf, GEN cyc, GEN cycgen, GEN long certifybuchall(GEN bnf) { - ulong av = avma; + gpmem_t av = avma; long nbgen,i,j,p,N,R1,R2,R,bound; GEN big,nf,reg,rootsofone,funits,gen,p1,gbound,cycgen,cyc; byteptr delta = diffptr; bnf = checkbnf(bnf); nf = (GEN)bnf[7]; N=degpol(nf[1]); if (N==1) return 1; - R1=itos(gmael(nf,2,1)); R2=itos(gmael(nf,2,2)); R=R1+R2-1; + nf_get_sign(nf, &R1, &R2); R = R1+R2-1; funits = check_units(bnf,"bnfcertify"); - testprime(bnf, zimmertbound(N,R2,absi((GEN)nf[3]))); + testprimes(bnf, zimmertbound(N,R2,absi((GEN)nf[3]))); reg = gmael(bnf,8,2); cyc = gmael3(bnf,8,1,2); nbgen = lg(cyc)-1; gen = gmael3(bnf,8,1,3); rootsofone = gmael(bnf,8,4); @@ -1224,8 +1274,10 @@ certifybuchall(GEN bnf) rootsofone = dummycopy(rootsofone); rootsofone[2] = (long)algtobasis(nf, (GEN)rootsofone[2]); - for (p = *delta++; p <= bound; p += *delta++) + for (p = *delta++; p <= bound; ) { check_prime(p,bnf,cyc,cycgen,funits,rootsofone,big); + NEXT_PRIME_VIADIFF(p, delta); + } if (nbgen) { @@ -1266,7 +1318,7 @@ imageofgroup0(GEN gen,GEN bnr,GEN H) static GEN imageofgroup(GEN gen,GEN bnr,GEN H) { - ulong av = avma; + gpmem_t av = avma; return gerepileupto(av,imageofgroup0(gen,bnr,H)); } @@ -1327,18 +1379,22 @@ bnrisconductor(GEN arg0,GEN arg1,GEN arg2) return itos(conductor(bnr,sub,-1)); } +GEN +isprincipalray_init(GEN bnf, GEN x) +{ + GEN z = cgetg(3,t_VEC); + z[2] = (long)quick_isprincipalgen(bnf, x); + z[1] = (long)x; return z; +} + /* special for isprincipalrayall */ static GEN getgen(GEN bnf, GEN gen) { long i,l = lg(gen); - GEN p1, g = cgetg(l, t_VEC); + GEN g = cgetg(l, t_VEC); for (i=1; i=0)? itos((GEN)ex[k]): 1; for (j=1; j<=ep; j++) { - mod[1] = (long)idealdivexact(nf,ideal,pr); + mod[1] = (long)idealdivpowprime(nf,ideal,pr,gun); clhss = orderofquotient(bnf,mod,H,gen); if (!egalii(clhss,clhray)) break; if (all < 0) { avma = av; return gzero; } @@ -1414,22 +1470,21 @@ conductor(GEN bnr, GEN H, long all) /* etant donne un bnr et un polynome relatif, trouve le groupe des normes correspondant a l'extension relative en supposant qu'elle est abelienne - et que le module donnant bnr est multiple du conducteur. Verifie que - l'extension est bien abelienne (sous GRH) si rnf != NULL, dans ce cas - rnf est le rnf de l'extension relative. */ -static GEN -rnfnormgroup0(GEN bnr, GEN polrel, GEN rnf) + et que le module donnant bnr est multiple du conducteur. */ +GEN +rnfnormgroup(GEN bnr, GEN polrel) { - long av=avma,i,j,reldeg,sizemat,p,pmax,nfac,k; - GEN bnf,polreldisc,discnf,nf,raycl,group,detgroup,fa,greldeg; - GEN contreld,primreld,reldisc,famo,ep,fac,col,p1,bd,upnf; - byteptr d = diffptr + 1; /* start at p = 2 */ + long i, j, reldeg, sizemat, p, nfac, k; + gpmem_t av = avma; + GEN bnf,index,discnf,nf,raycl,group,detgroup,fa,greldeg; + GEN famo,ep,fac,col; + byteptr d = diffptr; checkbnr(bnr); bnf=(GEN)bnr[1]; raycl=(GEN)bnr[5]; nf=(GEN)bnf[7]; polrel = fix_relative_pol(nf,polrel,1); if (typ(polrel)!=t_POL) err(typeer,"rnfnormgroup"); - reldeg=degpol(polrel); + reldeg = degpol(polrel); /* reldeg-th powers are in norm group */ greldeg = stoi(reldeg); group = diagonal(gmod((GEN)raycl[2], greldeg)); @@ -1437,124 +1492,95 @@ rnfnormgroup0(GEN bnr, GEN polrel, GEN rnf) if (!signe(gcoeff(group,i,i))) coeff(group,i,i) = (long)greldeg; detgroup = dethnf_i(group); k = cmpis(detgroup,reldeg); - if (k<0) - { - if (rnf) return NULL; + if (k < 0) err(talker,"not an Abelian extension in rnfnormgroup?"); - } - if (!rnf && !k) return gerepilecopy(av, group); + if (!k) return gerepilecopy(av, group); - polreldisc=discsr(polrel); - - if (rnf) - { - reldisc=gmael(rnf,3,1); - upnf=nfinit0(gmael(rnf,11,1),1,DEFAULTPREC); - } - else - { - reldisc = idealhermite(nf,polreldisc); - upnf = NULL; - } - - reldisc = idealmul(nf, reldisc, gmael3(bnr,2,1,1)); - contreld= content(reldisc); - primreld= gcmp1(contreld)? reldisc: gdiv(reldisc, contreld); - discnf = (GEN)nf[3]; - k = degpol(nf[1]); - bd = gmulsg(k, glog(absi(discnf), DEFAULTPREC)); - bd = gadd(bd,glog(mpabs(det(reldisc)),DEFAULTPREC)); - p1 = dbltor(reldeg * k * 2.5 + 5); - bd = gfloor(gsqr(gadd(gmulsg(4,bd),p1))); - - pmax = is_bigint(bd)? 0: itos(bd); - if (rnf) - { - if (DEBUGLEVEL) fprintferr("rnfnormgroup: bound for primes = %Z\n", bd); - if (!pmax) err(warner,"rnfnormgroup: prime bound too large, can't certify"); - } + index = (GEN)nf[4]; sizemat=lg(group)-1; - for (p=2; !pmax || p < pmax; p += *d++) + for (p=0 ;;) { long oldf = -1, lfa; /* If all pr are unramified and have the same residue degree, p =prod pr * and including last pr^f or p^f is the same, but the last isprincipal * is much easier! oldf is used to track this */ - if (!*d) err(primer1); - if (!smodis(contreld,p)) continue; /* all pr|p ramified */ + NEXT_PRIME_VIADIFF_CHECK(p,d); + if (!smodis(index, p)) continue; /* can't be treated efficiently */ - fa = primedec(nf,stoi(p)); lfa = lg(fa)-1; - + fa = primedec(nf, stoi(p)); lfa = lg(fa)-1; for (i=1; i<=lfa; i++) { - GEN pr = (GEN)fa[i]; + GEN pr = (GEN)fa[i], pp, T, polr; + GEN modpr = nf_to_ff_init(nf, &pr, &T, &pp); long f; + + polr = modprX(polrel, nf, modpr); + /* if pr (probably) ramified, we have to use all (non-ram) P | pr */ + if (!FqX_is_squarefree(polr, T,pp)) { oldf = 0; continue; } + + famo = FqX_factor(polr, T, pp); + fac = (GEN)famo[1]; f = degpol((GEN)fac[1]); + ep = (GEN)famo[2]; nfac = lg(ep)-1; /* check decomposition of pr has Galois type */ - if (element_val(nf,polreldisc,pr) != 0) + for (j=1; j<=nfac; j++) { - /* if pr ramified, we will have to use all (non-ram) P | pr */ - if (idealval(nf,primreld,pr)!=0) { oldf = 0; continue; } - - famo=idealfactor(upnf,rnfidealup(rnf,pr)); - ep=(GEN)famo[2]; - fac=(GEN)famo[1]; - nfac=lg(ep)-1; - f = itos(gmael(fac,1,4)); - for (j=1; j<=nfac; j++) - { - if (!gcmp1((GEN)ep[j])) err(bugparier,"rnfnormgroup"); - if (itos(gmael(fac,j,4)) != f) - { - if (rnf) return NULL; - err(talker,"non Galois extension in rnfnormgroup"); - } - } + if (!gcmp1((GEN)ep[j])) err(bugparier,"rnfnormgroup"); + if (degpol(fac[j]) != f) + err(talker,"non Galois extension in rnfnormgroup"); } - else - { - famo=nffactormod(nf,polrel,pr); - ep=(GEN)famo[2]; - fac=(GEN)famo[1]; - nfac=lg(ep)-1; - f = degpol((GEN)fac[1]); - for (j=1; j<=nfac; j++) - { - if (!gcmp1((GEN)ep[j])) err(bugparier,"rnfnormgroup"); - if (degpol(fac[j]) != f) - { - if (rnf) return NULL; - err(talker,"non Galois extension in rnfnormgroup"); - } - } - } if (oldf < 0) oldf = f; else if (oldf != f) oldf = 0; if (f == reldeg) continue; /* reldeg-th powers already included */ if (oldf && i == lfa && !smodis(discnf, p)) pr = stoi(p); /* pr^f = N P, P | pr, hence is in norm group */ - col = gmulsg(f, isprincipalrayall(bnr,pr,nf_REGULAR)); + col = gmulsg(f, isprincipalrayall(bnr,pr,0)); group = hnf(concatsp(group, col)); detgroup = dethnf_i(group); k = cmpis(detgroup,reldeg); if (k < 0) - { - if (rnf) return NULL; err(talker,"not an Abelian extension in rnfnormgroup"); - } - if (!rnf && !k) { cgiv(detgroup); return gerepileupto(av,group); } + if (!k) { cgiv(detgroup); return gerepileupto(av,group); } } } if (k>0) err(bugparier,"rnfnormgroup"); cgiv(detgroup); return gerepileupto(av,group); } -GEN -rnfnormgroup(GEN bnr, GEN polrel) +static int +rnf_is_abelian(GEN nf, GEN pol) { - return rnfnormgroup0(bnr,polrel,NULL); + GEN ro, rores, nfL, L, mod, d; + long i,j, l; + + nf = checknf(nf); + L = rnfequation(nf,pol); + mod = dummycopy(L); setvarn(mod, varn(nf[1])); + nfL = _initalg(mod, nf_PARTIALFACT, DEFAULTPREC); + ro = nfroots(nfL, L); + l = lg(ro)-1; + if (l != degpol(pol)) return 0; + if (isprime(stoi(l))) return 1; + ro = Q_remove_denom(ro, &d); + if (!d) rores = ro; + else + { + rores = cgetg(l+1, t_VEC); + for (i=1; i<=l; i++) + rores[i] = (long)rescale_pol((GEN)ro[i], d); + } + /* assume roots are sorted by increasing degree */ + for (i=1; i2) timer2(); + if (DEBUGLEVEL>2) (void)timer2(); bnf = checkbnf(bnf); flbou=0; nf = (GEN)bnf[7]; r1 = nf_get_r1(nf); degk = degpol(nf[1]); @@ -2219,7 +2236,7 @@ discrayabslistarchintern(GEN bnf, GEN arch, long bound if (bound > (long)maxprime()) err(primer1); for (p[2]=0; p[2]<=bound; ) { - p[2] += *ptdif++; + NEXT_PRIME_VIADIFF(p[2], ptdif); if (!flbou && p[2]>sqbou) { if (DEBUGLEVEL>1) fprintferr("\nStarting rayclassno computations\n"); @@ -2387,10 +2404,10 @@ discrayabslistarchintern(GEN bnf, GEN arch, long bound if (!allarch && nba) { p1 = (GEN)primedec(nf,gprime)[ffs%degk+1]; - ideal = idealmul(nf,ideal,idealpow(nf,p1,(GEN)ex[k])); + ideal = idealmulpowprime(nf,ideal,p1,(GEN)ex[k]); } S=0; clhss=0; - normi = ii; normps= itos(gpuigs(gprime,resp)); + normi = ii; normps= itos(gpowgs(gprime,resp)); for (j=1; j<=ep; j++) { GEN fad, fad1, fad2; @@ -2485,78 +2502,82 @@ GEN discrayabslistarchsquare(GEN bnf, GEN arch, long bound) { return discrayabslistarchintern(bnf,arch,bound, -1); } -static GEN -computehuv(GEN bnr,GEN id, GEN arch) +/* Let bnr1, bnr2 be such that mod(bnr2) | mod(bnr1), compute the + matrix of the surjective map Cl(bnr1) ->> Cl(bnr2) */ +GEN +bnrGetSurj(GEN bnr1, GEN bnr2) { - long i,nbgen, av = avma; - GEN bnf,bnrnew,listgen,P,U,DC; - GEN newmod=cgetg(3,t_VEC); - newmod[1]=(long)id; - newmod[2]=(long)arch; + long nbg, i; + GEN gen, M; - bnf=(GEN)bnr[1]; - bnrnew=buchrayall(bnf,newmod,nf_INIT); - listgen=gmael(bnr,5,3); nbgen=lg(listgen); - P=cgetg(nbgen,t_MAT); - for (i=1; i