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 2565477 : 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 = gc_GEN(av, x);
111 : }
112 : }
113 220157 : return gc_GEN(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 4060988 : init_form(struct buch_quad *B, GEN ex,
135 : GEN (*comp)(GEN,GEN,struct qfr_data *S))
136 : {
137 4060988 : long i, l = lg(B->powsubFB);
138 4060988 : GEN F = NULL;
139 22911401 : for (i=1; i<l; i++)
140 18859807 : if (ex[i])
141 : {
142 17682427 : GEN t = gmael(B->powsubFB,i,ex[i]);
143 17682427 : F = F? comp(F, t, B->q): t;
144 : }
145 4051594 : 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 11740383 : QFI_comp(GEN x, GEN y, struct qfr_data *S) { (void)S; return qfbcomp_i(x,y); }
152 :
153 : static GEN
154 160540 : qfi_factorback(struct buch_quad *B, GEN ex) { return init_form(B, ex, &QFI_comp); }
155 :
156 : static GEN
157 3703276 : random_form(struct buch_quad *B, GEN ex,
158 : GEN (*comp)(GEN,GEN, struct qfr_data *S))
159 : {
160 3703276 : long i, l = lg(ex);
161 3703276 : pari_sp av = avma;
162 : GEN F;
163 : for(;;)
164 : {
165 20591468 : for (i=1; i<l; i++) ex[i] = random_bits(RANDOM_BITS);
166 3703479 : if ((F = init_form(B, ex, comp))) return F;
167 463 : 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 3541751 : 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 2333 : bnf_increase_LIMC(ulong LIMC, ulong D)
187 : {
188 2333 : if (LIMC >= D) pari_err_BUG("Buchmann's algorithm");
189 2333 : if (LIMC <= D / 13.333)
190 240 : LIMC *= 2; /* tiny c <= 0.3 : double it */
191 : else
192 2093 : LIMC += maxuu(1, D / 20); /* large c, add 0.2 to it */
193 2333 : if (LIMC > D) LIMC = D;
194 2333 : 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 5029413 : Z_isquasismooth_prod(GEN N, GEN P)
206 : {
207 5029413 : P = gcdii(P,N);
208 10032099 : while (!is_pm1(P))
209 : {
210 4997779 : N = diviiexact(N, P);
211 5005082 : P = gcdii(N, P);
212 : }
213 5025593 : return N;
214 : }
215 :
216 : static long
217 5036130 : factorquad(struct buch_quad *B, GEN f, long nFB, ulong limp)
218 : {
219 : ulong X;
220 5036130 : long i, lo = 0;
221 5036130 : GEN F, x = gel(f,1), FB = B->FB, P = B->primfact, E = B->exprimfact;
222 5036130 : if (B->badprim && !is_pm1(gcdii(x, B->badprim))) return 0;
223 5029193 : F = Z_isquasismooth_prod(x, B->prodFB);
224 5025390 : if (cmpiu(F, B->limhash) > 0) return 0;
225 4401472 : 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 4391056 : X = uel(x,2);
242 4391056 : if (X == 1) { P[0] = 0; return 1; }
243 68607573 : for (;; i++)
244 68607573 : { /* single precision affair, split for efficiency */
245 72979881 : ulong p = uel(FB,i);
246 72979881 : ulong q = X / p, r = X % p; /* gcc makes a single div */
247 72979881 : if (!r)
248 : {
249 5620963 : long k = 0;
250 6787847 : do { k++; X = q; q = X / p; r = X % p; } while (!r);
251 5620963 : lo++; P[lo] = p; E[lo] = k;
252 : }
253 72979881 : if (q <= p) break;
254 68641227 : if (i == nFB) return 0;
255 : }
256 4338655 : END:
257 4338655 : if (X > B->limhash) return 0;
258 4338655 : if (X != 1 && X <= limp) { lo++; P[lo] = X; E[lo] = 1; X = 1; }
259 4338655 : 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 2565463 : largeprime(struct buch_quad *B, long q, GEN ex, long np, long nrho)
265 : {
266 2565463 : const long hashv = hash(q);
267 2565478 : long *pt, i, l = lg(B->subFB);
268 :
269 2787239 : for (pt = B->hashtab[hashv]; ; pt = (long*) pt[0])
270 : {
271 2787239 : if (!pt)
272 : {
273 2366213 : pt = (long*) pari_malloc((l+3) * sizeof(long));
274 2366515 : *pt++ = nrho; /* nrho = pt[-3] */
275 2366515 : *pt++ = np; /* np = pt[-2] */
276 2366515 : *pt++ = q; /* q = pt[-1] */
277 2366515 : pt[0] = (long)B->hashtab[hashv];
278 14990157 : for (i=1; i<l; i++) pt[i]=ex[i];
279 2366515 : B->hashtab[hashv]=pt; return NULL;
280 : }
281 421026 : if (pt[-1] == q) break;
282 : }
283 237826 : for(i=1; i<l; i++)
284 234566 : if (pt[i] != ex[i]) return pt;
285 3260 : return (pt[-2]==np)? NULL: pt;
286 : }
287 :
288 : static void
289 169623 : clearhash(long **hash)
290 : {
291 : long *pt;
292 : long i;
293 173836855 : for (i=0; i<HASHT; i++) {
294 176033781 : for (pt = hash[i]; pt; ) {
295 2366549 : void *z = (void*)(pt - 3);
296 2366549 : pt = (long*) pt[0]; pari_free(z);
297 : }
298 173667232 : hash[i] = NULL;
299 : }
300 168567 : }
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 400850 : GRH_ensure(GRHcheck_t *S, long nb)
308 : {
309 400850 : 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 400850 : }
315 : /* cache data for all primes up to the LIM */
316 : static void
317 1174151 : cache_prime_quad(GRHcheck_t *S, ulong LIM, GEN D)
318 : {
319 : GRHprime_t *pr;
320 : long nb;
321 :
322 1174151 : if (S->limp >= LIM) return;
323 72433 : nb = (long)primepi_upper_bound((double)LIM); /* #{p <= LIM} <= nb */
324 72437 : GRH_ensure(S, nb+1); /* room for one extra prime */
325 72437 : for (pr = S->primes + S->nprimes;;)
326 12670473 : {
327 12742910 : ulong p = u_forprime_next(&(S->P));
328 12742778 : pr->p = p;
329 12742778 : pr->logp = log((double)p);
330 12742778 : pr->dec = (GEN)kroiu(D,p);
331 12742910 : S->nprimes++;
332 12742910 : pr++;
333 : /* store up to nextprime(LIM) included */
334 12742910 : if (p >= LIM) { S->limp = p; break; }
335 : }
336 : }
337 :
338 : static GEN
339 70313 : compute_invresquad(GRHcheck_t *S, long LIMC)
340 : {
341 70313 : pari_sp av = avma;
342 70313 : GEN invres = real_1(DEFAULTPREC);
343 70313 : double limp = log((double)LIMC) / 2;
344 : GRHprime_t *pr;
345 : long i;
346 12748372 : for (pr = S->primes, i = S->nprimes; i > 0; pr++, i--)
347 : {
348 12680851 : long s = (long)pr->dec;
349 12680851 : if (s)
350 : {
351 12564484 : ulong p = pr->p;
352 12564484 : if (s > 0 || pr->logp <= limp)
353 : /* Both p and P contribute */
354 6394049 : invres = mulur(p - s, divru(invres, p));
355 6170435 : else if (s<0)
356 : /* Only p contributes */
357 6170427 : invres = mulur(p, divru(invres, p - 1));
358 : }
359 : }
360 67521 : return gc_uptoleaf(av, invres);
361 : }
362 :
363 : /* p | conductor of order of disc D ? */
364 : static int
365 391719 : is_bad(GEN D, ulong p)
366 : {
367 391719 : pari_sp av = avma;
368 391719 : if (p == 2)
369 : {
370 89538 : long r = mod16(D) >> 1;
371 89538 : if (r && signe(D) < 0) r = 8-r;
372 89538 : return (r < 4);
373 : }
374 302181 : 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 70300 : nthidealquad(GEN D, long n)
380 : {
381 70300 : pari_sp av = avma;
382 : forprime_t S;
383 : ulong p;
384 70300 : (void)u_forprime_init(&S, 2, ULONG_MAX);
385 357442 : while ((p = u_forprime_next(&S)) && n > 0)
386 287146 : if (!is_bad(D, p) && kroiu(D, p) >= 0) n--;
387 70294 : return gc_long(av, p);
388 : }
389 :
390 : static int
391 1033478 : quadGRHchk(GEN D, GRHcheck_t *S, ulong LIMC)
392 : {
393 1033478 : double logC = log((double)LIMC), SA = 0, SB = 0;
394 : long i;
395 :
396 1033478 : cache_prime_quad(S, LIMC, D);
397 1033467 : for (i = 0;; i++)
398 29530865 : {
399 30564332 : GRHprime_t *pr = S->primes+i;
400 30564332 : ulong p = pr->p;
401 : long M;
402 : double logNP, q, A, B;
403 30564332 : if (p > LIMC) break;
404 29620111 : if ((long)pr->dec < 0)
405 : {
406 14788933 : logNP = 2 * pr->logp;
407 14788933 : q = 1/(double)p;
408 : }
409 : else
410 : {
411 14831178 : logNP = pr->logp;
412 14831178 : q = 1/sqrt((double)p);
413 : }
414 29620111 : A = logNP * q; B = logNP * A; M = (long)(logC/logNP);
415 29620111 : if (M > 1)
416 : {
417 2502181 : double inv1_q = 1 / (1-q);
418 2502181 : A *= (1 - pow(q, (double) M)) * inv1_q;
419 2502181 : B *= (1 - pow(q, (double) M)*(M+1 - M*q)) * inv1_q * inv1_q;
420 : }
421 29620111 : if ((long)pr->dec>0) { SA += 2*A;SB += 2*B; } else { SA += A; SB += B; }
422 29620111 : if (p == LIMC) break;
423 : }
424 1033467 : 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 70384 : FBquad(struct buch_quad *B, ulong C2, ulong C1, GRHcheck_t *S)
430 : {
431 70384 : GEN D = B->q->D;
432 : long i;
433 : pari_sp av;
434 : GRHprime_t *pr;
435 :
436 70384 : cache_prime_quad(S, C2, D);
437 70384 : pr = S->primes;
438 70384 : B->numFB = cgetg(C2+1, t_VECSMALL);
439 70384 : B->FB = cgetg(C2+1, t_VECSMALL);
440 70368 : av = avma;
441 70368 : B->KC = 0; i = 0;
442 70368 : B->badprim = gen_1;
443 2812307 : for (;; pr++) /* p <= C2 */
444 2812307 : {
445 2882675 : ulong p = pr->p;
446 2882675 : if (!B->KC && p > C1) B->KC = i;
447 2882675 : if (p > C2) break;
448 2819788 : switch ((long)pr->dec)
449 : {
450 1389582 : case -1: break; /* inert */
451 104574 : case 0: /* ramified */
452 104574 : if (is_bad(D, p)) { B->badprim = muliu(B->badprim, p); break; }
453 : /* fall through */
454 : default: /* split */
455 1430158 : i++; B->numFB[p] = i; B->FB[i] = p; break;
456 : }
457 2819803 : if (p == C2)
458 : {
459 7496 : if (!B->KC) B->KC = i;
460 7496 : break;
461 : }
462 : }
463 70383 : B->KC2 = i;
464 70383 : setlg(B->FB, B->KC2+1);
465 70383 : if (B->badprim != gen_1)
466 42 : B->badprim = gc_INT(av, B->badprim);
467 : else
468 : {
469 70341 : B->badprim = NULL; set_avma(av);
470 : }
471 70384 : B->prodFB = zv_prod_Z(B->FB);
472 70384 : }
473 :
474 : /* create B->vperm, return B->subFB */
475 : static GEN
476 70384 : subFBquad(struct buch_quad *B, GEN D, double PROD, long minSFB)
477 : {
478 70384 : long i, j, lgsub = 1, ino = 1, lv = B->KC+1;
479 70384 : double prod = 1.;
480 : pari_sp av;
481 : GEN no;
482 :
483 70384 : B->vperm = cgetg(lv, t_VECSMALL);
484 70384 : av = avma;
485 70384 : no = cgetg(lv, t_VECSMALL);
486 334592 : for (j = 1; j < lv; j++)
487 : {
488 334515 : ulong p = uel(B->FB,j);
489 334515 : if (!umodiu(D, p)) no[ino++] = j; /* ramified */
490 : else
491 : {
492 254848 : B->vperm[lgsub++] = j;
493 254848 : prod *= p;
494 254848 : if (lgsub > minSFB && prod > PROD) break;
495 : }
496 : }
497 : /* lgsub >= 1 otherwise quadGRHchk is false */
498 70384 : i = lgsub;
499 150051 : for (j = 1; j < ino;i++,j++) B->vperm[i] = no[j];
500 1165654 : for ( ; i < lv; i++) B->vperm[i] = i;
501 70384 : no = gclone(vecslice(B->vperm, 1, lgsub-1));
502 70384 : 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 99264 : powsubFBquad(struct buch_quad *B, long n)
508 : {
509 99264 : pari_sp av = avma;
510 99264 : long i,j, l = lg(B->subFB);
511 99264 : GEN F, y, x = cgetg(l, t_VEC), D = B->q->D;
512 :
513 99263 : 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 427394 : for (i=1; i<l; i++)
526 : {
527 333261 : F = qfi_pf(D, B->FB[B->subFB[i]]);
528 333244 : y = cgetg(n+1, t_VEC); gel(x,i) = y;
529 333870 : gel(y,1) = F;
530 5323380 : for (j=2; j<=n; j++) gel(y,j) = qfbcomp_i(gel(y,j-1), F);
531 : }
532 : }
533 99250 : x = gclone(x); set_avma(av); return x;
534 : }
535 :
536 : static void
537 98269 : sub_fact(struct buch_quad *B, GEN col, GEN F)
538 : {
539 98269 : GEN b = gel(F,2);
540 : long i;
541 208020 : for (i=1; i<=B->primfact[0]; i++)
542 : {
543 109751 : ulong p = B->primfact[i], k = B->numFB[p];
544 109751 : long e = B->exprimfact[i];
545 109751 : if (umodiu(b, p<<1) > p) e = -e;
546 109751 : col[k] -= e;
547 : }
548 98269 : }
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 1891869 : add_fact(struct buch_quad *B, GEN col, GEN F)
580 : {
581 1891869 : GEN b = gel(F,2);
582 : long i;
583 5929817 : for (i=1; i<=B->primfact[0]; i++)
584 : {
585 4037777 : ulong p = B->primfact[i], k = B->numFB[p];
586 4037777 : long e = B->exprimfact[i];
587 4037777 : if (umodiu(b, p<<1) > p) e = -e;
588 4037948 : col[k] += e;
589 : }
590 1892040 : }
591 :
592 : static GEN
593 70300 : get_clgp(struct buch_quad *B, GEN W, GEN *ptD)
594 : {
595 70300 : GEN res, init, u1, D = ZM_snf_group(W,NULL,&u1);
596 70299 : long i, j, l = lg(W), c = lg(D);
597 :
598 70299 : res=cgetg(c,t_VEC); init = cgetg(l,t_VEC);
599 216083 : for (i=1; i<l; i++) gel(init,i) = primeform_u(B->q->D, B->FB[B->vperm[i]]);
600 195711 : for (j=1; j<c; j++)
601 : {
602 125413 : GEN g = NULL;
603 125413 : 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 423638 : for (i=1; i<l; i++)
617 : {
618 301936 : GEN t, u = gcoeff(u1,i,j);
619 301936 : if (!signe(u)) continue;
620 203559 : t = powgi(gel(init,i), u);
621 203559 : g = g? qfbcomp_i(g, t): t;
622 : }
623 : }
624 125413 : gel(res,j) = g;
625 : }
626 70298 : *ptD = D; return res;
627 : }
628 :
629 : static long
630 70314 : trivial_relations(struct buch_quad *B, GEN mat, GEN C)
631 : {
632 70314 : long i, j = 0;
633 70314 : GEN col, D = B->q->D;
634 1499837 : for (i = 1; i <= B->KC; i++)
635 : { /* ramified prime ==> trivial relation */
636 1429520 : if (umodiu(D, B->FB[i])) continue;
637 104312 : col = zero_zv(B->KC);
638 104314 : col[i] = 2; j++;
639 104314 : gel(mat,j) = col;
640 104314 : gel(C,j) = gen_0;
641 : }
642 70317 : 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 99057 : imag_relations(struct buch_quad *B, long need, long *pc, ulong LIMC, GEN mat)
668 : {
669 : pari_timer T;
670 99057 : long lgsub = lg(B->subFB), current = *pc, nbtest = 0, s = 0;
671 : long i, fpc;
672 : pari_sp av;
673 99057 : GEN col, form, ex = cgetg(lgsub, t_VECSMALL);
674 :
675 99057 : if (!current) current = 1;
676 99057 : if (DEBUGLEVEL>2) timer_start(&T);
677 99057 : av = avma;
678 : for(;;)
679 : {
680 3640410 : if (s >= need) break;
681 3541353 : set_avma(av);
682 3541261 : form = qfi_random(B,ex);
683 3538982 : form = qfbcomp_i(form, qfi_pf(B->q->D, B->FB[current]));
684 3538751 : nbtest++; fpc = factorquad(B,form,B->KC,LIMC);
685 3540498 : 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 3248934 : if (fpc > 1)
692 : {
693 1800365 : long *fpd = largeprime(B,fpc,ex,current,0);
694 : ulong b1, b2, p;
695 : GEN form2;
696 1800866 : if (!fpd)
697 : {
698 1640361 : if (DEBUGLEVEL>3) err_printf(".");
699 1640361 : continue;
700 : }
701 160505 : form2 = qfbcomp_i(qfi_factorback(B,fpd), qfi_pf(B->q->D, B->FB[fpd[-2]]));
702 160543 : p = fpc << 1;
703 160543 : b1 = umodiu(gel(form2,2), p);
704 160542 : b2 = umodiu(gel(form,2), p);
705 160544 : if (b1 != b2 && b1+b2 != p) continue;
706 :
707 160544 : col = gel(mat,++s);
708 160544 : add_fact(B,col, form);
709 160542 : (void)factorquad(B,form2,B->KC,LIMC);
710 160544 : if (b1==b2)
711 : {
712 414899 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += fpd[i]-ex[i];
713 80639 : sub_fact(B, col, form2); col[fpd[-2]]++;
714 : }
715 : else
716 : {
717 410127 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += -fpd[i]-ex[i];
718 79905 : add_fact(B, col, form2); col[fpd[-2]]--;
719 : }
720 160548 : if (DEBUGLEVEL>2) err_printf(" %ldP",s);
721 : }
722 : else
723 : {
724 1448569 : col = gel(mat,++s);
725 6958405 : for (i=1; i<lgsub; i++) col[B->subFB[i]] = -ex[i];
726 1448569 : add_fact(B, col, form);
727 1448999 : if (DEBUGLEVEL>2) err_printf(" %ld",s);
728 : }
729 1609428 : col[current]--;
730 1609428 : if (++current > B->KC) current = 1;
731 : }
732 99057 : if (DEBUGLEVEL>2) dbg_all(&T, "random", s, nbtest);
733 99057 : *pc = current;
734 99057 : }
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) { return mkvec2(qfr5_dist(e, d, prec), d); }
777 : /* z a pre-allocated pair [t_REAL, t_INT], D = [t,d] from dist() */
778 : static void
779 184688 : dist_set(GEN z, GEN D)
780 : {
781 184688 : affrr(gel(D,1), gel(z,1));
782 184688 : affsi(signe(gel(D,2)) < 0? 1: 0, gel(z,2));
783 184688 : }
784 :
785 : /* Real Quadratic fields */
786 :
787 : static void
788 5145 : real_relations(struct buch_quad *B, long need, long *pc, long lim, ulong LIMC, GEN mat, GEN C)
789 : {
790 : pari_timer T;
791 5145 : long lgsub = lg(B->subFB), prec = B->PRECREG, current = *pc, nbtest=0, s=0;
792 : long i, fpc, endcycle, rhoacc, rho;
793 : /* in a 2nd phase, don't include FB[current] but run along the cyle
794 : * ==> get more units */
795 5145 : int first = (current == 0);
796 : pari_sp av, av1;
797 5145 : GEN d, col, form, form0, form1, ex = cgetg(lgsub, t_VECSMALL);
798 :
799 5145 : if (DEBUGLEVEL>2) timer_start(&T);
800 5145 : if (!current) current = 1;
801 5145 : if (lim > need) lim = need;
802 5145 : av = avma;
803 : for(;;)
804 : {
805 166691 : if (s >= need) break;
806 161546 : if (first && s >= lim) {
807 2142 : first = 0;
808 2142 : if (DEBUGLEVEL>2) dbg_all(&T, "initial", s, nbtest);
809 : }
810 161546 : set_avma(av); form = qfr3_random(B, ex);
811 161546 : if (!first)
812 159369 : form = QFR3_comp(form, qfr3_pf(B->q, B->FB[current]), B->q);
813 161546 : av1 = avma;
814 161546 : form0 = form; form1 = NULL;
815 161546 : endcycle = rhoacc = 0;
816 161546 : rho = -1;
817 :
818 1300964 : CYCLE:
819 1300964 : if (endcycle || rho > 5000)
820 : {
821 21 : if (++current > B->KC) current = 1;
822 21 : continue;
823 : }
824 1300943 : if (gc_needed(av,1))
825 : {
826 0 : if(DEBUGMEM>1) pari_warn(warnmem,"real_relations");
827 0 : (void)gc_all(av1, form1? 2: 1, &form, &form1);
828 : }
829 1300943 : if (rho < 0) rho = 0; /* first time in */
830 : else
831 : {
832 1139397 : form = qfr3_rho(form, B->q); rho++;
833 1139397 : rhoacc++;
834 1139397 : if (first)
835 442526 : endcycle = (absequalii(gel(form,1),gel(form0,1))
836 221263 : && equalii(gel(form,2),gel(form0,2)));
837 : else
838 : {
839 918134 : if (absequalii(gel(form,1), gel(form,3))) /* a = -c */
840 : {
841 0 : if (absequalii(gel(form,1),gel(form0,1)) &&
842 0 : equalii(gel(form,2),gel(form0,2))) continue;
843 0 : form = qfr3_rho(form, B->q); rho++;
844 0 : rhoacc++;
845 : }
846 : else
847 918134 : { setsigne(form[1],1); setsigne(form[3],-1); }
848 918176 : if (equalii(gel(form,1),gel(form0,1)) &&
849 42 : equalii(gel(form,2),gel(form0,2))) continue;
850 : }
851 : }
852 1300943 : nbtest++; fpc = factorquad(B,form,B->KC,LIMC);
853 1300943 : if (!fpc)
854 : {
855 386778 : if (DEBUGLEVEL>3) err_printf(".");
856 386778 : goto CYCLE;
857 : }
858 914165 : if (fpc > 1)
859 : { /* look for Large Prime relation */
860 764946 : long *fpd = largeprime(B,fpc,ex,first? 0: current,rhoacc);
861 : ulong b1, b2, p;
862 : GEN form2;
863 764946 : if (!fpd)
864 : {
865 729477 : if (DEBUGLEVEL>3) err_printf(".");
866 729477 : goto CYCLE;
867 : }
868 35469 : if (!form1)
869 : {
870 35469 : form1 = qfr5_factorback(B,ex);
871 35469 : if (!first)
872 35469 : form1 = QFR5_comp(form1, qfr5_pf(B->q, B->FB[current], prec), B->q);
873 : }
874 35469 : form1 = qfr5_rho_pow(form1, rho, B->q);
875 35469 : rho = 0;
876 :
877 35469 : form2 = qfr5_factorback(B,fpd);
878 35469 : if (fpd[-2])
879 23709 : form2 = QFR5_comp(form2, qfr5_pf(B->q, B->FB[fpd[-2]], prec), B->q);
880 35469 : form2 = qfr5_rho_pow(form2, fpd[-3], B->q);
881 35469 : if (!absequalii(gel(form2,1),gel(form2,3)))
882 : {
883 35469 : setsigne(form2[1], 1);
884 35469 : setsigne(form2[3],-1);
885 : }
886 35469 : p = fpc << 1;
887 35469 : b1 = umodiu(gel(form2,2), p);
888 35469 : b2 = umodiu(gel(form1,2), p);
889 35469 : if (b1 != b2 && b1+b2 != p) goto CYCLE;
890 :
891 35469 : col = gel(mat,++s);
892 35469 : add_fact(B, col, form1);
893 35469 : (void)factorquad(B,form2,B->KC,LIMC);
894 35469 : if (b1==b2)
895 : {
896 135100 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += fpd[i]-ex[i];
897 17626 : sub_fact(B,col, form2);
898 17626 : if (fpd[-2]) col[fpd[-2]]++;
899 17626 : d = dist(subii(gel(form1,4),gel(form2,4)),
900 17626 : divrr(gel(form1,5),gel(form2,5)), prec);
901 : }
902 : else
903 : {
904 136780 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += -fpd[i]-ex[i];
905 17843 : add_fact(B, col, form2);
906 17843 : if (fpd[-2]) col[fpd[-2]]--;
907 17843 : d = dist(addii(gel(form1,4),gel(form2,4)),
908 17843 : mulrr(gel(form1,5),gel(form2,5)), prec);
909 : }
910 35469 : if (DEBUGLEVEL>2) err_printf(" %ldP",s);
911 : }
912 : else
913 : { /* standard relation */
914 149219 : if (!form1)
915 : {
916 126077 : form1 = qfr5_factorback(B, ex);
917 126077 : if (!first)
918 123900 : form1 = QFR5_comp(form1, qfr5_pf(B->q, B->FB[current], prec), B->q);
919 : }
920 149219 : form1 = qfr5_rho_pow(form1, rho, B->q);
921 149219 : rho = 0;
922 :
923 149219 : col = gel(mat,++s);
924 1147489 : for (i=1; i<lgsub; i++) col[B->subFB[i]] = -ex[i];
925 149219 : add_fact(B, col, form1);
926 149219 : d = dist(gel(form1,4), gel(form1,5), prec);
927 149219 : if (DEBUGLEVEL>2) err_printf(" %ld",s);
928 : }
929 184688 : dist_set(gel(C,s), d);
930 184688 : if (first)
931 : {
932 25319 : if (s >= lim) continue;
933 23163 : goto CYCLE;
934 : }
935 : else
936 : {
937 159369 : col[current]--;
938 159369 : if (++current > B->KC) current = 1;
939 : }
940 : }
941 5145 : if (DEBUGLEVEL>2) dbg_all(&T, "random", s, nbtest);
942 5145 : *pc = current;
943 5145 : }
944 :
945 : static int
946 7 : real_be_honest(struct buch_quad *B)
947 : {
948 7 : long p, fpc, s = B->KC, nbtest = 0;
949 7 : GEN F,F0, ex = cgetg(lg(B->subFB), t_VECSMALL);
950 7 : pari_sp av = avma;
951 :
952 28 : while (s<B->KC2)
953 : {
954 21 : p = B->FB[s+1]; if (DEBUGLEVEL>2) err_printf(" %ld",p);
955 21 : F = QFR3_comp(qfr3_random(B, ex), qfr3_pf(B->q, p), B->q);
956 21 : for (F0 = F;;)
957 : {
958 49 : fpc = factorquad(B,F,s,p-1);
959 49 : if (fpc == 1) { nbtest=0; s++; break; }
960 28 : if (++nbtest > 40) return 0;
961 28 : F = qfr3_canon(qfr3_rho(F, B->q), B->q);
962 28 : if (equalii(gel(F,1),gel(F0,1))
963 0 : && equalii(gel(F,2),gel(F0,2))) break;
964 : }
965 21 : set_avma(av);
966 : }
967 7 : return 1;
968 : }
969 :
970 : static GEN
971 55146 : crabs(GEN a)
972 : {
973 55146 : return signe(real_i(a)) < 0 ? gneg(a): a;
974 : }
975 :
976 : static GEN
977 33978 : gcdreal(GEN a,GEN b)
978 : {
979 33978 : if (!signe(real_i(a))) return crabs(b);
980 33012 : if (!signe(real_i(b))) return crabs(a);
981 32897 : if (expo(real_i(a))<-5) return crabs(b);
982 12040 : if (expo(real_i(b))<-5) return crabs(a);
983 9093 : a = crabs(a); b = crabs(b);
984 20019 : while (expo(real_i(b)) >= -5 && signe(real_i(b)))
985 : {
986 : long e;
987 10926 : GEN r, q = gcvtoi(divrr(real_i(a),real_i(b)),&e);
988 10926 : if (e > 0) return NULL;
989 10926 : r = gsub(a, gmul(q,b)); a = b; b = r;
990 : }
991 9093 : return crabs(a);
992 : }
993 :
994 : static int
995 91575 : get_R(struct buch_quad *B, GEN C, long sreg, GEN z, GEN *ptR)
996 : {
997 91575 : GEN R = gen_1;
998 : double c;
999 : long i;
1000 91575 : if (B->PRECREG)
1001 : {
1002 2982 : R = crabs(gel(C,1));
1003 36960 : for (i=2; i<=sreg; i++)
1004 : {
1005 33978 : R = gcdreal(gel(C,i), R);
1006 33978 : if (!R) return fupb_PRECI;
1007 : }
1008 2982 : if (gexpo(real_i(R)) <= -3)
1009 : {
1010 0 : if (DEBUGLEVEL>2) err_printf("regulator is zero.\n");
1011 0 : return fupb_RELAT;
1012 : }
1013 2982 : if (DEBUGLEVEL>2) err_printf("#### Tentative regulator: %Ps\n",R);
1014 : }
1015 91575 : c = gtodouble(gmul(z, real_i(R)));
1016 91575 : if (c < 0.8 || c > 1.3) return fupb_RELAT;
1017 70297 : *ptR = R; return fupb_NONE;
1018 : }
1019 :
1020 : static int
1021 70297 : quad_be_honest(struct buch_quad *B)
1022 : {
1023 : int r;
1024 70297 : if (B->KC2 <= B->KC) return 1;
1025 14 : if (DEBUGLEVEL>2)
1026 0 : err_printf("be honest for primes from %ld to %ld\n", B->FB[B->KC+1],B->FB[B->KC2]);
1027 14 : r = B->PRECREG? real_be_honest(B): imag_be_honest(B);
1028 14 : if (DEBUGLEVEL>2) err_printf("\n");
1029 14 : return r;
1030 : }
1031 :
1032 : static GEN
1033 70475 : Buchquad_i(GEN D, double cbach, double cbach2, long prec)
1034 : {
1035 70475 : const long MAXRELSUP = 20, SFB_MAX = 3, MPQS_THRESHOLD = 60;
1036 : pari_timer T;
1037 : pari_sp av, av2;
1038 70475 : const long RELSUP = 5;
1039 : long i, s, current, triv, sfb_trials, nrelsup, nreldep, need, nsubFB, minSFB;
1040 : ulong low, high, LIMC0, LIMC, LIMC2, LIMCMAX, cp;
1041 70475 : GEN W, cyc, gen, dep, mat, C, extraC, B, R, invhr, h = NULL; /*-Wall*/
1042 : double drc, sdrc, lim, LOGD, LOGD2;
1043 : GRHcheck_t GRHcheck;
1044 : struct qfr_data q;
1045 : struct buch_quad BQ;
1046 70475 : int FIRST = 1, use_mpqs = 0;
1047 : mpqs_handle_t H;
1048 : GEN missing_primes;
1049 :
1050 70475 : check_quaddisc(D, &s, /*junk*/&i, "Buchquad");
1051 70474 : R = NULL; /* -Wall */
1052 70474 : BQ.q = &q;
1053 70474 : q.D = D;
1054 70474 : if (s < 0)
1055 : {
1056 68318 : if (abscmpiu(q.D,4) <= 0)
1057 175 : retmkvec4(gen_1, cgetg(1,t_VEC), cgetg(1,t_VEC), gen_1);
1058 68143 : prec = BQ.PRECREG = 0;
1059 68143 : if (expi(D) >= MPQS_THRESHOLD)
1060 28 : use_mpqs = 1;
1061 : } else {
1062 2156 : BQ.PRECREG = maxss(prec+EXTRAPREC64, nbits2prec(2*expi(q.D) + 128));
1063 : }
1064 70299 : if (DEBUGLEVEL>2) timer_start(&T);
1065 70299 : BQ.primfact = new_chunk(100);
1066 70299 : BQ.exprimfact = new_chunk(100);
1067 70299 : BQ.hashtab = (long**) new_chunk(HASHT);
1068 72052903 : for (i=0; i<HASHT; i++) BQ.hashtab[i] = NULL;
1069 :
1070 70300 : drc = fabs(gtodouble(q.D));
1071 70300 : LOGD = log(drc);
1072 70300 : LOGD2 = LOGD * LOGD;
1073 :
1074 70300 : sdrc = lim = sqrt(drc);
1075 70300 : if (!BQ.PRECREG) lim /= sqrt(3.);
1076 70300 : cp = (ulong)exp(sqrt(LOGD*log(LOGD)/8.0));
1077 70300 : if (cp < 20) cp = 20;
1078 70300 : if (cbach > 6.) {
1079 0 : if (cbach2 < cbach) cbach2 = cbach;
1080 0 : cbach = 6.;
1081 : }
1082 70300 : if (cbach < 0.)
1083 0 : pari_err_DOMAIN("Buchquad","Bach constant","<",gen_0,dbltor(cbach));
1084 70300 : av = avma;
1085 70300 : BQ.powsubFB = BQ.subFB = NULL;
1086 70300 : minSFB = (expi(D) > 15)? 3: 2;
1087 70300 : init_GRHcheck(&GRHcheck, 2, BQ.PRECREG? 2: 0, LOGD);
1088 70300 : high = low = LIMC0 = maxss((long)(cbach2*LOGD2), 1);
1089 70300 : LIMCMAX = (long)(4.*LOGD2);
1090 : /* 97/1223 below to ensure a good enough approximation of residue */
1091 70300 : cache_prime_quad(&GRHcheck, expi(D) < 16 ? 97: 1223, D);
1092 587008 : while (!quadGRHchk(D, &GRHcheck, high))
1093 : {
1094 516708 : low = high;
1095 516708 : high *= 2;
1096 : }
1097 516777 : while (high - low > 1)
1098 : {
1099 446481 : long test = (low+high)/2;
1100 446481 : if (quadGRHchk(D, &GRHcheck, test))
1101 233932 : high = test;
1102 : else
1103 212548 : low = test;
1104 : }
1105 70296 : if (high == LIMC0+1 && quadGRHchk(D, &GRHcheck, LIMC0))
1106 0 : LIMC2 = LIMC0;
1107 : else
1108 70296 : LIMC2 = high;
1109 70296 : if (LIMC2 > LIMCMAX) LIMC2 = LIMCMAX;
1110 70296 : LIMC0 = (long)(cbach*LOGD2);
1111 70296 : LIMC = cbach ? LIMC0 : LIMC2;
1112 70296 : LIMC = maxss(LIMC, nthidealquad(D, 2));
1113 :
1114 : /* LIMC = Max(cbach*(log D)^2, exp(sqrt(log D loglog D) / 8)) */
1115 70313 : START:
1116 70313 : missing_primes = NULL;
1117 : do
1118 : {
1119 70383 : if (!FIRST) LIMC = bnf_increase_LIMC(LIMC,LIMCMAX);
1120 70383 : if (DEBUGLEVEL>2 && LIMC > LIMC0)
1121 0 : err_printf("%s*** Bach constant: %f\n", FIRST?"":"\n", LIMC/LOGD2);
1122 70383 : FIRST = 0; set_avma(av);
1123 70383 : guncloneNULL(BQ.subFB);
1124 70383 : guncloneNULL(BQ.powsubFB);
1125 70383 : clearhash(BQ.hashtab);
1126 70384 : if (LIMC < cp) LIMC = cp;
1127 70384 : if (LIMC2 < LIMC) LIMC2 = LIMC;
1128 70384 : if (BQ.PRECREG) qfr_data_init(q.D, BQ.PRECREG, &q);
1129 :
1130 70384 : FBquad(&BQ, LIMC2, LIMC, &GRHcheck);
1131 70384 : if (DEBUGLEVEL>2) timer_printf(&T, "factor base");
1132 70384 : BQ.subFB = subFBquad(&BQ, q.D, lim + 0.5, minSFB);
1133 70384 : if (DEBUGLEVEL>2) timer_printf(&T, "subFBquad = %Ps",
1134 : vecpermute(BQ.FB, BQ.subFB));
1135 70384 : nsubFB = lg(BQ.subFB) - 1;
1136 : }
1137 70384 : while (nsubFB < (expi(D) > 15 ? 3 : 2));
1138 : /* invhr = 2^r1 (2pi)^r2 / sqrt(D) w ~ L(chi,1) / hR */
1139 70314 : invhr = gmul(dbltor((BQ.PRECREG?2.:M_PI)/sdrc),
1140 : compute_invresquad(&GRHcheck, LIMC));
1141 70313 : BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1);
1142 70314 : if (DEBUGLEVEL>2) timer_printf(&T, "powsubFBquad");
1143 70314 : BQ.limhash = (LIMC & HIGHMASK)? (HIGHBIT>>1): LIMC*LIMC;
1144 :
1145 70314 : need = BQ.KC + RELSUP - 2;
1146 70314 : current = 0;
1147 70314 : W = NULL;
1148 70314 : sfb_trials = nreldep = nrelsup = 0;
1149 70314 : s = nsubFB + RELSUP;
1150 70314 : if (use_mpqs)
1151 28 : use_mpqs = mpqs_class_init(&H, D, BQ.KC);
1152 70314 : av2 = avma;
1153 :
1154 : do
1155 : {
1156 104537 : if ((nreldep & 3) == 1 || (nrelsup & 7) == 1) {
1157 28951 : if (DEBUGLEVEL>2) err_printf("*** Changing sub factor base\n");
1158 28951 : gunclone(BQ.subFB);
1159 28951 : gunclone(BQ.powsubFB);
1160 28951 : BQ.subFB = gclone(vecslice(BQ.vperm, 1, nsubFB));
1161 28950 : BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1);
1162 28951 : if (DEBUGLEVEL>2) timer_printf(&T, "powsubFBquad");
1163 28951 : clearhash(BQ.hashtab);
1164 : }
1165 104537 : if (!use_mpqs) need += 2;
1166 104537 : mat = cgetg(need+1, t_MAT);
1167 104537 : extraC = cgetg(need+1, t_VEC);
1168 104538 : if (!W) { /* first time */
1169 70314 : C = extraC;
1170 70314 : triv = trivial_relations(&BQ, mat, C);
1171 70314 : if (DEBUGLEVEL>2) err_printf("KC = %ld, need %ld relations\n", BQ.KC, need);
1172 : } else {
1173 34224 : triv = 0;
1174 34224 : if (DEBUGLEVEL>2) err_printf("...need %ld more relations\n", need);
1175 : }
1176 104538 : if (BQ.PRECREG) {
1177 189833 : for (i = triv+1; i<=need; i++) {
1178 184688 : gel(mat,i) = zero_zv(BQ.KC);
1179 184688 : gel(extraC,i) = mkcomplex(cgetr(BQ.PRECREG), cgeti(3));
1180 : }
1181 5145 : real_relations(&BQ, need - triv, ¤t, s,LIMC,mat + triv,extraC + triv);
1182 : } else {
1183 1718013 : for (i = triv+1; i<=need; i++) {
1184 1618621 : gel(mat,i) = zero_zv(BQ.KC);
1185 1618620 : gel(extraC,i) = gen_0;
1186 : }
1187 99392 : if (use_mpqs)
1188 336 : mpqs_relations(&BQ, need - triv, ¤t, LIMC,mat + triv, &H, missing_primes);
1189 : else
1190 99056 : imag_relations(&BQ, need - triv, ¤t, LIMC,mat + triv);
1191 : }
1192 104538 : if (DEBUGLEVEL>2) timer_start(&T);
1193 104537 : if (!W)
1194 70313 : W = hnfspec_i(mat,BQ.vperm,&dep,&B,&C,nsubFB);
1195 : else
1196 34224 : W = hnfadd_i(W,BQ.vperm,&dep,&B,&C, mat,extraC);
1197 104538 : if (DEBUGLEVEL>2) timer_printf(&T, "hnfadd");
1198 104538 : need = BQ.KC - (lg(W)-1) - (lg(B)-1);
1199 104538 : (void)gc_all(av2, 4, &W,&C,&B,&dep);
1200 104538 : missing_primes = vecslice(BQ.vperm,1,need);
1201 104538 : if (need)
1202 : {
1203 12960 : if (++nreldep > 15 && cbach < 1) goto START;
1204 12960 : continue;
1205 : }
1206 :
1207 91578 : h = ZM_det_triangular(W);
1208 91575 : if (DEBUGLEVEL>2) err_printf("\n#### Tentative class number: %Ps\n", h);
1209 :
1210 91575 : switch(get_R(&BQ, C, (lg(C)-1) - (lg(B)-1) - (lg(W)-1), mulir(h,invhr), &R))
1211 : {
1212 0 : case fupb_PRECI:
1213 0 : BQ.PRECREG = precdbl(BQ.PRECREG);
1214 0 : FIRST = 1; goto START;
1215 :
1216 21278 : case fupb_RELAT:
1217 21278 : if (++nrelsup > MAXRELSUP)
1218 : {
1219 63 : if (++sfb_trials > SFB_MAX && cbach <= 1) goto START;
1220 49 : if (nsubFB < minss(10,BQ.KC)) nsubFB++;
1221 : }
1222 21264 : need = minss(BQ.KC, nrelsup);
1223 : }
1224 : }
1225 104520 : while (need);
1226 : /* DONE */
1227 70297 : if (!quad_be_honest(&BQ)) goto START;
1228 70297 : if (DEBUGLEVEL>2) timer_printf(&T, "be honest");
1229 70297 : clearhash(BQ.hashtab);
1230 70300 : free_GRHcheck(&GRHcheck);
1231 :
1232 70300 : gen = get_clgp(&BQ,W,&cyc);
1233 70298 : gunclone(BQ.subFB);
1234 70300 : gunclone(BQ.powsubFB);
1235 70299 : if (BQ.PRECREG)
1236 2156 : return mkvec5(h, cyc, gen, real_i(R), mpodd(imag_i(R)) ? gen_m1:gen_1);
1237 : else
1238 68143 : return mkvec4(h, cyc, gen, real_i(R));
1239 : }
1240 : GEN
1241 4424 : Buchquad(GEN D, double c, double c2, long prec)
1242 : {
1243 4424 : pari_sp av = avma;
1244 4424 : GEN z = Buchquad_i(D, c, c2, prec);
1245 4424 : return gc_GEN(av, z);
1246 : }
1247 :
1248 : GEN
1249 0 : buchimag(GEN D, GEN c, GEN c2, GEN REL)
1250 0 : { (void)REL; return Buchquad(D,gtodouble(c),gtodouble(c2),0); }
1251 :
1252 : GEN
1253 0 : buchreal(GEN D, GEN flag, GEN c, GEN c2, GEN REL, long prec) {
1254 0 : if (signe(flag)) pari_err_IMPL("narrow class group");
1255 0 : (void)REL; return Buchquad(D,gtodouble(c),gtodouble(c2),prec);
1256 : }
1257 :
1258 : GEN
1259 4424 : quadclassunit0(GEN x, long flag, GEN data, long prec)
1260 : {
1261 : long lx;
1262 4424 : double c1 = 0.0, c2 = 0.0;
1263 :
1264 4424 : if (!data) lx=1;
1265 : else
1266 : {
1267 28 : lx = lg(data);
1268 28 : if (typ(data)!=t_VEC) pari_err_TYPE("quadclassunit", data);
1269 28 : if (lx > 7) pari_err_DIM("quadclassunit [tech vector]");
1270 28 : if (lx > 3) lx = 3;
1271 : }
1272 4424 : switch(lx)
1273 : {
1274 21 : case 3: c2 = gtodouble(gel(data,2));
1275 28 : case 2: c1 = gtodouble(gel(data,1));
1276 : }
1277 4424 : if (flag) pari_err_IMPL("narrow class group");
1278 4424 : return Buchquad(x,c1,c2,prec);
1279 : }
1280 : GEN
1281 61174 : quadclassno(GEN D)
1282 : {
1283 61174 : pari_sp av = avma;
1284 61174 : GEN h = abgrp_get_no(Buchquad_i(D, 0, 0, 0));
1285 61174 : return icopy_avma(h, av);
1286 : }
1287 : long
1288 4875 : quadclassnos(long D)
1289 : {
1290 4875 : pari_sp av = avma;
1291 4875 : long h = itos(abgrp_get_no(Buchquad_i(stoi(D), 0, 0, 0)));
1292 4875 : return gc_long(av, h);
1293 : }
|