Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

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

28495 views
License: GPL3
ubuntu2004
1
/* Copyright (C) 2000 The PARI group.
2
3
This file is part of the PARI/GP package.
4
5
PARI/GP is free software; you can redistribute it and/or modify it under the
6
terms of the GNU General Public License as published by the Free Software
7
Foundation; either version 2 of the License, or (at your option) any later
8
version. It is distributed in the hope that it will be useful, but WITHOUT
9
ANY WARRANTY WHATSOEVER.
10
11
Check the License for details. You should have received a copy of it, along
12
with the package; see the file 'COPYING'. If not, write to the Free Software
13
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14
15
/*******************************************************************/
16
/* */
17
/* COMPUTATION OF STARK UNITS OF TOTALLY REAL FIELDS */
18
/* */
19
/*******************************************************************/
20
#include "pari.h"
21
#include "paripriv.h"
22
23
#define DEBUGLEVEL DEBUGLEVEL_stark
24
25
/* ComputeCoeff */
26
typedef struct {
27
GEN L0, L1, L11, L2; /* VECSMALL of p */
28
GEN L1ray, L11ray; /* precomputed isprincipalray(pr), pr | p */
29
GEN rayZ; /* precomputed isprincipalray(i), i < condZ */
30
long condZ; /* generates cond(bnr) \cap Z, assumed small */
31
} LISTray;
32
33
/* Char evaluation */
34
typedef struct {
35
long ord;
36
GEN *val, chi;
37
} CHI_t;
38
39
/* RecCoeff */
40
typedef struct {
41
GEN M, beta, B, U, nB;
42
long v, G, N;
43
} RC_data;
44
45
/********************************************************************/
46
/* Miscellaneous functions */
47
/********************************************************************/
48
static GEN
49
chi_get_c(GEN chi) { return gmael(chi,1,2); }
50
static long
51
chi_get_deg(GEN chi) { return itou(gmael(chi,1,1)); }
52
53
/* Compute the image of logelt by character chi, zeta_ord(chi)^n; return n */
54
static ulong
55
CharEval_n(GEN chi, GEN logelt)
56
{
57
GEN gn = ZV_dotproduct(chi_get_c(chi), logelt);
58
return umodiu(gn, chi_get_deg(chi));
59
}
60
/* Compute the image of logelt by character chi, as a complex number */
61
static GEN
62
CharEval(GEN chi, GEN logelt)
63
{
64
ulong n = CharEval_n(chi, logelt), d = chi_get_deg(chi);
65
long nn = Fl_center(n,d,d>>1);
66
GEN x = gel(chi,2);
67
x = gpowgs(x, labs(nn));
68
if (nn < 0) x = conj_i(x);
69
return x;
70
}
71
72
/* return n such that C(elt) = z^n */
73
static ulong
74
CHI_eval_n(CHI_t *C, GEN logelt)
75
{
76
GEN n = ZV_dotproduct(C->chi, logelt);
77
return umodiu(n, C->ord);
78
}
79
/* return C(elt) */
80
static GEN
81
CHI_eval(CHI_t *C, GEN logelt)
82
{
83
return C->val[CHI_eval_n(C, logelt)];
84
}
85
86
static void
87
init_CHI(CHI_t *c, GEN CHI, GEN z)
88
{
89
long i, d = chi_get_deg(CHI);
90
GEN *v = (GEN*)new_chunk(d);
91
v[0] = gen_1;
92
if (d != 1)
93
{
94
v[1] = z;
95
for (i=2; i<d; i++) v[i] = gmul(v[i-1], z);
96
}
97
c->chi = chi_get_c(CHI);
98
c->ord = d;
99
c->val = v;
100
}
101
/* as t_POLMOD */
102
static void
103
init_CHI_alg(CHI_t *c, GEN CHI) {
104
long d = chi_get_deg(CHI);
105
GEN z;
106
switch(d)
107
{
108
case 1: z = gen_1; break;
109
case 2: z = gen_m1; break;
110
default: z = mkpolmod(pol_x(0), polcyclo(d,0));
111
}
112
init_CHI(c,CHI, z);
113
}
114
/* as t_COMPLEX */
115
static void
116
init_CHI_C(CHI_t *c, GEN CHI) {
117
init_CHI(c,CHI, gel(CHI,2));
118
}
119
120
typedef struct {
121
long r; /* rank = lg(gen) */
122
GEN j; /* current elt is gen[1]^j[1] ... gen[r]^j[r] */
123
GEN cyc; /* t_VECSMALL of elementary divisors */
124
} GROUP_t;
125
126
static int
127
NextElt(GROUP_t *G)
128
{
129
long i = 1;
130
if (G->r == 0) return 0; /* no more elt */
131
while (++G->j[i] == G->cyc[i]) /* from 0 to cyc[i]-1 */
132
{
133
G->j[i] = 0;
134
if (++i > G->r) return 0; /* no more elt */
135
}
136
return i; /* we have multiplied by gen[i] */
137
}
138
139
/* enumerate all group elements; trivial elt comes last */
140
GEN
141
cyc2elts(GEN cyc)
142
{
143
long i, n;
144
GEN z;
145
GROUP_t G;
146
147
G.cyc = typ(cyc)==t_VECSMALL? cyc: gtovecsmall(cyc);
148
n = zv_prod(G.cyc);
149
G.r = lg(cyc)-1;
150
G.j = zero_zv(G.r);
151
152
z = cgetg(n+1, t_VEC);
153
gel(z,n) = leafcopy(G.j); /* trivial elt comes last */
154
for (i = 1; i < n; i++)
155
{
156
(void)NextElt(&G);
157
gel(z,i) = leafcopy(G.j);
158
}
159
return z;
160
}
161
162
/* nchi: a character given by a vector [d, (c_i)], e.g. from char_normalize
163
* such that chi(x) = e((c . log(x)) / d) where log(x) on bnr.gen */
164
static GEN
165
get_Char(GEN nchi, long prec)
166
{ return mkvec2(nchi, rootsof1_cx(gel(nchi,1), prec)); }
167
168
/* prime divisors of conductor */
169
static GEN
170
divcond(GEN bnr) {GEN bid = bnr_get_bid(bnr); return gel(bid_get_fact(bid),1);}
171
172
/* vector of prime ideals dividing bnr but not bnrc */
173
static GEN
174
get_prdiff(GEN D, GEN Dc)
175
{
176
long n, i, l = lg(D);
177
GEN diff = cgetg(l, t_COL);
178
for (n = i = 1; i < l; i++)
179
if (!tablesearch(Dc, gel(D,i), &cmp_prime_ideal)) gel(diff,n++) = gel(D,i);
180
setlg(diff, n); return diff;
181
}
182
183
#define ch_prec(x) realprec(gel(x,1))
184
#define ch_C(x) gel(x,1)
185
#define ch_bnr(x) gel(x,2)
186
#define ch_3(x) gel(x,3)
187
#define ch_q(x) gel(x,3)[1]
188
#define ch_CHI(x) gel(x,4)
189
#define ch_diff(x) gel(x,5)
190
#define ch_CHI0(x) gel(x,6)
191
#define ch_small(x) gel(x,7)
192
#define ch_comp(x) gel(x,7)[1]
193
#define ch_phideg(x) gel(x,7)[2]
194
static long
195
ch_deg(GEN dtcr) { return chi_get_deg(ch_CHI(dtcr)); }
196
197
/********************************************************************/
198
/* 1rst part: find the field K */
199
/********************************************************************/
200
static GEN AllStark(GEN data, long flag, long prec);
201
202
/* Columns of C [HNF] give the generators of a subgroup of the finite abelian
203
* group A [ in terms of implicit generators ], compute data to work in A/C:
204
* 1) order
205
* 2) structure
206
* 3) the matrix A ->> A/C
207
* 4) the subgroup C */
208
static GEN
209
InitQuotient(GEN C)
210
{
211
GEN U, D = ZM_snfall_i(C, &U, NULL, 1), h = ZV_prod(D);
212
return mkvec5(h, D, U, C, cyc_normalize(D));
213
}
214
215
/* lift chi character on A/C [Qt from InitQuotient] to character on A [cyc]*/
216
static GEN
217
LiftChar(GEN Qt, GEN cyc, GEN chi)
218
{
219
GEN ncyc = gel(Qt,5), U = gel(Qt,3), nchi = char_normalize(chi, ncyc);
220
GEN c = ZV_ZM_mul(gel(nchi,2), U), d = gel(nchi,1);
221
return char_denormalize(cyc, d, c);
222
}
223
224
/* Let C be a subgroup, system of representatives of the quotient */
225
static GEN
226
ag_subgroup_classes(GEN C)
227
{
228
GEN U, D = ZM_snfall_i(C, &U, NULL, 1), e = cyc2elts(D);
229
long i, l = lg(e);
230
231
if (ZM_isidentity(U))
232
for (i = 1; i < l; i++) (void)vecsmall_to_vec_inplace(gel(e,i));
233
else
234
{
235
GEN Ui = ZM_inv(U,NULL);
236
for (i = 1; i < l; i++) gel(e,i) = ZM_zc_mul(Ui, gel(e,i));
237
}
238
return e;
239
}
240
241
/* Let s: A -> B given by [P,cycA,cycB] A and B, compute the kernel of s. */
242
GEN
243
ag_kernel(GEN S)
244
{
245
GEN U, P = gel(S,1), cycA = gel(S,2), DB = diagonal_shallow(gel(S,3));
246
long nA = lg(cycA)-1, rk;
247
248
rk = nA + lg(DB) - lg(ZM_hnfall_i(shallowconcat(P, DB), &U, 1));
249
return ZM_hnfmodid(matslice(U, 1,nA, 1,rk), cycA);
250
}
251
/* let H be a subgroup of A; return s(H) */
252
GEN
253
ag_subgroup_image(GEN S, GEN H)
254
{ return ZM_hnfmodid(ZM_mul(gel(S,1), H), gel(S,3)); }
255
256
/* Let m and n be two moduli such that n|m and let C be a congruence
257
group modulo n, compute the corresponding congruence group modulo m
258
ie the kernel of the map Clk(m) ->> Clk(n)/C */
259
static GEN
260
ComputeKernel(GEN bnrm, GEN bnrn, GEN dtQ)
261
{
262
pari_sp av = avma;
263
GEN S = bnrsurjection(bnrm, bnrn);
264
GEN P = ZM_mul(gel(dtQ,3), gel(S,1));
265
return gerepileupto(av, ag_kernel(mkvec3(P, gel(S,2), gel(dtQ,2))));
266
}
267
268
static long
269
cyc_is_cyclic(GEN cyc) { return lg(cyc) <= 2 || equali1(gel(cyc,2)); }
270
271
/* Let H be a subgroup of cl(bnr)/sugbroup, return 1 if
272
cl(bnr)/subgoup/H is cyclic and the signature of the
273
corresponding field is equal to sig and no finite prime
274
dividing cond(bnr) is totally split in this field. Return 0
275
otherwise. */
276
static long
277
IsGoodSubgroup(GEN H, GEN bnr, GEN map)
278
{
279
pari_sp av = avma;
280
GEN S, mod, modH, p1, U, P, PH, bnrH, iH, qH;
281
long j;
282
283
p1 = InitQuotient(H);
284
/* quotient is non cyclic */
285
if (!cyc_is_cyclic(gel(p1,2))) return gc_long(av,0);
286
287
(void)ZM_hnfall_i(shallowconcat(map,H), &U, 0);
288
setlg(U, lg(H));
289
for (j = 1; j < lg(U); j++) setlg(gel(U,j), lg(H));
290
p1 = ZM_hnfmodid(U, bnr_get_cyc(bnr)); /* H as a subgroup of bnr */
291
modH = bnrconductor_raw(bnr, p1);
292
mod = bnr_get_mod(bnr);
293
294
/* is the signature correct? */
295
if (!gequal(gel(modH,2), gel(mod,2))) return gc_long(av, 0);
296
297
/* finite part are the same: OK */
298
if (gequal(gel(modH,1), gel(mod,1))) return gc_long(av, 1);
299
300
/* need to check the splitting of primes dividing mod but not modH */
301
bnrH = Buchray(bnr, modH, nf_INIT);
302
P = divcond(bnr);
303
PH = divcond(bnrH);
304
S = bnrsurjection(bnr, bnrH);
305
/* H as a subgroup of bnrH */
306
iH = ag_subgroup_image(S, p1);
307
qH = InitQuotient(iH);
308
for (j = 1; j < lg(P); j++)
309
{
310
GEN pr = gel(P, j), e;
311
/* if pr divides modH, it is ramified, so it's good */
312
if (tablesearch(PH, pr, cmp_prime_ideal)) continue;
313
/* inertia degree of pr in bnr(modH)/H is charorder(e, cycH) */
314
e = ZM_ZC_mul(gel(qH,3), isprincipalray(bnrH, pr));
315
e = vecmodii(e, gel(qH,2));
316
if (ZV_equal0(e)) return gc_long(av,0); /* f = 1 */
317
}
318
return gc_long(av,1);
319
}
320
321
/* compute list of nontrivial characters trivial on H, modulo complex
322
* conjugation. If flag is set, impose a nontrivial conductor at infinity */
323
static GEN
324
AllChars(GEN bnr, GEN dtQ, long flag)
325
{
326
GEN v, vchi, cyc = bnr_get_cyc(bnr);
327
long n, i, hD = itos(gel(dtQ,1));
328
hashtable *S;
329
330
v = cgetg(hD+1, t_VEC); /* nonconjugate chars */
331
vchi = cyc2elts(gel(dtQ,2));
332
S = hash_create(hD, (ulong(*)(void*))&hash_GEN,
333
(int(*)(void*,void*))&ZV_equal, 1);
334
for (i = n = 1; i < hD; i++) /* remove i = hD: trivial char */
335
{ /* lift a character of D in Clk(m) */
336
GEN F, lchi = LiftChar(dtQ, cyc, zv_to_ZV(gel(vchi,i))), cchi = NULL;
337
338
if (hash_search(S, lchi)) continue;
339
F = bnrconductor_raw(bnr, lchi);
340
if (flag && gequal0(gel(F,2))) continue; /* f_oo(chi) trivial ? */
341
342
if (abscmpiu(charorder(cyc,lchi), 2) > 0)
343
{ /* nonreal chi: add its conjugate character to S */
344
cchi = charconj(cyc, lchi);
345
hash_insert(S, cchi, (void*)1);
346
}
347
gel(v, n++) = cchi? mkvec3(lchi, F, cchi): mkvec2(lchi, F);
348
}
349
setlg(v, n); return v;
350
}
351
352
static GEN InitChar(GEN bnr, GEN CR, long flag, long prec);
353
static void CharNewPrec(GEN data, long prec);
354
355
/* Given a conductor and a subgroups, return the corresponding complexity and
356
* precision required using quickpol. Fill data[5] with dataCR */
357
static long
358
CplxModulus(GEN data, long *newprec)
359
{
360
long dprec = DEFAULTPREC;
361
pari_sp av = avma;
362
for (;;)
363
{
364
GEN cpl, pol = AllStark(data, -1, dprec);
365
cpl = RgX_fpnorml2(pol, LOWDEFAULTPREC);
366
dprec = maxss(dprec, nbits2extraprec(gexpo(pol))) + EXTRAPREC64;
367
if (!gequal0(cpl)) { *newprec = dprec; return gexpo(cpl); }
368
set_avma(av);
369
if (DEBUGLEVEL>1) pari_warn(warnprec, "CplxModulus", dprec);
370
CharNewPrec(data, dprec);
371
}
372
}
373
374
/* return A \cap B in abelian group defined by cyc. NULL = whole group */
375
static GEN
376
subgp_intersect(GEN cyc, GEN A, GEN B)
377
{
378
GEN H, U;
379
long k, lH;
380
if (!A) return B;
381
if (!B) return A;
382
H = ZM_hnfall_i(shallowconcat(A,B), &U, 1);
383
setlg(U, lg(A)); lH = lg(H);
384
for (k = 1; k < lg(U); k++) setlg(gel(U,k), lH);
385
return ZM_hnfmodid(ZM_mul(A,U), cyc);
386
}
387
388
static void CharNewPrec(GEN dataCR, long prec);
389
/* Let (f,C) be a conductor without infinite part and a congruence group mod f.
390
* Compute (m,D) such that D is a congruence group of conductor m, f | m,
391
* divisible by all the infinite places but one, D is a subgroup of index 2 of
392
* Cm = Ker: Clk(m) -> Clk(f)/C. Consider further the subgroups H of Clk(m)/D
393
* with cyclic quotient Clk(m)/H such that no place dividing m is totally split
394
* in the extension KH corresponding to H: we want their intersection to be
395
* trivial. These H correspond to (the kernels of Galois orbits of) characters
396
* chi of Clk(m)/D such that chi(log_gen_arch(m_oo)) != 1 and for all pr | m
397
* we either have
398
* - chi(log_gen_pr(pr,1)) != 1 [pr | cond(chi) => ramified in KH]
399
* - or [pr \nmid cond(chi)] chi lifted to Clk(m/pr^oo) is not trivial at pr.
400
* We want the map from Clk(m)/D given by the vector of such caracters to have
401
* trivial kernel. Return bnr(m), D, Ck(m)/D and Clk(m)/Cm */
402
static GEN
403
FindModulus(GEN bnr, GEN dtQ, long *newprec)
404
{
405
const long LIMNORM = 400;
406
long n, i, maxnorm, minnorm, N, pr, rb, iscyc, olde = LONG_MAX;
407
pari_sp av = avma;
408
GEN bnf, nf, f, varch, m, rep = NULL;
409
410
bnf = bnr_get_bnf(bnr);
411
nf = bnf_get_nf(bnf);
412
N = nf_get_degree(nf);
413
f = gel(bnr_get_mod(bnr), 1);
414
415
/* if cpl < rb, it is not necessary to try another modulus */
416
rb = expi( powii(mulii(nf_get_disc(nf), ZM_det_triangular(f)),
417
gmul2n(bnr_get_no(bnr), 3)) );
418
419
/* Initialization of the possible infinite part */
420
varch = cgetg(N+1,t_VEC);
421
for (i = 1; i <= N; i++)
422
{
423
GEN a = const_vec(N,gen_1);
424
gel(a, N+1-i) = gen_0;
425
gel(varch, i) = a;
426
}
427
m = cgetg(3, t_VEC);
428
429
/* Go from minnorm up to maxnorm; if necessary, increase these values.
430
* If the extension is cyclic then a suitable conductor exists and we go on
431
* until we find it. Else, stop at norm LIMNORM. */
432
minnorm = 1;
433
maxnorm = 50;
434
iscyc = cyc_is_cyclic(gel(dtQ,2));
435
436
if (DEBUGLEVEL>1)
437
err_printf("Looking for a modulus of norm: ");
438
439
for(;;)
440
{
441
GEN listid = ideallist0(nf, maxnorm, 4+8); /* ideals of norm <= maxnorm */
442
pari_sp av1 = avma;
443
for (n = minnorm; n <= maxnorm; n++, set_avma(av1))
444
{
445
GEN idnormn = gel(listid,n);
446
long nbidnn = lg(idnormn) - 1;
447
if (DEBUGLEVEL>1) err_printf(" %ld", n);
448
for (i = 1; i <= nbidnn; i++)
449
{ /* finite part of the conductor */
450
long s;
451
452
gel(m,1) = idealmul(nf, f, gel(idnormn,i));
453
for (s = 1; s <= N; s++)
454
{ /* infinite part */
455
GEN candD, Cm, bnrm;
456
long lD, c;
457
458
gel(m,2) = gel(varch,s);
459
/* compute Clk(m), check if m is a conductor */
460
bnrm = Buchray(bnf, m, nf_INIT);
461
if (!bnrisconductor(bnrm, NULL)) continue;
462
463
/* compute Im(C) in Clk(m)... */
464
Cm = ComputeKernel(bnrm, bnr, dtQ);
465
/* ... and its subgroups of index 2 with conductor m */
466
candD = subgrouplist_cond_sub(bnrm, Cm, mkvec(gen_2));
467
lD = lg(candD);
468
for (c = 1; c < lD; c++)
469
{
470
GEN data, CR, D = gel(candD,c), QD = InitQuotient(D);
471
GEN ord = gel(QD,1), cyc = gel(QD,2), map = gel(QD,3);
472
long e;
473
474
if (!cyc_is_cyclic(cyc)) /* cyclic => suitable, else test */
475
{
476
GEN lH = subgrouplist(cyc, NULL), IK = NULL;
477
long j, ok = 0;
478
for (j = 1; j < lg(lH); j++)
479
{
480
GEN H = gel(lH, j), IH = subgp_intersect(cyc, IK, H);
481
/* if H > IK, no need to test H */
482
if (IK && gidentical(IH, IK)) continue;
483
if (IsGoodSubgroup(H, bnrm, map))
484
{
485
IK = IH; /* intersection of all good subgroups */
486
if (equalii(ord, ZM_det_triangular(IK))) { ok = 1; break; }
487
}
488
}
489
if (!ok) continue;
490
}
491
CR = InitChar(bnrm, AllChars(bnrm, QD, 1), 0, DEFAULTPREC);
492
data = mkvec4(bnrm, D, ag_subgroup_classes(Cm), CR);
493
if (DEBUGLEVEL>1)
494
err_printf("\nTrying modulus = %Ps and subgroup = %Ps\n",
495
bnr_get_mod(bnrm), D);
496
e = CplxModulus(data, &pr);
497
if (DEBUGLEVEL>1) err_printf("cpl = 2^%ld\n", e);
498
if (e < olde)
499
{
500
guncloneNULL(rep); rep = gclone(data);
501
*newprec = pr; olde = e;
502
}
503
if (olde < rb) goto END; /* OK */
504
if (DEBUGLEVEL>1) err_printf("Trying to find another modulus...");
505
}
506
}
507
if (rep) goto END; /* OK */
508
}
509
}
510
/* if necessary compute more ideals */
511
minnorm = maxnorm;
512
maxnorm <<= 1;
513
if (!iscyc && maxnorm > LIMNORM) return NULL;
514
}
515
END:
516
if (DEBUGLEVEL>1)
517
err_printf("No, we're done!\nModulus = %Ps and subgroup = %Ps\n",
518
bnr_get_mod(gel(rep,1)), gel(rep,2));
519
CharNewPrec(rep, *newprec); return gerepilecopy(av, rep);
520
}
521
522
/********************************************************************/
523
/* 2nd part: compute W(X) */
524
/********************************************************************/
525
526
/* find ilambda s.t. Diff*f*ilambda integral and coprime to f
527
and ilambda >> 0 at foo, fa = factorization of f */
528
static GEN
529
get_ilambda(GEN nf, GEN fa, GEN foo)
530
{
531
GEN x, w, E2, P = gel(fa,1), E = gel(fa,2), D = nf_get_diff(nf);
532
long i, l = lg(P);
533
if (l == 1) return gen_1;
534
w = cgetg(l, t_VEC);
535
E2 = cgetg(l, t_COL);
536
for (i = 1; i < l; i++)
537
{
538
GEN pr = gel(P,i), t = pr_get_tau(pr);
539
long e = itou(gel(E,i)), v = idealval(nf, D, pr);
540
if (v) { D = idealdivpowprime(nf, D, pr, utoipos(v)); e += v; }
541
gel(E2,i) = stoi(e+1);
542
if (typ(t) == t_MAT) t = gel(t,1);
543
gel(w,i) = gdiv(nfpow(nf, t, stoi(e)), powiu(pr_get_p(pr),e));
544
}
545
x = mkmat2(P, E2);
546
return idealchinese(nf, mkvec2(x, foo), w);
547
}
548
/* compute the list of W(chi) such that Ld(s,chi) = W(chi) Ld(1 - s, chi*),
549
* for all chi in LCHI. All chi have the same conductor (= cond(bnr)). */
550
static GEN
551
ArtinNumber(GEN bnr, GEN LCHI, long prec)
552
{
553
long ic, i, j, nz, nChar = lg(LCHI)-1;
554
pari_sp av2;
555
GEN sqrtnc, cond, condZ, cond0, cond1, nf, T, cyc, vN, vB, diff, vt, idh;
556
GEN zid, gen, z, nchi, indW, W, classe, s0, s, den, ilambda, sarch;
557
CHI_t **lC;
558
GROUP_t G;
559
560
lC = (CHI_t**)new_chunk(nChar + 1);
561
indW = cgetg(nChar + 1, t_VECSMALL);
562
W = cgetg(nChar + 1, t_VEC);
563
for (ic = 0, i = 1; i <= nChar; i++)
564
{
565
GEN CHI = gel(LCHI,i);
566
if (chi_get_deg(CHI) <= 2) { gel(W,i) = gen_1; continue; }
567
ic++; indW[ic] = i;
568
lC[ic] = (CHI_t*)new_chunk(sizeof(CHI_t));
569
init_CHI_C(lC[ic], CHI);
570
}
571
if (!ic) return W;
572
nChar = ic;
573
574
nf = bnr_get_nf(bnr);
575
diff = nf_get_diff(nf);
576
T = nf_get_Tr(nf);
577
cond = bnr_get_mod(bnr);
578
cond0 = gel(cond,1); condZ = gcoeff(cond0,1,1);
579
cond1 = gel(cond,2);
580
581
sqrtnc = gsqrt(idealnorm(nf, cond0), prec);
582
ilambda = get_ilambda(nf, bid_get_fact(bnr_get_bid(bnr)), cond1);
583
idh = idealmul(nf, ilambda, idealmul(nf, diff, cond0)); /* integral */
584
ilambda = Q_remove_denom(ilambda, &den);
585
z = den? rootsof1_cx(den, prec): NULL;
586
587
/* compute a system of generators of (Ok/cond)^*, we'll make them
588
* cond1-positive in the main loop */
589
zid = Idealstar(nf, cond0, nf_GEN);
590
cyc = abgrp_get_cyc(zid);
591
gen = abgrp_get_gen(zid);
592
nz = lg(gen) - 1;
593
sarch = nfarchstar(nf, cond0, vec01_to_indices(cond1));
594
595
nchi = cgetg(nChar+1, t_VEC);
596
for (ic = 1; ic <= nChar; ic++) gel(nchi,ic) = cgetg(nz + 1, t_VECSMALL);
597
for (i = 1; i <= nz; i++)
598
{
599
if (is_bigint(gel(cyc,i)))
600
pari_err_OVERFLOW("ArtinNumber [conductor too large]");
601
gel(gen,i) = set_sign_mod_divisor(nf, NULL, gel(gen,i), sarch);
602
classe = isprincipalray(bnr, gel(gen,i));
603
for (ic = 1; ic <= nChar; ic++) {
604
GEN n = gel(nchi,ic);
605
n[i] = CHI_eval_n(lC[ic], classe);
606
}
607
}
608
609
/* Sum chi(beta) * exp(2i * Pi * Tr(beta * ilambda) where beta
610
runs through the classes of (Ok/cond0)^* and beta cond1-positive */
611
vt = gel(T,1); /* ( Tr(w_i) )_i */
612
if (typ(ilambda) == t_COL)
613
vt = ZV_ZM_mul(vt, zk_multable(nf, ilambda));
614
else
615
vt = ZC_Z_mul(vt, ilambda);
616
/*vt = den . (Tr(w_i * ilambda))_i */
617
G.cyc = gtovecsmall(cyc);
618
G.r = nz;
619
G.j = zero_zv(nz);
620
vN = zero_Flm_copy(nz, nChar);
621
622
av2 = avma;
623
vB = const_vec(nz, gen_1);
624
s0 = z? powgi(z, modii(gel(vt,1), den)): gen_1; /* for beta = 1 */
625
s = const_vec(nChar, s0);
626
627
while ( (i = NextElt(&G)) )
628
{
629
GEN b = gel(vB,i);
630
b = nfmuli(nf, b, gel(gen,i));
631
b = typ(b) == t_COL? FpC_red(b, condZ): modii(b, condZ);
632
for (j=1; j<=i; j++) gel(vB,j) = b;
633
634
for (ic = 1; ic <= nChar; ic++)
635
{
636
GEN v = gel(vN,ic), n = gel(nchi,ic);
637
v[i] = Fl_add(v[i], n[i], lC[ic]->ord);
638
for (j=1; j<i; j++) v[j] = v[i];
639
}
640
641
gel(vB,i) = b = set_sign_mod_divisor(nf, NULL, b, sarch);
642
if (!z)
643
s0 = gen_1;
644
else
645
{
646
b = typ(b) == t_COL? ZV_dotproduct(vt, b): mulii(gel(vt,1),b);
647
s0 = powgi(z, modii(b,den));
648
}
649
for (ic = 1; ic <= nChar; ic++)
650
{
651
GEN v = gel(vN,ic), val = lC[ic]->val[ v[i] ];
652
gel(s,ic) = gadd(gel(s,ic), gmul(val, s0));
653
}
654
655
if (gc_needed(av2, 1))
656
{
657
if (DEBUGMEM > 1) pari_warn(warnmem,"ArtinNumber");
658
gerepileall(av2, 2, &s, &vB);
659
}
660
}
661
662
classe = isprincipalray(bnr, idh);
663
z = powIs(- (lg(gel(sarch,1))-1));
664
665
for (ic = 1; ic <= nChar; ic++)
666
{
667
s0 = gmul(gel(s,ic), CHI_eval(lC[ic], classe));
668
gel(W, indW[ic]) = gmul(gdiv(s0, sqrtnc), z);
669
}
670
return W;
671
}
672
673
static GEN
674
AllArtinNumbers(GEN CR, long prec)
675
{
676
pari_sp av = avma;
677
GEN vChar = gel(CR,1), dataCR = gel(CR,2);
678
long j, k, cl = lg(dataCR) - 1, J = lg(vChar)-1;
679
GEN W = cgetg(cl+1,t_VEC), WbyCond, LCHI;
680
681
for (j = 1; j <= J; j++)
682
{
683
GEN LChar = gel(vChar,j), ldata = vecpermute(dataCR, LChar);
684
GEN dtcr = gel(ldata,1), bnr = ch_bnr(dtcr);
685
long l = lg(LChar);
686
687
if (DEBUGLEVEL>1)
688
err_printf("* Root Number: cond. no %ld/%ld (%ld chars)\n", j, J, l-1);
689
LCHI = cgetg(l, t_VEC);
690
for (k = 1; k < l; k++) gel(LCHI,k) = ch_CHI0(gel(ldata,k));
691
WbyCond = ArtinNumber(bnr, LCHI, prec);
692
for (k = 1; k < l; k++) gel(W,LChar[k]) = gel(WbyCond,k);
693
}
694
return gerepilecopy(av, W);
695
}
696
697
/* compute the constant W of the functional equation of
698
Lambda(chi). If flag = 1 then chi is assumed to be primitive */
699
GEN
700
bnrrootnumber(GEN bnr, GEN chi, long flag, long prec)
701
{
702
pari_sp av = avma;
703
GEN cyc, W;
704
705
if (flag < 0 || flag > 1) pari_err_FLAG("bnrrootnumber");
706
checkbnr(bnr);
707
if (flag)
708
{
709
cyc = bnr_get_cyc(bnr);
710
if (!char_check(cyc,chi)) pari_err_TYPE("bnrrootnumber [character]", chi);
711
}
712
else
713
{
714
bnr_char_sanitize(&bnr, &chi);
715
cyc = bnr_get_cyc(bnr);
716
}
717
chi = char_normalize(chi, cyc_normalize(cyc));
718
chi = get_Char(chi, prec);
719
W = ArtinNumber(bnr, mkvec(chi), prec);
720
return gerepilecopy(av, gel(W,1));
721
}
722
723
/********************************************************************/
724
/* 3rd part: initialize the characters */
725
/********************************************************************/
726
727
/* Let chi be a character, A(chi) corresponding to the primes dividing diff
728
* at s = flag. If s = 0, returns [r, A] where r is the order of vanishing
729
* at s = 0 corresponding to diff. */
730
static GEN
731
AChi(GEN dtcr, long *r, long flag, long prec)
732
{
733
GEN A, diff = ch_diff(dtcr), bnrc = ch_bnr(dtcr), chi = ch_CHI0(dtcr);
734
long i, l = lg(diff);
735
736
A = gen_1; *r = 0;
737
for (i = 1; i < l; i++)
738
{
739
GEN B, pr = gel(diff,i), z = CharEval(chi, isprincipalray(bnrc, pr));
740
if (flag)
741
B = gsubsg(1, gdiv(z, pr_norm(pr)));
742
else if (gequal1(z))
743
{
744
B = glog(pr_norm(pr), prec);
745
(*r)++;
746
}
747
else
748
B = gsubsg(1, z);
749
A = gmul(A, B);
750
}
751
return A;
752
}
753
/* simplified version of Achi: return 1 if L(0,chi) = 0 */
754
static int
755
L_vanishes_at_0(GEN D)
756
{
757
GEN diff = ch_diff(D), bnrc = ch_bnr(D), chi = ch_CHI0(D);
758
long i, l = lg(diff);
759
for (i = 1; i < l; i++)
760
{
761
GEN pr = gel(diff,i);
762
if (!CharEval_n(chi, isprincipalray(bnrc, pr))) return 1;
763
}
764
return 0;
765
}
766
767
static GEN
768
_data3(GEN arch, long r2)
769
{
770
GEN z = cgetg(4, t_VECSMALL);
771
long i, r1 = lg(arch) - 1, q = 0;
772
for (i = 1; i <= r1; i++) if (signe(gel(arch,i))) q++;
773
z[1] = q;
774
z[2] = r1 - q;
775
z[3] = r2; return z;
776
}
777
static void
778
ch_get3(GEN dtcr, long *a, long *b, long *c)
779
{ GEN v = ch_3(dtcr); *a = v[1]; *b = v[2]; *c = v[3]; }
780
static GEN
781
get_C(GEN nf, long prec)
782
{
783
long r2 = nf_get_r2(nf), N = nf_get_degree(nf);
784
return gmul2n(sqrtr_abs(divir(nf_get_disc(nf), powru(mppi(prec),N))), -r2);
785
}
786
/* sort chars according to conductor */
787
static GEN
788
sortChars(GEN ch)
789
{
790
long j, l = lg(ch);
791
GEN F = cgetg(l, t_VEC);
792
for (j = 1; j < l; j++) gel(F, j) = gmael(ch,j,2);
793
return vec_equiv(F);
794
}
795
796
/* Given a list [chi, F = cond(chi)] of characters over Cl(bnr), return
797
* [vChar, dataCR], where vChar containes the equivalence classes of
798
* characters with the same conductor, and dataCR contains for each character:
799
* - bnr(F)
800
* - the constant C(F) [t_REAL]
801
* - [q, r1 - q, r2, rc] where
802
* q = number of real places in F
803
* rc = max{r1 + r2 - q + 1, r2 + q}
804
* - diff(chi) primes dividing m but not F
805
* - chi in bnr(m)
806
* - chi in bnr(F).
807
* If all is unset, only compute characters s.t. L(chi,0) != 0 */
808
static GEN
809
InitChar(GEN bnr, GEN ch, long all, long prec)
810
{
811
GEN bnf = checkbnf(bnr), nf = bnf_get_nf(bnf), mod = bnr_get_mod(bnr);
812
GEN C, dataCR, ncyc, vChar = sortChars(ch);
813
long n, l, r2 = nf_get_r2(nf), prec2 = precdbl(prec) + EXTRAPREC64;
814
long lv = lg(vChar);
815
816
C = get_C(nf, prec2);
817
ncyc = cyc_normalize(bnr_get_cyc(bnr));
818
819
dataCR = cgetg_copy(ch, &l);
820
for (n = 1; n < lv; n++)
821
{
822
GEN D, bnrc, v = gel(vChar, n); /* indices of chars of given conductor */
823
long a, i = v[1], lc = lg(v);
824
GEN F = gmael(ch,i,2);
825
826
gel(dataCR, i) = D = cgetg(8, t_VEC);
827
ch_C(D) = mulrr(C, gsqrt(ZM_det_triangular(gel(F,1)), prec2));
828
ch_3(D) = _data3(gel(F,2), r2);
829
if (gequal(F, mod))
830
{
831
ch_bnr(D) = bnrc = bnr;
832
ch_diff(D) = cgetg(1, t_VEC);
833
}
834
else
835
{
836
ch_bnr(D) = bnrc = Buchray(bnf, F, nf_INIT);
837
ch_diff(D) = get_prdiff(divcond(bnr), divcond(bnrc));
838
}
839
for (a = 1; a < lc; a++)
840
{
841
long i = v[a];
842
GEN chi = gmael(ch,i,1);
843
844
if (a > 1) gel(dataCR, i) = D = leafcopy(D);
845
chi = char_normalize(chi,ncyc);
846
ch_CHI(D) = get_Char(chi, prec2);
847
if (bnrc == bnr)
848
ch_CHI0(D) = ch_CHI(D);
849
else
850
{
851
chi = bnrchar_primitive(bnr, chi, bnrc);
852
ch_CHI0(D) = get_Char(chi, prec2);
853
}
854
/* set last */
855
ch_small(D) = mkvecsmall2(all || !L_vanishes_at_0(D),
856
eulerphiu(itou(gel(chi,1))));
857
}
858
}
859
return mkvec2(vChar, dataCR);
860
}
861
862
/* recompute dataCR with the new precision, modify bnr components in place */
863
static void
864
CharNewPrec(GEN data, long prec)
865
{
866
long j, l, prec2 = precdbl(prec) + EXTRAPREC64;
867
GEN C, nf, dataCR = gmael(data,4,2), D = gel(dataCR,1);
868
869
if (ch_prec(D) >= prec2) return;
870
nf = bnr_get_nf(ch_bnr(D));
871
if (nf_get_prec(nf) < prec) nf = nfnewprec_shallow(nf, prec); /* not prec2 */
872
C = get_C(nf, prec2); l = lg(dataCR);
873
for (j = 1; j < l; j++)
874
{
875
GEN f0;
876
D = gel(dataCR,j); f0 = gel(bnr_get_mod(ch_bnr(D)), 1);
877
ch_C(D) = mulrr(C, gsqrt(ZM_det_triangular(f0), prec2));
878
gmael(ch_bnr(D), 1, 7) = nf;
879
ch_CHI(D) = get_Char(gel(ch_CHI(D),1), prec2);
880
ch_CHI0(D)= get_Char(gel(ch_CHI0(D),1), prec2);
881
}
882
}
883
884
/********************************************************************/
885
/* 4th part: compute the coefficients an(chi) */
886
/* */
887
/* matan entries are arrays of ints containing the coefficients of */
888
/* an(chi) as a polmod modulo polcyclo(order(chi)) */
889
/********************************************************************/
890
891
static void
892
_0toCoeff(int *rep, long deg)
893
{
894
long i;
895
for (i=0; i<deg; i++) rep[i] = 0;
896
}
897
898
/* transform a polmod into Coeff */
899
static void
900
Polmod2Coeff(int *rep, GEN polmod, long deg)
901
{
902
long i;
903
if (typ(polmod) == t_POLMOD)
904
{
905
GEN pol = gel(polmod,2);
906
long d = degpol(pol);
907
908
pol += 2;
909
for (i=0; i<=d; i++) rep[i] = itos(gel(pol,i));
910
for ( ; i<deg; i++) rep[i] = 0;
911
}
912
else
913
{
914
rep[0] = itos(polmod);
915
for (i=1; i<deg; i++) rep[i] = 0;
916
}
917
}
918
919
/* initialize a deg * n matrix of ints */
920
static int**
921
InitMatAn(long n, long deg, long flag)
922
{
923
long i, j;
924
int *a, **A = (int**)pari_malloc((n+1)*sizeof(int*));
925
A[0] = NULL;
926
for (i = 1; i <= n; i++)
927
{
928
a = (int*)pari_malloc(deg*sizeof(int));
929
A[i] = a; a[0] = (i == 1 || flag);
930
for (j = 1; j < deg; j++) a[j] = 0;
931
}
932
return A;
933
}
934
935
static void
936
FreeMat(int **A, long n)
937
{
938
long i;
939
for (i = 0; i <= n; i++)
940
if (A[i]) pari_free((void*)A[i]);
941
pari_free((void*)A);
942
}
943
944
/* initialize Coeff reduction */
945
static int**
946
InitReduction(long d, long deg)
947
{
948
long j;
949
pari_sp av = avma;
950
int **A;
951
GEN polmod, pol;
952
953
A = (int**)pari_malloc(deg*sizeof(int*));
954
pol = polcyclo(d, 0);
955
for (j = 0; j < deg; j++)
956
{
957
A[j] = (int*)pari_malloc(deg*sizeof(int));
958
polmod = gmodulo(pol_xn(deg+j, 0), pol);
959
Polmod2Coeff(A[j], polmod, deg);
960
}
961
962
set_avma(av); return A;
963
}
964
965
#if 0
966
void
967
pan(int **an, long n, long deg)
968
{
969
long i,j;
970
for (i = 1; i <= n; i++)
971
{
972
err_printf("n = %ld: ",i);
973
for (j = 0; j < deg; j++) err_printf("%d ",an[i][j]);
974
err_printf("\n");
975
}
976
}
977
#endif
978
979
/* returns 0 if c is zero, 1 otherwise. */
980
static int
981
IsZero(int* c, long deg)
982
{
983
long i;
984
for (i = 0; i < deg; i++)
985
if (c[i]) return 0;
986
return 1;
987
}
988
989
/* set c0 <-- c0 * c1 */
990
static void
991
MulCoeff(int *c0, int* c1, int** reduc, long deg)
992
{
993
long i,j;
994
int c, *T;
995
996
if (IsZero(c0,deg)) return;
997
998
T = (int*)new_chunk(2*deg);
999
for (i = 0; i < 2*deg; i++)
1000
{
1001
c = 0;
1002
for (j = 0; j <= i; j++)
1003
if (j < deg && j > i - deg) c += c0[j] * c1[i-j];
1004
T[i] = c;
1005
}
1006
for (i = 0; i < deg; i++)
1007
{
1008
c = T[i];
1009
for (j = 0; j < deg; j++) c += reduc[j][i] * T[deg+j];
1010
c0[i] = c;
1011
}
1012
}
1013
1014
/* c0 <- c0 + c1 * c2 */
1015
static void
1016
AddMulCoeff(int *c0, int *c1, int* c2, int** reduc, long deg)
1017
{
1018
long i, j;
1019
pari_sp av;
1020
int c, *t;
1021
1022
if (IsZero(c2,deg)) return;
1023
if (!c1) /* c1 == 1 */
1024
{
1025
for (i = 0; i < deg; i++) c0[i] += c2[i];
1026
return;
1027
}
1028
av = avma;
1029
t = (int*)new_chunk(2*deg); /* = c1 * c2, not reduced */
1030
for (i = 0; i < 2*deg; i++)
1031
{
1032
c = 0;
1033
for (j = 0; j <= i; j++)
1034
if (j < deg && j > i - deg) c += c1[j] * c2[i-j];
1035
t[i] = c;
1036
}
1037
for (i = 0; i < deg; i++)
1038
{
1039
c = t[i];
1040
for (j = 0; j < deg; j++) c += reduc[j][i] * t[deg+j];
1041
c0[i] += c;
1042
}
1043
set_avma(av);
1044
}
1045
1046
/* evaluate the Coeff. No Garbage collector */
1047
static GEN
1048
EvalCoeff(GEN z, int* c, long deg)
1049
{
1050
long i,j;
1051
GEN e, r;
1052
1053
if (!c) return gen_0;
1054
#if 0
1055
/* standard Horner */
1056
e = stoi(c[deg - 1]);
1057
for (i = deg - 2; i >= 0; i--)
1058
e = gadd(stoi(c[i]), gmul(z, e));
1059
#else
1060
/* specific attention to sparse polynomials */
1061
e = NULL;
1062
for (i = deg-1; i >=0; i=j-1)
1063
{
1064
for (j=i; c[j] == 0; j--)
1065
if (j==0)
1066
{
1067
if (!e) return NULL;
1068
if (i!=j) z = gpowgs(z,i-j+1);
1069
return gmul(e,z);
1070
}
1071
if (e)
1072
{
1073
r = (i==j)? z: gpowgs(z,i-j+1);
1074
e = gadd(gmul(e,r), stoi(c[j]));
1075
}
1076
else
1077
e = stoi(c[j]);
1078
}
1079
#endif
1080
return e;
1081
}
1082
1083
/* copy the n * (m+1) array matan */
1084
static void
1085
CopyCoeff(int** a, int** a2, long n, long m)
1086
{
1087
long i,j;
1088
1089
for (i = 1; i <= n; i++)
1090
{
1091
int *b = a[i], *b2 = a2[i];
1092
for (j = 0; j < m; j++) b2[j] = b[j];
1093
}
1094
}
1095
1096
static void
1097
an_AddMul(int **an,int **an2, long np, long n, long deg, GEN chi, int **reduc)
1098
{
1099
GEN chi2 = chi;
1100
long q, qk, k;
1101
int *c, *c2 = (int*)new_chunk(deg);
1102
1103
CopyCoeff(an, an2, n/np, deg);
1104
for (q=np;;)
1105
{
1106
if (gequal1(chi2)) c = NULL; else { Polmod2Coeff(c2, chi2, deg); c = c2; }
1107
for(k = 1, qk = q; qk <= n; k++, qk += q)
1108
AddMulCoeff(an[qk], c, an2[k], reduc, deg);
1109
if (! (q = umuluu_le(q,np, n)) ) break;
1110
1111
chi2 = gmul(chi2, chi);
1112
}
1113
}
1114
1115
/* correct the coefficients an(chi) according with diff(chi) in place */
1116
static void
1117
CorrectCoeff(GEN dtcr, int** an, int** reduc, long n, long deg)
1118
{
1119
pari_sp av = avma;
1120
long lg, j;
1121
pari_sp av1;
1122
int **an2;
1123
GEN bnrc, diff;
1124
CHI_t C;
1125
1126
diff = ch_diff(dtcr); lg = lg(diff) - 1;
1127
if (!lg) return;
1128
1129
if (DEBUGLEVEL>2) err_printf("diff(CHI) = %Ps", diff);
1130
bnrc = ch_bnr(dtcr);
1131
init_CHI_alg(&C, ch_CHI0(dtcr));
1132
1133
an2 = InitMatAn(n, deg, 0);
1134
av1 = avma;
1135
for (j = 1; j <= lg; j++)
1136
{
1137
GEN pr = gel(diff,j);
1138
long Np = upr_norm(pr);
1139
GEN chi = CHI_eval(&C, isprincipalray(bnrc, pr));
1140
an_AddMul(an,an2,Np,n,deg,chi,reduc);
1141
set_avma(av1);
1142
}
1143
FreeMat(an2, n); set_avma(av);
1144
}
1145
1146
/* compute the coefficients an in the general case */
1147
static int**
1148
ComputeCoeff(GEN dtcr, LISTray *R, long n, long deg)
1149
{
1150
pari_sp av = avma, av2;
1151
long i, l;
1152
int **an, **reduc, **an2;
1153
GEN L;
1154
CHI_t C;
1155
1156
init_CHI_alg(&C, ch_CHI(dtcr));
1157
an = InitMatAn(n, deg, 0);
1158
an2 = InitMatAn(n, deg, 0);
1159
reduc = InitReduction(C.ord, deg);
1160
av2 = avma;
1161
1162
L = R->L1; l = lg(L);
1163
for (i=1; i<l; i++, set_avma(av2))
1164
{
1165
long np = L[i];
1166
GEN chi = CHI_eval(&C, gel(R->L1ray,i));
1167
an_AddMul(an,an2,np,n,deg,chi,reduc);
1168
}
1169
FreeMat(an2, n);
1170
1171
CorrectCoeff(dtcr, an, reduc, n, deg);
1172
FreeMat(reduc, deg-1);
1173
set_avma(av); return an;
1174
}
1175
1176
/********************************************************************/
1177
/* 5th part: compute L-functions at s=1 */
1178
/********************************************************************/
1179
static void
1180
deg11(LISTray *R, long p, GEN bnr, GEN pr) {
1181
GEN z = isprincipalray(bnr, pr);
1182
vecsmalltrunc_append(R->L1, p);
1183
vectrunc_append(R->L1ray, z);
1184
}
1185
static void
1186
deg12(LISTray *R, long p, GEN bnr, GEN Lpr) {
1187
GEN z = isprincipalray(bnr, gel(Lpr,1));
1188
vecsmalltrunc_append(R->L11, p);
1189
vectrunc_append(R->L11ray, z);
1190
}
1191
static void
1192
deg0(LISTray *R, long p) { vecsmalltrunc_append(R->L0, p); }
1193
static void
1194
deg2(LISTray *R, long p) { vecsmalltrunc_append(R->L2, p); }
1195
1196
static void
1197
InitPrimesQuad(GEN bnr, ulong N0, LISTray *R)
1198
{
1199
pari_sp av = avma;
1200
GEN bnf = bnr_get_bnf(bnr), cond = gel(bnr_get_mod(bnr), 1);
1201
long p,i,l, condZ = itos(gcoeff(cond,1,1)), contZ = itos(content(cond));
1202
GEN prime, Lpr, nf = bnf_get_nf(bnf), dk = nf_get_disc(nf);
1203
forprime_t T;
1204
1205
l = 1 + primepi_upper_bound(N0);
1206
R->L0 = vecsmalltrunc_init(l);
1207
R->L2 = vecsmalltrunc_init(l); R->condZ = condZ;
1208
R->L1 = vecsmalltrunc_init(l); R->L1ray = vectrunc_init(l);
1209
R->L11= vecsmalltrunc_init(l); R->L11ray= vectrunc_init(l);
1210
prime = utoipos(2);
1211
u_forprime_init(&T, 2, N0);
1212
while ( (p = u_forprime_next(&T)) )
1213
{
1214
prime[2] = p;
1215
switch (kroiu(dk, p))
1216
{
1217
case -1: /* inert */
1218
if (condZ % p == 0) deg0(R,p); else deg2(R,p);
1219
break;
1220
case 1: /* split */
1221
Lpr = idealprimedec(nf, prime);
1222
if (condZ % p != 0) deg12(R, p, bnr, Lpr);
1223
else if (contZ % p == 0) deg0(R,p);
1224
else
1225
{
1226
GEN pr = idealval(nf, cond, gel(Lpr,1))? gel(Lpr,2): gel(Lpr,1);
1227
deg11(R, p, bnr, pr);
1228
}
1229
break;
1230
default: /* ramified */
1231
if (condZ % p == 0)
1232
deg0(R,p);
1233
else
1234
deg11(R, p, bnr, idealprimedec_galois(nf,prime));
1235
break;
1236
}
1237
}
1238
/* precompute isprincipalray(x), x in Z */
1239
R->rayZ = cgetg(condZ, t_VEC);
1240
for (i=1; i<condZ; i++)
1241
gel(R->rayZ,i) = (ugcd(i,condZ) == 1)? isprincipalray(bnr, utoipos(i)): gen_0;
1242
gerepileall(av, 7, &(R->L0), &(R->L2), &(R->rayZ),
1243
&(R->L1), &(R->L1ray), &(R->L11), &(R->L11ray) );
1244
}
1245
1246
static void
1247
InitPrimes(GEN bnr, ulong N0, LISTray *R)
1248
{
1249
GEN bnf = bnr_get_bnf(bnr), cond = gel(bnr_get_mod(bnr), 1);
1250
long p, l, condZ, N = lg(cond)-1;
1251
GEN DL, prime, BOUND, nf = bnf_get_nf(bnf);
1252
forprime_t T;
1253
1254
R->condZ = condZ = itos(gcoeff(cond,1,1));
1255
l = primepi_upper_bound(N0) * N;
1256
DL = cgetg(N+1, t_VEC);
1257
R->L1 = vecsmalltrunc_init(l);
1258
R->L1ray = vectrunc_init(l);
1259
u_forprime_init(&T, 2, N0);
1260
prime = utoipos(2);
1261
BOUND = utoi(N0);
1262
while ( (p = u_forprime_next(&T)) )
1263
{
1264
pari_sp av = avma;
1265
long j, k, lP;
1266
GEN P;
1267
prime[2] = p;
1268
if (DEBUGLEVEL>1 && (p & 2047) == 1) err_printf("%ld ", p);
1269
P = idealprimedec_limit_norm(nf, prime, BOUND); lP = lg(P);
1270
for (j = 1; j < lP; j++)
1271
{
1272
GEN pr = gel(P,j), dl = NULL;
1273
if (condZ % p || !idealval(nf, cond, pr))
1274
{
1275
dl = gclone( isprincipalray(bnr, pr) );
1276
vecsmalltrunc_append(R->L1, upowuu(p, pr_get_f(pr)));
1277
}
1278
gel(DL,j) = dl;
1279
}
1280
set_avma(av);
1281
for (k = 1; k < j; k++)
1282
{
1283
if (!DL[k]) continue;
1284
vectrunc_append(R->L1ray, ZC_copy(gel(DL,k)));
1285
gunclone(gel(DL,k));
1286
}
1287
}
1288
}
1289
1290
static GEN /* cf polcoef */
1291
_sercoeff(GEN x, long n)
1292
{
1293
long i = n - valp(x);
1294
return (i < 0)? gen_0: gel(x,i+2);
1295
}
1296
1297
static void
1298
affect_coeff(GEN q, long n, GEN y, long t)
1299
{
1300
GEN x = _sercoeff(q,-n);
1301
if (x == gen_0) gel(y,n) = NULL;
1302
else { affgr(x, gel(y,n)); shiftr_inplace(gel(y,n), t); }
1303
}
1304
/* (x-i)(x-(i+1)) */
1305
static GEN
1306
d2(long i) { return deg2pol_shallow(gen_1, utoineg(2*i+1), muluu(i,i+1), 0); }
1307
/* x-i */
1308
static GEN
1309
d1(long i) { return deg1pol_shallow(gen_1, stoi(-i), 0); }
1310
1311
typedef struct {
1312
GEN c1, aij, bij, cS, cT, powracpi;
1313
long i0, a,b,c, r, rc1, rc2;
1314
} ST_t;
1315
1316
/* compute the principal part at the integers s = 0, -1, -2, ..., -i0
1317
* of Gamma((s+1)/2)^a Gamma(s/2)^b Gamma(s)^c / (s - z) with z = 0 and 1 */
1318
static void
1319
ppgamma(ST_t *T, long prec)
1320
{
1321
GEN G, G1, G2, A, E, O, x, sqpi, aij, bij;
1322
long c = T->c, r = T->r, i0 = T->i0, i, j, s, t, dx;
1323
pari_sp av;
1324
1325
T->aij = aij = cgetg(i0+1, t_VEC);
1326
T->bij = bij = cgetg(i0+1, t_VEC);
1327
for (i = 1; i <= i0; i++)
1328
{
1329
GEN p1, p2;
1330
gel(aij,i) = p1 = cgetg(r+1, t_VEC);
1331
gel(bij,i) = p2 = cgetg(r+1, t_VEC);
1332
for (j=1; j<=r; j++) { gel(p1,j) = cgetr(prec); gel(p2,j) = cgetr(prec); }
1333
}
1334
av = avma; x = pol_x(0);
1335
sqpi = sqrtr_abs(mppi(prec)); /* Gamma(1/2) */
1336
1337
G1 = gexp(integser(psi1series(r-1, 0, prec)), prec); /* Gamma(1 + x) */
1338
G = shallowcopy(G1); setvalp(G,-1); /* Gamma(x) */
1339
1340
/* expansion of log(Gamma(u) / Gamma(1/2)) at u = 1/2 */
1341
G2 = cgetg(r+2, t_SER);
1342
G2[1] = evalsigne(1) | _evalvalp(1) | evalvarn(0);
1343
gel(G2,2) = gneg(gadd(gmul2n(mplog2(prec), 1), mpeuler(prec)));
1344
for (i = 1; i < r; i++) gel(G2,i+2) = mulri(gel(G1,i+2), int2um1(i));
1345
G2 = gmul(sqpi, gexp(G2, prec)); /* Gamma(1/2 + x) */
1346
1347
/* We simplify to get one of the following two expressions
1348
* if (b > a) : sqrt(Pi)^a 2^{a-au} Gamma(u)^{a+c} Gamma( u/2 )^{|b-a|}
1349
* if (b <= a): sqrt(Pi)^b 2^{b-bu} Gamma(u)^{b+c} Gamma((u+1)/2)^{|b-a|} */
1350
if (T->b > T->a)
1351
{
1352
t = T->a; s = T->b; dx = 1;
1353
E = ser_unscale(G, ghalf);
1354
O = gmul2n(gdiv(ser_unscale(G2, ghalf), d1(1)), 1); /* Gamma((x-1)/2) */
1355
}
1356
else
1357
{
1358
t = T->b; s = T->a; dx = 0;
1359
E = ser_unscale(G2, ghalf);
1360
O = ser_unscale(G, ghalf);
1361
}
1362
/* (sqrt(Pi) 2^{1-x})^t Gamma(x)^{t+c} */
1363
A = gmul(gmul(powru(gmul2n(sqpi,1), t), gpowgs(G, t+c)),
1364
gpow(gen_2, RgX_to_ser(gmulgs(x,-t), r+2), prec));
1365
/* A * Gamma((x - dx + 1)/2)^{s-t} */
1366
E = gmul(A, gpowgs(E, s-t));
1367
/* A * Gamma((x - dx)/2)^{s-t} */
1368
O = gdiv(gmul(A, gpowgs(O, s-t)), gpowgs(gsubgs(x, 1), t+c));
1369
for (i = 0; i < i0/2; i++)
1370
{
1371
GEN p1, q1, A1 = gel(aij,2*i+1), B1 = gel(bij,2*i+1);
1372
GEN p2, q2, A2 = gel(aij,2*i+2), B2 = gel(bij,2*i+2);
1373
long t1 = i * (s+t), t2 = t1 + t;
1374
1375
p1 = gdiv(E, d1(2*i));
1376
q1 = gdiv(E, d1(2*i+1));
1377
p2 = gdiv(O, d1(2*i+1));
1378
q2 = gdiv(O, d1(2*i+2));
1379
for (j = 1; j <= r; j++)
1380
{
1381
affect_coeff(p1, j, A1, t1); affect_coeff(q1, j, B1, t1);
1382
affect_coeff(p2, j, A2, t2); affect_coeff(q2, j, B2, t2);
1383
}
1384
E = gdiv(E, gmul(gpowgs(d1(2*i+1+dx), s-t), gpowgs(d2(2*i+1), t+c)));
1385
O = gdiv(O, gmul(gpowgs(d1(2*i+2+dx), s-t), gpowgs(d2(2*i+2), t+c)));
1386
}
1387
set_avma(av);
1388
}
1389
1390
/* chi != 1. Return L(1, chi) if fl & 1, else [r, c] where L(s, chi) ~ c s^r
1391
* at s = 0. */
1392
static GEN
1393
GetValue(GEN dtcr, GEN W, GEN S, GEN T, long fl, long prec)
1394
{
1395
GEN cf, z;
1396
long q, b, c, r;
1397
int isreal = (ch_deg(dtcr) <= 2);
1398
1399
ch_get3(dtcr, &q, &b, &c);
1400
if (fl & 1)
1401
{ /* S(chi) + W(chi).T(chi)) / (C(chi) sqrt(Pi)^{r1 - q}) */
1402
cf = gmul(ch_C(dtcr), powruhalf(mppi(prec), b));
1403
1404
z = gadd(S, gmul(W, T));
1405
if (isreal) z = real_i(z);
1406
z = gdiv(z, cf);
1407
if (fl & 2) z = gmul(z, AChi(dtcr, &r, 1, prec));
1408
}
1409
else
1410
{ /* (W(chi).S(conj(chi)) + T(chi)) / (sqrt(Pi)^q 2^{r1 - q}) */
1411
cf = gmul2n(powruhalf(mppi(prec), q), b);
1412
1413
z = gadd(gmul(W, conj_i(S)), conj_i(T));
1414
if (isreal) z = real_i(z);
1415
z = gdiv(z, cf); r = 0;
1416
if (fl & 2) z = gmul(z, AChi(dtcr, &r, 0, prec));
1417
z = mkvec2(utoi(b + c + r), z);
1418
}
1419
return z;
1420
}
1421
1422
/* return the order and the first nonzero term of L(s, chi0)
1423
at s = 0. If flag != 0, adjust the value to get L_S(s, chi0). */
1424
static GEN
1425
GetValue1(GEN bnr, long flag, long prec)
1426
{
1427
GEN bnf = bnr_get_bnf(bnr), nf = bnf_get_nf(bnf);
1428
GEN h = bnf_get_no(bnf), R = bnf_get_reg(bnf);
1429
GEN c = gdivgs(mpmul(h, R), -bnf_get_tuN(bnf));
1430
long r = lg(nf_get_roots(nf)) - 2; /* r1 + r2 - 1 */;
1431
if (flag)
1432
{
1433
GEN diff = divcond(bnr);
1434
long i, l;
1435
l = lg(diff) - 1; r += l;
1436
for (i = 1; i <= l; i++) c = gmul(c, glog(pr_norm(gel(diff,i)), prec));
1437
}
1438
return mkvec2(utoi(r), c);
1439
}
1440
1441
/********************************************************************/
1442
/* 6th part: recover the coefficients */
1443
/********************************************************************/
1444
static long
1445
TestOne(GEN plg, RC_data *d)
1446
{
1447
long j, v = d->v;
1448
GEN z = gsub(d->beta, gel(plg,v));
1449
if (expo(z) >= d->G) return 0;
1450
for (j = 1; j < lg(plg); j++)
1451
if (j != v && mpcmp(d->B, mpabs_shallow(gel(plg,j))) < 0) return 0;
1452
return 1;
1453
}
1454
1455
static GEN
1456
chk_reccoeff_init(FP_chk_fun *chk, GEN r, GEN mat)
1457
{
1458
RC_data *d = (RC_data*)chk->data;
1459
(void)r; d->U = mat; return d->nB;
1460
}
1461
1462
static GEN
1463
chk_reccoeff(void *data, GEN x)
1464
{
1465
RC_data *d = (RC_data*)data;
1466
GEN v = gmul(d->U, x), z = gel(v,1);
1467
1468
if (!gequal1(z)) return NULL;
1469
*++v = evaltyp(t_COL) | evallg( lg(d->M) );
1470
if (TestOne(gmul(d->M, v), d)) return v;
1471
return NULL;
1472
}
1473
1474
/* Using Cohen's method */
1475
static GEN
1476
RecCoeff3(GEN nf, RC_data *d, long prec)
1477
{
1478
GEN A, M, nB, cand, p1, B2, C2, tB, beta2, nf2, Bd;
1479
GEN beta = d->beta, B = d->B;
1480
long N = d->N, v = d->v, e, BIG;
1481
long i, j, k, ct = 0, prec2;
1482
FP_chk_fun chk = { &chk_reccoeff, &chk_reccoeff_init, NULL, NULL, 0 };
1483
chk.data = (void*)d;
1484
1485
d->G = minss(-10, -prec2nbits(prec) >> 4);
1486
BIG = maxss(32, -2*d->G);
1487
tB = sqrtnr(real2n(BIG-N,DEFAULTPREC), N-1);
1488
Bd = grndtoi(gmin_shallow(B, tB), &e);
1489
if (e > 0) return NULL; /* failure */
1490
Bd = addiu(Bd, 1);
1491
prec2 = nbits2prec( expi(Bd) + 192 );
1492
prec2 = maxss(precdbl(prec), prec2);
1493
B2 = sqri(Bd);
1494
C2 = shifti(B2, BIG<<1);
1495
1496
LABrcf: ct++;
1497
beta2 = gprec_w(beta, prec2);
1498
nf2 = nfnewprec_shallow(nf, prec2);
1499
d->M = M = nf_get_M(nf2);
1500
1501
A = cgetg(N+2, t_MAT);
1502
for (i = 1; i <= N+1; i++) gel(A,i) = cgetg(N+2, t_COL);
1503
1504
gcoeff(A, 1, 1) = gadd(gmul(C2, gsqr(beta2)), B2);
1505
for (j = 2; j <= N+1; j++)
1506
{
1507
p1 = gmul(C2, gmul(gneg_i(beta2), gcoeff(M, v, j-1)));
1508
gcoeff(A, 1, j) = gcoeff(A, j, 1) = p1;
1509
}
1510
for (i = 2; i <= N+1; i++)
1511
for (j = i; j <= N+1; j++)
1512
{
1513
p1 = gen_0;
1514
for (k = 1; k <= N; k++)
1515
{
1516
GEN p2 = gmul(gcoeff(M, k, j-1), gcoeff(M, k, i-1));
1517
if (k == v) p2 = gmul(C2, p2);
1518
p1 = gadd(p1,p2);
1519
}
1520
gcoeff(A, i, j) = gcoeff(A, j, i) = p1;
1521
}
1522
1523
nB = mului(N+1, B2);
1524
d->nB = nB;
1525
cand = fincke_pohst(A, nB, -1, prec2, &chk);
1526
1527
if (!cand)
1528
{
1529
if (ct > 3) return NULL;
1530
prec2 = precdbl(prec2);
1531
if (DEBUGLEVEL>1) pari_warn(warnprec,"RecCoeff", prec2);
1532
goto LABrcf;
1533
}
1534
1535
cand = gel(cand,1);
1536
if (lg(cand) == 2) return gel(cand,1);
1537
1538
if (DEBUGLEVEL>1) err_printf("RecCoeff3: no solution found!\n");
1539
return NULL;
1540
}
1541
1542
/* Using linear dependance relations */
1543
static GEN
1544
RecCoeff2(GEN nf, RC_data *d, long prec)
1545
{
1546
pari_sp av;
1547
GEN vec, M = nf_get_M(nf), beta = d->beta;
1548
long bit, min, max, lM = lg(M);
1549
1550
d->G = minss(-20, -prec2nbits(prec) >> 4);
1551
1552
vec = vec_prepend(row(M, d->v), gneg(beta));
1553
min = (long)prec2nbits_mul(prec, 0.75);
1554
max = (long)prec2nbits_mul(prec, 0.98);
1555
av = avma;
1556
for (bit = max; bit >= min; bit-=32, set_avma(av))
1557
{
1558
long e;
1559
GEN v = lindep_bit(vec, bit), z = gel(v,1);
1560
if (!signe(z)) continue;
1561
*++v = evaltyp(t_COL) | evallg(lM);
1562
v = grndtoi(gdiv(v, z), &e);
1563
if (e > 0) break;
1564
if (TestOne(RgM_RgC_mul(M, v), d)) return v;
1565
}
1566
/* failure */
1567
return RecCoeff3(nf,d,prec);
1568
}
1569
1570
/* Attempts to find a polynomial with coefficients in nf such that
1571
its coefficients are close to those of pol at the place v and
1572
less than B at all the other places */
1573
static GEN
1574
RecCoeff(GEN nf, GEN pol, long v, long prec)
1575
{
1576
long j, md, cl = degpol(pol);
1577
pari_sp av = avma;
1578
RC_data d;
1579
1580
/* if precision(pol) is too low, abort */
1581
for (j = 2; j <= cl+1; j++)
1582
{
1583
GEN t = gel(pol, j);
1584
if (prec2nbits(precision(t)) - gexpo(t) < 34) return NULL;
1585
}
1586
1587
md = cl/2;
1588
pol = leafcopy(pol);
1589
1590
d.N = nf_get_degree(nf);
1591
d.v = v;
1592
1593
for (j = 1; j <= cl; j++)
1594
{ /* start with the coefficients in the middle,
1595
since they are the harder to recognize! */
1596
long cf = md + (j%2? j/2: -j/2);
1597
GEN t, bound = shifti(binomial(utoipos(cl), cf), cl-cf);
1598
1599
if (DEBUGLEVEL>1) err_printf("RecCoeff (cf = %ld, B = %Ps)\n", cf, bound);
1600
d.beta = real_i( gel(pol,cf+2) );
1601
d.B = bound;
1602
if (! (t = RecCoeff2(nf, &d, prec)) ) return NULL;
1603
gel(pol, cf+2) = coltoalg(nf,t);
1604
}
1605
gel(pol,cl+2) = gen_1;
1606
return gerepilecopy(av, pol);
1607
}
1608
1609
/* an[q * i] *= chi for all (i,p)=1 */
1610
static void
1611
an_mul(int **an, long p, long q, long n, long deg, GEN chi, int **reduc)
1612
{
1613
pari_sp av;
1614
long c,i;
1615
int *T;
1616
1617
if (gequal1(chi)) return;
1618
av = avma;
1619
T = (int*)new_chunk(deg); Polmod2Coeff(T,chi, deg);
1620
for (c = 1, i = q; i <= n; i += q, c++)
1621
if (c == p) c = 0; else MulCoeff(an[i], T, reduc, deg);
1622
set_avma(av);
1623
}
1624
/* an[q * i] = 0 for all (i,p)=1 */
1625
static void
1626
an_set0_coprime(int **an, long p, long q, long n, long deg)
1627
{
1628
long c,i;
1629
for (c = 1, i = q; i <= n; i += q, c++)
1630
if (c == p) c = 0; else _0toCoeff(an[i], deg);
1631
}
1632
/* an[q * i] = 0 for all i */
1633
static void
1634
an_set0(int **an, long p, long n, long deg)
1635
{
1636
long i;
1637
for (i = p; i <= n; i += p) _0toCoeff(an[i], deg);
1638
}
1639
1640
/* compute the coefficients an for the quadratic case */
1641
static int**
1642
computean(GEN dtcr, LISTray *R, long n, long deg)
1643
{
1644
pari_sp av = avma, av2;
1645
long i, p, q, condZ, l;
1646
int **an, **reduc;
1647
GEN L, chi, chi1;
1648
CHI_t C;
1649
1650
init_CHI_alg(&C, ch_CHI(dtcr));
1651
condZ= R->condZ;
1652
1653
an = InitMatAn(n, deg, 1);
1654
reduc = InitReduction(C.ord, deg);
1655
av2 = avma;
1656
1657
/* all pr | p divide cond */
1658
L = R->L0; l = lg(L);
1659
for (i=1; i<l; i++) an_set0(an,L[i],n,deg);
1660
1661
/* 1 prime of degree 2 */
1662
L = R->L2; l = lg(L);
1663
for (i=1; i<l; i++, set_avma(av2))
1664
{
1665
p = L[i];
1666
if (condZ == 1) chi = C.val[0]; /* 1 */
1667
else chi = CHI_eval(&C, gel(R->rayZ, p%condZ));
1668
chi1 = chi;
1669
for (q=p;;)
1670
{
1671
an_set0_coprime(an, p,q,n,deg); /* v_p(q) odd */
1672
if (! (q = umuluu_le(q,p, n)) ) break;
1673
1674
an_mul(an,p,q,n,deg,chi,reduc);
1675
if (! (q = umuluu_le(q,p, n)) ) break;
1676
chi = gmul(chi, chi1);
1677
}
1678
}
1679
1680
/* 1 prime of degree 1 */
1681
L = R->L1; l = lg(L);
1682
for (i=1; i<l; i++, set_avma(av2))
1683
{
1684
p = L[i];
1685
chi = CHI_eval(&C, gel(R->L1ray,i));
1686
chi1 = chi;
1687
for(q=p;;)
1688
{
1689
an_mul(an,p,q,n,deg,chi,reduc);
1690
if (! (q = umuluu_le(q,p, n)) ) break;
1691
chi = gmul(chi, chi1);
1692
}
1693
}
1694
1695
/* 2 primes of degree 1 */
1696
L = R->L11; l = lg(L);
1697
for (i=1; i<l; i++, set_avma(av2))
1698
{
1699
GEN ray1, ray2, chi11, chi12, chi2;
1700
1701
p = L[i]; ray1 = gel(R->L11ray,i); /* use pr1 pr2 = (p) */
1702
if (condZ == 1)
1703
ray2 = ZC_neg(ray1);
1704
else
1705
ray2 = ZC_sub(gel(R->rayZ, p%condZ), ray1);
1706
chi11 = CHI_eval(&C, ray1);
1707
chi12 = CHI_eval(&C, ray2);
1708
1709
chi1 = gadd(chi11, chi12);
1710
chi2 = chi12;
1711
for(q=p;;)
1712
{
1713
an_mul(an,p,q,n,deg,chi1,reduc);
1714
if (! (q = umuluu_le(q,p, n)) ) break;
1715
chi2 = gmul(chi2, chi12);
1716
chi1 = gadd(chi2, gmul(chi1, chi11));
1717
}
1718
}
1719
1720
CorrectCoeff(dtcr, an, reduc, n, deg);
1721
FreeMat(reduc, deg-1);
1722
set_avma(av); return an;
1723
}
1724
1725
/* return the vector of A^i/i for i = 1...n */
1726
static GEN
1727
mpvecpowdiv(GEN A, long n)
1728
{
1729
pari_sp av = avma;
1730
long i;
1731
GEN v = powersr(A, n);
1732
GEN w = cgetg(n+1, t_VEC);
1733
gel(w,1) = rcopy(gel(v,2));
1734
for (i=2; i<=n; i++) gel(w,i) = divru(gel(v,i+1), i);
1735
return gerepileupto(av, w);
1736
}
1737
1738
static void GetST0(GEN bnr, GEN *pS, GEN *pT, GEN CR, long prec);
1739
/* allocate memory for GetST answer */
1740
static void
1741
ST_alloc(GEN *pS, GEN *pT, long l, long prec)
1742
{
1743
long j;
1744
*pS = cgetg(l, t_VEC);
1745
*pT = cgetg(l, t_VEC);
1746
for (j = 1; j < l; j++)
1747
{
1748
gel(*pS,j) = cgetc(prec);
1749
gel(*pT,j) = cgetc(prec);
1750
}
1751
}
1752
1753
/* compute S and T for the quadratic case. The following cases are:
1754
* 1) bnr complex;
1755
* 2) bnr real and no infinite place divide cond_chi (TODO);
1756
* 3) bnr real and one infinite place divide cond_chi;
1757
* 4) bnr real and both infinite places divide cond_chi (TODO) */
1758
static void
1759
QuadGetST(GEN bnr, GEN *pS, GEN *pT, GEN CR, long prec)
1760
{
1761
pari_sp av, av1, av2;
1762
long ncond, n, j, k, n0;
1763
GEN vChar = gel(CR,1), dataCR = gel(CR,2), S, T, an, cs, N0, C;
1764
LISTray LIST;
1765
1766
/* initializations */
1767
ST_alloc(pS, pT, lg(dataCR), prec); T = *pT; S = *pS;
1768
av = avma;
1769
ncond = lg(vChar)-1;
1770
C = cgetg(ncond+1, t_VEC);
1771
N0 = cgetg(ncond+1, t_VECSMALL);
1772
cs = cgetg(ncond+1, t_VECSMALL);
1773
n0 = 0;
1774
for (j = 1; j <= ncond; j++)
1775
{
1776
GEN dtcr = gel(dataCR, mael(vChar,j,1)), c = ch_C(dtcr);
1777
long r1, r2;
1778
1779
gel(C,j) = c;
1780
nf_get_sign(bnr_get_nf(ch_bnr(dtcr)), &r1, &r2);
1781
if (r1 == 2) /* real quadratic */
1782
{
1783
cs[j] = 2 + ch_q(dtcr);
1784
if (cs[j] == 2 || cs[j] == 4)
1785
{ /* NOT IMPLEMENTED YET */
1786
GetST0(bnr, pS, pT, CR, prec);
1787
return;
1788
}
1789
/* FIXME: is this value of N0 correct for the general case ? */
1790
N0[j] = (long)prec2nbits_mul(prec, 0.35 * gtodouble(c));
1791
}
1792
else /* complex quadratic */
1793
{
1794
cs[j] = 1;
1795
N0[j] = (long)prec2nbits_mul(prec, 0.7 * gtodouble(c));
1796
}
1797
if (n0 < N0[j]) n0 = N0[j];
1798
}
1799
if (DEBUGLEVEL>1) err_printf("N0 = %ld\n", n0);
1800
InitPrimesQuad(bnr, n0, &LIST);
1801
1802
av1 = avma;
1803
/* loop over conductors */
1804
for (j = 1; j <= ncond; j++)
1805
{
1806
GEN c0 = gel(C,j), c1 = divur(1, c0), c2 = divur(2, c0);
1807
GEN ec1 = mpexp(c1), ec2 = mpexp(c2), LChar = gel(vChar,j);
1808
GEN vf0, vf1, cf0, cf1;
1809
const long nChar = lg(LChar)-1, NN = N0[j];
1810
1811
if (DEBUGLEVEL>1)
1812
err_printf("* conductor no %ld/%ld (N = %ld)\n\tInit: ", j,ncond,NN);
1813
if (realprec(ec1) > prec) ec1 = rtor(ec1, prec);
1814
if (realprec(ec2) > prec) ec2 = rtor(ec2, prec);
1815
switch(cs[j])
1816
{
1817
case 1:
1818
cf0 = gen_1;
1819
cf1 = c0;
1820
vf0 = mpveceint1(rtor(c1, prec), ec1, NN);
1821
vf1 = mpvecpowdiv(invr(ec1), NN); break;
1822
1823
case 3:
1824
cf0 = sqrtr(mppi(prec));
1825
cf1 = gmul2n(cf0, 1);
1826
cf0 = gmul(cf0, c0);
1827
vf0 = mpvecpowdiv(invr(ec2), NN);
1828
vf1 = mpveceint1(rtor(c2, prec), ec2, NN); break;
1829
1830
default:
1831
cf0 = cf1 = NULL; /* FIXME: not implemented */
1832
vf0 = vf1 = NULL;
1833
}
1834
for (k = 1; k <= nChar; k++)
1835
{
1836
long u = LChar[k], d, c;
1837
GEN dtcr = gel(dataCR, u), z, s, t;
1838
int **matan;
1839
1840
if (!ch_comp(dtcr)) continue;
1841
if (DEBUGLEVEL>1) err_printf("\tchar no: %ld (%ld/%ld)\n", u,k,nChar);
1842
d = ch_phideg(dtcr);
1843
z = gel(ch_CHI(dtcr), 2); s = t = gen_0; av2 = avma;
1844
matan = computean(gel(dataCR,u), &LIST, NN, d);
1845
for (n = 1, c = 0; n <= NN; n++)
1846
if ((an = EvalCoeff(z, matan[n], d)))
1847
{
1848
s = gadd(s, gmul(an, gel(vf0,n)));
1849
t = gadd(t, gmul(an, gel(vf1,n)));
1850
if (++c == 256) { gerepileall(av2,2, &s,&t); c = 0; }
1851
}
1852
gaffect(gmul(cf0, s), gel(S,u));
1853
gaffect(gmul(cf1, conj_i(t)), gel(T,u));
1854
FreeMat(matan,NN); set_avma(av2);
1855
}
1856
if (DEBUGLEVEL>1) err_printf("\n");
1857
set_avma(av1);
1858
}
1859
set_avma(av);
1860
}
1861
1862
/* s += t*u. All 3 of them t_REAL, except we allow s or u = NULL (for 0) */
1863
static GEN
1864
_addmulrr(GEN s, GEN t, GEN u)
1865
{
1866
if (u)
1867
{
1868
GEN v = mulrr(t, u);
1869
return s? addrr(s, v): v;
1870
}
1871
return s;
1872
}
1873
/* s += t. Both real, except we allow s or t = NULL (for exact 0) */
1874
static GEN
1875
_addrr(GEN s, GEN t)
1876
{ return t? (s? addrr(s, t): t) : s; }
1877
1878
/* S & T for the general case. This is time-critical: optimize */
1879
static void
1880
get_cS_cT(ST_t *T, long n)
1881
{
1882
pari_sp av;
1883
GEN csurn, nsurc, lncsurn, A, B, s, t, Z, aij, bij;
1884
long i, j, r, i0;
1885
1886
if (gel(T->cS,n)) return;
1887
1888
av = avma;
1889
aij = T->aij; i0= T->i0;
1890
bij = T->bij; r = T->r;
1891
Z = cgetg(r+1, t_VEC);
1892
gel(Z,1) = NULL; /* unused */
1893
1894
csurn = divru(T->c1, n);
1895
nsurc = invr(csurn);
1896
lncsurn = logr_abs(csurn);
1897
1898
if (r > 1)
1899
{
1900
gel(Z,2) = lncsurn; /* r >= 2 */
1901
for (i = 3; i <= r; i++)
1902
gel(Z,i) = divru(mulrr(gel(Z,i-1), lncsurn), i-1);
1903
/* Z[i] = ln^(i-1)(c1/n) / (i-1)! */
1904
}
1905
1906
/* i = i0 */
1907
A = gel(aij,i0); t = _addrr(NULL, gel(A,1));
1908
B = gel(bij,i0); s = _addrr(NULL, gel(B,1));
1909
for (j = 2; j <= r; j++)
1910
{
1911
s = _addmulrr(s, gel(Z,j),gel(B,j));
1912
t = _addmulrr(t, gel(Z,j),gel(A,j));
1913
}
1914
for (i = i0 - 1; i > 1; i--)
1915
{
1916
A = gel(aij,i); if (t) t = mulrr(t, nsurc);
1917
B = gel(bij,i); if (s) s = mulrr(s, nsurc);
1918
for (j = odd(i)? T->rc2: T->rc1; j > 1; j--)
1919
{
1920
s = _addmulrr(s, gel(Z,j),gel(B,j));
1921
t = _addmulrr(t, gel(Z,j),gel(A,j));
1922
}
1923
s = _addrr(s, gel(B,1));
1924
t = _addrr(t, gel(A,1));
1925
}
1926
/* i = 1 */
1927
A = gel(aij,1); if (t) t = mulrr(t, nsurc);
1928
B = gel(bij,1); if (s) s = mulrr(s, nsurc);
1929
s = _addrr(s, gel(B,1));
1930
t = _addrr(t, gel(A,1));
1931
for (j = 2; j <= r; j++)
1932
{
1933
s = _addmulrr(s, gel(Z,j),gel(B,j));
1934
t = _addmulrr(t, gel(Z,j),gel(A,j));
1935
}
1936
s = _addrr(s, T->b? mulrr(csurn, gel(T->powracpi,T->b+1)): csurn);
1937
if (!s) s = gen_0;
1938
if (!t) t = gen_0;
1939
gel(T->cS,n) = gclone(s);
1940
gel(T->cT,n) = gclone(t); set_avma(av);
1941
}
1942
1943
static void
1944
clear_cScT(ST_t *T, long N)
1945
{
1946
GEN cS = T->cS, cT = T->cT;
1947
long i;
1948
for (i=1; i<=N; i++)
1949
if (cS[i]) {
1950
gunclone(gel(cS,i));
1951
gunclone(gel(cT,i)); gel(cS,i) = gel(cT,i) = NULL;
1952
}
1953
}
1954
1955
static void
1956
init_cScT(ST_t *T, GEN dtcr, long N, long prec)
1957
{
1958
ch_get3(dtcr, &T->a, &T->b, &T->c);
1959
T->rc1 = T->a + T->c;
1960
T->rc2 = T->b + T->c;
1961
T->r = maxss(T->rc2+1, T->rc1); /* >= 2 */
1962
ppgamma(T, prec);
1963
clear_cScT(T, N);
1964
}
1965
1966
/* return a t_REAL */
1967
static GEN
1968
zeta_get_limx(long r1, long r2, long bit)
1969
{
1970
pari_sp av = avma;
1971
GEN p1, p2, c0, c1, A0;
1972
long r = r1 + r2, N = r + r2;
1973
1974
/* c1 = N 2^(-2r2 / N) */
1975
c1 = mulrs(powrfrac(real2n(1, DEFAULTPREC), -2*r2, N), N);
1976
1977
p1 = powru(Pi2n(1, DEFAULTPREC), r - 1);
1978
p2 = mulir(powuu(N,r), p1); shiftr_inplace(p2, -r2);
1979
c0 = sqrtr( divrr(p2, powru(c1, r+1)) );
1980
1981
A0 = logr_abs( gmul2n(c0, bit) ); p2 = divrr(A0, c1);
1982
p1 = divrr(mulur(N*(r+1), logr_abs(p2)), addsr(2*(r+1), gmul2n(A0,2)));
1983
return gerepileuptoleaf(av, divrr(addrs(p1, 1), powruhalf(p2, N)));
1984
}
1985
/* N_0 = floor( C_K / limx ). Large */
1986
static long
1987
zeta_get_N0(GEN C, GEN limx)
1988
{
1989
long e;
1990
pari_sp av = avma;
1991
GEN z = gcvtoi(gdiv(C, limx), &e); /* avoid truncation error */
1992
if (e >= 0 || is_bigint(z))
1993
pari_err_OVERFLOW("zeta_get_N0 [need too many primes]");
1994
return gc_long(av, itos(z));
1995
}
1996
1997
static GEN
1998
eval_i(long r1, long r2, GEN limx, long i)
1999
{
2000
GEN t = powru(limx, i);
2001
if (!r1) t = mulrr(t, powru(mpfactr(i , DEFAULTPREC), r2));
2002
else if (!r2) t = mulrr(t, powru(mpfactr(i/2, DEFAULTPREC), r1));
2003
else {
2004
GEN u1 = mpfactr(i/2, DEFAULTPREC);
2005
GEN u2 = mpfactr(i, DEFAULTPREC);
2006
if (r1 == r2) t = mulrr(t, powru(mulrr(u1,u2), r1));
2007
else t = mulrr(t, mulrr(powru(u1,r1), powru(u2,r2)));
2008
}
2009
return t;
2010
}
2011
2012
/* "small" even i such that limx^i ( (i\2)! )^r1 ( i! )^r2 > B. */
2013
static long
2014
get_i0(long r1, long r2, GEN B, GEN limx)
2015
{
2016
long imin = 1, imax = 1400;
2017
while (mpcmp(eval_i(r1,r2,limx, imax), B) < 0) { imin = imax; imax *= 2; }
2018
while(imax - imin >= 4)
2019
{
2020
long m = (imax + imin) >> 1;
2021
if (mpcmp(eval_i(r1,r2,limx, m), B) >= 0) imax = m; else imin = m;
2022
}
2023
return imax & ~1; /* make it even */
2024
}
2025
/* limx = zeta_get_limx(r1, r2, bit), a t_REAL */
2026
static long
2027
zeta_get_i0(long r1, long r2, long bit, GEN limx)
2028
{
2029
pari_sp av = avma;
2030
GEN B = gmul(sqrtr( divrr(powrs(mppi(DEFAULTPREC), r2-3), limx) ),
2031
gmul2n(powuu(5, r1), bit + r2));
2032
return gc_long(av, get_i0(r1, r2, B, limx));
2033
}
2034
2035
static void
2036
GetST0(GEN bnr, GEN *pS, GEN *pT, GEN CR, long prec)
2037
{
2038
pari_sp av, av1, av2;
2039
long n, j, k, jc, n0, prec2, i0, r1, r2, ncond;
2040
GEN nf = bnr_get_nf(bnr);
2041
GEN vChar = gel(CR,1), dataCR = gel(CR,2), N0, C, an, limx, S, T;
2042
LISTray LIST;
2043
ST_t cScT;
2044
2045
ST_alloc(pS, pT, lg(dataCR), prec); T = *pT; S = *pS;
2046
av = avma;
2047
nf_get_sign(nf,&r1,&r2);
2048
ncond = lg(vChar)-1;
2049
C = cgetg(ncond+1, t_VEC);
2050
N0 = cgetg(ncond+1, t_VECSMALL);
2051
n0 = 0;
2052
limx = zeta_get_limx(r1, r2, prec2nbits(prec));
2053
for (j = 1; j <= ncond; j++)
2054
{
2055
GEN dtcr = gel(dataCR, mael(vChar,j,1)), c = ch_C(dtcr);
2056
gel(C,j) = c;
2057
N0[j] = zeta_get_N0(c, limx);
2058
if (n0 < N0[j]) n0 = N0[j];
2059
}
2060
cScT.i0 = i0 = zeta_get_i0(r1, r2, prec2nbits(prec), limx);
2061
if (DEBUGLEVEL>1) err_printf("i0 = %ld, N0 = %ld\n",i0, n0);
2062
InitPrimes(bnr, n0, &LIST);
2063
prec2 = precdbl(prec) + EXTRAPREC64;
2064
cScT.powracpi = powersr(sqrtr(mppi(prec2)), r1);
2065
cScT.cS = cgetg(n0+1, t_VEC);
2066
cScT.cT = cgetg(n0+1, t_VEC);
2067
for (j=1; j<=n0; j++) gel(cScT.cS,j) = gel(cScT.cT,j) = NULL;
2068
2069
av1 = avma;
2070
for (jc = 1; jc <= ncond; jc++)
2071
{
2072
GEN LChar = gel(vChar,jc);
2073
long nChar = lg(LChar)-1, N = N0[jc];
2074
2075
/* Can discard completely a conductor if all chars satisfy L(0,chi) = 0
2076
* Not sure whether this is possible. */
2077
if (DEBUGLEVEL>1)
2078
err_printf("* conductor no %ld/%ld (N = %ld)\n\tInit: ", jc,ncond,N);
2079
2080
cScT.c1 = gel(C,jc);
2081
init_cScT(&cScT, gel(dataCR, LChar[1]), N, prec2);
2082
av2 = avma;
2083
for (k = 1; k <= nChar; k++)
2084
{
2085
long d, c, u = LChar[k];
2086
GEN dtcr = gel(dataCR, u), z, s, t;
2087
int **matan;
2088
2089
if (!ch_comp(dtcr)) continue;
2090
if (DEBUGLEVEL>1) err_printf("\tchar no: %ld (%ld/%ld)\n", u,k,nChar);
2091
z = gel(ch_CHI(dtcr), 2);
2092
d = ch_phideg(dtcr); s = t = gen_0;
2093
matan = ComputeCoeff(dtcr, &LIST, N, d);
2094
for (n = 1, c = 0; n <= N; n++)
2095
if ((an = EvalCoeff(z, matan[n], d)))
2096
{
2097
get_cS_cT(&cScT, n);
2098
s = gadd(s, gmul(an, gel(cScT.cS,n)));
2099
t = gadd(t, gmul(an, gel(cScT.cT,n)));
2100
if (++c == 256) { gerepileall(av2,2, &s,&t); c = 0; }
2101
}
2102
gaffect(s, gel(S,u));
2103
gaffect(conj_i(t), gel(T,u));
2104
FreeMat(matan, N); set_avma(av2);
2105
}
2106
if (DEBUGLEVEL>1) err_printf("\n");
2107
set_avma(av1);
2108
}
2109
clear_cScT(&cScT, n0);
2110
set_avma(av);
2111
}
2112
2113
static void
2114
GetST(GEN bnr, GEN *pS, GEN *pT, GEN CR, long prec)
2115
{
2116
if (nf_get_degree(bnr_get_nf(bnr)) == 2)
2117
QuadGetST(bnr, pS, pT, CR, prec);
2118
else
2119
GetST0(bnr, pS, pT, CR, prec);
2120
}
2121
2122
/*******************************************************************/
2123
/* */
2124
/* Class fields of real quadratic fields using Stark units */
2125
/* */
2126
/*******************************************************************/
2127
/* compute the Hilbert class field using genus class field theory when
2128
the exponent of the class group is exactly 2 (trivial group not covered) */
2129
/* Cf Herz, Construction of class fields, LNM 21, Theorem 1 (VII-6) */
2130
static GEN
2131
GenusFieldQuadReal(GEN disc)
2132
{
2133
long i, i0 = 0, l;
2134
pari_sp av = avma;
2135
GEN T = NULL, p0 = NULL, P;
2136
2137
P = gel(Z_factor(disc), 1);
2138
l = lg(P);
2139
for (i = 1; i < l; i++)
2140
{
2141
GEN p = gel(P,i);
2142
if (mod4(p) == 3) { p0 = p; i0 = i; break; }
2143
}
2144
l--; /* remove last prime */
2145
if (i0 == l) l--; /* ... remove p0 and last prime */
2146
for (i = 1; i < l; i++)
2147
{
2148
GEN p = gel(P,i), d, t;
2149
if (i == i0) continue;
2150
if (absequaliu(p, 2))
2151
switch (mod32(disc))
2152
{
2153
case 8: d = gen_2; break;
2154
case 24: d = shifti(p0, 1); break;
2155
default: d = p0; break;
2156
}
2157
else
2158
d = (mod4(p) == 1)? p: mulii(p0, p);
2159
t = mkpoln(3, gen_1, gen_0, negi(d)); /* x^2 - d */
2160
T = T? ZX_compositum_disjoint(T, t): t;
2161
}
2162
return gerepileupto(av, polredbest(T, 0));
2163
}
2164
static GEN
2165
GenusFieldQuadImag(GEN disc)
2166
{
2167
long i, l;
2168
pari_sp av = avma;
2169
GEN T = NULL, P;
2170
2171
P = gel(absZ_factor(disc), 1);
2172
l = lg(P);
2173
l--; /* remove last prime */
2174
for (i = 1; i < l; i++)
2175
{
2176
GEN p = gel(P,i), d, t;
2177
if (absequaliu(p, 2))
2178
switch (mod32(disc))
2179
{
2180
case 24: d = gen_2; break; /* disc = 8 mod 32 */
2181
case 8: d = gen_m2; break; /* disc =-8 mod 32 */
2182
default: d = gen_m1; break;
2183
}
2184
else
2185
d = (mod4(p) == 1)? p: negi(p);
2186
t = mkpoln(3, gen_1, gen_0, negi(d)); /* x^2 - d */
2187
T = T? ZX_compositum_disjoint(T, t): t;
2188
}
2189
return gerepileupto(av, polredbest(T, 0));
2190
}
2191
2192
/* if flag != 0, computes a fast and crude approximation of the result */
2193
static GEN
2194
AllStark(GEN data, long flag, long newprec)
2195
{
2196
const long BND = 300;
2197
long cl, i, j, cpt = 0, N, h, v, n, r1, r2, den;
2198
pari_sp av, av2;
2199
int **matan;
2200
GEN bnr = gel(data,1), nf = bnr_get_nf(bnr), p1, p2, S, T;
2201
GEN CR = gel(data,4), dataCR = gel(CR,2);
2202
GEN polrelnum, polrel, Lp, W, vzeta, C, cond1, L1, an;
2203
LISTray LIST;
2204
pari_timer ti;
2205
2206
nf_get_sign(nf, &r1,&r2);
2207
N = nf_get_degree(nf);
2208
cond1 = gel(bnr_get_mod(bnr), 2);
2209
2210
v = 1;
2211
while (gequal1(gel(cond1,v))) v++;
2212
cl = lg(dataCR)-1;
2213
h = itos(ZM_det_triangular(gel(data,2))) >> 1;
2214
2215
LABDOUB:
2216
if (DEBUGLEVEL) timer_start(&ti);
2217
av = avma;
2218
W = AllArtinNumbers(CR, newprec);
2219
if (DEBUGLEVEL) timer_printf(&ti,"Compute W");
2220
Lp = cgetg(cl + 1, t_VEC);
2221
if (!flag)
2222
{
2223
GetST(bnr, &S, &T, CR, newprec);
2224
if (DEBUGLEVEL) timer_printf(&ti, "S&T");
2225
for (i = 1; i <= cl; i++)
2226
{
2227
GEN chi = gel(dataCR, i), v = gen_0;
2228
if (ch_comp(chi))
2229
v = gel(GetValue(chi, gel(W,i), gel(S,i), gel(T,i), 2, newprec), 2);
2230
gel(Lp, i) = v;
2231
}
2232
}
2233
else
2234
{ /* compute a crude approximation of the result */
2235
C = cgetg(cl + 1, t_VEC);
2236
for (i = 1; i <= cl; i++) gel(C,i) = ch_C(gel(dataCR, i));
2237
n = zeta_get_N0(vecmax(C), zeta_get_limx(r1, r2, prec2nbits(newprec)));
2238
if (n > BND) n = BND;
2239
if (DEBUGLEVEL) err_printf("N0 in QuickPol: %ld \n", n);
2240
InitPrimes(bnr, n, &LIST);
2241
2242
L1 = cgetg(cl+1, t_VEC);
2243
/* use L(1) = sum (an / n) */
2244
for (i = 1; i <= cl; i++)
2245
{
2246
GEN dtcr = gel(dataCR,i);
2247
long d = ch_phideg(dtcr);
2248
matan = ComputeCoeff(dtcr, &LIST, n, d);
2249
av2 = avma;
2250
p1 = real_0(newprec); p2 = gel(ch_CHI(dtcr), 2);
2251
for (j = 1; j <= n; j++)
2252
if ( (an = EvalCoeff(p2, matan[j], d)) )
2253
p1 = gadd(p1, gdivgs(an, j));
2254
gel(L1,i) = gerepileupto(av2, p1);
2255
FreeMat(matan, n);
2256
}
2257
p1 = gmul2n(powruhalf(mppi(newprec), N-2), 1);
2258
2259
for (i = 1; i <= cl; i++)
2260
{
2261
long r;
2262
GEN WW, A = AChi(gel(dataCR,i), &r, 0, newprec);
2263
WW = gmul(gel(C,i), gmul(A, gel(W,i)));
2264
gel(Lp,i) = gdiv(gmul(WW, conj_i(gel(L1,i))), p1);
2265
}
2266
}
2267
2268
p1 = gel(data,3);
2269
den = flag ? h: 2*h;
2270
vzeta = cgetg(h + 1, t_VEC);
2271
for (i = 1; i <= h; i++)
2272
{
2273
GEN z = gen_0, sig = gel(p1,i);
2274
for (j = 1; j <= cl; j++)
2275
{
2276
GEN dtcr = gel(dataCR,j), CHI = ch_CHI(dtcr);
2277
GEN t = mulreal(gel(Lp,j), CharEval(CHI, sig));
2278
if (chi_get_deg(CHI) != 2) t = gmul2n(t, 1); /* character not real */
2279
z = gadd(z, t);
2280
}
2281
gel(vzeta,i) = gmul2n(gcosh(gdivgs(z,den), newprec), 1);
2282
}
2283
polrelnum = roots_to_pol(vzeta, 0);
2284
if (DEBUGLEVEL)
2285
{
2286
if (DEBUGLEVEL>1) {
2287
err_printf("polrelnum = %Ps\n", polrelnum);
2288
err_printf("zetavalues = %Ps\n", vzeta);
2289
if (!flag)
2290
err_printf("Checking the square-root of the Stark unit...\n");
2291
}
2292
timer_printf(&ti, "Compute %s", flag? "quickpol": "polrelnum");
2293
}
2294
if (flag) return gerepilecopy(av, polrelnum);
2295
2296
/* try to recognize this polynomial */
2297
polrel = RecCoeff(nf, polrelnum, v, newprec);
2298
if (!polrel)
2299
{
2300
for (j = 1; j <= h; j++)
2301
gel(vzeta,j) = gsubgs(gsqr(gel(vzeta,j)), 2);
2302
polrelnum = roots_to_pol(vzeta, 0);
2303
if (DEBUGLEVEL)
2304
{
2305
if (DEBUGLEVEL>1) {
2306
err_printf("It's not a square...\n");
2307
err_printf("polrelnum = %Ps\n", polrelnum);
2308
}
2309
timer_printf(&ti, "Compute polrelnum");
2310
}
2311
polrel = RecCoeff(nf, polrelnum, v, newprec);
2312
}
2313
if (!polrel) /* FAILED */
2314
{
2315
const long EXTRA_BITS = 64;
2316
long incr_pr;
2317
if (++cpt >= 3) pari_err_PREC( "stark (computation impossible)");
2318
/* estimate needed precision */
2319
incr_pr = prec2nbits(gprecision(polrelnum))- gexpo(polrelnum);
2320
if (incr_pr < 0) incr_pr = -incr_pr + EXTRA_BITS;
2321
newprec += nbits2extraprec(maxss(3*EXTRA_BITS, cpt*incr_pr));
2322
if (DEBUGLEVEL) pari_warn(warnprec, "AllStark", newprec);
2323
CharNewPrec(data, newprec);
2324
nf = bnr_get_nf(ch_bnr(gel(dataCR,1)));
2325
goto LABDOUB;
2326
}
2327
2328
if (DEBUGLEVEL) {
2329
if (DEBUGLEVEL>1) err_printf("polrel = %Ps\n", polrel);
2330
timer_printf(&ti, "Recpolnum");
2331
}
2332
return gerepilecopy(av, polrel);
2333
}
2334
2335
/********************************************************************/
2336
/* Main functions */
2337
/********************************************************************/
2338
static GEN
2339
bnrstark_cyclic(GEN bnr, GEN dtQ, long prec)
2340
{
2341
GEN v, vH, cyc = gel(dtQ,2), U = gel(dtQ,3), M = ZM_inv(U, NULL);
2342
long i, j, l = lg(M);
2343
2344
/* M = indep. generators of Cl_f/subgp, restrict to cyclic components */
2345
vH = cgetg(l, t_VEC);
2346
for (i = j = 1; i < l; i++)
2347
{
2348
if (is_pm1(gel(cyc,i))) break;
2349
gel(vH, j++) = ZM_hnfmodid(vecsplice(M,i), cyc);
2350
}
2351
setlg(vH, j); v = cgetg(l, t_VEC);
2352
for (i = 1; i < j; i++) gel(v,i) = bnrstark(bnr, gel(vH,i), prec);
2353
return v;
2354
}
2355
GEN
2356
bnrstark(GEN bnr, GEN subgrp, long prec)
2357
{
2358
long newprec;
2359
pari_sp av = avma;
2360
GEN nf, data, dtQ;
2361
2362
/* check the bnr */
2363
checkbnr(bnr); nf = bnr_get_nf(bnr);
2364
if (nf_get_degree(nf) == 1) return galoissubcyclo(bnr, subgrp, 0, 0);
2365
if (!nf_get_varn(nf))
2366
pari_err_PRIORITY("bnrstark", nf_get_pol(nf), "=", 0);
2367
if (nf_get_r2(nf)) pari_err_DOMAIN("bnrstark", "r2", "!=", gen_0, nf);
2368
2369
/* compute bnr(conductor) */
2370
bnr_subgroup_sanitize(&bnr, &subgrp);
2371
if (gequal1(ZM_det_triangular(subgrp))) { set_avma(av); return pol_x(0); }
2372
2373
/* check the class field */
2374
if (!gequal0(gel(bnr_get_mod(bnr), 2)))
2375
pari_err_DOMAIN("bnrstark", "r2(class field)", "!=", gen_0, bnr);
2376
2377
/* find a suitable extension N */
2378
dtQ = InitQuotient(subgrp);
2379
data = FindModulus(bnr, dtQ, &newprec);
2380
if (!data) return gerepileupto(av, bnrstark_cyclic(bnr, dtQ, prec));
2381
if (DEBUGLEVEL>1 && newprec > prec)
2382
err_printf("new precision: %ld\n", newprec);
2383
return gerepileupto(av, AllStark(data, 0, newprec));
2384
}
2385
2386
/* For each character of Cl(bnr)/subgp, compute L(1, chi) (or equivalently
2387
* the first nonzero term c(chi) of the expansion at s = 0).
2388
* If flag & 1: compute the value at s = 1 (for nontrivial characters),
2389
* else compute the term c(chi) and return [r(chi), c(chi)] where r(chi) is
2390
* the order of L(s, chi) at s = 0.
2391
* If flag & 2: compute the value of the L-function L_S(s, chi) where S is the
2392
* set of places dividing the modulus of bnr (and the infinite places),
2393
* else
2394
* compute the value of the primitive L-function attached to chi,
2395
* If flag & 4: return also the character */
2396
GEN
2397
bnrL1(GEN bnr, GEN subgp, long flag, long prec)
2398
{
2399
GEN L1, ch, Qt, z;
2400
long l, h;
2401
pari_sp av = avma;
2402
2403
checkbnr(bnr);
2404
if (flag < 0 || flag > 8) pari_err_FLAG("bnrL1");
2405
2406
subgp = bnr_subgroup_check(bnr, subgp, NULL);
2407
if (!subgp) subgp = diagonal_shallow(bnr_get_cyc(bnr));
2408
2409
Qt = InitQuotient(subgp);
2410
ch = AllChars(bnr, Qt, 0); l = lg(ch);
2411
h = itou(gel(Qt,1));
2412
L1 = cgetg((flag&1)? h: h+1, t_VEC);
2413
if (l > 1)
2414
{
2415
GEN W, S, T, CR = InitChar(bnr, ch, 1, prec), dataCR = gel(CR,2);
2416
long i, j;
2417
2418
GetST(bnr, &S, &T, CR, prec);
2419
W = AllArtinNumbers(CR, prec);
2420
for (i = j = 1; i < l; i++)
2421
{
2422
GEN chi = gel(ch,i);
2423
z = GetValue(gel(dataCR,i), gel(W,i), gel(S,i), gel(T,i), flag, prec);
2424
gel(L1,j++) = (flag & 4)? mkvec2(gel(chi,1), z): z;
2425
if (lg(chi) == 4)
2426
{ /* nonreal */
2427
z = conj_i(z);
2428
gel(L1, j++) = (flag & 4)? mkvec2(gel(chi,3), z): z;
2429
}
2430
}
2431
}
2432
if (!(flag & 1))
2433
{ /* trivial character */
2434
z = GetValue1(bnr, flag & 2, prec);
2435
if (flag & 4)
2436
{
2437
GEN chi = zerovec(lg(bnr_get_cyc(bnr))-1);
2438
z = mkvec2(chi, z);
2439
}
2440
gel(L1,h) = z;
2441
}
2442
return gerepilecopy(av, L1);
2443
}
2444
2445
/*******************************************************************/
2446
/* */
2447
/* Hilbert and Ray Class field using Stark */
2448
/* */
2449
/*******************************************************************/
2450
/* P in A[x,y], deg_y P < 2, return P0 and P1 in A[x] such that P = P0 + P1 y */
2451
static void
2452
split_pol_quad(GEN P, GEN *gP0, GEN *gP1)
2453
{
2454
long i, l = lg(P);
2455
GEN P0 = cgetg(l, t_POL), P1 = cgetg(l, t_POL);
2456
P0[1] = P1[1] = P[1];
2457
for (i = 2; i < l; i++)
2458
{
2459
GEN c = gel(P,i), c0 = c, c1 = gen_0;
2460
if (typ(c) == t_POL) /* write c = c1 y + c0 */
2461
switch(degpol(c))
2462
{
2463
case -1: c0 = gen_0; break;
2464
default: c1 = gel(c,3); /* fall through */
2465
case 0: c0 = gel(c,2); break;
2466
}
2467
gel(P0,i) = c0; gel(P1,i) = c1;
2468
}
2469
*gP0 = normalizepol_lg(P0, l);
2470
*gP1 = normalizepol_lg(P1, l);
2471
}
2472
2473
/* k = nf quadratic field, P relative equation of H_k (Hilbert class field)
2474
* return T in Z[X], such that H_k / Q is the compositum of Q[X]/(T) and k */
2475
static GEN
2476
makescind(GEN nf, GEN P)
2477
{
2478
GEN Pp, p, pol, G, L, a, roo, P0,P1, Ny,Try, nfpol = nf_get_pol(nf);
2479
long i, is_P;
2480
2481
P = lift_shallow(P);
2482
split_pol_quad(P, &P0, &P1);
2483
/* P = P0 + y P1, Norm_{k/Q}(P) = P0^2 + Tr y P0P1 + Ny P1^2, irreducible/Q */
2484
Ny = gel(nfpol, 2);
2485
Try = negi(gel(nfpol, 3));
2486
pol = RgX_add(RgX_sqr(P0), RgX_Rg_mul(RgX_sqr(P1), Ny));
2487
if (signe(Try)) pol = RgX_add(pol, RgX_Rg_mul(RgX_mul(P0,P1), Try));
2488
/* pol = rnfequation(nf, P); */
2489
G = galoisinit(pol, NULL);
2490
L = gal_get_group(G);
2491
p = gal_get_p(G);
2492
a = FpX_oneroot(nfpol, p);
2493
/* P mod a prime \wp above p (which splits) */
2494
Pp = FpXY_evalx(P, a, p);
2495
roo = gal_get_roots(G);
2496
is_P = gequal0( FpX_eval(Pp, remii(gel(roo,1),p), p) );
2497
/* each roo[i] mod p is a root of P or (exclusive) tau(P) mod \wp */
2498
/* record whether roo[1] is a root of P or tau(P) */
2499
2500
for (i = 1; i < lg(L); i++)
2501
{
2502
GEN perm = gel(L,i);
2503
long k = perm[1]; if (k == 1) continue;
2504
k = gequal0( FpX_eval(Pp, remii(gel(roo,k),p), p) );
2505
/* roo[k] is a root of the other polynomial */
2506
if (k != is_P)
2507
{
2508
ulong o = perm_orderu(perm);
2509
if (o != 2) perm = perm_powu(perm, o >> 1);
2510
/* perm has order two and doesn't belong to Gal(H_k/k) */
2511
return galoisfixedfield(G, perm, 1, varn(P));
2512
}
2513
}
2514
pari_err_BUG("makescind");
2515
return NULL; /*LCOV_EXCL_LINE*/
2516
}
2517
2518
/* pbnf = NULL if no bnf is needed, f = NULL may be passed for a trivial
2519
* conductor */
2520
static void
2521
quadray_init(GEN *pD, GEN f, GEN *pbnf, long prec)
2522
{
2523
GEN D = *pD, nf, bnf = NULL;
2524
if (typ(D) == t_INT)
2525
{
2526
int isfund;
2527
if (pbnf) {
2528
long v = f? gvar(f): NO_VARIABLE;
2529
if (v == NO_VARIABLE) v = 1;
2530
bnf = Buchall(quadpoly0(D, v), nf_FORCE, prec);
2531
nf = bnf_get_nf(bnf);
2532
isfund = equalii(D, nf_get_disc(nf));
2533
}
2534
else
2535
isfund = Z_isfundamental(D);
2536
if (!isfund) pari_err_DOMAIN("quadray", "isfundamental(D)", "=",gen_0, D);
2537
}
2538
else
2539
{
2540
bnf = checkbnf(D);
2541
nf = bnf_get_nf(bnf);
2542
if (nf_get_degree(nf) != 2)
2543
pari_err_DOMAIN("quadray", "degree", "!=", gen_2, nf_get_pol(nf));
2544
D = nf_get_disc(nf);
2545
}
2546
if (pbnf) *pbnf = bnf;
2547
*pD = D;
2548
}
2549
2550
/* compute the polynomial over Q of the Hilbert class field of
2551
Q(sqrt(D)) where D is a positive fundamental discriminant */
2552
static GEN
2553
quadhilbertreal(GEN D, long prec)
2554
{
2555
pari_sp av = avma;
2556
GEN bnf, pol, bnr, dtQ, data, M;
2557
long newprec;
2558
pari_timer T;
2559
2560
quadray_init(&D, NULL, &bnf, prec);
2561
switch(itou_or_0(cyc_get_expo(bnf_get_cyc(bnf))))
2562
{
2563
case 1: set_avma(av); return pol_x(0);
2564
case 2: return gerepileupto(av, GenusFieldQuadReal(D));
2565
}
2566
bnr = Buchray(bnf, gen_1, nf_INIT);
2567
M = diagonal_shallow(bnr_get_cyc(bnr));
2568
dtQ = InitQuotient(M);
2569
2570
if (DEBUGLEVEL) timer_start(&T);
2571
data = FindModulus(bnr, dtQ, &newprec);
2572
if (DEBUGLEVEL) timer_printf(&T,"FindModulus");
2573
if (!data) return gerepileupto(av, bnrstark_cyclic(bnr, dtQ, prec));
2574
pol = AllStark(data, 0, newprec);
2575
pol = makescind(bnf_get_nf(bnf), pol);
2576
return gerepileupto(av, polredbest(pol, 0));
2577
}
2578
2579
/*******************************************************************/
2580
/* */
2581
/* Hilbert and Ray Class field using CM (Schertz) */
2582
/* */
2583
/*******************************************************************/
2584
/* form^2 = 1 ? */
2585
static int
2586
hasexp2(GEN form)
2587
{
2588
GEN a = gel(form,1), b = gel(form,2), c = gel(form,3);
2589
return !signe(b) || absequalii(a,b) || equalii(a,c);
2590
}
2591
static int
2592
uhasexp2(GEN form)
2593
{
2594
long a = form[1], b = form[2], c = form[3];
2595
return !b || a == labs(b) || a == c;
2596
}
2597
2598
GEN
2599
qfbforms(GEN D)
2600
{
2601
ulong d = itou(D), dover3 = d/3, t, b2, a, b, c, h;
2602
GEN L = cgetg((long)(sqrt((double)d) * log2(d)), t_VEC);
2603
b2 = b = (d&1); h = 0;
2604
if (!b) /* b = 0 treated separately to avoid special cases */
2605
{
2606
t = d >> 2; /* (b^2 - D) / 4*/
2607
for (a=1; a*a<=t; a++)
2608
if (c = t/a, t == c*a) gel(L,++h) = mkvecsmall3(a,0,c);
2609
b = 2; b2 = 4;
2610
}
2611
/* now b > 0, b = D (mod 2) */
2612
for ( ; b2 <= dover3; b += 2, b2 = b*b)
2613
{
2614
t = (b2 + d) >> 2; /* (b^2 - D) / 4*/
2615
/* b = a */
2616
if (c = t/b, t == c*b) gel(L,++h) = mkvecsmall3(b,b,c);
2617
/* b < a < c */
2618
for (a = b+1; a*a < t; a++)
2619
if (c = t/a, t == c*a)
2620
{
2621
gel(L,++h) = mkvecsmall3(a, b,c);
2622
gel(L,++h) = mkvecsmall3(a,-b,c);
2623
}
2624
/* a = c */
2625
if (a * a == t) gel(L,++h) = mkvecsmall3(a,b,a);
2626
}
2627
setlg(L,h+1); return L;
2628
}
2629
2630
/* gcd(n, 24) */
2631
static long
2632
GCD24(long n)
2633
{
2634
switch(n % 24)
2635
{
2636
case 0: return 24;
2637
case 1: return 1;
2638
case 2: return 2;
2639
case 3: return 3;
2640
case 4: return 4;
2641
case 5: return 1;
2642
case 6: return 6;
2643
case 7: return 1;
2644
case 8: return 8;
2645
case 9: return 3;
2646
case 10: return 2;
2647
case 11: return 1;
2648
case 12: return 12;
2649
case 13: return 1;
2650
case 14: return 2;
2651
case 15: return 3;
2652
case 16: return 8;
2653
case 17: return 1;
2654
case 18: return 6;
2655
case 19: return 1;
2656
case 20: return 4;
2657
case 21: return 3;
2658
case 22: return 2;
2659
case 23: return 1;
2660
default: return 0;
2661
}
2662
}
2663
2664
struct gpq_data {
2665
long p, q;
2666
GEN sqd; /* sqrt(D), t_REAL */
2667
GEN u, D;
2668
GEN pq, pq2; /* p*q, 2*p*q */
2669
GEN qfpq ; /* class of \P * \Q */
2670
};
2671
2672
/* find P and Q two non principal prime ideals (above p <= q) such that
2673
* cl(P) = cl(Q) if P,Q have order 2 in Cl(K).
2674
* Ensure that e = 24 / gcd(24, (p-1)(q-1)) = 1 */
2675
/* D t_INT, discriminant */
2676
static void
2677
init_pq(GEN D, struct gpq_data *T)
2678
{
2679
const long Np = 6547; /* N.B. primepi(50000) = 5133 */
2680
const ulong maxq = 50000;
2681
GEN listp = cgetg(Np + 1, t_VECSMALL); /* primes p */
2682
GEN listP = cgetg(Np + 1, t_VEC); /* primeform(p) if of order 2, else NULL */
2683
GEN gcd24 = cgetg(Np + 1, t_VECSMALL); /* gcd(p-1, 24) */
2684
forprime_t S;
2685
long l = 1;
2686
double best = 0.;
2687
ulong q;
2688
2689
u_forprime_init(&S, 2, ULONG_MAX);
2690
T->D = D;
2691
T->p = T->q = 0;
2692
for(;;)
2693
{
2694
GEN Q;
2695
long i, gcdq, mod;
2696
int order2, store;
2697
double t;
2698
2699
q = u_forprime_next(&S);
2700
if (best > 0 && q >= maxq)
2701
{
2702
if (DEBUGLEVEL)
2703
pari_warn(warner,"possibly suboptimal (p,q) for D = %Ps", D);
2704
break;
2705
}
2706
if (kroiu(D, q) < 0) continue; /* inert */
2707
Q = qfbred_i(primeform_u(D, q));
2708
if (is_pm1(gel(Q,1))) continue; /* Q | q is principal */
2709
2710
store = 1;
2711
order2 = hasexp2(Q);
2712
gcd24[l] = gcdq = GCD24(q-1);
2713
mod = 24 / gcdq; /* mod must divide p-1 otherwise e > 1 */
2714
listp[l] = q;
2715
gel(listP,l) = order2 ? Q : NULL;
2716
t = (q+1)/(double)(q-1);
2717
for (i = 1; i < l; i++) /* try all (p, q), p < q in listp */
2718
{
2719
long p = listp[i], gcdp = gcd24[i];
2720
double b;
2721
/* P,Q order 2 => cl(Q) = cl(P) */
2722
if (order2 && gel(listP,i) && !gequal(gel(listP,i), Q)) continue;
2723
if (gcdp % gcdq == 0) store = 0; /* already a better one in the list */
2724
if ((p-1) % mod) continue;
2725
2726
b = (t*(p+1)) / (p-1); /* (p+1)(q+1) / (p-1)(q-1) */
2727
if (b > best) {
2728
store = 0; /* (p,q) always better than (q,r) for r >= q */
2729
best = b; T->q = q; T->p = p;
2730
if (DEBUGLEVEL>2) err_printf("p,q = %ld,%ld\n", p, q);
2731
}
2732
/* won't improve with this q as largest member */
2733
if (best > 0) break;
2734
}
2735
/* if !store or (q,r) won't improve on current best pair, forget that q */
2736
if (store && t*t > best)
2737
if (++l >= Np) pari_err_BUG("quadhilbert (not enough primes)");
2738
if (!best) /* (p,q) with p < q always better than (q,q) */
2739
{ /* try (q,q) */
2740
if (gcdq >= 12 && umodiu(D, q)) /* e = 1 and unramified */
2741
{
2742
double b = (t*q) / (q-1); /* q(q+1) / (q-1)^2 */
2743
if (b > best) {
2744
best = b; T->q = T->p = q;
2745
if (DEBUGLEVEL>2) err_printf("p,q = %ld,%ld\n", q, q);
2746
}
2747
}
2748
}
2749
/* If (p1+1)(q+1) / (p1-1)(q-1) <= best, we can no longer improve
2750
* even with best p : stop */
2751
if ((listp[1]+1)*t <= (listp[1]-1)*best) break;
2752
}
2753
if (DEBUGLEVEL>1)
2754
err_printf("(p, q) = %ld, %ld; gain = %f\n", T->p, T->q, 12*best);
2755
}
2756
2757
static GEN
2758
gpq(GEN form, struct gpq_data *T)
2759
{
2760
pari_sp av = avma;
2761
long a = form[1], b = form[2], c = form[3], p = T->p, q = T->q;
2762
GEN form2, w, z;
2763
int fl, real = 0;
2764
2765
form2 = qfbcomp_i(T->qfpq, mkqfb(stoi(a), stoi(-b), stoi(c), T->D));
2766
/* form2 and form yield complex conjugate roots : only compute for the
2767
* lexicographically smallest of the 2 */
2768
fl = cmpis(gel(form2,1), a);
2769
if (fl <= 0)
2770
{
2771
if (fl < 0) return NULL;
2772
fl = cmpis(gel(form2,2), b);
2773
if (fl <= 0)
2774
{
2775
if (fl < 0) return NULL;
2776
/* form == form2 : real root */
2777
real = 1;
2778
}
2779
}
2780
2781
if (p == 2) { /* (a,b,c) = (1,1,0) mod 2 ? */
2782
if (a % q == 0 && (a & b & 1) && !(c & 1))
2783
{ /* apply S : make sure that (a,b,c) represents odd values */
2784
lswap(a,c); b = -b;
2785
}
2786
}
2787
if (a % p == 0 || a % q == 0)
2788
{ /* apply T^k, look for c' = a k^2 + b k + c coprime to N */
2789
while (c % p == 0 || c % q == 0)
2790
{
2791
c += a + b;
2792
b += a << 1;
2793
}
2794
lswap(a, c); b = -b; /* apply S */
2795
}
2796
/* now (a,b,c) ~ form and (a,pq) = 1 */
2797
2798
/* gcd(2a, u) = 2, w = u mod 2pq, -b mod 2a */
2799
w = Z_chinese(T->u, stoi(-b), T->pq2, utoipos(a << 1));
2800
z = double_eta_quotient(utoipos(a), w, T->D, T->p, T->q, T->pq, T->sqd);
2801
if (real && typ(z) == t_COMPLEX) z = gcopy(gel(z, 1));
2802
return gerepileupto(av, z);
2803
}
2804
2805
/* returns an equation for the Hilbert class field of Q(sqrt(D)), D < 0
2806
* fundamental discriminant */
2807
static GEN
2808
quadhilbertimag(GEN D)
2809
{
2810
GEN L, P, Pi, Pr, qfp, u;
2811
pari_sp av = avma;
2812
long h, i, prec;
2813
struct gpq_data T;
2814
pari_timer ti;
2815
2816
if (DEBUGLEVEL>1) timer_start(&ti);
2817
if (lgefint(D) == 3)
2818
switch (D[2]) { /* = |D|; special cases where e > 1 */
2819
case 3:
2820
case 4:
2821
case 7:
2822
case 8:
2823
case 11:
2824
case 19:
2825
case 43:
2826
case 67:
2827
case 163: return pol_x(0);
2828
}
2829
L = qfbforms(D);
2830
h = lg(L)-1;
2831
if ((1L << vals(h)) == h) /* power of 2 */
2832
{ /* check whether > |Cl|/2 elements have order <= 2 ==> 2-elementary */
2833
long lim = (h>>1) + 1;
2834
for (i=1; i <= lim; i++)
2835
if (!uhasexp2(gel(L,i))) break;
2836
if (i > lim) return GenusFieldQuadImag(D);
2837
}
2838
if (DEBUGLEVEL>1) timer_printf(&ti,"class number = %ld",h);
2839
init_pq(D, &T);
2840
qfp = primeform_u(D, T.p);
2841
T.pq = muluu(T.p, T.q);
2842
T.pq2 = shifti(T.pq,1);
2843
if (T.p == T.q)
2844
{
2845
GEN qfbp2 = qfbcompraw(qfp, qfp);
2846
u = gel(qfbp2,2);
2847
T.u = modii(u, T.pq2);
2848
T.qfpq = qfbred_i(qfbp2);
2849
}
2850
else
2851
{
2852
GEN qfq = primeform_u(D, T.q), bp = gel(qfp,2), bq = gel(qfq,2);
2853
T.u = Z_chinese(bp, bq, utoipos(T.p << 1), utoipos(T.q << 1));
2854
/* T.u = bp (mod 2p), T.u = bq (mod 2q) */
2855
T.qfpq = qfbcomp_i(qfp, qfq);
2856
}
2857
/* u modulo 2pq */
2858
prec = LOWDEFAULTPREC;
2859
Pr = cgetg(h+1,t_VEC);
2860
Pi = cgetg(h+1,t_VEC);
2861
for(;;)
2862
{
2863
long ex, exmax = 0, r1 = 0, r2 = 0;
2864
pari_sp av0 = avma;
2865
T.sqd = sqrtr_abs(itor(D, prec));
2866
for (i=1; i<=h; i++)
2867
{
2868
GEN s = gpq(gel(L,i), &T);
2869
if (DEBUGLEVEL>3) err_printf("%ld ", i);
2870
if (!s) continue;
2871
if (typ(s) != t_COMPLEX) gel(Pr, ++r1) = s; /* real root */
2872
else gel(Pi, ++r2) = s;
2873
ex = gexpo(s); if (ex > 0) exmax += ex;
2874
}
2875
if (DEBUGLEVEL>1) timer_printf(&ti,"roots");
2876
setlg(Pr, r1+1);
2877
setlg(Pi, r2+1);
2878
P = roots_to_pol_r1(shallowconcat(Pr,Pi), 0, r1);
2879
P = grndtoi(P,&exmax);
2880
if (DEBUGLEVEL>1) timer_printf(&ti,"product, error bits = %ld",exmax);
2881
if (exmax <= -10) break;
2882
set_avma(av0); prec += nbits2extraprec(prec2nbits(DEFAULTPREC)+exmax);
2883
if (DEBUGLEVEL) pari_warn(warnprec,"quadhilbertimag",prec);
2884
}
2885
return gerepileupto(av,P);
2886
}
2887
2888
GEN
2889
quadhilbert(GEN D, long prec)
2890
{
2891
GEN d = D;
2892
quadray_init(&d, NULL, NULL, 0);
2893
return (signe(d)>0)? quadhilbertreal(D,prec)
2894
: quadhilbertimag(d);
2895
}
2896
2897
/* return a vector of all roots of 1 in bnf [not necessarily quadratic] */
2898
static GEN
2899
getallrootsof1(GEN bnf)
2900
{
2901
GEN T, u, nf = bnf_get_nf(bnf), tu;
2902
long i, n = bnf_get_tuN(bnf);
2903
2904
if (n == 2) {
2905
long N = nf_get_degree(nf);
2906
return mkvec2(scalarcol_shallow(gen_m1, N),
2907
scalarcol_shallow(gen_1, N));
2908
}
2909
tu = poltobasis(nf, bnf_get_tuU(bnf));
2910
T = zk_multable(nf, tu);
2911
u = cgetg(n+1, t_VEC); gel(u,1) = tu;
2912
for (i=2; i <= n; i++) gel(u,i) = ZM_ZC_mul(T, gel(u,i-1));
2913
return u;
2914
}
2915
/* assume bnr has the right conductor */
2916
static GEN
2917
get_lambda(GEN bnr)
2918
{
2919
GEN bnf = bnr_get_bnf(bnr), nf = bnf_get_nf(bnf), pol = nf_get_pol(nf);
2920
GEN f = gel(bnr_get_mod(bnr), 1), labas, lamodf, u;
2921
long a, b, f2, i, lu, v = varn(pol);
2922
2923
f2 = 2 * itos(gcoeff(f,1,1));
2924
u = getallrootsof1(bnf); lu = lg(u);
2925
for (i=1; i<lu; i++)
2926
gel(u,i) = ZC_hnfrem(gel(u,i), f); /* roots of 1, mod f */
2927
if (DEBUGLEVEL>1)
2928
err_printf("quadray: looking for [a,b] != unit mod 2f\n[a,b] = ");
2929
for (a=0; a<f2; a++)
2930
for (b=0; b<f2; b++)
2931
{
2932
GEN la = deg1pol_shallow(stoi(a), stoi(b), v); /* ax + b */
2933
if (umodiu(gnorm(mkpolmod(la, pol)), f2) != 1) continue;
2934
if (DEBUGLEVEL>1) err_printf("[%ld,%ld] ",a,b);
2935
2936
labas = poltobasis(nf, la);
2937
lamodf = ZC_hnfrem(labas, f);
2938
for (i=1; i<lu; i++)
2939
if (ZV_equal(lamodf, gel(u,i))) break;
2940
if (i < lu) continue; /* la = unit mod f */
2941
if (DEBUGLEVEL)
2942
{
2943
if (DEBUGLEVEL>1) err_printf("\n");
2944
err_printf("lambda = %Ps\n",la);
2945
}
2946
return labas;
2947
}
2948
pari_err_BUG("get_lambda");
2949
return NULL;/*LCOV_EXCL_LINE*/
2950
}
2951
2952
static GEN
2953
to_approx(GEN nf, GEN a)
2954
{
2955
GEN M = nf_get_M(nf);
2956
return gadd(gel(a,1), gmul(gcoeff(M,1,2),gel(a,2)));
2957
}
2958
/* Z-basis for a (over C) */
2959
static GEN
2960
get_om(GEN nf, GEN a) {
2961
return mkvec2(to_approx(nf,gel(a,2)),
2962
to_approx(nf,gel(a,1)));
2963
}
2964
2965
/* Compute all elts in class group G = [|G|,c,g], c=cyclic factors, g=gens.
2966
* Set list[j + 1] = g1^e1...gk^ek where j is the integer
2967
* ek + ck [ e(k-1) + c(k-1) [... + c2 [e1]]...] */
2968
static GEN
2969
getallelts(GEN bnr)
2970
{
2971
GEN nf, C, c, g, list, pows, gk;
2972
long lc, i, j, no;
2973
2974
nf = bnr_get_nf(bnr);
2975
no = itos( bnr_get_no(bnr) );
2976
c = bnr_get_cyc(bnr);
2977
g = bnr_get_gen_nocheck(bnr); lc = lg(c)-1;
2978
list = cgetg(no+1,t_VEC);
2979
gel(list,1) = matid(nf_get_degree(nf)); /* (1) */
2980
if (!no) return list;
2981
2982
pows = cgetg(lc+1,t_VEC);
2983
c = leafcopy(c); settyp(c, t_VECSMALL);
2984
for (i=1; i<=lc; i++)
2985
{
2986
long k = itos(gel(c,i));
2987
c[i] = k;
2988
gk = cgetg(k, t_VEC); gel(gk,1) = gel(g,i);
2989
for (j=2; j<k; j++)
2990
gel(gk,j) = idealmoddivisor(bnr, idealmul(nf, gel(gk,j-1), gel(gk,1)));
2991
gel(pows,i) = gk; /* powers of g[i] */
2992
}
2993
2994
C = cgetg(lc+1, t_VECSMALL); C[1] = c[lc];
2995
for (i=2; i<=lc; i++) C[i] = C[i-1] * c[lc-i+1];
2996
/* C[i] = c(k-i+1) * ... * ck */
2997
/* j < C[i+1] <==> j only involves g(k-i)...gk */
2998
i = 1;
2999
for (j=1; j < C[1]; j++)
3000
gel(list, j+1) = gmael(pows,lc,j);
3001
while(j<no)
3002
{
3003
long k;
3004
GEN a;
3005
if (j == C[i+1]) i++;
3006
a = gmael(pows,lc-i,j/C[i]);
3007
k = j%C[i] + 1;
3008
if (k > 1) a = idealmoddivisor(bnr, idealmul(nf, a, gel(list,k)));
3009
gel(list, ++j) = a;
3010
}
3011
return list;
3012
}
3013
3014
/* x quadratic integer (approximate), recognize it. If error return NULL */
3015
static GEN
3016
findbezk(GEN nf, GEN x)
3017
{
3018
GEN a,b, M = nf_get_M(nf), u = gcoeff(M,1,2);
3019
long ea, eb;
3020
3021
/* u t_COMPLEX generator of nf.zk, write x ~ a + b u, a,b in Z */
3022
b = grndtoi(mpdiv(imag_i(x), gel(u,2)), &eb);
3023
if (eb > -20) return NULL;
3024
a = grndtoi(mpsub(real_i(x), mpmul(b,gel(u,1))), &ea);
3025
if (ea > -20) return NULL;
3026
return signe(b)? coltoalg(nf, mkcol2(a,b)): a;
3027
}
3028
3029
static GEN
3030
findbezk_pol(GEN nf, GEN x)
3031
{
3032
long i, lx = lg(x);
3033
GEN y = cgetg(lx,t_POL);
3034
for (i=2; i<lx; i++)
3035
if (! (gel(y,i) = findbezk(nf,gel(x,i))) ) return NULL;
3036
y[1] = x[1]; return y;
3037
}
3038
3039
/* P approximation computed at initial precision prec. Compute needed prec
3040
* to know P with 1 word worth of trailing decimals */
3041
static long
3042
get_prec(GEN P, long prec)
3043
{
3044
long k = gprecision(P);
3045
if (k == 3) return precdbl(prec); /* approximation not trustworthy */
3046
k = prec - k; /* lost precision when computing P */
3047
if (k < 0) k = 0;
3048
k += nbits2prec(gexpo(P) + 128);
3049
if (k <= prec) k = precdbl(prec); /* dubious: old prec should have worked */
3050
return k;
3051
}
3052
3053
/* Compute data for ellphist */
3054
static GEN
3055
ellphistinit(GEN om, long prec)
3056
{
3057
GEN res,om1b,om2b, om1 = gel(om,1), om2 = gel(om,2);
3058
3059
if (gsigne(imag_i(gdiv(om1,om2))) < 0) { swap(om1,om2); om = mkvec2(om1,om2); }
3060
om1b = conj_i(om1);
3061
om2b = conj_i(om2); res = cgetg(4,t_VEC);
3062
gel(res,1) = gdivgs(elleisnum(om,2,0,prec),12);
3063
gel(res,2) = gdiv(PiI2(prec), gmul(om2, imag_i(gmul(om1b,om2))));
3064
gel(res,3) = om2b; return res;
3065
}
3066
3067
/* Computes log(phi^*(z,om)), using res computed by ellphistinit */
3068
static GEN
3069
ellphist(GEN om, GEN res, GEN z, long prec)
3070
{
3071
GEN u = imag_i(gmul(z, gel(res,3)));
3072
GEN zst = gsub(gmul(u, gel(res,2)), gmul(z,gel(res,1)));
3073
return gsub(ellsigma(om,z,1,prec),gmul2n(gmul(z,zst),-1));
3074
}
3075
3076
/* Computes phi^*(la,om)/phi^*(1,om) where (1,om) is an oriented basis of the
3077
ideal gf*gc^{-1} */
3078
static GEN
3079
computeth2(GEN om, GEN la, long prec)
3080
{
3081
GEN p1,p2,res = ellphistinit(om,prec);
3082
3083
p1 = gsub(ellphist(om,res,la,prec), ellphist(om,res,gen_1,prec));
3084
p2 = imag_i(p1);
3085
if (gexpo(real_i(p1))>20 || gexpo(p2)> prec2nbits(minss(prec,realprec(p2)))-10)
3086
return NULL;
3087
return gexp(p1,prec);
3088
}
3089
3090
/* Computes P_2(X)=polynomial in Z_K[X] closest to prod_gc(X-th2(gc)) where
3091
the product is over the ray class group bnr.*/
3092
static GEN
3093
computeP2(GEN bnr, long prec)
3094
{
3095
long clrayno, i, first = 1;
3096
pari_sp av=avma, av2;
3097
GEN listray, P0, P, lanum, la = get_lambda(bnr);
3098
GEN nf = bnr_get_nf(bnr), f = gel(bnr_get_mod(bnr), 1);
3099
listray = getallelts(bnr);
3100
clrayno = lg(listray)-1; av2 = avma;
3101
PRECPB:
3102
if (!first)
3103
{
3104
if (DEBUGLEVEL) pari_warn(warnprec,"computeP2",prec);
3105
nf = gerepilecopy(av2, nfnewprec_shallow(checknf(bnr),prec));
3106
}
3107
first = 0; lanum = to_approx(nf,la);
3108
P = cgetg(clrayno+1,t_VEC);
3109
for (i=1; i<=clrayno; i++)
3110
{
3111
GEN om = get_om(nf, idealdiv(nf,f,gel(listray,i)));
3112
GEN s = computeth2(om,lanum,prec);
3113
if (!s) { prec = precdbl(prec); goto PRECPB; }
3114
gel(P,i) = s;
3115
}
3116
P0 = roots_to_pol(P, 0);
3117
P = findbezk_pol(nf, P0);
3118
if (!P) { prec = get_prec(P0, prec); goto PRECPB; }
3119
return gerepilecopy(av, P);
3120
}
3121
3122
#define nexta(a) (a>0 ? -a : 1-a)
3123
static GEN
3124
do_compo(GEN A0, GEN B)
3125
{
3126
long a, i, l = lg(B), v = fetch_var_higher();
3127
GEN A, z;
3128
/* now v > x = pol_x(0) > nf variable */
3129
B = leafcopy(B); setvarn(B, v);
3130
for (i = 2; i < l; i++) gel(B,i) = monomial(gel(B,i), l-i-1, 0);
3131
/* B := x^deg(B) B(v/x) */
3132
A = A0 = leafcopy(A0); setvarn(A0, v);
3133
for (a = 0;; a = nexta(a))
3134
{
3135
if (a) A = RgX_translate(A0, stoi(a));
3136
z = resultant(A,B); /* in variable 0 */
3137
if (issquarefree(z)) break;
3138
}
3139
(void)delete_var(); return z;
3140
}
3141
#undef nexta
3142
3143
static GEN
3144
galoisapplypol(GEN nf, GEN s, GEN x)
3145
{
3146
long i, lx = lg(x);
3147
GEN y = cgetg(lx,t_POL);
3148
3149
for (i=2; i<lx; i++) gel(y,i) = galoisapply(nf,s,gel(x,i));
3150
y[1] = x[1]; return y;
3151
}
3152
/* x quadratic, write it as ua + v, u,v rational */
3153
static GEN
3154
findquad(GEN a, GEN x, GEN p)
3155
{
3156
long tu, tv;
3157
pari_sp av = avma;
3158
GEN u,v;
3159
if (typ(x) == t_POLMOD) x = gel(x,2);
3160
if (typ(a) == t_POLMOD) a = gel(a,2);
3161
u = poldivrem(x, a, &v);
3162
u = simplify_shallow(u); tu = typ(u);
3163
v = simplify_shallow(v); tv = typ(v);
3164
if (!is_scalar_t(tu)) pari_err_TYPE("findquad", u);
3165
if (!is_scalar_t(tv)) pari_err_TYPE("findquad", v);
3166
x = deg1pol(u, v, varn(a));
3167
if (typ(x) == t_POL) x = gmodulo(x,p);
3168
return gerepileupto(av, x);
3169
}
3170
static GEN
3171
findquad_pol(GEN p, GEN a, GEN x)
3172
{
3173
long i, lx = lg(x);
3174
GEN y = cgetg(lx,t_POL);
3175
for (i=2; i<lx; i++) gel(y,i) = findquad(a, gel(x,i), p);
3176
y[1] = x[1]; return y;
3177
}
3178
static GEN
3179
compocyclo(GEN nf, long m, long d)
3180
{
3181
GEN sb,a,b,s,p1,p2,p3,res,polL,polLK,nfL, D = nf_get_disc(nf);
3182
long ell,vx;
3183
3184
p1 = quadhilbertimag(D);
3185
p2 = polcyclo(m,0);
3186
if (d==1) return do_compo(p1,p2);
3187
3188
ell = m&1 ? m : (m>>2);
3189
if (absequalui(ell,D)) /* ell = |D| */
3190
{
3191
p2 = gcoeff(nffactor(nf,p2),1,1);
3192
return do_compo(p1,p2);
3193
}
3194
if (ell%4 == 3) ell = -ell;
3195
/* nf = K = Q(a), L = K(b) quadratic extension = Q(t) */
3196
polLK = quadpoly(stoi(ell)); /* relative polynomial */
3197
res = rnfequation2(nf, polLK);
3198
vx = nf_get_varn(nf);
3199
polL = gsubst(gel(res,1),0,pol_x(vx)); /* = charpoly(t) */
3200
a = gsubst(lift_shallow(gel(res,2)), 0,pol_x(vx));
3201
b = gsub(pol_x(vx), gmul(gel(res,3), a));
3202
nfL = nfinit(polL, DEFAULTPREC);
3203
p1 = gcoeff(nffactor(nfL,p1),1,1);
3204
p2 = gcoeff(nffactor(nfL,p2),1,1);
3205
p3 = do_compo(p1,p2); /* relative equation over L */
3206
/* compute non trivial s in Gal(L / K) */
3207
sb= gneg(gadd(b, RgX_coeff(polLK,1))); /* s(b) = Tr(b) - b */
3208
s = gadd(pol_x(vx), gsub(sb, b)); /* s(t) = t + s(b) - b */
3209
p3 = gmul(p3, galoisapplypol(nfL, s, p3));
3210
return findquad_pol(nf_get_pol(nf), a, p3);
3211
}
3212
3213
/* I integral ideal in HNF. (x) = I, x small in Z ? */
3214
static long
3215
isZ(GEN I)
3216
{
3217
GEN x = gcoeff(I,1,1);
3218
if (signe(gcoeff(I,1,2)) || !equalii(x, gcoeff(I,2,2))) return 0;
3219
return is_bigint(x)? -1: itos(x);
3220
}
3221
3222
/* Treat special cases directly. return NULL if not special case */
3223
static GEN
3224
treatspecialsigma(GEN bnr)
3225
{
3226
GEN bnf = bnr_get_bnf(bnr), nf = bnf_get_nf(bnf);
3227
GEN f = gel(bnr_get_mod(bnr), 1), D = nf_get_disc(nf);
3228
GEN p1, p2;
3229
long Ds, fl, tryf, i = isZ(f);
3230
3231
if (i == 1) return quadhilbertimag(D); /* f = 1 */
3232
3233
if (absequaliu(D,3)) /* Q(j) */
3234
{
3235
if (i == 4 || i == 5 || i == 7) return polcyclo(i,0);
3236
if (!absequaliu(gcoeff(f,1,1),9) || !absequaliu(Z_content(f),3)) return NULL;
3237
/* f = P_3^3 */
3238
p1 = mkpolmod(bnf_get_tuU(bnf), nf_get_pol(nf));
3239
return gadd(pol_xn(3,0), p1); /* x^3+j */
3240
}
3241
if (absequaliu(D,4)) /* Q(i) */
3242
{
3243
if (i == 3 || i == 5) return polcyclo(i,0);
3244
if (i != 4) return NULL;
3245
p1 = mkpolmod(bnf_get_tuU(bnf), nf_get_pol(nf));
3246
return gadd(pol_xn(2,0), p1); /* x^2+i */
3247
}
3248
Ds = smodis(D,48);
3249
if (i)
3250
{
3251
if (i==2 && Ds%16== 8) return compocyclo(nf, 4,1);
3252
if (i==3 && Ds% 3== 1) return compocyclo(nf, 3,1);
3253
if (i==4 && Ds% 8== 1) return compocyclo(nf, 4,1);
3254
if (i==6 && Ds ==40) return compocyclo(nf,12,1);
3255
return NULL;
3256
}
3257
3258
p1 = gcoeff(f,1,1); /* integer > 0 */
3259
tryf = itou_or_0(p1); if (!tryf) return NULL;
3260
p2 = gcoeff(f,2,2); /* integer > 0 */
3261
if (is_pm1(p2)) fl = 0;
3262
else {
3263
if (Ds % 16 != 8 || !absequaliu(Z_content(f),2)) return NULL;
3264
fl = 1; tryf >>= 1;
3265
}
3266
if (tryf <= 3 || umodiu(D, tryf) || !uisprime(tryf)) return NULL;
3267
if (fl) tryf <<= 2;
3268
return compocyclo(nf,tryf,2);
3269
}
3270
3271
GEN
3272
quadray(GEN D, GEN f, long prec)
3273
{
3274
GEN bnr, y, bnf, H = NULL;
3275
pari_sp av = avma;
3276
3277
if (isint1(f)) return quadhilbert(D, prec);
3278
quadray_init(&D, f, &bnf, prec);
3279
bnr = Buchray(bnf, f, nf_INIT|nf_GEN);
3280
if (is_pm1(bnr_get_no(bnr))) { set_avma(av); return pol_x(0); }
3281
if (signe(D) > 0)
3282
y = bnrstark(bnr, H, prec);
3283
else
3284
{
3285
bnr_subgroup_sanitize(&bnr, &H);
3286
y = treatspecialsigma(bnr);
3287
if (!y) y = computeP2(bnr, prec);
3288
}
3289
return gerepileupto(av, y);
3290
}
3291
3292