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
/* */
17
/* RNF STRUCTURE AND OPERATIONS */
18
/* */
19
/*******************************************************************/
20
#include "pari.h"
21
#include "paripriv.h"
22
23
#define DEBUGLEVEL DEBUGLEVEL_rnf
24
25
/* eq is an rnfeq; must return a t_POL */
26
GEN
27
eltreltoabs(GEN eq, GEN x)
28
{
29
GEN Pabs = gel(eq,1), a = gel(eq,2), k = gel(eq,3), T = gel(eq,4), b, s;
30
long i, v = varn(Pabs);
31
pari_sp av = avma;
32
33
if (varncmp(gvar(x), v) > 0) x = scalarpol(x,v);
34
x = RgX_nffix("eltreltoabs", T, x, 1);
35
/* Mod(X - k a, Pabs(X)) is a root of the relative polynomial */
36
if (signe(k))
37
x = RgXQX_translate(x, deg1pol_shallow(negi(k), gen_0, varn(T)), T);
38
b = pol_x(v);
39
s = gen_0;
40
for (i=lg(x)-1; i>1; i--)
41
{
42
GEN c = gel(x,i);
43
if (typ(c) == t_POL) c = RgX_RgXQ_eval(c, a, Pabs);
44
s = RgX_rem(gadd(c, gmul(b,s)), Pabs);
45
}
46
return gerepileupto(av, s);
47
}
48
GEN
49
rnfeltreltoabs(GEN rnf,GEN x)
50
{
51
const char *f = "rnfeltreltoabs";
52
GEN pol;
53
checkrnf(rnf);
54
pol = rnf_get_polabs(rnf);
55
switch(typ(x))
56
{
57
case t_INT: return icopy(x);
58
case t_FRAC: return gcopy(x);
59
case t_POLMOD:
60
if (RgX_equal_var(gel(x,1), pol))
61
{ /* already in 'abs' form, unless possibly if nf = Q */
62
if (rnf_get_nfdegree(rnf) == 1)
63
{
64
GEN y = gel(x,2);
65
pari_sp av = avma;
66
y = simplify_shallow(liftpol_shallow(y));
67
return gerepilecopy(av, mkpolmod(y, pol));
68
}
69
return gcopy(x);
70
}
71
x = polmod_nffix(f,rnf,x,0);
72
if (typ(x) == t_POLMOD) return rnfeltup(rnf,x);
73
retmkpolmod(eltreltoabs(rnf_get_map(rnf), x), ZX_copy(pol));
74
case t_POL:
75
if (varn(x) == rnf_get_nfvarn(rnf)) return rnfeltup(rnf,x);
76
retmkpolmod(eltreltoabs(rnf_get_map(rnf), x), ZX_copy(pol));
77
}
78
pari_err_TYPE(f,x);
79
return NULL;/*LCOV_EXCL_LINE*/
80
}
81
82
GEN
83
eltabstorel_lift(GEN rnfeq, GEN P)
84
{
85
GEN k, T = gel(rnfeq,4), R = gel(rnfeq,5);
86
if (is_scalar_t(typ(P))) return P;
87
k = gel(rnfeq,3);
88
P = lift_shallow(P);
89
if (signe(k))
90
P = RgXQX_translate(P, deg1pol_shallow(k, gen_0, varn(T)), T);
91
P = RgXQX_rem(P, R, T);
92
return QXQX_to_mod_shallow(P, T);
93
}
94
/* rnfeq = [pol,a,k,T,R], P a t_POL or scalar
95
* Return Mod(P(x + k Mod(y, T(y))), pol(x)) */
96
GEN
97
eltabstorel(GEN rnfeq, GEN P)
98
{
99
GEN T = gel(rnfeq,4), R = gel(rnfeq,5);
100
return mkpolmod(eltabstorel_lift(rnfeq,P), QXQX_to_mod_shallow(R,T));
101
}
102
GEN
103
rnfeltabstorel(GEN rnf,GEN x)
104
{
105
const char *f = "rnfeltabstorel";
106
pari_sp av = avma;
107
GEN pol, T, P, NF;
108
checkrnf(rnf);
109
T = rnf_get_nfpol(rnf);
110
P = rnf_get_pol(rnf);
111
pol = rnf_get_polabs(rnf);
112
switch(typ(x))
113
{
114
case t_INT: return icopy(x);
115
case t_FRAC: return gcopy(x);
116
case t_POLMOD:
117
if (RgX_equal_var(P, gel(x,1)))
118
{
119
x = polmod_nffix(f, rnf, x, 0);
120
P = QXQX_to_mod_shallow(P,T);
121
return gerepilecopy(av, mkpolmod(x,P));
122
}
123
if (RgX_equal_var(T, gel(x,1))) { x = Rg_nffix(f, T, x, 0); goto END; }
124
if (!RgX_equal_var(pol, gel(x,1))) pari_err_MODULUS(f, gel(x,1),pol);
125
x = gel(x,2); break;
126
case t_POL: break;
127
case t_COL:
128
NF = obj_check(rnf, rnf_NFABS);
129
if (!NF) pari_err_TYPE("rnfeltabstorel, apply nfinit(rnf)",x);
130
x = nf_to_scalar_or_alg(NF,x); break;
131
default:
132
pari_err_TYPE(f,x);
133
return NULL;/*LCOV_EXCL_LINE*/
134
}
135
switch(typ(x))
136
{
137
case t_INT: return icopy(x);
138
case t_FRAC: return gcopy(x);
139
case t_POL: break;
140
default: pari_err_TYPE(f, x);
141
}
142
RgX_check_QX(x,f);
143
if (varn(x) != varn(pol))
144
{
145
if (varn(x) == varn(T)) { x = Rg_nffix(f,T,x,0); goto END; }
146
pari_err_VAR(f, x,pol);
147
}
148
switch(lg(x))
149
{
150
case 2: set_avma(av); return gen_0;
151
case 3: return gerepilecopy(av, gel(x,2));
152
}
153
END:
154
return gerepilecopy(av, eltabstorel(rnf_get_map(rnf), x));
155
}
156
157
/* x a t_VEC of rnf elements in 'alg' form (t_POL). Assume maximal rank or 0 */
158
static GEN
159
modulereltoabs(GEN rnf, GEN x)
160
{
161
GEN W=gel(x,1), I=gel(x,2), rnfeq = rnf_get_map(rnf), polabs = gel(rnfeq,1);
162
long i, j, k, m, N = lg(W)-1;
163
GEN zknf, dzknf, M;
164
165
if (!N) return cgetg(1, t_VEC);
166
zknf = rnf_get_nfzk(rnf);
167
dzknf = gel(zknf,1);
168
m = rnf_get_nfdegree(rnf);
169
M = cgetg(N*m+1, t_VEC);
170
for (k=i=1; i<=N; i++)
171
{
172
GEN c0, cid, w = gel(W,i), id = gel(I,i);
173
174
if (lg(id) == 1) continue; /* must be a t_MAT */
175
id = Q_primitive_part(id, &cid);
176
w = Q_primitive_part(eltreltoabs(rnfeq,w), &c0);
177
c0 = div_content(mul_content(c0,cid), dzknf);
178
if (typ(id) == t_INT)
179
for (j=1; j<=m; j++)
180
{
181
GEN z = RgX_rem(gmul(w, gel(zknf,j)), polabs);
182
if (c0) z = RgX_Rg_mul(z, c0);
183
gel(M,k++) = z;
184
}
185
else
186
for (j=1; j<=m; j++)
187
{
188
GEN c, z = Q_primitive_part(RgV_RgC_mul(zknf,gel(id,j)), &c);
189
z = RgX_rem(gmul(w, z), polabs);
190
c = mul_content(c, c0); if (c) z = RgX_Rg_mul(z, c);
191
gel(M,k++) = z;
192
}
193
}
194
setlg(M, k); return M;
195
}
196
197
/* Z-basis for absolute maximal order: [NF.pol, NF.zk] */
198
GEN
199
rnf_zkabs(GEN rnf)
200
{
201
GEN d, v, M = modulereltoabs(rnf, rnf_get_zk(rnf));
202
GEN T = rnf_get_polabs(rnf);
203
long n = degpol(T);
204
M = Q_remove_denom(M, &d); /* t_VEC of t_POL */
205
if (d)
206
{
207
M = RgXV_to_RgM(M,n);
208
M = ZM_hnfmodall(M, d, hnf_MODID|hnf_CENTER);
209
M = RgM_Rg_div(M, d);
210
}
211
else
212
M = matid(n);
213
v = rnf_get_ramified_primes(rnf);
214
if (lg(v) == 1)
215
{
216
GEN D = gel(rnf_get_disc(rnf),1);
217
if (!isint1(D)) pari_err_TYPE("rnf_zkabs (old style rnf)", rnf);
218
}
219
v = shallowconcat(nf_get_ramified_primes(rnf_get_nf(rnf)), v);
220
return mkvec3(T, RgM_to_RgXV(M, varn(T)), ZV_sort_uniq(v));
221
}
222
223
static GEN
224
mknfabs(GEN rnf, long prec)
225
{
226
GEN NF;
227
if ((NF = obj_check(rnf,rnf_NFABS)))
228
{ if (nf_get_prec(NF) < prec) NF = nfnewprec_shallow(NF,prec); }
229
else
230
NF = nfinit(rnf_zkabs(rnf), prec);
231
return NF;
232
}
233
234
static GEN
235
mkupdown(GEN rnf)
236
{
237
GEN NF = obj_check(rnf, rnf_NFABS), M, zknf, dzknf;
238
long i, l;
239
zknf = rnf_get_nfzk(rnf);
240
dzknf = gel(zknf,1); if (gequal1(dzknf)) dzknf = NULL;
241
l = lg(zknf); M = cgetg(l, t_MAT);
242
gel(M,1) = vec_ei(nf_get_degree(NF), 1);
243
for (i = 2; i < l; i++)
244
{
245
GEN c = poltobasis(NF, gel(zknf,i));
246
if (dzknf) c = gdiv(c, dzknf);
247
gel(M,i) = c;
248
}
249
return Qevproj_init(M);
250
}
251
GEN
252
rnf_build_nfabs(GEN rnf, long prec)
253
{
254
GEN NF = obj_checkbuild_prec(rnf, rnf_NFABS, &mknfabs, &nf_get_prec, prec);
255
(void)obj_checkbuild(rnf, rnf_MAPS, &mkupdown);
256
return NF;
257
}
258
259
void
260
rnfcomplete(GEN rnf)
261
{ (void)rnf_build_nfabs(rnf, nf_get_prec(rnf_get_nf(rnf))); }
262
263
GEN
264
nf_nfzk(GEN nf, GEN rnfeq)
265
{
266
GEN pol = gel(rnfeq,1), a = gel(rnfeq,2);
267
return Q_primpart(QXV_QXQ_eval(nf_get_zkprimpart(nf), a, pol));
268
}
269
270
static GEN
271
rnfdisc_get_T_i(GEN P, GEN *lim)
272
{
273
*lim = NULL;
274
if (typ(P) == t_VEC && lg(P) == 3)
275
{
276
GEN L = gel(P,2);
277
long i, l;
278
*lim = L;
279
switch(typ(L))
280
{
281
case t_INT:
282
if (signe(L) <= 0) return NULL;
283
break;
284
case t_VEC: case t_COL:
285
l = lg(L);
286
for (i = 1; i < l; i++)
287
{
288
GEN p = gel(L,i);
289
if (typ(p) == t_INT)
290
{ if (signe(p) <= 0) return NULL; }
291
else checkprid(p);
292
}
293
break;
294
default: return NULL;
295
}
296
P = gel(P,1);
297
}
298
return (typ(P) == t_POL)? P: NULL;
299
}
300
/* true nf */
301
GEN
302
rnfdisc_get_T(GEN nf, GEN P, GEN *lim)
303
{
304
GEN T = rnfdisc_get_T_i(P, lim);
305
if (!T) pari_err_TYPE("rnfdisc",P);
306
return RgX_nffix("rnfdisc", nf_get_pol(nf), T, 1);
307
}
308
309
GEN
310
rnfpseudobasis(GEN nf, GEN pol)
311
{
312
pari_sp av = avma;
313
GEN D, z, lim;
314
nf = checknf(nf);
315
pol = rnfdisc_get_T(nf, pol, &lim);
316
z = rnfallbase(nf, pol, lim, NULL, &D, NULL, NULL);
317
return gerepilecopy(av, shallowconcat(z,D));
318
}
319
320
GEN
321
rnfinit0(GEN nf, GEN T, long flag)
322
{
323
pari_sp av = avma;
324
GEN lim, bas, D, f, B, DKP, rnfeq, rnf = obj_init(11, 2);
325
nf = checknf(nf);
326
T = rnfdisc_get_T(nf, T, &lim);
327
gel(rnf,11) = rnfeq = nf_rnfeq(nf,T);
328
gel(rnf,2) = nf_nfzk(nf, rnfeq);
329
bas = rnfallbase(nf, T, lim, rnf, &D, &f, &DKP);
330
B = matbasistoalg(nf,gel(bas,1));
331
gel(bas,1) = lift_if_rational( RgM_to_RgXV(B,varn(T)) );
332
gel(rnf,1) = T;
333
gel(rnf,3) = D;
334
gel(rnf,4) = f;
335
gel(rnf,5) = DKP;
336
gel(rnf,6) = cgetg(1, t_VEC); /* dummy */
337
gel(rnf,7) = bas;
338
gel(rnf,8) = lift_if_rational( RgM_inv_upper(B) );
339
gel(rnf,9) = typ(f) == t_INT? powiu(f, nf_get_degree(nf))
340
: RgM_det_triangular(f);
341
gel(rnf,10)= nf;
342
rnf = gerepilecopy(av, rnf);
343
if (flag) rnfcomplete(rnf);
344
return rnf;
345
}
346
GEN
347
rnfinit(GEN nf, GEN T) { return rnfinit0(nf,T,0); }
348
349
GEN
350
rnfeltup0(GEN rnf, GEN x, long flag)
351
{
352
pari_sp av = avma;
353
GEN zknf, nf, NF, POL;
354
long tx = typ(x);
355
checkrnf(rnf);
356
if (flag) rnfcomplete(rnf);
357
NF = obj_check(rnf,rnf_NFABS);
358
POL = rnf_get_polabs(rnf);
359
if (tx == t_POLMOD && RgX_equal_var(gel(x,1), POL))
360
{
361
if (flag) x = nf_to_scalar_or_basis(NF,x);
362
return gerepilecopy(av, x);
363
}
364
nf = rnf_get_nf(rnf);
365
if (NF && tx == t_COL && lg(x)-1 == degpol(POL) && nf_get_degree(rnf) > 1)
366
{
367
x = flag? nf_to_scalar_or_basis(NF,x)
368
: mkpolmod(nf_to_scalar_or_alg(NF,x), POL);
369
return gerepilecopy(av, x);
370
}
371
if (NF)
372
{
373
GEN d, proj;
374
x = nf_to_scalar_or_basis(nf, x);
375
if (typ(x) != t_COL) return gerepilecopy(av, x);
376
proj = obj_check(rnf,rnf_MAPS);
377
x = Q_remove_denom(x,&d);
378
x = ZM_ZC_mul(gel(proj,1), x);
379
if (d) x = gdiv(x,d);
380
if (!flag) x = basistoalg(NF,x);
381
}
382
else
383
{
384
zknf = rnf_get_nfzk(rnf);
385
x = nfeltup(nf, x, zknf);
386
if (typ(x) == t_POL) x = mkpolmod(x, POL);
387
}
388
return gerepilecopy(av, x);
389
}
390
GEN
391
rnfeltup(GEN rnf, GEN x) { return rnfeltup0(rnf,x,0); }
392
393
GEN
394
nfeltup(GEN nf, GEN x, GEN zknf)
395
{
396
GEN c, dzknf = gel(zknf,1);
397
x = nf_to_scalar_or_basis(nf, x);
398
if (typ(x) != t_COL) return x;
399
x = Q_primitive_part(x, &c);
400
if (!RgV_is_ZV(x)) pari_err_TYPE("rnfeltup", x);
401
if (gequal1(dzknf)) dzknf = NULL;
402
c = div_content(c, dzknf);
403
x = RgV_RgC_mul(zknf, x); if (c) x = RgX_Rg_mul(x, c);
404
return x;
405
}
406
407
static void
408
fail(const char *f, GEN x)
409
{ pari_err_DOMAIN(f,"element","not in", strtoGENstr("the base field"),x); }
410
/* x t_COL of length degabs */
411
static GEN
412
eltdown(GEN rnf, GEN x, long flag)
413
{
414
GEN z,y, d, proj = obj_check(rnf,rnf_MAPS);
415
GEN M= gel(proj,1), iM=gel(proj,2), diM=gel(proj,3), perm=gel(proj,4);
416
x = Q_remove_denom(x,&d);
417
if (!RgV_is_ZV(x)) pari_err_TYPE("rnfeltdown", x);
418
y = ZM_ZC_mul(iM, vecpermute(x, perm));
419
z = ZM_ZC_mul(M,y);
420
if (!isint1(diM)) z = ZC_Z_mul(z,diM);
421
if (!ZV_equal(z,x)) fail("rnfeltdown",x);
422
423
d = mul_denom(d, diM);
424
if (d) y = gdiv(y,d);
425
if (!flag) y = basistoalg(rnf_get_nf(rnf), y);
426
return y;
427
}
428
GEN
429
rnfeltdown0(GEN rnf, GEN x, long flag)
430
{
431
const char *f = "rnfeltdown";
432
pari_sp av = avma;
433
GEN z, T, NF, nf;
434
long v;
435
436
checkrnf(rnf);
437
NF = obj_check(rnf,rnf_NFABS);
438
nf = rnf_get_nf(rnf);
439
T = nf_get_pol(nf);
440
v = varn(T);
441
switch(typ(x))
442
{ /* directly belonging to base field ? */
443
case t_INT: return icopy(x);
444
case t_FRAC:return gcopy(x);
445
case t_POLMOD:
446
if (RgX_equal_var(gel(x,1), rnf_get_polabs(rnf)))
447
{
448
if (degpol(T) == 1)
449
{
450
x = simplify_shallow(liftpol_shallow(gel(x,2)));
451
if (typ(x) != t_POL) return gerepilecopy(av,x);
452
}
453
break;
454
}
455
x = polmod_nffix(f,rnf,x,0);
456
/* x was defined mod the relative polynomial & non constant => fail */
457
if (typ(x) == t_POL) fail(f,x);
458
if (flag) x = nf_to_scalar_or_basis(nf,x);
459
return gerepilecopy(av, x);
460
461
case t_POL:
462
if (varn(x) != v) break;
463
x = Rg_nffix(f,T,x,0);
464
if (flag) x = nf_to_scalar_or_basis(nf,x);
465
return gerepilecopy(av, x);
466
case t_COL:
467
{
468
long n = lg(x)-1;
469
if (n == degpol(T) && RgV_is_QV(x))
470
{
471
if (RgV_isscalar(x)) return gcopy(gel(x,1));
472
if (!flag) return gcopy(x);
473
return basistoalg(nf,x);
474
}
475
if (NF) break;
476
}
477
default: pari_err_TYPE(f, x);
478
}
479
/* x defined mod the absolute equation */
480
if (NF)
481
{
482
x = nf_to_scalar_or_basis(NF, x);
483
if (typ(x) == t_COL) x = eltdown(rnf,x,flag);
484
return gerepilecopy(av, x);
485
}
486
z = rnfeltabstorel(rnf,x);
487
switch(typ(z))
488
{
489
case t_INT:
490
case t_FRAC: return z;
491
}
492
/* typ(z) = t_POLMOD, varn of both components is rnf_get_varn(rnf) */
493
z = gel(z,2);
494
if (typ(z) == t_POL)
495
{
496
if (lg(z) != 3) fail(f,x);
497
z = gel(z,2);
498
}
499
return gerepilecopy(av, z);
500
}
501
GEN
502
rnfeltdown(GEN rnf, GEN x) { return rnfeltdown0(rnf,x,0); }
503
504
/* vector of rnf elt -> matrix of nf elts */
505
static GEN
506
rnfV_to_nfM(GEN rnf, GEN x)
507
{
508
long i, l = lg(x);
509
GEN y = cgetg(l, t_MAT);
510
for (i = 1; i < l; i++) gel(y,i) = rnfalgtobasis(rnf,gel(x,i));
511
return y;
512
}
513
514
static GEN
515
rnfprincipaltohnf(GEN rnf,GEN x)
516
{
517
pari_sp av = avma;
518
GEN bas = rnf_get_zk(rnf), nf = rnf_get_nf(rnf);
519
x = rnfbasistoalg(rnf,x);
520
x = gmul(x, gmodulo(gel(bas,1), rnf_get_pol(rnf)));
521
return gerepileupto(av, nfhnf(nf, mkvec2(rnfV_to_nfM(rnf,x), gel(bas,2))));
522
}
523
524
/* pseudo-basis for the 0 ideal */
525
static GEN
526
rnfideal0(void) { retmkvec2(cgetg(1,t_MAT),cgetg(1,t_VEC)); }
527
528
GEN
529
rnfidealhnf(GEN rnf, GEN x)
530
{
531
GEN z, nf, bas;
532
533
checkrnf(rnf); nf = rnf_get_nf(rnf);
534
switch(typ(x))
535
{
536
case t_INT: case t_FRAC:
537
if (isintzero(x)) return rnfideal0();
538
bas = rnf_get_zk(rnf); z = cgetg(3,t_VEC);
539
gel(z,1) = matid(rnf_get_degree(rnf));
540
gel(z,2) = gmul(x, gel(bas,2)); return z;
541
542
case t_VEC:
543
if (lg(x) == 3 && typ(gel(x,1)) == t_MAT) return nfhnf(nf, x);
544
case t_MAT:
545
return rnfidealabstorel(rnf, x);
546
547
case t_POLMOD: case t_POL: case t_COL:
548
return rnfprincipaltohnf(rnf,x);
549
}
550
pari_err_TYPE("rnfidealhnf",x);
551
return NULL; /* LCOV_EXCL_LINE */
552
}
553
554
static GEN
555
prodidnorm(GEN nf, GEN I)
556
{
557
long i, l = lg(I);
558
GEN z;
559
if (l == 1) return gen_1;
560
z = idealnorm(nf, gel(I,1));
561
for (i=2; i<l; i++) z = gmul(z, idealnorm(nf, gel(I,i)));
562
return z;
563
}
564
565
GEN
566
rnfidealnormrel(GEN rnf, GEN id)
567
{
568
pari_sp av = avma;
569
GEN nf, z = gel(rnfidealhnf(rnf,id), 2);
570
if (lg(z) == 1) return cgetg(1, t_MAT);
571
nf = rnf_get_nf(rnf); z = idealprod(nf, z);
572
return gerepileupto(av, idealmul(nf,z, rnf_get_index(rnf)));
573
}
574
575
GEN
576
rnfidealnormabs(GEN rnf, GEN id)
577
{
578
pari_sp av = avma;
579
GEN nf, z = gel(rnfidealhnf(rnf,id), 2);
580
if (lg(z) == 1) return gen_0;
581
nf = rnf_get_nf(rnf); z = prodidnorm(nf, z);
582
return gerepileupto(av, gmul(z, gel(rnf,9)));
583
}
584
585
static GEN
586
rnfidealreltoabs_i(GEN rnf, GEN x)
587
{
588
long i, l;
589
GEN w;
590
x = rnfidealhnf(rnf,x);
591
w = gel(x,1); l = lg(w); settyp(w, t_VEC);
592
for (i=1; i<l; i++) gel(w,i) = lift_shallow( rnfbasistoalg(rnf, gel(w,i)) );
593
return modulereltoabs(rnf, x);
594
}
595
GEN
596
rnfidealreltoabs(GEN rnf, GEN x)
597
{
598
pari_sp av = avma;
599
return gerepilecopy(av, rnfidealreltoabs_i(rnf,x));
600
}
601
GEN
602
rnfidealreltoabs0(GEN rnf, GEN x, long flag)
603
{
604
pari_sp av = avma;
605
long i, l;
606
GEN NF;
607
608
x = rnfidealreltoabs_i(rnf, x);
609
if (!flag) return gerepilecopy(av,x);
610
rnfcomplete(rnf);
611
NF = obj_check(rnf,rnf_NFABS);
612
l = lg(x); settyp(x, t_MAT);
613
for (i=1; i<l; i++) gel(x,i) = algtobasis(NF, gel(x,i));
614
return gerepileupto(av, idealhnf(NF,x));
615
}
616
617
GEN
618
rnfidealabstorel(GEN rnf, GEN x)
619
{
620
long n, N, j, tx = typ(x);
621
pari_sp av = avma;
622
GEN A, I, invbas;
623
624
checkrnf(rnf);
625
invbas = rnf_get_invzk(rnf);
626
if (tx != t_VEC && tx != t_MAT) pari_err_TYPE("rnfidealabstorel",x);
627
N = lg(x)-1;
628
if (N != rnf_get_absdegree(rnf))
629
{
630
if (!N) return rnfideal0();
631
pari_err_DIM("rnfidealabstorel");
632
}
633
n = rnf_get_degree(rnf);
634
A = cgetg(N+1,t_MAT);
635
I = cgetg(N+1,t_VEC);
636
for (j=1; j<=N; j++)
637
{
638
GEN t = lift_shallow( rnfeltabstorel(rnf, gel(x,j)) );
639
if (typ(t) == t_POL)
640
t = RgM_RgX_mul(invbas, t);
641
else
642
t = scalarcol_shallow(t, n);
643
gel(A,j) = t;
644
gel(I,j) = gen_1;
645
}
646
return gerepileupto(av, nfhnf(rnf_get_nf(rnf), mkvec2(A,I)));
647
}
648
649
GEN
650
rnfidealdown(GEN rnf,GEN x)
651
{
652
pari_sp av = avma;
653
GEN I;
654
if (typ(x) == t_MAT)
655
{
656
GEN d;
657
x = Q_remove_denom(x,&d);
658
if (RgM_is_ZM(x))
659
{
660
GEN NF = obj_check(rnf,rnf_NFABS);
661
if (NF)
662
{
663
GEN z, proj = obj_check(rnf,rnf_MAPS), ZK = gel(proj,1);
664
long i, lz, l;
665
x = idealhnf(NF,x);
666
if (lg(x) == 1) { set_avma(av); return cgetg(1,t_MAT); }
667
z = ZM_lll(shallowconcat(ZK,x), 0.99, LLL_KER);
668
lz = lg(z); l = lg(ZK);
669
for (i = 1; i < lz; i++) setlg(gel(z,i), l);
670
z = ZM_hnfmodid(z, gcoeff(x,1,1));
671
if (d) z = gdiv(z,d);
672
return gerepileupto(av, z);
673
}
674
}
675
}
676
x = rnfidealhnf(rnf,x); I = gel(x,2);
677
if (lg(I) == 1) { set_avma(av); return cgetg(1,t_MAT); }
678
return gerepilecopy(av, gel(I,1));
679
}
680
681
/* lift ideal x to the relative extension, returns a Z-basis */
682
GEN
683
rnfidealup(GEN rnf,GEN x)
684
{
685
pari_sp av = avma;
686
long i, n;
687
GEN nf, bas, bas2, I, x2, dx;
688
689
checkrnf(rnf); nf = rnf_get_nf(rnf);
690
n = rnf_get_degree(rnf);
691
bas = rnf_get_zk(rnf); bas2 = gel(bas,2);
692
693
(void)idealtyp(&x, &I); /* I is junk */
694
x = Q_remove_denom(x, &dx);
695
x2 = idealtwoelt(nf,x);
696
I = cgetg(n+1,t_VEC);
697
for (i=1; i<=n; i++)
698
{
699
GEN c = gel(bas2,i), d;
700
if (typ(c) == t_MAT)
701
{
702
c = Q_remove_denom(c,&d);
703
d = mul_denom(d, dx);
704
c = idealHNF_mul(nf,c,x2);
705
}
706
else
707
{
708
c = idealmul(nf,c,x);
709
d = dx;
710
}
711
if (d) c = gdiv(c,d);
712
gel(I,i) = c;
713
}
714
return gerepilecopy(av, modulereltoabs(rnf, mkvec2(gel(bas,1), I)));
715
}
716
GEN
717
rnfidealup0(GEN rnf,GEN x, long flag)
718
{
719
pari_sp av = avma;
720
GEN NF, nf, proj, d, x2;
721
722
if (!flag) return rnfidealup(rnf,x);
723
checkrnf(rnf); nf = rnf_get_nf(rnf);
724
rnfcomplete(rnf);
725
proj = obj_check(rnf,rnf_MAPS);
726
NF = obj_check(rnf,rnf_NFABS);
727
728
(void)idealtyp(&x, &d); /* d is junk */
729
x2 = idealtwoelt(nf,x);
730
x2 = Q_remove_denom(x2,&d);
731
if (typ(gel(x2,2)) == t_COL) gel(x2,2) = ZM_ZC_mul(gel(proj,1),gel(x2,2));
732
x2 = idealhnf_two(NF, x2);
733
if (d) x2 = gdiv(x2,d);
734
return gerepileupto(av, x2);
735
}
736
737
/* x a relative HNF => vector of 2 generators (relative polmods) */
738
GEN
739
rnfidealtwoelement(GEN rnf, GEN x)
740
{
741
pari_sp av = avma;
742
GEN y, cy, z, NF;
743
744
y = rnfidealreltoabs_i(rnf,x);
745
rnfcomplete(rnf);
746
NF = obj_check(rnf,rnf_NFABS);
747
y = matalgtobasis(NF, y); settyp(y, t_MAT);
748
y = Q_primitive_part(y, &cy);
749
y = ZM_hnf(y);
750
if (lg(y) == 1) { set_avma(av); return mkvec2(gen_0, gen_0); }
751
y = idealtwoelt(NF, y);
752
if (cy) y = RgV_Rg_mul(y, cy);
753
z = gel(y,2);
754
if (typ(z) == t_COL) z = rnfeltabstorel(rnf, nf_to_scalar_or_alg(NF, z));
755
return gerepilecopy(av, mkvec2(gel(y,1), z));
756
}
757
758
GEN
759
rnfidealmul(GEN rnf,GEN x,GEN y)
760
{
761
pari_sp av = avma;
762
GEN nf, z, x1, x2, p1, p2, bas;
763
764
y = rnfidealtwoelement(rnf,y);
765
if (isintzero(gel(y,1))) { set_avma(av); return rnfideal0(); }
766
nf = rnf_get_nf(rnf);
767
bas = rnf_get_zk(rnf);
768
x = rnfidealhnf(rnf,x);
769
x1 = gmodulo(gmul(gel(bas,1), matbasistoalg(nf,gel(x,1))), rnf_get_pol(rnf));
770
x2 = gel(x,2);
771
p1 = gmul(gel(y,1), gel(x,1));
772
p2 = rnfV_to_nfM(rnf, gmul(gel(y,2), x1));
773
z = mkvec2(shallowconcat(p1, p2), shallowconcat(x2, x2));
774
return gerepileupto(av, nfhnf(nf,z));
775
}
776
777
/* prK wrt NF ~ Q[x]/(polabs) */
778
static GEN
779
rnfidealprimedec_1(GEN rnf, GEN SL, GEN prK)
780
{
781
GEN v, piL, piK = pr_get_gen(prK);
782
long i, c, l;
783
if (pr_is_inert(prK)) return SL;
784
piL = rnfeltup0(rnf, piK, 1);
785
v = cgetg_copy(SL, &l);
786
for (i = c = 1; i < l; i++)
787
{
788
GEN P = gel(SL,i);
789
if (ZC_prdvd(piL, P)) gel(v,c++) = P;
790
}
791
setlg(v, c); return v;
792
}
793
GEN
794
rnfidealprimedec(GEN rnf, GEN pr)
795
{
796
pari_sp av = avma;
797
GEN p, z, NF, nf, SL;
798
checkrnf(rnf);
799
rnfcomplete(rnf);
800
NF = obj_check(rnf,rnf_NFABS);
801
nf = rnf_get_nf(rnf);
802
if (typ(pr) == t_INT) { p = pr; pr = NULL; }
803
else { checkprid(pr); p = pr_get_p(pr); }
804
SL = idealprimedec(NF, p);
805
if (pr) z = rnfidealprimedec_1(rnf, SL, pr);
806
else
807
{
808
GEN vK = idealprimedec(nf, p), vL;
809
long l = lg(vK), i;
810
vL = cgetg(l, t_VEC);
811
for (i = 1; i < l; i++) gel(vL,i) = rnfidealprimedec_1(rnf, SL, gel(vK,i));
812
z = mkvec2(vK, vL);
813
}
814
return gerepilecopy(av, z);
815
}
816
817
GEN
818
rnfidealfactor(GEN rnf, GEN x)
819
{
820
pari_sp av = avma;
821
GEN NF;
822
checkrnf(rnf);
823
rnfcomplete(rnf);
824
NF = obj_check(rnf,rnf_NFABS);
825
return gerepileupto(av, idealfactor(NF, rnfidealreltoabs0(rnf, x, 1)));
826
}
827
828
GEN
829
rnfequationall(GEN A, GEN B, long *pk, GEN *pLPRS)
830
{
831
long lA, lB;
832
GEN nf, C;
833
834
A = get_nfpol(A, &nf); lA = lg(A);
835
if (!nf) {
836
if (lA<=3) pari_err_CONSTPOL("rnfequation");
837
RgX_check_ZX(A,"rnfequation");
838
}
839
B = RgX_nffix("rnfequation", A,B,1); lB = lg(B);
840
if (lB<=3) pari_err_CONSTPOL("rnfequation");
841
B = Q_primpart(B);
842
843
if (!nfissquarefree(A,B))
844
pari_err_DOMAIN("rnfequation","issquarefree(B)","=",gen_0,B);
845
846
*pk = 0; C = ZX_ZXY_resultant_all(A, B, pk, pLPRS);
847
if (signe(leading_coeff(C)) < 0) C = ZX_neg(C);
848
*pk = -*pk; return Q_primpart(C);
849
}
850
851
GEN
852
rnfequation0(GEN A, GEN B, long flall)
853
{
854
pari_sp av = avma;
855
GEN LPRS, C;
856
long k;
857
858
C = rnfequationall(A, B, &k, flall? &LPRS: NULL);
859
if (flall)
860
{ /* a,b,c root of A,B,C = compositum, c = b + k a */
861
GEN a, mH0 = RgX_neg(gel(LPRS,1)), H1 = gel(LPRS,2);
862
a = QXQ_div(mH0, H1, C);
863
C = mkvec3(C, mkpolmod(a, C), stoi(k));
864
}
865
return gerepilecopy(av, C);
866
}
867
GEN
868
rnfequation(GEN nf, GEN pol) { return rnfequation0(nf,pol,0); }
869
GEN
870
rnfequation2(GEN nf, GEN pol) { return rnfequation0(nf,pol,1); }
871
GEN
872
nf_rnfeq(GEN nf, GEN R)
873
{
874
GEN pol, a, k, junk, eq;
875
R = liftpol_shallow(R);
876
eq = rnfequation2(nf, R);
877
pol = gel(eq,1);
878
a = gel(eq,2); if (typ(a) == t_POLMOD) a = gel(a,2);
879
k = gel(eq,3);
880
return mkvec5(pol,a,k,get_nfpol(nf, &junk),R);
881
}
882
/* only allow abstorel */
883
GEN
884
nf_rnfeqsimple(GEN nf, GEN R)
885
{
886
long sa;
887
GEN junk, pol;
888
R = liftpol_shallow(R);
889
pol = rnfequationall(nf, R, &sa, NULL);
890
return mkvec5(pol,gen_0/*dummy*/,stoi(sa),get_nfpol(nf, &junk),R);
891
}
892
893
/*******************************************************************/
894
/* */
895
/* RELATIVE LLL */
896
/* */
897
/*******************************************************************/
898
static GEN
899
nftau(long r1, GEN x)
900
{
901
long i, l = lg(x);
902
GEN s = r1? gel(x,1): gmul2n(real_i(gel(x,1)),1);
903
for (i=2; i<=r1; i++) s = gadd(s, gel(x,i));
904
for ( ; i < l; i++) s = gadd(s, gmul2n(real_i(gel(x,i)),1));
905
return s;
906
}
907
908
static GEN
909
initmat(long l)
910
{
911
GEN x = cgetg(l, t_MAT);
912
long i;
913
for (i = 1; i < l; i++) gel(x,i) = cgetg(l, t_COL);
914
return x;
915
}
916
917
static GEN
918
nftocomplex(GEN nf, GEN x)
919
{
920
GEN M = nf_get_M(nf);
921
x = nf_to_scalar_or_basis(nf,x);
922
if (typ(x) != t_COL) return const_col(nbrows(M), x);
923
return RgM_RgC_mul(M, x);
924
}
925
/* assume x a square t_MAT, return a t_VEC of embeddings of its columns */
926
static GEN
927
mattocomplex(GEN nf, GEN x)
928
{
929
long i,j, l = lg(x);
930
GEN v = cgetg(l, t_VEC);
931
for (j=1; j<l; j++)
932
{
933
GEN c = gel(x,j), b = cgetg(l, t_MAT);
934
for (i=1; i<l; i++) gel(b,i) = nftocomplex(nf, gel(c,i));
935
b = shallowtrans(b); settyp(b, t_COL);
936
gel(v,j) = b;
937
}
938
return v;
939
}
940
941
static GEN
942
nf_all_roots(GEN nf, GEN x, long prec)
943
{
944
long i, j, l = lg(x), ru = lg(nf_get_roots(nf));
945
GEN y = cgetg(l, t_POL), v, z;
946
947
x = RgX_to_nfX(nf, x);
948
y[1] = x[1];
949
for (i=2; i<l; i++) gel(y,i) = nftocomplex(nf, gel(x,i));
950
i = gprecision(y); if (i && i <= 3) return NULL;
951
952
v = cgetg(ru, t_VEC);
953
z = cgetg(l, t_POL); z[1] = x[1];
954
for (i=1; i<ru; i++)
955
{
956
for (j = 2; j < l; j++) gel(z,j) = gmael(y,j,i);
957
gel(v,i) = cleanroots(z, prec);
958
}
959
return v;
960
}
961
962
static GEN
963
rnfscal(GEN m, GEN x, GEN y)
964
{
965
long i, l = lg(m);
966
GEN z = cgetg(l, t_COL);
967
for (i = 1; i < l; i++)
968
gel(z,i) = gmul(conj_i(shallowtrans(gel(x,i))), gmul(gel(m,i), gel(y,i)));
969
return z;
970
}
971
972
/* x ideal in HNF */
973
static GEN
974
findmin(GEN nf, GEN x, GEN muf)
975
{
976
pari_sp av = avma;
977
long e;
978
GEN cx, y, m, M = nf_get_M(nf);
979
980
x = Q_primitive_part(x, &cx);
981
if (gequal1(gcoeff(x,1,1))) y = M;
982
else
983
{
984
GEN G = nf_get_G(nf);
985
m = lllfp(RgM_mul(G,x), 0.75, 0);
986
if (typ(m) != t_MAT)
987
{
988
x = ZM_lll(x, 0.75, LLL_INPLACE);
989
m = lllfp(RgM_mul(G,x), 0.75, 0);
990
if (typ(m) != t_MAT) pari_err_PREC("rnflllgram");
991
}
992
x = ZM_mul(x, m);
993
y = RgM_mul(M, x);
994
}
995
m = RgM_solve_realimag(y, muf);
996
if (!m) return NULL; /* precision problem */
997
if (cx) m = RgC_Rg_div(m, cx);
998
m = grndtoi(m, &e);
999
if (e >= 0) return NULL; /* precision problem */
1000
m = ZM_ZC_mul(x, m);
1001
if (cx) m = ZC_Q_mul(m, cx);
1002
return gerepileupto(av, m);
1003
}
1004
1005
static int
1006
RED(long k, long l, GEN U, GEN mu, GEN MC, GEN nf, GEN I, GEN *Ik_inv)
1007
{
1008
GEN x, xc, ideal;
1009
long i;
1010
1011
if (!*Ik_inv) *Ik_inv = idealinv(nf, gel(I,k));
1012
ideal = idealmul(nf,gel(I,l), *Ik_inv);
1013
x = findmin(nf, ideal, gcoeff(mu,k,l));
1014
if (!x) return 0;
1015
if (gequal0(x)) return 1;
1016
1017
xc = nftocomplex(nf,x);
1018
gel(MC,k) = gsub(gel(MC,k), vecmul(xc,gel(MC,l)));
1019
gel(U,k) = gsub(gel(U,k), gmul(coltoalg(nf,x), gel(U,l)));
1020
gcoeff(mu,k,l) = gsub(gcoeff(mu,k,l), xc);
1021
for (i=1; i<l; i++)
1022
gcoeff(mu,k,i) = gsub(gcoeff(mu,k,i), vecmul(xc,gcoeff(mu,l,i)));
1023
return 1;
1024
}
1025
1026
static int
1027
check_0(GEN B)
1028
{
1029
long i, l = lg(B);
1030
for (i = 1; i < l; i++)
1031
if (gsigne(gel(B,i)) <= 0) return 1;
1032
return 0;
1033
}
1034
1035
static int
1036
do_SWAP(GEN I, GEN MC, GEN MCS, GEN h, GEN mu, GEN B, long kmax, long k,
1037
const long alpha, long r1)
1038
{
1039
GEN p1, p2, muf, mufc, Bf, temp;
1040
long i, j;
1041
1042
p1 = nftau(r1, gadd(gel(B,k),
1043
gmul(gnorml2(gcoeff(mu,k,k-1)), gel(B,k-1))));
1044
p2 = nftau(r1, gel(B,k-1));
1045
if (gcmp(gmulsg(alpha,p1), gmulsg(alpha-1,p2)) > 0) return 0;
1046
1047
swap(gel(MC,k-1),gel(MC,k));
1048
swap(gel(h,k-1), gel(h,k));
1049
swap(gel(I,k-1), gel(I,k));
1050
for (j=1; j<=k-2; j++) swap(gcoeff(mu,k-1,j),gcoeff(mu,k,j));
1051
muf = gcoeff(mu,k,k-1);
1052
mufc = conj_i(muf);
1053
Bf = gadd(gel(B,k), vecmul(real_i(vecmul(muf,mufc)), gel(B,k-1)));
1054
if (check_0(Bf)) return 1; /* precision problem */
1055
1056
p1 = vecdiv(gel(B,k-1),Bf);
1057
gcoeff(mu,k,k-1) = vecmul(mufc,p1);
1058
temp = gel(MCS,k-1);
1059
gel(MCS,k-1) = gadd(gel(MCS,k), vecmul(muf,gel(MCS,k-1)));
1060
gel(MCS,k) = gsub(vecmul(vecdiv(gel(B,k),Bf), temp),
1061
vecmul(gcoeff(mu,k,k-1), gel(MCS,k)));
1062
gel(B,k) = vecmul(gel(B,k),p1);
1063
gel(B,k-1) = Bf;
1064
for (i=k+1; i<=kmax; i++)
1065
{
1066
temp = gcoeff(mu,i,k);
1067
gcoeff(mu,i,k) = gsub(gcoeff(mu,i,k-1), vecmul(muf, gcoeff(mu,i,k)));
1068
gcoeff(mu,i,k-1) = gadd(temp, vecmul(gcoeff(mu,k,k-1),gcoeff(mu,i,k)));
1069
}
1070
return 1;
1071
}
1072
1073
static GEN
1074
rel_T2(GEN nf, GEN pol, long lx, long prec)
1075
{
1076
long ru, i, j, k, l;
1077
GEN T2, s, unro, roorder, powreorder;
1078
1079
roorder = nf_all_roots(nf, pol, prec);
1080
if (!roorder) return NULL;
1081
ru = lg(roorder);
1082
unro = cgetg(lx,t_COL); for (i=1; i<lx; i++) gel(unro,i) = gen_1;
1083
powreorder = cgetg(lx,t_MAT); gel(powreorder,1) = unro;
1084
T2 = cgetg(ru, t_VEC);
1085
for (i = 1; i < ru; i++)
1086
{
1087
GEN ro = gel(roorder,i);
1088
GEN m = initmat(lx);
1089
for (k=2; k<lx; k++)
1090
{
1091
GEN c = cgetg(lx, t_COL); gel(powreorder,k) = c;
1092
for (j=1; j < lx; j++)
1093
gel(c,j) = gmul(gel(ro,j), gmael(powreorder,k-1,j));
1094
}
1095
for (l = 1; l < lx; l++)
1096
for (k = 1; k <= l; k++)
1097
{
1098
s = gen_0;
1099
for (j = 1; j < lx; j++)
1100
s = gadd(s, gmul(conj_i(gmael(powreorder,k,j)),
1101
gmael(powreorder,l,j)));
1102
if (l == k)
1103
gcoeff(m, l, l) = real_i(s);
1104
else
1105
{
1106
gcoeff(m, k, l) = s;
1107
gcoeff(m, l, k) = conj_i(s);
1108
}
1109
}
1110
gel(T2,i) = m;
1111
}
1112
return T2;
1113
}
1114
1115
/* given a base field nf (e.g main variable y), a polynomial pol with
1116
* coefficients in nf (e.g main variable x), and an order as output
1117
* by rnfpseudobasis, outputs a reduced order. */
1118
GEN
1119
rnflllgram(GEN nf, GEN pol, GEN order,long prec)
1120
{
1121
pari_sp av = avma;
1122
long j, k, l, kmax, r1, lx, count = 0;
1123
GEN M, I, h, H, mth, MC, MPOL, MCS, B, mu;
1124
const long alpha = 10, MAX_COUNT = 4;
1125
1126
nf = checknf(nf); r1 = nf_get_r1(nf);
1127
check_ZKmodule(order, "rnflllgram");
1128
M = gel(order,1);
1129
I = gel(order,2); lx = lg(I);
1130
if (lx < 3) return gcopy(order);
1131
if (lx-1 != degpol(pol)) pari_err_DIM("rnflllgram");
1132
I = leafcopy(I);
1133
H = NULL;
1134
MPOL = matbasistoalg(nf, M);
1135
MCS = matid(lx-1); /* dummy for gerepile */
1136
PRECNF:
1137
if (count == MAX_COUNT)
1138
{
1139
prec = precdbl(prec); count = 0;
1140
if (DEBUGLEVEL) pari_warn(warnprec,"rnflllgram",prec);
1141
nf = nfnewprec_shallow(nf,prec);
1142
}
1143
mth = rel_T2(nf, pol, lx, prec);
1144
if (!mth) { count = MAX_COUNT; goto PRECNF; }
1145
h = NULL;
1146
PRECPB:
1147
if (h)
1148
{ /* precision problem, recompute. If no progress, increase nf precision */
1149
if (++count == MAX_COUNT || RgM_isidentity(h)) {count = MAX_COUNT; goto PRECNF;}
1150
H = H? gmul(H, h): h;
1151
MPOL = gmul(MPOL, h);
1152
}
1153
h = matid(lx-1);
1154
MC = mattocomplex(nf, MPOL);
1155
mu = cgetg(lx,t_MAT);
1156
B = cgetg(lx,t_COL);
1157
for (j=1; j<lx; j++)
1158
{
1159
gel(mu,j) = zerocol(lx - 1);
1160
gel(B,j) = gen_0;
1161
}
1162
if (DEBUGLEVEL) err_printf("k = ");
1163
gel(B,1) = real_i(rnfscal(mth,gel(MC,1),gel(MC,1)));
1164
gel(MCS,1) = gel(MC,1);
1165
kmax = 1; k = 2;
1166
do
1167
{
1168
GEN Ik_inv = NULL;
1169
if (DEBUGLEVEL) err_printf("%ld ",k);
1170
if (k > kmax)
1171
{ /* Incremental Gram-Schmidt */
1172
kmax = k; gel(MCS,k) = gel(MC,k);
1173
for (j=1; j<k; j++)
1174
{
1175
gcoeff(mu,k,j) = vecdiv(rnfscal(mth,gel(MCS,j),gel(MC,k)),
1176
gel(B,j));
1177
gel(MCS,k) = gsub(gel(MCS,k), vecmul(gcoeff(mu,k,j),gel(MCS,j)));
1178
}
1179
gel(B,k) = real_i(rnfscal(mth,gel(MCS,k),gel(MCS,k)));
1180
if (check_0(gel(B,k))) goto PRECPB;
1181
}
1182
if (!RED(k, k-1, h, mu, MC, nf, I, &Ik_inv)) goto PRECPB;
1183
if (do_SWAP(I,MC,MCS,h,mu,B,kmax,k,alpha, r1))
1184
{
1185
if (!B[k]) goto PRECPB;
1186
if (k > 2) k--;
1187
}
1188
else
1189
{
1190
for (l=k-2; l; l--)
1191
if (!RED(k, l, h, mu, MC, nf, I, &Ik_inv)) goto PRECPB;
1192
k++;
1193
}
1194
if (gc_needed(av,2))
1195
{
1196
if(DEBUGMEM>1) pari_warn(warnmem,"rnflllgram");
1197
gerepileall(av, H?10:9, &nf,&mth,&h,&MPOL,&B,&MC,&MCS,&mu,&I,&H);
1198
}
1199
}
1200
while (k < lx);
1201
MPOL = gmul(MPOL,h);
1202
if (H) h = gmul(H, h);
1203
if (DEBUGLEVEL) err_printf("\n");
1204
MPOL = RgM_to_nfM(nf,MPOL);
1205
h = RgM_to_nfM(nf,h);
1206
return gerepilecopy(av, mkvec2(mkvec2(MPOL,I), h));
1207
}
1208
1209
GEN
1210
rnfpolred(GEN nf, GEN pol, long prec)
1211
{
1212
pari_sp av = avma;
1213
long i, j, n, v = varn(pol);
1214
GEN id, w, I, O, bnf, nfpol;
1215
1216
if (typ(pol)!=t_POL) pari_err_TYPE("rnfpolred",pol);
1217
bnf = nf; nf = checknf(bnf);
1218
bnf = (nf == bnf)? NULL: checkbnf(bnf);
1219
if (degpol(pol) <= 1) { w = cgetg(2, t_VEC); gel(w,1) = pol_x(v); return w; }
1220
nfpol = nf_get_pol(nf);
1221
1222
id = rnfpseudobasis(nf,pol);
1223
if (bnf && is_pm1( bnf_get_no(bnf) )) /* if bnf is principal */
1224
{
1225
GEN newI, newO;
1226
O = gel(id,1);
1227
I = gel(id,2); n = lg(I)-1;
1228
newI = cgetg(n+1,t_VEC);
1229
newO = cgetg(n+1,t_MAT);
1230
for (j=1; j<=n; j++)
1231
{
1232
GEN al = gen_if_principal(bnf,gel(I,j));
1233
gel(newI,j) = gen_1;
1234
gel(newO,j) = nfC_nf_mul(nf, gel(O,j), al);
1235
}
1236
id = mkvec2(newO, newI);
1237
}
1238
1239
id = gel(rnflllgram(nf,pol,id,prec),1);
1240
O = gel(id,1);
1241
I = gel(id,2); n = lg(I)-1;
1242
w = cgetg(n+1,t_VEC);
1243
pol = lift_shallow(pol);
1244
for (j=1; j<=n; j++)
1245
{
1246
GEN newpol, L, a, Ij = gel(I,j);
1247
a = RgC_Rg_mul(gel(O,j), (typ(Ij) == t_MAT)? gcoeff(Ij,1,1): Ij);
1248
for (i=n; i; i--) gel(a,i) = nf_to_scalar_or_alg(nf, gel(a,i));
1249
a = RgV_to_RgX(a, v);
1250
newpol = RgXQX_red(RgXQ_charpoly(a, pol, v), nfpol);
1251
newpol = Q_primpart(newpol);
1252
1253
(void)nfgcd_all(newpol, RgX_deriv(newpol), nfpol, nf_get_index(nf), &newpol);
1254
L = leading_coeff(newpol);
1255
gel(w,j) = (typ(L) == t_POL)? RgXQX_div(newpol, L, nfpol)
1256
: RgX_Rg_div(newpol, L);
1257
}
1258
return gerepilecopy(av,w);
1259
}
1260
1261
/*******************************************************************/
1262
/* */
1263
/* LINEAR ALGEBRA OVER Z_K (HNF,SNF) */
1264
/* */
1265
/*******************************************************************/
1266
/* A torsion-free module M over Z_K is given by [A,I].
1267
* I=[a_1,...,a_k] is a row vector of k fractional ideals given in HNF.
1268
* A is an n x k matrix (same k) such that if A_j is the j-th column of A then
1269
* M=a_1 A_1+...+a_k A_k. We say that [A,I] is a pseudo-basis if k=n */
1270
1271
/* Given an element x and an ideal I in HNF, gives an r such that x-r is in H
1272
* and r is small */
1273
GEN
1274
nfreduce(GEN nf, GEN x, GEN I)
1275
{
1276
pari_sp av = avma;
1277
GEN aI;
1278
x = nf_to_scalar_or_basis(checknf(nf), x);
1279
if (idealtyp(&I,&aI) != id_MAT || lg(I)==1) pari_err_TYPE("nfreduce",I);
1280
if (typ(x) != t_COL) x = scalarcol( gmod(x, gcoeff(I,1,1)), lg(I)-1 );
1281
else x = reducemodinvertible(x, I);
1282
return gerepileupto(av, x);
1283
}
1284
/* Given an element x and an ideal in HNF, gives an a in ideal such that
1285
* x-a is small. No checks */
1286
static GEN
1287
element_close(GEN nf, GEN x, GEN ideal)
1288
{
1289
pari_sp av = avma;
1290
GEN y = gcoeff(ideal,1,1);
1291
x = nf_to_scalar_or_basis(nf, x);
1292
if (typ(y) == t_INT && is_pm1(y)) return ground(x);
1293
if (typ(x) == t_COL)
1294
x = closemodinvertible(x, ideal);
1295
else
1296
x = gmul(y, gdivround(x,y));
1297
return gerepileupto(av, x);
1298
}
1299
1300
/* A + v B */
1301
static GEN
1302
colcomb1(GEN nf, GEN v, GEN A, GEN B)
1303
{
1304
if (isintzero(v)) return A;
1305
return RgC_to_nfC(nf, RgC_add(A, nfC_nf_mul(nf,B,v)));
1306
}
1307
/* u A + v B */
1308
static GEN
1309
colcomb(GEN nf, GEN u, GEN v, GEN A, GEN B)
1310
{
1311
if (isintzero(u)) return nfC_nf_mul(nf,B,v);
1312
if (u != gen_1) A = nfC_nf_mul(nf,A,u);
1313
return colcomb1(nf, v, A, B);
1314
}
1315
1316
/* return m[i,1..lim] * x */
1317
static GEN
1318
element_mulvecrow(GEN nf, GEN x, GEN m, long i, long lim)
1319
{
1320
long j, l = minss(lg(m), lim+1);
1321
GEN dx, y = cgetg(l, t_VEC);
1322
x = nf_to_scalar_or_basis(nf, x);
1323
if (typ(x) == t_COL)
1324
{
1325
x = zk_multable(nf, Q_remove_denom(x, &dx));
1326
for (j=1; j<l; j++)
1327
{
1328
GEN t = gcoeff(m,i,j);
1329
if (!isintzero(t))
1330
{
1331
if (typ(t) == t_COL)
1332
t = RgM_RgC_mul(x, t);
1333
else
1334
t = ZC_Q_mul(gel(x,1), t);
1335
if (dx) t = gdiv(t, dx);
1336
t = nf_to_scalar_or_basis(nf,t);
1337
}
1338
gel(y,j) = t;
1339
}
1340
}
1341
else
1342
{
1343
for (j=1; j<l; j++) gel(y,j) = gmul(x, gcoeff(m,i,j));
1344
}
1345
return y;
1346
}
1347
1348
/* u Z[s,] + v Z[t,], limitied to the first lim entries */
1349
static GEN
1350
rowcomb(GEN nf, GEN u, GEN v, long s, long t, GEN Z, long lim)
1351
{
1352
GEN z;
1353
if (gequal0(u))
1354
z = element_mulvecrow(nf,v,Z,t, lim);
1355
else
1356
{
1357
z = element_mulvecrow(nf,u,Z,s, lim);
1358
if (!gequal0(v)) z = gadd(z, element_mulvecrow(nf,v,Z,t, lim));
1359
}
1360
return z;
1361
}
1362
1363
/* nfbezout(0,b,A,B). Either bB = NULL or b*B */
1364
static GEN
1365
zero_nfbezout(GEN nf,GEN bB, GEN b, GEN A,GEN B,GEN *u,GEN *v,GEN *w,GEN *di)
1366
{
1367
GEN d;
1368
if (isint1(b))
1369
{
1370
*v = gen_1;
1371
*w = A;
1372
d = B;
1373
*di = idealinv(nf,d);
1374
}
1375
else
1376
{
1377
*v = nfinv(nf,b);
1378
*w = idealmul(nf,A,*v);
1379
d = bB? bB: idealmul(nf,b,B);
1380
*di = idealHNF_inv(nf,d);
1381
}
1382
*u = gen_0; return d;
1383
}
1384
1385
/* Given elements a,b and ideals A, B, outputs d = a.A+b.B and gives
1386
* di=d^-1, w=A.B.di, u, v such that au+bv=1 and u in A.di, v in B.di.
1387
* Assume A, B nonzero, but a or b can be zero (not both) */
1388
static GEN
1389
nfbezout(GEN nf,GEN a,GEN b, GEN A,GEN B, GEN *pu,GEN *pv,GEN *pw,GEN *pdi,
1390
int red)
1391
{
1392
GEN w, u, v, d, di, aA, bB;
1393
1394
if (isintzero(a)) return zero_nfbezout(nf,NULL,b,A,B,pu,pv,pw,pdi);
1395
if (isintzero(b)) return zero_nfbezout(nf,NULL,a,B,A,pv,pu,pw,pdi);
1396
1397
if (a != gen_1) /* frequently called with a = gen_1 */
1398
{
1399
a = nf_to_scalar_or_basis(nf,a);
1400
if (isint1(a)) a = gen_1;
1401
}
1402
aA = (a == gen_1)? idealhnf_shallow(nf,A): idealmul(nf,a,A);
1403
bB = idealmul(nf,b,B);
1404
d = idealadd(nf,aA,bB);
1405
if (gequal(aA, d)) return zero_nfbezout(nf,d, a,B,A,pv,pu,pw,pdi);
1406
if (gequal(bB, d)) return zero_nfbezout(nf,d, b,A,B,pu,pv,pw,pdi);
1407
/* general case is slow */
1408
di = idealHNF_inv(nf,d);
1409
aA = idealmul(nf,aA,di); /* integral */
1410
bB = idealmul(nf,bB,di); /* integral */
1411
1412
u = red? idealaddtoone_i(nf, aA, bB): idealaddtoone_raw(nf, aA, bB);
1413
w = idealmul(nf,aA,B);
1414
v = nfdiv(nf, nfsub(nf, gen_1, u), b);
1415
if (a != gen_1)
1416
{
1417
GEN inva = nfinv(nf, a);
1418
u = nfmul(nf,u,inva);
1419
w = idealmul(nf, inva, w); /* AB/d */
1420
}
1421
*pu = u; *pv = v; *pw = w; *pdi = di; return d;
1422
}
1423
/* v a vector of ideals, simplify in place the ones generated by elts of Q */
1424
static void
1425
idV_simplify(GEN v)
1426
{
1427
long i, l = lg(v);
1428
for (i = 1; i < l; i++)
1429
{
1430
GEN M = gel(v,i);
1431
if (typ(M)==t_MAT && RgM_isscalar(M,NULL))
1432
gel(v,i) = Q_abs_shallow(gcoeff(M,1,1));
1433
}
1434
}
1435
/* Given a torsion-free module x outputs a pseudo-basis for x in HNF */
1436
GEN
1437
nfhnf0(GEN nf, GEN x, long flag)
1438
{
1439
long i, j, def, idef, m, n;
1440
pari_sp av0 = avma, av;
1441
GEN y, A, I, J, U;
1442
1443
nf = checknf(nf);
1444
check_ZKmodule(x, "nfhnf");
1445
A = gel(x,1); RgM_dimensions(A, &m, &n);
1446
I = gel(x,2);
1447
if (!n) {
1448
if (!flag) return gcopy(x);
1449
retmkvec2(gcopy(x), cgetg(1,t_MAT));
1450
}
1451
U = flag? matid(n): NULL;
1452
idef = (n < m)? m-n : 0;
1453
av = avma;
1454
A = RgM_to_nfM(nf,A);
1455
I = leafcopy(I);
1456
J = zerovec(n); def = n;
1457
for (i=m; i>idef; i--)
1458
{
1459
GEN d, di = NULL;
1460
1461
j=def; while (j>=1 && isintzero(gcoeff(A,i,j))) j--;
1462
if (!j)
1463
{ /* no pivot on line i */
1464
if (idef) idef--;
1465
continue;
1466
}
1467
if (j==def) j--;
1468
else {
1469
swap(gel(A,j), gel(A,def));
1470
swap(gel(I,j), gel(I,def));
1471
if (U) swap(gel(U,j), gel(U,def));
1472
}
1473
for ( ; j; j--)
1474
{
1475
GEN a,b, u,v,w, S, T, S0, T0 = gel(A,j);
1476
b = gel(T0,i); if (isintzero(b)) continue;
1477
1478
S0 = gel(A,def); a = gel(S0,i);
1479
d = nfbezout(nf, a,b, gel(I,def),gel(I,j), &u,&v,&w,&di,1);
1480
S = colcomb(nf, u,v, S0,T0);
1481
T = colcomb(nf, a,gneg(b), T0,S0);
1482
gel(A,def) = S; gel(A,j) = T;
1483
gel(I,def) = d; gel(I,j) = w;
1484
if (U)
1485
{
1486
S0 = gel(U,def);
1487
T0 = gel(U,j);
1488
gel(U,def) = colcomb(nf, u,v, S0,T0);
1489
gel(U,j) = colcomb(nf, a,gneg(b), T0,S0);
1490
}
1491
}
1492
y = gcoeff(A,i,def);
1493
if (!isint1(y))
1494
{
1495
GEN yi = nfinv(nf,y);
1496
gel(A,def) = nfC_nf_mul(nf, gel(A,def), yi);
1497
gel(I,def) = idealmul(nf, y, gel(I,def));
1498
if (U) gel(U,def) = nfC_nf_mul(nf, gel(U,def), yi);
1499
di = NULL;
1500
}
1501
if (!di) di = idealinv(nf,gel(I,def));
1502
d = gel(I,def);
1503
gel(J,def) = di;
1504
for (j=def+1; j<=n; j++)
1505
{
1506
GEN mc, c = gcoeff(A,i,j); if (isintzero(c)) continue;
1507
c = element_close(nf, c, idealmul(nf,d,gel(J,j)));
1508
mc = gneg(c);
1509
gel(A,j) = colcomb1(nf, mc, gel(A,j),gel(A,def));
1510
if (U) gel(U,j) = colcomb1(nf, mc, gel(U,j),gel(U,def));
1511
}
1512
def--;
1513
if (gc_needed(av,2))
1514
{
1515
if(DEBUGMEM>1) pari_warn(warnmem,"nfhnf, i = %ld", i);
1516
gerepileall(av,U?4:3, &A,&I,&J,&U);
1517
}
1518
}
1519
n -= def;
1520
A += def; A[0] = evaltyp(t_MAT)|evallg(n+1);
1521
I += def; I[0] = evaltyp(t_VEC)|evallg(n+1);
1522
idV_simplify(I);
1523
x = mkvec2(A,I);
1524
if (U) x = mkvec2(x,U);
1525
return gerepilecopy(av0, x);
1526
}
1527
1528
GEN
1529
nfhnf(GEN nf, GEN x) { return nfhnf0(nf, x, 0); }
1530
1531
static GEN
1532
RgV_find_denom(GEN x)
1533
{
1534
long i, l = lg(x);
1535
for (i = 1; i < l; i++)
1536
if (Q_denom(gel(x,i)) != gen_1) return gel(x,i);
1537
return NULL;
1538
}
1539
/* A torsion module M over Z_K will be given by a row vector [A,I,J] with
1540
* three components. I=[b_1,...,b_n] is a row vector of n fractional ideals
1541
* given in HNF, J=[a_1,...,a_n] is a row vector of n fractional ideals in
1542
* HNF. A is an nxn matrix (same n) such that if A_j is the j-th column of A
1543
* and e_n is the canonical basis of K^n, then
1544
* M=(b_1e_1+...+b_ne_n)/(a_1A_1+...a_nA_n) */
1545
1546
/* x=[A,I,J] a torsion module as above. Output the
1547
* smith normal form as K=[c_1,...,c_n] such that x = Z_K/c_1+...+Z_K/c_n */
1548
GEN
1549
nfsnf0(GEN nf, GEN x, long flag)
1550
{
1551
long i, j, k, l, n, m;
1552
pari_sp av;
1553
GEN z,u,v,w,d,dinv,A,I,J, U,V;
1554
1555
nf = checknf(nf);
1556
if (typ(x)!=t_VEC || lg(x)!=4) pari_err_TYPE("nfsnf",x);
1557
A = gel(x,1);
1558
I = gel(x,2);
1559
J = gel(x,3);
1560
if (typ(A)!=t_MAT) pari_err_TYPE("nfsnf",A);
1561
n = lg(A)-1;
1562
if (typ(I)!=t_VEC) pari_err_TYPE("nfsnf",I);
1563
if (typ(J)!=t_VEC) pari_err_TYPE("nfsnf",J);
1564
if (lg(I)!=n+1 || lg(J)!=n+1) pari_err_DIM("nfsnf");
1565
RgM_dimensions(A, &m, &n);
1566
if (!n || n != m) pari_err_IMPL("nfsnf for empty or non square matrices");
1567
1568
av = avma;
1569
if (!flag) U = V = NULL;
1570
else
1571
{
1572
U = matid(m);
1573
V = matid(n);
1574
}
1575
A = RgM_to_nfM(nf, A);
1576
I = leafcopy(I);
1577
J = leafcopy(J);
1578
for (i = 1; i <= n; i++) gel(J,i) = idealinv(nf, gel(J,i));
1579
z = zerovec(n);
1580
for (i=n; i>=1; i--)
1581
{
1582
GEN Aii, a, b, db;
1583
long c = 0;
1584
for (j=i-1; j>=1; j--)
1585
{
1586
GEN S, T, S0, T0 = gel(A,j);
1587
b = gel(T0,i); if (gequal0(b)) continue;
1588
1589
S0 = gel(A,i); a = gel(S0,i);
1590
d = nfbezout(nf, a,b, gel(J,i),gel(J,j), &u,&v,&w,&dinv,1);
1591
S = colcomb(nf, u,v, S0,T0);
1592
T = colcomb(nf, a,gneg(b), T0,S0);
1593
gel(A,i) = S; gel(A,j) = T;
1594
gel(J,i) = d; gel(J,j) = w;
1595
if (V)
1596
{
1597
T0 = gel(V,j);
1598
S0 = gel(V,i);
1599
gel(V,i) = colcomb(nf, u,v, S0,T0);
1600
gel(V,j) = colcomb(nf, a,gneg(b), T0,S0);
1601
}
1602
}
1603
for (j=i-1; j>=1; j--)
1604
{
1605
GEN ri, rj;
1606
b = gcoeff(A,j,i); if (gequal0(b)) continue;
1607
1608
a = gcoeff(A,i,i);
1609
d = nfbezout(nf, a,b, gel(I,i),gel(I,j), &u,&v,&w,&dinv,1);
1610
ri = rowcomb(nf, u,v, i,j, A, i);
1611
rj = rowcomb(nf, a,gneg(b), j,i, A, i);
1612
for (k=1; k<=i; k++) {
1613
gcoeff(A,j,k) = gel(rj,k);
1614
gcoeff(A,i,k) = gel(ri,k);
1615
}
1616
if (U)
1617
{
1618
ri = rowcomb(nf, u,v, i,j, U, m);
1619
rj = rowcomb(nf, a,gneg(b), j,i, U, m);
1620
for (k=1; k<=m; k++) {
1621
gcoeff(U,j,k) = gel(rj,k);
1622
gcoeff(U,i,k) = gel(ri,k);
1623
}
1624
}
1625
gel(I,i) = d; gel(I,j) = w; c = 1;
1626
}
1627
if (c) { i++; continue; }
1628
1629
Aii = gcoeff(A,i,i); if (gequal0(Aii)) continue;
1630
gel(J,i) = idealmul(nf, gel(J,i), Aii);
1631
gcoeff(A,i,i) = gen_1;
1632
if (V) gel(V,i) = nfC_nf_mul(nf, gel(V,i), nfinv(nf,Aii));
1633
gel(z,i) = idealmul(nf,gel(J,i),gel(I,i));
1634
b = Q_remove_denom(gel(z,i), &db);
1635
for (k=1; k<i; k++)
1636
for (l=1; l<i; l++)
1637
{
1638
GEN d, D, p1, p2, p3, Akl = gcoeff(A,k,l);
1639
long t;
1640
if (gequal0(Akl)) continue;
1641
1642
p1 = idealmul(nf,Akl,gel(J,l));
1643
p3 = idealmul(nf, p1, gel(I,k));
1644
if (db) p3 = RgM_Rg_mul(p3, db);
1645
if (RgM_is_ZM(p3) && hnfdivide(b, p3)) continue;
1646
1647
/* find d in D = I[k]/I[i] not in J[i]/(A[k,l] J[l]) */
1648
D = idealdiv(nf,gel(I,k),gel(I,i));
1649
p2 = idealdiv(nf,gel(J,i), p1);
1650
d = RgV_find_denom(QM_gauss(p2, D));
1651
if (!d) pari_err_BUG("nfsnf");
1652
p1 = element_mulvecrow(nf,d,A,k,i);
1653
for (t=1; t<=i; t++) gcoeff(A,i,t) = gadd(gcoeff(A,i,t),gel(p1,t));
1654
if (U)
1655
{
1656
p1 = element_mulvecrow(nf,d,U,k,i);
1657
for (t=1; t<=i; t++) gcoeff(U,i,t) = gadd(gcoeff(U,i,t),gel(p1,t));
1658
}
1659
1660
k = i; c = 1; break;
1661
}
1662
if (gc_needed(av,1))
1663
{
1664
if(DEBUGMEM>1) pari_warn(warnmem,"nfsnf");
1665
gerepileall(av,U?6:4, &A,&I,&J,&z,&U,&V);
1666
}
1667
if (c) i++; /* iterate on row/column i */
1668
}
1669
if (U) z = mkvec3(z,U,V);
1670
return gerepilecopy(av, z);
1671
}
1672
GEN
1673
nfsnf(GEN nf, GEN x) { return nfsnf0(nf,x,0); }
1674
1675
/* Given a pseudo-basis x, outputs a multiple of its ideal determinant */
1676
GEN
1677
nfdetint(GEN nf, GEN x)
1678
{
1679
GEN pass,c,v,det1,piv,pivprec,vi,p1,A,I,id,idprod;
1680
long i, j, k, rg, n, m, m1, cm=0, N;
1681
pari_sp av = avma, av1;
1682
1683
nf = checknf(nf); N = nf_get_degree(nf);
1684
check_ZKmodule(x, "nfdetint");
1685
A = gel(x,1);
1686
I = gel(x,2);
1687
n = lg(A)-1; if (!n) return gen_1;
1688
1689
m1 = lgcols(A); m = m1-1;
1690
id = matid(N);
1691
c = new_chunk(m1); for (k=1; k<=m; k++) c[k] = 0;
1692
piv = pivprec = gen_1;
1693
1694
av1 = avma;
1695
det1 = idprod = gen_0; /* dummy for gerepileall */
1696
pass = cgetg(m1,t_MAT);
1697
v = cgetg(m1,t_COL);
1698
for (j=1; j<=m; j++)
1699
{
1700
gel(pass,j) = zerocol(m);
1701
gel(v,j) = gen_0; /* dummy */
1702
}
1703
for (rg=0,k=1; k<=n; k++)
1704
{
1705
long t = 0;
1706
for (i=1; i<=m; i++)
1707
if (!c[i])
1708
{
1709
vi=nfmul(nf,piv,gcoeff(A,i,k));
1710
for (j=1; j<=m; j++)
1711
if (c[j]) vi=gadd(vi,nfmul(nf,gcoeff(pass,i,j),gcoeff(A,j,k)));
1712
gel(v,i) = vi; if (!t && !gequal0(vi)) t=i;
1713
}
1714
if (t)
1715
{
1716
pivprec = piv;
1717
if (rg == m-1)
1718
{
1719
if (!cm)
1720
{
1721
cm=1; idprod = id;
1722
for (i=1; i<=m; i++)
1723
if (i!=t)
1724
idprod = (idprod==id)? gel(I,c[i])
1725
: idealmul(nf,idprod,gel(I,c[i]));
1726
}
1727
p1 = idealmul(nf,gel(v,t),gel(I,k)); c[t]=0;
1728
det1 = (typ(det1)==t_INT)? p1: idealadd(nf,p1,det1);
1729
}
1730
else
1731
{
1732
rg++; piv=gel(v,t); c[t]=k;
1733
for (i=1; i<=m; i++)
1734
if (!c[i])
1735
{
1736
for (j=1; j<=m; j++)
1737
if (c[j] && j!=t)
1738
{
1739
p1 = gsub(nfmul(nf,piv,gcoeff(pass,i,j)),
1740
nfmul(nf,gel(v,i),gcoeff(pass,t,j)));
1741
gcoeff(pass,i,j) = rg>1? nfdiv(nf,p1,pivprec)
1742
: p1;
1743
}
1744
gcoeff(pass,i,t) = gneg(gel(v,i));
1745
}
1746
}
1747
}
1748
if (gc_needed(av1,1))
1749
{
1750
if(DEBUGMEM>1) pari_warn(warnmem,"nfdetint");
1751
gerepileall(av1,6, &det1,&piv,&pivprec,&pass,&v,&idprod);
1752
}
1753
}
1754
if (!cm) { set_avma(av); return cgetg(1,t_MAT); }
1755
return gerepileupto(av, idealmul(nf,idprod,det1));
1756
}
1757
1758
/* reduce in place components of x[1..lim] mod D (destroy x). D in HNF */
1759
static void
1760
nfcleanmod(GEN nf, GEN x, long lim, GEN D)
1761
{
1762
GEN DZ, DZ2, dD;
1763
long i;
1764
D = Q_remove_denom(D, &dD);
1765
DZ = gcoeff(D,1,1); DZ2 = shifti(DZ, -1);
1766
for (i = 1; i <= lim; i++)
1767
{
1768
GEN c = nf_to_scalar_or_basis(nf, gel(x,i));
1769
switch(typ(c)) /* c = centermod(c, D) */
1770
{
1771
case t_INT:
1772
if (!signe(c)) break;
1773
if (dD) c = mulii(c, dD);
1774
c = centermodii(c, DZ, DZ2);
1775
if (dD) c = Qdivii(c,dD);
1776
break;
1777
case t_FRAC: {
1778
GEN dc = gel(c,2), nc = gel(c,1), N = mulii(DZ, dc);
1779
if (dD) nc = mulii(nc, dD);
1780
c = centermodii(nc, N, shifti(N,-1));
1781
c = Qdivii(c, dD ? mulii(dc,dD): dc);
1782
break;
1783
}
1784
case t_COL: {
1785
GEN dc;
1786
c = Q_remove_denom(c, &dc);
1787
if (dD) c = ZC_Z_mul(c, dD);
1788
c = ZC_hnfrem(c, dc? ZM_Z_mul(D,dc): D);
1789
dc = mul_content(dc, dD);
1790
if (ZV_isscalar(c))
1791
{
1792
c = gel(c,1);
1793
if (dc) c = Qdivii(c,dc);
1794
}
1795
else
1796
if (dc) c = RgC_Rg_div(c, dc);
1797
break;
1798
}
1799
}
1800
gel(x,i) = c;
1801
}
1802
}
1803
1804
GEN
1805
nfhnfmod(GEN nf, GEN x, GEN D)
1806
{
1807
long li, co, i, j, def, ldef;
1808
pari_sp av0=avma, av;
1809
GEN dA, dI, d0, w, p1, d, u, v, A, I, J, di;
1810
1811
nf = checknf(nf);
1812
check_ZKmodule(x, "nfhnfmod");
1813
A = gel(x,1);
1814
I = gel(x,2);
1815
co = lg(A); if (co==1) return cgetg(1,t_MAT);
1816
1817
li = lgcols(A);
1818
if (typ(D)!=t_MAT) D = idealhnf_shallow(nf, D);
1819
D = Q_remove_denom(D, NULL);
1820
RgM_check_ZM(D, "nfhnfmod");
1821
1822
av = avma;
1823
A = RgM_to_nfM(nf, A);
1824
A = Q_remove_denom(A, &dA);
1825
I = Q_remove_denom(leafcopy(I), &dI);
1826
dA = mul_denom(dA,dI);
1827
if (dA) D = ZM_Z_mul(D, powiu(dA, minss(li,co)));
1828
1829
def = co; ldef = (li>co)? li-co+1: 1;
1830
for (i=li-1; i>=ldef; i--)
1831
{
1832
def--; j=def; while (j>=1 && isintzero(gcoeff(A,i,j))) j--;
1833
if (!j) continue;
1834
if (j==def) j--;
1835
else {
1836
swap(gel(A,j), gel(A,def));
1837
swap(gel(I,j), gel(I,def));
1838
}
1839
for ( ; j; j--)
1840
{
1841
GEN a, b, S, T, S0, T0 = gel(A,j);
1842
b = gel(T0,i); if (isintzero(b)) continue;
1843
1844
S0 = gel(A,def); a = gel(S0,i);
1845
d = nfbezout(nf, a,b, gel(I,def),gel(I,j), &u,&v,&w,&di,0);
1846
S = colcomb(nf, u,v, S0,T0);
1847
T = colcomb(nf, a,gneg(b), T0,S0);
1848
if (u != gen_0 && v != gen_0) /* already reduced otherwise */
1849
nfcleanmod(nf, S, i, idealmul(nf,D,di));
1850
nfcleanmod(nf, T, i, idealdiv(nf,D,w));
1851
gel(A,def) = S; gel(A,j) = T;
1852
gel(I,def) = d; gel(I,j) = w;
1853
}
1854
if (gc_needed(av,2))
1855
{
1856
if(DEBUGMEM>1) pari_warn(warnmem,"[1]: nfhnfmod, i = %ld", i);
1857
gerepileall(av,dA? 4: 3, &A,&I,&D,&dA);
1858
}
1859
}
1860
def--; d0 = D;
1861
A += def; A[0] = evaltyp(t_MAT)|evallg(li);
1862
I += def; I[0] = evaltyp(t_VEC)|evallg(li);
1863
J = cgetg(li,t_VEC);
1864
for (i=li-1; i>=1; i--)
1865
{
1866
GEN b = gcoeff(A,i,i);
1867
d = nfbezout(nf, gen_1,b, d0,gel(I,i), &u,&v,&w,&di,0);
1868
p1 = nfC_nf_mul(nf,gel(A,i),v);
1869
if (i > 1)
1870
{
1871
d0 = idealmul(nf,d0,di);
1872
nfcleanmod(nf, p1, i, d0);
1873
}
1874
gel(A,i) = p1; gel(p1,i) = gen_1;
1875
gel(I,i) = d;
1876
gel(J,i) = di;
1877
}
1878
for (i=li-2; i>=1; i--)
1879
{
1880
d = gel(I,i);
1881
for (j=i+1; j<li; j++)
1882
{
1883
GEN c = gcoeff(A,i,j); if (isintzero(c)) continue;
1884
c = element_close(nf, c, idealmul(nf,d,gel(J,j)));
1885
gel(A,j) = colcomb1(nf, gneg(c), gel(A,j),gel(A,i));
1886
}
1887
if (gc_needed(av,2))
1888
{
1889
if(DEBUGMEM>1) pari_warn(warnmem,"[2]: nfhnfmod, i = %ld", i);
1890
gerepileall(av,dA? 4: 3, &A,&I,&J,&dA);
1891
}
1892
}
1893
idV_simplify(I);
1894
if (dA) I = gdiv(I,dA);
1895
return gerepilecopy(av0, mkvec2(A, I));
1896
}
1897
1898