Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2016 The PARI group.12This file is part of the PARI/GP package.34PARI/GP is free software; you can redistribute it and/or modify it under the5terms of the GNU General Public License as published by the Free Software6Foundation; either version 2 of the License, or (at your option) any later7version. It is distributed in the hope that it will be useful, but WITHOUT8ANY WARRANTY WHATSOEVER.910Check the License for details. You should have received a copy of it, along11with the package; see the file 'COPYING'. If not, write to the Free Software12Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */1314#include "pari.h"15#include "paripriv.h"16/*******************************************************************/17/* LOGARITHMIC CLASS GROUP */18/*******************************************************************/19/* min(v, v(Log_p Norm_{F_\p/Q_p}(x))) */20static long21vlognorm(GEN nf, GEN T, GEN x, GEN p, long v)22{23GEN a = nf_to_scalar_or_alg(nf, x);24GEN N = RgXQ_norm(a, T);25if (typ(N) != t_PADIC) N = cvtop(N, p, v);26return minss(v, valp( Qp_log(N) ));27}28/* K number field, pr a maximal ideal, let K_pr be the attached local29* field, K_pr = Q_p[X] / (T), T irreducible. Return \tilde{e}(K_pr/Q_p) */30static long31etilde(GEN nf, GEN pr, GEN T)32{33GEN gp = pr_get_p(pr);34ulong e = pr_get_e(pr);35long v, voo, vmin, p, k;3637if (!u_pval(e, gp))38{39v = u_pval(pr_get_f(pr), gp);40return itou( mului(e, powiu(gp, v)) );41}42nf = checknf(nf);43p = itou(gp);44k = e / (p-1) + 1;45/* log Norm_{F_P/Q_p} (1 + P^k) = Tr(P^k) = p^[(k + v(Diff))/ e] Z_p */46voo = (k + idealval(nf, nf_get_diff(nf), pr)) / e;47vmin = vlognorm(nf, T, pr_get_gen(pr), gp, voo);48if (k > 1)49{50GEN U = idealprincipalunits(nf, pr, k);51GEN gen = abgrp_get_gen(U), cyc = abgrp_get_cyc(U);52long i, l = lg(cyc);53for (i = 1; i < l; i++)54{55if (voo - Z_lval(gel(cyc,i), p) >= vmin) break;56vmin = vlognorm(nf, T, gel(gen,i), gp, vmin);57}58}59v = u_lval(degpol(T), p) + (p == 2UL? 2 : 1) - vmin;60(void)u_lvalrem(e, p, &e);61return e * upowuu(p,v);62}63static long64ftilde_from_e(GEN pr, long e) { return pr_get_e(pr) * pr_get_f(pr) / e; }65static long66ftilde(GEN K, GEN pr, GEN T) { return ftilde_from_e(pr, etilde(K,pr, T)); }6768static long69get_ZpX_index(GEN K, GEN pr, GEN T)70{71GEN p, pi;72long j, l = lg(T);73if (l == 2) return 1;74p = pr_get_p(pr); pi = nf_to_scalar_or_alg(K, pr_get_gen(pr));75for (j = 1; j < l; j++)76{77GEN t = gel(T,j);78if (t && gvaluation(RgXQ_norm(pi, t), p)) return j;79}80return 0;81}8283/* Given a number field K and a prime p, return84* S = places of K above p [primedec]85* R = corresponding p-adic factors of K.pol (mod p^k), in the same order */86static GEN87padicfact(GEN K, GEN S, long k)88{89GEN R, p = pr_get_p(gel(S,1));90GEN T = gel(factorpadic(nf_get_pol(K), p, k), 1);91long l, i;92S = idealprimedec(K, p);93R = cgetg_copy(S, &l);94for (i = 1; i < l; i++)95{96long j = get_ZpX_index(K, gel(S,i), T);97gel(R,i) = gel(T,j);98gel(T,j) = NULL;99}100return R;101}102103/* K a bnf, compute Cl'(K) = ell-Sylow of Cl(K) / (places above ell).104* Return [D, u, R0, U0, ordS]105* - D: cyclic factors for Cl'(K)106* - u: generators of cyclic factors (all coprime to ell)107* - R0: subgroup isprincipal(<S>) (divides K.cyc)108* - U0: generators of R0 are of the form S . U0109* - ordS[i] = order of S[i] in CL(K) */110static GEN111CL_prime(GEN K, GEN ell, GEN Sell)112{113GEN g, ordS, R0, U0, U, D, u, cyc = bnf_get_cyc(K);114long i, l, lD, lS = lg(Sell);115116g = leafcopy(bnf_get_gen(K));117l = lg(g);118for (i = 1; i < l; i++)119{120GEN A = gel(g,i), a = gcoeff(A,1,1);121long v = Z_pvalrem(a, ell, &a);122if (v) gel(g,i) = hnfmodid(A, a); /* make coprime to ell */123}124R0 = cgetg(lS, t_MAT);125ordS = cgetg(lS, t_VEC);126for (i = 1; i < lS; i++)127{128gel(R0,i) = isprincipal(K, gel(Sell,i));129gel(ordS,i) = charorder(cyc, gel(R0,i)); /* order of Sell[i] */130}131R0 = shallowconcat(R0, diagonal_shallow(cyc));132/* R0 = subgroup generated by S in Cl(K) [ divides diagonal(K.cyc) ]*/133R0 = ZM_hnfall(R0, &U0, 2); /* [S | cyc] * U0 = R0 in HNF */134D = ZM_snfall(R0, &U,NULL);135D = RgM_diagonal_shallow(D);136lD = lg(D);137u = ZM_inv(U, NULL); settyp(u, t_VEC);138for (i = 1; i < lD; i++) gel(u,i) = idealfactorback(K,g,gel(u,i),1);139setlg(U0, l);140U0 = rowslice(U0,1,lS-1); /* restrict to 'S' part */141return mkvec5(D, u, R0, U0, ordS);142}143144static GEN145ell1(GEN ell) { return equaliu(ell,2)? utoipos(5): addiu(ell,1); }146147/* log N_{F_P/Q_p}(x) */148static GEN149vtilde_i(GEN K, GEN x, GEN T, GEN ell, long prec)150{151GEN N, cx;152if (typ(x) != t_POL) x = nf_to_scalar_or_alg(K, x);153if (typ(x) != t_POL) { cx = x; N = NULL; }154else155{156x = Q_primitive_part(x,&cx);157N = resultant(RgX_rem(x,T), T);158N = cvtop(N,ell,prec);159}160if (cx)161{162(void)Q_pvalrem(cx, ell, &cx);163if (!isint1(cx))164{165cx = gpowgs(cvtop(cx,ell,prec), degpol(T));166N = N? gmul(N, cx): cx;167}168}169return N? Qp_log(N): gen_0;170}171static GEN172vecvtilde_i(GEN K, GEN x, GEN T, GEN ell, long prec)173{ pari_APPLY_same(vtilde_i(K, gel(x,i), T, ell, prec)); }174static GEN175vtilde(GEN K, GEN x, GEN T, GEN deg, GEN ell, long prec)176{177pari_sp av;178GEN v, G, E;179if (typ(x) != t_MAT) return gdiv(vtilde_i(K,x,T,ell,prec), deg);180G = gel(x,1);181E = gel(x,2); av = avma; v = vecvtilde_i(K,G,T,ell,prec);182return gerepileupto(av, gdiv(RgV_dotproduct(E, v), deg));183}184185/* v[i] = deg S[i] mod p^prec */186static GEN187get_vdegS(GEN Ftilde, GEN ell, long prec)188{189long i, l = lg(Ftilde);190GEN v = cgetg(l, t_VEC), degell = Qp_log( cvtop(ell1(ell), ell, prec) );191for (i = 1; i < l; i++) gel(v,i) = gmulsg(Ftilde[i], degell);192return v;193}194/* K a bnf. Compute kernel \tilde{Cl}_K(ell); return cyclic factors.195* Set *pM to (vtilde_S[i](US[j]))_{i,j} */196static GEN197CL_tilde(GEN K, GEN US, GEN ell, GEN T, long imin, GEN vdegS,198GEN *pM, long prec)199{200long i, j, k, lD, l = lg(T), lU = lg(US);201GEN D, M, ellk;202203/* p = P^e: \tilde{Cl}(l) = (1) */204if (l == 2) { *pM = cgetg(1, t_MAT); return cgetg(1, t_VEC); }205M = cgetg(lU, t_MAT);206for (j = 1; j < lU; j++)207{208GEN c = cgetg(l, t_COL), a = gel(US,j);209for (i = 1; i < l; i++)210gel(c,i) = vtilde(K, a, gel(T,i), gel(vdegS,i), ell, prec);211gel(M,j) = c;212}213k = padicprec(M, ell); ellk = powiu(ell, k);214*pM = M = gmod(M, ellk);215M = ZM_hnfmodid(rowsplice(M, imin), ellk);216D = matsnf0(M, 4); lD = lg(D);217if (lD > 1 && Z_pval(gel(D,1), ell) >= k) return NULL;218return D;219}220221/* [L:K] = ell^k; return 1 if L/K is locally cyclotomic at ell, 0 otherwise */222long223rnfislocalcyclo(GEN rnf)224{225pari_sp av = avma;226GEN K, L, S, SK, TK, SLs, SL2, TL, ell;227ulong ll;228long i, j, k, lk, lSK;229checkrnf(rnf);230lk = rnf_get_degree(rnf);231if (lk == 1) return 1;232k = uisprimepower(lk, &ll);233if (!k) pari_err_IMPL("rnfislocalcyclo for non-l-extensions");234ell = utoi(ll);235K = rnf_get_nf(rnf);236L = rnf_build_nfabs(rnf, nf_get_prec(K));237S = rnfidealprimedec(rnf, ell);238SK = gel(S,1);239SLs = gel(S,2);240SL2 = shallowconcat1(SLs);241TK = padicfact(K, SK, 100); lSK = lg(SK);242TL = padicfact(L, SL2, 100);243for (i = 1; i < lSK; i++)244{245long eK = etilde(K, gel(SK,i), gel(TK,i));246GEN SL = gel(SLs,i);247long lSL = lg(SL);248for (j = 1; j < lSL; j++)249{250long iS = gen_search(SL2, gel(SL,j), (void*)&cmp_prime_over_p,251&cmp_nodata);252long eL = etilde(L, gel(SL,j), gel(TL,iS));253if (dvdui(eL/eK, ell)) return gc_long(av,0);254}255};256return gc_long(av,1);257}258259#if 0260/* Return 1 if L/Q is locally cyclotomic at ell */261static int262islocalcycloQ(GEN L, GEN ell)263{264GEN SL = idealprimedec(L,ell), TL;265long i, lSL = lg(SL);266TL = padicfact(L, SL, 100);267for (i = 1; i < lSL; i++)268{269long eL = etilde(L, gel(SL,i), gel(TL,i));270if (dvdui(eL,ell)) return 0;271}272return 1;273}274#endif275276/* true nf, pr a prid */277static long278nfislocalpower_i(GEN nf, GEN pr, GEN a, GEN n)279{280long v, e, t;281GEN p, G, L;282a = nf_to_scalar_or_basis(nf,a);283if (!signe(n)) return isint1(a);284v = nfvalrem(nf, a, pr, &a); if (!dvdsi(v, n)) return 0;285p = pr_get_p(pr);286v = Z_pvalrem(n, p, &n);287if (!equali1(n))288{289GEN T, modpr = zk_to_Fq_init(nf, &pr, &T, &p);290GEN ap = nf_to_Fq(nf, a, modpr);291if (!Fq_ispower(ap, n, T, p)) return 0;292}293if (!v) return 1;294e = pr_get_e(pr);295if (v == 1) /* optimal formula */296t = itos( divii(mului(e,p), subiu(p,1)) ) + 1;297else /* straight Hensel */298t = 2 * e * v + 1;299G = Idealstarprk(nf, pr, t, nf_INIT);300L = ideallogmod(nf, a, G, powiu(p, v));301return ZV_equal0(L) || ZV_pval(L, p) >= v;302}303long304nfislocalpower(GEN nf, GEN pr, GEN a, GEN n)305{306pari_sp av = avma;307if (typ(n) != t_INT) pari_err_TYPE("nfislocalpower",n);308nf = checknf(nf); checkprid(pr);309return gc_long(av, nfislocalpower_i(nf, pr, a, n));310}311312/* v_ell( exponent(D) ) */313static long314ellexpo(GEN D, GEN ell) { return lg(D) == 1? 0: Z_pval(gel(D,1), ell); }315316static GEN317ellsylow(GEN cyc, GEN ell)318{319long i, l;320GEN d = cgetg_copy(cyc, &l);321for (i = 1; i < l; i++)322{323GEN c = gel(cyc,i), a;324if (!Z_pvalrem(c, ell, &a)) break;325gel(d,i) = diviiexact(c, a);326}327setlg(d, i); return d;328}329330static long331vnorm_x(GEN nf, GEN x, GEN ell)332{333x = nf_to_scalar_or_alg(nf,x);334if (typ(x) != t_POL) return 0;335x = Q_primpart(x);336return Q_pval(nfnorm(nf,x), ell);337}338static long339vtilde_prec_x(GEN nf, GEN x, GEN ell)340{341long i, l, v;342GEN G;343if (typ(x) != t_MAT) return vnorm_x(nf,x,ell);344G = gel(x,1); l = lg(G); v = 0;345for (i = 1; i < l; i++) v = maxss(v, vnorm_x(nf,gel(G,i),ell));346return v;347}348/* upper bound for \delta(vec): estimate loss of accuracy when evaluating349* \tilde{v} on the vec[i] */350static long351vtilde_prec(GEN nf, GEN vec, GEN ell)352{353long v0 = 0, i, l = lg(vec);354for (i = 1; i < l; i++)355v0 = maxss(v0, vtilde_prec_x(nf, gel(vec,i), ell));356return 3 + v0 + z_pval(nf_get_degree(nf), ell);357}358static GEN359get_Ftilde(GEN nf, GEN S, GEN T, GEN ell, long *pimin)360{361long j, lS = lg(S), vmin = lS;362GEN Ftilde = cgetg(lS, t_VECSMALL);363*pimin = 1;364for (j = 1; j < lS; j++)365{366long f = ftilde(nf, gel(S,j), gel(T,j)), v = z_pval(f, ell);367Ftilde[j] = f; if (v < vmin) { vmin = v; *pimin = j; }368}369return Ftilde;370}371static GEN372bnflog_i(GEN bnf, GEN ell)373{374long prec0, prec;375GEN nf, US, vdegS, S, T, M, CLp, CLt, Ftilde, vtG, ellk;376GEN D, Ap, cycAp, fu;377long imin, i, j, lvAp;378379bnf = checkbnf(bnf); nf = bnf_get_nf(bnf);380S = idealprimedec(nf, ell);381US = sunits_mod_units(bnf, S);382prec0 = maxss(30, vtilde_prec(nf, US, ell));383if (!(fu = bnf_build_cheapfu(bnf)) && !(fu = bnf_compactfu(bnf)))384bnf_build_units(bnf);385US = shallowconcat(fu, US);386settyp(US, t_COL);387T = padicfact(nf, S, prec0);388Ftilde = get_Ftilde(nf, S, T, ell, &imin);389CLp = CL_prime(bnf, ell, S);390cycAp = gel(CLp,1);391Ap = gel(CLp,2);392for(;;)393{394vdegS = get_vdegS(Ftilde, ell, prec0);395CLt = CL_tilde(nf, US, ell, T, imin, vdegS, &vtG, prec0);396if (CLt) break;397prec0 <<= 1;398T = padicfact(nf, S, prec0);399}400prec = ellexpo(cycAp, ell) + ellexpo(CLt,ell) + 1;401if (prec == 1) return mkvec3(cgetg(1,t_VEC), cgetg(1,t_VEC), cgetg(1,t_VEC));402403ellk = powiu(ell, prec);404lvAp = lg(Ap);405if (lvAp > 1)406{407long lS = lg(S);408GEN Kcyc = bnf_get_cyc(bnf);409GEN C = zeromatcopy(lvAp-1, lS-1);410GEN Rell = gel(CLp,3), Uell = gel(CLp,4), ordS = gel(CLp,5);411for (i = 1; i < lvAp; i++)412{413GEN a, b, bi, A = gel(Ap,i), d = gel(cycAp,i);414bi = isprincipal(bnf, A);415a = vecmodii(ZC_Z_mul(bi,d), Kcyc);416/* a in subgroup generated by S = Rell; hence b integral */417b = hnf_invimage(Rell, a);418b = vecmodii(ZM_ZC_mul(Uell, ZC_neg(b)), ordS);419A = mkvec2(A, trivial_fact());420A = idealpowred(nf, A, d);421/* find a principal representative of A_i^cycA_i up to elements of S */422a = isprincipalfact(bnf,gel(A,1),S,b,nf_GENMAT|nf_FORCE);423if (!gequal0(gel(a,1))) pari_err_BUG("bnflog");424a = famat_mul_shallow(gel(A,2), gel(a,2)); /* principal part */425if (lg(a) == 1) continue;426for (j = 1; j < lS; j++)427gcoeff(C,i,j) = vtilde(nf, a, gel(T,j), gel(vdegS,j), ell, prec0);428}429C = gmod(gneg(C),ellk);430C = shallowtrans(C);431M = mkmat2(mkcol2(diagonal_shallow(cycAp), C), mkcol2(gen_0, vtG));432M = shallowmatconcat(M); /* relation matrix */433}434else435M = vtG;436M = ZM_hnfmodid(M, ellk);437D = matsnf0(M, 4);438if (lg(D) == 1 || !dvdii(gel(D,1), ellk))439pari_err_BUG("bnflog [missing Z_l component]");440D = vecslice(D,2,lg(D)-1);441return mkvec3(D, CLt, ellsylow(cycAp, ell));442}443GEN444bnflog(GEN bnf, GEN ell)445{446pari_sp av = avma;447return gerepilecopy(av, bnflog_i(bnf, ell));448}449450GEN451bnflogef(GEN nf, GEN pr)452{453pari_sp av = avma;454long e, f, ef;455GEN p;456checkprid(pr); p = pr_get_p(pr);457nf = checknf(nf);458e = pr_get_e(pr);459f = pr_get_f(pr); ef = e*f;460if (u_pval(ef, p))461{462GEN T = gel(factorpadic(nf_get_pol(nf), p, 100), 1);463long j = get_ZpX_index(nf, pr, T);464e = etilde(nf, pr, gel(T,j));465f = ef / e;466}467set_avma(av); return mkvec2s(e,f);468}469470GEN471bnflogdegree(GEN nf, GEN A, GEN ell)472{473pari_sp av = avma;474GEN AZ, A0Z, NA0;475long vAZ;476477if (typ(ell) != t_INT) pari_err_TYPE("bnflogdegree", ell);478nf = checknf(nf);479A = idealhnf(nf, A);480AZ = gcoeff(A,1,1);481vAZ = Z_pvalrem(AZ, ell, &A0Z);482if (is_pm1(A0Z))483NA0 = gen_1;484else485(void)Z_pvalrem(idealnorm(nf,A), ell, &NA0);486if (vAZ)487{488GEN Aell = ZM_hnfmodid(A, powiu(ell,vAZ));489GEN S = idealprimedec(nf, ell), T;490long l, i, s = 0;491T = padicfact(nf, S, 100);492l = lg(S);493for (i = 1; i < l; i++)494{495GEN P = gel(S,i);496long v = idealval(nf, Aell, P);497if (v) s += v * ftilde(nf, P, gel(T,i));498}499if (s) NA0 = gmul(NA0, gpowgs(ell1(ell), s));500}501return gerepileupto(av, NA0);502}503504505