Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

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

28478 views
License: GPL3
ubuntu2004
1
/* Copyright (C) 2000 The PARI group.
2
3
This file is part of the PARI/GP package.
4
5
PARI/GP is free software; you can redistribute it and/or modify it under the
6
terms of the GNU General Public License as published by the Free Software
7
Foundation; either version 2 of the License, or (at your option) any later
8
version. It is distributed in the hope that it will be useful, but WITHOUT
9
ANY WARRANTY WHATSOEVER.
10
11
Check the License for details. You should have received a copy of it, along
12
with the package; see the file 'COPYING'. If not, write to the Free Software
13
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14
#include "pari.h"
15
#include "paripriv.h"
16
17
#define DEBUGLEVEL DEBUGLEVEL_factor
18
19
/* x,y two ZX, y non constant. Return q = x/y if y divides x in Z[X] and NULL
20
* otherwise. If not NULL, B is a t_INT upper bound for ||q||_oo. */
21
static GEN
22
ZX_divides_i(GEN x, GEN y, GEN B)
23
{
24
long dx, dy, dz, i, j;
25
pari_sp av;
26
GEN z,p1,y_lead;
27
28
dy=degpol(y);
29
dx=degpol(x);
30
dz=dx-dy; if (dz<0) return NULL;
31
z=cgetg(dz+3,t_POL); z[1] = x[1];
32
x += 2; y += 2; z += 2;
33
y_lead = gel(y,dy);
34
if (equali1(y_lead)) y_lead = NULL;
35
36
p1 = gel(x,dx);
37
if (y_lead) {
38
GEN r;
39
p1 = dvmdii(p1,y_lead, &r);
40
if (r != gen_0) return NULL;
41
}
42
else p1 = icopy(p1);
43
gel(z,dz) = p1;
44
for (i=dx-1; i>=dy; i--)
45
{
46
av = avma; p1 = gel(x,i);
47
for (j=i-dy+1; j<=i && j<=dz; j++)
48
p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
49
if (y_lead) {
50
GEN r;
51
p1 = dvmdii(p1,y_lead, &r);
52
if (r != gen_0) return NULL;
53
}
54
if (B && abscmpii(p1, B) > 0) return NULL;
55
p1 = gerepileuptoint(av, p1);
56
gel(z,i-dy) = p1;
57
}
58
av = avma;
59
for (; i >= 0; i--)
60
{
61
p1 = gel(x,i);
62
/* we always enter this loop at least once */
63
for (j=0; j<=i && j<=dz; j++)
64
p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
65
if (signe(p1)) return NULL;
66
set_avma(av);
67
}
68
return z - 2;
69
}
70
static GEN
71
ZX_divides(GEN x, GEN y) { return ZX_divides_i(x,y,NULL); }
72
73
#if 0
74
/* cf Beauzamy et al: upper bound for
75
* lc(x) * [2^(5/8) / pi^(3/8)] e^(1/4n) 2^(n/2) sqrt([x]_2)/ n^(3/8)
76
* where [x]_2 = sqrt(\sum_i=0^n x[i]^2 / binomial(n,i)). One factor has
77
* all coeffs less than then bound */
78
static GEN
79
two_factor_bound(GEN x)
80
{
81
long i, j, n = lg(x) - 3;
82
pari_sp av = avma;
83
GEN *invbin, c, r = cgetr(3), z;
84
85
x += 2; invbin = (GEN*)new_chunk(n+1);
86
z = real_1(LOWDEFAULTPREC); /* invbin[i] = 1 / binomial(n, i) */
87
for (i=0,j=n; j >= i; i++,j--)
88
{
89
invbin[i] = invbin[j] = z;
90
z = divru(mulru(z, i+1), n-i);
91
}
92
z = invbin[0]; /* = 1 */
93
for (i=0; i<=n; i++)
94
{
95
c = gel(x,i); if (!signe(c)) continue;
96
affir(c, r);
97
z = addrr(z, mulrr(sqrr(r), invbin[i]));
98
}
99
z = shiftr(sqrtr(z), n);
100
z = divrr(z, dbltor(pow((double)n, 0.75)));
101
z = roundr_safe(sqrtr(z));
102
z = mulii(z, absi_shallow(gel(x,n)));
103
return gerepileuptoint(av, shifti(z, 1));
104
}
105
#endif
106
107
/* A | S ==> |a_i| <= binom(d-1, i-1) || S ||_2 + binom(d-1, i) lc(S) */
108
static GEN
109
Mignotte_bound(GEN S)
110
{
111
long i, d = degpol(S);
112
GEN C, N2, t, binlS, lS = leading_coeff(S), bin = vecbinomial(d-1);
113
114
N2 = sqrtr(RgX_fpnorml2(S,DEFAULTPREC));
115
binlS = is_pm1(lS)? bin: ZC_Z_mul(bin, lS);
116
117
/* i = 0 */
118
C = gel(binlS,1);
119
/* i = d */
120
t = N2; if (gcmp(C, t) < 0) C = t;
121
for (i = 1; i < d; i++)
122
{
123
t = addri(mulir(gel(bin,i), N2), gel(binlS,i+1));
124
if (mpcmp(C, t) < 0) C = t;
125
}
126
return C;
127
}
128
/* A | S ==> |a_i|^2 <= 3^{3/2 + d} / (4 \pi d) [P]_2^2,
129
* where [P]_2 is Bombieri's 2-norm */
130
static GEN
131
Beauzamy_bound(GEN S)
132
{
133
const long prec = DEFAULTPREC;
134
long i, d = degpol(S);
135
GEN bin, lS, s, C;
136
bin = vecbinomial(d);
137
138
s = real_0(prec);
139
for (i=0; i<=d; i++)
140
{
141
GEN c = gel(S,i+2);
142
if (gequal0(c)) continue;
143
/* s += P_i^2 / binomial(d,i) */
144
s = addrr(s, divri(itor(sqri(c), prec), gel(bin,i+1)));
145
}
146
/* s = [S]_2^2 */
147
C = powruhalf(utor(3,prec), 3 + 2*d); /* 3^{3/2 + d} */
148
C = divrr(mulrr(C, s), mulur(4*d, mppi(prec)));
149
lS = absi_shallow(leading_coeff(S));
150
return mulir(lS, sqrtr(C));
151
}
152
153
static GEN
154
factor_bound(GEN S)
155
{
156
pari_sp av = avma;
157
GEN a = Mignotte_bound(S);
158
GEN b = Beauzamy_bound(S);
159
if (DEBUGLEVEL>2)
160
{
161
err_printf("Mignotte bound: %Ps\n",a);
162
err_printf("Beauzamy bound: %Ps\n",b);
163
}
164
return gerepileupto(av, ceil_safe(gmin_shallow(a, b)));
165
}
166
167
/* Naive recombination of modular factors: combine up to maxK modular
168
* factors, degree <= klim
169
*
170
* target = polynomial we want to factor
171
* famod = array of modular factors. Product should be congruent to
172
* target/lc(target) modulo p^a
173
* For true factors: S1,S2 <= p^b, with b <= a and p^(b-a) < 2^31 */
174
static GEN
175
cmbf(GEN pol, GEN famod, GEN bound, GEN p, long a, long b,
176
long klim, long *pmaxK, int *done)
177
{
178
long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1;
179
ulong spa_b, spa_bs2, Sbound;
180
GEN lc, lcpol, pa = powiu(p,a), pas2 = shifti(pa,-1);
181
GEN trace1 = cgetg(lfamod+1, t_VECSMALL);
182
GEN trace2 = cgetg(lfamod+1, t_VECSMALL);
183
GEN ind = cgetg(lfamod+1, t_VECSMALL);
184
GEN deg = cgetg(lfamod+1, t_VECSMALL);
185
GEN degsofar = cgetg(lfamod+1, t_VECSMALL);
186
GEN listmod = cgetg(lfamod+1, t_VEC);
187
GEN fa = cgetg(lfamod+1, t_VEC);
188
189
*pmaxK = cmbf_maxK(lfamod);
190
lc = absi_shallow(leading_coeff(pol));
191
if (equali1(lc)) lc = NULL;
192
lcpol = lc? ZX_Z_mul(pol, lc): pol;
193
194
{
195
GEN pa_b,pa_bs2,pb, lc2 = lc? sqri(lc): NULL;
196
197
pa_b = powiu(p, a-b); /* < 2^31 */
198
pa_bs2 = shifti(pa_b,-1);
199
pb= powiu(p, b);
200
for (i=1; i <= lfamod; i++)
201
{
202
GEN T1,T2, P = gel(famod,i);
203
long d = degpol(P);
204
205
deg[i] = d; P += 2;
206
T1 = gel(P,d-1);/* = - S_1 */
207
T2 = sqri(T1);
208
if (d > 1) T2 = subii(T2, shifti(gel(P,d-2),1));
209
T2 = modii(T2, pa); /* = S_2 Newton sum */
210
if (lc)
211
{
212
T1 = Fp_mul(lc, T1, pa);
213
T2 = Fp_mul(lc2,T2, pa);
214
}
215
uel(trace1,i) = itou(diviiround(T1, pb));
216
uel(trace2,i) = itou(diviiround(T2, pb));
217
}
218
spa_b = uel(pa_b,2); /* < 2^31 */
219
spa_bs2 = uel(pa_bs2,2); /* < 2^31 */
220
}
221
degsofar[0] = 0; /* sentinel */
222
223
/* ind runs through strictly increasing sequences of length K,
224
* 1 <= ind[i] <= lfamod */
225
nextK:
226
if (K > *pmaxK || 2*K > lfamod) goto END;
227
if (DEBUGLEVEL > 3)
228
err_printf("\n### K = %d, %Ps combinations\n", K,binomial(utoipos(lfamod), K));
229
setlg(ind, K+1); ind[1] = 1;
230
Sbound = (ulong) ((K+1)>>1);
231
i = 1; curdeg = deg[ind[1]];
232
for(;;)
233
{ /* try all combinations of K factors */
234
for (j = i; j < K; j++)
235
{
236
degsofar[j] = curdeg;
237
ind[j+1] = ind[j]+1; curdeg += deg[ind[j+1]];
238
}
239
if (curdeg <= klim) /* trial divide */
240
{
241
GEN y, q, list;
242
pari_sp av;
243
ulong t;
244
245
/* d - 1 test */
246
for (t=uel(trace1,ind[1]),i=2; i<=K; i++)
247
t = Fl_add(t, uel(trace1,ind[i]), spa_b);
248
if (t > spa_bs2) t = spa_b - t;
249
if (t > Sbound)
250
{
251
if (DEBUGLEVEL>6) err_printf(".");
252
goto NEXT;
253
}
254
/* d - 2 test */
255
for (t=uel(trace2,ind[1]),i=2; i<=K; i++)
256
t = Fl_add(t, uel(trace2,ind[i]), spa_b);
257
if (t > spa_bs2) t = spa_b - t;
258
if (t > Sbound)
259
{
260
if (DEBUGLEVEL>6) err_printf("|");
261
goto NEXT;
262
}
263
264
av = avma;
265
/* check trailing coeff */
266
y = lc;
267
for (i=1; i<=K; i++)
268
{
269
GEN q = constant_coeff(gel(famod,ind[i]));
270
if (y) q = mulii(y, q);
271
y = centermodii(q, pa, pas2);
272
}
273
if (!signe(y) || !dvdii(constant_coeff(lcpol), y))
274
{
275
if (DEBUGLEVEL>3) err_printf("T");
276
set_avma(av); goto NEXT;
277
}
278
y = lc; /* full computation */
279
for (i=1; i<=K; i++)
280
{
281
GEN q = gel(famod,ind[i]);
282
if (y) q = gmul(y, q);
283
y = centermod_i(q, pa, pas2);
284
}
285
286
/* y is the candidate factor */
287
if (! (q = ZX_divides_i(lcpol,y,bound)) )
288
{
289
if (DEBUGLEVEL>3) err_printf("*");
290
set_avma(av); goto NEXT;
291
}
292
/* found a factor */
293
list = cgetg(K+1, t_VEC);
294
gel(listmod,cnt) = list;
295
for (i=1; i<=K; i++) list[i] = famod[ind[i]];
296
297
y = Q_primpart(y);
298
gel(fa,cnt++) = y;
299
/* fix up pol */
300
pol = q;
301
if (lc) pol = Q_div_to_int(pol, leading_coeff(y));
302
for (i=j=k=1; i <= lfamod; i++)
303
{ /* remove used factors */
304
if (j <= K && i == ind[j]) j++;
305
else
306
{
307
gel(famod,k) = gel(famod,i);
308
uel(trace1,k) = uel(trace1,i);
309
uel(trace2,k) = uel(trace2,i);
310
deg[k] = deg[i]; k++;
311
}
312
}
313
lfamod -= K;
314
*pmaxK = cmbf_maxK(lfamod);
315
if (lfamod < 2*K) goto END;
316
i = 1; curdeg = deg[ind[1]];
317
bound = factor_bound(pol);
318
if (lc) lc = absi_shallow(leading_coeff(pol));
319
lcpol = lc? ZX_Z_mul(pol, lc): pol;
320
if (DEBUGLEVEL>3)
321
err_printf("\nfound factor %Ps\nremaining modular factor(s): %ld\n",
322
y, lfamod);
323
continue;
324
}
325
326
NEXT:
327
for (i = K+1;;)
328
{
329
if (--i == 0) { K++; goto nextK; }
330
if (++ind[i] <= lfamod - K + i)
331
{
332
curdeg = degsofar[i-1] + deg[ind[i]];
333
if (curdeg <= klim) break;
334
}
335
}
336
}
337
END:
338
*done = 1;
339
if (degpol(pol) > 0)
340
{ /* leftover factor */
341
if (signe(leading_coeff(pol)) < 0) pol = ZX_neg(pol);
342
if (lfamod >= 2*K) *done = 0;
343
344
setlg(famod, lfamod+1);
345
gel(listmod,cnt) = leafcopy(famod);
346
gel(fa,cnt++) = pol;
347
}
348
if (DEBUGLEVEL>6) err_printf("\n");
349
setlg(listmod, cnt);
350
setlg(fa, cnt); return mkvec2(fa, listmod);
351
}
352
353
/* recombination of modular factors: van Hoeij's algorithm */
354
355
/* Q in Z[X], return Q(2^n) */
356
static GEN
357
shifteval(GEN Q, long n)
358
{
359
pari_sp av = avma;
360
long i, l = lg(Q);
361
GEN s;
362
363
if (!signe(Q)) return gen_0;
364
s = gel(Q,l-1);
365
for (i = l-2; i > 1; i--)
366
{
367
s = addii(gel(Q,i), shifti(s, n));
368
if (gc_needed(av,1)) s = gerepileuptoint(av, s);
369
}
370
return s;
371
}
372
373
/* return integer y such that all |a| <= y if P(a) = 0 */
374
static GEN
375
root_bound(GEN P0)
376
{
377
GEN Q = leafcopy(P0), lP = absi_shallow(leading_coeff(Q)), x,y,z;
378
long k, d = degpol(Q);
379
380
/* P0 = lP x^d + Q, deg Q < d */
381
Q = normalizepol_lg(Q, d+2);
382
for (k=lg(Q)-1; k>1; k--) gel(Q,k) = absi_shallow(gel(Q,k));
383
k = (long)(fujiwara_bound(P0));
384
for ( ; k >= 0; k--)
385
{
386
pari_sp av = avma;
387
/* y = 2^k; Q(y) >= lP y^d ? */
388
if (cmpii(shifteval(Q,k), shifti(lP, d*k)) >= 0) break;
389
set_avma(av);
390
}
391
if (k < 0) k = 0;
392
y = int2n(k+1);
393
if (d > 2000) return y; /* likely to be expensive, don't bother */
394
x = int2n(k);
395
for(k=0; ; k++)
396
{
397
z = shifti(addii(x,y), -1);
398
if (equalii(x,z) || k > 5) break;
399
if (cmpii(ZX_Z_eval(Q,z), mulii(lP, powiu(z, d))) < 0)
400
y = z;
401
else
402
x = z;
403
}
404
return y;
405
}
406
407
GEN
408
chk_factors_get(GEN lt, GEN famod, GEN c, GEN T, GEN N)
409
{
410
long i = 1, j, l = lg(famod);
411
GEN V = cgetg(l, t_VEC);
412
for (j = 1; j < l; j++)
413
if (signe(gel(c,j))) gel(V,i++) = gel(famod,j);
414
if (lt && i > 1) gel(V,1) = RgX_Rg_mul(gel(V,1), lt);
415
setlg(V, i);
416
return T? FpXQXV_prod(V, T, N): FpXV_prod(V,N);
417
}
418
419
static GEN
420
chk_factors(GEN P, GEN M_L, GEN bound, GEN famod, GEN pa)
421
{
422
long i, r;
423
GEN pol = P, list, piv, y, ltpol, lt, paov2;
424
425
piv = ZM_hnf_knapsack(M_L);
426
if (!piv) return NULL;
427
if (DEBUGLEVEL>7) err_printf("ZM_hnf_knapsack output:\n%Ps\n",piv);
428
429
r = lg(piv)-1;
430
list = cgetg(r+1, t_VEC);
431
lt = absi_shallow(leading_coeff(pol));
432
if (equali1(lt)) lt = NULL;
433
ltpol = lt? ZX_Z_mul(pol, lt): pol;
434
paov2 = shifti(pa,-1);
435
for (i = 1;;)
436
{
437
if (DEBUGLEVEL) err_printf("LLL_cmbf: checking factor %ld\n",i);
438
y = chk_factors_get(lt, famod, gel(piv,i), NULL, pa);
439
y = FpX_center_i(y, pa, paov2);
440
if (! (pol = ZX_divides_i(ltpol,y,bound)) ) return NULL;
441
if (lt) y = Q_primpart(y);
442
gel(list,i) = y;
443
if (++i >= r) break;
444
445
if (lt)
446
{
447
pol = ZX_Z_divexact(pol, leading_coeff(y));
448
lt = absi_shallow(leading_coeff(pol));
449
ltpol = ZX_Z_mul(pol, lt);
450
}
451
else
452
ltpol = pol;
453
}
454
y = Q_primpart(pol);
455
gel(list,i) = y; return list;
456
}
457
458
GEN
459
LLL_check_progress(GEN Bnorm, long n0, GEN m, int final, long *ti_LLL)
460
{
461
GEN norm, u;
462
long i, R;
463
pari_timer T;
464
465
if (DEBUGLEVEL>2) timer_start(&T);
466
u = ZM_lll_norms(m, final? 0.999: 0.75, LLL_INPLACE, &norm);
467
if (DEBUGLEVEL>2) *ti_LLL += timer_delay(&T);
468
for (R=lg(m)-1; R > 0; R--)
469
if (cmprr(gel(norm,R), Bnorm) < 0) break;
470
for (i=1; i<=R; i++) setlg(u[i], n0+1);
471
if (R <= 1)
472
{
473
if (!R) pari_err_BUG("LLL_cmbf [no factor]");
474
return NULL; /* irreducible */
475
}
476
setlg(u, R+1); return u;
477
}
478
479
static ulong
480
next2pow(ulong a)
481
{
482
ulong b = 1;
483
while (b < a) b <<= 1;
484
return b;
485
}
486
487
/* Recombination phase of Berlekamp-Zassenhaus algorithm using a variant of
488
* van Hoeij's knapsack
489
*
490
* P = squarefree in Z[X].
491
* famod = array of (lifted) modular factors mod p^a
492
* bound = Mignotte bound for the size of divisors of P (for the sup norm)
493
* previously recombined all set of factors with less than rec elts */
494
static GEN
495
LLL_cmbf(GEN P, GEN famod, GEN p, GEN pa, GEN bound, long a, long rec)
496
{
497
const long N0 = 1; /* # of traces added at each step */
498
double BitPerFactor = 0.4; /* nb bits in p^(a-b) / modular factor */
499
long i,j,tmax,n0,C, dP = degpol(P);
500
double logp = log((double)itos(p)), LOGp2 = M_LN2/logp;
501
double b0 = log((double)dP*2) / logp, logBr;
502
GEN lP, Br, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO;
503
pari_sp av, av2;
504
long ti_LLL = 0, ti_CF = 0;
505
506
lP = absi_shallow(leading_coeff(P));
507
if (equali1(lP)) lP = NULL;
508
Br = root_bound(P);
509
if (lP) Br = mulii(lP, Br);
510
logBr = gtodouble(glog(Br, DEFAULTPREC)) / logp;
511
512
n0 = lg(famod) - 1;
513
C = (long)ceil( sqrt(N0 * n0 / 4.) ); /* > 1 */
514
Bnorm = dbltor(n0 * (C*C + N0*n0/4.) * 1.00001);
515
ZERO = zeromat(n0, N0);
516
517
av = avma;
518
TT = cgetg(n0+1, t_VEC);
519
Tra = cgetg(n0+1, t_MAT);
520
for (i=1; i<=n0; i++)
521
{
522
TT[i] = 0;
523
gel(Tra,i) = cgetg(N0+1, t_COL);
524
}
525
CM_L = scalarmat_s(C, n0);
526
/* tmax = current number of traces used (and computed so far) */
527
for (tmax = 0;; tmax += N0)
528
{
529
long b, bmin, bgood, delta, tnew = tmax + N0, r = lg(CM_L)-1;
530
GEN M_L, q, CM_Lp, oldCM_L;
531
int first = 1;
532
pari_timer ti2, TI;
533
534
bmin = (long)ceil(b0 + tnew*logBr);
535
if (DEBUGLEVEL>2)
536
err_printf("\nLLL_cmbf: %ld potential factors (tmax = %ld, bmin = %ld)\n",
537
r, tmax, bmin);
538
539
/* compute Newton sums (possibly relifting first) */
540
if (a <= bmin)
541
{
542
a = (long)ceil(bmin + 3*N0*logBr) + 1; /* enough for 3 more rounds */
543
a = (long)next2pow((ulong)a);
544
545
pa = powiu(p,a);
546
famod = ZpX_liftfact(P, famod, pa, p, a);
547
for (i=1; i<=n0; i++) TT[i] = 0;
548
}
549
for (i=1; i<=n0; i++)
550
{
551
GEN p1 = gel(Tra,i);
552
GEN p2 = polsym_gen(gel(famod,i), gel(TT,i), tnew, NULL, pa);
553
gel(TT,i) = p2;
554
p2 += 1+tmax; /* ignore traces number 0...tmax */
555
for (j=1; j<=N0; j++) gel(p1,j) = gel(p2,j);
556
if (lP)
557
{ /* make Newton sums integral */
558
GEN lPpow = powiu(lP, tmax);
559
for (j=1; j<=N0; j++)
560
{
561
lPpow = mulii(lPpow,lP);
562
gel(p1,j) = mulii(gel(p1,j), lPpow);
563
}
564
}
565
}
566
567
/* compute truncation parameter */
568
if (DEBUGLEVEL>2) { timer_start(&ti2); timer_start(&TI); }
569
oldCM_L = CM_L;
570
av2 = avma;
571
delta = b = 0; /* -Wall */
572
AGAIN:
573
M_L = Q_div_to_int(CM_L, utoipos(C));
574
T2 = centermod( ZM_mul(Tra, M_L), pa );
575
if (first)
576
{ /* initialize lattice, using few p-adic digits for traces */
577
double t = gexpo(T2) - maxdd(32.0, BitPerFactor*r);
578
bgood = (long) (t * LOGp2);
579
b = maxss(bmin, bgood);
580
delta = a - b;
581
}
582
else
583
{ /* add more p-adic digits and continue reduction */
584
long b0 = (long)(gexpo(T2) * LOGp2);
585
if (b0 < b) b = b0;
586
b = maxss(b-delta, bmin);
587
if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */
588
}
589
590
q = powiu(p, b);
591
m = vconcat( CM_L, gdivround(T2, q) );
592
if (first)
593
{
594
GEN P1 = scalarmat(powiu(p, a-b), N0);
595
first = 0;
596
m = shallowconcat( m, vconcat(ZERO, P1) );
597
/* [ C M_L 0 ]
598
* m = [ ] square matrix
599
* [ T2' p^(a-b) I_N0 ] T2' = Tra * M_L truncated
600
*/
601
}
602
603
CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL);
604
if (DEBUGLEVEL>2)
605
err_printf("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n",
606
a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, timer_delay(&TI));
607
if (!CM_L) { list = mkvec(P); break; }
608
if (b > bmin)
609
{
610
CM_L = gerepilecopy(av2, CM_L);
611
goto AGAIN;
612
}
613
if (DEBUGLEVEL>2) timer_printf(&ti2, "for this block of traces");
614
615
i = lg(CM_L) - 1;
616
if (i == r && ZM_equal(CM_L, oldCM_L))
617
{
618
CM_L = oldCM_L;
619
set_avma(av2); continue;
620
}
621
622
CM_Lp = FpM_image(CM_L, utoipos(27449)); /* inexpensive test */
623
if (lg(CM_Lp) != lg(CM_L))
624
{
625
if (DEBUGLEVEL>2) err_printf("LLL_cmbf: rank decrease\n");
626
CM_L = ZM_hnf(CM_L);
627
}
628
629
if (i <= r && i*rec < n0)
630
{
631
pari_timer ti;
632
if (DEBUGLEVEL>2) timer_start(&ti);
633
list = chk_factors(P, Q_div_to_int(CM_L,utoipos(C)), bound, famod, pa);
634
if (DEBUGLEVEL>2) ti_CF += timer_delay(&ti);
635
if (list) break;
636
if (DEBUGLEVEL>2) err_printf("LLL_cmbf: chk_factors failed");
637
}
638
CM_L = gerepilecopy(av2, CM_L);
639
if (gc_needed(av,1))
640
{
641
if(DEBUGMEM>1) pari_warn(warnmem,"LLL_cmbf");
642
gerepileall(av, 5, &CM_L, &TT, &Tra, &famod, &pa);
643
}
644
}
645
if (DEBUGLEVEL>2)
646
err_printf("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF);
647
return list;
648
}
649
650
/* Find a,b minimal such that A < q^a, B < q^b, 1 << q^(a-b) < 2^31 */
651
static int
652
cmbf_precs(GEN q, GEN A, GEN B, long *pta, long *ptb, GEN *qa, GEN *qb)
653
{
654
long a,b,amin,d = (long)(31 * M_LN2/gtodouble(glog(q,DEFAULTPREC)) - 1e-5);
655
int fl = 0;
656
657
b = logintall(B, q, qb) + 1;
658
*qb = mulii(*qb, q);
659
amin = b + d;
660
if (gcmp(powiu(q, amin), A) <= 0)
661
{
662
a = logintall(A, q, qa) + 1;
663
*qa = mulii(*qa, q);
664
b = a - d; *qb = powiu(q, b);
665
}
666
else
667
{ /* not enough room */
668
a = amin; *qa = powiu(q, a);
669
fl = 1;
670
}
671
if (DEBUGLEVEL > 3) {
672
err_printf("S_2 bound: %Ps^%ld\n", q,b);
673
err_printf("coeff bound: %Ps^%ld\n", q,a);
674
}
675
*pta = a;
676
*ptb = b; return fl;
677
}
678
679
/* use van Hoeij's knapsack algorithm */
680
static GEN
681
combine_factors(GEN target, GEN famod, GEN p, long klim)
682
{
683
GEN la, B, A, res, L, pa, pb, listmod;
684
long a,b, l, maxK, n = degpol(target);
685
int done;
686
pari_timer T;
687
688
A = factor_bound(target);
689
690
la = absi_shallow(leading_coeff(target));
691
B = mului(n, sqri(mulii(la, root_bound(target)))); /* = bound for S_2 */
692
693
(void)cmbf_precs(p, A, B, &a, &b, &pa, &pb);
694
695
if (DEBUGLEVEL>2) timer_start(&T);
696
famod = ZpX_liftfact(target, famod, pa, p, a);
697
if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %Ps^%ld)", p,a);
698
L = cmbf(target, famod, A, p, a, b, klim, &maxK, &done);
699
if (DEBUGLEVEL>2) timer_printf(&T, "Naive recombination");
700
701
res = gel(L,1);
702
listmod = gel(L,2); l = lg(listmod)-1;
703
famod = gel(listmod,l);
704
if (maxK > 0 && lg(famod)-1 > 2*maxK)
705
{
706
if (l!=1) A = factor_bound(gel(res,l));
707
if (DEBUGLEVEL > 4) err_printf("last factor still to be checked\n");
708
L = LLL_cmbf(gel(res,l), famod, p, pa, A, a, maxK);
709
if (DEBUGLEVEL>2) timer_printf(&T,"Knapsack");
710
/* remove last elt, possibly unfactored. Add all new ones. */
711
setlg(res, l); res = shallowconcat(res, L);
712
}
713
return res;
714
}
715
716
/* Assume 'a' a squarefree ZX; return 0 if no root (fl=1) / irreducible (fl=0).
717
* Otherwise return prime p such that a mod p has fewest roots / factors */
718
static ulong
719
pick_prime(GEN a, long fl, pari_timer *T)
720
{
721
pari_sp av = avma, av1;
722
const long MAXNP = 7, da = degpol(a);
723
long nmax = da+1, np;
724
ulong chosenp = 0;
725
GEN lead = gel(a,da+2);
726
forprime_t S;
727
if (equali1(lead)) lead = NULL;
728
u_forprime_init(&S, 2, ULONG_MAX);
729
av1 = avma;
730
for (np = 0; np < MAXNP; set_avma(av1))
731
{
732
ulong p = u_forprime_next(&S);
733
long nfacp;
734
GEN z;
735
736
if (!p) pari_err_OVERFLOW("DDF [out of small primes]");
737
if (lead && !umodiu(lead,p)) continue;
738
z = ZX_to_Flx(a, p);
739
if (!Flx_is_squarefree(z, p)) continue;
740
741
if (fl)
742
{
743
nfacp = Flx_nbroots(z, p);
744
if (!nfacp) { chosenp = 0; break; } /* no root */
745
}
746
else
747
{
748
nfacp = Flx_nbfact(z, p);
749
if (nfacp == 1) { chosenp = 0; break; } /* irreducible */
750
}
751
if (DEBUGLEVEL>4)
752
err_printf("...tried prime %3lu (%-3ld %s). Time = %ld\n",
753
p, nfacp, fl? "roots": "factors", timer_delay(T));
754
if (nfacp < nmax)
755
{
756
nmax = nfacp; chosenp = p;
757
if (da > 100 && nmax < 5) break; /* large degree, few factors. Enough */
758
}
759
np++;
760
}
761
return gc_ulong(av, chosenp);
762
}
763
764
/* Assume A a squarefree ZX; return the vector of its rational roots */
765
static GEN
766
DDF_roots(GEN A)
767
{
768
GEN p, lc, lcpol, z, pe, pes2, bound;
769
long i, m, e, lz;
770
ulong pp;
771
pari_sp av;
772
pari_timer T;
773
774
if (DEBUGLEVEL>2) timer_start(&T);
775
pp = pick_prime(A, 1, &T);
776
if (!pp) return cgetg(1,t_VEC); /* no root */
777
p = utoipos(pp);
778
lc = leading_coeff(A);
779
if (is_pm1(lc))
780
{ lc = NULL; lcpol = A; }
781
else
782
{ lc = absi_shallow(lc); lcpol = ZX_Z_mul(A, lc); }
783
bound = root_bound(A); if (lc) bound = mulii(lc, bound);
784
e = logintall(addiu(shifti(bound, 1), 1), p, &pe) + 1;
785
pe = mulii(pe, p);
786
pes2 = shifti(pe, -1);
787
if (DEBUGLEVEL>2) timer_printf(&T, "Root bound");
788
av = avma;
789
z = ZpX_roots(A, p, e); lz = lg(z);
790
z = deg1_from_roots(z, varn(A));
791
if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %lu^%ld)", pp,e);
792
for (m=1, i=1; i < lz; i++)
793
{
794
GEN q, r, y = gel(z,i);
795
if (lc) y = ZX_Z_mul(y, lc);
796
y = centermod_i(y, pe, pes2);
797
if (! (q = ZX_divides(lcpol, y)) ) continue;
798
799
lcpol = q;
800
r = negi( constant_coeff(y) );
801
if (lc) {
802
r = gdiv(r,lc);
803
lcpol = Q_primpart(lcpol);
804
lc = absi_shallow( leading_coeff(lcpol) );
805
if (is_pm1(lc)) lc = NULL; else lcpol = ZX_Z_mul(lcpol, lc);
806
}
807
gel(z,m++) = r;
808
if (gc_needed(av,2))
809
{
810
if (DEBUGMEM>1) pari_warn(warnmem,"DDF_roots, m = %ld", m);
811
gerepileall(av, lc? 3:2, &z, &lcpol, &lc);
812
}
813
}
814
if (DEBUGLEVEL>2) timer_printf(&T, "Recombination");
815
z[0] = evaltyp(t_VEC) | evallg(m); return z;
816
}
817
818
/* Assume a squarefree ZX, deg(a) > 0, return rational factors.
819
* In fact, a(0) != 0 but we don't use this */
820
static GEN
821
DDF(GEN a)
822
{
823
GEN ap, prime, famod, z;
824
long ti = 0;
825
ulong p = 0;
826
pari_sp av = avma;
827
pari_timer T, T2;
828
829
if (DEBUGLEVEL>2) { timer_start(&T); timer_start(&T2); }
830
p = pick_prime(a, 0, &T2);
831
if (!p) return mkvec(a);
832
prime = utoipos(p);
833
ap = Flx_normalize(ZX_to_Flx(a, p), p);
834
famod = gel(Flx_factor(ap, p), 1);
835
if (DEBUGLEVEL>2)
836
{
837
if (DEBUGLEVEL>4) timer_printf(&T2, "splitting mod p = %lu", p);
838
ti = timer_delay(&T);
839
err_printf("Time setup: %ld\n", ti);
840
}
841
z = combine_factors(a, FlxV_to_ZXV(famod), prime, degpol(a)-1);
842
if (DEBUGLEVEL>2)
843
err_printf("Total Time: %ld\n===========\n", ti + timer_delay(&T));
844
return gerepilecopy(av, z);
845
}
846
847
/* Distinct Degree Factorization (deflating first)
848
* Assume x squarefree, degree(x) > 0, x(0) != 0 */
849
GEN
850
ZX_DDF(GEN x)
851
{
852
GEN L;
853
long m;
854
x = ZX_deflate_max(x, &m);
855
L = DDF(x);
856
if (m > 1)
857
{
858
GEN e, v, fa = factoru(m);
859
long i,j,k, l;
860
861
e = gel(fa,2); k = 0;
862
fa= gel(fa,1); l = lg(fa);
863
for (i=1; i<l; i++) k += e[i];
864
v = cgetg(k+1, t_VECSMALL); k = 1;
865
for (i=1; i<l; i++)
866
for (j=1; j<=e[i]; j++) v[k++] = fa[i];
867
for (k--; k; k--)
868
{
869
GEN L2 = cgetg(1,t_VEC);
870
for (i=1; i < lg(L); i++)
871
L2 = shallowconcat(L2, DDF(RgX_inflate(gel(L,i), v[k])));
872
L = L2;
873
}
874
}
875
return L;
876
}
877
878
/* SquareFree Factorization. f = prod P^e, all e distinct, in Z[X] (char 0
879
* would be enough, if ZX_gcd --> ggcd). Return (P), set *ex = (e) */
880
GEN
881
ZX_squff(GEN f, GEN *ex)
882
{
883
GEN T, V, P, e;
884
long i, k, val = ZX_valrem(f, &f), n = 2 + degpol(f);
885
886
if (signe(leading_coeff(f)) < 0) f = ZX_neg(f);
887
e = cgetg(n,t_VECSMALL);
888
P = cgetg(n,t_COL);
889
T = ZX_gcd_all(f, ZX_deriv(f), &V);
890
for (k = i = 1;; k++)
891
{
892
GEN W = ZX_gcd_all(T,V, &T); /* V and W are squarefree */
893
long dW = degpol(W), dV = degpol(V);
894
/* f = prod_i T_i^{e_i}
895
* W = prod_{i: e_i > k} T_i,
896
* V = prod_{i: e_i >= k} T_i,
897
* T = prod_{i: e_i > k} T_i^{e_i - k} */
898
if (!dW)
899
{
900
if (dV) { gel(P,i) = Q_primpart(V); e[i] = k; i++; }
901
break;
902
}
903
if (dW == dV)
904
{
905
GEN U;
906
while ( (U = ZX_divides(T, V)) ) { k++; T = U; }
907
}
908
else
909
{
910
gel(P,i) = Q_primpart(RgX_div(V,W));
911
e[i] = k; i++; V = W;
912
}
913
}
914
if (val) { gel(P,i) = pol_x(varn(f)); e[i] = val; i++;}
915
setlg(P,i);
916
setlg(e,i); *ex = e; return P;
917
}
918
919
static GEN
920
fact_from_DDF(GEN fa, GEN e, long n)
921
{
922
GEN v,w, y = cgetg(3, t_MAT);
923
long i,j,k, l = lg(fa);
924
925
v = cgetg(n+1,t_COL); gel(y,1) = v;
926
w = cgetg(n+1,t_COL); gel(y,2) = w;
927
for (k=i=1; i<l; i++)
928
{
929
GEN L = gel(fa,i), ex = utoipos(e[i]);
930
long J = lg(L);
931
for (j=1; j<J; j++,k++)
932
{
933
gel(v,k) = gcopy(gel(L,j));
934
gel(w,k) = ex;
935
}
936
}
937
return y;
938
}
939
940
/* Factor x in Z[t] */
941
static GEN
942
ZX_factor_i(GEN x)
943
{
944
GEN fa,ex,y;
945
long n,i,l;
946
947
if (!signe(x)) return prime_fact(x);
948
fa = ZX_squff(x, &ex);
949
l = lg(fa); n = 0;
950
for (i=1; i<l; i++)
951
{
952
gel(fa,i) = ZX_DDF(gel(fa,i));
953
n += lg(gel(fa,i))-1;
954
}
955
y = fact_from_DDF(fa,ex,n);
956
return sort_factor_pol(y, cmpii);
957
}
958
GEN
959
ZX_factor(GEN x)
960
{
961
pari_sp av = avma;
962
return gerepileupto(av, ZX_factor_i(x));
963
}
964
GEN
965
QX_factor(GEN x)
966
{
967
pari_sp av = avma;
968
return gerepileupto(av, ZX_factor_i(Q_primpart(x)));
969
}
970
971
long
972
ZX_is_irred(GEN x)
973
{
974
pari_sp av = avma;
975
long l = lg(x);
976
GEN y;
977
if (l <= 3) return 0; /* degree < 1 */
978
if (l == 4) return 1; /* degree 1 */
979
if (ZX_val(x)) return 0;
980
if (!ZX_is_squarefree(x)) return 0;
981
y = ZX_DDF(x); set_avma(av);
982
return (lg(y) == 2);
983
}
984
985
GEN
986
nfrootsQ(GEN x)
987
{
988
pari_sp av = avma;
989
GEN z;
990
long val;
991
992
if (typ(x)!=t_POL) pari_err_TYPE("nfrootsQ",x);
993
if (!signe(x)) pari_err_ROOTS0("nfrootsQ");
994
x = Q_primpart(x);
995
RgX_check_ZX(x,"nfrootsQ");
996
val = ZX_valrem(x, &x);
997
z = DDF_roots( ZX_radical(x) );
998
if (val) z = vec_append(z, gen_0);
999
return gerepileupto(av, sort(z));
1000
}
1001
1002
/************************************************************************
1003
* GCD OVER Z[X] / Q[X] *
1004
************************************************************************/
1005
int
1006
ZX_is_squarefree(GEN x)
1007
{
1008
pari_sp av = avma;
1009
GEN d;
1010
long m;
1011
if (lg(x) == 2) return 0;
1012
m = ZX_deflate_order(x);
1013
if (m > 1)
1014
{
1015
if (!signe(gel(x,2))) return 0;
1016
x = RgX_deflate(x, m);
1017
}
1018
d = ZX_gcd(x,ZX_deriv(x));
1019
return gc_bool(av, lg(d) == 3);
1020
}
1021
1022
static int
1023
ZX_gcd_filter(GEN *pt_A, GEN *pt_P)
1024
{
1025
GEN A = *pt_A, P = *pt_P;
1026
long i, j, l = lg(A), n = 1, d = degpol(gel(A,1));
1027
GEN B, Q;
1028
for (i=2; i<l; i++)
1029
{
1030
long di = degpol(gel(A,i));
1031
if (di==d) n++;
1032
else if (d > di)
1033
{ n=1; d = di; }
1034
}
1035
if (n == l-1)
1036
return 0;
1037
B = cgetg(n+1, t_VEC);
1038
Q = cgetg(n+1, typ(P));
1039
for (i=1, j=1; i<l; i++)
1040
{
1041
if (degpol(gel(A,i))==d)
1042
{
1043
gel(B,j) = gel(A,i);
1044
Q[j] = P[i];
1045
j++;
1046
}
1047
}
1048
*pt_A = B; *pt_P = Q; return 1;
1049
}
1050
1051
static GEN
1052
ZX_gcd_Flx(GEN a, GEN b, ulong g, ulong p)
1053
{
1054
GEN H = Flx_gcd(a, b, p);
1055
if (!g)
1056
return Flx_normalize(H, p);
1057
else
1058
{
1059
ulong t = Fl_mul(g, Fl_inv(Flx_lead(H), p), p);
1060
return Flx_Fl_mul(H, t, p);
1061
}
1062
}
1063
1064
static GEN
1065
ZX_gcd_slice(GEN A, GEN B, GEN g, GEN P, GEN *mod)
1066
{
1067
pari_sp av = avma;
1068
long i, n = lg(P)-1;
1069
GEN H, T;
1070
if (n == 1)
1071
{
1072
ulong p = uel(P,1), gp = g ? umodiu(g, p): 0;
1073
GEN a = ZX_to_Flx(A, p), b = ZX_to_Flx(B, p);
1074
GEN Hp = ZX_gcd_Flx(a, b, gp, p);
1075
H = gerepileupto(av, Flx_to_ZX(Hp));
1076
*mod = utoi(p);
1077
return H;
1078
}
1079
T = ZV_producttree(P);
1080
A = ZX_nv_mod_tree(A, P, T);
1081
B = ZX_nv_mod_tree(B, P, T);
1082
g = g ? Z_ZV_mod_tree(g, P, T): NULL;
1083
H = cgetg(n+1, t_VEC);
1084
for(i=1; i <= n; i++)
1085
{
1086
ulong p = P[i];
1087
GEN a = gel(A,i), b = gel(B,i);
1088
gel(H,i) = ZX_gcd_Flx(a, b, g? g[i]: 0, p);
1089
}
1090
if (ZX_gcd_filter(&H, &P))
1091
T = ZV_producttree(P);
1092
H = nxV_chinese_center_tree(H, P, T, ZV_chinesetree(P, T));
1093
*mod = gmael(T, lg(T)-1, 1);
1094
gerepileall(av, 2, &H, mod);
1095
return H;
1096
}
1097
1098
GEN
1099
ZX_gcd_worker(GEN P, GEN A, GEN B, GEN g)
1100
{
1101
GEN V = cgetg(3, t_VEC);
1102
gel(V,1) = ZX_gcd_slice(A, B, equali1(g)? NULL: g , P, &gel(V,2));
1103
return V;
1104
}
1105
1106
static GEN
1107
ZX_gcd_chinese(GEN A, GEN P, GEN *mod)
1108
{
1109
ZX_gcd_filter(&A, &P);
1110
return nxV_chinese_center(A, P, mod);
1111
}
1112
1113
GEN
1114
ZX_gcd_all(GEN A, GEN B, GEN *Anew)
1115
{
1116
pari_sp av = avma;
1117
long k, valH, valA, valB, vA = varn(A), dA = degpol(A), dB = degpol(B);
1118
GEN worker, c, cA, cB, g, Ag, Bg, H = NULL, mod = gen_1, R;
1119
GEN Ap, Bp, Hp;
1120
forprime_t S;
1121
ulong pp;
1122
if (dA < 0) { if (Anew) *Anew = pol_0(vA); return ZX_copy(B); }
1123
if (dB < 0) { if (Anew) *Anew = pol_1(vA); return ZX_copy(A); }
1124
A = Q_primitive_part(A, &cA);
1125
B = Q_primitive_part(B, &cB);
1126
valA = ZX_valrem(A, &A); dA -= valA;
1127
valB = ZX_valrem(B, &B); dB -= valB;
1128
valH = minss(valA, valB);
1129
valA -= valH; /* valuation(Anew) */
1130
c = (cA && cB)? gcdii(cA, cB): NULL; /* content(gcd) */
1131
if (!dA || !dB)
1132
{
1133
if (Anew) *Anew = RgX_shift_shallow(A, valA);
1134
return monomial(c? c: gen_1, valH, vA);
1135
}
1136
g = gcdii(leading_coeff(A), leading_coeff(B)); /* multiple of lead(gcd) */
1137
if (is_pm1(g)) {
1138
g = NULL;
1139
Ag = A;
1140
Bg = B;
1141
} else {
1142
Ag = ZX_Z_mul(A,g);
1143
Bg = ZX_Z_mul(B,g);
1144
}
1145
init_modular_big(&S);
1146
do {
1147
pp = u_forprime_next(&S);
1148
Ap = ZX_to_Flx(Ag, pp);
1149
Bp = ZX_to_Flx(Bg, pp);
1150
} while (degpol(Ap) != dA || degpol(Bp) != dB);
1151
if (degpol(Flx_gcd(Ap, Bp, pp)) == 0)
1152
{
1153
if (Anew) *Anew = RgX_shift_shallow(A, valA);
1154
return monomial(c? c: gen_1, valH, vA);
1155
}
1156
worker = snm_closure(is_entry("_ZX_gcd_worker"), mkvec3(A, B, g? g: gen_1));
1157
av = avma;
1158
for (k = 1; ;k *= 2)
1159
{
1160
gen_inccrt_i("ZX_gcd", worker, g, (k+1)>>1, 0, &S, &H, &mod, ZX_gcd_chinese, NULL);
1161
gerepileall(av, 2, &H, &mod);
1162
Hp = ZX_to_Flx(H, pp);
1163
if (lgpol(Flx_rem(Ap, Hp, pp)) || lgpol(Flx_rem(Bp, Hp, pp))) continue;
1164
if (!ZX_divides(Bg, H)) continue;
1165
R = ZX_divides(Ag, H);
1166
if (R) break;
1167
}
1168
/* lead(H) = g */
1169
if (g) H = Q_primpart(H);
1170
if (c) H = ZX_Z_mul(H,c);
1171
if (DEBUGLEVEL>5) err_printf("done\n");
1172
if (Anew) *Anew = RgX_shift_shallow(R, valA);
1173
return valH? RgX_shift_shallow(H, valH): H;
1174
}
1175
1176
#if 0
1177
/* ceil( || p ||_oo / lc(p) ) */
1178
static GEN
1179
maxnorm(GEN p)
1180
{
1181
long i, n = degpol(p), av = avma;
1182
GEN x, m = gen_0;
1183
1184
p += 2;
1185
for (i=0; i<n; i++)
1186
{
1187
x = gel(p,i);
1188
if (abscmpii(x,m) > 0) m = x;
1189
}
1190
m = divii(m, gel(p,n));
1191
return gerepileuptoint(av, addiu(absi_shallow(m),1));
1192
}
1193
#endif
1194
1195
GEN
1196
ZX_gcd(GEN A, GEN B)
1197
{
1198
pari_sp av = avma;
1199
return gerepilecopy(av, ZX_gcd_all(A,B,NULL));
1200
}
1201
1202
GEN
1203
ZX_radical(GEN A) { GEN B; (void)ZX_gcd_all(A,ZX_deriv(A),&B); return B; }
1204
1205
static GEN
1206
_gcd(GEN a, GEN b)
1207
{
1208
if (!a) a = gen_1;
1209
if (!b) b = gen_1;
1210
return Q_gcd(a,b);
1211
}
1212
/* A0 and B0 in Q[X] */
1213
GEN
1214
QX_gcd(GEN A0, GEN B0)
1215
{
1216
GEN a, b, D;
1217
pari_sp av = avma, av2;
1218
1219
D = ZX_gcd(Q_primitive_part(A0, &a), Q_primitive_part(B0, &b));
1220
av2 = avma; a = _gcd(a,b);
1221
if (isint1(a)) set_avma(av2); else D = ZX_Q_mul(D, a);
1222
return gerepileupto(av, D);
1223
}
1224
1225
/*****************************************************************************
1226
* Variants of the Bradford-Davenport algorithm: look for cyclotomic *
1227
* factors, and decide whether a ZX is cyclotomic or a product of cyclotomic *
1228
*****************************************************************************/
1229
/* f of degree 1, return a cyclotomic factor (Phi_1 or Phi_2) or NULL */
1230
static GEN
1231
BD_deg1(GEN f)
1232
{
1233
GEN a = gel(f,3), b = gel(f,2); /* f = ax + b */
1234
if (!absequalii(a,b)) return NULL;
1235
return polcyclo((signe(a) == signe(b))? 2: 1, varn(f));
1236
}
1237
1238
/* f a squarefree ZX; not divisible by any Phi_n, n even */
1239
static GEN
1240
BD_odd(GEN f)
1241
{
1242
while(degpol(f) > 1)
1243
{
1244
GEN f1 = ZX_graeffe(f); /* contain all cyclotomic divisors of f */
1245
if (ZX_equal(f1, f)) return f; /* product of cyclotomics */
1246
f = ZX_gcd(f, f1);
1247
}
1248
if (degpol(f) == 1) return BD_deg1(f);
1249
return NULL; /* no cyclotomic divisor */
1250
}
1251
1252
static GEN
1253
myconcat(GEN v, GEN x)
1254
{
1255
if (typ(x) != t_VEC) x = mkvec(x);
1256
if (!v) return x;
1257
return shallowconcat(v, x);
1258
}
1259
1260
/* Bradford-Davenport algorithm.
1261
* f a squarefree ZX of degree > 0, return NULL or a vector of coprime
1262
* cyclotomic factors of f [ possibly reducible ] */
1263
static GEN
1264
BD(GEN f)
1265
{
1266
GEN G = NULL, Gs = NULL, Gp = NULL, Gi = NULL;
1267
GEN fs2, fp, f2, f1, fe, fo, fe1, fo1;
1268
RgX_even_odd(f, &fe, &fo);
1269
fe1 = ZX_eval1(fe);
1270
fo1 = ZX_eval1(fo);
1271
if (absequalii(fe1, fo1)) /* f(1) = 0 or f(-1) = 0 */
1272
{
1273
long i, v = varn(f);
1274
if (!signe(fe1))
1275
G = mkvec2(polcyclo(1, v), polcyclo(2, v)); /* both 0 */
1276
else if (signe(fe1) == signe(fo1))
1277
G = mkvec(polcyclo(2, v)); /*f(-1) = 0*/
1278
else
1279
G = mkvec(polcyclo(1, v)); /*f(1) = 0*/
1280
for (i = lg(G)-1; i; i--) f = RgX_div(f, gel(G,i));
1281
}
1282
/* f no longer divisible by Phi_1 or Phi_2 */
1283
if (degpol(f) <= 1) return G;
1284
f1 = ZX_graeffe(f); /* has at most square factors */
1285
if (ZX_equal(f1, f)) return myconcat(G,f); /* f = product of Phi_n, n odd */
1286
1287
fs2 = ZX_gcd_all(f1, ZX_deriv(f1), &f2); /* fs2 squarefree */
1288
if (degpol(fs2))
1289
{ /* fs contains all Phi_n | f, 4 | n; and only those */
1290
/* In that case, Graeffe(Phi_n) = Phi_{n/2}^2, and Phi_n = Phi_{n/2}(x^2) */
1291
GEN fs = RgX_inflate(fs2, 2);
1292
(void)ZX_gcd_all(f, fs, &f); /* remove those Phi_n | f, 4 | n */
1293
Gs = BD(fs2);
1294
if (Gs)
1295
{
1296
long i;
1297
for (i = lg(Gs)-1; i; i--) gel(Gs,i) = RgX_inflate(gel(Gs,i), 2);
1298
/* prod Gs[i] is the product of all Phi_n | f, 4 | n */
1299
G = myconcat(G, Gs);
1300
}
1301
/* f2 = f1 / fs2 */
1302
f1 = RgX_div(f2, fs2); /* f1 / fs2^2 */
1303
}
1304
fp = ZX_gcd(f, f1); /* contains all Phi_n | f, n > 1 odd; and only those */
1305
if (degpol(fp))
1306
{
1307
Gp = BD_odd(fp);
1308
/* Gp is the product of all Phi_n | f, n odd */
1309
if (Gp) G = myconcat(G, Gp);
1310
f = RgX_div(f, fp);
1311
}
1312
if (degpol(f))
1313
{ /* contains all Phi_n originally dividing f, n = 2 mod 4, n > 2;
1314
* and only those
1315
* In that case, Graeffe(Phi_n) = Phi_{n/2}, and Phi_n = Phi_{n/2}(-x) */
1316
Gi = BD_odd(ZX_z_unscale(f, -1));
1317
if (Gi)
1318
{ /* N.B. Phi_2 does not divide f */
1319
Gi = ZX_z_unscale(Gi, -1);
1320
/* Gi is the product of all Phi_n | f, n = 2 mod 4 */
1321
G = myconcat(G, Gi);
1322
}
1323
}
1324
return G;
1325
}
1326
1327
/* Let f be a nonzero QX, return the (squarefree) product of cyclotomic
1328
* divisors of f */
1329
GEN
1330
polcyclofactors(GEN f)
1331
{
1332
pari_sp av = avma;
1333
if (typ(f) != t_POL || !signe(f)) pari_err_TYPE("polcyclofactors",f);
1334
(void)RgX_valrem(f, &f);
1335
f = Q_primpart(f);
1336
RgX_check_ZX(f,"polcyclofactors");
1337
if (degpol(f))
1338
{
1339
f = BD(ZX_radical(f));
1340
if (f) return gerepilecopy(av, f);
1341
}
1342
set_avma(av); return cgetg(1,t_VEC);
1343
}
1344
1345
/* return t*x mod T(x), T a monic ZX. Assume deg(t) < deg(T) */
1346
static GEN
1347
ZXQ_mul_by_X(GEN t, GEN T)
1348
{
1349
GEN lt;
1350
t = RgX_shift_shallow(t, 1);
1351
if (degpol(t) < degpol(T)) return t;
1352
lt = leading_coeff(t);
1353
if (is_pm1(lt)) return signe(lt) > 0 ? ZX_sub(t, T): ZX_add(t, T);
1354
return ZX_sub(t, ZX_Z_mul(T, leading_coeff(t)));
1355
}
1356
/* f a product of Phi_n, all n odd; deg f > 1. Is it irreducible ? */
1357
static long
1358
BD_odd_iscyclo(GEN f)
1359
{
1360
pari_sp av;
1361
long d, e, n, bound;
1362
GEN t;
1363
f = ZX_deflate_max(f, &e);
1364
av = avma;
1365
/* The original f is cyclotomic (= Phi_{ne}) iff the present one is Phi_n,
1366
* where all prime dividing e also divide n. If current f is Phi_n,
1367
* then n is odd and squarefree */
1368
d = degpol(f); /* = phi(n) */
1369
/* Let e > 0, g multiplicative such that
1370
g(p) = p / (p-1)^(1+e) < 1 iff p < (p-1)^(1+e)
1371
For all squarefree odd n, we have g(n) < C, hence n < C phi(n)^(1+e), where
1372
C = \prod_{p odd | p > (p-1)^(1+e)} g(p)
1373
For e = 1/10, we obtain p = 3, 5 and C < 1.523
1374
For e = 1/100, we obtain p = 3, 5, ..., 29 and C < 2.573
1375
In fact, for n <= 10^7 odd & squarefree, we have n < 2.92 * phi(n)
1376
By the above, n<10^7 covers all d <= (10^7/2.573)^(1/(1+1/100)) < 3344391.
1377
*/
1378
if (d <= 3344391)
1379
bound = (long)(2.92 * d);
1380
else
1381
bound = (long)(2.573 * pow(d,1.01));
1382
/* IF f = Phi_n, n squarefree odd, then n <= bound */
1383
t = pol_xn(d-1, varn(f));
1384
for (n = d; n <= bound; n++)
1385
{
1386
t = ZXQ_mul_by_X(t, f);
1387
/* t = (X mod f(X))^d */
1388
if (degpol(t) == 0) break;
1389
if (gc_needed(av,1))
1390
{
1391
if(DEBUGMEM>1) pari_warn(warnmem,"BD_odd_iscyclo");
1392
t = gerepilecopy(av, t);
1393
}
1394
}
1395
if (n > bound || eulerphiu(n) != (ulong)d) return 0;
1396
1397
if (e > 1) return (u_ppo(e, n) == 1)? e * n : 0;
1398
return n;
1399
}
1400
1401
/* Checks if f, monic squarefree ZX with |constant coeff| = 1, is a cyclotomic
1402
* polynomial. Returns n if f = Phi_n, and 0 otherwise */
1403
static long
1404
BD_iscyclo(GEN f)
1405
{
1406
pari_sp av = avma;
1407
GEN f2, fn, f1;
1408
1409
if (degpol(f) == 1) return isint1(gel(f,2))? 2: 1;
1410
f1 = ZX_graeffe(f);
1411
/* f = product of Phi_n, n odd */
1412
if (ZX_equal(f, f1)) return gc_long(av, BD_odd_iscyclo(f));
1413
1414
fn = ZX_z_unscale(f, -1); /* f(-x) */
1415
/* f = product of Phi_n, n = 2 mod 4 */
1416
if (ZX_equal(f1, fn)) return gc_long(av, 2*BD_odd_iscyclo(fn));
1417
1418
if (issquareall(f1, &f2))
1419
{
1420
GEN lt = leading_coeff(f2);
1421
long c;
1422
if (signe(lt) < 0) f2 = ZX_neg(f2);
1423
c = BD_iscyclo(f2);
1424
return odd(c)? 0: 2*c;
1425
}
1426
return gc_long(av, 0);
1427
}
1428
long
1429
poliscyclo(GEN f)
1430
{
1431
long d;
1432
if (typ(f) != t_POL) pari_err_TYPE("poliscyclo", f);
1433
d = degpol(f);
1434
if (d <= 0 || !RgX_is_ZX(f)) return 0;
1435
if (!equali1(gel(f,d+2)) || !is_pm1(gel(f,2))) return 0;
1436
if (d == 1) return signe(gel(f,2)) > 0? 2: 1;
1437
return ZX_is_squarefree(f)? BD_iscyclo(f): 0;
1438
}
1439
1440
long
1441
poliscycloprod(GEN f)
1442
{
1443
pari_sp av = avma;
1444
long i, d = degpol(f);
1445
if (typ(f) != t_POL) pari_err_TYPE("poliscycloprod",f);
1446
if (!RgX_is_ZX(f)) return 0;
1447
if (!ZX_is_monic(f) || !is_pm1(constant_coeff(f))) return 0;
1448
if (d < 2) return (d == 1);
1449
if ( degpol(ZX_gcd_all(f, ZX_deriv(f), &f)) )
1450
{
1451
d = degpol(f);
1452
if (d == 1) return 1;
1453
}
1454
f = BD(f); if (!f) return 0;
1455
for (i = lg(f)-1; i; i--) d -= degpol(gel(f,i));
1456
return gc_long(av, d == 0);
1457
}
1458
1459