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 :
17 : #define DEBUGLEVEL DEBUGLEVEL_quadclassunit
18 :
19 : /*******************************************************************/
20 : /* */
21 : /* CLASS GROUP AND REGULATOR (McCURLEY, BUCHMANN) */
22 : /* QUADRATIC FIELDS */
23 : /* */
24 : /*******************************************************************/
25 : /* For largeprime() hashtable. Note that hashed pseudoprimes are odd (unless
26 : * 2 | index), hence the low order bit is not useful. So we hash
27 : * HASHBITS bits starting at bit 1, not bit 0 */
28 : #define HASHBITS 10
29 : static const long HASHT = 1L << HASHBITS;
30 :
31 : static long
32 2556566 : hash(long q) { return (q & ((1L << (HASHBITS+1)) - 1)) >> 1; }
33 : #undef HASHBITS
34 :
35 : /* See buch2.c:
36 : * B->subFB contains split p such that \prod p > sqrt(B->Disc)
37 : * B->powsubFB contains powers of forms in B->subFB */
38 : #define RANDOM_BITS 4
39 : static const long CBUCH = (1L<<RANDOM_BITS)-1;
40 :
41 : struct buch_quad
42 : {
43 : ulong limhash;
44 : long KC, KC2, PRECREG;
45 : long *primfact, *exprimfact, **hashtab;
46 : GEN FB, numFB, prodFB;
47 : GEN powsubFB, vperm, subFB, badprim;
48 : struct qfr_data *q;
49 : };
50 :
51 : /*******************************************************************/
52 : /* */
53 : /* Routines related to binary quadratic forms (for internal use) */
54 : /* */
55 : /*******************************************************************/
56 : /* output canonical representative wrt projection Cl^+ --> Cl (a > 0) */
57 : static GEN
58 1164331 : qfr3_canon(GEN x, struct qfr_data *S)
59 : {
60 1164331 : GEN a = gel(x,1), c = gel(x,3);
61 1164331 : if (signe(a) < 0) {
62 502173 : if (absequalii(a,c)) return qfr3_rho(x, S);
63 502166 : setsigne(a, 1);
64 502166 : setsigne(c,-1);
65 : }
66 1164324 : return x;
67 : }
68 : static GEN
69 3710 : qfr3_canon_safe(GEN x, struct qfr_data *S)
70 : {
71 3710 : GEN a = gel(x,1), c = gel(x,3);
72 3710 : if (signe(a) < 0) {
73 224 : if (absequalii(a,c)) return qfr3_rho(x, S);
74 224 : gel(x,1) = negi(a);
75 224 : gel(x,3) = negi(c);
76 : }
77 3710 : return x;
78 : }
79 : static GEN
80 1947281 : qfr5_canon(GEN x, struct qfr_data *S)
81 : {
82 1947281 : GEN a = gel(x,1), c = gel(x,3);
83 1947281 : if (signe(a) < 0) {
84 868427 : if (absequalii(a,c)) return qfr5_rho(x, S);
85 868420 : setsigne(a, 1);
86 868420 : setsigne(c,-1);
87 : }
88 1947274 : return x;
89 : }
90 : static GEN
91 1730337 : QFR5_comp(GEN x,GEN y, struct qfr_data *S)
92 1730337 : { return qfr5_canon(qfr5_comp(x,y,S), S); }
93 : static GEN
94 1005354 : QFR3_comp(GEN x, GEN y, struct qfr_data *S)
95 1005354 : { return qfr3_canon(qfr3_comp(x,y,S), S); }
96 :
97 : /* compute rho^n(x) */
98 : static GEN
99 220584 : qfr5_rho_pow(GEN x, long n, struct qfr_data *S)
100 : {
101 : long i;
102 220584 : pari_sp av = avma;
103 2216151 : for (i=1; i<=n; i++)
104 : {
105 1995567 : x = qfr5_rho(x,S);
106 1995567 : if (gc_needed(av,1))
107 : {
108 0 : if(DEBUGMEM>1) pari_warn(warnmem,"qfr5_rho_pow");
109 0 : x = gerepilecopy(av, x);
110 : }
111 : }
112 220584 : return gerepilecopy(av, x);
113 : }
114 :
115 : static GEN
116 216944 : qfr5_pf(struct qfr_data *S, long p, long prec)
117 : {
118 216944 : GEN y = primeform_u(S->D,p);
119 216944 : return qfr5_canon(qfr5_red(qfr_to_qfr5(y,prec), S), S);
120 : }
121 :
122 : static GEN
123 158956 : qfr3_pf(struct qfr_data *S, long p)
124 : {
125 158956 : GEN y = primeform_u(S->D,p);
126 158956 : return qfr3_canon(qfr3_red(y, S), S);
127 : }
128 :
129 : #define qfi_pf primeform_u
130 :
131 : /* Warning: ex[0] not set in general */
132 : static GEN
133 4043417 : init_form(struct buch_quad *B, GEN ex,
134 : GEN (*comp)(GEN,GEN,struct qfr_data *S))
135 : {
136 4043417 : long i, l = lg(B->powsubFB);
137 4043417 : GEN F = NULL;
138 22849263 : for (i=1; i<l; i++)
139 18812247 : if (ex[i])
140 : {
141 17639020 : GEN t = gmael(B->powsubFB,i,ex[i]);
142 17639020 : F = F? comp(F, t, B->q): t;
143 : }
144 4037016 : return F;
145 : }
146 : static GEN
147 197442 : qfr5_factorback(struct buch_quad *B, GEN ex) { return init_form(B, ex, &QFR5_comp); }
148 :
149 : static GEN
150 11714492 : QFI_comp(GEN x, GEN y, struct qfr_data *S) { (void)S; return qfbcomp_i(x,y); }
151 :
152 : static GEN
153 158782 : qfi_factorback(struct buch_quad *B, GEN ex) { return init_form(B, ex, &QFI_comp); }
154 :
155 : static GEN
156 3686147 : random_form(struct buch_quad *B, GEN ex,
157 : GEN (*comp)(GEN,GEN, struct qfr_data *S))
158 : {
159 3686147 : long i, l = lg(ex);
160 3686147 : pari_sp av = avma;
161 : GEN F;
162 : for(;;)
163 : {
164 20526370 : for (i=1; i<l; i++) ex[i] = random_bits(RANDOM_BITS);
165 3687133 : if ((F = init_form(B, ex, comp))) return F;
166 419 : set_avma(av);
167 : }
168 : }
169 : static GEN
170 161133 : qfr3_random(struct buch_quad *B,GEN ex){ return random_form(B, ex, &QFR3_comp); }
171 : static GEN
172 3525064 : qfi_random(struct buch_quad *B,GEN ex) { return random_form(B, ex, &QFI_comp); }
173 :
174 : /*******************************************************************/
175 : /* */
176 : /* Common subroutines */
177 : /* */
178 : /*******************************************************************/
179 : /* We assume prime ideals of norm < D generate Cl(K); failure with
180 : * a factor base of primes with norm < LIMC <= D. Suggest new value.
181 : * All values of the form c * log^2 (disc K) [where D has c = 4
182 : * (Grenie-Molteni, under GRH)]. A value of c in [0.3, 1] should be OK for most
183 : * fields. No example is known where c >= 2 is necessary. */
184 : ulong
185 2333 : bnf_increase_LIMC(ulong LIMC, ulong D)
186 : {
187 2333 : if (LIMC >= D) pari_err_BUG("Buchmann's algorithm");
188 2333 : if (LIMC <= D / 13.333)
189 191 : LIMC *= 2; /* tiny c <= 0.3 : double it */
190 : else
191 2142 : LIMC += maxuu(1, D / 20); /* large c, add 0.2 to it */
192 2333 : if (LIMC > D) LIMC = D;
193 2333 : return LIMC;
194 : }
195 :
196 : /* Is |q| <= p ? */
197 : static int
198 10186 : isless_iu(GEN q, ulong p) {
199 10186 : long l = lgefint(q);
200 10186 : return l==2 || (l == 3 && uel(q,2) <= p);
201 : }
202 :
203 : static GEN
204 5015415 : Z_isquasismooth_prod(GEN N, GEN P)
205 : {
206 5015415 : P = gcdii(P,N);
207 10004198 : while (!is_pm1(P))
208 : {
209 4982002 : N = diviiexact(N, P);
210 4997376 : P = gcdii(N, P);
211 : }
212 5005254 : return N;
213 : }
214 :
215 : static long
216 5016537 : factorquad(struct buch_quad *B, GEN f, long nFB, ulong limp)
217 : {
218 : ulong X;
219 5016537 : long i, lo = 0;
220 5016537 : GEN F, x = gel(f,1), FB = B->FB, P = B->primfact, E = B->exprimfact;
221 5016537 : if (B->badprim && !is_pm1(gcdii(x, B->badprim))) return 0;
222 5015361 : F = Z_isquasismooth_prod(x, B->prodFB);
223 5005425 : if (cmpiu(F, B->limhash) > 0) return 0;
224 4389890 : for (i=1; lgefint(x) > 3; i++)
225 : {
226 10186 : ulong p = uel(FB,i), r;
227 10186 : GEN q = absdiviu_rem(x, p, &r);
228 10186 : if (!r)
229 : {
230 1732 : long k = 0;
231 2952 : do { k++; x = q; q = absdiviu_rem(x, p, &r); } while (!r);
232 1732 : lo++; P[lo] = p; E[lo] = k;
233 : }
234 10186 : if (isless_iu(q,p)) {
235 1 : if (lgefint(x) == 3) { X = uel(x,2); goto END; }
236 32 : return 0;
237 : }
238 10185 : if (i == nFB) return 0;
239 : }
240 4379704 : X = uel(x,2);
241 4379704 : if (X == 1) { P[0] = 0; return 1; }
242 68510946 : for (;; i++)
243 68510946 : { /* single precision affair, split for efficiency */
244 72872019 : ulong p = uel(FB,i);
245 72872019 : ulong q = X / p, r = X % p; /* gcc makes a single div */
246 72872019 : if (!r)
247 : {
248 5619171 : long k = 0;
249 6783752 : do { k++; X = q; q = X / p; r = X % p; } while (!r);
250 5619171 : lo++; P[lo] = p; E[lo] = k;
251 : }
252 72872019 : if (q <= p) break;
253 68546257 : if (i == nFB) return 0;
254 : }
255 4325763 : END:
256 4325763 : if (X > B->limhash) return 0;
257 4325763 : if (X != 1 && X <= limp) { lo++; P[lo] = X; E[lo] = 1; X = 1; }
258 4325763 : P[0] = lo; return X;
259 : }
260 :
261 : /* Check for a "large prime relation" involving q; q may not be prime */
262 : static long *
263 2556608 : largeprime(struct buch_quad *B, long q, GEN ex, long np, long nrho)
264 : {
265 2556608 : const long hashv = hash(q);
266 2556551 : long *pt, i, l = lg(B->subFB);
267 :
268 2778832 : for (pt = B->hashtab[hashv]; ; pt = (long*) pt[0])
269 : {
270 2778832 : if (!pt)
271 : {
272 2357566 : pt = (long*) pari_malloc((l+3) * sizeof(long));
273 2357746 : *pt++ = nrho; /* nrho = pt[-3] */
274 2357746 : *pt++ = np; /* np = pt[-2] */
275 2357746 : *pt++ = q; /* q = pt[-1] */
276 2357746 : pt[0] = (long)B->hashtab[hashv];
277 14945324 : for (i=1; i<l; i++) pt[i]=ex[i];
278 2357746 : B->hashtab[hashv]=pt; return NULL;
279 : }
280 421266 : if (pt[-1] == q) break;
281 : }
282 242436 : for(i=1; i<l; i++)
283 238549 : if (pt[i] != ex[i]) return pt;
284 3887 : return (pt[-2]==np)? NULL: pt;
285 : }
286 :
287 : static void
288 169431 : clearhash(long **hash)
289 : {
290 : long *pt;
291 : long i;
292 173630229 : for (i=0; i<HASHT; i++) {
293 175818599 : for (pt = hash[i]; pt; ) {
294 2357801 : void *z = (void*)(pt - 3);
295 2357801 : pt = (long*) pt[0]; pari_free(z);
296 : }
297 173460798 : hash[i] = NULL;
298 : }
299 171661 : }
300 :
301 : /* last prime stored */
302 : ulong
303 0 : GRH_last_prime(GRHcheck_t *S) { return (S->primes + S->nprimes-1)->p; }
304 : /* ensure that S->primes can hold at least nb primes */
305 : void
306 399874 : GRH_ensure(GRHcheck_t *S, long nb)
307 : {
308 399874 : if (S->maxprimes <= nb)
309 : {
310 0 : do S->maxprimes *= 2; while (S->maxprimes <= nb);
311 0 : pari_realloc_ip((void**)&S->primes, S->maxprimes*sizeof(*S->primes));
312 : }
313 399874 : }
314 : /* cache data for all primes up to the LIM */
315 : static void
316 1173426 : cache_prime_quad(GRHcheck_t *S, ulong LIM, GEN D)
317 : {
318 : GRHprime_t *pr;
319 : long nb;
320 :
321 1173426 : if (S->limp >= LIM) return;
322 72331 : nb = (long)primepi_upper_bound((double)LIM); /* #{p <= LIM} <= nb */
323 72337 : GRH_ensure(S, nb+1); /* room for one extra prime */
324 72336 : for (pr = S->primes + S->nprimes;;)
325 12649733 : {
326 12722069 : ulong p = u_forprime_next(&(S->P));
327 12721622 : pr->p = p;
328 12721622 : pr->logp = log((double)p);
329 12721622 : pr->dec = (GEN)kroiu(D,p);
330 12722072 : S->nprimes++;
331 12722072 : pr++;
332 : /* store up to nextprime(LIM) included */
333 12722072 : if (p >= LIM) { S->limp = p; break; }
334 : }
335 : }
336 :
337 : static GEN
338 70258 : compute_invresquad(GRHcheck_t *S, long LIMC)
339 : {
340 70258 : pari_sp av = avma;
341 70258 : GEN invres = real_1(DEFAULTPREC);
342 70258 : double limp = log((double)LIMC) / 2;
343 : GRHprime_t *pr;
344 : long i;
345 12729343 : for (pr = S->primes, i = S->nprimes; i > 0; pr++, i--)
346 : {
347 12659801 : long s = (long)pr->dec;
348 12659801 : if (s)
349 : {
350 12531992 : ulong p = pr->p;
351 12531992 : if (s > 0 || pr->logp <= limp)
352 : /* Both p and P contribute */
353 6376364 : invres = mulur(p - s, divru(invres, p));
354 6155628 : else if (s<0)
355 : /* Only p contributes */
356 6155710 : invres = mulur(p, divru(invres, p - 1));
357 : }
358 : }
359 69542 : return gerepileuptoleaf(av, invres);
360 : }
361 :
362 : /* p | conductor of order of disc D ? */
363 : static int
364 391525 : is_bad(GEN D, ulong p)
365 : {
366 391525 : pari_sp av = avma;
367 391525 : if (p == 2)
368 : {
369 89559 : long r = mod16(D) >> 1;
370 89559 : if (r && signe(D) < 0) r = 8-r;
371 89559 : return (r < 4);
372 : }
373 301966 : return gc_bool(av, dvdii(D, sqru(p))); /* p^2 | D ? */
374 : }
375 :
376 : /* returns the n-th suitable ideal for the factorbase */
377 : static long
378 70258 : nthidealquad(GEN D, long n)
379 : {
380 70258 : pari_sp av = avma;
381 : forprime_t S;
382 : ulong p;
383 70258 : (void)u_forprime_init(&S, 2, ULONG_MAX);
384 357185 : while ((p = u_forprime_next(&S)) && n > 0)
385 286927 : if (!is_bad(D, p) && kroiu(D, p) >= 0) n--;
386 70256 : return gc_long(av, p);
387 : }
388 :
389 : static int
390 1032776 : quadGRHchk(GEN D, GRHcheck_t *S, ulong LIMC)
391 : {
392 1032776 : double logC = log((double)LIMC), SA = 0, SB = 0;
393 : long i;
394 :
395 1032776 : cache_prime_quad(S, LIMC, D);
396 1032788 : for (i = 0;; i++)
397 29330416 : {
398 30363204 : GRHprime_t *pr = S->primes+i;
399 30363204 : ulong p = pr->p;
400 : long M;
401 : double logNP, q, A, B;
402 30363204 : if (p > LIMC) break;
403 29419566 : if ((long)pr->dec < 0)
404 : {
405 14691580 : logNP = 2 * pr->logp;
406 14691580 : q = 1/(double)p;
407 : }
408 : else
409 : {
410 14727986 : logNP = pr->logp;
411 14727986 : q = 1/sqrt((double)p);
412 : }
413 29419566 : A = logNP * q; B = logNP * A; M = (long)(logC/logNP);
414 29419566 : if (M > 1)
415 : {
416 2496914 : double inv1_q = 1 / (1-q);
417 2496914 : A *= (1 - pow(q, (double) M)) * inv1_q;
418 2496914 : B *= (1 - pow(q, (double) M)*(M+1 - M*q)) * inv1_q * inv1_q;
419 : }
420 29419566 : if ((long)pr->dec>0) { SA += 2*A;SB += 2*B; } else { SA += A; SB += B; }
421 29419566 : if (p == LIMC) break;
422 : }
423 1032788 : return GRHok(S, logC, SA, SB);
424 : }
425 :
426 : /* C2 >= C1; create B->FB, B->numFB; set B->badprim. Return L(kro_D, 1) */
427 : static void
428 70391 : FBquad(struct buch_quad *B, ulong C2, ulong C1, GRHcheck_t *S)
429 : {
430 70391 : GEN D = B->q->D;
431 : long i;
432 : pari_sp av;
433 : GRHprime_t *pr;
434 :
435 70391 : cache_prime_quad(S, C2, D);
436 70391 : pr = S->primes;
437 70391 : B->numFB = cgetg(C2+1, t_VECSMALL);
438 70391 : B->FB = cgetg(C2+1, t_VECSMALL);
439 70383 : av = avma;
440 70383 : B->KC = 0; i = 0;
441 70383 : B->badprim = gen_1;
442 2798890 : for (;; pr++) /* p <= C2 */
443 2798890 : {
444 2869273 : ulong p = pr->p;
445 2869273 : if (!B->KC && p > C1) B->KC = i;
446 2869273 : if (p > C2) break;
447 2806400 : switch ((long)pr->dec)
448 : {
449 1382987 : case -1: break; /* inert */
450 104601 : case 0: /* ramified */
451 104601 : if (is_bad(D, p)) { B->badprim = muliu(B->badprim, p); break; }
452 : /* fall through */
453 : default: /* split */
454 1423392 : i++; B->numFB[p] = i; B->FB[i] = p; break;
455 : }
456 2806407 : if (p == C2)
457 : {
458 7517 : if (!B->KC) B->KC = i;
459 7517 : break;
460 : }
461 : }
462 70390 : B->KC2 = i;
463 70390 : setlg(B->FB, B->KC2+1);
464 70390 : if (B->badprim != gen_1)
465 21 : B->badprim = gerepileuptoint(av, B->badprim);
466 : else
467 : {
468 70369 : B->badprim = NULL; set_avma(av);
469 : }
470 70390 : B->prodFB = zv_prod_Z(B->FB);
471 70390 : }
472 :
473 : /* create B->vperm, return B->subFB */
474 : static GEN
475 70390 : subFBquad(struct buch_quad *B, GEN D, double PROD, long minSFB)
476 : {
477 70390 : long i, j, lgsub = 1, ino = 1, lv = B->KC+1;
478 70390 : double prod = 1.;
479 : pari_sp av;
480 : GEN no;
481 :
482 70390 : B->vperm = cgetg(lv, t_VECSMALL);
483 70391 : av = avma;
484 70391 : no = cgetg(lv, t_VECSMALL);
485 334517 : for (j = 1; j < lv; j++)
486 : {
487 334377 : ulong p = uel(B->FB,j);
488 334377 : if (!umodiu(D, p)) no[ino++] = j; /* ramified */
489 : else
490 : {
491 254585 : B->vperm[lgsub++] = j;
492 254585 : prod *= p;
493 254585 : if (lgsub > minSFB && prod > PROD) break;
494 : }
495 : }
496 : /* lgsub >= 1 otherwise quadGRHchk is false */
497 70391 : i = lgsub;
498 150183 : for (j = 1; j < ino;i++,j++) B->vperm[i] = no[j];
499 1158918 : for ( ; i < lv; i++) B->vperm[i] = i;
500 70391 : no = gclone(vecslice(B->vperm, 1, lgsub-1));
501 70391 : set_avma(av); return no;
502 : }
503 :
504 : /* assume n >= 1, x[i][j] = B->subFB[i]^j, for j = 1..n */
505 : static GEN
506 99043 : powsubFBquad(struct buch_quad *B, long n)
507 : {
508 99043 : pari_sp av = avma;
509 99043 : long i,j, l = lg(B->subFB);
510 99043 : GEN F, y, x = cgetg(l, t_VEC), D = B->q->D;
511 :
512 99045 : if (B->PRECREG) /* real */
513 : {
514 39088 : for (i=1; i<l; i++)
515 : {
516 34055 : F = qfr5_pf(B->q, B->FB[B->subFB[i]], B->PRECREG);
517 34055 : y = cgetg(n+1, t_VEC); gel(x,i) = y;
518 34055 : gel(y,1) = F;
519 544880 : for (j=2; j<=n; j++) gel(y,j) = QFR5_comp(gel(y,j-1), F, B->q);
520 : }
521 : }
522 : else /* imaginary */
523 : {
524 426866 : for (i=1; i<l; i++)
525 : {
526 332869 : F = qfi_pf(D, B->FB[B->subFB[i]]);
527 332852 : y = cgetg(n+1, t_VEC); gel(x,i) = y;
528 333618 : gel(y,1) = F;
529 5319229 : for (j=2; j<=n; j++) gel(y,j) = qfbcomp_i(gel(y,j-1), F);
530 : }
531 : }
532 99030 : x = gclone(x); set_avma(av); return x;
533 : }
534 :
535 : static void
536 97741 : sub_fact(struct buch_quad *B, GEN col, GEN F)
537 : {
538 97741 : GEN b = gel(F,2);
539 : long i;
540 207769 : for (i=1; i<=B->primfact[0]; i++)
541 : {
542 110027 : ulong p = B->primfact[i], k = B->numFB[p];
543 110027 : long e = B->exprimfact[i];
544 110027 : if (umodiu(b, p<<1) > p) e = -e;
545 110028 : col[k] -= e;
546 : }
547 97742 : }
548 : static void
549 1884962 : add_fact(struct buch_quad *B, GEN col, GEN F)
550 : {
551 1884962 : GEN b = gel(F,2);
552 : long i;
553 5915651 : for (i=1; i<=B->primfact[0]; i++)
554 : {
555 4030678 : ulong p = B->primfact[i], k = B->numFB[p];
556 4030678 : long e = B->exprimfact[i];
557 4030678 : if (umodiu(b, p<<1) > p) e = -e;
558 4030689 : col[k] += e;
559 : }
560 1884973 : }
561 :
562 : static GEN
563 70257 : get_clgp(struct buch_quad *B, GEN W, GEN *ptD)
564 : {
565 70257 : GEN res, init, u1, D = ZM_snf_group(W,NULL,&u1);
566 70255 : long i, j, l = lg(W), c = lg(D);
567 :
568 70255 : res=cgetg(c,t_VEC); init = cgetg(l,t_VEC);
569 215963 : for (i=1; i<l; i++) gel(init,i) = primeform_u(B->q->D, B->FB[B->vperm[i]]);
570 195555 : for (j=1; j<c; j++)
571 : {
572 125299 : GEN g = NULL;
573 125299 : if (signe(B->q->D) > 0)
574 : {
575 13293 : for (i=1; i<l; i++)
576 : {
577 9583 : GEN t, u = gcoeff(u1,i,j);
578 9583 : if (!signe(u)) continue;
579 4501 : t = qfr3_pow(gel(init,i), u, B->q);
580 4501 : g = g? qfr3_comp(g, t, B->q): t;
581 : }
582 3710 : g = qfr3_to_qfr(qfr3_canon_safe(qfr3_red(g, B->q), B->q), B->q->D);
583 : }
584 : else
585 : {
586 422805 : for (i=1; i<l; i++)
587 : {
588 301216 : GEN t, u = gcoeff(u1,i,j);
589 301216 : if (!signe(u)) continue;
590 203267 : t = powgi(gel(init,i), u);
591 203273 : g = g? qfbcomp_i(g, t): t;
592 : }
593 : }
594 125299 : gel(res,j) = g;
595 : }
596 70256 : *ptD = D; return res;
597 : }
598 :
599 : static long
600 70257 : trivial_relations(struct buch_quad *B, GEN mat, GEN C)
601 : {
602 70257 : long i, j = 0;
603 70257 : GEN col, D = B->q->D;
604 1492662 : for (i = 1; i <= B->KC; i++)
605 : { /* ramified prime ==> trivial relation */
606 1422400 : if (umodiu(D, B->FB[i])) continue;
607 104211 : col = zero_zv(B->KC);
608 104217 : col[i] = 2; j++;
609 104217 : gel(mat,j) = col;
610 104217 : gel(C,j) = gen_0;
611 : }
612 70262 : return j;
613 : }
614 :
615 : static void
616 0 : dbg_all(pari_timer *T, const char *phase, long s, long n)
617 : {
618 0 : err_printf("\n");
619 0 : timer_printf(T, "%s rel [#rel/#test = %ld/%ld]", phase,s,n);
620 0 : }
621 :
622 : /* Imaginary Quadratic fields */
623 :
624 : static void
625 98685 : imag_relations(struct buch_quad *B, long need, long *pc, ulong LIMC, GEN mat)
626 : {
627 : pari_timer T;
628 98685 : long lgsub = lg(B->subFB), current = *pc, nbtest = 0, s = 0;
629 : long i, fpc;
630 : pari_sp av;
631 98685 : GEN col, form, ex = cgetg(lgsub, t_VECSMALL);
632 :
633 98685 : if (!current) current = 1;
634 98685 : if (DEBUGLEVEL>2) timer_start(&T);
635 98685 : av = avma;
636 : for(;;)
637 : {
638 3623663 : if (s >= need) break;
639 3524980 : set_avma(av);
640 3524645 : form = qfi_random(B,ex);
641 3523556 : form = qfbcomp_i(form, qfi_pf(B->q->D, B->FB[current]));
642 3523358 : nbtest++; fpc = factorquad(B,form,B->KC,LIMC);
643 3525047 : if (!fpc)
644 : {
645 287959 : if (DEBUGLEVEL>3) err_printf(".");
646 287959 : if ((nbtest & 0xff) == 0 && ++current > B->KC) current = 1;
647 287959 : continue;
648 : }
649 3237088 : if (fpc > 1)
650 : {
651 1792522 : long *fpd = largeprime(B,fpc,ex,current,0);
652 : ulong b1, b2, p;
653 : GEN form2;
654 1792650 : if (!fpd)
655 : {
656 1633883 : if (DEBUGLEVEL>3) err_printf(".");
657 1633886 : continue;
658 : }
659 158767 : form2 = qfbcomp_i(qfi_factorback(B,fpd), qfi_pf(B->q->D, B->FB[fpd[-2]]));
660 158782 : p = fpc << 1;
661 158782 : b1 = umodiu(gel(form2,2), p);
662 158782 : b2 = umodiu(gel(form,2), p);
663 158782 : if (b1 != b2 && b1+b2 != p) continue;
664 :
665 158782 : col = gel(mat,++s);
666 158782 : add_fact(B,col, form);
667 158784 : (void)factorquad(B,form2,B->KC,LIMC);
668 158784 : if (b1==b2)
669 : {
670 409322 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += fpd[i]-ex[i];
671 79506 : sub_fact(B, col, form2); col[fpd[-2]]++;
672 : }
673 : else
674 : {
675 408495 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += -fpd[i]-ex[i];
676 79278 : add_fact(B, col, form2); col[fpd[-2]]--;
677 : }
678 158785 : if (DEBUGLEVEL>2) err_printf(" %ldP",s);
679 : }
680 : else
681 : {
682 1444566 : col = gel(mat,++s);
683 6942961 : for (i=1; i<lgsub; i++) col[B->subFB[i]] = -ex[i];
684 1444566 : add_fact(B, col, form);
685 1444651 : if (DEBUGLEVEL>2) err_printf(" %ld",s);
686 : }
687 1603133 : col[current]--;
688 1603133 : if (++current > B->KC) current = 1;
689 : }
690 98683 : if (DEBUGLEVEL>2) dbg_all(&T, "random", s, nbtest);
691 98683 : *pc = current;
692 98683 : }
693 :
694 : static int
695 7 : imag_be_honest(struct buch_quad *B)
696 : {
697 7 : long p, fpc, s = B->KC, nbtest = 0;
698 7 : GEN F, ex = cgetg(lg(B->subFB), t_VECSMALL);
699 7 : pari_sp av = avma;
700 :
701 525 : while (s<B->KC2)
702 : {
703 518 : p = B->FB[s+1]; if (DEBUGLEVEL>2) err_printf(" %ld",p);
704 518 : F = qfbcomp_i(qfi_pf(B->q->D, p), qfi_random(B, ex));
705 518 : fpc = factorquad(B,F,s,p-1);
706 518 : if (fpc == 1) { nbtest=0; s++; }
707 : else
708 392 : if (++nbtest > 40) return 0;
709 518 : set_avma(av);
710 : }
711 7 : return 1;
712 : }
713 :
714 : /* Real Quadratic fields */
715 :
716 : static void
717 5124 : real_relations(struct buch_quad *B, long need, long *pc, long lim, ulong LIMC, GEN mat, GEN C)
718 : {
719 : pari_timer T;
720 5124 : long lgsub = lg(B->subFB), prec = B->PRECREG, current = *pc, nbtest=0, s=0;
721 : long i, fpc, endcycle, rhoacc, rho;
722 : /* in a 2nd phase, don't include FB[current] but run along the cyle
723 : * ==> get more units */
724 5124 : int first = (current == 0);
725 : pari_sp av, av1;
726 5124 : GEN d, col, form, form0, form1, ex = cgetg(lgsub, t_VECSMALL);
727 :
728 5124 : if (DEBUGLEVEL>2) timer_start(&T);
729 5124 : if (!current) current = 1;
730 5124 : if (lim > need) lim = need;
731 5124 : av = avma;
732 : for(;;)
733 : {
734 166236 : if (s >= need) break;
735 161112 : if (first && s >= lim) {
736 2142 : first = 0;
737 2142 : if (DEBUGLEVEL>2) dbg_all(&T, "initial", s, nbtest);
738 : }
739 161112 : set_avma(av); form = qfr3_random(B, ex);
740 161112 : if (!first)
741 158935 : form = QFR3_comp(form, qfr3_pf(B->q, B->FB[current]), B->q);
742 161112 : av1 = avma;
743 161112 : form0 = form; form1 = NULL;
744 161112 : endcycle = rhoacc = 0;
745 161112 : rho = -1;
746 :
747 1297569 : CYCLE:
748 1297569 : if (endcycle || rho > 5000)
749 : {
750 21 : if (++current > B->KC) current = 1;
751 21 : continue;
752 : }
753 1297548 : if (gc_needed(av,1))
754 : {
755 0 : if(DEBUGMEM>1) pari_warn(warnmem,"real_relations");
756 0 : gerepileall(av1, form1? 2: 1, &form, &form1);
757 : }
758 1297548 : if (rho < 0) rho = 0; /* first time in */
759 : else
760 : {
761 1136436 : form = qfr3_rho(form, B->q); rho++;
762 1136436 : rhoacc++;
763 1136436 : if (first)
764 444430 : endcycle = (absequalii(gel(form,1),gel(form0,1))
765 222215 : && equalii(gel(form,2),gel(form0,2)));
766 : else
767 : {
768 914221 : if (absequalii(gel(form,1), gel(form,3))) /* a = -c */
769 : {
770 0 : if (absequalii(gel(form,1),gel(form0,1)) &&
771 0 : equalii(gel(form,2),gel(form0,2))) continue;
772 0 : form = qfr3_rho(form, B->q); rho++;
773 0 : rhoacc++;
774 : }
775 : else
776 914221 : { setsigne(form[1],1); setsigne(form[3],-1); }
777 914277 : if (equalii(gel(form,1),gel(form0,1)) &&
778 56 : equalii(gel(form,2),gel(form0,2))) continue;
779 : }
780 : }
781 1297548 : nbtest++; fpc = factorquad(B,form,B->KC,LIMC);
782 1297548 : if (!fpc)
783 : {
784 385511 : if (DEBUGLEVEL>3) err_printf(".");
785 385511 : goto CYCLE;
786 : }
787 912037 : if (fpc > 1)
788 : { /* look for Large Prime relation */
789 764113 : long *fpd = largeprime(B,fpc,ex,first? 0: current,rhoacc);
790 : ulong b1, b2, p;
791 : GEN form2;
792 764113 : if (!fpd)
793 : {
794 727783 : if (DEBUGLEVEL>3) err_printf(".");
795 727783 : goto CYCLE;
796 : }
797 36330 : if (!form1)
798 : {
799 36330 : form1 = qfr5_factorback(B,ex);
800 36330 : if (!first)
801 36330 : form1 = QFR5_comp(form1, qfr5_pf(B->q, B->FB[current], prec), B->q);
802 : }
803 36330 : form1 = qfr5_rho_pow(form1, rho, B->q);
804 36330 : rho = 0;
805 :
806 36330 : form2 = qfr5_factorback(B,fpd);
807 36330 : if (fpd[-2])
808 23954 : form2 = QFR5_comp(form2, qfr5_pf(B->q, B->FB[fpd[-2]], prec), B->q);
809 36330 : form2 = qfr5_rho_pow(form2, fpd[-3], B->q);
810 36330 : if (!absequalii(gel(form2,1),gel(form2,3)))
811 : {
812 36330 : setsigne(form2[1], 1);
813 36330 : setsigne(form2[3],-1);
814 : }
815 36330 : p = fpc << 1;
816 36330 : b1 = umodiu(gel(form2,2), p);
817 36330 : b2 = umodiu(gel(form1,2), p);
818 36330 : if (b1 != b2 && b1+b2 != p) goto CYCLE;
819 :
820 36330 : col = gel(mat,++s);
821 36330 : add_fact(B, col, form1);
822 36330 : (void)factorquad(B,form2,B->KC,LIMC);
823 36330 : if (b1==b2)
824 : {
825 139377 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += fpd[i]-ex[i];
826 18235 : sub_fact(B,col, form2);
827 18235 : if (fpd[-2]) col[fpd[-2]]++;
828 18235 : d = qfr5_dist(subii(gel(form1,4),gel(form2,4)),
829 18235 : divrr(gel(form1,5),gel(form2,5)), prec);
830 : }
831 : else
832 : {
833 138670 : for (i=1; i<lgsub; i++) col[B->subFB[i]] += -fpd[i]-ex[i];
834 18095 : add_fact(B, col, form2);
835 18095 : if (fpd[-2]) col[fpd[-2]]--;
836 18095 : d = qfr5_dist(addii(gel(form1,4),gel(form2,4)),
837 18095 : mulrr(gel(form1,5),gel(form2,5)), prec);
838 : }
839 36330 : if (DEBUGLEVEL>2) err_printf(" %ldP",s);
840 : }
841 : else
842 : { /* standard relation */
843 147924 : if (!form1)
844 : {
845 124782 : form1 = qfr5_factorback(B, ex);
846 124782 : if (!first)
847 122605 : form1 = QFR5_comp(form1, qfr5_pf(B->q, B->FB[current], prec), B->q);
848 : }
849 147924 : form1 = qfr5_rho_pow(form1, rho, B->q);
850 147924 : rho = 0;
851 :
852 147924 : col = gel(mat,++s);
853 1138494 : for (i=1; i<lgsub; i++) col[B->subFB[i]] = -ex[i];
854 147924 : add_fact(B, col, form1);
855 147924 : d = qfr5_dist(gel(form1,4), gel(form1,5), prec);
856 147924 : if (DEBUGLEVEL>2) err_printf(" %ld",s);
857 : }
858 184254 : affrr(d, gel(C,s));
859 184254 : if (first)
860 : {
861 25319 : if (s >= lim) continue;
862 23163 : goto CYCLE;
863 : }
864 : else
865 : {
866 158935 : col[current]--;
867 158935 : if (++current > B->KC) current = 1;
868 : }
869 : }
870 5124 : if (DEBUGLEVEL>2) dbg_all(&T, "random", s, nbtest);
871 5124 : *pc = current;
872 5124 : }
873 :
874 : static int
875 7 : real_be_honest(struct buch_quad *B)
876 : {
877 7 : long p, fpc, s = B->KC, nbtest = 0;
878 7 : GEN F,F0, ex = cgetg(lg(B->subFB), t_VECSMALL);
879 7 : pari_sp av = avma;
880 :
881 28 : while (s<B->KC2)
882 : {
883 21 : p = B->FB[s+1]; if (DEBUGLEVEL>2) err_printf(" %ld",p);
884 21 : F = QFR3_comp(qfr3_random(B, ex), qfr3_pf(B->q, p), B->q);
885 21 : for (F0 = F;;)
886 : {
887 42 : fpc = factorquad(B,F,s,p-1);
888 42 : if (fpc == 1) { nbtest=0; s++; break; }
889 21 : if (++nbtest > 40) return 0;
890 21 : F = qfr3_canon(qfr3_rho(F, B->q), B->q);
891 21 : if (equalii(gel(F,1),gel(F0,1))
892 0 : && equalii(gel(F,2),gel(F0,2))) break;
893 : }
894 21 : set_avma(av);
895 : }
896 7 : return 1;
897 : }
898 :
899 : static GEN
900 32025 : gcdreal(GEN a,GEN b)
901 : {
902 32025 : if (!signe(a)) return mpabs_shallow(b);
903 31363 : if (!signe(b)) return mpabs_shallow(a);
904 31215 : if (typ(a)==t_INT)
905 : {
906 0 : if (typ(b)==t_INT) return gcdii(a,b);
907 0 : a = itor(a, lg(b));
908 : }
909 31215 : else if (typ(b)==t_INT)
910 0 : b = itor(b, lg(a));
911 31215 : if (expo(a)<-5) return absr(b);
912 11305 : if (expo(b)<-5) return absr(a);
913 8456 : a = absr(a); b = absr(b);
914 18680 : while (expo(b) >= -5 && signe(b))
915 : {
916 : long e;
917 10224 : GEN r, q = gcvtoi(divrr(a,b),&e);
918 10224 : if (e > 0) return NULL;
919 10224 : r = subrr(a, mulir(q,b)); a = b; b = r;
920 : }
921 8456 : return mpabs_shallow(a);
922 : }
923 :
924 : static int
925 90925 : get_R(struct buch_quad *B, GEN C, long sreg, GEN z, GEN *ptR)
926 : {
927 90925 : GEN R = gen_1;
928 : double c;
929 : long i;
930 :
931 90925 : if (B->PRECREG)
932 : {
933 2877 : R = mpabs_shallow(gel(C,1));
934 34902 : for (i=2; i<=sreg; i++)
935 : {
936 32025 : R = gcdreal(gel(C,i), R);
937 32025 : if (!R) return fupb_PRECI;
938 : }
939 2877 : if (gexpo(R) <= -3)
940 : {
941 0 : if (DEBUGLEVEL>2) err_printf("regulator is zero.\n");
942 0 : return fupb_RELAT;
943 : }
944 2877 : if (DEBUGLEVEL>2) err_printf("#### Tentative regulator: %Ps\n",R);
945 : }
946 90925 : c = gtodouble(gmul(z, R));
947 90924 : if (c < 0.8 || c > 1.3) return fupb_RELAT;
948 70255 : *ptR = R; return fupb_NONE;
949 : }
950 :
951 : static int
952 70255 : quad_be_honest(struct buch_quad *B)
953 : {
954 : int r;
955 70255 : if (B->KC2 <= B->KC) return 1;
956 14 : if (DEBUGLEVEL>2)
957 0 : err_printf("be honest for primes from %ld to %ld\n", B->FB[B->KC+1],B->FB[B->KC2]);
958 14 : r = B->PRECREG? real_be_honest(B): imag_be_honest(B);
959 14 : if (DEBUGLEVEL>2) err_printf("\n");
960 14 : return r;
961 : }
962 :
963 : static GEN
964 70432 : Buchquad_i(GEN D, double cbach, double cbach2, long prec)
965 : {
966 70432 : const long MAXRELSUP = 7, SFB_MAX = 3;
967 : pari_timer T;
968 : pari_sp av, av2;
969 70432 : const long RELSUP = 5;
970 : long i, s, current, triv, sfb_trials, nrelsup, nreldep, need, nsubFB, minSFB;
971 : ulong low, high, LIMC0, LIMC, LIMC2, LIMCMAX, cp;
972 70432 : GEN W, cyc, gen, dep, mat, C, extraC, B, R, invhr, h = NULL; /*-Wall*/
973 : double drc, sdrc, lim, LOGD, LOGD2;
974 : GRHcheck_t GRHcheck;
975 : struct qfr_data q;
976 : struct buch_quad BQ;
977 70432 : int FIRST = 1;
978 :
979 70432 : check_quaddisc(D, &s, /*junk*/&i, "Buchquad");
980 70433 : R = NULL; /* -Wall */
981 70433 : BQ.q = &q;
982 70433 : q.D = D;
983 70433 : if (s < 0)
984 : {
985 68277 : if (abscmpiu(q.D,4) <= 0)
986 175 : retmkvec4(gen_1, cgetg(1,t_VEC), cgetg(1,t_VEC), gen_1);
987 68101 : prec = BQ.PRECREG = 0;
988 : } else {
989 2156 : BQ.PRECREG = maxss(prec+EXTRAPREC64, nbits2prec(2*expi(q.D) + 128));
990 : }
991 70257 : if (DEBUGLEVEL>2) timer_start(&T);
992 70257 : BQ.primfact = new_chunk(100);
993 70256 : BQ.exprimfact = new_chunk(100);
994 70255 : BQ.hashtab = (long**) new_chunk(HASHT);
995 72006316 : for (i=0; i<HASHT; i++) BQ.hashtab[i] = NULL;
996 :
997 70258 : drc = fabs(gtodouble(q.D));
998 70254 : LOGD = log(drc);
999 70254 : LOGD2 = LOGD * LOGD;
1000 :
1001 70254 : sdrc = lim = sqrt(drc);
1002 70254 : if (!BQ.PRECREG) lim /= sqrt(3.);
1003 70254 : cp = (ulong)exp(sqrt(LOGD*log(LOGD)/8.0));
1004 70254 : if (cp < 20) cp = 20;
1005 70254 : if (cbach > 6.) {
1006 0 : if (cbach2 < cbach) cbach2 = cbach;
1007 0 : cbach = 6.;
1008 : }
1009 70254 : if (cbach < 0.)
1010 0 : pari_err_DOMAIN("Buchquad","Bach constant","<",gen_0,dbltor(cbach));
1011 70254 : av = avma;
1012 70254 : BQ.powsubFB = BQ.subFB = NULL;
1013 70254 : minSFB = (expi(D) > 15)? 3: 2;
1014 70257 : init_GRHcheck(&GRHcheck, 2, BQ.PRECREG? 2: 0, LOGD);
1015 70257 : high = low = LIMC0 = maxss((long)(cbach2*LOGD2), 1);
1016 70256 : LIMCMAX = (long)(4.*LOGD2);
1017 : /* 97/1223 below to ensure a good enough approximation of residue */
1018 70256 : cache_prime_quad(&GRHcheck, expi(D) < 16 ? 97: 1223, D);
1019 586628 : while (!quadGRHchk(D, &GRHcheck, high))
1020 : {
1021 516370 : low = high;
1022 516370 : high *= 2;
1023 : }
1024 516438 : while (high - low > 1)
1025 : {
1026 446189 : long test = (low+high)/2;
1027 446189 : if (quadGRHchk(D, &GRHcheck, test))
1028 233706 : high = test;
1029 : else
1030 212483 : low = test;
1031 : }
1032 70249 : if (high == LIMC0+1 && quadGRHchk(D, &GRHcheck, LIMC0))
1033 0 : LIMC2 = LIMC0;
1034 : else
1035 70249 : LIMC2 = high;
1036 70249 : if (LIMC2 > LIMCMAX) LIMC2 = LIMCMAX;
1037 70249 : LIMC0 = (long)(cbach*LOGD2);
1038 70249 : LIMC = cbach ? LIMC0 : LIMC2;
1039 70249 : LIMC = maxss(LIMC, nthidealquad(D, 2));
1040 :
1041 : /* LIMC = Max(cbach*(log D)^2, exp(sqrt(log D loglog D) / 8)) */
1042 70257 : START:
1043 : do
1044 : {
1045 70390 : if (!FIRST) LIMC = bnf_increase_LIMC(LIMC,LIMCMAX);
1046 70390 : if (DEBUGLEVEL>2 && LIMC > LIMC0)
1047 0 : err_printf("%s*** Bach constant: %f\n", FIRST?"":"\n", LIMC/LOGD2);
1048 70390 : FIRST = 0; set_avma(av);
1049 70390 : guncloneNULL(BQ.subFB);
1050 70390 : guncloneNULL(BQ.powsubFB);
1051 70390 : clearhash(BQ.hashtab);
1052 70391 : if (LIMC < cp) LIMC = cp;
1053 70391 : if (LIMC2 < LIMC) LIMC2 = LIMC;
1054 70391 : if (BQ.PRECREG) qfr_data_init(q.D, BQ.PRECREG, &q);
1055 :
1056 70391 : FBquad(&BQ, LIMC2, LIMC, &GRHcheck);
1057 70390 : if (DEBUGLEVEL>2) timer_printf(&T, "factor base");
1058 70390 : BQ.subFB = subFBquad(&BQ, q.D, lim + 0.5, minSFB);
1059 70391 : if (DEBUGLEVEL>2) timer_printf(&T, "subFBquad = %Ps",
1060 : vecpermute(BQ.FB, BQ.subFB));
1061 70391 : nsubFB = lg(BQ.subFB) - 1;
1062 : }
1063 70391 : while (nsubFB < (expi(D) > 15 ? 3 : 2));
1064 : /* invhr = 2^r1 (2pi)^r2 / sqrt(D) w ~ L(chi,1) / hR */
1065 70258 : invhr = gmul(dbltor((BQ.PRECREG?2.:M_PI)/sdrc),
1066 : compute_invresquad(&GRHcheck, LIMC));
1067 70256 : BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1);
1068 70258 : if (DEBUGLEVEL>2) timer_printf(&T, "powsubFBquad");
1069 70258 : BQ.limhash = (LIMC & HIGHMASK)? (HIGHBIT>>1): LIMC*LIMC;
1070 :
1071 70258 : need = BQ.KC + RELSUP - 2;
1072 70258 : current = 0;
1073 70258 : W = NULL;
1074 70258 : sfb_trials = nreldep = nrelsup = 0;
1075 70258 : s = nsubFB + RELSUP;
1076 70258 : av2 = avma;
1077 :
1078 : do
1079 : {
1080 103809 : if ((nreldep & 3) == 1 || (nrelsup & 7) == 1) {
1081 28787 : if (DEBUGLEVEL>2) err_printf("*** Changing sub factor base\n");
1082 28787 : gunclone(BQ.subFB);
1083 28787 : gunclone(BQ.powsubFB);
1084 28787 : BQ.subFB = gclone(vecslice(BQ.vperm, 1, nsubFB));
1085 28787 : BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1);
1086 28787 : if (DEBUGLEVEL>2) timer_printf(&T, "powsubFBquad");
1087 28787 : clearhash(BQ.hashtab);
1088 : }
1089 103809 : need += 2;
1090 103809 : mat = cgetg(need+1, t_MAT);
1091 103806 : extraC = cgetg(need+1, t_VEC);
1092 103808 : if (!W) { /* first time */
1093 70257 : C = extraC;
1094 70257 : triv = trivial_relations(&BQ, mat, C);
1095 70258 : if (DEBUGLEVEL>2) err_printf("KC = %ld, need %ld relations\n", BQ.KC, need);
1096 : } else {
1097 33551 : triv = 0;
1098 33551 : if (DEBUGLEVEL>2) err_printf("...need %ld more relations\n", need);
1099 : }
1100 103809 : if (BQ.PRECREG) {
1101 189378 : for (i = triv+1; i<=need; i++) {
1102 184254 : gel(mat,i) = zero_zv(BQ.KC);
1103 184254 : gel(extraC,i) = cgetr(BQ.PRECREG);
1104 : }
1105 5124 : real_relations(&BQ, need - triv, ¤t, s,LIMC,mat + triv,extraC + triv);
1106 : } else {
1107 1702284 : for (i = triv+1; i<=need; i++) {
1108 1603601 : gel(mat,i) = zero_zv(BQ.KC);
1109 1603599 : gel(extraC,i) = gen_0;
1110 : }
1111 98683 : imag_relations(&BQ, need - triv, ¤t, LIMC,mat + triv);
1112 : }
1113 :
1114 103808 : if (!W)
1115 70257 : W = hnfspec_i(mat,BQ.vperm,&dep,&B,&C,nsubFB);
1116 : else
1117 33551 : W = hnfadd_i(W,BQ.vperm,&dep,&B,&C, mat,extraC);
1118 103808 : gerepileall(av2, 4, &W,&C,&B,&dep);
1119 103809 : need = BQ.KC - (lg(W)-1) - (lg(B)-1);
1120 103809 : if (need)
1121 : {
1122 12881 : if (++nreldep > 15 && cbach < 1) goto START;
1123 12881 : continue;
1124 : }
1125 :
1126 90928 : h = ZM_det_triangular(W);
1127 90927 : if (DEBUGLEVEL>2) err_printf("\n#### Tentative class number: %Ps\n", h);
1128 :
1129 90927 : switch(get_R(&BQ, C, (lg(C)-1) - (lg(B)-1) - (lg(W)-1), mulir(h,invhr), &R))
1130 : {
1131 0 : case fupb_PRECI:
1132 0 : BQ.PRECREG = precdbl(BQ.PRECREG);
1133 0 : FIRST = 1; goto START;
1134 :
1135 20669 : case fupb_RELAT:
1136 20669 : if (++nrelsup > MAXRELSUP)
1137 : {
1138 35 : if (++sfb_trials > SFB_MAX && cbach <= 1) goto START;
1139 35 : if (nsubFB < minss(10,BQ.KC)) nsubFB++;
1140 : }
1141 20669 : need = minss(BQ.KC, nrelsup);
1142 : }
1143 : }
1144 103806 : while (need);
1145 : /* DONE */
1146 70255 : if (!quad_be_honest(&BQ)) goto START;
1147 70255 : if (DEBUGLEVEL>2) timer_printf(&T, "be honest");
1148 70255 : clearhash(BQ.hashtab);
1149 70258 : free_GRHcheck(&GRHcheck);
1150 :
1151 70257 : gen = get_clgp(&BQ,W,&cyc);
1152 70258 : gunclone(BQ.subFB);
1153 70258 : gunclone(BQ.powsubFB);
1154 70257 : return mkvec4(h, cyc, gen, R);
1155 : }
1156 : GEN
1157 4396 : Buchquad(GEN D, double c, double c2, long prec)
1158 : {
1159 4396 : pari_sp av = avma;
1160 4396 : GEN z = Buchquad_i(D, c, c2, prec);
1161 4396 : return gerepilecopy(av, z);
1162 : }
1163 :
1164 : GEN
1165 0 : buchimag(GEN D, GEN c, GEN c2, GEN REL)
1166 0 : { (void)REL; return Buchquad(D,gtodouble(c),gtodouble(c2),0); }
1167 :
1168 : GEN
1169 0 : buchreal(GEN D, GEN flag, GEN c, GEN c2, GEN REL, long prec) {
1170 0 : if (signe(flag)) pari_err_IMPL("narrow class group");
1171 0 : (void)REL; return Buchquad(D,gtodouble(c),gtodouble(c2),prec);
1172 : }
1173 :
1174 : GEN
1175 4396 : quadclassunit0(GEN x, long flag, GEN data, long prec)
1176 : {
1177 : long lx;
1178 4396 : double c1 = 0.0, c2 = 0.0;
1179 :
1180 4396 : if (!data) lx=1;
1181 : else
1182 : {
1183 28 : lx = lg(data);
1184 28 : if (typ(data)!=t_VEC) pari_err_TYPE("quadclassunit", data);
1185 28 : if (lx > 7) pari_err_DIM("quadclassunit [tech vector]");
1186 28 : if (lx > 3) lx = 3;
1187 : }
1188 4396 : switch(lx)
1189 : {
1190 21 : case 3: c2 = gtodouble(gel(data,2));
1191 28 : case 2: c1 = gtodouble(gel(data,1));
1192 : }
1193 4396 : if (flag) pari_err_IMPL("narrow class group");
1194 4396 : return Buchquad(x,c1,c2,prec);
1195 : }
1196 : GEN
1197 61168 : quadclassno(GEN D)
1198 : {
1199 61168 : pari_sp av = avma;
1200 61168 : GEN h = abgrp_get_no(Buchquad_i(D, 0, 0, 0));
1201 61166 : return icopy_avma(h, av);
1202 : }
1203 : long
1204 4868 : quadclassnos(long D)
1205 : {
1206 4868 : pari_sp av = avma;
1207 4868 : long h = itos(abgrp_get_no(Buchquad_i(stoi(D), 0, 0, 0)));
1208 4868 : return gc_long(av, h);
1209 : }
|