Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2000 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/*******************************************************************/15/* RNFISNORM */16/* (Adapted from Denis Simon's original implementation) */17/*******************************************************************/18#include "pari.h"19#include "paripriv.h"2021static void22p_append(GEN p, hashtable *H, hashtable *H2)23{24ulong h = H->hash(p);25hashentry *e = hash_search2(H, (void*)p, h);26if (!e)27{28hash_insert2(H, (void*)p, NULL, h);29if (H2) hash_insert2(H2, (void*)p, NULL, h);30}31}3233/* N a t_INT */34static void35Zfa_append(GEN N, hashtable *H, hashtable *H2)36{37if (!is_pm1(N))38{39GEN v = gel(absZ_factor(N),1);40long i, l = lg(v);41for (i=1; i<l; i++) p_append(gel(v,i), H, H2);42}43}44/* N a t_INT or t_FRAC or ideal in HNF*/45static void46fa_append(GEN N, hashtable *H, hashtable *H2)47{48switch(typ(N))49{50case t_INT:51Zfa_append(N,H,H2);52break;53case t_FRAC:54Zfa_append(gel(N,1),H,H2);55Zfa_append(gel(N,2),H,H2);56break;57default: /*t_MAT*/58Zfa_append(gcoeff(N,1,1),H,H2);59break;60}61}6263/* apply lift(rnfeltup) to all coeffs, without rnf structure */64static GEN65nfX_eltup(GEN nf, GEN rnfeq, GEN x)66{67long i, l;68GEN y = cgetg_copy(x, &l), zknf = nf_nfzk(nf, rnfeq);69for (i=2; i<l; i++) gel(y,i) = nfeltup(nf, gel(x,i), zknf);70y[1] = x[1]; return y;71}7273static hashtable *74hash_create_INT(ulong s)75{ return hash_create(s, (ulong(*)(void*))&hash_GEN,76(int(*)(void*,void*))&equalii, 1); }77GEN78rnfisnorminit(GEN T, GEN R, int galois)79{80pari_sp av = avma;81long i, l, dR;82GEN S, gen, cyc, bnf, nf, nfabs, rnfeq, bnfabs, k, polabs;83GEN y = cgetg(9, t_VEC);84hashtable *H = hash_create_INT(100UL);8586if (galois < 0 || galois > 2) pari_err_FLAG("rnfisnorminit");87T = get_bnfpol(T, &bnf, &nf);88if (!bnf) bnf = Buchall(nf? nf: T, nf_FORCE, DEFAULTPREC);89if (!nf) nf = bnf_get_nf(bnf);9091R = get_bnfpol(R, &bnfabs, &nfabs);92if (!gequal1(leading_coeff(R))) pari_err_IMPL("non monic relative equation");93dR = degpol(R);94if (dR <= 2) galois = 1;9596R = RgX_nffix("rnfisnorminit", T, R, 1);97if (nf_get_degree(nf) == 1) /* over Q */98rnfeq = mkvec5(R,gen_0,gen_0,T,R);99else if (galois == 2) /* needs eltup+abstorel */100rnfeq = nf_rnfeq(nf, R);101else /* needs abstorel */102rnfeq = nf_rnfeqsimple(nf, R);103polabs = gel(rnfeq,1);104k = gel(rnfeq,3);105if (!bnfabs || !gequal0(k))106bnfabs = Buchall(polabs, nf_FORCE, nf_get_prec(nf));107if (!nfabs) nfabs = bnf_get_nf(bnfabs);108109if (galois == 2)110{111GEN P = polabs==R? leafcopy(R): nfX_eltup(nf, rnfeq, R);112setvarn(P, fetch_var_higher());113galois = !!nfroots_if_split(&nfabs, P);114(void)delete_var();115}116117cyc = bnf_get_cyc(bnfabs);118gen = bnf_get_gen(bnfabs); l = lg(cyc);119for(i=1; i<l; i++)120{121GEN g = gel(gen,i);122if (ugcdiu(gel(cyc,i), dR) == 1) break;123Zfa_append(gcoeff(g,1,1), H, NULL);124}125if (!galois)126{127GEN Ndiscrel = diviiexact(nf_get_disc(nfabs), powiu(nf_get_disc(nf), dR));128Zfa_append(Ndiscrel, H, NULL);129}130S = hash_keys(H); settyp(S,t_VEC);131gel(y,1) = bnf;132gel(y,2) = bnfabs;133gel(y,3) = R;134gel(y,4) = rnfeq;135gel(y,5) = S;136gel(y,6) = nf_pV_to_prV(nf, S);137gel(y,7) = nf_pV_to_prV(nfabs, S);138gel(y,8) = stoi(galois); return gerepilecopy(av, y);139}140141/* T as output by rnfisnorminit142* if flag=0 assume extension is Galois (==> answer is unconditional)143* if flag>0 add to S all primes dividing p <= flag144* if flag<0 add to S all primes dividing abs(flag)145146* answer is a vector v = [a,b] such that147* x = N(a)*b and x is a norm iff b = 1 [assuming S large enough] */148GEN149rnfisnorm(GEN T, GEN x, long flag)150{151pari_sp av = avma;152GEN bnf, rel, R, rnfeq, nfpol;153GEN nf, aux, H, U, Y, M, A, bnfS, sunitrel, futu, S, S1, S2, Sx;154long L, i, itu;155hashtable *H0, *H2;156if (typ(T) != t_VEC || lg(T) != 9)157pari_err_TYPE("rnfisnorm [please apply rnfisnorminit()]", T);158bnf = gel(T,1);159rel = gel(T,2);160bnf = checkbnf(bnf);161rel = checkbnf(rel);162nf = bnf_get_nf(bnf);163x = nf_to_scalar_or_alg(nf,x);164if (gequal0(x)) { set_avma(av); return mkvec2(gen_0, gen_1); }165if (gequal1(x)) { set_avma(av); return mkvec2(gen_1, gen_1); }166R = gel(T,3);167rnfeq = gel(T,4);168if (gequalm1(x) && odd(degpol(R)))169{ set_avma(av); return mkvec2(gen_m1, gen_1); }170171/* build set T of ideals involved in the solutions */172nfpol = nf_get_pol(nf);173S = gel(T,5);174H0 = hash_create_INT(100UL);175H2 = hash_create_INT(100UL);176L = lg(S);177for (i = 1; i < L; i++) p_append(gel(S,i),H0,NULL);178S1 = gel(T,6);179S2 = gel(T,7);180if (flag > 0)181{182forprime_t T;183ulong p;184u_forprime_init(&T, 2, flag);185while ((p = u_forprime_next(&T))) p_append(utoipos(p), H0,H2);186}187else if (flag < 0)188Zfa_append(utoipos(-flag),H0,H2);189/* overkill: prime ideals dividing x would be enough */190A = idealnumden(nf, x);191fa_append(gel(A,1), H0,H2);192fa_append(gel(A,2), H0,H2);193Sx = hash_keys(H2); L = lg(Sx);194if (L > 1)195{ /* new primes */196settyp(Sx, t_VEC);197S1 = shallowconcat(S1, nf_pV_to_prV(nf, Sx));198S2 = shallowconcat(S2, nf_pV_to_prV(rel, Sx));199}200201/* computation on T-units */202futu = shallowconcat(bnf_get_fu(rel), bnf_get_tuU(rel));203bnfS = bnfsunit(bnf,S1,LOWDEFAULTPREC);204sunitrel = shallowconcat(futu, gel(bnfsunit(rel,S2,LOWDEFAULTPREC), 1));205206A = lift_shallow(bnfissunit(bnf,bnfS,x));207L = lg(sunitrel);208itu = lg(nf_get_roots(nf))-1; /* index of torsion unit in bnfsunit(nf) output */209M = cgetg(L+1,t_MAT);210for (i=1; i<L; i++)211{212GEN u = eltabstorel(rnfeq, gel(sunitrel,i));213gel(sunitrel,i) = u;214u = bnfissunit(bnf,bnfS, gnorm(u));215if (lg(u) == 1) pari_err_BUG("rnfisnorm");216gel(u,itu) = lift_shallow(gel(u,itu)); /* lift root of 1 part */217gel(M,i) = u;218}219aux = zerocol(lg(A)-1); gel(aux,itu) = utoipos( bnf_get_tuN(rel) );220gel(M,L) = aux;221H = ZM_hnfall(M, &U, 2);222Y = RgM_RgC_mul(U, inverseimage(H,A));223/* Y: sols of MY = A over Q */224setlg(Y, L);225aux = factorback2(sunitrel, gfloor(Y));226x = mkpolmod(x,nfpol);227if (!gequal1(aux)) x = gdiv(x, gnorm(aux));228x = lift_if_rational(x);229if (typ(aux) == t_POLMOD && degpol(nfpol) == 1)230gel(aux,2) = lift_if_rational(gel(aux,2));231return gerepilecopy(av, mkvec2(aux, x));232}233234GEN235bnfisnorm(GEN bnf, GEN x, long flag)236{237pari_sp av = avma;238GEN T = rnfisnorminit(pol_x(fetch_var()), bnf, flag == 0? 1: 2);239GEN r = rnfisnorm(T, x, flag == 1? 0: flag);240(void)delete_var();241return gerepileupto(av,r);242}243244245