Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

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

28485 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
/* BASIC NF OPERATIONS */
18
/* (continued) */
19
/* */
20
/*******************************************************************/
21
#include "pari.h"
22
#include "paripriv.h"
23
24
#define DEBUGLEVEL DEBUGLEVEL_nf
25
26
/*******************************************************************/
27
/* */
28
/* IDEAL OPERATIONS */
29
/* */
30
/*******************************************************************/
31
32
/* A valid ideal is either principal (valid nf_element), or prime, or a matrix
33
* on the integer basis in HNF.
34
* A prime ideal is of the form [p,a,e,f,b], where the ideal is p.Z_K+a.Z_K,
35
* p is a rational prime, a belongs to Z_K, e=e(P/p), f=f(P/p), and b
36
* is Lenstra's constant, such that p.P^(-1)= p Z_K + b Z_K.
37
*
38
* An extended ideal is a couple [I,F] where I is an ideal and F is either an
39
* algebraic number, or a factorization matrix attached to an algebraic number.
40
* All routines work with either extended ideals or ideals (an omitted F is
41
* assumed to be factor(1)). All ideals are output in HNF form. */
42
43
/* types and conversions */
44
45
long
46
idealtyp(GEN *ideal, GEN *arch)
47
{
48
GEN x = *ideal;
49
long t,lx,tx = typ(x);
50
51
if (tx!=t_VEC || lg(x)!=3) *arch = NULL;
52
else
53
{
54
GEN a = gel(x,2);
55
if (typ(a) == t_MAT && lg(a) != 3)
56
{ /* allow [;] */
57
if (lg(a) != 1) pari_err_TYPE("idealtyp [extended ideal]",x);
58
a = trivial_fact();
59
}
60
*arch = a;
61
x = gel(x,1); tx = typ(x);
62
}
63
switch(tx)
64
{
65
case t_MAT: lx = lg(x);
66
if (lx == 1) { t = id_PRINCIPAL; x = gen_0; break; }
67
if (lx != lgcols(x)) pari_err_TYPE("idealtyp [nonsquare t_MAT]",x);
68
t = id_MAT;
69
break;
70
71
case t_VEC: if (lg(x)!=6) pari_err_TYPE("idealtyp",x);
72
t = id_PRIME; break;
73
74
case t_POL: case t_POLMOD: case t_COL:
75
case t_INT: case t_FRAC:
76
t = id_PRINCIPAL; break;
77
default:
78
pari_err_TYPE("idealtyp",x);
79
return 0; /*LCOV_EXCL_LINE*/
80
}
81
*ideal = x; return t;
82
}
83
84
/* true nf; v = [a,x,...], a in Z. Return (a,x) */
85
GEN
86
idealhnf_two(GEN nf, GEN v)
87
{
88
GEN p = gel(v,1), pi = gel(v,2), m = zk_scalar_or_multable(nf, pi);
89
if (typ(m) == t_INT) return scalarmat(gcdii(m,p), nf_get_degree(nf));
90
return ZM_hnfmodid(m, p);
91
}
92
/* true nf */
93
GEN
94
pr_hnf(GEN nf, GEN pr)
95
{
96
GEN p = pr_get_p(pr), m;
97
if (pr_is_inert(pr)) return scalarmat(p, nf_get_degree(nf));
98
m = zk_scalar_or_multable(nf, pr_get_gen(pr));
99
return ZM_hnfmodprime(m, p);
100
}
101
102
GEN
103
idealhnf_principal(GEN nf, GEN x)
104
{
105
GEN cx;
106
x = nf_to_scalar_or_basis(nf, x);
107
switch(typ(x))
108
{
109
case t_COL: break;
110
case t_INT: if (!signe(x)) return cgetg(1,t_MAT);
111
return scalarmat(absi_shallow(x), nf_get_degree(nf));
112
case t_FRAC:
113
return scalarmat(Q_abs_shallow(x), nf_get_degree(nf));
114
default: pari_err_TYPE("idealhnf",x);
115
}
116
x = Q_primitive_part(x, &cx);
117
RgV_check_ZV(x, "idealhnf");
118
x = zk_multable(nf, x);
119
x = ZM_hnfmodid(x, zkmultable_capZ(x));
120
return cx? ZM_Q_mul(x,cx): x;
121
}
122
123
/* x integral ideal in t_MAT form, nx columns */
124
static GEN
125
vec_mulid(GEN nf, GEN x, long nx, long N)
126
{
127
GEN m = cgetg(nx*N + 1, t_MAT);
128
long i, j, k;
129
for (i=k=1; i<=nx; i++)
130
for (j=1; j<=N; j++) gel(m, k++) = zk_ei_mul(nf, gel(x,i),j);
131
return m;
132
}
133
/* true nf */
134
GEN
135
idealhnf_shallow(GEN nf, GEN x)
136
{
137
long tx = typ(x), lx = lg(x), N;
138
139
/* cannot use idealtyp because here we allow nonsquare matrices */
140
if (tx == t_VEC && lx == 3) { x = gel(x,1); tx = typ(x); lx = lg(x); }
141
if (tx == t_VEC && lx == 6) return pr_hnf(nf,x); /* PRIME */
142
switch(tx)
143
{
144
case t_MAT:
145
{
146
GEN cx;
147
long nx = lx-1;
148
N = nf_get_degree(nf);
149
if (nx == 0) return cgetg(1, t_MAT);
150
if (nbrows(x) != N) pari_err_TYPE("idealhnf [wrong dimension]",x);
151
if (nx == 1) return idealhnf_principal(nf, gel(x,1));
152
153
if (nx == N && RgM_is_ZM(x) && ZM_ishnf(x)) return x;
154
x = Q_primitive_part(x, &cx);
155
if (nx < N) x = vec_mulid(nf, x, nx, N);
156
x = ZM_hnfmod(x, ZM_detmult(x));
157
return cx? ZM_Q_mul(x,cx): x;
158
}
159
case t_QFB:
160
{
161
pari_sp av = avma;
162
GEN u, D = nf_get_disc(nf), T = nf_get_pol(nf), f = nf_get_index(nf);
163
GEN A = gel(x,1), B = gel(x,2);
164
N = nf_get_degree(nf);
165
if (N != 2)
166
pari_err_TYPE("idealhnf [Qfb for nonquadratic fields]", x);
167
if (!equalii(qfb_disc(x), D))
168
pari_err_DOMAIN("idealhnf [Qfb]", "disc(q)", "!=", D, x);
169
/* x -> A Z + (-B + sqrt(D)) / 2 Z
170
K = Q[t]/T(t), t^2 + ut + v = 0, u^2 - 4v = Df^2
171
=> t = (-u + sqrt(D) f)/2
172
=> sqrt(D)/2 = (t + u/2)/f */
173
u = gel(T,3);
174
B = deg1pol_shallow(ginv(f),
175
gsub(gdiv(u, shifti(f,1)), gdiv(B,gen_2)),
176
varn(T));
177
return gerepileupto(av, idealhnf_two(nf, mkvec2(A,B)));
178
}
179
default: return idealhnf_principal(nf, x); /* PRINCIPAL */
180
}
181
}
182
GEN
183
idealhnf(GEN nf, GEN x)
184
{
185
pari_sp av = avma;
186
GEN y = idealhnf_shallow(checknf(nf), x);
187
return (avma == av)? gcopy(y): gerepileupto(av, y);
188
}
189
190
/* GP functions */
191
192
GEN
193
idealtwoelt0(GEN nf, GEN x, GEN a)
194
{
195
if (!a) return idealtwoelt(nf,x);
196
return idealtwoelt2(nf,x,a);
197
}
198
199
GEN
200
idealpow0(GEN nf, GEN x, GEN n, long flag)
201
{
202
if (flag) return idealpowred(nf,x,n);
203
return idealpow(nf,x,n);
204
}
205
206
GEN
207
idealmul0(GEN nf, GEN x, GEN y, long flag)
208
{
209
if (flag) return idealmulred(nf,x,y);
210
return idealmul(nf,x,y);
211
}
212
213
GEN
214
idealdiv0(GEN nf, GEN x, GEN y, long flag)
215
{
216
switch(flag)
217
{
218
case 0: return idealdiv(nf,x,y);
219
case 1: return idealdivexact(nf,x,y);
220
default: pari_err_FLAG("idealdiv");
221
}
222
return NULL; /* LCOV_EXCL_LINE */
223
}
224
225
GEN
226
idealaddtoone0(GEN nf, GEN arg1, GEN arg2)
227
{
228
if (!arg2) return idealaddmultoone(nf,arg1);
229
return idealaddtoone(nf,arg1,arg2);
230
}
231
232
/* b not a scalar */
233
static GEN
234
hnf_Z_ZC(GEN nf, GEN a, GEN b) { return hnfmodid(zk_multable(nf,b), a); }
235
/* b not a scalar */
236
static GEN
237
hnf_Z_QC(GEN nf, GEN a, GEN b)
238
{
239
GEN db;
240
b = Q_remove_denom(b, &db);
241
if (db) a = mulii(a, db);
242
b = hnf_Z_ZC(nf,a,b);
243
return db? RgM_Rg_div(b, db): b;
244
}
245
/* b not a scalar (not point in trying to optimize for this case) */
246
static GEN
247
hnf_Q_QC(GEN nf, GEN a, GEN b)
248
{
249
GEN da, db;
250
if (typ(a) == t_INT) return hnf_Z_QC(nf, a, b);
251
da = gel(a,2);
252
a = gel(a,1);
253
b = Q_remove_denom(b, &db);
254
/* write da = d*A, db = d*B, gcd(A,B) = 1
255
* gcd(a/(d A), b/(d B)) = gcd(a B, A b) / A B d = gcd(a B, b) / A B d */
256
if (db)
257
{
258
GEN d = gcdii(da,db);
259
if (!is_pm1(d)) db = diviiexact(db,d); /* B */
260
if (!is_pm1(db))
261
{
262
a = mulii(a, db); /* a B */
263
da = mulii(da, db); /* A B d = lcm(denom(a),denom(b)) */
264
}
265
}
266
return RgM_Rg_div(hnf_Z_ZC(nf,a,b), da);
267
}
268
static GEN
269
hnf_QC_QC(GEN nf, GEN a, GEN b)
270
{
271
GEN da, db, d, x;
272
a = Q_remove_denom(a, &da);
273
b = Q_remove_denom(b, &db);
274
if (da) b = ZC_Z_mul(b, da);
275
if (db) a = ZC_Z_mul(a, db);
276
d = mul_denom(da, db);
277
a = zk_multable(nf,a); da = zkmultable_capZ(a);
278
b = zk_multable(nf,b); db = zkmultable_capZ(b);
279
x = ZM_hnfmodid(shallowconcat(a,b), gcdii(da,db));
280
return d? RgM_Rg_div(x, d): x;
281
}
282
static GEN
283
hnf_Q_Q(GEN nf, GEN a, GEN b) {return scalarmat(Q_gcd(a,b), nf_get_degree(nf));}
284
GEN
285
idealhnf0(GEN nf, GEN a, GEN b)
286
{
287
long ta, tb;
288
pari_sp av;
289
GEN x;
290
if (!b) return idealhnf(nf,a);
291
292
/* HNF of aZ_K+bZ_K */
293
av = avma; nf = checknf(nf);
294
a = nf_to_scalar_or_basis(nf,a); ta = typ(a);
295
b = nf_to_scalar_or_basis(nf,b); tb = typ(b);
296
if (ta == t_COL)
297
x = (tb==t_COL)? hnf_QC_QC(nf, a,b): hnf_Q_QC(nf, b,a);
298
else
299
x = (tb==t_COL)? hnf_Q_QC(nf, a,b): hnf_Q_Q(nf, a,b);
300
return gerepileupto(av, x);
301
}
302
303
/*******************************************************************/
304
/* */
305
/* TWO-ELEMENT FORM */
306
/* */
307
/*******************************************************************/
308
static GEN idealapprfact_i(GEN nf, GEN x, int nored);
309
310
static int
311
ok_elt(GEN x, GEN xZ, GEN y)
312
{
313
pari_sp av = avma;
314
return gc_bool(av, ZM_equal(x, ZM_hnfmodid(y, xZ)));
315
}
316
317
static GEN
318
addmul_col(GEN a, long s, GEN b)
319
{
320
long i,l;
321
if (!s) return a? leafcopy(a): a;
322
if (!a) return gmulsg(s,b);
323
l = lg(a);
324
for (i=1; i<l; i++)
325
if (signe(gel(b,i))) gel(a,i) = addii(gel(a,i), mulsi(s, gel(b,i)));
326
return a;
327
}
328
329
/* a <-- a + s * b, all coeffs integers */
330
static GEN
331
addmul_mat(GEN a, long s, GEN b)
332
{
333
long j,l;
334
/* copy otherwise next call corrupts a */
335
if (!s) return a? RgM_shallowcopy(a): a;
336
if (!a) return gmulsg(s,b);
337
l = lg(a);
338
for (j=1; j<l; j++)
339
(void)addmul_col(gel(a,j), s, gel(b,j));
340
return a;
341
}
342
343
static GEN
344
get_random_a(GEN nf, GEN x, GEN xZ)
345
{
346
pari_sp av;
347
long i, lm, l = lg(x);
348
GEN a, z, beta, mul;
349
350
beta= cgetg(l, t_VEC);
351
mul = cgetg(l, t_VEC); lm = 1; /* = lg(mul) */
352
/* look for a in x such that a O/xZ = x O/xZ */
353
for (i = 2; i < l; i++)
354
{
355
GEN xi = gel(x,i);
356
GEN t = FpM_red(zk_multable(nf,xi), xZ); /* ZM, cannot be a scalar */
357
if (gequal0(t)) continue;
358
if (ok_elt(x,xZ, t)) return xi;
359
gel(beta,lm) = xi;
360
/* mul[i] = { canonical generators for x[i] O/xZ as Z-module } */
361
gel(mul,lm) = t; lm++;
362
}
363
setlg(mul, lm);
364
setlg(beta,lm);
365
z = cgetg(lm, t_VECSMALL);
366
for(av = avma;; set_avma(av))
367
{
368
for (a=NULL,i=1; i<lm; i++)
369
{
370
long t = random_bits(4) - 7; /* in [-7,8] */
371
z[i] = t;
372
a = addmul_mat(a, t, gel(mul,i));
373
}
374
/* a = matrix (NOT HNF) of ideal generated by beta.z in O/xZ */
375
if (a && ok_elt(x,xZ, a)) break;
376
}
377
for (a=NULL,i=1; i<lm; i++)
378
a = addmul_col(a, z[i], gel(beta,i));
379
return a;
380
}
381
382
/* x square matrix, assume it is HNF */
383
static GEN
384
mat_ideal_two_elt(GEN nf, GEN x)
385
{
386
GEN y, a, cx, xZ;
387
long N = nf_get_degree(nf);
388
pari_sp av, tetpil;
389
390
if (lg(x)-1 != N) pari_err_DIM("idealtwoelt");
391
if (N == 2) return mkvec2copy(gcoeff(x,1,1), gel(x,2));
392
393
y = cgetg(3,t_VEC); av = avma;
394
cx = Q_content(x);
395
xZ = gcoeff(x,1,1);
396
if (gequal(xZ, cx)) /* x = (cx) */
397
{
398
gel(y,1) = cx;
399
gel(y,2) = gen_0; return y;
400
}
401
if (equali1(cx)) cx = NULL;
402
else
403
{
404
x = Q_div_to_int(x, cx);
405
xZ = gcoeff(x,1,1);
406
}
407
if (N < 6)
408
a = get_random_a(nf, x, xZ);
409
else
410
{
411
const long FB[] = { _evallg(15+1) | evaltyp(t_VECSMALL),
412
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47
413
};
414
GEN P, E, a1 = Z_lsmoothen(xZ, (GEN)FB, &P, &E);
415
if (!a1) /* factors completely */
416
a = idealapprfact_i(nf, idealfactor(nf,x), 1);
417
else if (lg(P) == 1) /* no small factors */
418
a = get_random_a(nf, x, xZ);
419
else /* general case */
420
{
421
GEN A0, A1, a0, u0, u1, v0, v1, pi0, pi1, t, u;
422
a0 = diviiexact(xZ, a1);
423
A0 = ZM_hnfmodid(x, a0); /* smooth part of x */
424
A1 = ZM_hnfmodid(x, a1); /* cofactor */
425
pi0 = idealapprfact_i(nf, idealfactor(nf,A0), 1);
426
pi1 = get_random_a(nf, A1, a1);
427
(void)bezout(a0, a1, &v0,&v1);
428
u0 = mulii(a0, v0);
429
u1 = mulii(a1, v1);
430
if (typ(pi0) != t_COL) t = addmulii(u0, pi0, u1);
431
else
432
{ t = ZC_Z_mul(pi0, u1); gel(t,1) = addii(gel(t,1), u0); }
433
u = ZC_Z_mul(pi1, u0); gel(u,1) = addii(gel(u,1), u1);
434
a = nfmuli(nf, centermod(u, xZ), centermod(t, xZ));
435
}
436
}
437
if (cx)
438
{
439
a = centermod(a, xZ);
440
tetpil = avma;
441
if (typ(cx) == t_INT)
442
{
443
gel(y,1) = mulii(xZ, cx);
444
gel(y,2) = ZC_Z_mul(a, cx);
445
}
446
else
447
{
448
gel(y,1) = gmul(xZ, cx);
449
gel(y,2) = RgC_Rg_mul(a, cx);
450
}
451
}
452
else
453
{
454
tetpil = avma;
455
gel(y,1) = icopy(xZ);
456
gel(y,2) = centermod(a, xZ);
457
}
458
gerepilecoeffssp(av,tetpil,y+1,2); return y;
459
}
460
461
/* Given an ideal x, returns [a,alpha] such that a is in Q,
462
* x = a Z_K + alpha Z_K, alpha in K^*
463
* a = 0 or alpha = 0 are possible, but do not try to determine whether
464
* x is principal. */
465
GEN
466
idealtwoelt(GEN nf, GEN x)
467
{
468
pari_sp av;
469
GEN z;
470
long tx = idealtyp(&x,&z);
471
nf = checknf(nf);
472
if (tx == id_MAT) return mat_ideal_two_elt(nf,x);
473
if (tx == id_PRIME) return mkvec2copy(gel(x,1), gel(x,2));
474
/* id_PRINCIPAL */
475
av = avma; x = nf_to_scalar_or_basis(nf, x);
476
return gerepilecopy(av, typ(x)==t_COL? mkvec2(gen_0,x):
477
mkvec2(Q_abs_shallow(x),gen_0));
478
}
479
480
/*******************************************************************/
481
/* */
482
/* FACTORIZATION */
483
/* */
484
/*******************************************************************/
485
/* x integral ideal in HNF, Zval = v_p(x \cap Z) > 0; return v_p(Nx) */
486
static long
487
idealHNF_norm_pval(GEN x, GEN p, long Zval)
488
{
489
long i, v = Zval, l = lg(x);
490
for (i = 2; i < l; i++) v += Z_pval(gcoeff(x,i,i), p);
491
return v;
492
}
493
494
/* x integral in HNF, f0 = partial factorization of a multiple of
495
* x[1,1] = x\cap Z */
496
GEN
497
idealHNF_Z_factor_i(GEN x, GEN f0, GEN *pvN, GEN *pvZ)
498
{
499
GEN P, E, vN, vZ, xZ = gcoeff(x,1,1), f = f0? f0: Z_factor(xZ);
500
long i, l;
501
P = gel(f,1); l = lg(P);
502
E = gel(f,2);
503
*pvN = vN = cgetg(l, t_VECSMALL);
504
*pvZ = vZ = cgetg(l, t_VECSMALL);
505
for (i = 1; i < l; i++)
506
{
507
GEN p = gel(P,i);
508
vZ[i] = f0? Z_pval(xZ, p): (long) itou(gel(E,i));
509
vN[i] = idealHNF_norm_pval(x,p, vZ[i]);
510
}
511
return P;
512
}
513
/* return P, primes dividing Nx and xZ = x\cap Z, set v_p(Nx), v_p(xZ);
514
* x integral in HNF */
515
GEN
516
idealHNF_Z_factor(GEN x, GEN *pvN, GEN *pvZ)
517
{ return idealHNF_Z_factor_i(x, NULL, pvN, pvZ); }
518
519
/* v_P(A)*f(P) <= Nval [e.g. Nval = v_p(Norm A)], Zval = v_p(A \cap Z).
520
* Return v_P(A) */
521
static long
522
idealHNF_val(GEN A, GEN P, long Nval, long Zval)
523
{
524
long f = pr_get_f(P), vmax, v, e, i, j, k, l;
525
GEN mul, B, a, y, r, p, pk, cx, vals;
526
pari_sp av;
527
528
if (Nval < f) return 0;
529
p = pr_get_p(P);
530
e = pr_get_e(P);
531
/* v_P(A) <= max [ e * v_p(A \cap Z), floor[v_p(Nix) / f ] */
532
vmax = minss(Zval * e, Nval / f);
533
mul = pr_get_tau(P);
534
l = lg(mul);
535
B = cgetg(l,t_MAT);
536
/* B[1] not needed: v_pr(A[1]) = v_pr(A \cap Z) is known already */
537
gel(B,1) = gen_0; /* dummy */
538
for (j = 2; j < l; j++)
539
{
540
GEN x = gel(A,j);
541
gel(B,j) = y = cgetg(l, t_COL);
542
for (i = 1; i < l; i++)
543
{ /* compute a = (x.t0)_i, A in HNF ==> x[j+1..l-1] = 0 */
544
a = mulii(gel(x,1), gcoeff(mul,i,1));
545
for (k = 2; k <= j; k++) a = addii(a, mulii(gel(x,k), gcoeff(mul,i,k)));
546
/* p | a ? */
547
gel(y,i) = dvmdii(a,p,&r); if (signe(r)) return 0;
548
}
549
}
550
vals = cgetg(l, t_VECSMALL);
551
/* vals[1] not needed */
552
for (j = 2; j < l; j++)
553
{
554
gel(B,j) = Q_primitive_part(gel(B,j), &cx);
555
vals[j] = cx? 1 + e * Q_pval(cx, p): 1;
556
}
557
pk = powiu(p, ceildivuu(vmax, e));
558
av = avma; y = cgetg(l,t_COL);
559
/* can compute mod p^ceil((vmax-v)/e) */
560
for (v = 1; v < vmax; v++)
561
{ /* we know v_pr(Bj) >= v for all j */
562
if (e == 1 || (vmax - v) % e == 0) pk = diviiexact(pk, p);
563
for (j = 2; j < l; j++)
564
{
565
GEN x = gel(B,j); if (v < vals[j]) continue;
566
for (i = 1; i < l; i++)
567
{
568
pari_sp av2 = avma;
569
a = mulii(gel(x,1), gcoeff(mul,i,1));
570
for (k = 2; k < l; k++) a = addii(a, mulii(gel(x,k), gcoeff(mul,i,k)));
571
/* a = (x.t_0)_i; p | a ? */
572
a = dvmdii(a,p,&r); if (signe(r)) return v;
573
if (lgefint(a) > lgefint(pk)) a = remii(a, pk);
574
gel(y,i) = gerepileuptoint(av2, a);
575
}
576
gel(B,j) = y; y = x;
577
if (gc_needed(av,3))
578
{
579
if(DEBUGMEM>1) pari_warn(warnmem,"idealval");
580
gerepileall(av,3, &y,&B,&pk);
581
}
582
}
583
}
584
return v;
585
}
586
/* true nf, x != 0 integral ideal in HNF, cx t_INT or NULL,
587
* FA integer factorization matrix or NULL. Return partial factorization of
588
* cx * x above primes in FA (complete factorization if !FA)*/
589
static GEN
590
idealHNF_factor_i(GEN nf, GEN x, GEN cx, GEN FA)
591
{
592
const long N = lg(x)-1;
593
long i, j, k, l, v;
594
GEN vN, vZ, vP, vE, vp = idealHNF_Z_factor_i(x, FA, &vN,&vZ);
595
596
l = lg(vp);
597
i = cx? expi(cx)+1: 1;
598
vP = cgetg((l+i-2)*N+1, t_COL);
599
vE = cgetg((l+i-2)*N+1, t_COL);
600
for (i = k = 1; i < l; i++)
601
{
602
GEN L, p = gel(vp,i);
603
long Nval = vN[i], Zval = vZ[i], vc = cx? Z_pvalrem(cx,p,&cx): 0;
604
if (vc)
605
{
606
L = idealprimedec(nf,p);
607
if (is_pm1(cx)) cx = NULL;
608
}
609
else
610
L = idealprimedec_limit_f(nf,p,Nval);
611
for (j = 1; Nval && j < lg(L); j++) /* !Nval => only cx contributes */
612
{
613
GEN P = gel(L,j);
614
pari_sp av = avma;
615
v = idealHNF_val(x, P, Nval, Zval);
616
set_avma(av);
617
Nval -= v*pr_get_f(P);
618
v += vc * pr_get_e(P); if (!v) continue;
619
gel(vP,k) = P;
620
gel(vE,k) = utoipos(v); k++;
621
}
622
if (vc) for (; j<lg(L); j++)
623
{
624
GEN P = gel(L,j);
625
gel(vP,k) = P;
626
gel(vE,k) = utoipos(vc * pr_get_e(P)); k++;
627
}
628
}
629
if (cx && !FA)
630
{ /* complete factorization */
631
GEN f = Z_factor(cx), cP = gel(f,1), cE = gel(f,2);
632
long lc = lg(cP);
633
for (i=1; i<lc; i++)
634
{
635
GEN p = gel(cP,i), L = idealprimedec(nf,p);
636
long vc = itos(gel(cE,i));
637
for (j=1; j<lg(L); j++)
638
{
639
GEN P = gel(L,j);
640
gel(vP,k) = P;
641
gel(vE,k) = utoipos(vc * pr_get_e(P)); k++;
642
}
643
}
644
}
645
setlg(vP, k);
646
setlg(vE, k); return mkmat2(vP, vE);
647
}
648
/* true nf, x integral ideal */
649
static GEN
650
idealHNF_factor(GEN nf, GEN x, ulong lim)
651
{
652
GEN cx, F = NULL;
653
if (lim)
654
{
655
GEN P, E;
656
long i;
657
/* strict useless because of prime table */
658
F = absZ_factor_limit(gcoeff(x,1,1), lim);
659
P = gel(F,1);
660
E = gel(F,2);
661
/* filter out entries > lim */
662
for (i = lg(P)-1; i; i--)
663
if (cmpiu(gel(P,i), lim) <= 0) break;
664
setlg(P, i+1);
665
setlg(E, i+1);
666
}
667
x = Q_primitive_part(x, &cx);
668
return idealHNF_factor_i(nf, x, cx, F);
669
}
670
/* c * vector(#L,i,L[i].e), assume results fit in ulong */
671
static GEN
672
prV_e_muls(GEN L, long c)
673
{
674
long j, l = lg(L);
675
GEN z = cgetg(l, t_COL);
676
for (j = 1; j < l; j++) gel(z,j) = stoi(c * pr_get_e(gel(L,j)));
677
return z;
678
}
679
/* true nf, y in Q */
680
static GEN
681
Q_nffactor(GEN nf, GEN y, ulong lim)
682
{
683
GEN f, P, E;
684
long l, i;
685
if (typ(y) == t_INT)
686
{
687
if (!signe(y)) pari_err_DOMAIN("idealfactor", "ideal", "=",gen_0,y);
688
if (is_pm1(y)) return trivial_fact();
689
}
690
y = Q_abs_shallow(y);
691
if (!lim) f = Q_factor(y);
692
else
693
{
694
f = Q_factor_limit(y, lim);
695
P = gel(f,1);
696
E = gel(f,2);
697
for (i = lg(P)-1; i > 0; i--)
698
if (abscmpiu(gel(P,i), lim) < 0) break;
699
setlg(P,i+1); setlg(E,i+1);
700
}
701
P = gel(f,1); l = lg(P); if (l == 1) return f;
702
E = gel(f,2);
703
for (i = 1; i < l; i++)
704
{
705
gel(P,i) = idealprimedec(nf, gel(P,i));
706
gel(E,i) = prV_e_muls(gel(P,i), itos(gel(E,i)));
707
}
708
P = shallowconcat1(P); gel(f,1) = P; settyp(P, t_COL);
709
E = shallowconcat1(E); gel(f,2) = E; return f;
710
}
711
712
GEN
713
idealfactor_partial(GEN nf, GEN x, GEN L)
714
{
715
pari_sp av = avma;
716
long i, j, l;
717
GEN P, E;
718
if (!L) return idealfactor(nf, x);
719
if (typ(L) == t_INT) return idealfactor_limit(nf, x, itou(L));
720
l = lg(L); if (l == 1) return trivial_fact();
721
P = cgetg(l, t_VEC);
722
for (i = 1; i < l; i++)
723
{
724
GEN p = gel(L,i);
725
gel(P,i) = typ(p) == t_INT? idealprimedec(nf, p): mkvec(p);
726
}
727
P = shallowconcat1(P); settyp(P, t_COL);
728
P = gen_sort_uniq(P, (void*)&cmp_prime_ideal, &cmp_nodata);
729
E = cgetg_copy(P, &l);
730
for (i = j = 1; i < l; i++)
731
{
732
long v = idealval(nf, x, gel(P,i));
733
if (v) { gel(P,j) = gel(P,i); gel(E,j) = stoi(v); j++; }
734
}
735
setlg(P,j);
736
setlg(E,j); return gerepilecopy(av, mkmat2(P, E));
737
}
738
GEN
739
idealfactor_limit(GEN nf, GEN x, ulong lim)
740
{
741
pari_sp av = avma;
742
GEN fa, y;
743
long tx = idealtyp(&x,&y);
744
745
if (tx == id_PRIME)
746
{
747
if (lim && abscmpiu(pr_get_p(x), lim) >= 0) return trivial_fact();
748
retmkmat2(mkcolcopy(x), mkcol(gen_1));
749
}
750
nf = checknf(nf);
751
if (tx == id_PRINCIPAL)
752
{
753
y = nf_to_scalar_or_basis(nf, x);
754
if (typ(y) != t_COL) return gerepilecopy(av, Q_nffactor(nf, y, lim));
755
}
756
y = idealnumden(nf, x);
757
fa = idealHNF_factor(nf, gel(y,1), lim);
758
if (!isint1(gel(y,2)))
759
fa = famat_div_shallow(fa, idealHNF_factor(nf, gel(y,2), lim));
760
fa = gerepilecopy(av, fa);
761
return sort_factor(fa, (void*)&cmp_prime_ideal, &cmp_nodata);
762
}
763
GEN
764
idealfactor(GEN nf, GEN x) { return idealfactor_limit(nf, x, 0); }
765
GEN
766
gpidealfactor(GEN nf, GEN x, GEN lim)
767
{
768
ulong L = 0;
769
if (lim)
770
{
771
if (typ(lim) != t_INT || signe(lim) < 0) pari_err_FLAG("idealfactor");
772
L = itou(lim);
773
}
774
return idealfactor_limit(nf, x, L);
775
}
776
777
static GEN
778
ramified_root(GEN nf, GEN R, GEN A, long n)
779
{
780
GEN v, P = gel(idealfactor(nf, R), 1);
781
long i, l = lg(P);
782
v = cgetg(l, t_VECSMALL);
783
for (i = 1; i < l; i++)
784
{
785
long w = idealval(nf, A, gel(P,i));
786
if (w % n) return NULL;
787
v[i] = w / n;
788
}
789
return idealfactorback(nf, P, v, 0);
790
}
791
static int
792
ramified_root_simple(GEN nf, long n, GEN P, GEN v)
793
{
794
long i, l = lg(v);
795
for (i = 1; i < l; i++) if (v[i])
796
{
797
GEN vpr = idealprimedec(nf, gel(P,i));
798
long lpr = lg(vpr), j;
799
for (j = 1; j < lpr; j++)
800
{
801
long e = pr_get_e(gel(vpr,j));
802
if ((e * v[i]) % n) return 0;
803
}
804
}
805
return 1;
806
}
807
/* true nf; A is assumed to be the n-th power of an integral ideal,
808
* return its n-th root; n > 1 */
809
static long
810
idealsqrtn_int(GEN nf, GEN A, long n, GEN *pB)
811
{
812
GEN C, root;
813
long i, l;
814
815
if (typ(A) == t_INT) /* > 0 */
816
{
817
GEN P = nf_get_ramified_primes(nf), v, q;
818
l = lg(P); v = cgetg(l, t_VECSMALL);
819
for (i = 1; i < l; i++) v[i] = Z_pvalrem(A, gel(P,i), &A);
820
C = gen_1;
821
if (!isint1(A) && !Z_ispowerall(A, n, pB? &C: NULL)) return 0;
822
if (!pB) return ramified_root_simple(nf, n, P, v);
823
q = factorback2(P, v);
824
root = ramified_root(nf, q, q, n);
825
if (!root) return 0;
826
if (!equali1(C)) root = isint1(root)? C: ZM_Z_mul(root, C);
827
*pB = root; return 1;
828
}
829
/* compute valuations at ramified primes */
830
root = ramified_root(nf, idealadd(nf, nf_get_diff(nf), A), A, n);
831
if (!root) return 0;
832
/* remove ramified primes */
833
if (isint1(root))
834
root = matid(nf_get_degree(nf));
835
else
836
A = idealdivexact(nf, A, idealpows(nf,root,n));
837
A = Q_primitive_part(A, &C);
838
if (C)
839
{
840
if (!Z_ispowerall(C,n,&C)) return 0;
841
if (pB) root = ZM_Z_mul(root, C);
842
}
843
844
/* compute final n-th root, at most degree(nf)-1 iterations */
845
for (i = 0;; i++)
846
{
847
GEN J, b, a = gcoeff(A,1,1); /* A \cap Z */
848
if (is_pm1(a)) break;
849
if (!Z_ispowerall(a,n,&b)) return 0;
850
J = idealadd(nf, b, A);
851
A = idealdivexact(nf, idealpows(nf,J,n), A);
852
/* div and not divexact here */
853
if (pB) root = odd(i)? idealdiv(nf, root, J): idealmul(nf, root, J);
854
}
855
if (pB) *pB = root;
856
return 1;
857
}
858
859
/* A is assumed to be the n-th power of an ideal in nf
860
returns its n-th root. */
861
long
862
idealispower(GEN nf, GEN A, long n, GEN *pB)
863
{
864
pari_sp av = avma;
865
GEN v, N, D;
866
nf = checknf(nf);
867
if (n <= 0) pari_err_DOMAIN("idealispower", "n", "<=", gen_0, stoi(n));
868
if (n == 1) { if (pB) *pB = idealhnf(nf,A); return 1; }
869
v = idealnumden(nf,A);
870
if (gequal0(gel(v,1))) { set_avma(av); if (pB) *pB = cgetg(1,t_MAT); return 1; }
871
if (!idealsqrtn_int(nf, gel(v,1), n, pB? &N: NULL)) return 0;
872
if (!idealsqrtn_int(nf, gel(v,2), n, pB? &D: NULL)) return 0;
873
if (pB) *pB = gerepileupto(av, idealdiv(nf,N,D)); else set_avma(av);
874
return 1;
875
}
876
877
/* x t_INT or integral nonzero ideal in HNF */
878
static GEN
879
idealredmodpower_i(GEN nf, GEN x, ulong k, ulong B)
880
{
881
GEN cx, y, U, N, F, Q;
882
if (typ(x) == t_INT)
883
{
884
if (!signe(x) || is_pm1(x)) return gen_1;
885
F = Z_factor_limit(x, B);
886
gel(F,2) = gdiventgs(gel(F,2), k);
887
return ginv(factorback(F));
888
}
889
N = gcoeff(x,1,1); if (is_pm1(N)) return gen_1;
890
F = absZ_factor_limit_strict(N, B, &U);
891
if (U)
892
{
893
GEN M = powii(gel(U,1), gel(U,2));
894
y = hnfmodid(x, M); /* coprime part to B! */
895
if (!idealispower(nf, y, k, &U)) U = NULL;
896
x = hnfmodid(x, diviiexact(N, M));
897
}
898
/* x = B-smooth part of initial x */
899
x = Q_primitive_part(x, &cx);
900
F = idealHNF_factor_i(nf, x, cx, F);
901
gel(F,2) = gdiventgs(gel(F,2), k);
902
Q = idealfactorback(nf, gel(F,1), gel(F,2), 0);
903
if (U) Q = idealmul(nf,Q,U);
904
if (typ(Q) == t_INT) return Q;
905
y = idealred_elt(nf, idealHNF_inv_Z(nf, Q));
906
return gdiv(y, gcoeff(Q,1,1));
907
}
908
GEN
909
idealredmodpower(GEN nf, GEN x, ulong n, ulong B)
910
{
911
pari_sp av = avma;
912
GEN a, b;
913
nf = checknf(nf);
914
if (!n) pari_err_DOMAIN("idealredmodpower","n", "=", gen_0, gen_0);
915
x = idealnumden(nf, x);
916
a = gel(x,1);
917
if (isintzero(a)) { set_avma(av); return gen_1; }
918
a = idealredmodpower_i(nf, gel(x,1), n, B);
919
b = idealredmodpower_i(nf, gel(x,2), n, B);
920
if (!isint1(b)) a = nf_to_scalar_or_basis(nf, nfdiv(nf, a, b));
921
return gerepilecopy(av, a);
922
}
923
924
/* P prime ideal in idealprimedec format. Return valuation(A) at P */
925
long
926
idealval(GEN nf, GEN A, GEN P)
927
{
928
pari_sp av = avma;
929
GEN a, p, cA;
930
long vcA, v, Zval, tx = idealtyp(&A,&a);
931
932
if (tx == id_PRINCIPAL) return nfval(nf,A,P);
933
checkprid(P);
934
if (tx == id_PRIME) return pr_equal(P, A)? 1: 0;
935
/* id_MAT */
936
nf = checknf(nf);
937
A = Q_primitive_part(A, &cA);
938
p = pr_get_p(P);
939
vcA = cA? Q_pval(cA,p): 0;
940
if (pr_is_inert(P)) return gc_long(av,vcA);
941
Zval = Z_pval(gcoeff(A,1,1), p);
942
if (!Zval) v = 0;
943
else
944
{
945
long Nval = idealHNF_norm_pval(A, p, Zval);
946
v = idealHNF_val(A, P, Nval, Zval);
947
}
948
return gc_long(av, vcA? v + vcA*pr_get_e(P): v);
949
}
950
GEN
951
gpidealval(GEN nf, GEN ix, GEN P)
952
{
953
long v = idealval(nf,ix,P);
954
return v == LONG_MAX? mkoo(): stoi(v);
955
}
956
957
/* gcd and generalized Bezout */
958
959
GEN
960
idealadd(GEN nf, GEN x, GEN y)
961
{
962
pari_sp av = avma;
963
long tx, ty;
964
GEN z, a, dx, dy, dz;
965
966
tx = idealtyp(&x,&z);
967
ty = idealtyp(&y,&z); nf = checknf(nf);
968
if (tx != id_MAT) x = idealhnf_shallow(nf,x);
969
if (ty != id_MAT) y = idealhnf_shallow(nf,y);
970
if (lg(x) == 1) return gerepilecopy(av,y);
971
if (lg(y) == 1) return gerepilecopy(av,x); /* check for 0 ideal */
972
dx = Q_denom(x);
973
dy = Q_denom(y); dz = lcmii(dx,dy);
974
if (is_pm1(dz)) dz = NULL; else {
975
x = Q_muli_to_int(x, dz);
976
y = Q_muli_to_int(y, dz);
977
}
978
a = gcdii(gcoeff(x,1,1), gcoeff(y,1,1));
979
if (is_pm1(a))
980
{
981
long N = lg(x)-1;
982
if (!dz) { set_avma(av); return matid(N); }
983
return gerepileupto(av, scalarmat(ginv(dz), N));
984
}
985
z = ZM_hnfmodid(shallowconcat(x,y), a);
986
if (dz) z = RgM_Rg_div(z,dz);
987
return gerepileupto(av,z);
988
}
989
990
static GEN
991
trivial_merge(GEN x)
992
{ return (lg(x) == 1 || !is_pm1(gcoeff(x,1,1)))? NULL: gen_1; }
993
/* true nf */
994
static GEN
995
_idealaddtoone(GEN nf, GEN x, GEN y, long red)
996
{
997
GEN a;
998
long tx = idealtyp(&x, &a/*junk*/);
999
long ty = idealtyp(&y, &a/*junk*/);
1000
long ea;
1001
if (tx != id_MAT) x = idealhnf_shallow(nf, x);
1002
if (ty != id_MAT) y = idealhnf_shallow(nf, y);
1003
if (lg(x) == 1)
1004
a = trivial_merge(y);
1005
else if (lg(y) == 1)
1006
a = trivial_merge(x);
1007
else
1008
a = hnfmerge_get_1(x, y);
1009
if (!a) pari_err_COPRIME("idealaddtoone",x,y);
1010
if (red && (ea = gexpo(a)) > 10)
1011
{
1012
GEN b = (typ(a) == t_COL)? a: scalarcol_shallow(a, nf_get_degree(nf));
1013
b = ZC_reducemodlll(b, idealHNF_mul(nf,x,y));
1014
if (gexpo(b) < ea) a = b;
1015
}
1016
return a;
1017
}
1018
/* true nf */
1019
GEN
1020
idealaddtoone_i(GEN nf, GEN x, GEN y)
1021
{ return _idealaddtoone(nf, x, y, 1); }
1022
/* true nf */
1023
GEN
1024
idealaddtoone_raw(GEN nf, GEN x, GEN y)
1025
{ return _idealaddtoone(nf, x, y, 0); }
1026
1027
GEN
1028
idealaddtoone(GEN nf, GEN x, GEN y)
1029
{
1030
GEN z = cgetg(3,t_VEC), a;
1031
pari_sp av = avma;
1032
nf = checknf(nf);
1033
a = gerepileupto(av, idealaddtoone_i(nf,x,y));
1034
gel(z,1) = a;
1035
gel(z,2) = typ(a) == t_COL? Z_ZC_sub(gen_1,a): subui(1,a);
1036
return z;
1037
}
1038
1039
/* assume elements of list are integral ideals */
1040
GEN
1041
idealaddmultoone(GEN nf, GEN list)
1042
{
1043
pari_sp av = avma;
1044
long N, i, l, nz, tx = typ(list);
1045
GEN H, U, perm, L;
1046
1047
nf = checknf(nf); N = nf_get_degree(nf);
1048
if (!is_vec_t(tx)) pari_err_TYPE("idealaddmultoone",list);
1049
l = lg(list);
1050
L = cgetg(l, t_VEC);
1051
if (l == 1)
1052
pari_err_DOMAIN("idealaddmultoone", "sum(ideals)", "!=", gen_1, L);
1053
nz = 0; /* number of nonzero ideals in L */
1054
for (i=1; i<l; i++)
1055
{
1056
GEN I = gel(list,i);
1057
if (typ(I) != t_MAT) I = idealhnf_shallow(nf,I);
1058
if (lg(I) != 1)
1059
{
1060
nz++; RgM_check_ZM(I,"idealaddmultoone");
1061
if (lgcols(I) != N+1) pari_err_TYPE("idealaddmultoone [not an ideal]", I);
1062
}
1063
gel(L,i) = I;
1064
}
1065
H = ZM_hnfperm(shallowconcat1(L), &U, &perm);
1066
if (lg(H) == 1 || !equali1(gcoeff(H,1,1)))
1067
pari_err_DOMAIN("idealaddmultoone", "sum(ideals)", "!=", gen_1, L);
1068
for (i=1; i<=N; i++)
1069
if (perm[i] == 1) break;
1070
U = gel(U,(nz-1)*N + i); /* (L[1]|...|L[nz]) U = 1 */
1071
nz = 0;
1072
for (i=1; i<l; i++)
1073
{
1074
GEN c = gel(L,i);
1075
if (lg(c) == 1)
1076
c = gen_0;
1077
else {
1078
c = ZM_ZC_mul(c, vecslice(U, nz*N + 1, (nz+1)*N));
1079
nz++;
1080
}
1081
gel(L,i) = c;
1082
}
1083
return gerepilecopy(av, L);
1084
}
1085
1086
/* multiplication */
1087
1088
/* x integral ideal (without archimedean component) in HNF form
1089
* y = [a,alpha] corresponds to the integral ideal aZ_K+alpha Z_K, a in Z,
1090
* alpha a ZV or a ZM (multiplication table). Multiply them */
1091
static GEN
1092
idealHNF_mul_two(GEN nf, GEN x, GEN y)
1093
{
1094
GEN m, a = gel(y,1), alpha = gel(y,2);
1095
long i, N;
1096
1097
if (typ(alpha) != t_MAT)
1098
{
1099
alpha = zk_scalar_or_multable(nf, alpha);
1100
if (typ(alpha) == t_INT) /* e.g. y inert ? 0 should not (but may) occur */
1101
return signe(a)? ZM_Z_mul(x, gcdii(a, alpha)): cgetg(1,t_MAT);
1102
}
1103
N = lg(x)-1; m = cgetg((N<<1)+1,t_MAT);
1104
for (i=1; i<=N; i++) gel(m,i) = ZM_ZC_mul(alpha,gel(x,i));
1105
for (i=1; i<=N; i++) gel(m,i+N) = ZC_Z_mul(gel(x,i), a);
1106
return ZM_hnfmodid(m, mulii(a, gcoeff(x,1,1)));
1107
}
1108
1109
/* Assume x and y are integral in HNF form [NOT extended]. Not memory clean.
1110
* HACK: ideal in y can be of the form [a,b], a in Z, b in Z_K */
1111
GEN
1112
idealHNF_mul(GEN nf, GEN x, GEN y)
1113
{
1114
GEN z;
1115
if (typ(y) == t_VEC)
1116
z = idealHNF_mul_two(nf,x,y);
1117
else
1118
{ /* reduce one ideal to two-elt form. The smallest */
1119
GEN xZ = gcoeff(x,1,1), yZ = gcoeff(y,1,1);
1120
if (cmpii(xZ, yZ) < 0)
1121
{
1122
if (is_pm1(xZ)) return gcopy(y);
1123
z = idealHNF_mul_two(nf, y, mat_ideal_two_elt(nf,x));
1124
}
1125
else
1126
{
1127
if (is_pm1(yZ)) return gcopy(x);
1128
z = idealHNF_mul_two(nf, x, mat_ideal_two_elt(nf,y));
1129
}
1130
}
1131
return z;
1132
}
1133
1134
/* operations on elements in factored form */
1135
1136
GEN
1137
famat_mul_shallow(GEN f, GEN g)
1138
{
1139
if (typ(f) != t_MAT) f = to_famat_shallow(f,gen_1);
1140
if (typ(g) != t_MAT) g = to_famat_shallow(g,gen_1);
1141
if (lgcols(f) == 1) return g;
1142
if (lgcols(g) == 1) return f;
1143
return mkmat2(shallowconcat(gel(f,1), gel(g,1)),
1144
shallowconcat(gel(f,2), gel(g,2)));
1145
}
1146
GEN
1147
famat_mulpow_shallow(GEN f, GEN g, GEN e)
1148
{
1149
if (!signe(e)) return f;
1150
return famat_mul_shallow(f, famat_pow_shallow(g, e));
1151
}
1152
1153
GEN
1154
famat_mulpows_shallow(GEN f, GEN g, long e)
1155
{
1156
if (e==0) return f;
1157
return famat_mul_shallow(f, famat_pows_shallow(g, e));
1158
}
1159
1160
GEN
1161
famat_div_shallow(GEN f, GEN g)
1162
{ return famat_mul_shallow(f, famat_inv_shallow(g)); }
1163
1164
GEN
1165
to_famat(GEN x, GEN y) { retmkmat2(mkcolcopy(x), mkcolcopy(y)); }
1166
GEN
1167
to_famat_shallow(GEN x, GEN y) { return mkmat2(mkcol(x), mkcol(y)); }
1168
1169
/* concat the single elt x; not gconcat since x may be a t_COL */
1170
static GEN
1171
append(GEN v, GEN x)
1172
{
1173
long i, l = lg(v);
1174
GEN w = cgetg(l+1, typ(v));
1175
for (i=1; i<l; i++) gel(w,i) = gcopy(gel(v,i));
1176
gel(w,i) = gcopy(x); return w;
1177
}
1178
/* add x^1 to famat f */
1179
static GEN
1180
famat_add(GEN f, GEN x)
1181
{
1182
GEN h = cgetg(3,t_MAT);
1183
if (lgcols(f) == 1)
1184
{
1185
gel(h,1) = mkcolcopy(x);
1186
gel(h,2) = mkcol(gen_1);
1187
}
1188
else
1189
{
1190
gel(h,1) = append(gel(f,1), x);
1191
gel(h,2) = gconcat(gel(f,2), gen_1);
1192
}
1193
return h;
1194
}
1195
/* add x^-1 to famat f */
1196
static GEN
1197
famat_sub(GEN f, GEN x)
1198
{
1199
GEN h = cgetg(3,t_MAT);
1200
if (lgcols(f) == 1)
1201
{
1202
gel(h,1) = mkcolcopy(x);
1203
gel(h,2) = mkcol(gen_m1);
1204
}
1205
else
1206
{
1207
gel(h,1) = append(gel(f,1), x);
1208
gel(h,2) = gconcat(gel(f,2), gen_m1);
1209
}
1210
return h;
1211
}
1212
1213
GEN
1214
famat_mul(GEN f, GEN g)
1215
{
1216
GEN h;
1217
if (typ(g) != t_MAT) {
1218
if (typ(f) == t_MAT) return famat_add(f, g);
1219
h = cgetg(3, t_MAT);
1220
gel(h,1) = mkcol2(gcopy(f), gcopy(g));
1221
gel(h,2) = mkcol2(gen_1, gen_1);
1222
}
1223
if (typ(f) != t_MAT) return famat_add(g, f);
1224
if (lgcols(f) == 1) return gcopy(g);
1225
if (lgcols(g) == 1) return gcopy(f);
1226
h = cgetg(3,t_MAT);
1227
gel(h,1) = gconcat(gel(f,1), gel(g,1));
1228
gel(h,2) = gconcat(gel(f,2), gel(g,2));
1229
return h;
1230
}
1231
1232
GEN
1233
famat_div(GEN f, GEN g)
1234
{
1235
GEN h;
1236
if (typ(g) != t_MAT) {
1237
if (typ(f) == t_MAT) return famat_sub(f, g);
1238
h = cgetg(3, t_MAT);
1239
gel(h,1) = mkcol2(gcopy(f), gcopy(g));
1240
gel(h,2) = mkcol2(gen_1, gen_m1);
1241
}
1242
if (typ(f) != t_MAT) return famat_sub(g, f);
1243
if (lgcols(f) == 1) return famat_inv(g);
1244
if (lgcols(g) == 1) return gcopy(f);
1245
h = cgetg(3,t_MAT);
1246
gel(h,1) = gconcat(gel(f,1), gel(g,1));
1247
gel(h,2) = gconcat(gel(f,2), gneg(gel(g,2)));
1248
return h;
1249
}
1250
1251
GEN
1252
famat_sqr(GEN f)
1253
{
1254
GEN h;
1255
if (typ(f) != t_MAT) return to_famat(f,gen_2);
1256
if (lgcols(f) == 1) return gcopy(f);
1257
h = cgetg(3,t_MAT);
1258
gel(h,1) = gcopy(gel(f,1));
1259
gel(h,2) = gmul2n(gel(f,2),1);
1260
return h;
1261
}
1262
1263
GEN
1264
famat_inv_shallow(GEN f)
1265
{
1266
if (typ(f) != t_MAT) return to_famat_shallow(f,gen_m1);
1267
if (lgcols(f) == 1) return f;
1268
return mkmat2(gel(f,1), ZC_neg(gel(f,2)));
1269
}
1270
GEN
1271
famat_inv(GEN f)
1272
{
1273
if (typ(f) != t_MAT) return to_famat(f,gen_m1);
1274
if (lgcols(f) == 1) return gcopy(f);
1275
retmkmat2(gcopy(gel(f,1)), ZC_neg(gel(f,2)));
1276
}
1277
GEN
1278
famat_pow(GEN f, GEN n)
1279
{
1280
if (typ(f) != t_MAT) return to_famat(f,n);
1281
if (lgcols(f) == 1) return gcopy(f);
1282
retmkmat2(gcopy(gel(f,1)), ZC_Z_mul(gel(f,2),n));
1283
}
1284
GEN
1285
famat_pow_shallow(GEN f, GEN n)
1286
{
1287
if (is_pm1(n)) return signe(n) > 0? f: famat_inv_shallow(f);
1288
if (typ(f) != t_MAT) return to_famat_shallow(f,n);
1289
if (lgcols(f) == 1) return f;
1290
return mkmat2(gel(f,1), ZC_Z_mul(gel(f,2),n));
1291
}
1292
1293
GEN
1294
famat_pows_shallow(GEN f, long n)
1295
{
1296
if (n==1) return f;
1297
if (n==-1) return famat_inv_shallow(f);
1298
if (typ(f) != t_MAT) return to_famat_shallow(f, stoi(n));
1299
if (lgcols(f) == 1) return f;
1300
return mkmat2(gel(f,1), ZC_z_mul(gel(f,2),n));
1301
}
1302
1303
GEN
1304
famat_Z_gcd(GEN M, GEN n)
1305
{
1306
pari_sp av=avma;
1307
long i, j, l=lgcols(M);
1308
GEN F=cgetg(3,t_MAT);
1309
gel(F,1)=cgetg(l,t_COL);
1310
gel(F,2)=cgetg(l,t_COL);
1311
for (i=1, j=1; i<l; i++)
1312
{
1313
GEN p = gcoeff(M,i,1);
1314
GEN e = gminsg(Z_pval(n,p),gcoeff(M,i,2));
1315
if (signe(e))
1316
{
1317
gcoeff(F,j,1)=p;
1318
gcoeff(F,j,2)=e;
1319
j++;
1320
}
1321
}
1322
setlg(gel(F,1),j); setlg(gel(F,2),j);
1323
return gerepilecopy(av,F);
1324
}
1325
1326
/* x assumed to be a t_MATs (factorization matrix), or compatible with
1327
* the element_* functions. */
1328
static GEN
1329
ext_sqr(GEN nf, GEN x)
1330
{ return (typ(x)==t_MAT)? famat_sqr(x): nfsqr(nf, x); }
1331
static GEN
1332
ext_mul(GEN nf, GEN x, GEN y)
1333
{ return (typ(x)==t_MAT)? famat_mul(x,y): nfmul(nf, x, y); }
1334
static GEN
1335
ext_inv(GEN nf, GEN x)
1336
{ return (typ(x)==t_MAT)? famat_inv(x): nfinv(nf, x); }
1337
static GEN
1338
ext_pow(GEN nf, GEN x, GEN n)
1339
{ return (typ(x)==t_MAT)? famat_pow(x,n): nfpow(nf, x, n); }
1340
1341
GEN
1342
famat_to_nf(GEN nf, GEN f)
1343
{
1344
GEN t, x, e;
1345
long i;
1346
if (lgcols(f) == 1) return gen_1;
1347
x = gel(f,1);
1348
e = gel(f,2);
1349
t = nfpow(nf, gel(x,1), gel(e,1));
1350
for (i=lg(x)-1; i>1; i--)
1351
t = nfmul(nf, t, nfpow(nf, gel(x,i), gel(e,i)));
1352
return t;
1353
}
1354
1355
GEN
1356
famat_idealfactor(GEN nf, GEN x)
1357
{
1358
long i, l;
1359
GEN g = gel(x,1), e = gel(x,2), h = cgetg_copy(g, &l);
1360
for (i = 1; i < l; i++) gel(h,i) = idealfactor(nf, gel(g,i));
1361
h = famat_reduce(famatV_factorback(h,e));
1362
return sort_factor(h, (void*)&cmp_prime_ideal, &cmp_nodata);
1363
}
1364
1365
GEN
1366
famat_reduce(GEN fa)
1367
{
1368
GEN E, G, L, g, e;
1369
long i, k, l;
1370
1371
if (typ(fa) != t_MAT || lgcols(fa) == 1) return fa;
1372
g = gel(fa,1); l = lg(g);
1373
e = gel(fa,2);
1374
L = gen_indexsort(g, (void*)&cmp_universal, &cmp_nodata);
1375
G = cgetg(l, t_COL);
1376
E = cgetg(l, t_COL);
1377
/* merge */
1378
for (k=i=1; i<l; i++,k++)
1379
{
1380
gel(G,k) = gel(g,L[i]);
1381
gel(E,k) = gel(e,L[i]);
1382
if (k > 1 && gidentical(gel(G,k), gel(G,k-1)))
1383
{
1384
gel(E,k-1) = addii(gel(E,k), gel(E,k-1));
1385
k--;
1386
}
1387
}
1388
/* kill 0 exponents */
1389
l = k;
1390
for (k=i=1; i<l; i++)
1391
if (!gequal0(gel(E,i)))
1392
{
1393
gel(G,k) = gel(G,i);
1394
gel(E,k) = gel(E,i); k++;
1395
}
1396
setlg(G, k);
1397
setlg(E, k); return mkmat2(G,E);
1398
}
1399
GEN
1400
matreduce(GEN f)
1401
{ pari_sp av = avma;
1402
switch(typ(f))
1403
{
1404
case t_VEC: case t_COL:
1405
{
1406
GEN e; f = vec_reduce(f, &e); settyp(f, t_COL);
1407
return gerepilecopy(av, mkmat2(f, zc_to_ZC(e)));
1408
}
1409
case t_MAT:
1410
if (lg(f) == 3) break;
1411
default:
1412
pari_err_TYPE("matreduce", f);
1413
}
1414
if (typ(gel(f,1)) == t_VECSMALL)
1415
f = famatsmall_reduce(f);
1416
else
1417
{
1418
if (!RgV_is_ZV(gel(f,2))) pari_err_TYPE("matreduce",f);
1419
f = famat_reduce(f);
1420
}
1421
return gerepilecopy(av, f);
1422
}
1423
1424
GEN
1425
famatsmall_reduce(GEN fa)
1426
{
1427
GEN E, G, L, g, e;
1428
long i, k, l;
1429
if (lgcols(fa) == 1) return fa;
1430
g = gel(fa,1); l = lg(g);
1431
e = gel(fa,2);
1432
L = vecsmall_indexsort(g);
1433
G = cgetg(l, t_VECSMALL);
1434
E = cgetg(l, t_VECSMALL);
1435
/* merge */
1436
for (k=i=1; i<l; i++,k++)
1437
{
1438
G[k] = g[L[i]];
1439
E[k] = e[L[i]];
1440
if (k > 1 && G[k] == G[k-1])
1441
{
1442
E[k-1] += E[k];
1443
k--;
1444
}
1445
}
1446
/* kill 0 exponents */
1447
l = k;
1448
for (k=i=1; i<l; i++)
1449
if (E[i])
1450
{
1451
G[k] = G[i];
1452
E[k] = E[i]; k++;
1453
}
1454
setlg(G, k);
1455
setlg(E, k); return mkmat2(G,E);
1456
}
1457
1458
GEN
1459
famat_remove_trivial(GEN fa)
1460
{
1461
GEN P, E, p = gel(fa,1), e = gel(fa,2);
1462
long j, k, l = lg(p);
1463
P = cgetg(l, t_COL);
1464
E = cgetg(l, t_COL);
1465
for (j = k = 1; j < l; j++)
1466
if (signe(gel(e,j))) { gel(P,k) = gel(p,j); gel(E,k++) = gel(e,j); }
1467
setlg(P, k); setlg(E, k); return mkmat2(P,E);
1468
}
1469
1470
GEN
1471
famatV_factorback(GEN v, GEN e)
1472
{
1473
long i, l = lg(e);
1474
GEN V;
1475
if (l == 1) return trivial_fact();
1476
V = signe(gel(e,1))? famat_pow_shallow(gel(v,1), gel(e,1)): trivial_fact();
1477
for (i = 2; i < l; i++) V = famat_mulpow_shallow(V, gel(v,i), gel(e,i));
1478
return V;
1479
}
1480
1481
GEN
1482
famatV_zv_factorback(GEN v, GEN e)
1483
{
1484
long i, l = lg(e);
1485
GEN V;
1486
if (l == 1) return trivial_fact();
1487
V = uel(e,1)? famat_pows_shallow(gel(v,1), uel(e,1)): trivial_fact();
1488
for (i = 2; i < l; i++) V = famat_mulpows_shallow(V, gel(v,i), uel(e,i));
1489
return V;
1490
}
1491
1492
GEN
1493
ZM_famat_limit(GEN fa, GEN limit)
1494
{
1495
pari_sp av;
1496
GEN E, G, g, e, r;
1497
long i, k, l, n, lG;
1498
1499
if (lgcols(fa) == 1) return fa;
1500
g = gel(fa,1); l = lg(g);
1501
e = gel(fa,2);
1502
for(n=0, i=1; i<l; i++)
1503
if (cmpii(gel(g,i),limit)<=0) n++;
1504
lG = n<l-1 ? n+2 : n+1;
1505
G = cgetg(lG, t_COL);
1506
E = cgetg(lG, t_COL);
1507
av = avma;
1508
for (i=1, k=1, r = gen_1; i<l; i++)
1509
{
1510
if (cmpii(gel(g,i),limit)<=0)
1511
{
1512
gel(G,k) = gel(g,i);
1513
gel(E,k) = gel(e,i);
1514
k++;
1515
} else r = mulii(r, powii(gel(g,i), gel(e,i)));
1516
}
1517
if (k<i)
1518
{
1519
gel(G, k) = gerepileuptoint(av, r);
1520
gel(E, k) = gen_1;
1521
}
1522
return mkmat2(G,E);
1523
}
1524
1525
/* assume pr has degree 1 and coprime to Q_denom(x) */
1526
static GEN
1527
to_Fp_coprime(GEN nf, GEN x, GEN modpr)
1528
{
1529
GEN d, r, p = modpr_get_p(modpr);
1530
x = nf_to_scalar_or_basis(nf,x);
1531
if (typ(x) != t_COL) return Rg_to_Fp(x,p);
1532
x = Q_remove_denom(x, &d);
1533
r = zk_to_Fq(x, modpr);
1534
if (d) r = Fp_div(r, d, p);
1535
return r;
1536
}
1537
1538
/* pr coprime to all denominators occurring in x */
1539
static GEN
1540
famat_to_Fp_coprime(GEN nf, GEN x, GEN modpr)
1541
{
1542
GEN p = modpr_get_p(modpr);
1543
GEN t = NULL, g = gel(x,1), e = gel(x,2), q = subiu(p,1);
1544
long i, l = lg(g);
1545
for (i = 1; i < l; i++)
1546
{
1547
GEN n = modii(gel(e,i), q);
1548
if (signe(n))
1549
{
1550
GEN h = to_Fp_coprime(nf, gel(g,i), modpr);
1551
h = Fp_pow(h, n, p);
1552
t = t? Fp_mul(t, h, p): h;
1553
}
1554
}
1555
return t? modii(t, p): gen_1;
1556
}
1557
1558
/* cf famat_to_nf_modideal_coprime, modpr attached to prime of degree 1 */
1559
GEN
1560
nf_to_Fp_coprime(GEN nf, GEN x, GEN modpr)
1561
{
1562
return typ(x)==t_MAT? famat_to_Fp_coprime(nf, x, modpr)
1563
: to_Fp_coprime(nf, x, modpr);
1564
}
1565
1566
static long
1567
zk_pvalrem(GEN x, GEN p, GEN *py)
1568
{ return (typ(x) == t_INT)? Z_pvalrem(x, p, py): ZV_pvalrem(x, p, py); }
1569
/* x a QC or Q. Return a ZC or Z, whose content is coprime to Z. Set v, dx
1570
* such that x = p^v (newx / dx); dx = NULL if 1 */
1571
static GEN
1572
nf_remove_denom_p(GEN nf, GEN x, GEN p, GEN *pdx, long *pv)
1573
{
1574
long vcx;
1575
GEN dx;
1576
x = nf_to_scalar_or_basis(nf, x);
1577
x = Q_remove_denom(x, &dx);
1578
if (dx)
1579
{
1580
vcx = - Z_pvalrem(dx, p, &dx);
1581
if (!vcx) vcx = zk_pvalrem(x, p, &x);
1582
if (isint1(dx)) dx = NULL;
1583
}
1584
else
1585
{
1586
vcx = zk_pvalrem(x, p, &x);
1587
dx = NULL;
1588
}
1589
*pv = vcx;
1590
*pdx = dx; return x;
1591
}
1592
/* x = b^e/p^(e-1) in Z_K; x = 0 mod p/pr^e, (x,pr) = 1. Return NULL
1593
* if p inert (instead of 1) */
1594
static GEN
1595
p_makecoprime(GEN pr)
1596
{
1597
GEN B = pr_get_tau(pr), b;
1598
long i, e;
1599
1600
if (typ(B) == t_INT) return NULL;
1601
b = gel(B,1); /* B = multiplication table by b */
1602
e = pr_get_e(pr);
1603
if (e == 1) return b;
1604
/* one could also divide (exactly) by p in each iteration */
1605
for (i = 1; i < e; i++) b = ZM_ZC_mul(B, b);
1606
return ZC_Z_divexact(b, powiu(pr_get_p(pr), e-1));
1607
}
1608
1609
/* Compute A = prod g[i]^e[i] mod pr^k, assuming (A, pr) = 1.
1610
* Method: modify each g[i] so that it becomes coprime to pr,
1611
* g[i] *= (b/p)^v_pr(g[i]), where b/p = pr^(-1) times something integral
1612
* and prime to p; globally, we multiply by (b/p)^v_pr(A) = 1.
1613
* Optimizations:
1614
* 1) remove all powers of p from contents, and consider extra generator p^vp;
1615
* modified as p * (b/p)^e = b^e / p^(e-1)
1616
* 2) remove denominators, coprime to p, by multiplying by inverse mod prk\cap Z
1617
*
1618
* EX = multiple of exponent of (O_K / pr^k)^* used to reduce the product in
1619
* case the e[i] are large */
1620
GEN
1621
famat_makecoprime(GEN nf, GEN g, GEN e, GEN pr, GEN prk, GEN EX)
1622
{
1623
GEN G, E, t, vp = NULL, p = pr_get_p(pr), prkZ = gcoeff(prk, 1,1);
1624
long i, l = lg(g);
1625
1626
G = cgetg(l+1, t_VEC);
1627
E = cgetg(l+1, t_VEC); /* l+1: room for "modified p" */
1628
for (i=1; i < l; i++)
1629
{
1630
long vcx;
1631
GEN dx, x = nf_remove_denom_p(nf, gel(g,i), p, &dx, &vcx);
1632
if (vcx) /* = v_p(content(g[i])) */
1633
{
1634
GEN a = mulsi(vcx, gel(e,i));
1635
vp = vp? addii(vp, a): a;
1636
}
1637
/* x integral, content coprime to p; dx coprime to p */
1638
if (typ(x) == t_INT)
1639
{ /* x coprime to p, hence to pr */
1640
x = modii(x, prkZ);
1641
if (dx) x = Fp_div(x, dx, prkZ);
1642
}
1643
else
1644
{
1645
(void)ZC_nfvalrem(x, pr, &x); /* x *= (b/p)^v_pr(x) */
1646
x = ZC_hnfrem(FpC_red(x,prkZ), prk);
1647
if (dx) x = FpC_Fp_mul(x, Fp_inv(dx,prkZ), prkZ);
1648
}
1649
gel(G,i) = x;
1650
gel(E,i) = gel(e,i);
1651
}
1652
1653
t = vp? p_makecoprime(pr): NULL;
1654
if (!t)
1655
{ /* no need for extra generator */
1656
setlg(G,l);
1657
setlg(E,l);
1658
}
1659
else
1660
{
1661
gel(G,i) = FpC_red(t, prkZ);
1662
gel(E,i) = vp;
1663
}
1664
return famat_to_nf_modideal_coprime(nf, G, E, prk, EX);
1665
}
1666
1667
/* simplified version of famat_makecoprime for X = SUnits[1] */
1668
GEN
1669
sunits_makecoprime(GEN X, GEN pr, GEN prk)
1670
{
1671
GEN G, p = pr_get_p(pr), prkZ = gcoeff(prk,1,1);
1672
long i, l = lg(X);
1673
1674
G = cgetg(l, t_VEC);
1675
for (i = 1; i < l; i++)
1676
{
1677
GEN x = gel(X,i);
1678
if (typ(x) == t_INT) /* a prime */
1679
x = equalii(x,p)? p_makecoprime(pr): modii(x, prkZ);
1680
else
1681
{
1682
(void)ZC_nfvalrem(x, pr, &x); /* x *= (b/p)^v_pr(x) */
1683
x = ZC_hnfrem(FpC_red(x,prkZ), prk);
1684
}
1685
gel(G,i) = x;
1686
}
1687
return G;
1688
}
1689
1690
/* prod g[i]^e[i] mod bid, assume (g[i], id) = 1 and 1 < lg(g) <= lg(e) */
1691
GEN
1692
famat_to_nf_moddivisor(GEN nf, GEN g, GEN e, GEN bid)
1693
{
1694
GEN t, cyc = bid_get_cyc(bid);
1695
if (lg(cyc) == 1)
1696
t = gen_1;
1697
else
1698
t = famat_to_nf_modideal_coprime(nf, g, e, bid_get_ideal(bid),
1699
cyc_get_expo(cyc));
1700
return set_sign_mod_divisor(nf, mkmat2(g,e), t, bid_get_sarch(bid));
1701
}
1702
1703
GEN
1704
vecmul(GEN x, GEN y)
1705
{
1706
if (is_scalar_t(typ(x))) return gmul(x,y);
1707
pari_APPLY_same(vecmul(gel(x,i), gel(y,i)))
1708
}
1709
1710
GEN
1711
vecinv(GEN x)
1712
{
1713
if (is_scalar_t(typ(x))) return ginv(x);
1714
pari_APPLY_same(vecinv(gel(x,i)))
1715
}
1716
1717
GEN
1718
vecpow(GEN x, GEN n)
1719
{
1720
if (is_scalar_t(typ(x))) return powgi(x,n);
1721
pari_APPLY_same(vecpow(gel(x,i), n))
1722
}
1723
1724
GEN
1725
vecdiv(GEN x, GEN y)
1726
{
1727
if (is_scalar_t(typ(x))) return gdiv(x,y);
1728
pari_APPLY_same(vecdiv(gel(x,i), gel(y,i)))
1729
}
1730
1731
/* A ideal as a square t_MAT */
1732
static GEN
1733
idealmulelt(GEN nf, GEN x, GEN A)
1734
{
1735
long i, lx;
1736
GEN dx, dA, D;
1737
if (lg(A) == 1) return cgetg(1, t_MAT);
1738
x = nf_to_scalar_or_basis(nf,x);
1739
if (typ(x) != t_COL)
1740
return isintzero(x)? cgetg(1,t_MAT): RgM_Rg_mul(A, Q_abs_shallow(x));
1741
x = Q_remove_denom(x, &dx);
1742
A = Q_remove_denom(A, &dA);
1743
x = zk_multable(nf, x);
1744
D = mulii(zkmultable_capZ(x), gcoeff(A,1,1));
1745
x = zkC_multable_mul(A, x);
1746
settyp(x, t_MAT); lx = lg(x);
1747
/* x may contain scalars (at most 1 since the ideal is nonzero)*/
1748
for (i=1; i<lx; i++)
1749
if (typ(gel(x,i)) == t_INT)
1750
{
1751
if (i > 1) swap(gel(x,1), gel(x,i)); /* help HNF */
1752
gel(x,1) = scalarcol_shallow(gel(x,1), lx-1);
1753
break;
1754
}
1755
x = ZM_hnfmodid(x, D);
1756
dx = mul_denom(dx,dA);
1757
return dx? gdiv(x,dx): x;
1758
}
1759
1760
/* nf a true nf, tx <= ty */
1761
static GEN
1762
idealmul_aux(GEN nf, GEN x, GEN y, long tx, long ty)
1763
{
1764
GEN z, cx, cy;
1765
switch(tx)
1766
{
1767
case id_PRINCIPAL:
1768
switch(ty)
1769
{
1770
case id_PRINCIPAL:
1771
return idealhnf_principal(nf, nfmul(nf,x,y));
1772
case id_PRIME:
1773
{
1774
GEN p = pr_get_p(y), pi = pr_get_gen(y), cx;
1775
if (pr_is_inert(y)) return RgM_Rg_mul(idealhnf_principal(nf,x),p);
1776
1777
x = nf_to_scalar_or_basis(nf, x);
1778
switch(typ(x))
1779
{
1780
case t_INT:
1781
if (!signe(x)) return cgetg(1,t_MAT);
1782
return ZM_Z_mul(pr_hnf(nf,y), absi_shallow(x));
1783
case t_FRAC:
1784
return RgM_Rg_mul(pr_hnf(nf,y), Q_abs_shallow(x));
1785
}
1786
/* t_COL */
1787
x = Q_primitive_part(x, &cx);
1788
x = zk_multable(nf, x);
1789
z = shallowconcat(ZM_Z_mul(x,p), ZM_ZC_mul(x,pi));
1790
z = ZM_hnfmodid(z, mulii(p, zkmultable_capZ(x)));
1791
return cx? ZM_Q_mul(z, cx): z;
1792
}
1793
default: /* id_MAT */
1794
return idealmulelt(nf, x,y);
1795
}
1796
case id_PRIME:
1797
if (ty==id_PRIME)
1798
{ y = pr_hnf(nf,y); cy = NULL; }
1799
else
1800
y = Q_primitive_part(y, &cy);
1801
y = idealHNF_mul_two(nf,y,x);
1802
return cy? ZM_Q_mul(y,cy): y;
1803
1804
default: /* id_MAT */
1805
{
1806
long N = nf_get_degree(nf);
1807
if (lg(x)-1 != N || lg(y)-1 != N) pari_err_DIM("idealmul");
1808
x = Q_primitive_part(x, &cx);
1809
y = Q_primitive_part(y, &cy); cx = mul_content(cx,cy);
1810
y = idealHNF_mul(nf,x,y);
1811
return cx? ZM_Q_mul(y,cx): y;
1812
}
1813
}
1814
}
1815
1816
/* output the ideal product x.y */
1817
GEN
1818
idealmul(GEN nf, GEN x, GEN y)
1819
{
1820
pari_sp av;
1821
GEN res, ax, ay, z;
1822
long tx = idealtyp(&x,&ax);
1823
long ty = idealtyp(&y,&ay), f;
1824
if (tx>ty) { swap(ax,ay); swap(x,y); lswap(tx,ty); }
1825
f = (ax||ay); res = f? cgetg(3,t_VEC): NULL; /*product is an extended ideal*/
1826
av = avma;
1827
z = gerepileupto(av, idealmul_aux(checknf(nf), x,y, tx,ty));
1828
if (!f) return z;
1829
if (ax && ay)
1830
ax = ext_mul(nf, ax, ay);
1831
else
1832
ax = gcopy(ax? ax: ay);
1833
gel(res,1) = z; gel(res,2) = ax; return res;
1834
}
1835
1836
/* Return x, integral in 2-elt form, such that pr^2 = c * x. cf idealpowprime
1837
* nf = true nf */
1838
static GEN
1839
idealsqrprime(GEN nf, GEN pr, GEN *pc)
1840
{
1841
GEN p = pr_get_p(pr), q, gen;
1842
long e = pr_get_e(pr), f = pr_get_f(pr);
1843
1844
q = (e == 1)? sqri(p): p;
1845
if (e <= 2 && e * f == nf_get_degree(nf))
1846
{ /* pr^e = (p) */
1847
*pc = q;
1848
return mkvec2(gen_1,gen_0);
1849
}
1850
gen = nfsqr(nf, pr_get_gen(pr));
1851
gen = FpC_red(gen, q);
1852
*pc = NULL;
1853
return mkvec2(q, gen);
1854
}
1855
/* cf idealpow_aux */
1856
static GEN
1857
idealsqr_aux(GEN nf, GEN x, long tx)
1858
{
1859
GEN T = nf_get_pol(nf), m, cx, a, alpha;
1860
long N = degpol(T);
1861
switch(tx)
1862
{
1863
case id_PRINCIPAL:
1864
return idealhnf_principal(nf, nfsqr(nf,x));
1865
case id_PRIME:
1866
if (pr_is_inert(x)) return scalarmat(sqri(gel(x,1)), N);
1867
x = idealsqrprime(nf, x, &cx);
1868
x = idealhnf_two(nf,x);
1869
return cx? ZM_Z_mul(x, cx): x;
1870
default:
1871
x = Q_primitive_part(x, &cx);
1872
a = mat_ideal_two_elt(nf,x); alpha = gel(a,2); a = gel(a,1);
1873
alpha = nfsqr(nf,alpha);
1874
m = zk_scalar_or_multable(nf, alpha);
1875
if (typ(m) == t_INT) {
1876
x = gcdii(sqri(a), m);
1877
if (cx) x = gmul(x, gsqr(cx));
1878
x = scalarmat(x, N);
1879
}
1880
else
1881
{ /* could use gcdii(sqri(a), zkmultable_capZ(m)), but costly */
1882
x = ZM_hnfmodid(m, sqri(a));
1883
if (cx) cx = gsqr(cx);
1884
if (cx) x = ZM_Q_mul(x, cx);
1885
}
1886
return x;
1887
}
1888
}
1889
GEN
1890
idealsqr(GEN nf, GEN x)
1891
{
1892
pari_sp av;
1893
GEN res, ax, z;
1894
long tx = idealtyp(&x,&ax);
1895
res = ax? cgetg(3,t_VEC): NULL; /*product is an extended ideal*/
1896
av = avma;
1897
z = gerepileupto(av, idealsqr_aux(checknf(nf), x, tx));
1898
if (!ax) return z;
1899
gel(res,1) = z;
1900
gel(res,2) = ext_sqr(nf, ax); return res;
1901
}
1902
1903
/* norm of an ideal */
1904
GEN
1905
idealnorm(GEN nf, GEN x)
1906
{
1907
pari_sp av;
1908
GEN y;
1909
long tx;
1910
1911
switch(idealtyp(&x,&y))
1912
{
1913
case id_PRIME: return pr_norm(x);
1914
case id_MAT: return RgM_det_triangular(x);
1915
}
1916
/* id_PRINCIPAL */
1917
nf = checknf(nf); av = avma;
1918
x = nfnorm(nf, x);
1919
tx = typ(x);
1920
if (tx == t_INT) return gerepileuptoint(av, absi(x));
1921
if (tx != t_FRAC) pari_err_TYPE("idealnorm",x);
1922
return gerepileupto(av, Q_abs(x));
1923
}
1924
1925
/* x \cap Z */
1926
GEN
1927
idealdown(GEN nf, GEN x)
1928
{
1929
pari_sp av = avma;
1930
GEN y, c;
1931
switch(idealtyp(&x,&y))
1932
{
1933
case id_PRIME: return icopy(pr_get_p(x));
1934
case id_MAT: return gcopy(gcoeff(x,1,1));
1935
}
1936
/* id_PRINCIPAL */
1937
nf = checknf(nf); av = avma;
1938
x = nf_to_scalar_or_basis(nf, x);
1939
if (is_rational_t(typ(x))) return Q_abs(x);
1940
x = Q_primitive_part(x, &c);
1941
y = zkmultable_capZ(zk_multable(nf, x));
1942
return gerepilecopy(av, mul_content(c, y));
1943
}
1944
1945
/* true nf */
1946
static GEN
1947
idealismaximal_int(GEN nf, GEN p)
1948
{
1949
GEN L;
1950
if (!BPSW_psp(p)) return NULL;
1951
if (!dvdii(nf_get_index(nf), p) &&
1952
!FpX_is_irred(FpX_red(nf_get_pol(nf),p), p)) return NULL;
1953
L = idealprimedec(nf, p);
1954
return lg(L) == 2? gel(L,1): NULL;
1955
}
1956
/* true nf */
1957
static GEN
1958
idealismaximal_mat(GEN nf, GEN x)
1959
{
1960
GEN p, c, L;
1961
long i, l, f;
1962
x = Q_primitive_part(x, &c);
1963
p = gcoeff(x,1,1);
1964
if (c)
1965
{
1966
if (typ(c) == t_FRAC || !equali1(p)) return NULL;
1967
return idealismaximal_int(nf, p);
1968
}
1969
if (!BPSW_psp(p)) return NULL;
1970
l = lg(x); f = 1;
1971
for (i = 2; i < l; i++)
1972
{
1973
c = gcoeff(x,i,i);
1974
if (equalii(c, p)) f++; else if (!equali1(c)) return NULL;
1975
}
1976
L = idealprimedec_limit_f(nf, p, f);
1977
for (i = lg(L)-1; i; i--)
1978
{
1979
GEN pr = gel(L,i);
1980
if (pr_get_f(pr) != f) break;
1981
if (idealval(nf, x, pr) == 1) return pr;
1982
}
1983
return NULL;
1984
}
1985
/* true nf */
1986
static GEN
1987
idealismaximal_i(GEN nf, GEN x)
1988
{
1989
GEN L, p, pr, c;
1990
long i, l;
1991
switch(idealtyp(&x,&c))
1992
{
1993
case id_PRIME: return x;
1994
case id_MAT: return idealismaximal_mat(nf, x);
1995
}
1996
/* id_PRINCIPAL */
1997
nf = checknf(nf);
1998
x = nf_to_scalar_or_basis(nf, x);
1999
switch(typ(x))
2000
{
2001
case t_INT: return idealismaximal_int(nf, absi_shallow(x));
2002
case t_FRAC: return NULL;
2003
}
2004
x = Q_primitive_part(x, &c);
2005
if (c) return NULL;
2006
p = zkmultable_capZ(zk_multable(nf, x));
2007
L = idealprimedec(nf, p); l = lg(L); pr = NULL;
2008
for (i = 1; i < l; i++)
2009
{
2010
long v = ZC_nfval(x, gel(L,i));
2011
if (v > 1 || (v && pr)) return NULL;
2012
pr = gel(L,i);
2013
}
2014
return pr;
2015
}
2016
GEN
2017
idealismaximal(GEN nf, GEN x)
2018
{
2019
pari_sp av = avma;
2020
x = idealismaximal_i(checknf(nf), x);
2021
if (!x) { set_avma(av); return gen_0; }
2022
return gerepilecopy(av, x);
2023
}
2024
2025
/* I^(-1) = { x \in K, Tr(x D^(-1) I) \in Z }, D different of K/Q
2026
*
2027
* nf[5][6] = pp( D^(-1) ) = pp( HNF( T^(-1) ) ), T = (Tr(wi wj))
2028
* nf[5][7] = same in 2-elt form.
2029
* Assume I integral. Return the integral ideal (I\cap Z) I^(-1) */
2030
GEN
2031
idealHNF_inv_Z(GEN nf, GEN I)
2032
{
2033
GEN J, dual, IZ = gcoeff(I,1,1); /* I \cap Z */
2034
if (isint1(IZ)) return matid(lg(I)-1);
2035
J = idealHNF_mul(nf,I, gmael(nf,5,7));
2036
/* I in HNF, hence easily inverted; multiply by IZ to get integer coeffs
2037
* missing content cancels while solving the linear equation */
2038
dual = shallowtrans( hnf_divscale(J, gmael(nf,5,6), IZ) );
2039
return ZM_hnfmodid(dual, IZ);
2040
}
2041
/* I HNF with rational coefficients (denominator d). */
2042
GEN
2043
idealHNF_inv(GEN nf, GEN I)
2044
{
2045
GEN J, IQ = gcoeff(I,1,1); /* I \cap Q; d IQ = dI \cap Z */
2046
J = idealHNF_inv_Z(nf, Q_remove_denom(I, NULL)); /* = (dI)^(-1) * (d IQ) */
2047
return equali1(IQ)? J: RgM_Rg_div(J, IQ);
2048
}
2049
2050
/* return p * P^(-1) [integral] */
2051
GEN
2052
pr_inv_p(GEN pr)
2053
{
2054
if (pr_is_inert(pr)) return matid(pr_get_f(pr));
2055
return ZM_hnfmodid(pr_get_tau(pr), pr_get_p(pr));
2056
}
2057
GEN
2058
pr_inv(GEN pr)
2059
{
2060
GEN p = pr_get_p(pr);
2061
if (pr_is_inert(pr)) return scalarmat(ginv(p), pr_get_f(pr));
2062
return RgM_Rg_div(ZM_hnfmodid(pr_get_tau(pr),p), p);
2063
}
2064
2065
GEN
2066
idealinv(GEN nf, GEN x)
2067
{
2068
GEN res, ax;
2069
pari_sp av;
2070
long tx = idealtyp(&x,&ax), N;
2071
2072
res = ax? cgetg(3,t_VEC): NULL;
2073
nf = checknf(nf); av = avma;
2074
N = nf_get_degree(nf);
2075
switch (tx)
2076
{
2077
case id_MAT:
2078
if (lg(x)-1 != N) pari_err_DIM("idealinv");
2079
x = idealHNF_inv(nf,x); break;
2080
case id_PRINCIPAL:
2081
x = nf_to_scalar_or_basis(nf, x);
2082
if (typ(x) != t_COL)
2083
x = idealhnf_principal(nf,ginv(x));
2084
else
2085
{ /* nfinv + idealhnf where we already know (x) \cap Z */
2086
GEN c, d;
2087
x = Q_remove_denom(x, &c);
2088
x = zk_inv(nf, x);
2089
x = Q_remove_denom(x, &d); /* true inverse is c/d * x */
2090
if (!d) /* x and x^(-1) integral => x a unit */
2091
x = c? scalarmat(c, N): matid(N);
2092
else
2093
{
2094
c = c? gdiv(c,d): ginv(d);
2095
x = zk_multable(nf, x);
2096
x = ZM_Q_mul(ZM_hnfmodid(x,d), c);
2097
}
2098
}
2099
break;
2100
case id_PRIME:
2101
x = pr_inv(x); break;
2102
}
2103
x = gerepileupto(av,x); if (!ax) return x;
2104
gel(res,1) = x;
2105
gel(res,2) = ext_inv(nf, ax); return res;
2106
}
2107
2108
/* write x = A/B, A,B coprime integral ideals */
2109
GEN
2110
idealnumden(GEN nf, GEN x)
2111
{
2112
pari_sp av = avma;
2113
GEN x0, ax, c, d, A, B, J;
2114
long tx = idealtyp(&x,&ax);
2115
nf = checknf(nf);
2116
switch (tx)
2117
{
2118
case id_PRIME:
2119
retmkvec2(idealhnf(nf, x), gen_1);
2120
case id_PRINCIPAL:
2121
{
2122
GEN xZ, mx;
2123
x = nf_to_scalar_or_basis(nf, x);
2124
switch(typ(x))
2125
{
2126
case t_INT: return gerepilecopy(av, mkvec2(absi_shallow(x),gen_1));
2127
case t_FRAC:return gerepilecopy(av, mkvec2(absi_shallow(gel(x,1)), gel(x,2)));
2128
}
2129
/* t_COL */
2130
x = Q_remove_denom(x, &d);
2131
if (!d) return gerepilecopy(av, mkvec2(idealhnf(nf, x), gen_1));
2132
mx = zk_multable(nf, x);
2133
xZ = zkmultable_capZ(mx);
2134
x = ZM_hnfmodid(mx, xZ); /* principal ideal (x) */
2135
x0 = mkvec2(xZ, mx); /* same, for fast multiplication */
2136
break;
2137
}
2138
default: /* id_MAT */
2139
{
2140
long n = lg(x)-1;
2141
if (n == 0) return mkvec2(gen_0, gen_1);
2142
if (n != nf_get_degree(nf)) pari_err_DIM("idealnumden");
2143
x0 = x = Q_remove_denom(x, &d);
2144
if (!d) return gerepilecopy(av, mkvec2(x, gen_1));
2145
break;
2146
}
2147
}
2148
J = hnfmodid(x, d); /* = d/B */
2149
c = gcoeff(J,1,1); /* (d/B) \cap Z, divides d */
2150
B = idealHNF_inv_Z(nf, J); /* (d/B \cap Z) B/d */
2151
if (!equalii(c,d)) B = ZM_Z_mul(B, diviiexact(d,c)); /* = B ! */
2152
A = idealHNF_mul(nf, B, x0); /* d * (original x) * B = d A */
2153
A = ZM_Z_divexact(A, d); /* = A ! */
2154
return gerepilecopy(av, mkvec2(A, B));
2155
}
2156
2157
/* Return x, integral in 2-elt form, such that pr^n = c * x. Assume n != 0.
2158
* nf = true nf */
2159
static GEN
2160
idealpowprime(GEN nf, GEN pr, GEN n, GEN *pc)
2161
{
2162
GEN p = pr_get_p(pr), q, gen;
2163
2164
*pc = NULL;
2165
if (is_pm1(n)) /* n = 1 special cased for efficiency */
2166
{
2167
q = p;
2168
if (typ(pr_get_tau(pr)) == t_INT) /* inert */
2169
{
2170
*pc = (signe(n) >= 0)? p: ginv(p);
2171
return mkvec2(gen_1,gen_0);
2172
}
2173
if (signe(n) >= 0) gen = pr_get_gen(pr);
2174
else
2175
{
2176
gen = pr_get_tau(pr); /* possibly t_MAT */
2177
*pc = ginv(p);
2178
}
2179
}
2180
else if (equalis(n,2)) return idealsqrprime(nf, pr, pc);
2181
else
2182
{
2183
long e = pr_get_e(pr), f = pr_get_f(pr);
2184
GEN r, m = truedvmdis(n, e, &r);
2185
if (e * f == nf_get_degree(nf))
2186
{ /* pr^e = (p) */
2187
if (signe(m)) *pc = powii(p,m);
2188
if (!signe(r)) return mkvec2(gen_1,gen_0);
2189
q = p;
2190
gen = nfpow(nf, pr_get_gen(pr), r);
2191
}
2192
else
2193
{
2194
m = absi_shallow(m);
2195
if (signe(r)) m = addiu(m,1);
2196
q = powii(p,m); /* m = ceil(|n|/e) */
2197
if (signe(n) >= 0) gen = nfpow(nf, pr_get_gen(pr), n);
2198
else
2199
{
2200
gen = pr_get_tau(pr);
2201
if (typ(gen) == t_MAT) gen = gel(gen,1);
2202
n = negi(n);
2203
gen = ZC_Z_divexact(nfpow(nf, gen, n), powii(p, subii(n,m)));
2204
*pc = ginv(q);
2205
}
2206
}
2207
gen = FpC_red(gen, q);
2208
}
2209
return mkvec2(q, gen);
2210
}
2211
2212
/* x * pr^n. Assume x in HNF or scalar (possibly nonintegral) */
2213
GEN
2214
idealmulpowprime(GEN nf, GEN x, GEN pr, GEN n)
2215
{
2216
GEN c, cx, y;
2217
long N;
2218
2219
nf = checknf(nf);
2220
N = nf_get_degree(nf);
2221
if (!signe(n)) return typ(x) == t_MAT? x: scalarmat_shallow(x, N);
2222
2223
/* inert, special cased for efficiency */
2224
if (pr_is_inert(pr))
2225
{
2226
GEN q = powii(pr_get_p(pr), n);
2227
return typ(x) == t_MAT? RgM_Rg_mul(x,q)
2228
: scalarmat_shallow(gmul(Q_abs(x),q), N);
2229
}
2230
2231
y = idealpowprime(nf, pr, n, &c);
2232
if (typ(x) == t_MAT)
2233
{ x = Q_primitive_part(x, &cx); if (is_pm1(gcoeff(x,1,1))) x = NULL; }
2234
else
2235
{ cx = x; x = NULL; }
2236
cx = mul_content(c,cx);
2237
if (x)
2238
x = idealHNF_mul_two(nf,x,y);
2239
else
2240
x = idealhnf_two(nf,y);
2241
if (cx) x = ZM_Q_mul(x,cx);
2242
return x;
2243
}
2244
GEN
2245
idealdivpowprime(GEN nf, GEN x, GEN pr, GEN n)
2246
{
2247
return idealmulpowprime(nf,x,pr, negi(n));
2248
}
2249
2250
/* nf = true nf */
2251
static GEN
2252
idealpow_aux(GEN nf, GEN x, long tx, GEN n)
2253
{
2254
GEN T = nf_get_pol(nf), m, cx, n1, a, alpha;
2255
long N = degpol(T), s = signe(n);
2256
if (!s) return matid(N);
2257
switch(tx)
2258
{
2259
case id_PRINCIPAL:
2260
return idealhnf_principal(nf, nfpow(nf,x,n));
2261
case id_PRIME:
2262
if (pr_is_inert(x)) return scalarmat(powii(gel(x,1), n), N);
2263
x = idealpowprime(nf, x, n, &cx);
2264
x = idealhnf_two(nf,x);
2265
return cx? ZM_Q_mul(x, cx): x;
2266
default:
2267
if (is_pm1(n)) return (s < 0)? idealinv(nf, x): gcopy(x);
2268
n1 = (s < 0)? negi(n): n;
2269
2270
x = Q_primitive_part(x, &cx);
2271
a = mat_ideal_two_elt(nf,x); alpha = gel(a,2); a = gel(a,1);
2272
alpha = nfpow(nf,alpha,n1);
2273
m = zk_scalar_or_multable(nf, alpha);
2274
if (typ(m) == t_INT) {
2275
x = gcdii(powii(a,n1), m);
2276
if (s<0) x = ginv(x);
2277
if (cx) x = gmul(x, powgi(cx,n));
2278
x = scalarmat(x, N);
2279
}
2280
else
2281
{ /* could use gcdii(powii(a,n1), zkmultable_capZ(m)), but costly */
2282
x = ZM_hnfmodid(m, powii(a,n1));
2283
if (cx) cx = powgi(cx,n);
2284
if (s<0) {
2285
GEN xZ = gcoeff(x,1,1);
2286
cx = cx ? gdiv(cx, xZ): ginv(xZ);
2287
x = idealHNF_inv_Z(nf,x);
2288
}
2289
if (cx) x = ZM_Q_mul(x, cx);
2290
}
2291
return x;
2292
}
2293
}
2294
2295
/* raise the ideal x to the power n (in Z) */
2296
GEN
2297
idealpow(GEN nf, GEN x, GEN n)
2298
{
2299
pari_sp av;
2300
long tx;
2301
GEN res, ax;
2302
2303
if (typ(n) != t_INT) pari_err_TYPE("idealpow",n);
2304
tx = idealtyp(&x,&ax);
2305
res = ax? cgetg(3,t_VEC): NULL;
2306
av = avma;
2307
x = gerepileupto(av, idealpow_aux(checknf(nf), x, tx, n));
2308
if (!ax) return x;
2309
ax = ext_pow(nf, ax, n);
2310
gel(res,1) = x;
2311
gel(res,2) = ax;
2312
return res;
2313
}
2314
2315
/* Return ideal^e in number field nf. e is a C integer. */
2316
GEN
2317
idealpows(GEN nf, GEN ideal, long e)
2318
{
2319
long court[] = {evaltyp(t_INT) | _evallg(3),0,0};
2320
affsi(e,court); return idealpow(nf,ideal,court);
2321
}
2322
2323
static GEN
2324
_idealmulred(GEN nf, GEN x, GEN y)
2325
{ return idealred(nf,idealmul(nf,x,y)); }
2326
static GEN
2327
_idealsqrred(GEN nf, GEN x)
2328
{ return idealred(nf,idealsqr(nf,x)); }
2329
static GEN
2330
_mul(void *data, GEN x, GEN y) { return _idealmulred((GEN)data,x,y); }
2331
static GEN
2332
_sqr(void *data, GEN x) { return _idealsqrred((GEN)data, x); }
2333
2334
/* compute x^n (x ideal, n integer), reducing along the way */
2335
GEN
2336
idealpowred(GEN nf, GEN x, GEN n)
2337
{
2338
pari_sp av = avma, av2;
2339
long s;
2340
GEN y;
2341
2342
if (typ(n) != t_INT) pari_err_TYPE("idealpowred",n);
2343
s = signe(n); if (s == 0) return idealpow(nf,x,n);
2344
y = gen_pow_i(x, n, (void*)nf, &_sqr, &_mul);
2345
av2 = avma;
2346
if (s < 0) y = idealinv(nf,y);
2347
if (s < 0 || is_pm1(n)) y = idealred(nf,y);
2348
return avma == av2? gerepilecopy(av,y): gerepileupto(av,y);
2349
}
2350
2351
GEN
2352
idealmulred(GEN nf, GEN x, GEN y)
2353
{
2354
pari_sp av = avma;
2355
return gerepileupto(av, _idealmulred(nf,x,y));
2356
}
2357
2358
long
2359
isideal(GEN nf,GEN x)
2360
{
2361
long N, i, j, lx, tx = typ(x);
2362
pari_sp av;
2363
GEN T, xZ;
2364
2365
nf = checknf(nf); T = nf_get_pol(nf); lx = lg(x);
2366
if (tx==t_VEC && lx==3) { x = gel(x,1); tx = typ(x); lx = lg(x); }
2367
switch(tx)
2368
{
2369
case t_INT: case t_FRAC: return 1;
2370
case t_POL: return varn(x) == varn(T);
2371
case t_POLMOD: return RgX_equal_var(T, gel(x,1));
2372
case t_VEC: return get_prid(x)? 1 : 0;
2373
case t_MAT: break;
2374
default: return 0;
2375
}
2376
N = degpol(T);
2377
if (lx-1 != N) return (lx == 1);
2378
if (nbrows(x) != N) return 0;
2379
2380
av = avma; x = Q_primpart(x);
2381
if (!ZM_ishnf(x)) return 0;
2382
xZ = gcoeff(x,1,1);
2383
for (j=2; j<=N; j++)
2384
if (!dvdii(xZ, gcoeff(x,j,j))) return gc_long(av,0);
2385
for (i=2; i<=N; i++)
2386
for (j=2; j<=N; j++)
2387
if (! hnf_invimage(x, zk_ei_mul(nf,gel(x,i),j))) return gc_long(av,0);
2388
return gc_long(av,1);
2389
}
2390
2391
GEN
2392
idealdiv(GEN nf, GEN x, GEN y)
2393
{
2394
pari_sp av = avma, tetpil;
2395
GEN z = idealinv(nf,y);
2396
tetpil = avma; return gerepile(av,tetpil, idealmul(nf,x,z));
2397
}
2398
2399
/* This routine computes the quotient x/y of two ideals in the number field nf.
2400
* It assumes that the quotient is an integral ideal. The idea is to find an
2401
* ideal z dividing y such that gcd(Nx/Nz, Nz) = 1. Then
2402
*
2403
* x + (Nx/Nz) x
2404
* ----------- = ---
2405
* y + (Ny/Nz) y
2406
*
2407
* Proof: we can assume x and y are integral. Let p be any prime ideal
2408
*
2409
* If p | Nz, then it divides neither Nx/Nz nor Ny/Nz (since Nx/Nz is the
2410
* product of the integers N(x/y) and N(y/z)). Both the numerator and the
2411
* denominator on the left will be coprime to p. So will x/y, since x/y is
2412
* assumed integral and its norm N(x/y) is coprime to p.
2413
*
2414
* If instead p does not divide Nz, then v_p (Nx/Nz) = v_p (Nx) >= v_p(x).
2415
* Hence v_p (x + Nx/Nz) = v_p(x). Likewise for the denominators. QED.
2416
*
2417
* Peter Montgomery. July, 1994. */
2418
static void
2419
err_divexact(GEN x, GEN y)
2420
{ pari_err_DOMAIN("idealdivexact","denominator(x/y)", "!=",
2421
gen_1,mkvec2(x,y)); }
2422
GEN
2423
idealdivexact(GEN nf, GEN x0, GEN y0)
2424
{
2425
pari_sp av = avma;
2426
GEN x, y, xZ, yZ, Nx, Ny, Nz, cy, q, r;
2427
2428
nf = checknf(nf);
2429
x = idealhnf_shallow(nf, x0);
2430
y = idealhnf_shallow(nf, y0);
2431
if (lg(y) == 1) pari_err_INV("idealdivexact", y0);
2432
if (lg(x) == 1) { set_avma(av); return cgetg(1, t_MAT); } /* numerator is zero */
2433
y = Q_primitive_part(y, &cy);
2434
if (cy) x = RgM_Rg_div(x,cy);
2435
xZ = gcoeff(x,1,1); if (typ(xZ) != t_INT) err_divexact(x,y);
2436
yZ = gcoeff(y,1,1); if (isint1(yZ)) return gerepilecopy(av, x);
2437
Nx = idealnorm(nf,x);
2438
Ny = idealnorm(nf,y);
2439
if (typ(Nx) != t_INT) err_divexact(x,y);
2440
q = dvmdii(Nx,Ny, &r);
2441
if (signe(r)) err_divexact(x,y);
2442
if (is_pm1(q)) { set_avma(av); return matid(nf_get_degree(nf)); }
2443
/* Find a norm Nz | Ny such that gcd(Nx/Nz, Nz) = 1 */
2444
for (Nz = Ny;;) /* q = Nx/Nz */
2445
{
2446
GEN p1 = gcdii(Nz, q);
2447
if (is_pm1(p1)) break;
2448
Nz = diviiexact(Nz,p1);
2449
q = mulii(q,p1);
2450
}
2451
xZ = gcoeff(x,1,1); q = gcdii(q, xZ);
2452
if (!equalii(xZ,q))
2453
{ /* Replace x/y by x+(Nx/Nz) / y+(Ny/Nz) */
2454
x = ZM_hnfmodid(x, q);
2455
/* y reduced to unit ideal ? */
2456
if (Nz == Ny) return gerepileupto(av, x);
2457
2458
yZ = gcoeff(y,1,1); q = gcdii(diviiexact(Ny,Nz), yZ);
2459
y = ZM_hnfmodid(y, q);
2460
}
2461
yZ = gcoeff(y,1,1);
2462
y = idealHNF_mul(nf,x, idealHNF_inv_Z(nf,y));
2463
return gerepileupto(av, ZM_Z_divexact(y, yZ));
2464
}
2465
2466
GEN
2467
idealintersect(GEN nf, GEN x, GEN y)
2468
{
2469
pari_sp av = avma;
2470
long lz, lx, i;
2471
GEN z, dx, dy, xZ, yZ;;
2472
2473
nf = checknf(nf);
2474
x = idealhnf_shallow(nf,x);
2475
y = idealhnf_shallow(nf,y);
2476
if (lg(x) == 1 || lg(y) == 1) { set_avma(av); return cgetg(1,t_MAT); }
2477
x = Q_remove_denom(x, &dx);
2478
y = Q_remove_denom(y, &dy);
2479
if (dx) y = ZM_Z_mul(y, dx);
2480
if (dy) x = ZM_Z_mul(x, dy);
2481
xZ = gcoeff(x,1,1);
2482
yZ = gcoeff(y,1,1);
2483
dx = mul_denom(dx,dy);
2484
z = ZM_lll(shallowconcat(x,y), 0.99, LLL_KER); lz = lg(z);
2485
lx = lg(x);
2486
for (i=1; i<lz; i++) setlg(z[i], lx);
2487
z = ZM_hnfmodid(ZM_mul(x,z), lcmii(xZ, yZ));
2488
if (dx) z = RgM_Rg_div(z,dx);
2489
return gerepileupto(av,z);
2490
}
2491
2492
/*******************************************************************/
2493
/* */
2494
/* T2-IDEAL REDUCTION */
2495
/* */
2496
/*******************************************************************/
2497
2498
static GEN
2499
chk_vdir(GEN nf, GEN vdir)
2500
{
2501
long i, l = lg(vdir);
2502
GEN v;
2503
if (l != lg(nf_get_roots(nf))) pari_err_DIM("idealred");
2504
switch(typ(vdir))
2505
{
2506
case t_VECSMALL: return vdir;
2507
case t_VEC: break;
2508
default: pari_err_TYPE("idealred",vdir);
2509
}
2510
v = cgetg(l, t_VECSMALL);
2511
for (i = 1; i < l; i++) v[i] = itos(gceil(gel(vdir,i)));
2512
return v;
2513
}
2514
2515
static void
2516
twistG(GEN G, long r1, long i, long v)
2517
{
2518
long j, lG = lg(G);
2519
if (i <= r1) {
2520
for (j=1; j<lG; j++) gcoeff(G,i,j) = gmul2n(gcoeff(G,i,j), v);
2521
} else {
2522
long k = (i<<1) - r1;
2523
for (j=1; j<lG; j++)
2524
{
2525
gcoeff(G,k-1,j) = gmul2n(gcoeff(G,k-1,j), v);
2526
gcoeff(G,k ,j) = gmul2n(gcoeff(G,k ,j), v);
2527
}
2528
}
2529
}
2530
2531
GEN
2532
nf_get_Gtwist(GEN nf, GEN vdir)
2533
{
2534
long i, l, v, r1;
2535
GEN G;
2536
2537
if (!vdir) return nf_get_roundG(nf);
2538
if (typ(vdir) == t_MAT)
2539
{
2540
long N = nf_get_degree(nf);
2541
if (lg(vdir) != N+1 || lgcols(vdir) != N+1) pari_err_DIM("idealred");
2542
return vdir;
2543
}
2544
vdir = chk_vdir(nf, vdir);
2545
G = RgM_shallowcopy(nf_get_G(nf));
2546
r1 = nf_get_r1(nf);
2547
l = lg(vdir);
2548
for (i=1; i<l; i++)
2549
{
2550
v = vdir[i]; if (!v) continue;
2551
twistG(G, r1, i, v);
2552
}
2553
return RM_round_maxrank(G);
2554
}
2555
GEN
2556
nf_get_Gtwist1(GEN nf, long i)
2557
{
2558
GEN G = RgM_shallowcopy( nf_get_G(nf) );
2559
long r1 = nf_get_r1(nf);
2560
twistG(G, r1, i, 10);
2561
return RM_round_maxrank(G);
2562
}
2563
2564
GEN
2565
RM_round_maxrank(GEN G0)
2566
{
2567
long e, r = lg(G0)-1;
2568
pari_sp av = avma;
2569
for (e = 4; ; e <<= 1, set_avma(av))
2570
{
2571
GEN G = gmul2n(G0, e), H = ground(G);
2572
if (ZM_rank(H) == r) return H; /* maximal rank ? */
2573
}
2574
}
2575
2576
GEN
2577
idealred0(GEN nf, GEN I, GEN vdir)
2578
{
2579
pari_sp av = avma;
2580
GEN G, aI, IZ, J, y, yZ, my, c1 = NULL;
2581
long N;
2582
2583
nf = checknf(nf);
2584
N = nf_get_degree(nf);
2585
/* put first for sanity checks, unused when I obviously principal */
2586
G = nf_get_Gtwist(nf, vdir);
2587
switch (idealtyp(&I,&aI))
2588
{
2589
case id_PRIME:
2590
if (pr_is_inert(I)) {
2591
if (!aI) { set_avma(av); return matid(N); }
2592
c1 = gel(I,1); I = matid(N);
2593
goto END;
2594
}
2595
IZ = pr_get_p(I);
2596
J = pr_inv_p(I);
2597
I = idealhnf_two(nf,I);
2598
break;
2599
case id_MAT:
2600
I = Q_primitive_part(I, &c1);
2601
IZ = gcoeff(I,1,1);
2602
if (is_pm1(IZ))
2603
{
2604
if (!aI) { set_avma(av); return matid(N); }
2605
goto END;
2606
}
2607
J = idealHNF_inv_Z(nf, I);
2608
break;
2609
default: /* id_PRINCIPAL, silly case */
2610
if (gequal0(I)) I = cgetg(1,t_MAT); else { c1 = I; I = matid(N); }
2611
if (!aI) return I;
2612
goto END;
2613
}
2614
/* now I integral, HNF; and J = (I\cap Z) I^(-1), integral */
2615
y = idealpseudomin(J, G); /* small elt in (I\cap Z)I^(-1), integral */
2616
if (equalii(ZV_content(y), IZ))
2617
{ /* already reduced */
2618
if (!aI) return gerepilecopy(av, I);
2619
goto END;
2620
}
2621
2622
my = zk_multable(nf, y);
2623
I = ZM_Z_divexact(ZM_mul(my, I), IZ); /* y I / (I\cap Z), integral */
2624
c1 = mul_content(c1, IZ);
2625
my = ZM_gauss(my, col_ei(N,1)); /* y^-1 */
2626
yZ = Q_denom(my); /* (y) \cap Z */
2627
I = hnfmodid(I, yZ);
2628
if (!aI) return gerepileupto(av, I);
2629
c1 = RgC_Rg_mul(my, c1);
2630
END:
2631
if (c1) aI = ext_mul(nf, aI,c1);
2632
return gerepilecopy(av, mkvec2(I, aI));
2633
}
2634
2635
GEN
2636
idealmin(GEN nf, GEN x, GEN vdir)
2637
{
2638
pari_sp av = avma;
2639
GEN y, dx;
2640
nf = checknf(nf);
2641
switch( idealtyp(&x,&y) )
2642
{
2643
case id_PRINCIPAL: return gcopy(x);
2644
case id_PRIME: x = pr_hnf(nf,x); break;
2645
case id_MAT: if (lg(x) == 1) return gen_0;
2646
}
2647
x = Q_remove_denom(x, &dx);
2648
y = idealpseudomin(x, nf_get_Gtwist(nf,vdir));
2649
if (dx) y = RgC_Rg_div(y, dx);
2650
return gerepileupto(av, y);
2651
}
2652
2653
/*******************************************************************/
2654
/* */
2655
/* APPROXIMATION THEOREM */
2656
/* */
2657
/*******************************************************************/
2658
/* a = ppi(a,b) ppo(a,b), where ppi regroups primes common to a and b
2659
* and ppo(a,b) = Z_ppo(a,b) */
2660
/* return gcd(a,b),ppi(a,b),ppo(a,b) */
2661
GEN
2662
Z_ppio(GEN a, GEN b)
2663
{
2664
GEN x, y, d = gcdii(a,b);
2665
if (is_pm1(d)) return mkvec3(gen_1, gen_1, a);
2666
x = d; y = diviiexact(a,d);
2667
for(;;)
2668
{
2669
GEN g = gcdii(x,y);
2670
if (is_pm1(g)) return mkvec3(d, x, y);
2671
x = mulii(x,g); y = diviiexact(y,g);
2672
}
2673
}
2674
/* a = ppg(a,b)pple(a,b), where ppg regroups primes such that v(a) > v(b)
2675
* and pple all others */
2676
/* return gcd(a,b),ppg(a,b),pple(a,b) */
2677
GEN
2678
Z_ppgle(GEN a, GEN b)
2679
{
2680
GEN x, y, g, d = gcdii(a,b);
2681
if (equalii(a, d)) return mkvec3(a, gen_1, a);
2682
x = diviiexact(a,d); y = d;
2683
for(;;)
2684
{
2685
g = gcdii(x,y);
2686
if (is_pm1(g)) return mkvec3(d, x, y);
2687
x = mulii(x,g); y = diviiexact(y,g);
2688
}
2689
}
2690
static void
2691
Z_dcba_rec(GEN L, GEN a, GEN b)
2692
{
2693
GEN x, r, v, g, h, c, c0;
2694
long n;
2695
if (is_pm1(b)) {
2696
if (!is_pm1(a)) vectrunc_append(L, a);
2697
return;
2698
}
2699
v = Z_ppio(a,b);
2700
a = gel(v,2);
2701
r = gel(v,3);
2702
if (!is_pm1(r)) vectrunc_append(L, r);
2703
v = Z_ppgle(a,b);
2704
g = gel(v,1);
2705
h = gel(v,2);
2706
x = c0 = gel(v,3);
2707
for (n = 1; !is_pm1(h); n++)
2708
{
2709
GEN d, y;
2710
long i;
2711
v = Z_ppgle(h,sqri(g));
2712
g = gel(v,1);
2713
h = gel(v,2);
2714
c = gel(v,3); if (is_pm1(c)) continue;
2715
d = gcdii(c,b);
2716
x = mulii(x,d);
2717
y = d; for (i=1; i < n; i++) y = sqri(y);
2718
Z_dcba_rec(L, diviiexact(c,y), d);
2719
}
2720
Z_dcba_rec(L,diviiexact(b,x), c0);
2721
}
2722
static GEN
2723
Z_cba_rec(GEN L, GEN a, GEN b)
2724
{
2725
GEN g;
2726
if (lg(L) > 10)
2727
{ /* a few naive steps before switching to dcba */
2728
Z_dcba_rec(L, a, b);
2729
return gel(L, lg(L)-1);
2730
}
2731
if (is_pm1(a)) return b;
2732
g = gcdii(a,b);
2733
if (is_pm1(g)) { vectrunc_append(L, a); return b; }
2734
a = diviiexact(a,g);
2735
b = diviiexact(b,g);
2736
return Z_cba_rec(L, Z_cba_rec(L, a, g), b);
2737
}
2738
GEN
2739
Z_cba(GEN a, GEN b)
2740
{
2741
GEN L = vectrunc_init(expi(a) + expi(b) + 2);
2742
GEN t = Z_cba_rec(L, a, b);
2743
if (!is_pm1(t)) vectrunc_append(L, t);
2744
return L;
2745
}
2746
/* P = coprime base, extend it by b; TODO: quadratic for now */
2747
GEN
2748
ZV_cba_extend(GEN P, GEN b)
2749
{
2750
long i, l = lg(P);
2751
GEN w = cgetg(l+1, t_VEC);
2752
for (i = 1; i < l; i++)
2753
{
2754
GEN v = Z_cba(gel(P,i), b);
2755
long nv = lg(v)-1;
2756
gel(w,i) = vecslice(v, 1, nv-1); /* those divide P[i] but not b */
2757
b = gel(v,nv);
2758
}
2759
gel(w,l) = b; return shallowconcat1(w);
2760
}
2761
GEN
2762
ZV_cba(GEN v)
2763
{
2764
long i, l = lg(v);
2765
GEN P;
2766
if (l <= 2) return v;
2767
P = Z_cba(gel(v,1), gel(v,2));
2768
for (i = 3; i < l; i++) P = ZV_cba_extend(P, gel(v,i));
2769
return P;
2770
}
2771
2772
/* write x = x1 x2, x2 maximal s.t. (x2,f) = 1, return x2 */
2773
GEN
2774
Z_ppo(GEN x, GEN f)
2775
{
2776
for (;;)
2777
{
2778
f = gcdii(x, f); if (is_pm1(f)) break;
2779
x = diviiexact(x, f);
2780
}
2781
return x;
2782
}
2783
/* write x = x1 x2, x2 maximal s.t. (x2,f) = 1, return x2 */
2784
ulong
2785
u_ppo(ulong x, ulong f)
2786
{
2787
for (;;)
2788
{
2789
f = ugcd(x, f); if (f == 1) break;
2790
x /= f;
2791
}
2792
return x;
2793
}
2794
2795
/* result known to be representable as an ulong */
2796
static ulong
2797
lcmuu(ulong a, ulong b) { ulong d = ugcd(a,b); return (a/d) * b; }
2798
2799
/* assume 0 < x < N; return u in (Z/NZ)^* such that u x = gcd(x,N) (mod N);
2800
* set *pd = gcd(x,N) */
2801
ulong
2802
Fl_invgen(ulong x, ulong N, ulong *pd)
2803
{
2804
ulong d, d0, e, v, v1;
2805
long s;
2806
*pd = d = xgcduu(N, x, 0, &v, &v1, &s);
2807
if (s > 0) v = N - v;
2808
if (d == 1) return v;
2809
/* vx = gcd(x,N) (mod N), v coprime to N/d but need not be coprime to N */
2810
e = N / d;
2811
d0 = u_ppo(d, e); /* d = d0 d1, d0 coprime to N/d, rad(d1) | N/d */
2812
if (d0 == 1) return v;
2813
e = lcmuu(e, d / d0);
2814
return u_chinese_coprime(v, 1, e, d0, e*d0);
2815
}
2816
2817
/* x t_INT, f ideal. Write x = x1 x2, sqf(x1) | f, (x2,f) = 1. Return x2 */
2818
static GEN
2819
nf_coprime_part(GEN nf, GEN x, GEN listpr)
2820
{
2821
long v, j, lp = lg(listpr), N = nf_get_degree(nf);
2822
GEN x1, x2, ex;
2823
2824
#if 0 /*1) via many gcds. Expensive ! */
2825
GEN f = idealprodprime(nf, listpr);
2826
f = ZM_hnfmodid(f, x); /* first gcd is less expensive since x in Z */
2827
x = scalarmat(x, N);
2828
for (;;)
2829
{
2830
if (gequal1(gcoeff(f,1,1))) break;
2831
x = idealdivexact(nf, x, f);
2832
f = ZM_hnfmodid(shallowconcat(f,x), gcoeff(x,1,1)); /* gcd(f,x) */
2833
}
2834
x2 = x;
2835
#else /*2) from prime decomposition */
2836
x1 = NULL;
2837
for (j=1; j<lp; j++)
2838
{
2839
GEN pr = gel(listpr,j);
2840
v = Z_pval(x, pr_get_p(pr)); if (!v) continue;
2841
2842
ex = muluu(v, pr_get_e(pr)); /* = v_pr(x) > 0 */
2843
x1 = x1? idealmulpowprime(nf, x1, pr, ex)
2844
: idealpow(nf, pr, ex);
2845
}
2846
x = scalarmat(x, N);
2847
x2 = x1? idealdivexact(nf, x, x1): x;
2848
#endif
2849
return x2;
2850
}
2851
2852
/* L0 in K^*, assume (L0,f) = 1. Return L integral, L0 = L mod f */
2853
GEN
2854
make_integral(GEN nf, GEN L0, GEN f, GEN listpr)
2855
{
2856
GEN fZ, t, L, D2, d1, d2, d;
2857
2858
L = Q_remove_denom(L0, &d);
2859
if (!d) return L0;
2860
2861
/* L0 = L / d, L integral */
2862
fZ = gcoeff(f,1,1);
2863
if (typ(L) == t_INT) return Fp_mul(L, Fp_inv(d, fZ), fZ);
2864
/* Kill denom part coprime to fZ */
2865
d2 = Z_ppo(d, fZ);
2866
t = Fp_inv(d2, fZ); if (!is_pm1(t)) L = ZC_Z_mul(L,t);
2867
if (equalii(d, d2)) return L;
2868
2869
d1 = diviiexact(d, d2);
2870
/* L0 = (L / d1) mod f. d1 not coprime to f
2871
* write (d1) = D1 D2, D2 minimal, (D2,f) = 1. */
2872
D2 = nf_coprime_part(nf, d1, listpr);
2873
t = idealaddtoone_i(nf, D2, f); /* in D2, 1 mod f */
2874
L = nfmuli(nf,t,L);
2875
2876
/* if (L0, f) = 1, then L in D1 ==> in D1 D2 = (d1) */
2877
return Q_div_to_int(L, d1); /* exact division */
2878
}
2879
2880
/* assume L is a list of prime ideals. Return the product */
2881
GEN
2882
idealprodprime(GEN nf, GEN L)
2883
{
2884
long l = lg(L), i;
2885
GEN z;
2886
if (l == 1) return matid(nf_get_degree(nf));
2887
z = pr_hnf(nf, gel(L,1));
2888
for (i=2; i<l; i++) z = idealHNF_mul_two(nf,z, gel(L,i));
2889
return z;
2890
}
2891
2892
/* optimize for the frequent case I = nfhnf()[2]: lots of them are 1 */
2893
GEN
2894
idealprod(GEN nf, GEN I)
2895
{
2896
long i, l = lg(I);
2897
GEN z;
2898
for (i = 1; i < l; i++)
2899
if (!equali1(gel(I,i))) break;
2900
if (i == l) return gen_1;
2901
z = gel(I,i);
2902
for (i++; i<l; i++) z = idealmul(nf, z, gel(I,i));
2903
return z;
2904
}
2905
2906
/* v_pr(idealprod(nf,I)) */
2907
long
2908
idealprodval(GEN nf, GEN I, GEN pr)
2909
{
2910
long i, l = lg(I), v = 0;
2911
for (i = 1; i < l; i++)
2912
if (!equali1(gel(I,i))) v += idealval(nf, gel(I,i), pr);
2913
return v;
2914
}
2915
2916
/* assume L is a list of prime ideals. Return prod L[i]^e[i] */
2917
GEN
2918
factorbackprime(GEN nf, GEN L, GEN e)
2919
{
2920
long l = lg(L), i;
2921
GEN z;
2922
2923
if (l == 1) return matid(nf_get_degree(nf));
2924
z = idealpow(nf, gel(L,1), gel(e,1));
2925
for (i=2; i<l; i++)
2926
if (signe(gel(e,i))) z = idealmulpowprime(nf,z, gel(L,i),gel(e,i));
2927
return z;
2928
}
2929
2930
/* F in Z, divisible exactly by pr.p. Return F-uniformizer for pr, i.e.
2931
* a t in Z_K such that v_pr(t) = 1 and (t, F/pr) = 1 */
2932
GEN
2933
pr_uniformizer(GEN pr, GEN F)
2934
{
2935
GEN p = pr_get_p(pr), t = pr_get_gen(pr);
2936
if (!equalii(F, p))
2937
{
2938
long e = pr_get_e(pr);
2939
GEN u, v, q = (e == 1)? sqri(p): p;
2940
u = mulii(q, Fp_inv(q, diviiexact(F,p))); /* 1 mod F/p, 0 mod q */
2941
v = subui(1UL, u); /* 0 mod F/p, 1 mod q */
2942
if (pr_is_inert(pr))
2943
t = addii(mulii(p, v), u);
2944
else
2945
{
2946
t = ZC_Z_mul(t, v);
2947
gel(t,1) = addii(gel(t,1), u); /* return u + vt */
2948
}
2949
}
2950
return t;
2951
}
2952
/* L = list of prime ideals, return lcm_i (L[i] \cap \ZM) */
2953
GEN
2954
prV_lcm_capZ(GEN L)
2955
{
2956
long i, r = lg(L);
2957
GEN F;
2958
if (r == 1) return gen_1;
2959
F = pr_get_p(gel(L,1));
2960
for (i = 2; i < r; i++)
2961
{
2962
GEN pr = gel(L,i), p = pr_get_p(pr);
2963
if (!dvdii(F, p)) F = mulii(F,p);
2964
}
2965
return F;
2966
}
2967
2968
/* Given a prime ideal factorization with possibly zero or negative
2969
* exponents, gives b such that v_p(b) = v_p(x) for all prime ideals pr | x
2970
* and v_pr(b) >= 0 for all other pr.
2971
* For optimal performance, all [anti-]uniformizers should be precomputed,
2972
* but no support for this yet.
2973
*
2974
* If nored, do not reduce result.
2975
* No garbage collecting */
2976
static GEN
2977
idealapprfact_i(GEN nf, GEN x, int nored)
2978
{
2979
GEN z, d, L, e, e2, F;
2980
long i, r;
2981
int flagden;
2982
2983
nf = checknf(nf);
2984
L = gel(x,1);
2985
e = gel(x,2);
2986
F = prV_lcm_capZ(L);
2987
flagden = 0;
2988
z = NULL; r = lg(e);
2989
for (i = 1; i < r; i++)
2990
{
2991
long s = signe(gel(e,i));
2992
GEN pi, q;
2993
if (!s) continue;
2994
if (s < 0) flagden = 1;
2995
pi = pr_uniformizer(gel(L,i), F);
2996
q = nfpow(nf, pi, gel(e,i));
2997
z = z? nfmul(nf, z, q): q;
2998
}
2999
if (!z) return gen_1;
3000
if (nored || typ(z) != t_COL) return z;
3001
e2 = cgetg(r, t_VEC);
3002
for (i=1; i<r; i++) gel(e2,i) = addiu(gel(e,i), 1);
3003
x = factorbackprime(nf, L,e2);
3004
if (flagden) /* denominator */
3005
{
3006
z = Q_remove_denom(z, &d);
3007
d = diviiexact(d, Z_ppo(d, F));
3008
x = RgM_Rg_mul(x, d);
3009
}
3010
else
3011
d = NULL;
3012
z = ZC_reducemodlll(z, x);
3013
return d? RgC_Rg_div(z,d): z;
3014
}
3015
3016
GEN
3017
idealapprfact(GEN nf, GEN x) {
3018
pari_sp av = avma;
3019
return gerepileupto(av, idealapprfact_i(nf, x, 0));
3020
}
3021
GEN
3022
idealappr(GEN nf, GEN x) {
3023
pari_sp av = avma;
3024
if (!is_nf_extfactor(x)) x = idealfactor(nf, x);
3025
return gerepileupto(av, idealapprfact_i(nf, x, 0));
3026
}
3027
3028
/* OBSOLETE */
3029
GEN
3030
idealappr0(GEN nf, GEN x, long fl) { (void)fl; return idealappr(nf, x); }
3031
3032
static GEN
3033
mat_ideal_two_elt2(GEN nf, GEN x, GEN a)
3034
{
3035
GEN F = idealfactor(nf,a), P = gel(F,1), E = gel(F,2);
3036
long i, r = lg(E);
3037
for (i=1; i<r; i++) gel(E,i) = stoi( idealval(nf,x,gel(P,i)) );
3038
return idealapprfact_i(nf,F,1);
3039
}
3040
3041
static void
3042
not_in_ideal(GEN a) {
3043
pari_err_DOMAIN("idealtwoelt2","element mod ideal", "!=", gen_0, a);
3044
}
3045
/* x integral in HNF, a an 'nf' */
3046
static int
3047
in_ideal(GEN x, GEN a)
3048
{
3049
switch(typ(a))
3050
{
3051
case t_INT: return dvdii(a, gcoeff(x,1,1));
3052
case t_COL: return RgV_is_ZV(a) && !!hnf_invimage(x, a);
3053
default: return 0;
3054
}
3055
}
3056
3057
/* Given an integral ideal x and a in x, gives a b such that
3058
* x = aZ_K + bZ_K using the approximation theorem */
3059
GEN
3060
idealtwoelt2(GEN nf, GEN x, GEN a)
3061
{
3062
pari_sp av = avma;
3063
GEN cx, b;
3064
3065
nf = checknf(nf);
3066
a = nf_to_scalar_or_basis(nf, a);
3067
x = idealhnf_shallow(nf,x);
3068
if (lg(x) == 1)
3069
{
3070
if (!isintzero(a)) not_in_ideal(a);
3071
set_avma(av); return gen_0;
3072
}
3073
x = Q_primitive_part(x, &cx);
3074
if (cx) a = gdiv(a, cx);
3075
if (!in_ideal(x, a)) not_in_ideal(a);
3076
b = mat_ideal_two_elt2(nf, x, a);
3077
if (typ(b) == t_COL)
3078
{
3079
GEN mod = idealhnf_principal(nf,a);
3080
b = ZC_hnfrem(b,mod);
3081
if (ZV_isscalar(b)) b = gel(b,1);
3082
}
3083
else
3084
{
3085
GEN aZ = typ(a) == t_COL? Q_denom(zk_inv(nf,a)): a; /* (a) \cap Z */
3086
b = centermodii(b, aZ, shifti(aZ,-1));
3087
}
3088
b = cx? gmul(b,cx): gcopy(b);
3089
return gerepileupto(av, b);
3090
}
3091
3092
/* Given 2 integral ideals x and y in nf, returns a beta in nf such that
3093
* beta * x is an integral ideal coprime to y */
3094
GEN
3095
idealcoprimefact(GEN nf, GEN x, GEN fy)
3096
{
3097
GEN L = gel(fy,1), e;
3098
long i, r = lg(L);
3099
3100
e = cgetg(r, t_COL);
3101
for (i=1; i<r; i++) gel(e,i) = stoi( -idealval(nf,x,gel(L,i)) );
3102
return idealapprfact_i(nf, mkmat2(L,e), 0);
3103
}
3104
GEN
3105
idealcoprime(GEN nf, GEN x, GEN y)
3106
{
3107
pari_sp av = avma;
3108
return gerepileupto(av, idealcoprimefact(nf, x, idealfactor(nf,y)));
3109
}
3110
3111
GEN
3112
nfmulmodpr(GEN nf, GEN x, GEN y, GEN modpr)
3113
{
3114
pari_sp av = avma;
3115
GEN z, p, pr = modpr, T;
3116
3117
nf = checknf(nf); modpr = nf_to_Fq_init(nf,&pr,&T,&p);
3118
x = nf_to_Fq(nf,x,modpr);
3119
y = nf_to_Fq(nf,y,modpr);
3120
z = Fq_mul(x,y,T,p);
3121
return gerepileupto(av, algtobasis(nf, Fq_to_nf(z,modpr)));
3122
}
3123
3124
GEN
3125
nfdivmodpr(GEN nf, GEN x, GEN y, GEN modpr)
3126
{
3127
pari_sp av = avma;
3128
nf = checknf(nf);
3129
return gerepileupto(av, nfreducemodpr(nf, nfdiv(nf,x,y), modpr));
3130
}
3131
3132
GEN
3133
nfpowmodpr(GEN nf, GEN x, GEN k, GEN modpr)
3134
{
3135
pari_sp av=avma;
3136
GEN z, T, p, pr = modpr;
3137
3138
nf = checknf(nf); modpr = nf_to_Fq_init(nf,&pr,&T,&p);
3139
z = nf_to_Fq(nf,x,modpr);
3140
z = Fq_pow(z,k,T,p);
3141
return gerepileupto(av, algtobasis(nf, Fq_to_nf(z,modpr)));
3142
}
3143
3144
GEN
3145
nfkermodpr(GEN nf, GEN x, GEN modpr)
3146
{
3147
pari_sp av = avma;
3148
GEN T, p, pr = modpr;
3149
3150
nf = checknf(nf); modpr = nf_to_Fq_init(nf, &pr,&T,&p);
3151
if (typ(x)!=t_MAT) pari_err_TYPE("nfkermodpr",x);
3152
x = nfM_to_FqM(x, nf, modpr);
3153
return gerepilecopy(av, FqM_to_nfM(FqM_ker(x,T,p), modpr));
3154
}
3155
3156
GEN
3157
nfsolvemodpr(GEN nf, GEN a, GEN b, GEN pr)
3158
{
3159
const char *f = "nfsolvemodpr";
3160
pari_sp av = avma;
3161
GEN T, p, modpr;
3162
3163
nf = checknf(nf);
3164
modpr = nf_to_Fq_init(nf, &pr,&T,&p);
3165
if (typ(a)!=t_MAT) pari_err_TYPE(f,a);
3166
a = nfM_to_FqM(a, nf, modpr);
3167
switch(typ(b))
3168
{
3169
case t_MAT:
3170
b = nfM_to_FqM(b, nf, modpr);
3171
b = FqM_gauss(a,b,T,p);
3172
if (!b) pari_err_INV(f,a);
3173
a = FqM_to_nfM(b, modpr);
3174
break;
3175
case t_COL:
3176
b = nfV_to_FqV(b, nf, modpr);
3177
b = FqM_FqC_gauss(a,b,T,p);
3178
if (!b) pari_err_INV(f,a);
3179
a = FqV_to_nfV(b, modpr);
3180
break;
3181
default: pari_err_TYPE(f,b);
3182
}
3183
return gerepilecopy(av, a);
3184
}
3185
3186