Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

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

28486 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
#include "pari.h"
15
#include "paripriv.h"
16
17
#define DEBUGLEVEL DEBUGLEVEL_bnf
18
19
/*******************************************************************/
20
/* */
21
/* CLASS GROUP AND REGULATOR (McCURLEY, BUCHMANN) */
22
/* GENERAL NUMBER FIELDS */
23
/* */
24
/*******************************************************************/
25
/* get_random_ideal */
26
static const long RANDOM_BITS = 4;
27
/* Buchall */
28
static const long RELSUP = 5;
29
static const long FAIL_DIVISOR = 32;
30
static const long MINFAIL = 10;
31
/* small_norm */
32
static const long BNF_RELPID = 4;
33
static const long BMULT = 8;
34
static const long maxtry_ELEMENT = 1000*1000;
35
static const long maxtry_DEP = 20;
36
static const long maxtry_FACT = 500;
37
/* rnd_rel */
38
static const long RND_REL_RELPID = 1;
39
/* random relations */
40
static const long MINSFB = 3;
41
static const long SFB_MAX = 3;
42
static const long DEPSIZESFBMULT = 16;
43
static const long DEPSFBDIV = 10;
44
/* add_rel_i */
45
static const ulong mod_p = 27449UL;
46
/* be_honest */
47
static const long maxtry_HONEST = 50;
48
49
typedef struct FACT {
50
long pr, ex;
51
} FACT;
52
53
typedef struct subFB_t {
54
GEN subFB;
55
struct subFB_t *old;
56
} subFB_t;
57
58
/* a factor base contains only noninert primes
59
* KC = # of P in factor base (p <= n, NP <= n2)
60
* KC2= # of P assumed to generate class group (NP <= n2)
61
*
62
* KCZ = # of rational primes under ideals counted by KC
63
* KCZ2= same for KC2 */
64
65
typedef struct FB_t {
66
GEN FB; /* FB[i] = i-th rational prime used in factor base */
67
GEN LP; /* vector of all prime ideals in FB */
68
GEN LV; /* LV[p] = vector of P|p, NP <= n2
69
* isclone() is set for LV[p] iff all P|p are in FB
70
* LV[i], i not prime or i > n2, is undefined! */
71
GEN iLP; /* iLP[p] = i such that LV[p] = [LP[i],...] */
72
GEN L_jid; /* indexes of "useful" prime ideals for rnd_rel */
73
long KC, KCZ, KCZ2;
74
GEN subFB; /* LP o subFB = part of FB used to build random relations */
75
int sfb_chg; /* need to change subFB ? */
76
GEN perm; /* permutation of LP used to represent relations [updated by
77
hnfspec/hnfadd: dense rows come first] */
78
GEN idealperm; /* permutation of ideals under field automorphisms */
79
GEN minidx; /* minidx[i] min ideal in orbit of LP[i] under field autom */
80
subFB_t *allsubFB; /* all subFB's used */
81
GEN embperm; /* permutations of the complex embeddings */
82
long MAXDEPSIZESFB; /* # trials before increasing subFB */
83
long MAXDEPSFB; /* MAXDEPSIZESFB / DEPSFBDIV, # trials befor rotating subFB */
84
} FB_t;
85
86
enum { sfb_CHANGE = 1, sfb_INCREASE = 2 };
87
88
typedef struct REL_t {
89
GEN R; /* relation vector as t_VECSMALL; clone */
90
long nz; /* index of first nonzero elt in R (hash) */
91
GEN m; /* pseudo-minimum yielding the relation; clone */
92
long relorig; /* relation this one is an image of */
93
long relaut; /* automorphim used to compute this relation from the original */
94
GEN emb; /* archimedean embeddings */
95
GEN junk[2]; /*make sure sizeof(struct) is a power of two.*/
96
} REL_t;
97
98
typedef struct RELCACHE_t {
99
REL_t *chk; /* last checkpoint */
100
REL_t *base; /* first rel found */
101
REL_t *last; /* last rel found so far */
102
REL_t *end; /* target for last relation. base <= last <= end */
103
size_t len; /* number of rels pre-allocated in base */
104
long relsup; /* how many linearly dependent relations we allow */
105
GEN basis; /* mod p basis (generating family actually) */
106
ulong missing; /* missing vectors in generating family above */
107
} RELCACHE_t;
108
109
typedef struct FP_t {
110
double **q;
111
GEN x;
112
double *y;
113
double *z;
114
double *v;
115
} FP_t;
116
117
typedef struct RNDREL_t {
118
long jid;
119
GEN ex;
120
} RNDREL_t;
121
122
static void
123
wr_rel(GEN e)
124
{
125
long i, l = lg(e);
126
for (i = 1; i < l; i++)
127
if (e[i]) err_printf("%ld^%ld ",i,e[i]);
128
}
129
static void
130
dbg_newrel(RELCACHE_t *cache)
131
{
132
if (DEBUGLEVEL > 1)
133
{
134
err_printf("\n++++ cglob = %ld\nrel = ", cache->last - cache->base);
135
wr_rel(cache->last->R);
136
err_printf("\n");
137
}
138
else
139
err_printf("%ld ", cache->last - cache->base);
140
}
141
142
static void
143
delete_cache(RELCACHE_t *M)
144
{
145
REL_t *rel;
146
for (rel = M->base+1; rel <= M->last; rel++)
147
{
148
gunclone(rel->R);
149
if (rel->m) gunclone(rel->m);
150
}
151
pari_free((void*)M->base); M->base = NULL;
152
}
153
154
static void
155
delete_FB(FB_t *F)
156
{
157
subFB_t *s, *sold;
158
for (s = F->allsubFB; s; s = sold) { sold = s->old; pari_free(s); }
159
gunclone(F->minidx);
160
gunclone(F->idealperm);
161
}
162
163
static void
164
reallocate(RELCACHE_t *M, long len)
165
{
166
REL_t *old = M->base;
167
M->len = len;
168
pari_realloc_ip((void**)&M->base, (len+1) * sizeof(REL_t));
169
if (old)
170
{
171
size_t last = M->last - old, chk = M->chk - old, end = M->end - old;
172
M->last = M->base + last;
173
M->chk = M->base + chk;
174
M->end = M->base + end;
175
}
176
}
177
178
#define pr_get_smallp(pr) gel(pr,1)[2]
179
180
/* don't take P|p all other Q|p are already there */
181
static int
182
bad_subFB(FB_t *F, long t)
183
{
184
GEN LP, P = gel(F->LP,t);
185
long p = pr_get_smallp(P);
186
LP = gel(F->LV,p);
187
return (isclone(LP) && t == F->iLP[p] + lg(LP)-1);
188
}
189
190
static void
191
assign_subFB(FB_t *F, GEN yes, long iyes)
192
{
193
long i, lv = sizeof(subFB_t) + iyes*sizeof(long); /* for struct + GEN */
194
subFB_t *s = (subFB_t *)pari_malloc(lv);
195
s->subFB = (GEN)&s[1];
196
s->old = F->allsubFB; F->allsubFB = s;
197
for (i = 0; i < iyes; i++) s->subFB[i] = yes[i];
198
F->subFB = s->subFB;
199
F->MAXDEPSIZESFB = (iyes-1) * DEPSIZESFBMULT;
200
F->MAXDEPSFB = F->MAXDEPSIZESFB / DEPSFBDIV;
201
}
202
203
/* Determine the permutation of the ideals made by each field automorphism */
204
static GEN
205
FB_aut_perm(FB_t *F, GEN auts, GEN cyclic)
206
{
207
long i, j, m, KC = F->KC, nauts = lg(auts)-1;
208
GEN minidx, perm = zero_Flm_copy(KC, nauts);
209
210
if (!nauts) { F->minidx = gclone(identity_zv(KC)); return cgetg(1,t_MAT); }
211
minidx = zero_Flv(KC);
212
for (m = 1; m < lg(cyclic); m++)
213
{
214
GEN thiscyc = gel(cyclic, m);
215
long k0 = thiscyc[1];
216
GEN aut = gel(auts, k0), permk0 = gel(perm, k0), ppermk;
217
i = 1;
218
while (i <= KC)
219
{
220
pari_sp av2 = avma;
221
GEN seen = zero_Flv(KC), P = gel(F->LP, i);
222
long imin = i, p, f, l;
223
p = pr_get_smallp(P);
224
f = pr_get_f(P);
225
do
226
{
227
if (++i > KC) break;
228
P = gel(F->LP, i);
229
}
230
while (p == pr_get_smallp(P) && f == pr_get_f(P));
231
for (j = imin; j < i; j++)
232
{
233
GEN img = ZM_ZC_mul(aut, pr_get_gen(gel(F->LP, j)));
234
for (l = imin; l < i; l++)
235
if (!seen[l] && ZC_prdvd(img, gel(F->LP, l)))
236
{
237
seen[l] = 1; permk0[j] = l; break;
238
}
239
}
240
set_avma(av2);
241
}
242
for (ppermk = permk0, i = 2; i < lg(thiscyc); i++)
243
{
244
GEN permk = gel(perm, thiscyc[i]);
245
for (j = 1; j <= KC; j++) permk[j] = permk0[ppermk[j]];
246
ppermk = permk;
247
}
248
}
249
for (j = 1; j <= KC; j++)
250
{
251
if (minidx[j]) continue;
252
minidx[j] = j;
253
for (i = 1; i <= nauts; i++) minidx[coeff(perm, j, i)] = j;
254
}
255
F->minidx = gclone(minidx); return perm;
256
}
257
258
/* set subFB.
259
* Fill F->perm (if != NULL): primes ideals sorted by increasing norm (except
260
* the ones in subFB come first [dense rows for hnfspec]) */
261
static void
262
subFBgen(FB_t *F, GEN auts, GEN cyclic, double PROD, long minsFB)
263
{
264
GEN y, perm, yes, no;
265
long i, j, k, iyes, ino, lv = F->KC + 1;
266
double prod;
267
pari_sp av;
268
269
F->LP = cgetg(lv, t_VEC);
270
F->L_jid = F->perm = cgetg(lv, t_VECSMALL);
271
av = avma;
272
y = cgetg(lv,t_COL); /* Norm P */
273
for (k=0, i=1; i <= F->KCZ; i++)
274
{
275
GEN LP = gel(F->LV,F->FB[i]);
276
long l = lg(LP);
277
for (j = 1; j < l; j++)
278
{
279
GEN P = gel(LP,j);
280
k++;
281
gel(y,k) = pr_norm(P);
282
gel(F->LP,k) = P;
283
}
284
}
285
/* perm sorts LP by increasing norm */
286
perm = indexsort(y);
287
no = cgetg(lv, t_VECSMALL); ino = 1;
288
yes = cgetg(lv, t_VECSMALL); iyes = 1;
289
prod = 1.0;
290
for (i = 1; i < lv; i++)
291
{
292
long t = perm[i];
293
if (bad_subFB(F, t)) { no[ino++] = t; continue; }
294
295
yes[iyes++] = t;
296
prod *= (double)itos(gel(y,t));
297
if (iyes > minsFB && prod > PROD) break;
298
}
299
setlg(yes, iyes);
300
for (j=1; j<iyes; j++) F->perm[j] = yes[j];
301
for (i=1; i<ino; i++, j++) F->perm[j] = no[i];
302
for ( ; j<lv; j++) F->perm[j] = perm[j];
303
F->allsubFB = NULL;
304
F->idealperm = gclone(FB_aut_perm(F, auts, cyclic));
305
if (iyes) assign_subFB(F, yes, iyes);
306
set_avma(av);
307
}
308
static int
309
subFB_change(FB_t *F)
310
{
311
long i, iyes, minsFB, lv = F->KC + 1, l = lg(F->subFB)-1;
312
pari_sp av = avma;
313
GEN yes, L_jid = F->L_jid, present = zero_zv(lv-1);
314
315
switch (F->sfb_chg)
316
{
317
case sfb_INCREASE: minsFB = l + 1; break;
318
default: minsFB = l; break;
319
}
320
321
yes = cgetg(minsFB+1, t_VECSMALL); iyes = 1;
322
if (L_jid)
323
{
324
for (i = 1; i < lg(L_jid); i++)
325
{
326
long l = L_jid[i];
327
yes[iyes++] = l;
328
present[l] = 1;
329
if (iyes > minsFB) break;
330
}
331
}
332
else i = 1;
333
if (iyes <= minsFB)
334
{
335
for ( ; i < lv; i++)
336
{
337
long l = F->perm[i];
338
if (present[l]) continue;
339
yes[iyes++] = l;
340
if (iyes > minsFB) break;
341
}
342
if (i == lv) return 0;
343
}
344
if (zv_equal(F->subFB, yes))
345
{
346
if (DEBUGLEVEL) err_printf("\n*** NOT Changing sub factor base\n");
347
}
348
else
349
{
350
if (DEBUGLEVEL) err_printf("\n*** Changing sub factor base\n");
351
assign_subFB(F, yes, iyes);
352
}
353
F->sfb_chg = 0; return gc_bool(av, 1);
354
}
355
356
/* make sure enough room to store n more relations */
357
static void
358
pre_allocate(RELCACHE_t *cache, size_t n)
359
{
360
size_t len = (cache->last - cache->base) + n;
361
if (len >= cache->len) reallocate(cache, len << 1);
362
}
363
364
void
365
init_GRHcheck(GRHcheck_t *S, long N, long R1, double LOGD)
366
{
367
const double c1 = M_PI*M_PI/2;
368
const double c2 = 3.663862376709;
369
const double c3 = 3.801387092431; /* Euler + log(8*Pi)*/
370
S->clone = 0;
371
S->cN = R1*c2 + N*c1;
372
S->cD = LOGD - N*c3 - R1*M_PI/2;
373
S->maxprimes = 16000; /* sufficient for LIMC=176081*/
374
S->primes = (GRHprime_t*)pari_malloc(S->maxprimes*sizeof(*S->primes));
375
S->nprimes = 0;
376
S->limp = 0;
377
u_forprime_init(&S->P, 2, ULONG_MAX);
378
}
379
380
void
381
free_GRHcheck(GRHcheck_t *S)
382
{
383
if (S->clone)
384
{
385
long i = S->nprimes;
386
GRHprime_t *pr;
387
for (pr = S->primes, i = S->nprimes; i > 0; pr++, i--) gunclone(pr->dec);
388
}
389
pari_free(S->primes);
390
}
391
392
int
393
GRHok(GRHcheck_t *S, double L, double SA, double SB)
394
{
395
return (S->cD + (S->cN + 2*SB) / L - 2*SA < -1e-8);
396
}
397
398
/* Return factorization pattern of p: [f,n], where n[i] primes of
399
* residue degree f[i] */
400
static GEN
401
get_fs(GEN nf, GEN P, GEN index, ulong p)
402
{
403
long j, k, f, n, l;
404
GEN fs, ns;
405
406
if (umodiu(index, p))
407
{ /* easy case: p does not divide index */
408
GEN F = Flx_degfact(ZX_to_Flx(P,p), p);
409
fs = gel(F,1); l = lg(fs);
410
}
411
else
412
{
413
GEN F = idealprimedec(nf, utoipos(p));
414
l = lg(F);
415
fs = cgetg(l, t_VECSMALL);
416
for (j = 1; j < l; j++) fs[j] = pr_get_f(gel(F,j));
417
}
418
ns = cgetg(l, t_VECSMALL);
419
f = fs[1]; n = 1;
420
for (j = 2, k = 1; j < l; j++)
421
if (fs[j] == f)
422
n++;
423
else
424
{
425
ns[k] = n; fs[k] = f; k++;
426
f = fs[j]; n = 1;
427
}
428
ns[k] = n; fs[k] = f; k++;
429
setlg(fs, k);
430
setlg(ns, k); return mkvec2(fs,ns);
431
}
432
433
/* cache data for all rational primes up to the LIM */
434
static void
435
cache_prime_dec(GRHcheck_t *S, ulong LIM, GEN nf)
436
{
437
pari_sp av = avma;
438
GRHprime_t *pr;
439
GEN index, P;
440
double nb;
441
442
if (S->limp >= LIM) return;
443
S->clone = 1;
444
nb = primepi_upper_bound((double)LIM); /* #{p <= LIM} <= nb */
445
GRH_ensure(S, nb+1); /* room for one extra prime */
446
P = nf_get_pol(nf);
447
index = nf_get_index(nf);
448
for (pr = S->primes + S->nprimes;;)
449
{
450
ulong p = u_forprime_next(&(S->P));
451
pr->p = p;
452
pr->logp = log((double)p);
453
pr->dec = gclone(get_fs(nf, P, index, p));
454
S->nprimes++;
455
pr++;
456
set_avma(av);
457
/* store up to nextprime(LIM) included */
458
if (p >= LIM) { S->limp = p; break; }
459
}
460
}
461
462
static double
463
tailresback(long R1, long R2, double rK, long C, double C2, double C3, double r1K, double r2K, double logC, double logC2, double logC3)
464
{
465
const double rQ = 1.83787706641;
466
const double r1Q = 1.98505372441;
467
const double r2Q = 1.07991541347;
468
return fabs((R1+R2-1)*(12*logC3+4*logC2-9*logC-6)/(2*C*logC3)
469
+ (rK-rQ)*(6*logC2 + 5*logC + 2)/(C*logC3)
470
- R2*(6*logC2+11*logC+6)/(C2*logC2)
471
- 2*(r1K-r1Q)*(3*logC2 + 4*logC + 2)/(C2*logC3)
472
+ (R1+R2-1)*(12*logC3+40*logC2+45*logC+18)/(6*C3*logC3)
473
+ (r2K-r2Q)*(2*logC2 + 3*logC + 2)/(C3*logC3));
474
}
475
476
static double
477
tailres(long R1, long R2, double al2K, double rKm, double rKM, double r1Km,
478
double r1KM, double r2Km, double r2KM, double C, long i)
479
{
480
/* C >= 3*2^i, lower bound for eint1(log(C)/2) */
481
/* for(i=0,30,print(eint1(log(3*2^i)/2))) */
482
static double tab[] = {
483
0.50409264803,
484
0.26205336997,
485
0.14815491171,
486
0.08770540561,
487
0.05347651832,
488
0.03328934284,
489
0.02104510690,
490
0.01346475900,
491
0.00869778586,
492
0.00566279855,
493
0.00371111950,
494
0.00244567837,
495
0.00161948049,
496
0.00107686891,
497
0.00071868750,
498
0.00048119961,
499
0.00032312188,
500
0.00021753772,
501
0.00014679818,
502
9.9272855581E-5,
503
6.7263969995E-5,
504
4.5656812967E-5,
505
3.1041124593E-5,
506
2.1136011590E-5,
507
1.4411645381E-5,
508
9.8393304088E-6,
509
6.7257395409E-6,
510
4.6025878272E-6,
511
3.1529719271E-6,
512
2.1620490021E-6,
513
1.4839266071E-6
514
};
515
const double logC = log(C), logC2 = logC*logC, logC3 = logC*logC2;
516
const double C2 = C*C, C3 = C*C2;
517
double E1 = i >30? 0: tab[i];
518
return al2K*((33*logC2+22*logC+8)/(8*logC3*sqrt(C))+15*E1/16)
519
+ maxdd(tailresback(rKm,r1KM,r2Km, C,C2,C3,R1,R2,logC,logC2,logC3),
520
tailresback(rKM,r1Km,r2KM, C,C2,C3,R1,R2,logC,logC2,logC3))/2
521
+ ((R1+R2-1)*4*C+R2)*(C2+6*logC)/(4*C2*C2*logC2);
522
}
523
524
static long
525
primeneeded(long N, long R1, long R2, double LOGD)
526
{
527
const double lim = 0.25; /* should be log(2)/2 == 0.34657... */
528
const double al2K = 0.3526*LOGD - 0.8212*N + 4.5007;
529
const double rKm = -1.0155*LOGD + 2.1042*N - 8.3419;
530
const double rKM = -0.5 *LOGD + 1.2076*N + 1;
531
const double r1Km = - LOGD + 1.4150*N;
532
const double r1KM = - LOGD + 1.9851*N;
533
const double r2Km = - LOGD + 0.9151*N;
534
const double r2KM = - LOGD + 1.0800*N;
535
long Cmin = 3, Cmax = 3, i = 0;
536
while (tailres(R1, R2, al2K, rKm, rKM, r1Km, r1KM, r2Km, r2KM, Cmax, i) > lim)
537
{
538
Cmin = Cmax;
539
Cmax *= 2;
540
i++;
541
}
542
i--;
543
while (Cmax - Cmin > 1)
544
{
545
long t = (Cmin + Cmax)/2;
546
if (tailres(R1, R2, al2K, rKm, rKM, r1Km, r1KM, r2Km, r2KM, t, i) > lim)
547
Cmin = t;
548
else
549
Cmax = t;
550
}
551
return Cmax;
552
}
553
554
/* ~ 1 / Res(s = 1, zeta_K) */
555
static GEN
556
compute_invres(GRHcheck_t *S, long LIMC)
557
{
558
pari_sp av = avma;
559
double loginvres = 0.;
560
GRHprime_t *pr;
561
long i;
562
double logLIMC = log((double)LIMC);
563
double logLIMC2 = logLIMC*logLIMC, denc;
564
double c0, c1, c2;
565
denc = 1/(pow((double)LIMC, 3.) * logLIMC * logLIMC2);
566
c2 = ( logLIMC2 + 3 * logLIMC / 2 + 1) * denc;
567
denc *= LIMC;
568
c1 = (3 * logLIMC2 + 4 * logLIMC + 2) * denc;
569
denc *= LIMC;
570
c0 = (3 * logLIMC2 + 5 * logLIMC / 2 + 1) * denc;
571
for (pr = S->primes, i = S->nprimes; i > 0; pr++, i--)
572
{
573
GEN dec, fs, ns;
574
long addpsi;
575
double addpsi1, addpsi2;
576
double logp = pr->logp, NPk;
577
long j, k, limp = logLIMC/logp;
578
ulong p = pr->p, p2 = p*p;
579
if (limp < 1) break;
580
dec = pr->dec;
581
fs = gel(dec, 1); ns = gel(dec, 2);
582
loginvres += 1./p;
583
/* NB: limp = 1 nearly always and limp > 2 for very few primes */
584
for (k=2, NPk = p; k <= limp; k++) { NPk *= p; loginvres += 1/(k * NPk); }
585
addpsi = limp;
586
addpsi1 = p *(pow((double)p , (double)limp)-1)/(p -1);
587
addpsi2 = p2*(pow((double)p2, (double)limp)-1)/(p2-1);
588
j = lg(fs);
589
while (--j > 0)
590
{
591
long f, nb, kmax;
592
double NP, NP2, addinvres;
593
f = fs[j]; if (f > limp) continue;
594
nb = ns[j];
595
NP = pow((double)p, (double)f);
596
addinvres = 1/NP;
597
kmax = limp / f;
598
for (k=2, NPk = NP; k <= kmax; k++) { NPk *= NP; addinvres += 1/(k*NPk); }
599
NP2 = NP*NP;
600
loginvres -= nb * addinvres;
601
addpsi -= nb * f * kmax;
602
addpsi1 -= nb*(f*NP *(pow(NP ,(double)kmax)-1)/(NP -1));
603
addpsi2 -= nb*(f*NP2*(pow(NP2,(double)kmax)-1)/(NP2-1));
604
}
605
loginvres -= (addpsi*c0 - addpsi1*c1 + addpsi2*c2)*logp;
606
}
607
return gerepileuptoleaf(av, mpexp(dbltor(loginvres)));
608
}
609
610
static long
611
nthideal(GRHcheck_t *S, GEN nf, long n)
612
{
613
pari_sp av = avma;
614
GEN P = nf_get_pol(nf);
615
ulong p = 0, *vecN = (ulong*)const_vecsmall(n, LONG_MAX);
616
long i, N = poldegree(P, -1);
617
for (i = 0; ; i++)
618
{
619
GRHprime_t *pr;
620
GEN fs;
621
cache_prime_dec(S, p+1, nf);
622
pr = S->primes + i;
623
fs = gel(pr->dec, 1);
624
p = pr->p;
625
if (fs[1] != N)
626
{
627
GEN ns = gel(pr->dec, 2);
628
long k, l, j = lg(fs);
629
while (--j > 0)
630
{
631
ulong NP = upowuu(p, fs[j]);
632
long nf;
633
if (!NP) continue;
634
for (k = 1; k <= n; k++) if (vecN[k] > NP) break;
635
if (k > n) continue;
636
/* vecN[k] <= NP */
637
nf = ns[j]; /*#{primes of norme NP} = nf, insert them here*/
638
for (l = k+nf; l <= n; l++) vecN[l] = vecN[l-nf];
639
for (l = 0; l < nf && k+l <= n; l++) vecN[k+l] = NP;
640
while (l <= k) vecN[l++] = NP;
641
}
642
}
643
if (p > vecN[n]) break;
644
}
645
return gc_long(av, vecN[n]);
646
}
647
648
/* Compute FB, LV, iLP + KC*. Reset perm
649
* C2: bound for norm of tested prime ideals (includes be_honest())
650
* C1: bound for p, such that P|p (NP <= C2) used to build relations */
651
static void
652
FBgen(FB_t *F, GEN nf, long N, ulong C1, ulong C2, GRHcheck_t *S)
653
{
654
GRHprime_t *pr;
655
long i, ip;
656
GEN prim;
657
const double L = log((double)C2 + 0.5);
658
659
cache_prime_dec(S, C2, nf);
660
pr = S->primes;
661
F->sfb_chg = 0;
662
F->FB = cgetg(C2+1, t_VECSMALL);
663
F->iLP = cgetg(C2+1, t_VECSMALL);
664
F->LV = zerovec(C2);
665
666
prim = icopy(gen_1);
667
i = ip = 0;
668
F->KC = F->KCZ = 0;
669
for (;; pr++) /* p <= C2 */
670
{
671
ulong p = pr->p;
672
long k, l, m;
673
GEN LP, nb, f;
674
675
if (!F->KC && p > C1) { F->KCZ = i; F->KC = ip; }
676
if (p > C2) break;
677
678
if (DEBUGLEVEL>1) err_printf(" %ld",p);
679
680
f = gel(pr->dec, 1); nb = gel(pr->dec, 2);
681
if (f[1] == N)
682
{
683
if (p == C2) break;
684
continue; /* p inert */
685
}
686
l = (long)(L/pr->logp); /* p^f <= C2 <=> f <= l */
687
for (k=0, m=1; m < lg(f) && f[m]<=l; m++) k += nb[m];
688
if (!k)
689
{ /* too inert to appear in FB */
690
if (p == C2) break;
691
continue;
692
}
693
prim[2] = p; LP = idealprimedec_limit_f(nf,prim, l);
694
/* keep noninert ideals with Norm <= C2 */
695
if (m == lg(f)) setisclone(LP); /* flag it: all prime divisors in FB */
696
F->FB[++i]= p;
697
gel(F->LV,p) = LP;
698
F->iLP[p] = ip; ip += k;
699
if (p == C2) break;
700
}
701
if (!F->KC) { F->KCZ = i; F->KC = ip; }
702
/* Note F->KC > 0 otherwise GRHchk is false */
703
setlg(F->FB, F->KCZ+1); F->KCZ2 = i;
704
if (DEBUGLEVEL>1)
705
{
706
err_printf("\n");
707
if (DEBUGLEVEL>6)
708
{
709
err_printf("########## FACTORBASE ##########\n\n");
710
err_printf("KC2=%ld, KC=%ld, KCZ=%ld, KCZ2=%ld\n",
711
ip, F->KC, F->KCZ, F->KCZ2);
712
for (i=1; i<=F->KCZ; i++) err_printf("++ LV[%ld] = %Ps",i,gel(F->LV,F->FB[i]));
713
}
714
}
715
F->perm = NULL; F->L_jid = NULL;
716
}
717
718
static int
719
GRHchk(GEN nf, GRHcheck_t *S, ulong LIMC)
720
{
721
double logC = log((double)LIMC), SA = 0, SB = 0;
722
GRHprime_t *pr = S->primes;
723
724
cache_prime_dec(S, LIMC, nf);
725
for (pr = S->primes;; pr++)
726
{
727
ulong p = pr->p;
728
GEN dec, fs, ns;
729
double logCslogp;
730
long j;
731
732
if (p > LIMC) break;
733
dec = pr->dec; fs = gel(dec, 1); ns = gel(dec,2);
734
logCslogp = logC/pr->logp;
735
for (j = 1; j < lg(fs); j++)
736
{
737
long f = fs[j], M, nb;
738
double logNP, q, A, B;
739
if (f > logCslogp) break;
740
logNP = f * pr->logp;
741
q = 1/sqrt((double)upowuu(p, f));
742
A = logNP * q; B = logNP * A; M = (long)(logCslogp/f);
743
if (M > 1)
744
{
745
double inv1_q = 1 / (1-q);
746
A *= (1 - pow(q, (double)M)) * inv1_q;
747
B *= (1 - pow(q, (double)M)*(M+1 - M*q)) * inv1_q * inv1_q;
748
}
749
nb = ns[j];
750
SA += nb * A;
751
SB += nb * B;
752
}
753
if (p == LIMC) break;
754
}
755
return GRHok(S, logC, SA, SB);
756
}
757
758
/* SMOOTH IDEALS */
759
static void
760
store(long i, long e, FACT *fact)
761
{
762
++fact[0].pr;
763
fact[fact[0].pr].pr = i; /* index */
764
fact[fact[0].pr].ex = e; /* exponent */
765
}
766
767
/* divide out x by all P|p, where x as in can_factor(). k = v_p(Nx) */
768
static int
769
divide_p_elt(GEN LP, long ip, long k, GEN m, FACT *fact)
770
{
771
long j, l = lg(LP);
772
for (j=1; j<l; j++)
773
{
774
GEN P = gel(LP,j);
775
long v = ZC_nfval(m, P);
776
if (!v) continue;
777
store(ip + j, v, fact); /* v = v_P(m) > 0 */
778
k -= v * pr_get_f(P);
779
if (!k) return 1;
780
}
781
return 0;
782
}
783
static int
784
divide_p_id(GEN LP, long ip, long k, GEN nf, GEN I, FACT *fact)
785
{
786
long j, l = lg(LP);
787
for (j=1; j<l; j++)
788
{
789
GEN P = gel(LP,j);
790
long v = idealval(nf,I, P);
791
if (!v) continue;
792
store(ip + j, v, fact); /* v = v_P(I) > 0 */
793
k -= v * pr_get_f(P);
794
if (!k) return 1;
795
}
796
return 0;
797
}
798
static int
799
divide_p_quo(GEN LP, long ip, long k, GEN nf, GEN I, GEN m, FACT *fact)
800
{
801
long j, l = lg(LP);
802
for (j=1; j<l; j++)
803
{
804
GEN P = gel(LP,j);
805
long v = ZC_nfval(m, P);
806
if (!v) continue;
807
v -= idealval(nf,I, P);
808
if (!v) continue;
809
store(ip + j, v, fact); /* v = v_P(m / I) > 0 */
810
k -= v * pr_get_f(P);
811
if (!k) return 1;
812
}
813
return 0;
814
}
815
816
/* |*N| != 0 is the norm of a primitive ideal, in particular not divisible by
817
* any inert prime. Is |*N| a smooth rational integer wrt F ? (put the
818
* exponents in *ex) */
819
static int
820
smooth_norm(FB_t *F, GEN *N, GEN *ex)
821
{
822
GEN FB = F->FB;
823
const long KCZ = F->KCZ;
824
const ulong limp = uel(FB,KCZ); /* last p in FB */
825
long i;
826
827
*ex = new_chunk(KCZ+1);
828
for (i=1; ; i++)
829
{
830
int stop;
831
ulong p = uel(FB,i);
832
long v = Z_lvalrem_stop(N, p, &stop);
833
(*ex)[i] = v;
834
if (v)
835
{
836
GEN LP = gel(F->LV,p);
837
if (lg(LP) == 1) return 0;
838
if (stop) break;
839
}
840
if (i == KCZ) return 0;
841
}
842
(*ex)[0] = i;
843
return (abscmpiu(*N,limp) <= 0);
844
}
845
846
static int
847
divide_p(FB_t *F, long p, long k, GEN nf, GEN I, GEN m, FACT *fact)
848
{
849
GEN LP = gel(F->LV,p);
850
long ip = F->iLP[p];
851
if (!m) return divide_p_id (LP,ip,k,nf,I,fact);
852
if (!I) return divide_p_elt(LP,ip,k,m,fact);
853
return divide_p_quo(LP,ip,k,nf,I,m,fact);
854
}
855
856
/* Let x = m if I == NULL,
857
* I if m == NULL,
858
* m/I otherwise.
859
* Can we factor the integral primitive ideal x ? |N| = Norm x > 0 */
860
static long
861
can_factor(FB_t *F, GEN nf, GEN I, GEN m, GEN N, FACT *fact)
862
{
863
GEN ex;
864
long i, res = 0;
865
fact[0].pr = 0;
866
if (is_pm1(N)) return 1;
867
if (!smooth_norm(F, &N, &ex)) goto END;
868
for (i=1; i<=ex[0]; i++)
869
if (ex[i] && !divide_p(F, F->FB[i], ex[i], nf, I, m, fact)) goto END;
870
res = is_pm1(N) || divide_p(F, itou(N), 1, nf, I, m, fact);
871
END:
872
if (!res && DEBUGLEVEL > 1) err_printf(".");
873
return res;
874
}
875
876
/* can we factor m/I ? [m in I from idealpseudomin_nonscalar], NI = norm I */
877
static long
878
factorgen(FB_t *F, GEN nf, GEN I, GEN NI, GEN m, FACT *fact)
879
{
880
long e, r1 = nf_get_r1(nf);
881
GEN M = nf_get_M(nf);
882
GEN N = divri(embed_norm(RgM_RgC_mul(M,m), r1), NI); /* ~ N(m/I) */
883
N = grndtoi(N, &e);
884
if (e > -1)
885
{
886
if (DEBUGLEVEL > 1) err_printf("+");
887
return 0;
888
}
889
return can_factor(F, nf, I, m, N, fact);
890
}
891
892
/* FUNDAMENTAL UNITS */
893
894
/* a, m real. Return (Re(x) + a) + I * (Im(x) % m) */
895
static GEN
896
addRe_modIm(GEN x, GEN a, GEN m)
897
{
898
GEN re, im, z;
899
if (typ(x) == t_COMPLEX)
900
{
901
im = modRr_safe(gel(x,2), m);
902
if (!im) return NULL;
903
re = gadd(gel(x,1), a);
904
z = gequal0(im)? re: mkcomplex(re, im);
905
}
906
else
907
z = gadd(x, a);
908
return z;
909
}
910
911
/* clean archimedean components */
912
static GEN
913
cleanarch(GEN x, long N, long prec)
914
{
915
long i, l, R1, RU;
916
GEN s, pi2, y = cgetg_copy(x, &l);
917
918
if (typ(x) == t_MAT)
919
{
920
for (i = 1; i < l; i++)
921
if (!(gel(y,i) = cleanarch(gel(x,i), N, prec))) return NULL;
922
return y;
923
}
924
RU = l-1; R1 = (RU<<1) - N; pi2 = Pi2n(1, prec);
925
s = gdivgs(RgV_sum(real_i(x)), -N); /* -log |norm(x)| / N */
926
for (i = 1; i <= R1; i++)
927
if (!(gel(y,i) = addRe_modIm(gel(x,i), s, pi2))) return NULL;
928
if (i <= RU)
929
{
930
GEN pi4 = Pi2n(2, prec), s2 = gmul2n(s, 1);
931
for ( ; i <= RU; i++)
932
if (!(gel(y,i) = addRe_modIm(gel(x,i), s2, pi4))) return NULL;
933
}
934
return y;
935
}
936
GEN
937
nf_cxlog_normalize(GEN nf, GEN x, long prec)
938
{
939
long N = nf_get_degree(checknf(nf));
940
return cleanarch(x, N, prec);
941
}
942
943
static GEN
944
not_given(long reason)
945
{
946
if (DEBUGLEVEL)
947
switch(reason)
948
{
949
case fupb_LARGE:
950
pari_warn(warner,"fundamental units too large, not given");
951
break;
952
case fupb_PRECI:
953
pari_warn(warner,"insufficient precision for fundamental units, not given");
954
break;
955
}
956
return NULL;
957
}
958
959
/* check whether exp(x) will 1) get too big (real(x) large), 2) require
960
* large accuracy for argument reduction (imag(x) large) */
961
static long
962
expbitprec(GEN x, long *e)
963
{
964
GEN re, im;
965
if (typ(x) != t_COMPLEX) re = x;
966
else
967
{
968
im = gel(x,2); *e = maxss(*e, expo(im) + 5 - bit_prec(im));
969
re = gel(x,1);
970
}
971
return (expo(re) <= 20);
972
973
}
974
static long
975
RgC_expbitprec(GEN x)
976
{
977
long l = lg(x), i, e = - (long)HIGHEXPOBIT;
978
for (i = 1; i < l; i++)
979
if (!expbitprec(gel(x,i), &e)) return LONG_MAX;
980
return e;
981
}
982
static long
983
RgM_expbitprec(GEN x)
984
{
985
long i, j, I, J, e = - (long)HIGHEXPOBIT;
986
RgM_dimensions(x, &I,&J);
987
for (j = 1; j <= J; j++)
988
for (i = 1; i <= I; i++)
989
if (!expbitprec(gcoeff(x,i,j), &e)) return LONG_MAX;
990
return e;
991
}
992
993
static GEN
994
FlxqX_chinese_unit(GEN X, GEN U, GEN invzk, GEN D, GEN T, ulong p)
995
{
996
long i, lU = lg(U), lX = lg(X), d = lg(invzk)-1;
997
GEN M = cgetg(lU, t_MAT);
998
if (D)
999
{
1000
D = Flv_inv(D, p);
1001
for (i = 1; i < lX; i++)
1002
if (uel(D, i) != 1)
1003
gel(X,i) = Flx_Fl_mul(gel(X,i), uel(D,i), p);
1004
}
1005
for (i = 1; i < lU; i++)
1006
{
1007
GEN H = FlxqV_factorback(X, gel(U, i), T, p);
1008
gel(M, i) = Flm_Flc_mul(invzk, Flx_to_Flv(H, d), p);
1009
}
1010
return M;
1011
}
1012
1013
static GEN
1014
chinese_unit_slice(GEN A, GEN U, GEN B, GEN D, GEN C, GEN P, GEN *mod)
1015
{
1016
pari_sp av = avma;
1017
long i, n = lg(P)-1, v = varn(C);
1018
GEN H, T;
1019
if (n == 1)
1020
{
1021
ulong p = uel(P,1);
1022
GEN a = ZXV_to_FlxV(A, p), b = ZM_to_Flm(B, p), c = ZX_to_Flx(C, p);
1023
GEN d = D ? ZV_to_Flv(D, p): NULL;
1024
GEN Hp = FlxqX_chinese_unit(a, U, b, d, c, p);
1025
H = gerepileupto(av, Flm_to_ZM(Hp));
1026
*mod = utoi(p);
1027
return H;
1028
}
1029
T = ZV_producttree(P);
1030
A = ZXC_nv_mod_tree(A, P, T, v);
1031
B = ZM_nv_mod_tree(B, P, T);
1032
D = D ? ZV_nv_mod_tree(D, P, T): NULL;
1033
C = ZX_nv_mod_tree(C, P, T);
1034
1035
H = cgetg(n+1, t_VEC);
1036
for(i=1; i <= n; i++)
1037
{
1038
ulong p = P[i];
1039
GEN a = gel(A,i), b = gel(B,i), c = gel(C,i), d = D ? gel(D,i): NULL;
1040
gel(H,i) = FlxqX_chinese_unit(a, U, b, d, c, p);
1041
}
1042
H = nmV_chinese_center_tree_seq(H, P, T, ZV_chinesetree(P, T));
1043
*mod = gmael(T, lg(T)-1, 1);
1044
gerepileall(av, 2, &H, mod);
1045
return H;
1046
}
1047
1048
GEN
1049
chinese_unit_worker(GEN P, GEN A, GEN U, GEN B, GEN D, GEN C)
1050
{
1051
GEN V = cgetg(3, t_VEC);
1052
gel(V,1) = chinese_unit_slice(A, U, B, isintzero(D) ? NULL: D, C, P, &gel(V,2));
1053
return V;
1054
}
1055
1056
/* Let x = \prod X[i]^E[i] = u, return u.
1057
* If dX != NULL, X[i] = nX[i] / dX[i] where nX[i] is a ZX, dX[i] in Z */
1058
static GEN
1059
chinese_unit(GEN nf, GEN nX, GEN dX, GEN U, ulong bnd)
1060
{
1061
pari_sp av = avma;
1062
GEN f = nf_get_index(nf), T = nf_get_pol(nf), invzk = nf_get_invzk(nf);
1063
GEN H, mod;
1064
forprime_t S;
1065
GEN worker = snm_closure(is_entry("_chinese_unit_worker"),
1066
mkcol5(nX, U, invzk, dX? dX: gen_0, T));
1067
init_modular_big(&S);
1068
H = gen_crt("chinese_units", worker, &S, f, bnd, 0, &mod, nmV_chinese_center, FpM_center);
1069
settyp(H, t_VEC); return gerepilecopy(av, H);
1070
}
1071
1072
/* *pE a ZM */
1073
static void
1074
ZM_remove_unused(GEN *pE, GEN *pX)
1075
{
1076
long j, k, l = lg(*pX);
1077
GEN E = *pE, v = cgetg(l, t_VECSMALL);
1078
for (j = k = 1; j < l; j++)
1079
if (!ZMrow_equal0(E, j)) v[k++] = j;
1080
if (k < l)
1081
{
1082
setlg(v, k);
1083
*pX = vecpermute(*pX,v);
1084
*pE = rowpermute(E,v);
1085
}
1086
}
1087
1088
/* s = -log|norm(x)|/N */
1089
static GEN
1090
fixarch(GEN x, GEN s, long R1)
1091
{
1092
long i, l;
1093
GEN y = cgetg_copy(x, &l);
1094
for (i = 1; i <= R1; i++) gel(y,i) = gadd(s, gel(x,i));
1095
for ( ; i < l; i++) gel(y,i) = gadd(s, gmul2n(gel(x,i),-1));
1096
return y;
1097
}
1098
1099
static GEN
1100
getfu(GEN nf, GEN *ptA, GEN *ptU, long prec)
1101
{
1102
GEN U, y, matep, A, T = nf_get_pol(nf), M = nf_get_M(nf);
1103
long e, j, R1, RU, N = degpol(T);
1104
1105
R1 = nf_get_r1(nf); RU = (N+R1) >> 1;
1106
if (RU == 1) return cgetg(1,t_VEC);
1107
1108
A = *ptA;
1109
matep = cgetg(RU,t_MAT);
1110
for (j = 1; j < RU; j++)
1111
{
1112
GEN Aj = gel(A,j), s = gdivgs(RgV_sum(real_i(Aj)), -N);
1113
gel(matep,j) = fixarch(Aj, s, R1);
1114
}
1115
U = lll(real_i(matep));
1116
if (lg(U) < RU) return not_given(fupb_PRECI);
1117
if (ptU) { *ptU = U; *ptA = A = RgM_ZM_mul(A,U); }
1118
y = RgM_ZM_mul(matep,U);
1119
e = RgM_expbitprec(y);
1120
if (e >= 0) return not_given(e == LONG_MAX? fupb_LARGE: fupb_PRECI);
1121
if (prec <= 0) prec = gprecision(A);
1122
y = RgM_solve_realimag(M, gexp(y,prec));
1123
if (!y) return not_given(fupb_PRECI);
1124
y = grndtoi(y, &e); if (e >= 0) return not_given(fupb_PRECI);
1125
settyp(y, t_VEC);
1126
1127
if (!ptU) *ptA = A = RgM_ZM_mul(A, U);
1128
for (j = 1; j < RU; j++)
1129
{ /* y[i] are hopefully unit generators. Normalize: smallest T2 norm */
1130
GEN u = gel(y,j), v = zk_inv(nf, u);
1131
if (!v || !is_pm1(Q_denom(v)) || ZV_isscalar(u))
1132
return not_given(fupb_PRECI);
1133
if (gcmp(RgC_fpnorml2(v,DEFAULTPREC), RgC_fpnorml2(u,DEFAULTPREC)) < 0)
1134
{
1135
gel(A,j) = RgC_neg(gel(A,j));
1136
if (ptU) gel(U,j) = ZC_neg(gel(U,j));
1137
u = v;
1138
}
1139
gel(y,j) = nf_to_scalar_or_alg(nf, u);
1140
}
1141
return y;
1142
}
1143
1144
static void
1145
err_units() { pari_err_PREC("makeunits [cannot get units, use bnfinit(,1)]"); }
1146
1147
/* bound for log2 |sigma(u)|, sigma complex embedding, u fundamental unit
1148
* attached to bnf_get_logfu */
1149
static double
1150
log2fubound(GEN bnf)
1151
{
1152
GEN LU = bnf_get_logfu(bnf);
1153
long i, j, l = lg(LU), r1 = nf_get_r1(bnf_get_nf(bnf));
1154
double e = 0.0;
1155
for (j = 1; j < l; j++)
1156
{
1157
GEN u = gel(LU,j);
1158
for (i = 1; i <= r1; i++)
1159
{
1160
GEN E = real_i(gel(u,i));
1161
e = maxdd(e, gtodouble(E));
1162
}
1163
for ( ; i <= l; i++)
1164
{
1165
GEN E = real_i(gel(u,i));
1166
e = maxdd(e, gtodouble(E) / 2);
1167
}
1168
}
1169
return e / M_LN2;
1170
}
1171
/* bound for log2(|split_real_imag(M, y)|_oo / |y|_oo)*/
1172
static double
1173
log2Mbound(GEN nf)
1174
{
1175
GEN G = nf_get_G(nf), D = nf_get_disc(nf);
1176
long r2 = nf_get_r2(nf), l = lg(G), i;
1177
double e, d = dbllog2(D)/2 - r2 * M_LN2; /* log2 |det(split_real_imag(M))| */
1178
e = log2(nf_get_degree(nf));
1179
for (i = 2; i < l; i++) e += dbllog2(gnorml2(gel(G,i))); /* Hadamard bound */
1180
return e / 2 - d;
1181
}
1182
1183
static GEN
1184
vec_chinese_unit(GEN bnf)
1185
{
1186
GEN nf = bnf_get_nf(bnf), SUnits = bnf_get_sunits(bnf);
1187
ulong bnd = (ulong)ceil(log2Mbound(nf) + log2fubound(bnf));
1188
GEN X, dX, Y, U, f = nf_get_index(nf);
1189
long j, l, v = nf_get_varn(nf);
1190
if (!SUnits) err_units(); /* no compact units */
1191
Y = gel(SUnits,1);
1192
U = gel(SUnits,2);
1193
ZM_remove_unused(&U, &Y); l = lg(Y); X = cgetg(l, t_VEC);
1194
if (is_pm1(f)) f = dX = NULL; else dX = cgetg(l, t_VEC);
1195
for (j = 1; j < l; j++)
1196
{
1197
GEN t = nf_to_scalar_or_alg(nf, gel(Y,j));
1198
if (f)
1199
{
1200
GEN den;
1201
t = Q_remove_denom(t, &den);
1202
gel(dX,j) = den ? den: gen_1;
1203
}
1204
gel(X,j) = typ(t) == t_INT? scalarpol_shallow(t,v): t;
1205
}
1206
return chinese_unit(nf, X, dX, U, bnd);
1207
}
1208
1209
static GEN
1210
makeunits(GEN bnf)
1211
{
1212
GEN nf = bnf_get_nf(bnf), fu = bnf_get_fu_nocheck(bnf);
1213
GEN tu = nf_to_scalar_or_basis(nf, bnf_get_tuU(bnf));
1214
fu = (typ(fu) == t_MAT)? vec_chinese_unit(bnf): matalgtobasis(nf, fu);
1215
return vec_prepend(fu, tu);
1216
}
1217
1218
/*******************************************************************/
1219
/* */
1220
/* PRINCIPAL IDEAL ALGORITHM (DISCRETE LOG) */
1221
/* */
1222
/*******************************************************************/
1223
1224
/* G: prime ideals, E: vector of nonnegative exponents.
1225
* C = possible extra prime (^1) or NULL
1226
* Return Norm (product) */
1227
static GEN
1228
get_norm_fact_primes(GEN G, GEN E, GEN C)
1229
{
1230
pari_sp av=avma;
1231
GEN N = gen_1, P, p;
1232
long i, c = lg(E);
1233
for (i=1; i<c; i++)
1234
{
1235
GEN ex = gel(E,i);
1236
long s = signe(ex);
1237
if (!s) continue;
1238
1239
P = gel(G,i); p = pr_get_p(P);
1240
N = mulii(N, powii(p, mului(pr_get_f(P), ex)));
1241
}
1242
if (C) N = mulii(N, pr_norm(C));
1243
return gerepileuptoint(av, N);
1244
}
1245
1246
/* gen: HNF ideals */
1247
static GEN
1248
get_norm_fact(GEN gen, GEN ex, GEN *pd)
1249
{
1250
long i, c = lg(ex);
1251
GEN d,N,I,e,n,ne,de;
1252
d = N = gen_1;
1253
for (i=1; i<c; i++)
1254
if (signe(gel(ex,i)))
1255
{
1256
I = gel(gen,i); e = gel(ex,i); n = ZM_det_triangular(I);
1257
ne = powii(n,e);
1258
de = equalii(n, gcoeff(I,1,1))? ne: powii(gcoeff(I,1,1), e);
1259
N = mulii(N, ne);
1260
d = mulii(d, de);
1261
}
1262
*pd = d; return N;
1263
}
1264
1265
static GEN
1266
get_pr_lists(GEN FB, long N, int list_pr)
1267
{
1268
GEN pr, L;
1269
long i, l = lg(FB), p, pmax;
1270
1271
pmax = 0;
1272
for (i=1; i<l; i++)
1273
{
1274
pr = gel(FB,i); p = pr_get_smallp(pr);
1275
if (p > pmax) pmax = p;
1276
}
1277
L = const_vec(pmax, NULL);
1278
if (list_pr)
1279
{
1280
for (i=1; i<l; i++)
1281
{
1282
pr = gel(FB,i); p = pr_get_smallp(pr);
1283
if (!L[p]) gel(L,p) = vectrunc_init(N+1);
1284
vectrunc_append(gel(L,p), pr);
1285
}
1286
for (p=1; p<=pmax; p++)
1287
if (L[p]) gen_sort_inplace(gel(L,p), (void*)&cmp_prime_over_p,
1288
&cmp_nodata, NULL);
1289
}
1290
else
1291
{
1292
for (i=1; i<l; i++)
1293
{
1294
pr = gel(FB,i); p = pr_get_smallp(pr);
1295
if (!L[p]) gel(L,p) = vecsmalltrunc_init(N+1);
1296
vecsmalltrunc_append(gel(L,p), i);
1297
}
1298
}
1299
return L;
1300
}
1301
1302
/* recover FB, LV, iLP, KCZ from Vbase */
1303
static GEN
1304
recover_partFB(FB_t *F, GEN Vbase, long N)
1305
{
1306
GEN FB, LV, iLP, L = get_pr_lists(Vbase, N, 0);
1307
long l = lg(L), p, ip, i;
1308
1309
i = ip = 0;
1310
FB = cgetg(l, t_VECSMALL);
1311
iLP= cgetg(l, t_VECSMALL);
1312
LV = cgetg(l, t_VEC);
1313
for (p = 2; p < l; p++)
1314
{
1315
if (!L[p]) continue;
1316
FB[++i] = p;
1317
gel(LV,p) = vecpermute(Vbase, gel(L,p));
1318
iLP[p]= ip; ip += lg(gel(L,p))-1;
1319
}
1320
F->KCZ = i;
1321
F->KC = ip;
1322
F->FB = FB; setlg(FB, i+1);
1323
F->LV = LV;
1324
F->iLP= iLP; return L;
1325
}
1326
1327
/* add v^e to factorization */
1328
static void
1329
add_to_fact(long v, long e, FACT *fact)
1330
{
1331
long i, l = fact[0].pr;
1332
for (i=1; i<=l && fact[i].pr < v; i++)/*empty*/;
1333
if (i <= l && fact[i].pr == v) fact[i].ex += e; else store(v, e, fact);
1334
}
1335
static void
1336
inv_fact(FACT *fact)
1337
{
1338
long i, l = fact[0].pr;
1339
for (i=1; i<=l; i++) fact[i].ex = -fact[i].ex;
1340
}
1341
1342
/* L (small) list of primes above the same p including pr. Return pr index */
1343
static int
1344
pr_index(GEN L, GEN pr)
1345
{
1346
long j, l = lg(L);
1347
GEN al = pr_get_gen(pr);
1348
for (j=1; j<l; j++)
1349
if (ZV_equal(al, pr_get_gen(gel(L,j)))) return j;
1350
pari_err_BUG("codeprime");
1351
return 0; /* LCOV_EXCL_LINE */
1352
}
1353
1354
static long
1355
Vbase_to_FB(FB_t *F, GEN pr)
1356
{
1357
long p = pr_get_smallp(pr);
1358
return F->iLP[p] + pr_index(gel(F->LV,p), pr);
1359
}
1360
1361
/* x, y 2 extended ideals whose first component is an integral HNF and second
1362
* a famat */
1363
static GEN
1364
idealHNF_mulred(GEN nf, GEN x, GEN y)
1365
{
1366
GEN A = idealHNF_mul(nf, gel(x,1), gel(y,1));
1367
GEN F = famat_mul_shallow(gel(x,2), gel(y,2));
1368
return idealred(nf, mkvec2(A, F));
1369
}
1370
/* idealred(x * pr^n), n > 0 is small, x extended ideal. Reduction in order to
1371
* avoid prec pb: don't let id become too large as lgsub increases */
1372
static GEN
1373
idealmulpowprime2(GEN nf, GEN x, GEN pr, ulong n)
1374
{
1375
GEN A = idealmulpowprime(nf, gel(x,1), pr, utoipos(n));
1376
return mkvec2(A, gel(x,2));
1377
}
1378
static GEN
1379
init_famat(GEN x) { return mkvec2(x, trivial_fact()); }
1380
/* optimized idealfactorback + reduction; z = init_famat() */
1381
static GEN
1382
powred(GEN z, GEN nf, GEN p, GEN e)
1383
{ gel(z,1) = p; return idealpowred(nf, z, e); }
1384
static GEN
1385
genback(GEN z, GEN nf, GEN P, GEN E)
1386
{
1387
long i, l = lg(E);
1388
GEN I = NULL;
1389
for (i = 1; i < l; i++)
1390
if (signe(gel(E,i)))
1391
{
1392
GEN J = powred(z, nf, gel(P,i), gel(E,i));
1393
I = I? idealHNF_mulred(nf, I, J): J;
1394
}
1395
return I; /* != NULL since a generator */
1396
}
1397
1398
/* return famat y (principal ideal) such that y / x is smooth [wrt Vbase] */
1399
static GEN
1400
SPLIT(FB_t *F, GEN nf, GEN x, GEN Vbase, FACT *fact)
1401
{
1402
GEN vecG, ex, Ly, y, x0, Nx = ZM_det_triangular(x);
1403
long nbtest_lim, nbtest, i, j, k, ru, lgsub;
1404
pari_sp av;
1405
1406
/* try without reduction if x is small */
1407
if (gexpo(gcoeff(x,1,1)) < 100 &&
1408
can_factor(F, nf, x, NULL, Nx, fact)) return NULL;
1409
1410
av = avma;
1411
Ly = idealpseudominvec(x, nf_get_roundG(nf));
1412
for(k=1; k<lg(Ly); k++)
1413
{
1414
y = gel(Ly,k);
1415
if (factorgen(F, nf, x, Nx, y, fact)) return y;
1416
}
1417
set_avma(av);
1418
1419
/* reduce in various directions */
1420
ru = lg(nf_get_roots(nf));
1421
vecG = cgetg(ru, t_VEC);
1422
for (j=1; j<ru; j++)
1423
{
1424
gel(vecG,j) = nf_get_Gtwist1(nf, j);
1425
av = avma;
1426
Ly = idealpseudominvec(x, gel(vecG,j));
1427
for(k=1; k<lg(Ly); k++)
1428
{
1429
y = gel(Ly,k);
1430
if (factorgen(F, nf, x, Nx, y, fact)) return y;
1431
}
1432
set_avma(av);
1433
}
1434
1435
/* tough case, multiply by random products */
1436
lgsub = 3;
1437
ex = cgetg(lgsub, t_VECSMALL);
1438
x0 = init_famat(x);
1439
nbtest = 1; nbtest_lim = 4;
1440
for(;;)
1441
{
1442
GEN Ired, I, NI, id = x0;
1443
av = avma;
1444
if (DEBUGLEVEL>2) err_printf("# ideals tried = %ld\n",nbtest);
1445
for (i=1; i<lgsub; i++)
1446
{
1447
ex[i] = random_bits(RANDOM_BITS);
1448
if (ex[i]) id = idealmulpowprime2(nf, id, gel(Vbase,i), ex[i]);
1449
}
1450
if (id == x0) continue;
1451
/* I^(-1) * \prod Vbase[i]^ex[i] = (id[2]) / x */
1452
1453
I = gel(id,1); NI = ZM_det_triangular(I);
1454
if (can_factor(F, nf, I, NULL, NI, fact))
1455
{
1456
inv_fact(fact); /* I^(-1) */
1457
for (i=1; i<lgsub; i++)
1458
if (ex[i]) add_to_fact(Vbase_to_FB(F,gel(Vbase,i)), ex[i], fact);
1459
return gel(id,2);
1460
}
1461
Ired = ru == 2? I: ZM_lll(I, 0.99, LLL_INPLACE);
1462
for (j=1; j<ru; j++)
1463
{
1464
pari_sp av2 = avma;
1465
Ly = idealpseudominvec(Ired, gel(vecG,j));
1466
for (k=1; k < lg(Ly); k++)
1467
{
1468
y = gel(Ly,k);
1469
if (factorgen(F, nf, I, NI, y, fact))
1470
{
1471
for (i=1; i<lgsub; i++)
1472
if (ex[i]) add_to_fact(Vbase_to_FB(F,gel(Vbase,i)), ex[i], fact);
1473
return famat_mul_shallow(gel(id,2), y);
1474
}
1475
}
1476
set_avma(av2);
1477
}
1478
set_avma(av);
1479
if (++nbtest > nbtest_lim)
1480
{
1481
nbtest = 0;
1482
if (++lgsub < minss(8, lg(Vbase)-1))
1483
{
1484
nbtest_lim <<= 1;
1485
ex = cgetg(lgsub, t_VECSMALL);
1486
}
1487
else nbtest_lim = LONG_MAX; /* don't increase further */
1488
if (DEBUGLEVEL>2) err_printf("SPLIT: increasing factor base [%ld]\n",lgsub);
1489
}
1490
}
1491
}
1492
1493
INLINE GEN
1494
bnf_get_W(GEN bnf) { return gel(bnf,1); }
1495
INLINE GEN
1496
bnf_get_B(GEN bnf) { return gel(bnf,2); }
1497
INLINE GEN
1498
bnf_get_C(GEN bnf) { return gel(bnf,4); }
1499
INLINE GEN
1500
bnf_get_vbase(GEN bnf) { return gel(bnf,5); }
1501
INLINE GEN
1502
bnf_get_Ur(GEN bnf) { return gmael(bnf,9,1); }
1503
INLINE GEN
1504
bnf_get_ga(GEN bnf) { return gmael(bnf,9,2); }
1505
INLINE GEN
1506
bnf_get_GD(GEN bnf) { return gmael(bnf,9,3); }
1507
1508
/* Return y (as an elt of K or a t_MAT representing an elt in Z[K])
1509
* such that x / (y) is smooth and store the exponents of its factorization
1510
* on g_W and g_B in Wex / Bex; return NULL for y = 1 */
1511
static GEN
1512
split_ideal(GEN bnf, GEN x, GEN *pWex, GEN *pBex)
1513
{
1514
GEN L, y, Vbase = bnf_get_vbase(bnf);
1515
GEN Wex, W = bnf_get_W(bnf);
1516
GEN Bex, B = bnf_get_B(bnf);
1517
long p, j, i, l, nW, nB;
1518
FACT *fact;
1519
FB_t F;
1520
1521
L = recover_partFB(&F, Vbase, lg(x)-1);
1522
fact = (FACT*)stack_malloc((F.KC+1)*sizeof(FACT));
1523
y = SPLIT(&F, bnf_get_nf(bnf), x, Vbase, fact);
1524
nW = lg(W)-1; *pWex = Wex = zero_zv(nW);
1525
nB = lg(B)-1; *pBex = Bex = zero_zv(nB); l = lg(F.FB);
1526
p = j = 0; /* -Wall */
1527
for (i = 1; i <= fact[0].pr; i++)
1528
{ /* decode index C = ip+j --> (p,j) */
1529
long a, b, t, C = fact[i].pr;
1530
for (t = 1; t < l; t++)
1531
{
1532
long q = F.FB[t], k = C - F.iLP[q];
1533
if (k <= 0) break;
1534
p = q;
1535
j = k;
1536
}
1537
a = gel(L, p)[j];
1538
b = a - nW;
1539
if (b <= 0) Wex[a] = y? -fact[i].ex: fact[i].ex;
1540
else Bex[b] = y? -fact[i].ex: fact[i].ex;
1541
}
1542
return y;
1543
}
1544
1545
GEN
1546
init_red_mod_units(GEN bnf, long prec)
1547
{
1548
GEN s = gen_0, p1,s1,mat, logfu = bnf_get_logfu(bnf);
1549
long i,j, RU = lg(logfu);
1550
1551
if (RU == 1) return NULL;
1552
mat = cgetg(RU,t_MAT);
1553
for (j=1; j<RU; j++)
1554
{
1555
p1 = cgetg(RU+1,t_COL); gel(mat,j) = p1;
1556
s1 = gen_0;
1557
for (i=1; i<RU; i++)
1558
{
1559
gel(p1,i) = real_i(gcoeff(logfu,i,j));
1560
s1 = mpadd(s1, mpsqr(gel(p1,i)));
1561
}
1562
gel(p1,RU) = gen_0; if (mpcmp(s1,s) > 0) s = s1;
1563
}
1564
s = gsqrt(gmul2n(s,RU),prec);
1565
if (expo(s) < 27) s = utoipos(1UL << 27);
1566
return mkvec2(mat, s);
1567
}
1568
1569
/* z computed above. Return unit exponents that would reduce col (arch) */
1570
GEN
1571
red_mod_units(GEN col, GEN z)
1572
{
1573
long i,RU;
1574
GEN x,mat,N2;
1575
1576
if (!z) return NULL;
1577
mat= gel(z,1);
1578
N2 = gel(z,2);
1579
RU = lg(mat); x = cgetg(RU+1,t_COL);
1580
for (i=1; i<RU; i++) gel(x,i) = real_i(gel(col,i));
1581
gel(x,RU) = N2;
1582
x = lll(shallowconcat(mat,x));
1583
if (typ(x) != t_MAT || lg(x) <= RU) return NULL;
1584
x = gel(x,RU);
1585
if (signe(gel(x,RU)) < 0) x = gneg_i(x);
1586
if (!gequal1(gel(x,RU))) pari_err_BUG("red_mod_units");
1587
setlg(x,RU); return x;
1588
}
1589
1590
static GEN
1591
add(GEN a, GEN t) { return a = a? RgC_add(a,t): t; }
1592
1593
/* [x] archimedian components, A column vector. return [x] A */
1594
static GEN
1595
act_arch(GEN A, GEN x)
1596
{
1597
GEN a;
1598
long i,l = lg(A), tA = typ(A);
1599
if (tA == t_MAT)
1600
{ /* assume lg(x) >= l */
1601
a = cgetg(l, t_MAT);
1602
for (i=1; i<l; i++) gel(a,i) = act_arch(gel(A,i), x);
1603
return a;
1604
}
1605
if (l==1) return cgetg(1, t_COL);
1606
a = NULL;
1607
if (tA == t_VECSMALL)
1608
{
1609
for (i=1; i<l; i++)
1610
{
1611
long c = A[i];
1612
if (c) a = add(a, gmulsg(c, gel(x,i)));
1613
}
1614
}
1615
else
1616
{ /* A a t_COL of t_INT. Assume lg(A)==lg(x) */
1617
for (i=1; i<l; i++)
1618
{
1619
GEN c = gel(A,i);
1620
if (signe(c)) a = add(a, gmul(c, gel(x,i)));
1621
}
1622
}
1623
return a? a: zerocol(lgcols(x)-1);
1624
}
1625
/* act_arch(matdiagonal(v), x) */
1626
static GEN
1627
diagact_arch(GEN v, GEN x)
1628
{
1629
long i, l = lg(v);
1630
GEN a = cgetg(l, t_MAT);
1631
for (i = 1; i < l; i++) gel(a,i) = gmul(gel(x,i), gel(v,i));
1632
return a;
1633
}
1634
1635
static long
1636
prec_arch(GEN bnf)
1637
{
1638
GEN a = bnf_get_C(bnf);
1639
long i, l = lg(a), prec;
1640
1641
for (i=1; i<l; i++)
1642
if ( (prec = gprecision(gel(a,i))) ) return prec;
1643
return DEFAULTPREC;
1644
}
1645
1646
static long
1647
needed_bitprec(GEN x)
1648
{
1649
long i, e = 0, l = lg(x);
1650
for (i = 1; i < l; i++)
1651
{
1652
GEN c = gel(x,i);
1653
long f = gexpo(c) - prec2nbits(gprecision(c));
1654
if (f > e) e = f;
1655
}
1656
return e;
1657
}
1658
1659
/* col = archimedian components of x, Nx its norm, dx a multiple of its
1660
* denominator. Return x or NULL (fail) */
1661
GEN
1662
isprincipalarch(GEN bnf, GEN col, GEN kNx, GEN e, GEN dx, long *pe)
1663
{
1664
GEN nf, x, y, logfu, s, M;
1665
long N, prec = gprecision(col);
1666
bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); M = nf_get_M(nf);
1667
if (!prec) prec = prec_arch(bnf);
1668
*pe = 128;
1669
logfu = bnf_get_logfu(bnf);
1670
N = nf_get_degree(nf);
1671
if (!(col = cleanarch(col,N,prec))) return NULL;
1672
if (lg(col) > 2)
1673
{ /* reduce mod units */
1674
GEN u, z = init_red_mod_units(bnf,prec);
1675
if (!(u = red_mod_units(col,z))) return NULL;
1676
col = RgC_add(col, RgM_RgC_mul(logfu, u));
1677
if (!(col = cleanarch(col,N,prec))) return NULL;
1678
}
1679
s = divru(mulir(e, glog(kNx,prec)), N);
1680
col = fixarch(col, s, nf_get_r1(nf));
1681
if (RgC_expbitprec(col) >= 0) return NULL;
1682
col = gexp(col, prec);
1683
/* d.alpha such that x = alpha \prod gj^ej */
1684
x = RgM_solve_realimag(M,col); if (!x) return NULL;
1685
x = RgC_Rg_mul(x, dx);
1686
y = grndtoi(x, pe);
1687
if (*pe > -5) { *pe = needed_bitprec(x); return NULL; }
1688
return RgC_Rg_div(y, dx);
1689
}
1690
1691
/* y = C \prod g[i]^e[i] ? */
1692
static int
1693
fact_ok(GEN nf, GEN y, GEN C, GEN g, GEN e)
1694
{
1695
pari_sp av = avma;
1696
long i, c = lg(e);
1697
GEN z = C? C: gen_1;
1698
for (i=1; i<c; i++)
1699
if (signe(gel(e,i))) z = idealmul(nf, z, idealpow(nf, gel(g,i), gel(e,i)));
1700
if (typ(z) != t_MAT) z = idealhnf_shallow(nf,z);
1701
if (typ(y) != t_MAT) y = idealhnf_shallow(nf,y);
1702
return gc_bool(av, ZM_equal(y,z));
1703
}
1704
static GEN
1705
ZV_divrem(GEN A, GEN B, GEN *pR)
1706
{
1707
long i, l = lg(A);
1708
GEN Q = cgetg(l, t_COL), R = cgetg(l, t_COL);
1709
for (i = 1; i < l; i++) gel(Q,i) = truedvmdii(gel(A,i), gel(B,i), &gel(R,i));
1710
*pR = R; return Q;
1711
}
1712
1713
static GEN
1714
Ur_ZC_mul(GEN bnf, GEN v)
1715
{
1716
GEN w, U = bnf_get_Ur(bnf);
1717
long i, l = lg(bnf_get_cyc(bnf)); /* may be < lgcols(U) */
1718
1719
w = cgetg(l, t_COL);
1720
for (i = 1; i < l; i++) gel(w,i) = ZMrow_ZC_mul(U, v, i);
1721
return w;
1722
}
1723
1724
static GEN
1725
ZV_mul(GEN x, GEN y)
1726
{
1727
long i, l = lg(x);
1728
GEN z = cgetg(l, t_COL);
1729
for (i = 1; i < l; i++) gel(z,i) = mulii(gel(x,i), gel(y,i));
1730
return z;
1731
}
1732
static int
1733
dump_gen(GEN x, long flag)
1734
{
1735
GEN d;
1736
if (!(flag & nf_GENMAT)) return 0;
1737
x = Q_remove_denom(x, &d);
1738
return (d && expi(d) > 32) || gexpo(x) > 32;
1739
}
1740
1741
/* assume x in HNF; cf class_group_gen for notations. Return NULL iff
1742
* flag & nf_FORCE and computation of principal ideal generator fails */
1743
static GEN
1744
isprincipalall(GEN bnf, GEN x, long *pprec, long flag)
1745
{
1746
GEN xar, Wex, Bex, gen, xc, col, A, Q, R, UA, SUnits;
1747
GEN C = bnf_get_C(bnf), nf = bnf_get_nf(bnf), cyc = bnf_get_cyc(bnf);
1748
long nB, nW, e;
1749
1750
if (lg(cyc) == 1 && !(flag & (nf_GEN|nf_GENMAT|nf_GEN_IF_PRINCIPAL)))
1751
return cgetg(1,t_COL);
1752
if (lg(x) == 2)
1753
{ /* nf = Q */
1754
col = gel(x,1);
1755
if (flag & nf_GENMAT) col = to_famat_shallow(col, gen_1);
1756
return (flag & nf_GEN_IF_PRINCIPAL)? col: mkvec2(cgetg(1,t_COL), col);
1757
}
1758
1759
x = Q_primitive_part(x, &xc);
1760
if (equali1(gcoeff(x,1,1))) /* trivial ideal */
1761
{
1762
R = zerocol(lg(cyc)-1);
1763
if (!(flag & (nf_GEN|nf_GENMAT|nf_GEN_IF_PRINCIPAL))) return R;
1764
if (flag & nf_GEN_IF_PRINCIPAL)
1765
return scalarcol_shallow(xc? xc: gen_1, nf_get_degree(nf));
1766
if (flag & nf_GENMAT)
1767
col = xc? to_famat_shallow(xc, gen_1): trivial_fact();
1768
else
1769
col = scalarcol_shallow(xc? xc: gen_1, nf_get_degree(nf));
1770
return mkvec2(R, col);
1771
}
1772
xar = split_ideal(bnf, x, &Wex, &Bex);
1773
/* x = g_W Wex + g_B Bex + [xar] = g_W (Wex - B*Bex) + [xar] + [C_B]Bex */
1774
A = zc_to_ZC(Wex); nB = lg(Bex)-1;
1775
if (nB) A = ZC_sub(A, ZM_zc_mul(bnf_get_B(bnf), Bex));
1776
UA = Ur_ZC_mul(bnf, A);
1777
Q = ZV_divrem(UA, cyc, &R);
1778
/* g_W (Wex - B*Bex) = G Ur A - [ga]A = G R + [GD]Q - [ga]A
1779
* Finally: x = G R + [xar] + [C_B]Bex + [GD]Q - [ga]A */
1780
if (!(flag & (nf_GEN|nf_GENMAT|nf_GEN_IF_PRINCIPAL))) return R;
1781
if ((flag & nf_GEN_IF_PRINCIPAL) && !ZV_equal0(R)) return gen_0;
1782
1783
nW = lg(Wex)-1;
1784
gen = bnf_get_gen(bnf);
1785
col = NULL;
1786
SUnits = bnf_get_sunits(bnf);
1787
if (lg(R) == 1
1788
|| abscmpiu(gel(R,vecindexmax(R)), 4 * bit_accuracy(*pprec)) < 0)
1789
{ /* q = N (x / prod gj^ej) = N(alpha), denom(alpha) | d */
1790
GEN d, q = gdiv(ZM_det_triangular(x), get_norm_fact(gen, R, &d));
1791
col = xar? nf_cxlog(nf, xar, *pprec): NULL;
1792
if (nB) col = add(col, act_arch(Bex, nW? vecslice(C,nW+1,lg(C)-1): C));
1793
if (nW) col = add(col, RgC_sub(act_arch(Q, bnf_get_GD(bnf)),
1794
act_arch(A, bnf_get_ga(bnf))));
1795
col = isprincipalarch(bnf, col, q, gen_1, d, &e);
1796
if (col && ((SUnits && dump_gen(col, flag))
1797
|| !fact_ok(nf,x, col,gen,R))) col = NULL;
1798
}
1799
if (!col && (flag & nf_GENMAT))
1800
{
1801
if (SUnits)
1802
{
1803
GEN X = gel(SUnits,1), U = gel(SUnits,2), C = gel(SUnits,3);
1804
GEN v = gel(bnf,9), Ge = gel(v,4), M1 = gel(v,5), M2 = gel(v,6);
1805
GEN z = NULL, F = NULL;
1806
if (nB)
1807
{
1808
GEN C2 = nW? vecslice(C, nW+1, lg(C)-1): C;
1809
z = ZM_zc_mul(C2, Bex);
1810
}
1811
if (nW)
1812
{ /* [GD]Q - [ga]A = ([X]M1 - [Ge]D) Q - ([X]M2 - [Ge]Ur) A */
1813
GEN C1 = vecslice(C, 1, nW);
1814
GEN v = ZC_sub(ZM_ZC_mul(M1,Q), ZM_ZC_mul(M2,A));
1815
z = add(z, ZM_ZC_mul(C1, v));
1816
F = famat_reduce(famatV_factorback(Ge, ZC_sub(UA, ZV_mul(cyc,Q))));
1817
if (lgcols(F) == 1) F = NULL;
1818
}
1819
/* reduce modulo units and Q^* */
1820
if (lg(U) != 1) z = ZC_sub(z, ZM_ZC_mul(U, RgM_Babai(U,z)));
1821
col = mkmat2(X, z);
1822
if (F) col = famat_mul_shallow(col, F);
1823
col = famat_remove_trivial(col);
1824
if (xar) col = famat_mul_shallow(col, xar);
1825
}
1826
else if (!ZV_equal0(R))
1827
{ /* in case isprincipalfact calls bnfinit() due to prec trouble...*/
1828
GEN y = isprincipalfact(bnf, x, gen, ZC_neg(R), flag);
1829
if (typ(y) != t_VEC) return y;
1830
col = gel(y,2);
1831
}
1832
}
1833
if (col)
1834
{ /* add back missing content */
1835
if (xc) col = (typ(col)==t_MAT)? famat_mul_shallow(col,xc)
1836
: RgC_Rg_mul(col,xc);
1837
if (typ(col) != t_MAT && lg(col) != 1 && (flag & nf_GENMAT))
1838
col = to_famat_shallow(col, gen_1);
1839
}
1840
else
1841
{
1842
if (e < 0) e = 0;
1843
*pprec += nbits2extraprec(e + 128);
1844
if (flag & nf_FORCE)
1845
{
1846
if (DEBUGLEVEL)
1847
pari_warn(warner,"precision too low for generators, e = %ld",e);
1848
return NULL;
1849
}
1850
pari_warn(warner,"precision too low for generators, not given");
1851
col = cgetg(1, t_COL);
1852
}
1853
return (flag & nf_GEN_IF_PRINCIPAL)? col: mkvec2(R, col);
1854
}
1855
1856
static GEN
1857
triv_gen(GEN bnf, GEN x, long flag)
1858
{
1859
pari_sp av = avma;
1860
GEN nf = bnf_get_nf(bnf);
1861
long c;
1862
if (flag & nf_GEN_IF_PRINCIPAL)
1863
{
1864
if (!(flag & nf_GENMAT)) return algtobasis(nf,x);
1865
x = nf_to_scalar_or_basis(nf,x);
1866
if (typ(x) == t_INT && is_pm1(x)) return trivial_fact();
1867
return gerepilecopy(av, to_famat_shallow(x, gen_1));
1868
}
1869
c = lg(bnf_get_cyc(bnf)) - 1;
1870
if (flag & nf_GENMAT)
1871
retmkvec2(zerocol(c), to_famat_shallow(algtobasis(nf,x), gen_1));
1872
if (flag & nf_GEN)
1873
retmkvec2(zerocol(c), algtobasis(nf,x));
1874
return zerocol(c);
1875
}
1876
1877
GEN
1878
bnfisprincipal0(GEN bnf,GEN x,long flag)
1879
{
1880
pari_sp av = avma;
1881
GEN arch, c, nf;
1882
long pr;
1883
1884
bnf = checkbnf(bnf);
1885
nf = bnf_get_nf(bnf);
1886
switch( idealtyp(&x, &arch) )
1887
{
1888
case id_PRINCIPAL:
1889
if (gequal0(x)) pari_err_DOMAIN("bnfisprincipal","ideal","=",gen_0,x);
1890
return triv_gen(bnf, x, flag);
1891
case id_PRIME:
1892
if (pr_is_inert(x)) return triv_gen(bnf, pr_get_p(x), flag);
1893
x = pr_hnf(nf, x);
1894
break;
1895
case id_MAT:
1896
if (lg(x)==1) pari_err_DOMAIN("bnfisprincipal","ideal","=",gen_0,x);
1897
if (nf_get_degree(nf) != lg(x)-1)
1898
pari_err_TYPE("idealtyp [dimension != degree]", x);
1899
}
1900
pr = prec_arch(bnf); /* precision of unit matrix */
1901
c = getrand();
1902
for (;;)
1903
{
1904
pari_sp av1 = avma;
1905
GEN y = isprincipalall(bnf,x,&pr,flag);
1906
if (y) return gerepilecopy(av, y);
1907
1908
if (DEBUGLEVEL) pari_warn(warnprec,"isprincipal",pr);
1909
set_avma(av1); bnf = bnfnewprec_shallow(bnf,pr); setrand(c);
1910
}
1911
}
1912
GEN
1913
isprincipal(GEN bnf,GEN x) { return bnfisprincipal0(bnf,x,0); }
1914
1915
/* FIXME: OBSOLETE */
1916
GEN
1917
isprincipalgen(GEN bnf,GEN x)
1918
{ return bnfisprincipal0(bnf,x,nf_GEN); }
1919
GEN
1920
isprincipalforce(GEN bnf,GEN x)
1921
{ return bnfisprincipal0(bnf,x,nf_FORCE); }
1922
GEN
1923
isprincipalgenforce(GEN bnf,GEN x)
1924
{ return bnfisprincipal0(bnf,x,nf_GEN | nf_FORCE); }
1925
1926
/* lg(u) > 1 */
1927
static int
1928
RgV_is1(GEN u) { return isint1(gel(u,1)) && RgV_isscalar(u); }
1929
static GEN
1930
add_principal_part(GEN nf, GEN u, GEN v, long flag)
1931
{
1932
if (flag & nf_GENMAT)
1933
return (typ(u) == t_COL && RgV_is1(u))? v: famat_mul_shallow(v,u);
1934
else
1935
return nfmul(nf, v, u);
1936
}
1937
1938
#if 0
1939
/* compute C prod P[i]^e[i], e[i] >=0 for all i. C may be NULL (omitted)
1940
* e destroyed ! */
1941
static GEN
1942
expand(GEN nf, GEN C, GEN P, GEN e)
1943
{
1944
long i, l = lg(e), done = 1;
1945
GEN id = C;
1946
for (i=1; i<l; i++)
1947
{
1948
GEN ei = gel(e,i);
1949
if (signe(ei))
1950
{
1951
if (mod2(ei)) id = id? idealmul(nf, id, gel(P,i)): gel(P,i);
1952
ei = shifti(ei,-1);
1953
if (signe(ei)) done = 0;
1954
gel(e,i) = ei;
1955
}
1956
}
1957
if (id != C) id = idealred(nf, id);
1958
if (done) return id;
1959
return idealmulred(nf, id, idealsqr(nf, expand(nf,id,P,e)));
1960
}
1961
/* C is an extended ideal, possibly with C[1] = NULL */
1962
static GEN
1963
expandext(GEN nf, GEN C, GEN P, GEN e)
1964
{
1965
long i, l = lg(e), done = 1;
1966
GEN A = gel(C,1);
1967
for (i=1; i<l; i++)
1968
{
1969
GEN ei = gel(e,i);
1970
if (signe(ei))
1971
{
1972
if (mod2(ei)) A = A? idealmul(nf, A, gel(P,i)): gel(P,i);
1973
ei = shifti(ei,-1);
1974
if (signe(ei)) done = 0;
1975
gel(e,i) = ei;
1976
}
1977
}
1978
if (A == gel(C,1))
1979
A = C;
1980
else
1981
A = idealred(nf, mkvec2(A, gel(C,2)));
1982
if (done) return A;
1983
return idealmulred(nf, A, idealsqr(nf, expand(nf,A,P,e)));
1984
}
1985
#endif
1986
1987
static GEN
1988
expand(GEN nf, GEN C, GEN P, GEN e)
1989
{
1990
long i, l = lg(e);
1991
GEN B, A = C;
1992
for (i=1; i<l; i++) /* compute prod P[i]^e[i] */
1993
if (signe(gel(e,i)))
1994
{
1995
B = idealpowred(nf, gel(P,i), gel(e,i));
1996
A = A? idealmulred(nf,A,B): B;
1997
}
1998
return A;
1999
}
2000
static GEN
2001
expandext(GEN nf, GEN C, GEN P, GEN e)
2002
{
2003
long i, l = lg(e);
2004
GEN B, A = gel(C,1), C1 = A;
2005
for (i=1; i<l; i++) /* compute prod P[i]^e[i] */
2006
if (signe(gel(e,i)))
2007
{
2008
gel(C,1) = gel(P,i);
2009
B = idealpowred(nf, C, gel(e,i));
2010
A = A? idealmulred(nf,A,B): B;
2011
}
2012
return A == C1? C: A;
2013
}
2014
2015
/* isprincipal for C * \prod P[i]^e[i] (C omitted if NULL) */
2016
GEN
2017
isprincipalfact(GEN bnf, GEN C, GEN P, GEN e, long flag)
2018
{
2019
const long gen = flag & (nf_GEN|nf_GENMAT|nf_GEN_IF_PRINCIPAL);
2020
long prec;
2021
pari_sp av = avma;
2022
GEN C0, Cext, c, id, nf = checknf(bnf);
2023
2024
if (gen)
2025
{
2026
Cext = (flag & nf_GENMAT)? trivial_fact()
2027
: mkpolmod(gen_1,nf_get_pol(nf));
2028
C0 = mkvec2(C, Cext);
2029
id = expandext(nf, C0, P, e);
2030
} else {
2031
Cext = NULL;
2032
C0 = C;
2033
id = expand(nf, C, P, e);
2034
}
2035
if (id == C0) /* e = 0 */
2036
{
2037
if (!C) return bnfisprincipal0(bnf, gen_1, flag);
2038
switch(typ(C))
2039
{
2040
case t_INT: case t_FRAC: case t_POL: case t_POLMOD: case t_COL:
2041
return triv_gen(bnf, C, flag);
2042
}
2043
C = idealhnf_shallow(nf,C);
2044
}
2045
else
2046
{
2047
if (gen) { C = gel(id,1); Cext = gel(id,2); } else C = id;
2048
}
2049
prec = prec_arch(bnf);
2050
c = getrand();
2051
for (;;)
2052
{
2053
pari_sp av1 = avma;
2054
GEN y = isprincipalall(bnf, C, &prec, flag);
2055
if (y)
2056
{
2057
if (flag & nf_GEN_IF_PRINCIPAL)
2058
{
2059
if (typ(y) == t_INT) return gc_NULL(av);
2060
y = add_principal_part(nf, y, Cext, flag);
2061
}
2062
else
2063
{
2064
GEN u = gel(y,2);
2065
if (!gen || typ(y) != t_VEC) return gerepileupto(av,y);
2066
if (lg(u) != 1) gel(y,2) = add_principal_part(nf, u, Cext, flag);
2067
}
2068
return gerepilecopy(av, y);
2069
}
2070
if (DEBUGLEVEL) pari_warn(warnprec,"isprincipal",prec);
2071
set_avma(av1); bnf = bnfnewprec_shallow(bnf,prec); setrand(c);
2072
}
2073
}
2074
GEN
2075
isprincipalfact_or_fail(GEN bnf, GEN C, GEN P, GEN e)
2076
{
2077
const long flag = nf_GENMAT|nf_FORCE;
2078
long prec;
2079
pari_sp av = avma;
2080
GEN u, y, id, C0, Cext, nf = bnf_get_nf(bnf);
2081
2082
Cext = trivial_fact();
2083
C0 = mkvec2(C, Cext);
2084
id = expandext(nf, C0, P, e);
2085
if (id == C0) /* e = 0 */
2086
C = idealhnf_shallow(nf,C);
2087
else {
2088
C = gel(id,1); Cext = gel(id,2);
2089
}
2090
prec = prec_arch(bnf);
2091
y = isprincipalall(bnf, C, &prec, flag);
2092
if (!y) { set_avma(av); return utoipos(prec); }
2093
u = gel(y,2);
2094
if (lg(u) != 1) gel(y,2) = add_principal_part(nf, u, Cext, flag);
2095
return gerepilecopy(av, y);
2096
}
2097
2098
GEN
2099
nfsign_from_logarch(GEN LA, GEN invpi, GEN archp)
2100
{
2101
long l = lg(archp), i;
2102
GEN y = cgetg(l, t_VECSMALL);
2103
pari_sp av = avma;
2104
2105
for (i=1; i<l; i++)
2106
{
2107
GEN c = ground( gmul(imag_i(gel(LA,archp[i])), invpi) );
2108
y[i] = mpodd(c)? 1: 0;
2109
}
2110
set_avma(av); return y;
2111
}
2112
2113
GEN
2114
nfsign_tu(GEN bnf, GEN archp)
2115
{
2116
long n;
2117
if (bnf_get_tuN(bnf) != 2) return cgetg(1, t_VECSMALL);
2118
n = archp? lg(archp) - 1: nf_get_r1(bnf_get_nf(bnf));
2119
return const_vecsmall(n, 1);
2120
}
2121
GEN
2122
nfsign_fu(GEN bnf, GEN archp)
2123
{
2124
GEN invpi, y, A = bnf_get_logfu(bnf), nf = bnf_get_nf(bnf);
2125
long j = 1, RU = lg(A);
2126
2127
if (!archp) archp = identity_perm( nf_get_r1(nf) );
2128
invpi = invr( mppi(nf_get_prec(nf)) );
2129
y = cgetg(RU,t_MAT);
2130
for (j = 1; j < RU; j++)
2131
gel(y,j) = nfsign_from_logarch(gel(A,j), invpi, archp);
2132
return y;
2133
}
2134
GEN
2135
nfsign_units(GEN bnf, GEN archp, int add_zu)
2136
{
2137
GEN sfu = nfsign_fu(bnf, archp);
2138
return add_zu? vec_prepend(sfu, nfsign_tu(bnf, archp)): sfu;
2139
}
2140
2141
/* obsolete */
2142
GEN
2143
signunits(GEN bnf)
2144
{
2145
pari_sp av;
2146
GEN S, y, nf;
2147
long i, j, r1, r2;
2148
2149
bnf = checkbnf(bnf); nf = bnf_get_nf(bnf);
2150
nf_get_sign(nf, &r1,&r2);
2151
S = zeromatcopy(r1, r1+r2-1); av = avma;
2152
y = nfsign_fu(bnf, NULL);
2153
for (j = 1; j < lg(y); j++)
2154
{
2155
GEN Sj = gel(S,j), yj = gel(y,j);
2156
for (i = 1; i <= r1; i++) gel(Sj,i) = yj[i]? gen_m1: gen_1;
2157
}
2158
set_avma(av); return S;
2159
}
2160
2161
static GEN
2162
get_log_embed(REL_t *rel, GEN M, long RU, long R1, long prec)
2163
{
2164
GEN arch, C, z = rel->m;
2165
long i;
2166
arch = typ(z) == t_COL? RgM_RgC_mul(M, z): const_col(nbrows(M), z);
2167
C = cgetg(RU+1, t_COL); arch = glog(arch, prec);
2168
for (i=1; i<=R1; i++) gel(C,i) = gel(arch,i);
2169
for ( ; i<=RU; i++) gel(C,i) = gmul2n(gel(arch,i), 1);
2170
return C;
2171
}
2172
static GEN
2173
rel_embed(REL_t *rel, FB_t *F, GEN embs, long ind, GEN M, long RU, long R1,
2174
long prec)
2175
{
2176
GEN C, D, perm;
2177
long i, n;
2178
if (!rel->relaut) return get_log_embed(rel, M, RU, R1, prec);
2179
/* image of another relation by automorphism */
2180
C = gel(embs, ind - rel->relorig);
2181
perm = gel(F->embperm, rel->relaut);
2182
D = cgetg_copy(C, &n);
2183
for (i = 1; i < n; i++)
2184
{
2185
long v = perm[i];
2186
gel(D,i) = (v > 0)? gel(C,v): conj_i(gel(C,-v));
2187
}
2188
return D;
2189
}
2190
static GEN
2191
get_embs(FB_t *F, RELCACHE_t *cache, GEN nf, GEN embs, long PREC)
2192
{
2193
long ru, j, k, l = cache->last - cache->chk + 1, r1 = nf_get_r1(nf);
2194
GEN M = nf_get_M(nf), nembs = cgetg(cache->last - cache->base+1, t_MAT);
2195
REL_t *rel;
2196
2197
for (k = 1; k <= cache->chk - cache->base; k++) gel(nembs,k) = gel(embs,k);
2198
embs = nembs; ru = nbrows(M);
2199
for (j=1,rel = cache->chk + 1; j < l; rel++,j++,k++)
2200
gel(embs,k) = rel_embed(rel, F, embs, k, M, ru, r1, PREC);
2201
return embs;
2202
}
2203
static void
2204
set_rel_alpha(REL_t *rel, GEN auts, GEN vA, long ind)
2205
{
2206
GEN u;
2207
if (!rel->relaut)
2208
u = rel->m;
2209
else
2210
u = ZM_ZC_mul(gel(auts, rel->relaut), gel(vA, ind - rel->relorig));
2211
gel(vA, ind) = u;
2212
}
2213
static GEN
2214
set_fact(FB_t *F, FACT *fact, GEN e, long *pnz)
2215
{
2216
long n = fact[0].pr;
2217
GEN c = zero_Flv(F->KC);
2218
if (!n) /* trivial factorization */
2219
*pnz = F->KC+1;
2220
else
2221
{
2222
long i, nz = minss(fact[1].pr, fact[n].pr);
2223
for (i = 1; i <= n; i++) c[fact[i].pr] = fact[i].ex;
2224
if (e)
2225
{
2226
long l = lg(e);
2227
for (i = 1; i < l; i++)
2228
if (e[i]) { long v = F->subFB[i]; c[v] += e[i]; if (v < nz) nz = v; }
2229
}
2230
*pnz = nz;
2231
}
2232
return c;
2233
}
2234
2235
/* Is cols already in the cache ? bs = index of first non zero coeff in cols
2236
* General check for colinearity useless since exceedingly rare */
2237
static int
2238
already_known(RELCACHE_t *cache, long bs, GEN cols)
2239
{
2240
REL_t *r;
2241
long l = lg(cols);
2242
for (r = cache->last; r > cache->base; r--)
2243
if (bs == r->nz)
2244
{
2245
GEN coll = r->R;
2246
long b = bs;
2247
while (b < l && cols[b] == coll[b]) b++;
2248
if (b == l) return 1;
2249
}
2250
return 0;
2251
}
2252
2253
/* Add relation R to cache, nz = index of first non zero coeff in R.
2254
* If relation is a linear combination of the previous ones, return 0.
2255
* Otherwise, update basis and return > 0. Compute mod p (much faster)
2256
* so some kernel vector might not be genuine. */
2257
static int
2258
add_rel_i(RELCACHE_t *cache, GEN R, long nz, GEN m, long orig, long aut, REL_t **relp, long in_rnd_rel)
2259
{
2260
long i, k, n = lg(R)-1;
2261
2262
if (nz == n+1) { k = 0; goto ADD_REL; }
2263
if (already_known(cache, nz, R)) return -1;
2264
if (cache->last >= cache->base + cache->len) return 0;
2265
if (DEBUGLEVEL>6)
2266
{
2267
err_printf("adding vector = %Ps\n",R);
2268
err_printf("generators =\n%Ps\n", cache->basis);
2269
}
2270
if (cache->missing)
2271
{
2272
GEN a = leafcopy(R), basis = cache->basis;
2273
k = lg(a);
2274
do --k; while (!a[k]);
2275
while (k)
2276
{
2277
GEN c = gel(basis, k);
2278
if (c[k])
2279
{
2280
long ak = a[k];
2281
for (i=1; i < k; i++) if (c[i]) a[i] = (a[i] + ak*(mod_p-c[i])) % mod_p;
2282
a[k] = 0;
2283
do --k; while (!a[k]); /* k cannot go below 0: codeword is a sentinel */
2284
}
2285
else
2286
{
2287
ulong invak = Fl_inv(uel(a,k), mod_p);
2288
/* Cleanup a */
2289
for (i = k; i-- > 1; )
2290
{
2291
long j, ai = a[i];
2292
c = gel(basis, i);
2293
if (!ai || !c[i]) continue;
2294
ai = mod_p-ai;
2295
for (j = 1; j < i; j++) if (c[j]) a[j] = (a[j] + ai*c[j]) % mod_p;
2296
a[i] = 0;
2297
}
2298
/* Insert a/a[k] as k-th column */
2299
c = gel(basis, k);
2300
for (i = 1; i<k; i++) if (a[i]) c[i] = (a[i] * invak) % mod_p;
2301
c[k] = 1; a = c;
2302
/* Cleanup above k */
2303
for (i = k+1; i<n; i++)
2304
{
2305
long j, ck;
2306
c = gel(basis, i);
2307
ck = c[k];
2308
if (!ck) continue;
2309
ck = mod_p-ck;
2310
for (j = 1; j < k; j++) if (a[j]) c[j] = (c[j] + ck*a[j]) % mod_p;
2311
c[k] = 0;
2312
}
2313
cache->missing--;
2314
break;
2315
}
2316
}
2317
}
2318
else
2319
k = (cache->last - cache->base) + 1;
2320
if (k || cache->relsup > 0 || (m && in_rnd_rel))
2321
{
2322
REL_t *rel;
2323
2324
ADD_REL:
2325
rel = ++cache->last;
2326
if (!k && cache->relsup && nz < n+1)
2327
{
2328
cache->relsup--;
2329
k = (rel - cache->base) + cache->missing;
2330
}
2331
rel->R = gclone(R);
2332
rel->m = m ? gclone(m) : NULL;
2333
rel->nz = nz;
2334
if (aut)
2335
{
2336
rel->relorig = (rel - cache->base) - orig;
2337
rel->relaut = aut;
2338
}
2339
else
2340
rel->relaut = 0;
2341
if (relp) *relp = rel;
2342
if (DEBUGLEVEL) dbg_newrel(cache);
2343
}
2344
return k;
2345
}
2346
2347
static int
2348
add_rel(RELCACHE_t *cache, FB_t *F, GEN R, long nz, GEN m, long in_rnd_rel)
2349
{
2350
REL_t *rel;
2351
long k, l, reln;
2352
const long lauts = lg(F->idealperm), KC = F->KC;
2353
2354
k = add_rel_i(cache, R, nz, m, 0, 0, &rel, in_rnd_rel);
2355
if (k > 0 && typ(m) != t_INT)
2356
{
2357
GEN Rl = cgetg(KC+1, t_VECSMALL);
2358
reln = rel - cache->base;
2359
for (l = 1; l < lauts; l++)
2360
{
2361
GEN perml = gel(F->idealperm, l);
2362
long i, nzl = perml[nz];
2363
2364
for (i = 1; i <= KC; i++) Rl[i] = 0;
2365
for (i = nz; i <= KC; i++)
2366
if (R[i])
2367
{
2368
long v = perml[i];
2369
2370
if (v < nzl) nzl = v;
2371
Rl[v] = R[i];
2372
}
2373
(void)add_rel_i(cache, Rl, nzl, NULL, reln, l, NULL, in_rnd_rel);
2374
}
2375
}
2376
return k;
2377
}
2378
2379
INLINE void
2380
step(GEN x, double *y, GEN inc, long k)
2381
{
2382
if (!y[k])
2383
x[k]++; /* leading coeff > 0 */
2384
else
2385
{
2386
long i = inc[k];
2387
x[k] += i;
2388
inc[k] = (i > 0)? -1-i: 1-i;
2389
}
2390
}
2391
2392
INLINE long
2393
Fincke_Pohst_ideal(RELCACHE_t *cache, FB_t *F, GEN nf, GEN M, GEN I,
2394
GEN NI, FACT *fact, long Nrelid, FP_t *fp, RNDREL_t *rr, long prec,
2395
long *Nsmall, long *Nfact)
2396
{
2397
pari_sp av;
2398
const long N = nf_get_degree(nf), R1 = nf_get_r1(nf);
2399
GEN G = nf_get_G(nf), G0 = nf_get_roundG(nf), r, u, gx, inc, ideal;
2400
double BOUND, B1, B2;
2401
long j, k, skipfirst, relid=0, dependent=0, try_elt=0, try_factor=0;
2402
2403
inc = const_vecsmall(N, 1);
2404
u = ZM_lll(ZM_mul(G0, I), 0.99, LLL_IM);
2405
ideal = ZM_mul(I,u); /* approximate T2-LLL reduction */
2406
r = gaussred_from_QR(RgM_mul(G, ideal), prec); /* Cholesky for T2 | ideal */
2407
if (!r) pari_err_BUG("small_norm (precision too low)");
2408
2409
for (k=1; k<=N; k++)
2410
{
2411
if (!gisdouble(gcoeff(r,k,k),&(fp->v[k]))) return 0;
2412
for (j=1; j<k; j++) if (!gisdouble(gcoeff(r,j,k),&(fp->q[j][k]))) return 0;
2413
if (DEBUGLEVEL>3) err_printf("v[%ld]=%.4g ",k,fp->v[k]);
2414
}
2415
B1 = fp->v[1]; /* T2(ideal[1]) */
2416
B2 = fp->v[2] + B1 * fp->q[1][2] * fp->q[1][2]; /* T2(ideal[2]) */
2417
if (ZV_isscalar(gel(ideal,1))) /* probable */
2418
{
2419
skipfirst = 1;
2420
BOUND = mindd(BMULT * B1, 2 * B2);
2421
}
2422
else
2423
{
2424
BOUND = mindd(BMULT * B1, 2 * B2);
2425
skipfirst = 0;
2426
}
2427
/* BOUND at most BMULT fp->x smallest known vector */
2428
if (DEBUGLEVEL>1)
2429
{
2430
if (DEBUGLEVEL>3) err_printf("\n");
2431
err_printf("BOUND = %.4g\n",BOUND);
2432
}
2433
BOUND *= 1 + 1e-6;
2434
k = N; fp->y[N] = fp->z[N] = 0; fp->x[N] = 0;
2435
for (av = avma;; set_avma(av), step(fp->x,fp->y,inc,k))
2436
{
2437
GEN R;
2438
long nz;
2439
do
2440
{ /* look for primitive element of small norm, cf minim00 */
2441
int fl = 0;
2442
double p;
2443
if (k > 1)
2444
{
2445
long l = k-1;
2446
fp->z[l] = 0;
2447
for (j=k; j<=N; j++) fp->z[l] += fp->q[l][j]*fp->x[j];
2448
p = (double)fp->x[k] + fp->z[k];
2449
fp->y[l] = fp->y[k] + p*p*fp->v[k];
2450
if (l <= skipfirst && !fp->y[1]) fl = 1;
2451
fp->x[l] = (long)floor(-fp->z[l] + 0.5);
2452
k = l;
2453
}
2454
for(;; step(fp->x,fp->y,inc,k))
2455
{
2456
if (++try_elt > maxtry_ELEMENT) return 0;
2457
if (!fl)
2458
{
2459
p = (double)fp->x[k] + fp->z[k];
2460
if (fp->y[k] + p*p*fp->v[k] <= BOUND) break;
2461
2462
step(fp->x,fp->y,inc,k);
2463
2464
p = (double)fp->x[k] + fp->z[k];
2465
if (fp->y[k] + p*p*fp->v[k] <= BOUND) break;
2466
}
2467
fl = 0; inc[k] = 1;
2468
if (++k > N) return 0;
2469
}
2470
} while (k > 1);
2471
2472
/* element complete */
2473
if (zv_content(fp->x) !=1) continue; /* not primitive */
2474
gx = ZM_zc_mul(ideal,fp->x);
2475
if (ZV_isscalar(gx)) continue;
2476
if (++try_factor > maxtry_FACT) return 0;
2477
2478
if (!Nrelid)
2479
{
2480
if (!factorgen(F,nf,I,NI,gx,fact)) continue;
2481
return 1;
2482
}
2483
else if (rr)
2484
{
2485
if (!factorgen(F,nf,I,NI,gx,fact)) continue;
2486
add_to_fact(rr->jid, 1, fact);
2487
}
2488
else
2489
{
2490
GEN Nx, xembed = RgM_RgC_mul(M, gx);
2491
long e;
2492
if (Nsmall) (*Nsmall)++;
2493
Nx = grndtoi(embed_norm(xembed, R1), &e);
2494
if (e >= 0) {
2495
if (DEBUGLEVEL > 1) err_printf("+");
2496
continue;
2497
}
2498
if (!can_factor(F, nf, NULL, gx, Nx, fact)) continue;
2499
}
2500
2501
/* smooth element */
2502
R = set_fact(F, fact, rr ? rr->ex : NULL, &nz);
2503
/* make sure we get maximal rank first, then allow all relations */
2504
if (add_rel(cache, F, R, nz, gx, rr ? 1 : 0) <= 0)
2505
{ /* probably Q-dependent from previous ones: forget it */
2506
if (DEBUGLEVEL>1) err_printf("*");
2507
if (++dependent > maxtry_DEP) break;
2508
continue;
2509
}
2510
dependent = 0;
2511
if (DEBUGLEVEL && Nfact) (*Nfact)++;
2512
if (cache->last >= cache->end) return 1; /* we have enough */
2513
if (++relid == Nrelid) break;
2514
}
2515
return 0;
2516
}
2517
2518
static void
2519
small_norm(RELCACHE_t *cache, FB_t *F, GEN nf, long Nrelid, GEN M,
2520
FACT *fact, GEN p0)
2521
{
2522
const long prec = nf_get_prec(nf);
2523
FP_t fp;
2524
pari_sp av;
2525
GEN L_jid = F->L_jid, Np0;
2526
long Nsmall, Nfact, n = lg(L_jid);
2527
pari_timer T;
2528
2529
if (DEBUGLEVEL)
2530
{
2531
timer_start(&T);
2532
err_printf("#### Look for %ld relations in %ld ideals (small_norm)\n",
2533
cache->end - cache->last, lg(L_jid)-1);
2534
if (p0) err_printf("Look in p0 = %Ps\n", vecslice(p0,1,4));
2535
}
2536
Nsmall = Nfact = 0;
2537
minim_alloc(lg(M), &fp.q, &fp.x, &fp.y, &fp.z, &fp.v);
2538
Np0 = p0? pr_norm(p0): NULL;
2539
for (av = avma; --n; set_avma(av))
2540
{
2541
long j = L_jid[n];
2542
GEN id = gel(F->LP, j), Nid;
2543
if (DEBUGLEVEL>1)
2544
err_printf("\n*** Ideal no %ld: %Ps\n", j, vecslice(id,1,4));
2545
if (p0)
2546
{ Nid = mulii(Np0, pr_norm(id)); id = idealmul(nf, p0, id); }
2547
else
2548
{ Nid = pr_norm(id); id = pr_hnf(nf, id);}
2549
if (Fincke_Pohst_ideal(cache, F, nf, M, id, Nid, fact, Nrelid, &fp,
2550
NULL, prec, &Nsmall, &Nfact)) break;
2551
}
2552
if (DEBUGLEVEL && Nsmall)
2553
{
2554
if (DEBUGLEVEL == 1)
2555
{ if (Nfact) err_printf("\n"); }
2556
else
2557
err_printf(" \nnb. fact./nb. small norm = %ld/%ld = %.3f\n",
2558
Nfact,Nsmall,((double)Nfact)/Nsmall);
2559
if (timer_get(&T)>1) timer_printf(&T,"small_norm");
2560
}
2561
}
2562
2563
static GEN
2564
get_random_ideal(FB_t *F, GEN nf, GEN ex)
2565
{
2566
long i, l = lg(ex);
2567
for (;;)
2568
{
2569
GEN I = NULL;
2570
for (i = 1; i < l; i++)
2571
if ((ex[i] = random_bits(RANDOM_BITS)))
2572
{
2573
GEN pr = gel(F->LP, F->subFB[i]), e = utoipos(ex[i]);
2574
I = I? idealmulpowprime(nf, I, pr, e): idealpow(nf, pr, e);
2575
}
2576
if (I && !ZM_isscalar(I,NULL)) return I; /* != (n)Z_K */
2577
}
2578
}
2579
2580
static void
2581
rnd_rel(RELCACHE_t *cache, FB_t *F, GEN nf, FACT *fact)
2582
{
2583
pari_timer T;
2584
GEN L_jid = F->L_jid, M = nf_get_M(nf), R, NR;
2585
long i, l = lg(L_jid), prec = nf_get_prec(nf);
2586
RNDREL_t rr;
2587
FP_t fp;
2588
pari_sp av;
2589
2590
if (DEBUGLEVEL) {
2591
timer_start(&T);
2592
err_printf("\n#### Look for %ld relations in %ld ideals (rnd_rel)\n",
2593
cache->end - cache->last, l-1);
2594
}
2595
rr.ex = cgetg(lg(F->subFB), t_VECSMALL);
2596
R = get_random_ideal(F, nf, rr.ex); /* random product from subFB */
2597
NR = ZM_det_triangular(R);
2598
minim_alloc(lg(M), &fp.q, &fp.x, &fp.y, &fp.z, &fp.v);
2599
for (av = avma, i = 1; i < l; i++, set_avma(av))
2600
{ /* try P[j] * base */
2601
long j = L_jid[i];
2602
GEN P = gel(F->LP, j), Nid = mulii(NR, pr_norm(P));
2603
if (DEBUGLEVEL>1) err_printf("\n*** Ideal %ld: %Ps\n", j, vecslice(P,1,4));
2604
rr.jid = j;
2605
if (Fincke_Pohst_ideal(cache, F, nf, M, idealHNF_mul(nf, R, P), Nid, fact,
2606
RND_REL_RELPID, &fp, &rr, prec, NULL, NULL)) break;
2607
}
2608
if (DEBUGLEVEL)
2609
{
2610
err_printf("\n");
2611
if (timer_get(&T) > 1) timer_printf(&T,"for remaining ideals");
2612
}
2613
}
2614
2615
static GEN
2616
automorphism_perms(GEN M, GEN auts, GEN cyclic, long r1, long r2, long N)
2617
{
2618
long L = lgcols(M), lauts = lg(auts), lcyc = lg(cyclic), i, j, l, m;
2619
GEN Mt, perms = cgetg(lauts, t_VEC);
2620
pari_sp av;
2621
2622
for (l = 1; l < lauts; l++) gel(perms, l) = cgetg(L, t_VECSMALL);
2623
av = avma;
2624
Mt = shallowtrans(gprec_w(M, LOWDEFAULTPREC));
2625
Mt = shallowconcat(Mt, conj_i(vecslice(Mt, r1+1, r1+r2)));
2626
for (l = 1; l < lcyc; l++)
2627
{
2628
GEN thiscyc = gel(cyclic, l), thisperm, perm, prev, Nt;
2629
long k = thiscyc[1];
2630
2631
Nt = RgM_mul(shallowtrans(gel(auts, k)), Mt);
2632
perm = gel(perms, k);
2633
for (i = 1; i < L; i++)
2634
{
2635
GEN v = gel(Nt, i), minD;
2636
minD = gnorml2(gsub(v, gel(Mt, 1)));
2637
perm[i] = 1;
2638
for (j = 2; j <= N; j++)
2639
{
2640
GEN D = gnorml2(gsub(v, gel(Mt, j)));
2641
if (gcmp(D, minD) < 0) { minD = D; perm[i] = j >= L ? r2-j : j; }
2642
}
2643
}
2644
for (prev = perm, m = 2; m < lg(thiscyc); m++, prev = thisperm)
2645
{
2646
thisperm = gel(perms, thiscyc[m]);
2647
for (i = 1; i < L; i++)
2648
{
2649
long pp = labs(prev[i]);
2650
thisperm[i] = prev[i] < 0 ? -perm[pp] : perm[pp];
2651
}
2652
}
2653
}
2654
set_avma(av); return perms;
2655
}
2656
2657
/* Determine the field automorphisms as matrices on the integral basis */
2658
static GEN
2659
automorphism_matrices(GEN nf, GEN *cycp)
2660
{
2661
pari_sp av = avma;
2662
GEN auts = galoisconj(nf, NULL), mats, cyclic, cyclicidx;
2663
long nauts = lg(auts)-1, i, j, k, l;
2664
2665
cyclic = cgetg(nauts+1, t_VEC);
2666
cyclicidx = zero_Flv(nauts);
2667
for (l = 1; l <= nauts; l++)
2668
{
2669
GEN aut = gel(auts, l);
2670
if (gequalX(aut)) { swap(gel(auts, l), gel(auts, nauts)); break; }
2671
}
2672
/* trivial automorphism is last */
2673
for (l = 1; l <= nauts; l++) gel(auts, l) = algtobasis(nf, gel(auts, l));
2674
/* Compute maximal cyclic subgroups */
2675
for (l = nauts; --l > 0; ) if (!cyclicidx[l])
2676
{
2677
GEN elt = gel(auts, l), aut = elt, cyc = cgetg(nauts+1, t_VECSMALL);
2678
cyc[1] = cyclicidx[l] = l; j = 1;
2679
do
2680
{
2681
elt = galoisapply(nf, elt, aut);
2682
for (k = 1; k <= nauts; k++) if (gequal(elt, gel(auts, k))) break;
2683
cyclicidx[k] = l; cyc[++j] = k;
2684
}
2685
while (k != nauts);
2686
setlg(cyc, j);
2687
gel(cyclic, l) = cyc;
2688
}
2689
for (i = j = 1; i < nauts; i++)
2690
if (cyclicidx[i] == i) cyclic[j++] = cyclic[i];
2691
setlg(cyclic, j);
2692
mats = cgetg(nauts, t_VEC);
2693
while (--j > 0)
2694
{
2695
GEN cyc = gel(cyclic, j);
2696
long id = cyc[1];
2697
GEN M, Mi, aut = gel(auts, id);
2698
2699
gel(mats, id) = Mi = M = nfgaloismatrix(nf, aut);
2700
for (i = 2; i < lg(cyc); i++) gel(mats, cyc[i]) = Mi = ZM_mul(Mi, M);
2701
}
2702
gerepileall(av, 2, &mats, &cyclic);
2703
if (cycp) *cycp = cyclic;
2704
return mats;
2705
}
2706
2707
/* vP a list of maximal ideals above the same p from idealprimedec: f(P/p) is
2708
* increasing; 1 <= j <= #vP; orbit a zc of length <= #vP; auts a vector of
2709
* automorphisms in ZM form.
2710
* Set orbit[i] = 1 for all vP[i], i >= j, in the orbit of pr = vP[j] wrt auts.
2711
* N.B.1 orbit need not be initialized to 0: useful to incrementally run
2712
* through successive orbits
2713
* N.B.2 i >= j, so primes with index < j will be missed; run incrementally
2714
* starting from j = 1 ! */
2715
static void
2716
pr_orbit_fill(GEN orbit, GEN auts, GEN vP, long j)
2717
{
2718
GEN pr = gel(vP,j), gen = pr_get_gen(pr);
2719
long i, l = lg(auts), J = lg(orbit), f = pr_get_f(pr);
2720
orbit[j] = 1;
2721
for (i = 1; i < l; i++)
2722
{
2723
GEN g = ZM_ZC_mul(gel(auts,i), gen);
2724
long k;
2725
for (k = j+1; k < J; k++)
2726
{
2727
GEN prk = gel(vP,k);
2728
if (pr_get_f(prk) > f) break; /* f(P[k]) increases with k */
2729
/* don't check that e matches: (almost) always 1 ! */
2730
if (!orbit[k] && ZC_prdvd(g, prk)) { orbit[k] = 1; break; }
2731
}
2732
}
2733
}
2734
/* remark: F->KCZ changes if be_honest() fails */
2735
static int
2736
be_honest(FB_t *F, GEN nf, GEN auts, FACT *fact)
2737
{
2738
long i, iz, nbtest;
2739
long lgsub = lg(F->subFB), KCZ0 = F->KCZ;
2740
long N = nf_get_degree(nf), prec = nf_get_prec(nf);
2741
GEN M = nf_get_M(nf);
2742
FP_t fp;
2743
pari_sp av;
2744
2745
if (DEBUGLEVEL) {
2746
err_printf("Be honest for %ld primes from %ld to %ld\n", F->KCZ2 - F->KCZ,
2747
F->FB[ F->KCZ+1 ], F->FB[ F->KCZ2 ]);
2748
}
2749
minim_alloc(N+1, &fp.q, &fp.x, &fp.y, &fp.z, &fp.v);
2750
if (lg(auts) == 1) auts = NULL;
2751
av = avma;
2752
for (iz=F->KCZ+1; iz<=F->KCZ2; iz++, set_avma(av))
2753
{
2754
long p = F->FB[iz];
2755
GEN pr_orbit, P = gel(F->LV,p);
2756
long j, J = lg(P); /* > 1 */
2757
/* the P|p, NP > C2 are assumed in subgroup generated by FB + last P
2758
* with NP <= C2 is unramified --> check all but last */
2759
if (pr_get_e(gel(P,J-1)) == 1) J--;
2760
if (J == 1) continue;
2761
if (DEBUGLEVEL>1) err_printf("%ld ", p);
2762
pr_orbit = auts? zero_zv(J-1): NULL;
2763
for (j = 1; j < J; j++)
2764
{
2765
GEN Nid, id, id0;
2766
if (pr_orbit)
2767
{
2768
if (pr_orbit[j]) continue;
2769
/* discard all primes in automorphism orbit simultaneously */
2770
pr_orbit_fill(pr_orbit, auts, P, j);
2771
}
2772
id = id0 = pr_hnf(nf,gel(P,j));
2773
Nid = pr_norm(gel(P,j));
2774
for (nbtest=0;;)
2775
{
2776
if (Fincke_Pohst_ideal(NULL, F, nf, M, id, Nid, fact, 0, &fp,
2777
NULL, prec, NULL, NULL)) break;
2778
if (++nbtest > maxtry_HONEST)
2779
{
2780
if (DEBUGLEVEL)
2781
pari_warn(warner,"be_honest() failure on prime %Ps\n", gel(P,j));
2782
return 0;
2783
}
2784
/* occurs at most once in the whole function */
2785
for (i = 1, id = id0; i < lgsub; i++)
2786
{
2787
long ex = random_bits(RANDOM_BITS);
2788
if (ex)
2789
{
2790
GEN pr = gel(F->LP, F->subFB[i]);
2791
id = idealmulpowprime(nf, id, pr, utoipos(ex));
2792
}
2793
}
2794
if (!equali1(gcoeff(id,N,N))) id = Q_primpart(id);
2795
if (expi(gcoeff(id,1,1)) > 100) id = idealred(nf, id);
2796
Nid = ZM_det_triangular(id);
2797
}
2798
}
2799
F->KCZ++; /* SUCCESS, "enlarge" factorbase */
2800
}
2801
F->KCZ = KCZ0; return gc_bool(av,1);
2802
}
2803
2804
/* all primes with N(P) <= BOUND factor on factorbase ? */
2805
void
2806
bnftestprimes(GEN bnf, GEN BOUND)
2807
{
2808
pari_sp av0 = avma, av;
2809
ulong count = 0;
2810
GEN auts, p, nf = bnf_get_nf(bnf), Vbase = bnf_get_vbase(bnf);
2811
GEN fb = gen_sort_shallow(Vbase, (void*)&cmp_prime_ideal, cmp_nodata);
2812
ulong pmax = pr_get_smallp(gel(fb, lg(fb)-1)); /*largest p in factorbase*/
2813
forprime_t S;
2814
FACT *fact;
2815
FB_t F;
2816
2817
(void)recover_partFB(&F, Vbase, nf_get_degree(nf));
2818
fact = (FACT*)stack_malloc((F.KC+1)*sizeof(FACT));
2819
forprime_init(&S, gen_2, BOUND);
2820
auts = automorphism_matrices(nf, NULL);
2821
if (lg(auts) == 1) auts = NULL;
2822
av = avma;
2823
while (( p = forprime_next(&S) ))
2824
{
2825
GEN pr_orbit, vP;
2826
long j, J;
2827
2828
if (DEBUGLEVEL == 1 && ++count > 1000)
2829
{
2830
err_printf("passing p = %Ps / %Ps\n", p, BOUND);
2831
count = 0;
2832
}
2833
set_avma(av);
2834
vP = idealprimedec_limit_norm(bnf, p, BOUND);
2835
J = lg(vP);
2836
/* if last is unramified, all P|p in subgroup generated by FB: skip last */
2837
if (J > 1 && pr_get_e(gel(vP,J-1)) == 1) J--;
2838
if (J == 1) continue;
2839
if (DEBUGLEVEL>1) err_printf("*** p = %Ps\n",p);
2840
pr_orbit = auts? zero_zv(J-1): NULL;
2841
for (j = 1; j < J; j++)
2842
{
2843
GEN P = gel(vP,j);
2844
long k = 0;
2845
if (pr_orbit)
2846
{
2847
if (pr_orbit[j]) continue;
2848
/* discard all primes in automorphism orbit simultaneously */
2849
pr_orbit_fill(pr_orbit, auts, vP, j);
2850
}
2851
if (abscmpiu(p, pmax) > 0 || !(k = tablesearch(fb, P, &cmp_prime_ideal)))
2852
(void)SPLIT(&F, nf, pr_hnf(nf,P), Vbase, fact);
2853
if (DEBUGLEVEL>1)
2854
{
2855
err_printf(" Testing P = %Ps\n",P);
2856
if (k) err_printf(" #%ld in factor base\n",k);
2857
else err_printf(" is %Ps\n", isprincipal(bnf,P));
2858
}
2859
}
2860
}
2861
set_avma(av0);
2862
}
2863
2864
/* A t_MAT of complex floats, in fact reals. Extract a submatrix B
2865
* whose columns are definitely nonzero, i.e. gexpo(A[j]) >= -2
2866
*
2867
* If possible precision problem (t_REAL 0 with large exponent), set
2868
* *precpb to 1 */
2869
static GEN
2870
clean_cols(GEN A, int *precpb)
2871
{
2872
long l = lg(A), h, i, j, k;
2873
GEN B;
2874
*precpb = 0;
2875
if (l == 1) return A;
2876
h = lgcols(A);;
2877
B = cgetg(l, t_MAT);
2878
for (i = k = 1; i < l; i++)
2879
{
2880
GEN Ai = gel(A,i);
2881
int non0 = 0;
2882
for (j = 1; j < h; j++)
2883
{
2884
GEN c = gel(Ai,j);
2885
if (gexpo(c) >= -2)
2886
{
2887
if (gequal0(c)) *precpb = 1; else non0 = 1;
2888
}
2889
}
2890
if (non0) gel(B, k++) = Ai;
2891
}
2892
setlg(B, k); return B;
2893
}
2894
2895
static long
2896
compute_multiple_of_R_pivot(GEN X, GEN x0/*unused*/, long ix, GEN c)
2897
{
2898
GEN x = gel(X,ix);
2899
long i, k = 0, ex = - (long)HIGHEXPOBIT, lx = lg(x);
2900
(void)x0;
2901
for (i=1; i<lx; i++)
2902
if (!c[i] && !gequal0(gel(x,i)))
2903
{
2904
long e = gexpo(gel(x,i));
2905
if (e > ex) { ex = e; k = i; }
2906
}
2907
return (k && ex > -32)? k: lx;
2908
}
2909
2910
/* Ar = (log |sigma_i(u_j)|) for units (u_j) found so far,
2911
* RU = R1+R2 = unit rank, N = field degree
2912
* need = unit rank defect
2913
* L = NULL (prec problem) or B^(-1) * A with approximate rational entries
2914
* (as t_REAL), B a submatrix of A, with (probably) maximal rank RU */
2915
static GEN
2916
compute_multiple_of_R(GEN Ar, long RU, long N, long *pneed, long *bit, GEN *ptL)
2917
{
2918
GEN T, d, mdet, Im_mdet, kR, L;
2919
long i, j, r, R1 = 2*RU - N;
2920
int precpb;
2921
pari_sp av = avma;
2922
2923
if (RU == 1) { *ptL = zeromat(0, lg(Ar)-1); return gen_1; }
2924
2925
if (DEBUGLEVEL) err_printf("\n#### Computing regulator multiple\n");
2926
mdet = clean_cols(Ar, &precpb);
2927
/* will cause precision to increase on later failure, but we may succeed! */
2928
*ptL = precpb? NULL: gen_1;
2929
T = cgetg(RU+1,t_COL);
2930
for (i=1; i<=R1; i++) gel(T,i) = gen_1;
2931
for ( ; i<=RU; i++) gel(T,i) = gen_2;
2932
mdet = shallowconcat(T, mdet); /* det(Span(mdet)) = N * R */
2933
2934
/* could be using indexrank(), but need custom "get_pivot" function */
2935
d = RgM_pivots(mdet, NULL, &r, &compute_multiple_of_R_pivot);
2936
/* # of independent columns == unit rank ? */
2937
if (lg(mdet)-1 - r != RU)
2938
{
2939
if (DEBUGLEVEL)
2940
err_printf("Unit group rank = %ld < %ld\n",lg(mdet)-1 - r, RU);
2941
*pneed = RU - (lg(mdet)-1-r); return gc_NULL(av);
2942
}
2943
2944
Im_mdet = cgetg(RU+1, t_MAT); /* extract independent columns */
2945
/* N.B: d[1] = 1, corresponding to T above */
2946
gel(Im_mdet, 1) = T;
2947
for (i = j = 2; i <= RU; j++)
2948
if (d[j]) gel(Im_mdet, i++) = gel(mdet,j);
2949
2950
/* integral multiple of R: the cols we picked form a Q-basis, they have an
2951
* index in the full lattice. First column is T */
2952
kR = divru(det2(Im_mdet), N);
2953
/* R > 0.2 uniformly */
2954
if (!signe(kR) || expo(kR) < -3)
2955
{
2956
if (DEBUGLEVEL) err_printf("Regulator is zero.\n");
2957
*pneed = 0; return gc_NULL(av);
2958
}
2959
d = det2(rowslice(vecslice(Im_mdet, 2, RU), 2, RU));
2960
setabssign(d); setabssign(kR);
2961
if (gexpo(gsub(d,kR)) - gexpo(d) > -20) { *ptL = NULL; return gc_NULL(av); }
2962
L = RgM_inv(Im_mdet);
2963
/* estimate # of correct bits in result */
2964
if (!L || (*bit = - gexpo(RgM_Rg_sub(RgM_mul(L,Im_mdet), gen_1))) < 16)
2965
{ *ptL = NULL; return gc_NULL(av); }
2966
2967
L = RgM_mul(rowslice(L,2,RU), Ar); /* approximate rational entries */
2968
gerepileall(av,2, &L, &kR);
2969
*ptL = L; return kR;
2970
}
2971
2972
/* leave small integer n as is, convert huge n to t_REAL (for readability) */
2973
static GEN
2974
i2print(GEN n)
2975
{ return lgefint(n) <= DEFAULTPREC? n: itor(n,LOWDEFAULTPREC); }
2976
2977
static long
2978
bad_check(GEN c)
2979
{
2980
long ec = gexpo(c);
2981
if (DEBUGLEVEL) err_printf("\n ***** check = %.28Pg\n",c);
2982
/* safe check for c < 0.75 : avoid underflow in gtodouble() */
2983
if (ec < -1 || (ec == -1 && gtodouble(c) < 0.75)) return fupb_PRECI;
2984
/* safe check for c > 1.3 : avoid overflow */
2985
if (ec > 0 || (ec == 0 && gtodouble(c) > 1.3)) return fupb_RELAT;
2986
return fupb_NONE;
2987
}
2988
/* Input:
2989
* lambda = approximate rational entries: coords of units found so far on a
2990
* sublattice of maximal rank (sublambda)
2991
* *ptkR = regulator of sublambda = multiple of regulator of lambda
2992
* Compute R = true regulator of lambda.
2993
*
2994
* If c := Rz ~ 1, by Dirichlet's formula, then lambda is the full group of
2995
* units AND the full set of relations for the class group has been computed.
2996
*
2997
* In fact z is a very rough approximation and we only expect 0.75 < Rz < 1.3
2998
* bit is an estimate for the actual accuracy of lambda
2999
*
3000
* Output: *ptkR = R, *ptU = basis of fundamental units (in terms lambda) */
3001
static long
3002
compute_R(GEN lambda, GEN z, GEN *ptL, GEN *ptkR)
3003
{
3004
pari_sp av = avma;
3005
long bit, r, reason, RU = lg(lambda) == 1? 1: lgcols(lambda);
3006
GEN L, H, D, den, R, c;
3007
3008
*ptL = NULL;
3009
if (DEBUGLEVEL) err_printf("\n#### Computing check\n");
3010
if (RU == 1) { *ptkR = gen_1; *ptL = lambda; return bad_check(z); }
3011
D = gmul2n(mpmul(*ptkR,z), 1); /* bound for denom(lambda) */
3012
if (expo(D) < 0 && rtodbl(D) < 0.95) return fupb_PRECI;
3013
L = bestappr(lambda,D);
3014
if (lg(L) == 1)
3015
{
3016
if (DEBUGLEVEL) err_printf("truncation error in bestappr\n");
3017
return fupb_PRECI;
3018
}
3019
den = Q_denom(L);
3020
if (mpcmp(den,D) > 0)
3021
{
3022
if (DEBUGLEVEL) err_printf("D = %Ps\nden = %Ps\n",D, i2print(den));
3023
return fupb_PRECI;
3024
}
3025
bit = -gexpo(gsub(L, lambda)); /* input accuracy */
3026
L = Q_muli_to_int(L, den);
3027
if (gexpo(L) + expi(den) > bit - 32)
3028
{
3029
if (DEBUGLEVEL) err_printf("dubious bestappr; den = %Ps\n", i2print(den));
3030
return fupb_PRECI;
3031
}
3032
H = ZM_hnf(L); r = lg(H)-1;
3033
if (!r || r != nbrows(H))
3034
R = gen_0; /* wrong rank */
3035
else
3036
R = gmul(*ptkR, gdiv(ZM_det_triangular(H), powiu(den, r)));
3037
/* R = tentative regulator; regulator > 0.2 uniformly */
3038
if (gexpo(R) < -3) {
3039
if (DEBUGLEVEL) err_printf("\n#### Tentative regulator: %.28Pg\n", R);
3040
return gc_long(av, fupb_PRECI);
3041
}
3042
c = gmul(R,z); /* should be n (= 1 if we are done) */
3043
if (DEBUGLEVEL) err_printf("\n#### Tentative regulator: %.28Pg\n", R);
3044
if ((reason = bad_check(c))) return gc_long(av, reason);
3045
*ptkR = R; *ptL = L; return fupb_NONE;
3046
}
3047
static GEN
3048
get_clg2(GEN cyc, GEN Ga, GEN C, GEN Ur, GEN Ge, GEN M1, GEN M2)
3049
{
3050
GEN GD = gsub(act_arch(M1, C), diagact_arch(cyc, Ga));
3051
GEN ga = gsub(act_arch(M2, C), act_arch(Ur, Ga));
3052
return mkvecn(6, Ur, ga, GD, Ge, M1, M2);
3053
}
3054
/* compute class group (clg1) + data for isprincipal (clg2) */
3055
static GEN
3056
class_group_gen(GEN nf,GEN W,GEN C,GEN Vbase,long prec, GEN *pclg2)
3057
{
3058
GEN M1, M2, z, G, Ga, Ge, cyc, X, Y, D, U, V, Ur, Ui, Uir;
3059
long j, l;
3060
3061
D = ZM_snfall(W,&U,&V); /* UWV=D, D diagonal, G = g Ui (G=new gens, g=old) */
3062
Ui = ZM_inv(U, NULL);
3063
l = lg(D); cyc = cgetg(l, t_VEC); /* elementary divisors */
3064
for (j = 1; j < l; j++)
3065
{
3066
gel(cyc,j) = gcoeff(D,j,j); /* strip useless components */
3067
if (is_pm1(gel(cyc,j))) break;
3068
}
3069
l = j;
3070
Ur = ZM_hnfdivrem(U, D, &Y);
3071
Uir = ZM_hnfdivrem(Ui,W, &X);
3072
/* {x} = logarithmic embedding of x (arch. component)
3073
* NB: [J,z] = idealred(I) --> I = y J, with {y} = - z
3074
* G = g Uir - {Ga}, Uir = Ui + WX
3075
* g = G Ur - {ga}, Ur = U + DY */
3076
G = cgetg(l,t_VEC);
3077
Ga= cgetg(l,t_MAT);
3078
Ge= cgetg(l,t_COL);
3079
z = init_famat(NULL);
3080
for (j = 1; j < l; j++)
3081
{
3082
GEN I = genback(z, nf, Vbase, gel(Uir,j));
3083
gel(G,j) = gel(I,1); /* generator, order cyc[j] */
3084
gel(Ge,j)= gel(I,2);
3085
gel(Ga,j)= nf_cxlog(nf, gel(I,2), prec);
3086
if (!gel(Ga,j)) pari_err_PREC("class_group_gen");
3087
}
3088
/* {ga} = {GD}Y + G U - g = {GD}Y - {Ga} U + gW X U
3089
= gW (X Ur + V Y) - {Ga}Ur */
3090
M2 = ZM_add(ZM_mul(X,Ur), ZM_mul(V,Y));
3091
setlg(cyc,l); setlg(V,l); setlg(D,l);
3092
/* G D =: {GD} = g (Ui + W X) D - {Ga}D = g W (V + X D) - {Ga}D
3093
* NB: Ui D = W V. gW is given by (first l-1 cols of) C */
3094
M1 = ZM_add(V, ZM_mul(X,D));
3095
*pclg2 = get_clg2(cyc, Ga, C, Ur, Ge, M1, M2);
3096
return mkvec3(ZV_prod(cyc), cyc, G);
3097
}
3098
3099
/* compute principal ideals corresponding to (gen[i]^cyc[i]) */
3100
static GEN
3101
makecycgen(GEN bnf)
3102
{
3103
GEN cyc, gen, h, nf, y, GD;
3104
long e,i,l;
3105
3106
if (DEBUGLEVEL) pari_warn(warner,"completing bnf (building cycgen)");
3107
nf = bnf_get_nf(bnf);
3108
cyc = bnf_get_cyc(bnf);
3109
gen = bnf_get_gen(bnf);
3110
GD = bnf_get_GD(bnf);
3111
h = cgetg_copy(gen, &l);
3112
for (i = 1; i < l; i++)
3113
{
3114
GEN gi = gel(gen,i), ci = gel(cyc,i);
3115
if (abscmpiu(ci, 5) < 0)
3116
{
3117
GEN N = ZM_det_triangular(gi);
3118
y = isprincipalarch(bnf,gel(GD,i), N, ci, gen_1, &e);
3119
if (y && fact_ok(nf,y,NULL,mkvec(gi),mkvec(ci)))
3120
{
3121
gel(h,i) = to_famat_shallow(y,gen_1);
3122
continue;
3123
}
3124
}
3125
y = isprincipalfact(bnf, NULL, mkvec(gi), mkvec(ci), nf_GENMAT|nf_FORCE);
3126
gel(h,i) = gel(y,2);
3127
}
3128
return h;
3129
}
3130
3131
static GEN
3132
get_y(GEN bnf, GEN W, GEN B, GEN C, GEN pFB, long j)
3133
{
3134
GEN y, nf = bnf_get_nf(bnf);
3135
long e, lW = lg(W)-1;
3136
GEN ex = (j<=lW)? gel(W,j): gel(B,j-lW);
3137
GEN P = (j<=lW)? NULL: gel(pFB,j);
3138
if (C)
3139
{ /* archimedean embeddings known: cheap trial */
3140
GEN Nx = get_norm_fact_primes(pFB, ex, P);
3141
y = isprincipalarch(bnf,gel(C,j), Nx,gen_1, gen_1, &e);
3142
if (y && fact_ok(nf,y,P,pFB,ex)) return y;
3143
}
3144
y = isprincipalfact_or_fail(bnf, P, pFB, ex);
3145
return typ(y) == t_INT? y: gel(y,2);
3146
}
3147
/* compute principal ideals corresponding to bnf relations */
3148
static GEN
3149
makematal(GEN bnf)
3150
{
3151
GEN W = bnf_get_W(bnf), B = bnf_get_B(bnf), C = bnf_get_C(bnf);
3152
GEN pFB, ma, retry;
3153
long lma, j, prec = 0;
3154
3155
if (DEBUGLEVEL) pari_warn(warner,"completing bnf (building matal)");
3156
lma=lg(W)+lg(B)-1;
3157
pFB = bnf_get_vbase(bnf);
3158
ma = cgetg(lma,t_VEC);
3159
retry = vecsmalltrunc_init(lma);
3160
for (j=lma-1; j>0; j--)
3161
{
3162
pari_sp av = avma;
3163
GEN y = get_y(bnf, W, B, C, pFB, j);
3164
if (typ(y) == t_INT)
3165
{
3166
long E = itos(y);
3167
if (DEBUGLEVEL>1) err_printf("\n%ld done later at prec %ld\n",j,E);
3168
set_avma(av);
3169
vecsmalltrunc_append(retry, j);
3170
if (E > prec) prec = E;
3171
}
3172
else
3173
{
3174
if (DEBUGLEVEL>1) err_printf("%ld ",j);
3175
gel(ma,j) = gerepileupto(av,y);
3176
}
3177
}
3178
if (prec)
3179
{
3180
long k, l = lg(retry);
3181
GEN y, nf = bnf_get_nf(bnf);
3182
if (DEBUGLEVEL) pari_warn(warnprec,"makematal",prec);
3183
nf = nfnewprec_shallow(nf,prec);
3184
bnf = Buchall(nf, nf_FORCE, prec);
3185
if (DEBUGLEVEL) err_printf("makematal, adding missing entries:");
3186
for (k=1; k<l; k++)
3187
{
3188
pari_sp av = avma;
3189
long j = retry[k];
3190
y = get_y(bnf,W,B,NULL, pFB, j);
3191
if (typ(y) == t_INT) pari_err_PREC("makematal");
3192
if (DEBUGLEVEL>1) err_printf("%ld ",j);
3193
gel(ma,j) = gerepileupto(av,y);
3194
}
3195
}
3196
if (DEBUGLEVEL>1) err_printf("\n");
3197
return ma;
3198
}
3199
3200
enum { MATAL = 1, CYCGEN, UNITS };
3201
GEN
3202
bnf_build_cycgen(GEN bnf)
3203
{ return obj_checkbuild(bnf, CYCGEN, &makecycgen); }
3204
GEN
3205
bnf_build_matalpha(GEN bnf)
3206
{ return obj_checkbuild(bnf, MATAL, &makematal); }
3207
GEN
3208
bnf_build_units(GEN bnf)
3209
{ return obj_checkbuild(bnf, UNITS, &makeunits); }
3210
3211
/* return fu in compact form if available; in terms of a fixed basis
3212
* of S-units */
3213
GEN
3214
bnf_compactfu_mat(GEN bnf)
3215
{
3216
GEN X, U, SUnits = bnf_get_sunits(bnf);
3217
if (!SUnits) return NULL;
3218
X = gel(SUnits,1);
3219
U = gel(SUnits,2); ZM_remove_unused(&U, &X);
3220
return mkvec2(X, U);
3221
}
3222
/* return fu in compact form if available; individually as famat */
3223
GEN
3224
bnf_compactfu(GEN bnf)
3225
{
3226
GEN fu, X, U, SUnits = bnf_get_sunits(bnf);
3227
long i, l;
3228
if (!SUnits) return NULL;
3229
X = gel(SUnits,1);
3230
U = gel(SUnits,2); l = lg(U); fu = cgetg(l, t_VEC);
3231
for (i = 1; i < l; i++)
3232
gel(fu,i) = famat_remove_trivial(mkmat2(X, gel(U,i)));
3233
return fu;
3234
}
3235
/* return expanded fu if available */
3236
GEN
3237
bnf_has_fu(GEN bnf)
3238
{
3239
GEN fu = obj_check(bnf, UNITS);
3240
if (fu) return vecsplice(fu, 1);
3241
fu = bnf_get_fu_nocheck(bnf);
3242
return (typ(fu) == t_MAT)? NULL: fu;
3243
}
3244
/* return expanded fu if available; build if cheap */
3245
GEN
3246
bnf_build_cheapfu(GEN bnf)
3247
{
3248
GEN fu, SUnits;
3249
if ((fu = bnf_has_fu(bnf))) return fu;
3250
if ((SUnits = bnf_get_sunits(bnf)))
3251
{
3252
pari_sp av = avma;
3253
long e = gexpo(real_i(bnf_get_logfu(bnf)));
3254
set_avma(av); if (e < 13) return vecsplice(bnf_build_units(bnf), 1);
3255
}
3256
return NULL;
3257
}
3258
3259
static GEN
3260
get_regulator(GEN mun)
3261
{
3262
pari_sp av = avma;
3263
GEN R;
3264
3265
if (lg(mun) == 1) return gen_1;
3266
R = det( rowslice(real_i(mun), 1, lgcols(mun)-2) );
3267
setabssign(R); return gerepileuptoleaf(av, R);
3268
}
3269
3270
/* return corrected archimedian components for elts of x (vector)
3271
* (= log(sigma_i(x)) - log(|Nx|) / [K:Q]) */
3272
static GEN
3273
get_archclean(GEN nf, GEN x, long prec, int units)
3274
{
3275
long k, N, l = lg(x);
3276
GEN M = cgetg(l, t_MAT);
3277
3278
if (l == 1) return M;
3279
N = nf_get_degree(nf);
3280
for (k = 1; k < l; k++)
3281
{
3282
pari_sp av = avma;
3283
GEN c = nf_cxlog(nf, gel(x,k), prec);
3284
if (!c || (!units && !(c = cleanarch(c, N, prec)))) return NULL;
3285
gel(M,k) = gerepilecopy(av, c);
3286
}
3287
return M;
3288
}
3289
static void
3290
Sunits_archclean(GEN nf, GEN Sunits, GEN *pmun, GEN *pC, long prec)
3291
{
3292
GEN M, X = gel(Sunits,1), U = gel(Sunits,2), G = gel(Sunits,3);
3293
long k, N = nf_get_degree(nf), l = lg(X);
3294
3295
M = cgetg(l, t_MAT);
3296
for (k = 1; k < l; k++)
3297
if (!(gel(M,k) = nf_cxlog(nf, gel(X,k), prec))) return;
3298
*pmun = cleanarch(RgM_ZM_mul(M, U), N, prec);
3299
if (*pmun) *pC = cleanarch(RgM_ZM_mul(M, G), N, prec);
3300
}
3301
3302
GEN
3303
bnfnewprec_shallow(GEN bnf, long prec)
3304
{
3305
GEN nf0 = bnf_get_nf(bnf), nf, v, fu, matal, y, mun, C;
3306
GEN Sunits = bnf_get_sunits(bnf), Ur, Ga, Ge, M1, M2;
3307
long r1, r2, prec0 = prec;
3308
3309
nf_get_sign(nf0, &r1, &r2);
3310
if (Sunits)
3311
{
3312
fu = matal = NULL;
3313
prec += nbits2extraprec(gexpo(Sunits));
3314
}
3315
else
3316
{
3317
fu = bnf_build_units(bnf);
3318
fu = vecslice(fu, 2, lg(fu)-1);
3319
if (r1 + r2 > 1) {
3320
long e = gexpo(bnf_get_logfu(bnf)) + 1 - TWOPOTBITS_IN_LONG;
3321
if (e >= 0) prec += nbits2extraprec(e);
3322
}
3323
matal = bnf_build_matalpha(bnf);
3324
}
3325
3326
if (DEBUGLEVEL && prec0 != prec) pari_warn(warnprec,"bnfnewprec",prec);
3327
for(C = NULL;;)
3328
{
3329
pari_sp av = avma;
3330
nf = nfnewprec_shallow(nf0,prec);
3331
if (Sunits)
3332
Sunits_archclean(nf, Sunits, &mun, &C, prec);
3333
else
3334
{
3335
mun = get_archclean(nf, fu, prec, 1);
3336
if (mun) C = get_archclean(nf, matal, prec, 0);
3337
}
3338
if (C) break;
3339
set_avma(av); prec = precdbl(prec);
3340
if (DEBUGLEVEL) pari_warn(warnprec,"bnfnewprec(extra)",prec);
3341
}
3342
y = leafcopy(bnf);
3343
gel(y,3) = mun;
3344
gel(y,4) = C;
3345
gel(y,7) = nf;
3346
gel(y,8) = v = leafcopy(gel(bnf,8));
3347
gel(v,2) = get_regulator(mun);
3348
v = gel(bnf,9);
3349
if (lg(v) < 7) pari_err_TYPE("bnfnewprec [obsolete bnf format]", bnf);
3350
Ur = gel(v,1);
3351
Ge = gel(v,4);
3352
Ga = nfV_cxlog(nf, Ge, prec);
3353
M1 = gel(v,5);
3354
M2 = gel(v,6);
3355
gel(y,9) = get_clg2(bnf_get_cyc(bnf), Ga, C, Ur, Ge, M1, M2);
3356
return y;
3357
}
3358
GEN
3359
bnfnewprec(GEN bnf, long prec)
3360
{
3361
pari_sp av = avma;
3362
return gerepilecopy(av, bnfnewprec_shallow(checkbnf(bnf), prec));
3363
}
3364
3365
GEN
3366
bnrnewprec_shallow(GEN bnr, long prec)
3367
{
3368
GEN y = cgetg(7,t_VEC);
3369
long i;
3370
gel(y,1) = bnfnewprec_shallow(bnr_get_bnf(bnr), prec);
3371
for (i=2; i<7; i++) gel(y,i) = gel(bnr,i);
3372
return y;
3373
}
3374
GEN
3375
bnrnewprec(GEN bnr, long prec)
3376
{
3377
GEN y = cgetg(7,t_VEC);
3378
long i;
3379
checkbnr(bnr);
3380
gel(y,1) = bnfnewprec(bnr_get_bnf(bnr), prec);
3381
for (i=2; i<7; i++) gel(y,i) = gcopy(gel(bnr,i));
3382
return y;
3383
}
3384
3385
static GEN
3386
buchall_end(GEN nf,GEN res, GEN clg2, GEN W, GEN B, GEN A, GEN C,GEN Vbase)
3387
{
3388
GEN z = obj_init(9, 3);
3389
gel(z,1) = W;
3390
gel(z,2) = B;
3391
gel(z,3) = A;
3392
gel(z,4) = C;
3393
gel(z,5) = Vbase;
3394
gel(z,6) = gen_0;
3395
gel(z,7) = nf;
3396
gel(z,8) = res;
3397
gel(z,9) = clg2;
3398
return z;
3399
}
3400
3401
GEN
3402
bnfinit0(GEN P, long flag, GEN data, long prec)
3403
{
3404
double c1 = 0., c2 = 0.;
3405
long fl, relpid = BNF_RELPID;
3406
3407
if (data)
3408
{
3409
long lx = lg(data);
3410
if (typ(data) != t_VEC || lx > 5) pari_err_TYPE("bnfinit",data);
3411
switch(lx)
3412
{
3413
case 4: relpid = itos(gel(data,3));
3414
case 3: c2 = gtodouble(gel(data,2));
3415
case 2: c1 = gtodouble(gel(data,1));
3416
}
3417
}
3418
switch(flag)
3419
{
3420
case 2:
3421
case 0: fl = 0; break;
3422
case 1: fl = nf_FORCE; break;
3423
default: pari_err_FLAG("bnfinit");
3424
return NULL; /* LCOV_EXCL_LINE */
3425
}
3426
return Buchall_param(P, c1, c2, relpid, fl, prec);
3427
}
3428
GEN
3429
Buchall(GEN P, long flag, long prec)
3430
{ return Buchall_param(P, 0., 0., BNF_RELPID, flag & nf_FORCE, prec); }
3431
3432
static GEN
3433
Buchall_deg1(GEN nf)
3434
{
3435
GEN v = cgetg(1,t_VEC), m = cgetg(1,t_MAT);
3436
GEN res, W, A, B, C, Vbase = cgetg(1,t_COL);
3437
GEN fu = v, R = gen_1, zu = mkvec2(gen_2, gen_m1);
3438
GEN clg1 = mkvec3(gen_1,v,v), clg2 = mkvecn(6, m,m,m,v,m,m);
3439
3440
W = A = B = C = m; res = mkvec5(clg1, R, gen_1, zu, fu);
3441
return buchall_end(nf,res,clg2,W,B,A,C,Vbase);
3442
}
3443
3444
/* return (small set of) indices of columns generating the same lattice as x.
3445
* Assume HNF(x) is inexpensive (few rows, many columns).
3446
* Dichotomy approach since interesting columns may be at the very end */
3447
GEN
3448
extract_full_lattice(GEN x)
3449
{
3450
long dj, j, k, l = lg(x);
3451
GEN h, h2, H, v;
3452
3453
if (l < 200) return NULL; /* not worth it */
3454
3455
v = vecsmalltrunc_init(l);
3456
H = ZM_hnf(x);
3457
h = cgetg(1, t_MAT);
3458
dj = 1;
3459
for (j = 1; j < l; )
3460
{
3461
pari_sp av = avma;
3462
long lv = lg(v);
3463
3464
for (k = 0; k < dj; k++) v[lv+k] = j+k;
3465
setlg(v, lv + dj);
3466
h2 = ZM_hnf(vecpermute(x, v));
3467
if (ZM_equal(h, h2))
3468
{ /* these dj columns can be eliminated */
3469
set_avma(av); setlg(v, lv);
3470
j += dj;
3471
if (j >= l) break;
3472
dj <<= 1;
3473
if (j + dj >= l) { dj = (l - j) >> 1; if (!dj) dj = 1; }
3474
}
3475
else if (dj > 1)
3476
{ /* at least one interesting column, try with first half of this set */
3477
set_avma(av); setlg(v, lv);
3478
dj >>= 1; /* > 0 */
3479
}
3480
else
3481
{ /* this column should be kept */
3482
if (ZM_equal(h2, H)) break;
3483
h = h2; j++;
3484
}
3485
}
3486
return v;
3487
}
3488
3489
static void
3490
init_rel(RELCACHE_t *cache, FB_t *F, long add_need)
3491
{
3492
const long n = F->KC + add_need; /* expected # of needed relations */
3493
long i, j, k, p;
3494
GEN c, P;
3495
GEN R;
3496
3497
if (DEBUGLEVEL) err_printf("KCZ = %ld, KC = %ld, n = %ld\n", F->KCZ,F->KC,n);
3498
reallocate(cache, 10*n + 50); /* make room for lots of relations */
3499
cache->chk = cache->base;
3500
cache->end = cache->base + n;
3501
cache->relsup = add_need;
3502
cache->last = cache->base;
3503
cache->missing = lg(cache->basis) - 1;
3504
for (i = 1; i <= F->KCZ; i++)
3505
{ /* trivial relations (p) = prod P^e */
3506
p = F->FB[i]; P = gel(F->LV,p);
3507
if (!isclone(P)) continue;
3508
3509
/* all prime divisors in FB */
3510
c = zero_Flv(F->KC); k = F->iLP[p];
3511
R = c; c += k;
3512
for (j = lg(P)-1; j; j--) c[j] = pr_get_e(gel(P,j));
3513
add_rel(cache, F, R, k+1, pr_get_p(gel(P,1)), 0);
3514
}
3515
}
3516
3517
/* Let z = \zeta_n in nf. List of not-obviously-dependent generators for
3518
* cyclotomic units modulo torsion in Q(z) [independent when n a prime power]:
3519
* - z^a - 1, n/(a,n) not a prime power, a \nmid n unless a=1, 1 <= a < n/2
3520
* - (Z^a - 1)/(Z - 1), p^k || n, Z = z^{n/p^k}, (p,a) = 1, 1 < a <= (p^k-1)/2
3521
*/
3522
GEN
3523
nfcyclotomicunits(GEN nf, GEN zu)
3524
{
3525
long n = itos(gel(zu, 1)), n2, lP, i, a;
3526
GEN z, fa, P, E, L, mz, powz;
3527
if (n <= 6) return cgetg(1, t_VEC);
3528
3529
z = algtobasis(nf,gel(zu, 2));
3530
if ((n & 3) == 2) { n = n >> 1; z = ZC_neg(z); } /* ensure n != 2 (mod 4) */
3531
n2 = n/2;
3532
mz = zk_multable(nf, z); /* multiplication by z */
3533
powz = cgetg(n2, t_VEC); gel(powz,1) = z;
3534
for (i = 2; i < n2; i++) gel(powz,i) = ZM_ZC_mul(mz, gel(powz,i-1));
3535
/* powz[i] = z^i */
3536
3537
L = vectrunc_init(n);
3538
fa = factoru(n);
3539
P = gel(fa,1); lP = lg(P);
3540
E = gel(fa,2);
3541
for (i = 1; i < lP; i++)
3542
{ /* second kind */
3543
long p = P[i], k = E[i], pk = upowuu(p,k), pk2 = (pk-1) / 2;
3544
GEN u = gen_1;
3545
for (a = 2; a <= pk2; a++)
3546
{
3547
u = nfadd(nf, u, gel(powz, (n/pk) * (a-1))); /* = (Z^a-1)/(Z-1) */
3548
if (a % p) vectrunc_append(L, u);
3549
}
3550
}
3551
if (lP > 2) for (a = 1; a < n2; a++)
3552
{ /* first kind, when n not a prime power */
3553
ulong p;
3554
if (a > 1 && (n % a == 0 || uisprimepower(n/ugcd(a,n), &p))) continue;
3555
vectrunc_append(L, nfadd(nf, gel(powz, a), gen_m1));
3556
}
3557
return L;
3558
}
3559
static void
3560
add_cyclotomic_units(GEN nf, GEN zu, RELCACHE_t *cache, FB_t *F)
3561
{
3562
pari_sp av = avma;
3563
GEN L = nfcyclotomicunits(nf, zu);
3564
long i, l = lg(L);
3565
if (l > 1)
3566
{
3567
GEN R = zero_Flv(F->KC);
3568
for(i = 1; i < l; i++) add_rel(cache, F, R, F->KC+1, gel(L,i), 0);
3569
}
3570
set_avma(av);
3571
}
3572
3573
static GEN
3574
trim_list(FB_t *F)
3575
{
3576
pari_sp av = avma;
3577
GEN v, L_jid = F->L_jid, minidx = F->minidx, present = zero_Flv(F->KC);
3578
long i, j, imax = minss(lg(L_jid), F->KC + 1);
3579
3580
v = cgetg(imax, t_VECSMALL);
3581
for (i = j = 1; i < imax; i++)
3582
{
3583
long k = minidx[ L_jid[i] ];
3584
if (!present[k]) { v[j++] = L_jid[i]; present[k] = 1; }
3585
}
3586
setlg(v, j); return gerepileuptoleaf(av, v);
3587
}
3588
3589
static void
3590
try_elt(RELCACHE_t *cache, FB_t *F, GEN nf, GEN x, FACT *fact)
3591
{
3592
pari_sp av = avma;
3593
GEN R, Nx;
3594
long nz, tx = typ(x);
3595
3596
if (tx == t_INT || tx == t_FRAC) return;
3597
if (tx != t_COL) x = algtobasis(nf, x);
3598
if (RgV_isscalar(x)) return;
3599
x = Q_primpart(x);
3600
Nx = nfnorm(nf, x);
3601
if (!can_factor(F, nf, NULL, x, Nx, fact)) return;
3602
3603
/* smooth element */
3604
R = set_fact(F, fact, NULL, &nz);
3605
/* make sure we get maximal rank first, then allow all relations */
3606
(void) add_rel(cache, F, R, nz, x, 0);
3607
set_avma(av);
3608
}
3609
3610
static void
3611
matenlarge(GEN C, long h)
3612
{
3613
GEN _0 = zerocol(h);
3614
long i;
3615
for (i = lg(C); --i; ) gel(C,i) = shallowconcat(gel(C,i), _0);
3616
}
3617
3618
/* E = floating point embeddings */
3619
static GEN
3620
matbotidembs(RELCACHE_t *cache, GEN E)
3621
{
3622
long w = cache->last - cache->chk, h = cache->last - cache->base;
3623
long j, d = h - w, hE = nbrows(E);
3624
GEN y = cgetg(w+1,t_MAT), _0 = zerocol(h);
3625
for (j = 1; j <= w; j++)
3626
{
3627
GEN c = shallowconcat(gel(E,j), _0);
3628
if (d + j >= 1) gel(c, d + j + hE) = gen_1;
3629
gel(y,j) = c;
3630
}
3631
return y;
3632
}
3633
static GEN
3634
matbotid(RELCACHE_t *cache)
3635
{
3636
long w = cache->last - cache->chk, h = cache->last - cache->base;
3637
long j, d = h - w;
3638
GEN y = cgetg(w+1,t_MAT);
3639
for (j = 1; j <= w; j++)
3640
{
3641
GEN c = zerocol(h);
3642
if (d + j >= 1) gel(c, d + j) = gen_1;
3643
gel(y,j) = c;
3644
}
3645
return y;
3646
}
3647
3648
static long
3649
myprecdbl(long prec, GEN C)
3650
{
3651
long p = prec2nbits(prec) < 1280? precdbl(prec): (long)(prec * 1.5);
3652
if (C) p = maxss(p, minss(3*p, prec + nbits2extraprec(gexpo(C))));
3653
return p;
3654
}
3655
3656
static GEN
3657
_nfnewprec(GEN nf, long prec, long *isclone)
3658
{
3659
GEN NF = gclone(nfnewprec_shallow(nf, prec));
3660
if (*isclone) gunclone(nf);
3661
*isclone = 1; return NF;
3662
}
3663
3664
/* Nrelid = nb relations per ideal, possibly 0. If flag is set, keep data in
3665
* algebraic form. */
3666
GEN
3667
Buchall_param(GEN P, double cbach, double cbach2, long Nrelid, long flag, long prec)
3668
{
3669
pari_timer T;
3670
pari_sp av0 = avma, av, av2;
3671
long PREC, N, R1, R2, RU, low, high, LIMC0, LIMC, LIMC2, LIMCMAX, zc, i;
3672
long LIMres, bit = 0, flag_nfinit = 0;
3673
long nreldep, sfb_trials, need, old_need, precdouble = 0, TRIES = 0;
3674
long nfisclone = 0;
3675
long done_small, small_fail, fail_limit, squash_index, small_norm_prec;
3676
double LOGD, LOGD2, lim;
3677
GEN computed = NULL, fu = NULL, zu, nf, M_sn, D, A, W, R, h, Ce, PERM;
3678
GEN small_multiplier, auts, cyclic, embs, SUnits;
3679
GEN res, L, invhr, B, C, lambda, dep, clg1, clg2, Vbase;
3680
const char *precpb = NULL;
3681
nfmaxord_t nfT;
3682
RELCACHE_t cache;
3683
FB_t F;
3684
GRHcheck_t GRHcheck;
3685
FACT *fact;
3686
3687
if (DEBUGLEVEL) timer_start(&T);
3688
P = get_nfpol(P, &nf);
3689
if (nf)
3690
D = nf_get_disc(nf);
3691
else
3692
{
3693
nfinit_basic(&nfT, P);
3694
D = nfT.dK;
3695
if (!ZX_is_monic(nfT.T0))
3696
{
3697
pari_warn(warner,"nonmonic polynomial in bnfinit, using polredbest");
3698
flag_nfinit = nf_RED;
3699
}
3700
}
3701
N = degpol(P);
3702
if (N <= 1)
3703
{
3704
if (!nf) nf = nfinit_complete(&nfT, flag_nfinit, DEFAULTPREC);
3705
return gerepilecopy(av0, Buchall_deg1(nf));
3706
}
3707
D = absi_shallow(D);
3708
LOGD = dbllog2(D) * M_LN2;
3709
LOGD2 = LOGD*LOGD;
3710
LIMCMAX = (long)(12.*LOGD2);
3711
/* In small_norm, LLL reduction produces v0 in I such that
3712
* T2(v0) <= (4/3)^((n-1)/2) NI^(2/n) disc(K)^(1/n)
3713
* We consider v with T2(v) <= BMULT * T2(v0)
3714
* Hence Nv <= ((4/3)^((n-1)/2) * BMULT / n)^(n/2) NI sqrt(disc(K)).
3715
* NI <= LIMCMAX^2 */
3716
PREC = maxss(DEFAULTPREC, prec);
3717
if (nf) PREC = maxss(PREC, nf_get_prec(nf));
3718
PREC = maxss(PREC, nbits2prec((long)(LOGD2 * 0.02) + N*N));
3719
if (DEBUGLEVEL) err_printf("PREC = %ld\n", PREC);
3720
small_norm_prec = nbits2prec( BITS_IN_LONG +
3721
(N/2. * ((N-1)/2.*log(4./3) + log(BMULT/(double)N))
3722
+ 2*log((double) LIMCMAX) + LOGD/2) / M_LN2 ); /*enough to compute norms*/
3723
if (small_norm_prec > PREC) PREC = small_norm_prec;
3724
if (!nf)
3725
nf = nfinit_complete(&nfT, flag_nfinit, PREC);
3726
else if (nf_get_prec(nf) < PREC)
3727
nf = nfnewprec_shallow(nf, PREC);
3728
M_sn = nf_get_M(nf);
3729
if (PREC > small_norm_prec) M_sn = gprec_w(M_sn, small_norm_prec);
3730
3731
zu = nfrootsof1(nf);
3732
gel(zu,2) = nf_to_scalar_or_alg(nf, gel(zu,2));
3733
3734
nf_get_sign(nf, &R1, &R2); RU = R1+R2;
3735
auts = automorphism_matrices(nf, &cyclic);
3736
F.embperm = automorphism_perms(nf_get_M(nf), auts, cyclic, R1, R2, N);
3737
if (DEBUGLEVEL)
3738
{
3739
timer_printf(&T, "nfinit & nfrootsof1");
3740
err_printf("%s bnf: R1 = %ld, R2 = %ld\nD = %Ps\n",
3741
flag? "Algebraic": "Floating point", R1,R2, D);
3742
}
3743
if (LOGD < 20.)
3744
{ /* tiny disc, Minkowski may be smaller than Bach */
3745
lim = exp(-N + R2 * log(4/M_PI) + LOGD/2) * sqrt(2*M_PI*N);
3746
if (lim < 3) lim = 3;
3747
}
3748
else /* to be ignored */
3749
lim = -1;
3750
if (cbach > 12.) {
3751
if (cbach2 < cbach) cbach2 = cbach;
3752
cbach = 12.;
3753
}
3754
if (cbach < 0.)
3755
pari_err_DOMAIN("Buchall","Bach constant","<",gen_0,dbltor(cbach));
3756
3757
cache.base = NULL; F.subFB = NULL; F.LP = NULL; SUnits = Ce = NULL;
3758
init_GRHcheck(&GRHcheck, N, R1, LOGD);
3759
high = low = LIMC0 = maxss((long)(cbach2*LOGD2), 1);
3760
while (!GRHchk(nf, &GRHcheck, high)) { low = high; high *= 2; }
3761
while (high - low > 1)
3762
{
3763
long test = (low+high)/2;
3764
if (GRHchk(nf, &GRHcheck, test)) high = test; else low = test;
3765
}
3766
LIMC2 = (high == LIMC0+1 && GRHchk(nf, &GRHcheck, LIMC0))? LIMC0: high;
3767
if (LIMC2 > LIMCMAX) LIMC2 = LIMCMAX;
3768
/* Assuming GRH, {P, NP <= LIMC2} generate Cl(K) */
3769
if (DEBUGLEVEL) err_printf("LIMC2 = %ld\n", LIMC2);
3770
LIMC0 = (long)(cbach*LOGD2); /* initial value for LIMC */
3771
LIMC = cbach? LIMC0: LIMC2; /* use {P, NP <= LIMC} as a factorbase */
3772
LIMC = maxss(LIMC, nthideal(&GRHcheck, nf, N));
3773
if (DEBUGLEVEL) timer_printf(&T, "computing Bach constant");
3774
LIMres = primeneeded(N, R1, R2, LOGD);
3775
cache_prime_dec(&GRHcheck, LIMres, nf);
3776
/* invhr ~ 2^r1 (2pi)^r2 / sqrt(D) w * Res(zeta_K, s=1) = 1 / hR */
3777
invhr = gmul(gdiv(gmul2n(powru(mppi(DEFAULTPREC), R2), RU),
3778
mulri(gsqrt(D,DEFAULTPREC),gel(zu,1))),
3779
compute_invres(&GRHcheck, LIMres));
3780
if (DEBUGLEVEL) timer_printf(&T, "computing inverse of hR");
3781
av = avma;
3782
3783
START:
3784
if (DEBUGLEVEL) timer_start(&T);
3785
if (TRIES) LIMC = bnf_increase_LIMC(LIMC,LIMCMAX);
3786
if (DEBUGLEVEL && LIMC > LIMC0)
3787
err_printf("%s*** Bach constant: %f\n", TRIES?"\n":"", LIMC/LOGD2);
3788
if (cache.base)
3789
{
3790
REL_t *rel;
3791
for (i = 1, rel = cache.base + 1; rel < cache.last; rel++)
3792
if (rel->m) i++;
3793
computed = cgetg(i, t_VEC);
3794
for (i = 1, rel = cache.base + 1; rel < cache.last; rel++)
3795
if (rel->m) gel(computed, i++) = rel->m;
3796
computed = gclone(computed); delete_cache(&cache);
3797
}
3798
TRIES++; set_avma(av);
3799
if (F.LP) delete_FB(&F);
3800
if (LIMC2 < LIMC) LIMC2 = LIMC;
3801
if (DEBUGLEVEL) { err_printf("LIMC = %ld, LIMC2 = %ld\n",LIMC,LIMC2); }
3802
3803
FBgen(&F, nf, N, LIMC, LIMC2, &GRHcheck);
3804
if (!F.KC) goto START;
3805
av = avma;
3806
subFBgen(&F,auts,cyclic,lim < 0? LIMC2: mindd(lim,LIMC2),MINSFB);
3807
if (lg(F.subFB) == 1) goto START;
3808
if (DEBUGLEVEL)
3809
timer_printf(&T, "factorbase (#subFB = %ld) and ideal permutations",
3810
lg(F.subFB)-1);
3811
3812
fact = (FACT*)stack_malloc((F.KC+1)*sizeof(FACT));
3813
PERM = leafcopy(F.perm); /* to be restored in case of precision increase */
3814
cache.basis = zero_Flm_copy(F.KC,F.KC);
3815
small_multiplier = zero_Flv(F.KC);
3816
done_small = small_fail = squash_index = zc = sfb_trials = nreldep = 0;
3817
fail_limit = F.KC + 1;
3818
W = A = R = NULL;
3819
av2 = avma;
3820
init_rel(&cache, &F, RELSUP + RU-1);
3821
old_need = need = cache.end - cache.last;
3822
add_cyclotomic_units(nf, zu, &cache, &F);
3823
if (DEBUGLEVEL) err_printf("\n");
3824
cache.end = cache.last + need;
3825
3826
if (computed)
3827
{
3828
for (i = 1; i < lg(computed); i++)
3829
try_elt(&cache, &F, nf, gel(computed, i), fact);
3830
gunclone(computed);
3831
if (DEBUGLEVEL && i > 1)
3832
timer_printf(&T, "including already computed relations");
3833
need = 0;
3834
}
3835
3836
do
3837
{
3838
GEN Ar, C0;
3839
do
3840
{
3841
pari_sp av4 = avma;
3842
if (need > 0)
3843
{
3844
long oneed = cache.end - cache.last;
3845
/* Test below can be true if small_norm did not find enough linearly
3846
* dependent relations */
3847
if (need < oneed) need = oneed;
3848
pre_allocate(&cache, need+lg(auts)-1+(R ? lg(W)-1 : 0));
3849
cache.end = cache.last + need;
3850
F.L_jid = trim_list(&F);
3851
}
3852
if (need > 0 && Nrelid > 0 && (done_small <= F.KC+1 || A) &&
3853
small_fail <= fail_limit &&
3854
cache.last < cache.base + 2*F.KC+2*RU+RELSUP /* heuristic */)
3855
{
3856
long j, k, LIE = (R && lg(W) > 1 && (done_small % 2));
3857
REL_t *last = cache.last;
3858
pari_sp av3 = avma;
3859
GEN p0;
3860
if (LIE)
3861
{ /* We have full rank for class group and unit. The following tries to
3862
* improve the prime group lattice by looking for relations involving
3863
* the primes generating the class group. */
3864
long n = lg(W)-1; /* need n relations to squash the class group */
3865
F.L_jid = vecslice(F.perm, 1, n);
3866
cache.end = cache.last + n;
3867
/* Lie to the add_rel subsystem: pretend we miss relations involving
3868
* the primes generating the class group (and only those). */
3869
cache.missing = n;
3870
for ( ; n > 0; n--) mael(cache.basis, F.perm[n], F.perm[n]) = 0;
3871
}
3872
j = done_small % (F.KC+1);
3873
if (j == 0) p0 = NULL;
3874
else
3875
{
3876
p0 = gel(F.LP, j);
3877
if (!A)
3878
{ /* Prevent considering both P_iP_j and P_jP_i in small_norm */
3879
/* Not all elements end up in F.L_jid (eliminated by hnfspec/add or
3880
* by trim_list): keep track of which ideals are being considered
3881
* at each run. */
3882
long mj = small_multiplier[j];
3883
for (i = k = 1; i < lg(F.L_jid); i++)
3884
if (F.L_jid[i] > mj)
3885
{
3886
small_multiplier[F.L_jid[i]] = j;
3887
F.L_jid[k++] = F.L_jid[i];
3888
}
3889
setlg(F.L_jid, k);
3890
}
3891
}
3892
if (lg(F.L_jid) > 1)
3893
small_norm(&cache, &F, nf, Nrelid, M_sn, fact, p0);
3894
F.L_jid = F.perm; set_avma(av3);
3895
if (!A && cache.last != last) small_fail = 0; else small_fail++;
3896
if (LIE)
3897
{ /* restore add_rel subsystem: undo above lie */
3898
long n = lg(W) - 1;
3899
for ( ; n > 0; n--) mael(cache.basis, F.perm[n], F.perm[n]) = 1;
3900
cache.missing = 0;
3901
}
3902
cache.end = cache.last;
3903
done_small++;
3904
need = F.sfb_chg = 0;
3905
}
3906
if (need > 0)
3907
{ /* Random relations */
3908
if (++nreldep > F.MAXDEPSIZESFB) {
3909
if (++sfb_trials > SFB_MAX && LIMC < LIMCMAX/6) goto START;
3910
F.sfb_chg = sfb_INCREASE;
3911
nreldep = 0;
3912
}
3913
else if (!(nreldep % F.MAXDEPSFB))
3914
F.sfb_chg = sfb_CHANGE;
3915
if (F.sfb_chg && !subFB_change(&F)) goto START;
3916
rnd_rel(&cache, &F, nf, fact);
3917
F.L_jid = F.perm;
3918
}
3919
if (DEBUGLEVEL) timer_start(&T);
3920
if (precpb)
3921
{
3922
REL_t *rel;
3923
if (DEBUGLEVEL)
3924
{
3925
char str[64]; sprintf(str,"Buchall_param (%s)",precpb);
3926
pari_warn(warnprec,str,PREC);
3927
}
3928
nf = _nfnewprec(nf, PREC, &nfisclone);
3929
precdouble++; precpb = NULL;
3930
3931
if (flag)
3932
{ /* recompute embs only, no need to redo HNF */
3933
long j, le = lg(embs), lC = lg(C);
3934
GEN E, M = nf_get_M(nf);
3935
set_avma(av4);
3936
for (rel = cache.base+1, i = 1; i < le; i++,rel++)
3937
gel(embs,i) = rel_embed(rel, &F, embs, i, M, RU, R1, PREC);
3938
E = RgM_ZM_mul(embs, rowslice(C, RU+1, nbrows(C)));
3939
for (j = 1; j < lC; j++)
3940
for (i = 1; i <= RU; i++) gcoeff(C,i,j) = gcoeff(E,i,j);
3941
av4 = avma;
3942
}
3943
else
3944
{ /* recompute embs + HNF */
3945
for(i = 1; i < lg(PERM); i++) F.perm[i] = PERM[i];
3946
cache.chk = cache.base;
3947
W = NULL;
3948
}
3949
if (DEBUGLEVEL) timer_printf(&T, "increasing accuracy");
3950
}
3951
set_avma(av4);
3952
if (cache.chk != cache.last)
3953
{ /* Reduce relation matrices */
3954
long l = cache.last - cache.chk + 1, j;
3955
GEN mat = cgetg(l, t_MAT);
3956
REL_t *rel;
3957
3958
for (j=1,rel = cache.chk + 1; j < l; rel++,j++) gel(mat,j) = rel->R;
3959
if (!flag || W)
3960
{
3961
embs = get_embs(&F, &cache, nf, embs, PREC);
3962
if (DEBUGLEVEL && timer_get(&T) > 1)
3963
timer_printf(&T, "floating point embeddings");
3964
}
3965
if (!W)
3966
{ /* never reduced before */
3967
C = flag? matbotid(&cache): embs;
3968
W = hnfspec_i(mat, F.perm, &dep, &B, &C, F.subFB ? lg(F.subFB)-1:0);
3969
if (DEBUGLEVEL)
3970
timer_printf(&T, "hnfspec [%ld x %ld]", lg(F.perm)-1, l-1);
3971
if (flag)
3972
{
3973
PREC += nbits2extraprec(gexpo(C));
3974
if (nf_get_prec(nf) < PREC) nf = _nfnewprec(nf, PREC, &nfisclone);
3975
embs = get_embs(&F, &cache, nf, embs, PREC);
3976
C = vconcat(RgM_ZM_mul(embs, C), C);
3977
}
3978
if (DEBUGLEVEL)
3979
timer_printf(&T, "hnfspec floating points");
3980
}
3981
else
3982
{
3983
long k = lg(embs);
3984
GEN E = vecslice(embs, k-l+1,k-1);
3985
if (flag)
3986
{
3987
E = matbotidembs(&cache, E);
3988
matenlarge(C, cache.last - cache.chk);
3989
}
3990
W = hnfadd_i(W, F.perm, &dep, &B, &C, mat, E);
3991
if (DEBUGLEVEL)
3992
timer_printf(&T, "hnfadd (%ld + %ld)", l-1, lg(dep)-1);
3993
}
3994
gerepileall(av2, 5, &W,&C,&B,&dep,&embs);
3995
cache.chk = cache.last;
3996
}
3997
else if (!W)
3998
{
3999
need = old_need;
4000
F.L_jid = vecslice(F.perm, 1, need);
4001
continue;
4002
}
4003
need = F.KC - (lg(W)-1) - (lg(B)-1);
4004
if (!need && cache.missing)
4005
{ /* The test above will never be true except if 27449|class number.
4006
* Ensure that if we have maximal rank for the ideal lattice, then
4007
* cache.missing == 0. */
4008
for (i = 1; cache.missing; i++)
4009
if (!mael(cache.basis, i, i))
4010
{
4011
long j;
4012
cache.missing--; mael(cache.basis, i, i) = 1;
4013
for (j = i+1; j <= F.KC; j++) mael(cache.basis, j, i) = 0;
4014
}
4015
}
4016
zc = (lg(C)-1) - (lg(B)-1) - (lg(W)-1);
4017
if (RU-1-zc > 0) need = minss(need + RU-1-zc, F.KC); /* for units */
4018
if (need)
4019
{ /* dependent rows */
4020
F.L_jid = vecslice(F.perm, 1, need);
4021
vecsmall_sort(F.L_jid);
4022
if (need != old_need) { nreldep = 0; old_need = need; }
4023
}
4024
else
4025
{ /* If the relation lattice is too small, check will be > 1 and we will
4026
* do a new run of small_norm/rnd_rel asking for 1 relation. This often
4027
* gives a relation involving L_jid[1]. We rotate the first element of
4028
* L_jid in order to increase the probability of finding relations that
4029
* increases the lattice. */
4030
long j, n = lg(W) - 1;
4031
if (n > 1 && squash_index % n)
4032
{
4033
F.L_jid = leafcopy(F.perm);
4034
for (j = 1; j <= n; j++)
4035
F.L_jid[j] = F.perm[1 + (j + squash_index - 1) % n];
4036
}
4037
else
4038
F.L_jid = F.perm;
4039
squash_index++;
4040
}
4041
}
4042
while (need);
4043
4044
if (!A)
4045
{
4046
small_fail = old_need = 0;
4047
fail_limit = maxss(F.KC / FAIL_DIVISOR, MINFAIL);
4048
}
4049
A = vecslice(C, 1, zc); /* cols corresponding to units */
4050
if (flag) A = rowslice(A, 1, RU);
4051
Ar = real_i(A);
4052
R = compute_multiple_of_R(Ar, RU, N, &need, &bit, &lambda);
4053
if (need < old_need) small_fail = 0;
4054
#if 0 /* A good idea if we are indeed stuck but needs tuning */
4055
/* we have computed way more relations than should be necessary */
4056
if (TRIES < 3 && LIMC < LIMCMAX / 24 &&
4057
cache.last - cache.base > 10 * F.KC) goto START;
4058
#endif
4059
old_need = need;
4060
if (!lambda)
4061
{ precpb = "bestappr"; PREC = myprecdbl(PREC, flag? C: NULL); continue; }
4062
if (!R)
4063
{ /* not full rank for units */
4064
if (!need)
4065
{ precpb = "regulator"; PREC = myprecdbl(PREC, flag? C: NULL); }
4066
continue;
4067
}
4068
h = ZM_det_triangular(W);
4069
if (DEBUGLEVEL) err_printf("\n#### Tentative class number: %Ps\n", h);
4070
i = compute_R(lambda, mulir(h,invhr), &L, &R);
4071
if (DEBUGLEVEL)
4072
{
4073
err_printf("\n");
4074
timer_printf(&T, "computing regulator and check");
4075
}
4076
switch(i)
4077
{
4078
case fupb_RELAT:
4079
need = 1; /* not enough relations */
4080
continue;
4081
case fupb_PRECI: /* prec problem unless we cheat on Bach constant */
4082
if ((precdouble&7) == 7 && LIMC<=LIMCMAX/6) goto START;
4083
precpb = "compute_R"; PREC = myprecdbl(PREC, flag? C: NULL);
4084
continue;
4085
}
4086
/* DONE */
4087
4088
if (F.KCZ2 > F.KCZ)
4089
{
4090
if (F.sfb_chg && !subFB_change(&F)) goto START;
4091
if (!be_honest(&F, nf, auts, fact)) goto START;
4092
if (DEBUGLEVEL) timer_printf(&T, "to be honest");
4093
}
4094
F.KCZ2 = 0; /* be honest only once */
4095
4096
/* fundamental units */
4097
{
4098
GEN AU, CU, U, v = extract_full_lattice(L); /* L may be large */
4099
CU = NULL;
4100
if (v) { A = vecpermute(A, v); L = vecpermute(L, v); }
4101
/* arch. components of fund. units */
4102
U = ZM_lll(L, 0.99, LLL_IM);
4103
U = ZM_mul(U, lll(RgM_ZM_mul(real_i(A), U)));
4104
AU = RgM_ZM_mul(A, U);
4105
A = cleanarch(AU, N, PREC);
4106
if (DEBUGLEVEL) timer_printf(&T, "units LLL + cleanarch");
4107
if (!A || (lg(A) > 1 && gprecision(A) <= 2))
4108
{
4109
long add = nbits2extraprec( gexpo(AU) + 64 ) - gprecision(AU);
4110
precpb = "cleanarch"; PREC += maxss(add, 1); continue;
4111
}
4112
if (flag)
4113
{
4114
long l = lgcols(C) - RU;
4115
REL_t *rel;
4116
SUnits = cgetg(l, t_COL);
4117
for (rel = cache.base+1, i = 1; i < l; i++,rel++)
4118
set_rel_alpha(rel, auts, SUnits, i);
4119
if (RU > 1)
4120
{
4121
GEN c = v? vecpermute(C,v): vecslice(C,1,zc);
4122
CU = ZM_mul(rowslice(c, RU+1, nbrows(c)), U);
4123
}
4124
}
4125
if (DEBUGLEVEL) err_printf("\n#### Computing fundamental units\n");
4126
fu = getfu(nf, &A, CU? &U: NULL, PREC);
4127
CU = CU? ZM_mul(CU, U): cgetg(1, t_MAT);
4128
if (DEBUGLEVEL) timer_printf(&T, "getfu");
4129
Ce = vecslice(C, zc+1, lg(C)-1);
4130
if (flag) SUnits = mkvec4(SUnits, CU, rowslice(Ce, RU+1, nbrows(Ce)),
4131
utoipos(LIMC));
4132
}
4133
/* class group generators */
4134
if (flag) Ce = rowslice(Ce, 1, RU);
4135
C0 = Ce; Ce = cleanarch(Ce, N, PREC);
4136
if (!Ce) {
4137
long add = nbits2extraprec( gexpo(C0) + 64 ) - gprecision(C0);
4138
precpb = "cleanarch"; PREC += maxss(add, 1);
4139
}
4140
if (DEBUGLEVEL) timer_printf(&T, "cleanarch");
4141
} while (need || precpb);
4142
4143
Vbase = vecpermute(F.LP, F.perm);
4144
if (!fu) fu = cgetg(1, t_MAT);
4145
if (!SUnits) SUnits = gen_1;
4146
clg1 = class_group_gen(nf,W,Ce,Vbase,PREC, &clg2);
4147
res = mkvec5(clg1, R, SUnits, zu, fu);
4148
res = buchall_end(nf,res,clg2,W,B,A,Ce,Vbase);
4149
delete_FB(&F);
4150
res = gerepilecopy(av0, res);
4151
if (flag) obj_insert_shallow(res, MATAL, cgetg(1,t_VEC));
4152
if (nfisclone) gunclone(nf);
4153
delete_cache(&cache);
4154
free_GRHcheck(&GRHcheck);
4155
return res;
4156
}
4157
4158