Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

Testing latest pari + WASM + node.js... and it works?! Wow.

28479 views
License: GPL3
ubuntu2004
1
/* Copyright (C) 2000 The PARI group.
2
3
This file is part of the PARI/GP package.
4
5
PARI/GP is free software; you can redistribute it and/or modify it under the
6
terms of the GNU General Public License as published by the Free Software
7
Foundation; either version 2 of the License, or (at your option) any later
8
version. It is distributed in the hope that it will be useful, but WITHOUT
9
ANY WARRANTY WHATSOEVER.
10
11
Check the License for details. You should have received a copy of it, along
12
with the package; see the file 'COPYING'. If not, write to the Free Software
13
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14
15
/*******************************************************************/
16
/* RNFISNORM */
17
/* (Adapted from Denis Simon's original implementation) */
18
/*******************************************************************/
19
#include "pari.h"
20
#include "paripriv.h"
21
22
static void
23
p_append(GEN p, hashtable *H, hashtable *H2)
24
{
25
ulong h = H->hash(p);
26
hashentry *e = hash_search2(H, (void*)p, h);
27
if (!e)
28
{
29
hash_insert2(H, (void*)p, NULL, h);
30
if (H2) hash_insert2(H2, (void*)p, NULL, h);
31
}
32
}
33
34
/* N a t_INT */
35
static void
36
Zfa_append(GEN N, hashtable *H, hashtable *H2)
37
{
38
if (!is_pm1(N))
39
{
40
GEN v = gel(absZ_factor(N),1);
41
long i, l = lg(v);
42
for (i=1; i<l; i++) p_append(gel(v,i), H, H2);
43
}
44
}
45
/* N a t_INT or t_FRAC or ideal in HNF*/
46
static void
47
fa_append(GEN N, hashtable *H, hashtable *H2)
48
{
49
switch(typ(N))
50
{
51
case t_INT:
52
Zfa_append(N,H,H2);
53
break;
54
case t_FRAC:
55
Zfa_append(gel(N,1),H,H2);
56
Zfa_append(gel(N,2),H,H2);
57
break;
58
default: /*t_MAT*/
59
Zfa_append(gcoeff(N,1,1),H,H2);
60
break;
61
}
62
}
63
64
/* apply lift(rnfeltup) to all coeffs, without rnf structure */
65
static GEN
66
nfX_eltup(GEN nf, GEN rnfeq, GEN x)
67
{
68
long i, l;
69
GEN y = cgetg_copy(x, &l), zknf = nf_nfzk(nf, rnfeq);
70
for (i=2; i<l; i++) gel(y,i) = nfeltup(nf, gel(x,i), zknf);
71
y[1] = x[1]; return y;
72
}
73
74
static hashtable *
75
hash_create_INT(ulong s)
76
{ return hash_create(s, (ulong(*)(void*))&hash_GEN,
77
(int(*)(void*,void*))&equalii, 1); }
78
GEN
79
rnfisnorminit(GEN T, GEN R, int galois)
80
{
81
pari_sp av = avma;
82
long i, l, dR;
83
GEN S, gen, cyc, bnf, nf, nfabs, rnfeq, bnfabs, k, polabs;
84
GEN y = cgetg(9, t_VEC);
85
hashtable *H = hash_create_INT(100UL);
86
87
if (galois < 0 || galois > 2) pari_err_FLAG("rnfisnorminit");
88
T = get_bnfpol(T, &bnf, &nf);
89
if (!bnf) bnf = Buchall(nf? nf: T, nf_FORCE, DEFAULTPREC);
90
if (!nf) nf = bnf_get_nf(bnf);
91
92
R = get_bnfpol(R, &bnfabs, &nfabs);
93
if (!gequal1(leading_coeff(R))) pari_err_IMPL("non monic relative equation");
94
dR = degpol(R);
95
if (dR <= 2) galois = 1;
96
97
R = RgX_nffix("rnfisnorminit", T, R, 1);
98
if (nf_get_degree(nf) == 1) /* over Q */
99
rnfeq = mkvec5(R,gen_0,gen_0,T,R);
100
else if (galois == 2) /* needs eltup+abstorel */
101
rnfeq = nf_rnfeq(nf, R);
102
else /* needs abstorel */
103
rnfeq = nf_rnfeqsimple(nf, R);
104
polabs = gel(rnfeq,1);
105
k = gel(rnfeq,3);
106
if (!bnfabs || !gequal0(k))
107
bnfabs = Buchall(polabs, nf_FORCE, nf_get_prec(nf));
108
if (!nfabs) nfabs = bnf_get_nf(bnfabs);
109
110
if (galois == 2)
111
{
112
GEN P = polabs==R? leafcopy(R): nfX_eltup(nf, rnfeq, R);
113
setvarn(P, fetch_var_higher());
114
galois = !!nfroots_if_split(&nfabs, P);
115
(void)delete_var();
116
}
117
118
cyc = bnf_get_cyc(bnfabs);
119
gen = bnf_get_gen(bnfabs); l = lg(cyc);
120
for(i=1; i<l; i++)
121
{
122
GEN g = gel(gen,i);
123
if (ugcdiu(gel(cyc,i), dR) == 1) break;
124
Zfa_append(gcoeff(g,1,1), H, NULL);
125
}
126
if (!galois)
127
{
128
GEN Ndiscrel = diviiexact(nf_get_disc(nfabs), powiu(nf_get_disc(nf), dR));
129
Zfa_append(Ndiscrel, H, NULL);
130
}
131
S = hash_keys(H); settyp(S,t_VEC);
132
gel(y,1) = bnf;
133
gel(y,2) = bnfabs;
134
gel(y,3) = R;
135
gel(y,4) = rnfeq;
136
gel(y,5) = S;
137
gel(y,6) = nf_pV_to_prV(nf, S);
138
gel(y,7) = nf_pV_to_prV(nfabs, S);
139
gel(y,8) = stoi(galois); return gerepilecopy(av, y);
140
}
141
142
/* T as output by rnfisnorminit
143
* if flag=0 assume extension is Galois (==> answer is unconditional)
144
* if flag>0 add to S all primes dividing p <= flag
145
* if flag<0 add to S all primes dividing abs(flag)
146
147
* answer is a vector v = [a,b] such that
148
* x = N(a)*b and x is a norm iff b = 1 [assuming S large enough] */
149
GEN
150
rnfisnorm(GEN T, GEN x, long flag)
151
{
152
pari_sp av = avma;
153
GEN bnf, rel, R, rnfeq, nfpol;
154
GEN nf, aux, H, U, Y, M, A, bnfS, sunitrel, futu, S, S1, S2, Sx;
155
long L, i, itu;
156
hashtable *H0, *H2;
157
if (typ(T) != t_VEC || lg(T) != 9)
158
pari_err_TYPE("rnfisnorm [please apply rnfisnorminit()]", T);
159
bnf = gel(T,1);
160
rel = gel(T,2);
161
bnf = checkbnf(bnf);
162
rel = checkbnf(rel);
163
nf = bnf_get_nf(bnf);
164
x = nf_to_scalar_or_alg(nf,x);
165
if (gequal0(x)) { set_avma(av); return mkvec2(gen_0, gen_1); }
166
if (gequal1(x)) { set_avma(av); return mkvec2(gen_1, gen_1); }
167
R = gel(T,3);
168
rnfeq = gel(T,4);
169
if (gequalm1(x) && odd(degpol(R)))
170
{ set_avma(av); return mkvec2(gen_m1, gen_1); }
171
172
/* build set T of ideals involved in the solutions */
173
nfpol = nf_get_pol(nf);
174
S = gel(T,5);
175
H0 = hash_create_INT(100UL);
176
H2 = hash_create_INT(100UL);
177
L = lg(S);
178
for (i = 1; i < L; i++) p_append(gel(S,i),H0,NULL);
179
S1 = gel(T,6);
180
S2 = gel(T,7);
181
if (flag > 0)
182
{
183
forprime_t T;
184
ulong p;
185
u_forprime_init(&T, 2, flag);
186
while ((p = u_forprime_next(&T))) p_append(utoipos(p), H0,H2);
187
}
188
else if (flag < 0)
189
Zfa_append(utoipos(-flag),H0,H2);
190
/* overkill: prime ideals dividing x would be enough */
191
A = idealnumden(nf, x);
192
fa_append(gel(A,1), H0,H2);
193
fa_append(gel(A,2), H0,H2);
194
Sx = hash_keys(H2); L = lg(Sx);
195
if (L > 1)
196
{ /* new primes */
197
settyp(Sx, t_VEC);
198
S1 = shallowconcat(S1, nf_pV_to_prV(nf, Sx));
199
S2 = shallowconcat(S2, nf_pV_to_prV(rel, Sx));
200
}
201
202
/* computation on T-units */
203
futu = shallowconcat(bnf_get_fu(rel), bnf_get_tuU(rel));
204
bnfS = bnfsunit(bnf,S1,LOWDEFAULTPREC);
205
sunitrel = shallowconcat(futu, gel(bnfsunit(rel,S2,LOWDEFAULTPREC), 1));
206
207
A = lift_shallow(bnfissunit(bnf,bnfS,x));
208
L = lg(sunitrel);
209
itu = lg(nf_get_roots(nf))-1; /* index of torsion unit in bnfsunit(nf) output */
210
M = cgetg(L+1,t_MAT);
211
for (i=1; i<L; i++)
212
{
213
GEN u = eltabstorel(rnfeq, gel(sunitrel,i));
214
gel(sunitrel,i) = u;
215
u = bnfissunit(bnf,bnfS, gnorm(u));
216
if (lg(u) == 1) pari_err_BUG("rnfisnorm");
217
gel(u,itu) = lift_shallow(gel(u,itu)); /* lift root of 1 part */
218
gel(M,i) = u;
219
}
220
aux = zerocol(lg(A)-1); gel(aux,itu) = utoipos( bnf_get_tuN(rel) );
221
gel(M,L) = aux;
222
H = ZM_hnfall(M, &U, 2);
223
Y = RgM_RgC_mul(U, inverseimage(H,A));
224
/* Y: sols of MY = A over Q */
225
setlg(Y, L);
226
aux = factorback2(sunitrel, gfloor(Y));
227
x = mkpolmod(x,nfpol);
228
if (!gequal1(aux)) x = gdiv(x, gnorm(aux));
229
x = lift_if_rational(x);
230
if (typ(aux) == t_POLMOD && degpol(nfpol) == 1)
231
gel(aux,2) = lift_if_rational(gel(aux,2));
232
return gerepilecopy(av, mkvec2(aux, x));
233
}
234
235
GEN
236
bnfisnorm(GEN bnf, GEN x, long flag)
237
{
238
pari_sp av = avma;
239
GEN T = rnfisnorminit(pol_x(fetch_var()), bnf, flag == 0? 1: 2);
240
GEN r = rnfisnorm(T, x, flag == 1? 0: flag);
241
(void)delete_var();
242
return gerepileupto(av,r);
243
}
244
245