Line data Source code
1 : /* Copyright (C) 2000 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 : #include "pari.h"
15 : #include "paripriv.h"
16 : #include "mpqs.h"
17 :
18 : #define DEBUGLEVEL DEBUGLEVEL_quadclassunit
19 :
20 : /*******************************************************************/
21 : /* */
22 : /* CLASS GROUP AND REGULATOR (McCURLEY, BUCHMANN) */
23 : /* QUADRATIC FIELDS */
24 : /* */
25 : /*******************************************************************/
26 : /* For largeprime() hashtable. Note that hashed pseudoprimes are odd (unless
27 : * 2 | index), hence the low order bit is not useful. So we hash
28 : * HASHBITS bits starting at bit 1, not bit 0 */
29 : #define HASHBITS 10
30 : static const long HASHT = 1L << HASHBITS;
31 :
32 : static long
33 2565062 : hash(long q) { return (q & ((1L << (HASHBITS+1)) - 1)) >> 1; }
34 : #undef HASHBITS
35 :
36 : /* See buch2.c:
37 : * B->subFB contains split p such that \prod p > sqrt(B->Disc)
38 : * B->powsubFB contains powers of forms in B->subFB */
39 : #define RANDOM_BITS 4
40 : static const long CBUCH = (1L<<RANDOM_BITS)-1;
41 :
42 : struct buch_quad
43 : {
44 : ulong limhash;
45 : long KC, KC2, PRECREG;
46 : long *primfact, *exprimfact, **hashtab;
47 : GEN FB, numFB, prodFB;
48 : GEN powsubFB, vperm, subFB, badprim;
49 : struct qfr_data *q;
50 : };
51 :
52 : /*******************************************************************/
53 : /* */
54 : /* Routines related to binary quadratic forms (for internal use) */
55 : /* */
56 : /*******************************************************************/
57 : /* output canonical representative wrt projection Cl^+ --> Cl (a > 0) */
58 : static GEN
59 1166963 : qfr3_canon(GEN x, struct qfr_data *S)
60 : {
61 1166963 : GEN a = gel(x,1), c = gel(x,3);
62 1166963 : if (signe(a) < 0) {
63 403298 : if (absequalii(a,c)) return qfr3_rho(x, S);
64 403284 : setsigne(a, 1);
65 403284 : setsigne(c,-1);
66 : }
67 1166949 : return x;
68 : }
69 : static GEN
70 3710 : qfr3_canon_safe(GEN x, struct qfr_data *S)
71 : {
72 3710 : GEN a = gel(x,1), c = gel(x,3);
73 3710 : if (signe(a) < 0) {
74 224 : if (absequalii(a,c)) return qfr3_rho(x, S);
75 224 : gel(x,1) = negi(a);
76 224 : gel(x,3) = negi(c);
77 : }
78 3710 : return x;
79 : }
80 : static GEN
81 1952748 : qfr5_canon(GEN x, struct qfr_data *S)
82 : {
83 1952748 : GEN a = gel(x,1), c = gel(x,3);
84 1952748 : if (signe(a) < 0) {
85 723268 : if (absequalii(a,c)) return qfr5_rho(x, S);
86 723254 : setsigne(a, 1);
87 723254 : setsigne(c,-1);
88 : }
89 1952734 : return x;
90 : }
91 : static GEN
92 1735160 : QFR5_comp(GEN x,GEN y, struct qfr_data *S)
93 1735160 : { return qfr5_canon(qfr5_comp(x,y,S), S); }
94 : static GEN
95 1007545 : QFR3_comp(GEN x, GEN y, struct qfr_data *S)
96 1007545 : { return qfr3_canon(qfr3_comp(x,y,S), S); }
97 :
98 : /* compute rho^n(x) */
99 : static GEN
100 220157 : qfr5_rho_pow(GEN x, long n, struct qfr_data *S)
101 : {
102 : long i;
103 220157 : pari_sp av = avma;
104 2194360 : for (i=1; i<=n; i++)
105 : {
106 1974203 : x = qfr5_rho(x,S);
107 1974203 : if (gc_needed(av,1))
108 : {
109 0 : if(DEBUGMEM>1) pari_warn(warnmem,"qfr5_rho_pow");
110 0 : x = gerepilecopy(av, x);
111 : }
112 : }
113 220157 : return gerepilecopy(av, x);
114 : }
115 :
116 : static GEN
117 217588 : qfr5_pf(struct qfr_data *S, long p, long prec)
118 : {
119 217588 : GEN y = primeform_u(S->D,p);
120 217588 : return qfr5_canon(qfr5_red(qfr_to_qfr5(y,prec), S), S);
121 : }
122 :
123 : static GEN
124 159390 : qfr3_pf(struct qfr_data *S, long p)
125 : {
126 159390 : GEN y = primeform_u(S->D,p);
127 159390 : return qfr3_canon(qfr3_red(y, S), S);
128 : }
129 :
130 : #define qfi_pf primeform_u
131 :
132 : /* Warning: ex[0] not set in general */
133 : static GEN
134 4061514 : init_form(struct buch_quad *B, GEN ex,
135 : GEN (*comp)(GEN,GEN,struct qfr_data *S))
136 : {
137 4061514 : long i, l = lg(B->powsubFB);
138 4061514 : GEN F = NULL;
139 22902090 : for (i=1; i<l; i++)
140 18855542 : if (ex[i])
141 : {
142 17678913 : GEN t = gmael(B->powsubFB,i,ex[i]);
143 17678913 : F = F? comp(F, t, B->q): t;
144 : }
145 4046548 : return F;
146 : }
147 : static GEN
148 197015 : qfr5_factorback(struct buch_quad *B, GEN ex) { return init_form(B, ex, &QFR5_comp); }
149 :
150 : static GEN
151 11737788 : QFI_comp(GEN x, GEN y, struct qfr_data *S) { (void)S; return qfbcomp_i(x,y); }
152 :
153 : static GEN
154 160620 : qfi_factorback(struct buch_quad *B, GEN ex) { return init_form(B, ex, &QFI_comp); }
155 :
156 : static GEN
157 3703538 : random_form(struct buch_quad *B, GEN ex,
158 : GEN (*comp)(GEN,GEN, struct qfr_data *S))
159 : {
160 3703538 : long i, l = lg(ex);
161 3703538 : pari_sp av = avma;
162 : GEN F;
163 : for(;;)
164 : {
165 20590891 : for (i=1; i<l; i++) ex[i] = random_bits(RANDOM_BITS);
166 3703728 : if ((F = init_form(B, ex, comp))) return F;
167 448 : set_avma(av);
168 : }
169 : }
170 : static GEN
171 161567 : qfr3_random(struct buch_quad *B,GEN ex){ return random_form(B, ex, &QFR3_comp); }
172 : static GEN
173 3542017 : qfi_random(struct buch_quad *B,GEN ex) { return random_form(B, ex, &QFI_comp); }
174 :
175 : /*******************************************************************/
176 : /* */
177 : /* Common subroutines */
178 : /* */
179 : /*******************************************************************/
180 : /* We assume prime ideals of norm < D generate Cl(K); failure with
181 : * a factor base of primes with norm < LIMC <= D. Suggest new value.
182 : * All values of the form c * log^2 (disc K) [where D has c = 4
183 : * (Grenie-Molteni, under GRH)]. A value of c in [0.3, 1] should be OK for most
184 : * fields. No example is known where c >= 2 is necessary. */
185 : ulong
186 2395 : bnf_increase_LIMC(ulong LIMC, ulong D)
187 : {
188 2395 : if (LIMC >= D) pari_err_BUG("Buchmann's algorithm");
189 2395 : if (LIMC <= D / 13.333)
190 239 : LIMC *= 2; /* tiny c <= 0.3 : double it */
191 : else
192 2156 : LIMC += maxuu(1, D / 20); /* large c, add 0.2 to it */
193 2395 : if (LIMC > D) LIMC = D;
194 2395 : return LIMC;
195 : }
196 :
197 : /* Is |q| <= p ? */
198 : static int
199 10416 : isless_iu(GEN q, ulong p) {
200 10416 : long l = lgefint(q);
201 10416 : return l==2 || (l == 3 && uel(q,2) <= p);
202 : }
203 :
204 : static GEN
205 5028465 : Z_isquasismooth_prod(GEN N, GEN P)
206 : {
207 5028465 : P = gcdii(P,N);
208 10032767 : while (!is_pm1(P))
209 : {
210 4998097 : N = diviiexact(N, P);
211 5005857 : P = gcdii(N, P);
212 : }
213 5025684 : return N;
214 : }
215 :
216 : static long
217 5034994 : factorquad(struct buch_quad *B, GEN f, long nFB, ulong limp)
218 : {
219 : ulong X;
220 5034994 : long i, lo = 0;
221 5034994 : GEN F, x = gel(f,1), FB = B->FB, P = B->primfact, E = B->exprimfact;
222 5034994 : if (B->badprim && !is_pm1(gcdii(x, B->badprim))) return 0;
223 5028057 : F = Z_isquasismooth_prod(x, B->prodFB);
224 5025546 : if (cmpiu(F, B->limhash) > 0) return 0;
225 4401796 : for (i=1; lgefint(x) > 3; i++)
226 : {
227 10416 : ulong p = uel(FB,i), r;
228 10416 : GEN q = absdiviu_rem(x, p, &r);
229 10416 : if (!r)
230 : {
231 1530 : long k = 0;
232 2633 : do { k++; x = q; q = absdiviu_rem(x, p, &r); } while (!r);
233 1530 : lo++; P[lo] = p; E[lo] = k;
234 : }
235 10416 : if (isless_iu(q,p)) {
236 1 : if (lgefint(x) == 3) { X = uel(x,2); goto END; }
237 34 : return 0;
238 : }
239 10415 : if (i == nFB) return 0;
240 : }
241 4391380 : X = uel(x,2);
242 4391380 : if (X == 1) { P[0] = 0; return 1; }
243 68605388 : for (;; i++)
244 68605388 : { /* single precision affair, split for efficiency */
245 72978056 : ulong p = uel(FB,i);
246 72978056 : ulong q = X / p, r = X % p; /* gcc makes a single div */
247 72978056 : if (!r)
248 : {
249 5621439 : long k = 0;
250 6788796 : do { k++; X = q; q = X / p; r = X % p; } while (!r);
251 5621439 : lo++; P[lo] = p; E[lo] = k;
252 : }
253 72978056 : if (q <= p) break;
254 68638773 : if (i == nFB) return 0;
255 : }
256 4339284 : END:
257 4339284 : if (X > B->limhash) return 0;
258 4339284 : if (X != 1 && X <= limp) { lo++; P[lo] = X; E[lo] = 1; X = 1; }
259 4339284 : P[0] = lo; return X;
260 : }
261 :
262 : /* Check for a "large prime relation" involving q; q may not be prime */
263 : static long *
264 2565043 : largeprime(struct buch_quad *B, long q, GEN ex, long np, long nrho)
265 : {
266 2565043 : const long hashv = hash(q);
267 2565064 : long *pt, i, l = lg(B->subFB);
268 :
269 2786782 : for (pt = B->hashtab[hashv]; ; pt = (long*) pt[0])
270 : {
271 2786782 : if (!pt)
272 : {
273 2365694 : pt = (long*) pari_malloc((l+3) * sizeof(long));
274 2365967 : *pt++ = nrho; /* nrho = pt[-3] */
275 2365967 : *pt++ = np; /* np = pt[-2] */
276 2365967 : *pt++ = q; /* q = pt[-1] */
277 2365967 : pt[0] = (long)B->hashtab[hashv];
278 14987228 : for (i=1; i<l; i++) pt[i]=ex[i];
279 2365967 : B->hashtab[hashv]=pt; return NULL;
280 : }
281 421088 : if (pt[-1] == q) break;
282 : }
283 237912 : for(i=1; i<l; i++)
284 234620 : if (pt[i] != ex[i]) return pt;
285 3292 : return (pt[-2]==np)? NULL: pt;
286 : }
287 :
288 : static void
289 169809 : clearhash(long **hash)
290 : {
291 : long *pt;
292 : long i;
293 174020828 : for (i=0; i<HASHT; i++) {
294 176217008 : for (pt = hash[i]; pt; ) {
295 2365989 : void *z = (void*)(pt - 3);
296 2365989 : pt = (long*) pt[0]; pari_free(z);
297 : }
298 173851019 : hash[i] = NULL;
299 : }
300 169946 : }
301 :
302 : /* last prime stored */
303 : ulong
304 0 : GRH_last_prime(GRHcheck_t *S) { return (S->primes + S->nprimes-1)->p; }
305 : /* ensure that S->primes can hold at least nb primes */
306 : void
307 401062 : GRH_ensure(GRHcheck_t *S, long nb)
308 : {
309 401062 : if (S->maxprimes <= nb)
310 : {
311 0 : do S->maxprimes *= 2; while (S->maxprimes <= nb);
312 0 : pari_realloc_ip((void**)&S->primes, S->maxprimes*sizeof(*S->primes));
313 : }
314 401062 : }
315 : /* cache data for all primes up to the LIM */
316 : static void
317 1174813 : cache_prime_quad(GRHcheck_t *S, ulong LIM, GEN D)
318 : {
319 : GRHprime_t *pr;
320 : long nb;
321 :
322 1174813 : if (S->limp >= LIM) return;
323 72497 : nb = (long)primepi_upper_bound((double)LIM); /* #{p <= LIM} <= nb */
324 72504 : GRH_ensure(S, nb+1); /* room for one extra prime */
325 72504 : for (pr = S->primes + S->nprimes;;)
326 12669037 : {
327 12741541 : ulong p = u_forprime_next(&(S->P));
328 12741284 : pr->p = p;
329 12741284 : pr->logp = log((double)p);
330 12741284 : pr->dec = (GEN)kroiu(D,p);
331 12741543 : S->nprimes++;
332 12741543 : pr++;
333 : /* store up to nextprime(LIM) included */
334 12741543 : if (p >= LIM) { S->limp = p; break; }
335 : }
336 : }
337 :
338 : static GEN
339 70376 : compute_invresquad(GRHcheck_t *S, long LIMC)
340 : {
341 70376 : pari_sp av = avma;
342 70376 : GEN invres = real_1(DEFAULTPREC);
343 70375 : double limp = log((double)LIMC) / 2;
344 : GRHprime_t *pr;
345 : long i;
346 12744142 : for (pr = S->primes, i = S->nprimes; i > 0; pr++, i--)
347 : {
348 12677326 : long s = (long)pr->dec;
349 12677326 : if (s)
350 : {
351 12561275 : ulong p = pr->p;
352 12561275 : if (s > 0 || pr->logp <= limp)
353 : /* Both p and P contribute */
354 6391455 : invres = mulur(p - s, divru(invres, p));
355 6169820 : else if (s<0)
356 : /* Only p contributes */
357 6169815 : invres = mulur(p, divru(invres, p - 1));
358 : }
359 : }
360 66816 : return gerepileuptoleaf(av, invres);
361 : }
362 :
363 : /* p | conductor of order of disc D ? */
364 : static int
365 392084 : is_bad(GEN D, ulong p)
366 : {
367 392084 : pari_sp av = avma;
368 392084 : if (p == 2)
369 : {
370 89690 : long r = mod16(D) >> 1;
371 89689 : if (r && signe(D) < 0) r = 8-r;
372 89689 : return (r < 4);
373 : }
374 302394 : return gc_bool(av, dvdii(D, sqru(p))); /* p^2 | D ? */
375 : }
376 :
377 : /* returns the n-th suitable ideal for the factorbase */
378 : static long
379 70362 : nthidealquad(GEN D, long n)
380 : {
381 70362 : pari_sp av = avma;
382 : forprime_t S;
383 : ulong p;
384 70362 : (void)u_forprime_init(&S, 2, ULONG_MAX);
385 357580 : while ((p = u_forprime_next(&S)) && n > 0)
386 287239 : if (!is_bad(D, p) && kroiu(D, p) >= 0) n--;
387 70351 : return gc_long(av, p);
388 : }
389 :
390 : static int
391 1033955 : quadGRHchk(GEN D, GRHcheck_t *S, ulong LIMC)
392 : {
393 1033955 : double logC = log((double)LIMC), SA = 0, SB = 0;
394 : long i;
395 :
396 1033955 : cache_prime_quad(S, LIMC, D);
397 1033940 : for (i = 0;; i++)
398 29533619 : {
399 30567559 : GRHprime_t *pr = S->primes+i;
400 30567559 : ulong p = pr->p;
401 : long M;
402 : double logNP, q, A, B;
403 30567559 : if (p > LIMC) break;
404 29622911 : if ((long)pr->dec < 0)
405 : {
406 14790392 : logNP = 2 * pr->logp;
407 14790392 : q = 1/(double)p;
408 : }
409 : else
410 : {
411 14832519 : logNP = pr->logp;
412 14832519 : q = 1/sqrt((double)p);
413 : }
414 29622911 : A = logNP * q; B = logNP * A; M = (long)(logC/logNP);
415 29622911 : if (M > 1)
416 : {
417 2502415 : double inv1_q = 1 / (1-q);
418 2502415 : A *= (1 - pow(q, (double) M)) * inv1_q;
419 2502415 : B *= (1 - pow(q, (double) M)*(M+1 - M*q)) * inv1_q * inv1_q;
420 : }
421 29622911 : if ((long)pr->dec>0) { SA += 2*A;SB += 2*B; } else { SA += A; SB += B; }
422 29622911 : if (p == LIMC) break;
423 : }
424 1033940 : return GRHok(S, logC, SA, SB);
425 : }
426 :
427 : /* C2 >= C1; create B->FB, B->numFB; set B->badprim. Return L(kro_D, 1) */
428 : static void
429 70509 : FBquad(struct buch_quad *B, ulong C2, ulong C1, GRHcheck_t *S)
430 : {
431 70509 : GEN D = B->q->D;
432 : long i;
433 : pari_sp av;
434 : GRHprime_t *pr;
435 :
436 70509 : cache_prime_quad(S, C2, D);
437 70509 : pr = S->primes;
438 70509 : B->numFB = cgetg(C2+1, t_VECSMALL);
439 70509 : B->FB = cgetg(C2+1, t_VECSMALL);
440 70464 : av = avma;
441 70464 : B->KC = 0; i = 0;
442 70464 : B->badprim = gen_1;
443 2813616 : for (;; pr++) /* p <= C2 */
444 2813616 : {
445 2884080 : ulong p = pr->p;
446 2884080 : if (!B->KC && p > C1) B->KC = i;
447 2884080 : if (p > C2) break;
448 2821089 : switch ((long)pr->dec)
449 : {
450 1390245 : case -1: break; /* inert */
451 104851 : case 0: /* ramified */
452 104851 : if (is_bad(D, p)) { B->badprim = muliu(B->badprim, p); break; }
453 : /* fall through */
454 : default: /* split */
455 1430825 : i++; B->numFB[p] = i; B->FB[i] = p; break;
456 : }
457 2821133 : if (p == C2)
458 : {
459 7517 : if (!B->KC) B->KC = i;
460 7517 : break;
461 : }
462 : }
463 70508 : B->KC2 = i;
464 70508 : setlg(B->FB, B->KC2+1);
465 70509 : if (B->badprim != gen_1)
466 42 : B->badprim = gerepileuptoint(av, B->badprim);
467 : else
468 : {
469 70467 : B->badprim = NULL; set_avma(av);
470 : }
471 70509 : B->prodFB = zv_prod_Z(B->FB);
472 70504 : }
473 :
474 : /* create B->vperm, return B->subFB */
475 : static GEN
476 70504 : subFBquad(struct buch_quad *B, GEN D, double PROD, long minSFB)
477 : {
478 70504 : long i, j, lgsub = 1, ino = 1, lv = B->KC+1;
479 70504 : double prod = 1.;
480 : pari_sp av;
481 : GEN no;
482 :
483 70504 : B->vperm = cgetg(lv, t_VECSMALL);
484 70504 : av = avma;
485 70504 : no = cgetg(lv, t_VECSMALL);
486 335115 : for (j = 1; j < lv; j++)
487 : {
488 334975 : ulong p = uel(B->FB,j);
489 334975 : if (!umodiu(D, p)) no[ino++] = j; /* ramified */
490 : else
491 : {
492 255038 : B->vperm[lgsub++] = j;
493 255038 : prod *= p;
494 255038 : if (lgsub > minSFB && prod > PROD) break;
495 : }
496 : }
497 : /* lgsub >= 1 otherwise quadGRHchk is false */
498 70509 : i = lgsub;
499 150447 : for (j = 1; j < ino;i++,j++) B->vperm[i] = no[j];
500 1166003 : for ( ; i < lv; i++) B->vperm[i] = i;
501 70509 : no = gclone(vecslice(B->vperm, 1, lgsub-1));
502 70509 : set_avma(av); return no;
503 : }
504 :
505 : /* assume n >= 1, x[i][j] = B->subFB[i]^j, for j = 1..n */
506 : static GEN
507 99319 : powsubFBquad(struct buch_quad *B, long n)
508 : {
509 99319 : pari_sp av = avma;
510 99319 : long i,j, l = lg(B->subFB);
511 99319 : GEN F, y, x = cgetg(l, t_VEC), D = B->q->D;
512 :
513 99318 : if (B->PRECREG) /* real */
514 : {
515 39627 : for (i=1; i<l; i++)
516 : {
517 34510 : F = qfr5_pf(B->q, B->FB[B->subFB[i]], B->PRECREG);
518 34510 : y = cgetg(n+1, t_VEC); gel(x,i) = y;
519 34510 : gel(y,1) = F;
520 552160 : for (j=2; j<=n; j++) gel(y,j) = QFR5_comp(gel(y,j-1), F, B->q);
521 : }
522 : }
523 : else /* imaginary */
524 : {
525 427501 : for (i=1; i<l; i++)
526 : {
527 333328 : F = qfi_pf(D, B->FB[B->subFB[i]]);
528 333306 : y = cgetg(n+1, t_VEC); gel(x,i) = y;
529 334586 : gel(y,1) = F;
530 5320153 : for (j=2; j<=n; j++) gel(y,j) = qfbcomp_i(gel(y,j-1), F);
531 : }
532 : }
533 99290 : x = gclone(x); set_avma(av); return x;
534 : }
535 :
536 : static void
537 98289 : sub_fact(struct buch_quad *B, GEN col, GEN F)
538 : {
539 98289 : GEN b = gel(F,2);
540 : long i;
541 208018 : for (i=1; i<=B->primfact[0]; i++)
542 : {
543 109729 : ulong p = B->primfact[i], k = B->numFB[p];
544 109729 : long e = B->exprimfact[i];
545 109729 : if (umodiu(b, p<<1) > p) e = -e;
546 109729 : col[k] -= e;
547 : }
548 98289 : }
549 :
550 : #if 0
551 : static void
552 : dbg_fact(struct buch_quad *B)
553 : {
554 : long i;
555 : for (i=1; i<=B->primfact[0]; i++)
556 : {
557 : ulong p = B->primfact[i];
558 : long e = B->exprimfact[i];
559 : err_printf("%lu^%ld ",p,e);
560 : }
561 : }
562 :
563 : static void
564 : chk_fact(struct buch_quad *B, GEN col)
565 : {
566 : long i, l = lg(col);
567 : GEN Q = qfi_pf(B->q->D, 1);
568 : for (i=1; i< l; i++)
569 : {
570 : ulong p = B->FB[i];
571 : long k = col[i];
572 : Q = qfbcomp(qfbpowraw(qfi_pf(B->q->D, p),k),Q);
573 : }
574 : if (!gequal1(gel(Q,1))) pari_err_BUG("chk_fact");
575 : }
576 : #endif
577 :
578 : static void
579 1892821 : add_fact(struct buch_quad *B, GEN col, GEN F)
580 : {
581 1892821 : GEN b = gel(F,2);
582 : long i;
583 5932152 : for (i=1; i<=B->primfact[0]; i++)
584 : {
585 4039150 : ulong p = B->primfact[i], k = B->numFB[p];
586 4039150 : long e = B->exprimfact[i];
587 4039150 : if (umodiu(b, p<<1) > p) e = -e;
588 4039331 : col[k] += e;
589 : }
590 1893002 : }
591 :
592 : static GEN
593 70362 : get_clgp(struct buch_quad *B, GEN W, GEN *ptD)
594 : {
595 70362 : GEN res, init, u1, D = ZM_snf_group(W,NULL,&u1);
596 70360 : long i, j, l = lg(W), c = lg(D);
597 :
598 70360 : res=cgetg(c,t_VEC); init = cgetg(l,t_VEC);
599 216300 : for (i=1; i<l; i++) gel(init,i) = primeform_u(B->q->D, B->FB[B->vperm[i]]);
600 195862 : for (j=1; j<c; j++)
601 : {
602 125505 : GEN g = NULL;
603 125505 : if (signe(B->q->D) > 0)
604 : {
605 13328 : for (i=1; i<l; i++)
606 : {
607 9618 : GEN t, u = gcoeff(u1,i,j);
608 9618 : if (!signe(u)) continue;
609 4543 : t = qfr3_pow(gel(init,i), u, B->q);
610 4543 : g = g? qfr3_comp(g, t, B->q): t;
611 : }
612 3710 : g = qfr3_to_qfr(qfr3_canon_safe(qfr3_red(g, B->q), B->q), B->q->D);
613 : }
614 : else
615 : {
616 423911 : for (i=1; i<l; i++)
617 : {
618 302121 : GEN t, u = gcoeff(u1,i,j);
619 302121 : if (!signe(u)) continue;
620 203708 : t = powgi(gel(init,i), u);
621 203713 : g = g? qfbcomp_i(g, t): t;
622 : }
623 : }
624 125503 : gel(res,j) = g;
625 : }
626 70357 : *ptD = D; return res;
627 : }
628 :
629 : static long
630 70376 : trivial_relations(struct buch_quad *B, GEN mat, GEN C)
631 : {
632 70376 : long i, j = 0;
633 70376 : GEN col, D = B->q->D;
634 1500328 : for (i = 1; i <= B->KC; i++)
635 : { /* ramified prime ==> trivial relation */
636 1429946 : if (umodiu(D, B->FB[i])) continue;
637 104423 : col = zero_zv(B->KC);
638 104430 : col[i] = 2; j++;
639 104430 : gel(mat,j) = col;
640 104430 : gel(C,j) = gen_0;
641 : }
642 70382 : return j;
643 : }
644 :
645 : static void
646 0 : dbg_all(pari_timer *T, const char *phase, long s, long n)
647 : {
648 0 : err_printf("\n");
649 0 : timer_printf(T, "%s rel [#rel/#test = %ld/%ld]", phase,s,n);
650 0 : }
651 :
652 : /* Imaginary Quadratic fields */
653 :
654 : static void
655 8813 : rel_to_col(struct buch_quad *B, GEN col, GEN rel, GEN b)
656 : {
657 8813 : GEN P = gel(rel, 1), E = gel(rel, 2);
658 8813 : long i, lP = lg(P);
659 105784 : for (i=1; i<lP; i++)
660 : {
661 96971 : ulong p = uel(P, i), e = uel(E, i);
662 96971 : col[B->numFB[p]] += umodiu(b, p<<1) > p ? -e :e;
663 : }
664 8813 : }
665 :
666 : static void
667 99163 : imag_relations(struct buch_quad *B, long need, long *pc, ulong LIMC, GEN mat)
668 : {
669 : pari_timer T;
670 99163 : long lgsub = lg(B->subFB), current = *pc, nbtest = 0, s = 0;
671 : long i, fpc;
672 : pari_sp av;
673 99163 : GEN col, form, ex = cgetg(lgsub, t_VECSMALL);
674 :
675 99163 : if (!current) current = 1;
676 99163 : if (DEBUGLEVEL>2) timer_start(&T);
677 99162 : av = avma;
678 : for(;;)
679 : {
680 3640859 : if (s >= need) break;
681 3541697 : set_avma(av);
682 3541559 : form = qfi_random(B,ex);
683 3538033 : form = qfbcomp_i(form, qfi_pf(B->q->D, B->FB[current]));
684 3537336 : nbtest++; fpc = factorquad(B,form,B->KC,LIMC);
685 3540910 : if (!fpc)
686 : {
687 291564 : if (DEBUGLEVEL>3) err_printf(".");
688 291564 : if ((nbtest & 0xff) == 0 && ++current > B->KC) current = 1;
689 291564 : continue;
690 : }
691 3249346 : if (fpc > 1)
692 : {
693 1799953 : long *fpd = largeprime(B,fpc,ex,current,0);
694 : ulong b1, b2, p;
695 : GEN form2;
696 1800401 : if (!fpd)
697 : {
698 1639817 : if (DEBUGLEVEL>3) err_printf(".");
699 1639817 : continue;
700 : }
701 160584 : form2 = qfbcomp_i(qfi_factorback(B,fpd), qfi_pf(B->q->D, B->FB[fpd[-2]]));
702 160617 : p = fpc << 1;
703 160617 : b1 = umodiu(gel(form2,2), p);
704 160620 : b2 = umodiu(gel(form,2), p);
705 160623 : if (b1 != b2 && b1+b2 != p) continue;
706 :
707 160623 : col = gel(mat,++s);
708 160623 : add_fact(B,col, form);
709 160623 : (void)factorquad(B,form2,B->KC,LIMC);
710 160625 : if (b1==b2)
711 : {
712 414942 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += fpd[i]-ex[i];
713 80663 : sub_fact(B, col, form2); col[fpd[-2]]++;
714 : }
715 : else
716 : {
717 410349 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += -fpd[i]-ex[i];
718 79962 : add_fact(B, col, form2); col[fpd[-2]]--;
719 : }
720 160626 : if (DEBUGLEVEL>2) err_printf(" %ldP",s);
721 : }
722 : else
723 : {
724 1449393 : col = gel(mat,++s);
725 6960998 : for (i=1; i<lgsub; i++) col[B->subFB[i]] = -ex[i];
726 1449393 : add_fact(B, col, form);
727 1449835 : if (DEBUGLEVEL>2) err_printf(" %ld",s);
728 : }
729 1610316 : col[current]--;
730 1610316 : if (++current > B->KC) current = 1;
731 : }
732 99162 : if (DEBUGLEVEL>2) dbg_all(&T, "random", s, nbtest);
733 99162 : *pc = current;
734 99162 : }
735 :
736 : static void
737 336 : mpqs_relations(struct buch_quad *B, long need, long *pc, ulong LIMC, GEN mat, mpqs_handle_t *H, GEN missing_primes)
738 : {
739 : pari_timer T;
740 : long i, lV;
741 : GEN V;
742 336 : if (DEBUGLEVEL>2) timer_start(&T);
743 336 : V = mpqs_class_rels(H, need, missing_primes);
744 336 : if (!V) { imag_relations(B, need, pc, LIMC, mat); return; }
745 336 : lV = lg(V);
746 9149 : for (i = 1; i < lV && i <= need; i++)
747 : {
748 8813 : GEN formA = gel(V,i), rel = gel(formA,2), b = gel(formA,1);
749 8813 : GEN col = gel(mat,i);
750 8813 : rel_to_col(B, col, rel, b);
751 : }
752 336 : if (DEBUGLEVEL>2) timer_printf(&T, "MPQS rel [#rel = %ld]", i-1);
753 : }
754 :
755 : static int
756 7 : imag_be_honest(struct buch_quad *B)
757 : {
758 7 : long p, fpc, s = B->KC, nbtest = 0;
759 7 : GEN F, ex = cgetg(lg(B->subFB), t_VECSMALL);
760 7 : pari_sp av = avma;
761 :
762 525 : while (s<B->KC2)
763 : {
764 518 : p = B->FB[s+1]; if (DEBUGLEVEL>2) err_printf(" %ld",p);
765 518 : F = qfbcomp_i(qfi_pf(B->q->D, p), qfi_random(B, ex));
766 518 : fpc = factorquad(B,F,s,p-1);
767 518 : if (fpc == 1) { nbtest=0; s++; }
768 : else
769 392 : if (++nbtest > 40) return 0;
770 518 : set_avma(av);
771 : }
772 7 : return 1;
773 : }
774 :
775 : static GEN
776 184688 : dist(GEN e, GEN d, long prec)
777 : {
778 184688 : GEN t = qfr5_dist(e, d, prec);
779 184688 : return signe(d) < 0 ? mkcomplex(t, gen_1): t;
780 : }
781 :
782 : /* Real Quadratic fields */
783 :
784 : static void
785 5145 : real_relations(struct buch_quad *B, long need, long *pc, long lim, ulong LIMC, GEN mat, GEN C)
786 : {
787 : pari_timer T;
788 5145 : long lgsub = lg(B->subFB), prec = B->PRECREG, current = *pc, nbtest=0, s=0;
789 : long i, fpc, endcycle, rhoacc, rho;
790 : /* in a 2nd phase, don't include FB[current] but run along the cyle
791 : * ==> get more units */
792 5145 : int first = (current == 0);
793 : pari_sp av, av1;
794 5145 : GEN d, col, form, form0, form1, ex = cgetg(lgsub, t_VECSMALL);
795 :
796 5145 : if (DEBUGLEVEL>2) timer_start(&T);
797 5145 : if (!current) current = 1;
798 5145 : if (lim > need) lim = need;
799 5145 : av = avma;
800 : for(;;)
801 : {
802 166691 : if (s >= need) break;
803 161546 : if (first && s >= lim) {
804 2142 : first = 0;
805 2142 : if (DEBUGLEVEL>2) dbg_all(&T, "initial", s, nbtest);
806 : }
807 161546 : set_avma(av); form = qfr3_random(B, ex);
808 161546 : if (!first)
809 159369 : form = QFR3_comp(form, qfr3_pf(B->q, B->FB[current]), B->q);
810 161546 : av1 = avma;
811 161546 : form0 = form; form1 = NULL;
812 161546 : endcycle = rhoacc = 0;
813 161546 : rho = -1;
814 :
815 1300964 : CYCLE:
816 1300964 : if (endcycle || rho > 5000)
817 : {
818 21 : if (++current > B->KC) current = 1;
819 21 : continue;
820 : }
821 1300943 : if (gc_needed(av,1))
822 : {
823 0 : if(DEBUGMEM>1) pari_warn(warnmem,"real_relations");
824 0 : gerepileall(av1, form1? 2: 1, &form, &form1);
825 : }
826 1300943 : if (rho < 0) rho = 0; /* first time in */
827 : else
828 : {
829 1139397 : form = qfr3_rho(form, B->q); rho++;
830 1139397 : rhoacc++;
831 1139397 : if (first)
832 442526 : endcycle = (absequalii(gel(form,1),gel(form0,1))
833 221263 : && equalii(gel(form,2),gel(form0,2)));
834 : else
835 : {
836 918134 : if (absequalii(gel(form,1), gel(form,3))) /* a = -c */
837 : {
838 0 : if (absequalii(gel(form,1),gel(form0,1)) &&
839 0 : equalii(gel(form,2),gel(form0,2))) continue;
840 0 : form = qfr3_rho(form, B->q); rho++;
841 0 : rhoacc++;
842 : }
843 : else
844 918134 : { setsigne(form[1],1); setsigne(form[3],-1); }
845 918176 : if (equalii(gel(form,1),gel(form0,1)) &&
846 42 : equalii(gel(form,2),gel(form0,2))) continue;
847 : }
848 : }
849 1300943 : nbtest++; fpc = factorquad(B,form,B->KC,LIMC);
850 1300943 : if (!fpc)
851 : {
852 386778 : if (DEBUGLEVEL>3) err_printf(".");
853 386778 : goto CYCLE;
854 : }
855 914165 : if (fpc > 1)
856 : { /* look for Large Prime relation */
857 764946 : long *fpd = largeprime(B,fpc,ex,first? 0: current,rhoacc);
858 : ulong b1, b2, p;
859 : GEN form2;
860 764946 : if (!fpd)
861 : {
862 729477 : if (DEBUGLEVEL>3) err_printf(".");
863 729477 : goto CYCLE;
864 : }
865 35469 : if (!form1)
866 : {
867 35469 : form1 = qfr5_factorback(B,ex);
868 35469 : if (!first)
869 35469 : form1 = QFR5_comp(form1, qfr5_pf(B->q, B->FB[current], prec), B->q);
870 : }
871 35469 : form1 = qfr5_rho_pow(form1, rho, B->q);
872 35469 : rho = 0;
873 :
874 35469 : form2 = qfr5_factorback(B,fpd);
875 35469 : if (fpd[-2])
876 23709 : form2 = QFR5_comp(form2, qfr5_pf(B->q, B->FB[fpd[-2]], prec), B->q);
877 35469 : form2 = qfr5_rho_pow(form2, fpd[-3], B->q);
878 35469 : if (!absequalii(gel(form2,1),gel(form2,3)))
879 : {
880 35469 : setsigne(form2[1], 1);
881 35469 : setsigne(form2[3],-1);
882 : }
883 35469 : p = fpc << 1;
884 35469 : b1 = umodiu(gel(form2,2), p);
885 35469 : b2 = umodiu(gel(form1,2), p);
886 35469 : if (b1 != b2 && b1+b2 != p) goto CYCLE;
887 :
888 35469 : col = gel(mat,++s);
889 35469 : add_fact(B, col, form1);
890 35469 : (void)factorquad(B,form2,B->KC,LIMC);
891 35469 : if (b1==b2)
892 : {
893 135100 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += fpd[i]-ex[i];
894 17626 : sub_fact(B,col, form2);
895 17626 : if (fpd[-2]) col[fpd[-2]]++;
896 17626 : d = dist(subii(gel(form1,4),gel(form2,4)),
897 17626 : divrr(gel(form1,5),gel(form2,5)), prec);
898 : }
899 : else
900 : {
901 136780 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += -fpd[i]-ex[i];
902 17843 : add_fact(B, col, form2);
903 17843 : if (fpd[-2]) col[fpd[-2]]--;
904 17843 : d = dist(addii(gel(form1,4),gel(form2,4)),
905 17843 : mulrr(gel(form1,5),gel(form2,5)), prec);
906 : }
907 35469 : if (DEBUGLEVEL>2) err_printf(" %ldP",s);
908 : }
909 : else
910 : { /* standard relation */
911 149219 : if (!form1)
912 : {
913 126077 : form1 = qfr5_factorback(B, ex);
914 126077 : if (!first)
915 123900 : form1 = QFR5_comp(form1, qfr5_pf(B->q, B->FB[current], prec), B->q);
916 : }
917 149219 : form1 = qfr5_rho_pow(form1, rho, B->q);
918 149219 : rho = 0;
919 :
920 149219 : col = gel(mat,++s);
921 1147489 : for (i=1; i<lgsub; i++) col[B->subFB[i]] = -ex[i];
922 149219 : add_fact(B, col, form1);
923 149219 : d = dist(gel(form1,4), gel(form1,5), prec);
924 149219 : if (DEBUGLEVEL>2) err_printf(" %ld",s);
925 : }
926 184688 : gaffect(d, gel(C,s));
927 184688 : if (first)
928 : {
929 25319 : if (s >= lim) continue;
930 23163 : goto CYCLE;
931 : }
932 : else
933 : {
934 159369 : col[current]--;
935 159369 : if (++current > B->KC) current = 1;
936 : }
937 : }
938 5145 : if (DEBUGLEVEL>2) dbg_all(&T, "random", s, nbtest);
939 5145 : *pc = current;
940 5145 : }
941 :
942 : static int
943 7 : real_be_honest(struct buch_quad *B)
944 : {
945 7 : long p, fpc, s = B->KC, nbtest = 0;
946 7 : GEN F,F0, ex = cgetg(lg(B->subFB), t_VECSMALL);
947 7 : pari_sp av = avma;
948 :
949 28 : while (s<B->KC2)
950 : {
951 21 : p = B->FB[s+1]; if (DEBUGLEVEL>2) err_printf(" %ld",p);
952 21 : F = QFR3_comp(qfr3_random(B, ex), qfr3_pf(B->q, p), B->q);
953 21 : for (F0 = F;;)
954 : {
955 49 : fpc = factorquad(B,F,s,p-1);
956 49 : if (fpc == 1) { nbtest=0; s++; break; }
957 28 : if (++nbtest > 40) return 0;
958 28 : F = qfr3_canon(qfr3_rho(F, B->q), B->q);
959 28 : if (equalii(gel(F,1),gel(F0,1))
960 0 : && equalii(gel(F,2),gel(F0,2))) break;
961 : }
962 21 : set_avma(av);
963 : }
964 7 : return 1;
965 : }
966 :
967 : static GEN
968 55146 : crabs(GEN a)
969 : {
970 55146 : return signe(real_i(a)) < 0 ? gneg(a): a;
971 : }
972 :
973 : static GEN
974 33978 : gcdreal(GEN a,GEN b)
975 : {
976 33978 : if (!signe(real_i(a))) return crabs(b);
977 33012 : if (!signe(real_i(b))) return crabs(a);
978 32897 : if (expo(real_i(a))<-5) return crabs(b);
979 12040 : if (expo(real_i(b))<-5) return crabs(a);
980 9093 : a = crabs(a); b = crabs(b);
981 20019 : while (expo(real_i(b)) >= -5 && signe(real_i(b)))
982 : {
983 : long e;
984 10926 : GEN r, q = gcvtoi(divrr(real_i(a),real_i(b)),&e);
985 10926 : if (e > 0) return NULL;
986 10926 : r = gsub(a, gmul(q,b)); a = b; b = r;
987 : }
988 9093 : return crabs(a);
989 : }
990 :
991 : static int
992 91695 : get_R(struct buch_quad *B, GEN C, long sreg, GEN z, GEN *ptR)
993 : {
994 91695 : GEN R = gen_1;
995 : double c;
996 : long i;
997 91695 : if (B->PRECREG)
998 : {
999 2982 : R = crabs(gel(C,1));
1000 36960 : for (i=2; i<=sreg; i++)
1001 : {
1002 33978 : R = gcdreal(gel(C,i), R);
1003 33978 : if (!R) return fupb_PRECI;
1004 : }
1005 2982 : if (gexpo(real_i(R)) <= -3)
1006 : {
1007 0 : if (DEBUGLEVEL>2) err_printf("regulator is zero.\n");
1008 0 : return fupb_RELAT;
1009 : }
1010 2982 : if (DEBUGLEVEL>2) err_printf("#### Tentative regulator: %Ps\n",R);
1011 : }
1012 91695 : c = gtodouble(gmul(z, real_i(R)));
1013 91698 : if (c < 0.8 || c > 1.3) return fupb_RELAT;
1014 70362 : *ptR = R; return fupb_NONE;
1015 : }
1016 :
1017 : static int
1018 70362 : quad_be_honest(struct buch_quad *B)
1019 : {
1020 : int r;
1021 70362 : if (B->KC2 <= B->KC) return 1;
1022 14 : if (DEBUGLEVEL>2)
1023 0 : err_printf("be honest for primes from %ld to %ld\n", B->FB[B->KC+1],B->FB[B->KC2]);
1024 14 : r = B->PRECREG? real_be_honest(B): imag_be_honest(B);
1025 14 : if (DEBUGLEVEL>2) err_printf("\n");
1026 14 : return r;
1027 : }
1028 :
1029 : static GEN
1030 70534 : Buchquad_i(GEN D, double cbach, double cbach2, long prec)
1031 : {
1032 70534 : const long MAXRELSUP = 20, SFB_MAX = 3, MPQS_THRESHOLD = 60;
1033 : pari_timer T;
1034 : pari_sp av, av2;
1035 70534 : const long RELSUP = 5;
1036 : long i, s, current, triv, sfb_trials, nrelsup, nreldep, need, nsubFB, minSFB;
1037 : ulong low, high, LIMC0, LIMC, LIMC2, LIMCMAX, cp;
1038 70534 : GEN W, cyc, gen, dep, mat, C, extraC, B, R, invhr, h = NULL; /*-Wall*/
1039 : double drc, sdrc, lim, LOGD, LOGD2;
1040 : GRHcheck_t GRHcheck;
1041 : struct qfr_data q;
1042 : struct buch_quad BQ;
1043 70534 : int FIRST = 1, use_mpqs = 0;
1044 : mpqs_handle_t H;
1045 : GEN missing_primes;
1046 :
1047 70534 : check_quaddisc(D, &s, /*junk*/&i, "Buchquad");
1048 70534 : R = NULL; /* -Wall */
1049 70534 : BQ.q = &q;
1050 70534 : q.D = D;
1051 70534 : if (s < 0)
1052 : {
1053 68378 : if (abscmpiu(q.D,4) <= 0)
1054 175 : retmkvec4(gen_1, cgetg(1,t_VEC), cgetg(1,t_VEC), gen_1);
1055 68203 : prec = BQ.PRECREG = 0;
1056 68203 : if (expi(D) >= MPQS_THRESHOLD)
1057 28 : use_mpqs = 1;
1058 : } else {
1059 2156 : BQ.PRECREG = maxss(prec+EXTRAPREC64, nbits2prec(2*expi(q.D) + 128));
1060 : }
1061 70359 : if (DEBUGLEVEL>2) timer_start(&T);
1062 70359 : BQ.primfact = new_chunk(100);
1063 70359 : BQ.exprimfact = new_chunk(100);
1064 70359 : BQ.hashtab = (long**) new_chunk(HASHT);
1065 72110305 : for (i=0; i<HASHT; i++) BQ.hashtab[i] = NULL;
1066 :
1067 70362 : drc = fabs(gtodouble(q.D));
1068 70359 : LOGD = log(drc);
1069 70359 : LOGD2 = LOGD * LOGD;
1070 :
1071 70359 : sdrc = lim = sqrt(drc);
1072 70359 : if (!BQ.PRECREG) lim /= sqrt(3.);
1073 70359 : cp = (ulong)exp(sqrt(LOGD*log(LOGD)/8.0));
1074 70359 : if (cp < 20) cp = 20;
1075 70359 : if (cbach > 6.) {
1076 0 : if (cbach2 < cbach) cbach2 = cbach;
1077 0 : cbach = 6.;
1078 : }
1079 70359 : if (cbach < 0.)
1080 0 : pari_err_DOMAIN("Buchquad","Bach constant","<",gen_0,dbltor(cbach));
1081 70359 : av = avma;
1082 70359 : BQ.powsubFB = BQ.subFB = NULL;
1083 70359 : minSFB = (expi(D) > 15)? 3: 2;
1084 70359 : init_GRHcheck(&GRHcheck, 2, BQ.PRECREG? 2: 0, LOGD);
1085 70360 : high = low = LIMC0 = maxss((long)(cbach2*LOGD2), 1);
1086 70360 : LIMCMAX = (long)(4.*LOGD2);
1087 : /* 97/1223 below to ensure a good enough approximation of residue */
1088 70360 : cache_prime_quad(&GRHcheck, expi(D) < 16 ? 97: 1223, D);
1089 587313 : while (!quadGRHchk(D, &GRHcheck, high))
1090 : {
1091 516951 : low = high;
1092 516951 : high *= 2;
1093 : }
1094 517020 : while (high - low > 1)
1095 : {
1096 446657 : long test = (low+high)/2;
1097 446657 : if (quadGRHchk(D, &GRHcheck, test))
1098 233958 : high = test;
1099 : else
1100 212702 : low = test;
1101 : }
1102 70363 : if (high == LIMC0+1 && quadGRHchk(D, &GRHcheck, LIMC0))
1103 0 : LIMC2 = LIMC0;
1104 : else
1105 70363 : LIMC2 = high;
1106 70363 : if (LIMC2 > LIMCMAX) LIMC2 = LIMCMAX;
1107 70363 : LIMC0 = (long)(cbach*LOGD2);
1108 70363 : LIMC = cbach ? LIMC0 : LIMC2;
1109 70363 : LIMC = maxss(LIMC, nthidealquad(D, 2));
1110 :
1111 : /* LIMC = Max(cbach*(log D)^2, exp(sqrt(log D loglog D) / 8)) */
1112 70373 : START:
1113 70373 : missing_primes = NULL;
1114 : do
1115 : {
1116 70506 : if (!FIRST) LIMC = bnf_increase_LIMC(LIMC,LIMCMAX);
1117 70506 : if (DEBUGLEVEL>2 && LIMC > LIMC0)
1118 0 : err_printf("%s*** Bach constant: %f\n", FIRST?"":"\n", LIMC/LOGD2);
1119 70506 : FIRST = 0; set_avma(av);
1120 70506 : guncloneNULL(BQ.subFB);
1121 70506 : guncloneNULL(BQ.powsubFB);
1122 70506 : clearhash(BQ.hashtab);
1123 70509 : if (LIMC < cp) LIMC = cp;
1124 70509 : if (LIMC2 < LIMC) LIMC2 = LIMC;
1125 70509 : if (BQ.PRECREG) qfr_data_init(q.D, BQ.PRECREG, &q);
1126 :
1127 70509 : FBquad(&BQ, LIMC2, LIMC, &GRHcheck);
1128 70504 : if (DEBUGLEVEL>2) timer_printf(&T, "factor base");
1129 70504 : BQ.subFB = subFBquad(&BQ, q.D, lim + 0.5, minSFB);
1130 70509 : if (DEBUGLEVEL>2) timer_printf(&T, "subFBquad = %Ps",
1131 : vecpermute(BQ.FB, BQ.subFB));
1132 70509 : nsubFB = lg(BQ.subFB) - 1;
1133 : }
1134 70509 : while (nsubFB < (expi(D) > 15 ? 3 : 2));
1135 : /* invhr = 2^r1 (2pi)^r2 / sqrt(D) w ~ L(chi,1) / hR */
1136 70376 : invhr = gmul(dbltor((BQ.PRECREG?2.:M_PI)/sdrc),
1137 : compute_invresquad(&GRHcheck, LIMC));
1138 70374 : BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1);
1139 70376 : if (DEBUGLEVEL>2) timer_printf(&T, "powsubFBquad");
1140 70376 : BQ.limhash = (LIMC & HIGHMASK)? (HIGHBIT>>1): LIMC*LIMC;
1141 :
1142 70376 : need = BQ.KC + RELSUP - 2;
1143 70376 : current = 0;
1144 70376 : W = NULL;
1145 70376 : sfb_trials = nreldep = nrelsup = 0;
1146 70376 : s = nsubFB + RELSUP;
1147 70376 : if (use_mpqs)
1148 28 : use_mpqs = mpqs_class_init(&H, D, BQ.KC);
1149 70376 : av2 = avma;
1150 :
1151 : do
1152 : {
1153 104644 : if ((nreldep & 3) == 1 || (nrelsup & 7) == 1) {
1154 28945 : if (DEBUGLEVEL>2) err_printf("*** Changing sub factor base\n");
1155 28945 : gunclone(BQ.subFB);
1156 28945 : gunclone(BQ.powsubFB);
1157 28945 : BQ.subFB = gclone(vecslice(BQ.vperm, 1, nsubFB));
1158 28945 : BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1);
1159 28945 : if (DEBUGLEVEL>2) timer_printf(&T, "powsubFBquad");
1160 28945 : clearhash(BQ.hashtab);
1161 : }
1162 104644 : if (!use_mpqs) need += 2;
1163 104644 : mat = cgetg(need+1, t_MAT);
1164 104643 : extraC = cgetg(need+1, t_VEC);
1165 104644 : if (!W) { /* first time */
1166 70376 : C = extraC;
1167 70376 : triv = trivial_relations(&BQ, mat, C);
1168 70374 : if (DEBUGLEVEL>2) err_printf("KC = %ld, need %ld relations\n", BQ.KC, need);
1169 : } else {
1170 34268 : triv = 0;
1171 34268 : if (DEBUGLEVEL>2) err_printf("...need %ld more relations\n", need);
1172 : }
1173 104642 : if (BQ.PRECREG) {
1174 189833 : for (i = triv+1; i<=need; i++) {
1175 184688 : gel(mat,i) = zero_zv(BQ.KC);
1176 184688 : gel(extraC,i) = mkcomplex(cgetr(BQ.PRECREG), cgeti(3));
1177 : }
1178 5145 : real_relations(&BQ, need - triv, ¤t, s,LIMC,mat + triv,extraC + triv);
1179 : } else {
1180 1719003 : for (i = triv+1; i<=need; i++) {
1181 1619511 : gel(mat,i) = zero_zv(BQ.KC);
1182 1619506 : gel(extraC,i) = gen_0;
1183 : }
1184 99492 : if (use_mpqs)
1185 336 : mpqs_relations(&BQ, need - triv, ¤t, LIMC,mat + triv, &H, missing_primes);
1186 : else
1187 99156 : imag_relations(&BQ, need - triv, ¤t, LIMC,mat + triv);
1188 : }
1189 104643 : if (DEBUGLEVEL>2) timer_start(&T);
1190 104643 : if (!W)
1191 70375 : W = hnfspec_i(mat,BQ.vperm,&dep,&B,&C,nsubFB);
1192 : else
1193 34268 : W = hnfadd_i(W,BQ.vperm,&dep,&B,&C, mat,extraC);
1194 104644 : if (DEBUGLEVEL>2) timer_printf(&T, "hnfadd");
1195 104644 : need = BQ.KC - (lg(W)-1) - (lg(B)-1);
1196 104644 : gerepileall(av2, 4, &W,&C,&B,&dep);
1197 104644 : missing_primes = vecslice(BQ.vperm,1,need);
1198 104644 : if (need)
1199 : {
1200 12946 : if (++nreldep > 15 && cbach < 1) goto START;
1201 12946 : continue;
1202 : }
1203 :
1204 91698 : h = ZM_det_triangular(W);
1205 91695 : if (DEBUGLEVEL>2) err_printf("\n#### Tentative class number: %Ps\n", h);
1206 :
1207 91695 : switch(get_R(&BQ, C, (lg(C)-1) - (lg(B)-1) - (lg(W)-1), mulir(h,invhr), &R))
1208 : {
1209 0 : case fupb_PRECI:
1210 0 : BQ.PRECREG = precdbl(BQ.PRECREG);
1211 0 : FIRST = 1; goto START;
1212 :
1213 21336 : case fupb_RELAT:
1214 21336 : if (++nrelsup > MAXRELSUP)
1215 : {
1216 63 : if (++sfb_trials > SFB_MAX && cbach <= 1) goto START;
1217 49 : if (nsubFB < minss(10,BQ.KC)) nsubFB++;
1218 : }
1219 21322 : need = minss(BQ.KC, nrelsup);
1220 : }
1221 : }
1222 104630 : while (need);
1223 : /* DONE */
1224 70362 : if (!quad_be_honest(&BQ)) goto START;
1225 70362 : if (DEBUGLEVEL>2) timer_printf(&T, "be honest");
1226 70362 : clearhash(BQ.hashtab);
1227 70362 : free_GRHcheck(&GRHcheck);
1228 :
1229 70362 : gen = get_clgp(&BQ,W,&cyc);
1230 70359 : gunclone(BQ.subFB);
1231 70362 : gunclone(BQ.powsubFB);
1232 70361 : if (BQ.PRECREG)
1233 2156 : return mkvec5(h, cyc, gen, real_i(R), mpodd(imag_i(R)) ? gen_m1:gen_1);
1234 : else
1235 68205 : return mkvec4(h, cyc, gen, real_i(R));
1236 : }
1237 : GEN
1238 4424 : Buchquad(GEN D, double c, double c2, long prec)
1239 : {
1240 4424 : pari_sp av = avma;
1241 4424 : GEN z = Buchquad_i(D, c, c2, prec);
1242 4424 : return gerepilecopy(av, z);
1243 : }
1244 :
1245 : GEN
1246 0 : buchimag(GEN D, GEN c, GEN c2, GEN REL)
1247 0 : { (void)REL; return Buchquad(D,gtodouble(c),gtodouble(c2),0); }
1248 :
1249 : GEN
1250 0 : buchreal(GEN D, GEN flag, GEN c, GEN c2, GEN REL, long prec) {
1251 0 : if (signe(flag)) pari_err_IMPL("narrow class group");
1252 0 : (void)REL; return Buchquad(D,gtodouble(c),gtodouble(c2),prec);
1253 : }
1254 :
1255 : GEN
1256 4424 : quadclassunit0(GEN x, long flag, GEN data, long prec)
1257 : {
1258 : long lx;
1259 4424 : double c1 = 0.0, c2 = 0.0;
1260 :
1261 4424 : if (!data) lx=1;
1262 : else
1263 : {
1264 28 : lx = lg(data);
1265 28 : if (typ(data)!=t_VEC) pari_err_TYPE("quadclassunit", data);
1266 28 : if (lx > 7) pari_err_DIM("quadclassunit [tech vector]");
1267 28 : if (lx > 3) lx = 3;
1268 : }
1269 4424 : switch(lx)
1270 : {
1271 21 : case 3: c2 = gtodouble(gel(data,2));
1272 28 : case 2: c1 = gtodouble(gel(data,1));
1273 : }
1274 4424 : if (flag) pari_err_IMPL("narrow class group");
1275 4424 : return Buchquad(x,c1,c2,prec);
1276 : }
1277 : GEN
1278 61169 : quadclassno(GEN D)
1279 : {
1280 61169 : pari_sp av = avma;
1281 61169 : GEN h = abgrp_get_no(Buchquad_i(D, 0, 0, 0));
1282 61174 : return icopy_avma(h, av);
1283 : }
1284 : long
1285 4938 : quadclassnos(long D)
1286 : {
1287 4938 : pari_sp av = avma;
1288 4938 : long h = itos(abgrp_get_no(Buchquad_i(stoi(D), 0, 0, 0)));
1289 4938 : return gc_long(av, h);
1290 : }
|