Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

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

28485 views
License: GPL3
ubuntu2004
1
/* Copyright (C) 2007 The PARI group.
2
3
This file is part of the PARI/GP package.
4
5
PARI/GP is free software; you can redistribute it and/or modify it under the
6
terms of the GNU General Public License as published by the Free Software
7
Foundation; either version 2 of the License, or (at your option) any later
8
version. It is distributed in the hope that it will be useful, but WITHOUT
9
ANY WARRANTY WHATSOEVER.
10
11
Check the License for details. You should have received a copy of it, along
12
with the package; see the file 'COPYING'. If not, write to the Free Software
13
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14
15
#include "pari.h"
16
#include "paripriv.h"
17
18
/*******************************************************************/
19
/* */
20
/* ZX */
21
/* */
22
/*******************************************************************/
23
void
24
RgX_check_QX(GEN x, const char *s)
25
{ if (!RgX_is_QX(x)) pari_err_TYPE(stack_strcat(s," [not in Q[X]]"), x); }
26
void
27
RgX_check_ZX(GEN x, const char *s)
28
{ if (!RgX_is_ZX(x)) pari_err_TYPE(stack_strcat(s," [not in Z[X]]"), x); }
29
long
30
ZX_max_lg(GEN x)
31
{
32
long i, prec = 0, lx = lg(x);
33
34
for (i=2; i<lx; i++) { long l = lgefint(gel(x,i)); if (l > prec) prec = l; }
35
return prec;
36
}
37
38
GEN
39
ZX_add(GEN x, GEN y)
40
{
41
long lx,ly,i;
42
GEN z;
43
lx = lg(x); ly = lg(y); if (lx < ly) swapspec(x,y, lx,ly);
44
z = cgetg(lx,t_POL); z[1] = x[1];
45
for (i=2; i<ly; i++) gel(z,i) = addii(gel(x,i),gel(y,i));
46
for ( ; i<lx; i++) gel(z,i) = icopy(gel(x,i));
47
if (lx == ly) z = ZX_renormalize(z, lx);
48
if (!lgpol(z)) { set_avma((pari_sp)(z + lx)); return pol_0(varn(x)); }
49
return z;
50
}
51
52
GEN
53
ZX_sub(GEN x,GEN y)
54
{
55
long i, lx = lg(x), ly = lg(y);
56
GEN z;
57
if (lx >= ly)
58
{
59
z = cgetg(lx,t_POL); z[1] = x[1];
60
for (i=2; i<ly; i++) gel(z,i) = subii(gel(x,i),gel(y,i));
61
if (lx == ly)
62
{
63
z = ZX_renormalize(z, lx);
64
if (!lgpol(z)) { set_avma((pari_sp)(z + lx)); z = pol_0(varn(x)); }
65
}
66
else
67
for ( ; i<lx; i++) gel(z,i) = icopy(gel(x,i));
68
}
69
else
70
{
71
z = cgetg(ly,t_POL); z[1] = y[1];
72
for (i=2; i<lx; i++) gel(z,i) = subii(gel(x,i),gel(y,i));
73
for ( ; i<ly; i++) gel(z,i) = negi(gel(y,i));
74
}
75
return z;
76
}
77
78
GEN
79
ZX_neg(GEN x)
80
{
81
long i, l = lg(x);
82
GEN y = cgetg(l,t_POL);
83
y[1] = x[1]; for(i=2; i<l; i++) gel(y,i) = negi(gel(x,i));
84
return y;
85
}
86
GEN
87
ZX_copy(GEN x)
88
{
89
long i, l = lg(x);
90
GEN y = cgetg(l, t_POL);
91
y[1] = x[1];
92
for (i=2; i<l; i++)
93
{
94
GEN c = gel(x,i);
95
gel(y,i) = lgefint(c) == 2? gen_0: icopy(c);
96
}
97
return y;
98
}
99
100
GEN
101
scalar_ZX(GEN x, long v)
102
{
103
GEN z;
104
if (!signe(x)) return pol_0(v);
105
z = cgetg(3, t_POL);
106
z[1] = evalsigne(1) | evalvarn(v);
107
gel(z,2) = icopy(x); return z;
108
}
109
110
GEN
111
scalar_ZX_shallow(GEN x, long v)
112
{
113
GEN z;
114
if (!signe(x)) return pol_0(v);
115
z = cgetg(3, t_POL);
116
z[1] = evalsigne(1) | evalvarn(v);
117
gel(z,2) = x; return z;
118
}
119
120
GEN
121
ZX_Z_add(GEN y, GEN x)
122
{
123
long lz, i;
124
GEN z = cgetg_copy(y, &lz);
125
if (lz == 2) { set_avma((pari_sp)(z + 2)); return scalar_ZX(x,varn(y)); }
126
z[1] = y[1];
127
gel(z,2) = addii(gel(y,2),x);
128
for(i=3; i<lz; i++) gel(z,i) = icopy(gel(y,i));
129
if (lz==3) z = ZX_renormalize(z,lz);
130
return z;
131
}
132
GEN
133
ZX_Z_add_shallow(GEN y, GEN x)
134
{
135
long lz, i;
136
GEN z = cgetg_copy(y, &lz);
137
if (lz == 2) { set_avma((pari_sp)(z + 2)); return scalar_ZX_shallow(x,varn(y)); }
138
z[1] = y[1];
139
gel(z,2) = addii(gel(y,2),x);
140
for(i=3; i<lz; i++) gel(z,i) = gel(y,i);
141
if (lz==3) z = ZX_renormalize(z,lz);
142
return z;
143
}
144
145
GEN
146
ZX_Z_sub(GEN y, GEN x)
147
{
148
long lz, i;
149
GEN z = cgetg_copy(y, &lz);
150
if (lz == 2)
151
{ /* scalarpol(negi(x), v) */
152
long v = varn(y);
153
set_avma((pari_sp)(z + 2));
154
if (!signe(x)) return pol_0(v);
155
z = cgetg(3,t_POL);
156
z[1] = evalvarn(v) | evalsigne(1);
157
gel(z,2) = negi(x); return z;
158
}
159
z[1] = y[1];
160
gel(z,2) = subii(gel(y,2),x);
161
for(i=3; i<lz; i++) gel(z,i) = icopy(gel(y,i));
162
if (lz==3) z = ZX_renormalize(z,lz);
163
return z;
164
}
165
166
GEN
167
Z_ZX_sub(GEN x, GEN y)
168
{
169
long lz, i;
170
GEN z = cgetg_copy(y, &lz);
171
if (lz == 2) { set_avma((pari_sp)(z + 2)); return scalar_ZX(x,varn(y)); }
172
z[1] = y[1];
173
gel(z,2) = subii(x, gel(y,2));
174
for(i=3; i<lz; i++) gel(z,i) = negi(gel(y,i));
175
if (lz==3) z = ZX_renormalize(z,lz);
176
return z;
177
}
178
179
GEN
180
ZX_Z_divexact(GEN y,GEN x)
181
{
182
long i, l = lg(y);
183
GEN z = cgetg(l,t_POL); z[1] = y[1];
184
for(i=2; i<l; i++) gel(z,i) = diviiexact(gel(y,i),x);
185
return z;
186
}
187
188
GEN
189
ZX_divuexact(GEN y, ulong x)
190
{
191
long i, l = lg(y);
192
GEN z = cgetg(l,t_POL); z[1] = y[1];
193
for(i=2; i<l; i++) gel(z,i) = diviuexact(gel(y,i),x);
194
return z;
195
}
196
197
GEN
198
zx_z_divexact(GEN y, long x)
199
{
200
long i, l = lg(y);
201
GEN z = cgetg(l,t_VECSMALL); z[1] = y[1];
202
for (i=2; i<l; i++) z[i] = y[i]/x;
203
return z;
204
}
205
206
GEN
207
ZX_Z_mul(GEN y,GEN x)
208
{
209
GEN z;
210
long i, l;
211
if (!signe(x)) return pol_0(varn(y));
212
l = lg(y); z = cgetg(l,t_POL); z[1] = y[1];
213
for(i=2; i<l; i++) gel(z,i) = mulii(gel(y,i),x);
214
return z;
215
}
216
217
GEN
218
ZX_mulu(GEN y, ulong x)
219
{
220
GEN z;
221
long i, l;
222
if (!x) return pol_0(varn(y));
223
l = lg(y); z = cgetg(l,t_POL); z[1] = y[1];
224
for(i=2; i<l; i++) gel(z,i) = mului(x,gel(y,i));
225
return z;
226
}
227
228
GEN
229
ZX_shifti(GEN y, long n)
230
{
231
GEN z;
232
long i, l;
233
l = lg(y); z = cgetg(l,t_POL); z[1] = y[1];
234
for(i=2; i<l; i++) gel(z,i) = shifti(gel(y,i),n);
235
return ZX_renormalize(z,l);
236
}
237
238
GEN
239
ZX_remi2n(GEN y, long n)
240
{
241
GEN z;
242
long i, l;
243
l = lg(y); z = cgetg(l,t_POL); z[1] = y[1];
244
for(i=2; i<l; i++) gel(z,i) = remi2n(gel(y,i),n);
245
return ZX_renormalize(z,l);
246
}
247
248
GEN
249
ZXT_remi2n(GEN z, long n)
250
{
251
if (typ(z) == t_POL)
252
return ZX_remi2n(z, n);
253
else
254
{
255
long i,l = lg(z);
256
GEN x = cgetg(l, t_VEC);
257
for (i=1; i<l; i++) gel(x,i) = ZXT_remi2n(gel(z,i), n);
258
return x;
259
}
260
}
261
262
GEN
263
zx_to_ZX(GEN z)
264
{
265
long i, l = lg(z);
266
GEN x = cgetg(l,t_POL);
267
for (i=2; i<l; i++) gel(x,i) = stoi(z[i]);
268
x[1] = evalsigne(l-2!=0)| z[1]; return x;
269
}
270
271
GEN
272
ZX_deriv(GEN x)
273
{
274
long i,lx = lg(x)-1;
275
GEN y;
276
277
if (lx<3) return pol_0(varn(x));
278
y = cgetg(lx,t_POL);
279
for (i=2; i<lx ; i++) gel(y,i) = mului(i-1,gel(x,i+1));
280
y[1] = x[1]; return y;
281
}
282
283
int
284
ZX_equal(GEN V, GEN W)
285
{
286
long i, l = lg(V);
287
if (lg(W) != l) return 0;
288
for (i = 2; i < l; i++)
289
if (!equalii(gel(V,i), gel(W,i))) return 0;
290
return 1;
291
}
292
293
static long
294
ZX_valspec(GEN x, long nx)
295
{
296
long vx;
297
for (vx = 0; vx<nx ; vx++)
298
if (signe(gel(x,vx))) break;
299
return vx;
300
}
301
302
long
303
ZX_val(GEN x)
304
{
305
long vx;
306
if (!signe(x)) return LONG_MAX;
307
for (vx = 0;; vx++)
308
if (signe(gel(x,2+vx))) break;
309
return vx;
310
}
311
long
312
ZX_valrem(GEN x, GEN *Z)
313
{
314
long vx;
315
if (!signe(x)) { *Z = pol_0(varn(x)); return LONG_MAX; }
316
for (vx = 0;; vx++)
317
if (signe(gel(x,2+vx))) break;
318
*Z = RgX_shift_shallow(x, -vx);
319
return vx;
320
}
321
322
GEN
323
ZX_div_by_X_1(GEN a, GEN *r)
324
{
325
long l = lg(a), i;
326
GEN a0, z0, z = cgetg(l-1, t_POL);
327
z[1] = a[1];
328
a0 = a + l-1;
329
z0 = z + l-2; *z0 = *a0--;
330
for (i=l-3; i>1; i--) /* z[i] = a[i+1] + z[i+1] */
331
{
332
GEN t = addii(gel(a0--,0), gel(z0--,0));
333
gel(z0,0) = t;
334
}
335
if (r) *r = addii(gel(a0,0), gel(z0,0));
336
return z;
337
}
338
339
/* return P(X + c) using destructive Horner, optimize for c = 1,-1 */
340
static GEN
341
ZX_translate_basecase(GEN P, GEN c)
342
{
343
pari_sp av = avma;
344
GEN Q, R;
345
long i, k, n;
346
347
if (!signe(P) || !signe(c)) return ZX_copy(P);
348
Q = leafcopy(P);
349
R = Q+2; n = degpol(P);
350
if (equali1(c))
351
{
352
for (i=1; i<=n; i++)
353
{
354
for (k=n-i; k<n; k++) gel(R,k) = addii(gel(R,k), gel(R,k+1));
355
if (gc_needed(av,2))
356
{
357
if(DEBUGMEM>1) pari_warn(warnmem,"ZX_translate(1), i = %ld/%ld", i,n);
358
Q = gerepilecopy(av, Q); R = Q+2;
359
}
360
}
361
}
362
else if (equalim1(c))
363
{
364
for (i=1; i<=n; i++)
365
{
366
for (k=n-i; k<n; k++) gel(R,k) = subii(gel(R,k), gel(R,k+1));
367
if (gc_needed(av,2))
368
{
369
if(DEBUGMEM>1) pari_warn(warnmem,"ZX_translate(-1), i = %ld/%ld", i,n);
370
Q = gerepilecopy(av, Q); R = Q+2;
371
}
372
}
373
}
374
else
375
{
376
for (i=1; i<=n; i++)
377
{
378
for (k=n-i; k<n; k++) gel(R,k) = addmulii_inplace(gel(R,k), c, gel(R,k+1));
379
if (gc_needed(av,2))
380
{
381
if(DEBUGMEM>1) pari_warn(warnmem,"ZX_translate, i = %ld/%ld", i,n);
382
Q = gerepilecopy(av, Q); R = Q+2;
383
}
384
}
385
}
386
return gerepilecopy(av, Q);
387
}
388
389
static GEN
390
Z_Xpm1_powu(long n, long s, long v)
391
{
392
long d, k;
393
GEN C;
394
if (!n) return pol_1(v);
395
d = (n + 1) >> 1;
396
C = cgetg(n+3, t_POL);
397
C[1] = evalsigne(1)| evalvarn(v);
398
gel(C,2) = gen_1;
399
gel(C,3) = utoipos(n);
400
for (k=2; k <= d; k++)
401
gel(C,k+2) = diviuexact(mului(n-k+1, gel(C,k+1)), k);
402
if (s < 0)
403
for (k = odd(n)? 0: 1; k <= d; k += 2)
404
togglesign_safe(&gel(C,k+2));
405
if (s > 0 || !odd(n))
406
for (k = d+1; k <= n; k++) gel(C,k+2) = gel(C,n-k+2);
407
else
408
for (k = d+1; k <= n; k++) gel(C,k+2) = negi(gel(C,n-k+2));
409
return C;
410
}
411
/* return (x+u)^n */
412
static GEN
413
Z_XpN_powu(GEN u, long n, long v)
414
{
415
pari_sp av;
416
long k;
417
GEN B, C, V;
418
if (!n) return pol_1(v);
419
if (is_pm1(u))
420
return Z_Xpm1_powu(n, signe(u), v);
421
av = avma;
422
V = gpowers(u, n);
423
B = vecbinomial(n);
424
C = cgetg(n+3, t_POL);
425
C[1] = evalsigne(1)| evalvarn(v);
426
for (k=1; k <= n+1; k++)
427
gel(C,k+1) = mulii(gel(V,n+2-k), gel(B,k));
428
return gerepileupto(av, C);
429
}
430
431
GEN
432
ZX_translate(GEN P, GEN c)
433
{
434
pari_sp av = avma;
435
long n = degpol(P);
436
if (n < 220)
437
return ZX_translate_basecase(P, c);
438
else
439
{
440
long d = n >> 1;
441
GEN Q = ZX_translate(RgX_shift_shallow(P, -d), c);
442
GEN R = ZX_translate(RgXn_red_shallow(P, d), c);
443
GEN S = Z_XpN_powu(c, d, varn(P));
444
return gerepileupto(av, ZX_add(ZX_mul(Q, S), R));
445
}
446
}
447
448
GEN
449
ZX_Z_eval(GEN x, GEN y)
450
{
451
long i = lg(x)-1, j;
452
pari_sp av = avma;
453
GEN t, r;
454
455
if (i<=2) return (i==2)? icopy(gel(x,2)): gen_0;
456
if (!signe(y)) return icopy(gel(x,2));
457
458
t = gel(x,i); i--;
459
#if 0 /* standard Horner's rule */
460
for ( ; i>=2; i--)
461
t = addii(mulii(t,y),gel(x,i));
462
#endif
463
/* specific attention to sparse polynomials */
464
for ( ; i>=2; i = j-1)
465
{
466
for (j = i; !signe(gel(x,j)); j--)
467
if (j==2)
468
{
469
if (i != j) y = powiu(y, i-j+1);
470
return gerepileuptoint(av, mulii(t,y));
471
}
472
r = (i==j)? y: powiu(y, i-j+1);
473
t = addii(mulii(t,r), gel(x,j));
474
if (gc_needed(av,2))
475
{
476
if (DEBUGMEM>1) pari_warn(warnmem,"ZX_Z_eval: i = %ld",i);
477
t = gerepileuptoint(av, t);
478
}
479
}
480
return gerepileuptoint(av, t);
481
}
482
483
/* Return 2^(n degpol(P)) P(x >> n) */
484
GEN
485
ZX_rescale2n(GEN P, long n)
486
{
487
long i, l = lg(P), ni = n;
488
GEN Q;
489
if (l==2) return pol_0(varn(P));
490
Q = cgetg(l,t_POL);
491
gel(Q,l-1) = icopy(gel(P,l-1));
492
for (i=l-2; i>=2; i--)
493
{
494
gel(Q,i) = shifti(gel(P,i), ni);
495
ni += n;
496
}
497
Q[1] = P[1]; return Q;
498
}
499
500
/* Return h^deg(P) P(x / h), not memory clean. h integer, P ZX */
501
GEN
502
ZX_rescale(GEN P, GEN h)
503
{
504
long l = lg(P);
505
GEN Q = cgetg(l,t_POL);
506
if (l != 2)
507
{
508
long i = l-1;
509
GEN hi = h;
510
gel(Q,i) = gel(P,i);
511
if (l != 3) { i--; gel(Q,i) = mulii(gel(P,i), h); }
512
for (i--; i>=2; i--) { hi = mulii(hi,h); gel(Q,i) = mulii(gel(P,i), hi); }
513
}
514
Q[1] = P[1]; return Q;
515
}
516
/* Return h^(deg(P)-1) P(x / h), P!=0, h=lt(P), memory unclean; monic result */
517
GEN
518
ZX_rescale_lt(GEN P)
519
{
520
long l = lg(P);
521
GEN Q = cgetg(l,t_POL);
522
gel(Q,l-1) = gen_1;
523
if (l != 3)
524
{
525
long i = l-1;
526
GEN h = gel(P,i), hi = h;
527
i--; gel(Q,i) = gel(P,i);
528
if (l != 4) { i--; gel(Q,i) = mulii(gel(P,i), h); }
529
for (i--; i>=2; i--) { hi = mulii(hi,h); gel(Q,i) = mulii(gel(P,i), hi); }
530
}
531
Q[1] = P[1]; return Q;
532
}
533
534
/*Eval x in 2^(k*BIL) in linear time*/
535
static GEN
536
ZX_eval2BILspec(GEN x, long k, long nx)
537
{
538
pari_sp av = avma;
539
long i,j, lz = k*nx, ki;
540
GEN pz = cgetipos(2+lz);
541
GEN nz = cgetipos(2+lz);
542
for(i=0; i < lz; i++)
543
{
544
*int_W(pz,i) = 0UL;
545
*int_W(nz,i) = 0UL;
546
}
547
for(i=0, ki=0; i<nx; i++, ki+=k)
548
{
549
GEN c = gel(x,i);
550
long lc = lgefint(c)-2;
551
if (signe(c)==0) continue;
552
if (signe(c) > 0)
553
for (j=0; j<lc; j++) *int_W(pz,j+ki) = *int_W(c,j);
554
else
555
for (j=0; j<lc; j++) *int_W(nz,j+ki) = *int_W(c,j);
556
}
557
pz = int_normalize(pz,0);
558
nz = int_normalize(nz,0); return gerepileuptoint(av, subii(pz,nz));
559
}
560
561
static long
562
ZX_expispec(GEN x, long nx)
563
{
564
long i, m = 0;
565
for(i = 0; i < nx; i++)
566
{
567
long e = expi(gel(x,i));
568
if (e > m) m = e;
569
}
570
return m;
571
}
572
573
static GEN
574
Z_mod2BIL_ZX(GEN x, long bs, long d, long vx)
575
{
576
long i, offset, lm = lgefint(x)-2, l = d+vx+3, sx = signe(x);
577
GEN s1 = int2n(bs*BITS_IN_LONG), pol = cgetg(l, t_POL);
578
int carry = 0;
579
pol[1] = evalsigne(1);
580
for (i=0; i<vx; i++) gel(pol,i+2) = gen_0;
581
for (offset=0; i <= d+vx; i++, offset += bs)
582
{
583
pari_sp av = avma;
584
long lz = minss(bs, lm-offset);
585
GEN z = lz > 0 ?adduispec_offset(carry, x, offset, lz): utoi(carry);
586
if (lgefint(z) == 3+bs) { carry = 1; z = gen_0;}
587
else
588
{
589
carry = (lgefint(z) == 2+bs && (HIGHBIT & *int_W(z,bs-1)));
590
if (carry)
591
z = gerepileuptoint(av, (sx==-1)? subii(s1,z): subii(z,s1));
592
else if (sx==-1) togglesign(z);
593
}
594
gel(pol,i+2) = z;
595
}
596
return ZX_renormalize(pol,l);
597
}
598
599
static GEN
600
ZX_sqrspec_sqri(GEN x, long nx, long ex, long v)
601
{
602
long e = 2*ex + expu(nx) + 3;
603
long N = divsBIL(e)+1;
604
GEN z = sqri(ZX_eval2BILspec(x,N,nx));
605
return Z_mod2BIL_ZX(z, N, nx*2-2, v);
606
}
607
608
static GEN
609
ZX_mulspec_mulii(GEN x, GEN y, long nx, long ny, long ex, long ey, long v)
610
{
611
long e = ex + ey + expu(minss(nx,ny)) + 3;
612
long N = divsBIL(e)+1;
613
GEN z = mulii(ZX_eval2BILspec(x,N,nx), ZX_eval2BILspec(y,N,ny));
614
return Z_mod2BIL_ZX(z, N, nx+ny-2, v);
615
}
616
617
INLINE GEN
618
ZX_sqrspec_basecase_limb(GEN x, long a, long i)
619
{
620
pari_sp av = avma;
621
GEN s = gen_0;
622
long j, l = (i+1)>>1;
623
for (j=a; j<l; j++)
624
{
625
GEN xj = gel(x,j), xx = gel(x,i-j);
626
if (signe(xj) && signe(xx))
627
s = addii(s, mulii(xj, xx));
628
}
629
s = shifti(s,1);
630
if ((i&1) == 0)
631
{
632
GEN t = gel(x, i>>1);
633
if (signe(t))
634
s = addii(s, sqri(t));
635
}
636
return gerepileuptoint(av,s);
637
}
638
639
static GEN
640
ZX_sqrspec_basecase(GEN x, long nx, long v)
641
{
642
long i, lz, nz;
643
GEN z;
644
645
lz = (nx << 1) + 1; nz = lz-2;
646
lz += v;
647
z = cgetg(lz,t_POL); z[1] = evalsigne(1); z += 2;
648
for (i=0; i<v; i++) gel(z++, 0) = gen_0;
649
for (i=0; i<nx; i++)
650
gel(z,i) = ZX_sqrspec_basecase_limb(x, 0, i);
651
for ( ; i<nz; i++) gel(z,i) = ZX_sqrspec_basecase_limb(x, i-nx+1, i);
652
z -= v+2; return z;
653
}
654
655
static GEN
656
Z_sqrshiftspec_ZX(GEN x, long vx)
657
{
658
long i, nz = 2*vx+1;
659
GEN z = cgetg(2+nz, t_POL);
660
z[1] = evalsigne(1);
661
for(i=2;i<nz+1;i++) gel(z,i) = gen_0;
662
gel(z,nz+1) = sqri(x);
663
return z;
664
}
665
666
static GEN
667
Z_ZX_mulshiftspec(GEN x, GEN y, long ny, long vz)
668
{
669
long i, nz = vz+ny;
670
GEN z = cgetg(2+nz, t_POL);
671
z[1] = evalsigne(1);
672
for (i=0; i<vz; i++) gel(z,i+2) = gen_0;
673
for (i=0; i<ny; i++) gel(z,i+vz+2) = mulii(x, gel(y,i));
674
return z;
675
}
676
677
GEN
678
ZX_sqrspec(GEN x, long nx)
679
{
680
#ifdef PARI_KERNEL_GMP
681
const long low[]={ 17, 32, 96, 112, 160, 128, 128, 160, 160, 160, 160, 160, 176, 192, 192, 192, 192, 192, 224, 224, 224, 240, 240, 240, 272, 288, 288, 240, 288, 304, 304, 304, 304, 304, 304, 352, 352, 368, 352, 352, 352, 368, 368, 432, 432, 496, 432, 496, 496};
682
const long high[]={ 102860, 70254, 52783, 27086, 24623, 18500, 15289, 13899, 12635, 11487, 10442, 9493, 8630, 7845, 7132, 7132, 6484, 6484, 5894, 5894, 4428, 4428, 3660, 4428, 3660, 3660, 2749, 2499, 2272, 2066, 1282, 1282, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 963, 963, 724, 658, 658, 658, 528, 528, 528, 528};
683
#else
684
const long low[]={ 17, 17, 32, 32, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 112, 112, 128, 112, 112, 112, 112, 112, 128, 128, 160, 160, 112, 128, 128, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 176, 160, 160, 176, 160, 160, 176, 176, 208, 176, 176, 176, 192, 192, 176, 176, 224, 176, 224, 224, 176, 224, 224, 224, 176, 176, 176, 176, 176, 176, 176, 176, 224, 176, 176, 224, 224, 224, 224, 224, 224, 224, 240, 288, 240, 288, 288, 240, 288, 288, 240, 240, 304, 304};
685
const long high[]={ 165657, 85008, 52783, 43622, 32774, 27086, 22385, 15289, 13899, 12635, 11487, 10442, 9493, 7845, 6484, 6484, 5894, 5894, 4871, 4871, 4428, 4026, 3660, 3660, 3660, 3327, 3327, 3024, 2749, 2749, 2272, 2749, 2499, 2499, 2272, 1878, 1878, 1878, 1707, 1552, 1552, 1552, 1552, 1552, 1411, 1411, 1411, 1282, 1282, 1282, 1282, 1282, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1060, 1060, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 876, 876, 876, 876, 796, 658, 724, 658, 724, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 336, 658, 658, 592, 336, 336};
686
#endif
687
const long nblow = numberof(low);
688
pari_sp av;
689
long ex, vx;
690
GEN z;
691
if (!nx) return pol_0(0);
692
vx = ZX_valspec(x,nx); nx-=vx; x+=vx;
693
if (nx==1) return Z_sqrshiftspec_ZX(gel(x, 0), vx);
694
av = avma;
695
ex = ZX_expispec(x,nx);
696
if (nx-2 < nblow && low[nx-2]<=ex && ex<=high[nx-2])
697
z = ZX_sqrspec_basecase(x, nx, 2*vx);
698
else
699
z = ZX_sqrspec_sqri(x, nx, ex, 2*vx);
700
return gerepileupto(av, z);
701
}
702
703
GEN
704
ZX_sqr(GEN x)
705
{
706
GEN z = ZX_sqrspec(x+2, lgpol(x));
707
z[1] = x[1];
708
return z;
709
}
710
711
GEN
712
ZX_mulspec(GEN x, GEN y, long nx, long ny)
713
{
714
pari_sp av;
715
long ex, ey, vx, vy, v;
716
if (!nx || !ny) return pol_0(0);
717
vx = ZX_valspec(x,nx); nx-=vx; x += vx;
718
vy = ZX_valspec(y,ny); ny-=vy; y += vy;
719
v = vx + vy;
720
if (nx==1) return Z_ZX_mulshiftspec(gel(x,0), y, ny, v);
721
if (ny==1) return Z_ZX_mulshiftspec(gel(y,0), x, nx, v);
722
if (nx == 2 && ny == 2)
723
{
724
GEN a0 = gel(x,0), a1 = gel(x,1), A0, A1, A2;
725
GEN b0 = gel(y,0), b1 = gel(y,1), z = cgetg(5 + v, t_POL);
726
long i;
727
z[1] = evalvarn(0) | evalsigne(1);
728
A0 = mulii(a0, b0);
729
A2 = mulii(a1, b1); av = avma;
730
A1 = gerepileuptoint(av, subii(addii(A0,A2),
731
mulii(subii(a1,a0), subii(b1,b0))));
732
i = 4 + v;
733
gel(z,i--) = A2;
734
gel(z,i--) = A1;
735
gel(z,i--) = A0; while (i > 1) gel(z, i--) = gen_0;
736
return z;
737
}
738
#if 0
739
/* generically slower even when degrees differ a lot; sometimes about twice
740
* faster when bitsize is moderate */
741
if (DEBUGVAR)
742
return RgX_mulspec(x - vx, y - vy, nx + vx, ny + vy);
743
#endif
744
av = avma;
745
ex = ZX_expispec(x, nx);
746
ey = ZX_expispec(y, ny);
747
return gerepileupto(av, ZX_mulspec_mulii(x,y,nx,ny,ex,ey,v));
748
}
749
GEN
750
ZX_mul(GEN x, GEN y)
751
{
752
GEN z;
753
if (x == y) return ZX_sqr(x);
754
z = ZX_mulspec(x+2,y+2,lgpol(x),lgpol(y));
755
z[1] = x[1];
756
if (!signe(y)) z[1] &= VARNBITS;
757
return z;
758
}
759
760
/* x,y two ZX in the same variable; assume y is monic */
761
GEN
762
ZX_rem(GEN x, GEN y)
763
{
764
long vx, dx, dy, dz, i, j, sx, lr;
765
pari_sp av0, av;
766
GEN z,p1,rem;
767
768
vx = varn(x);
769
dy = degpol(y);
770
dx = degpol(x);
771
if (dx < dy) return ZX_copy(x);
772
if (!dy) return pol_0(vx); /* y is constant */
773
av0 = avma; dz = dx-dy;
774
z=cgetg(dz+3,t_POL); z[1] = x[1];
775
x += 2; y += 2; z += 2;
776
777
p1 = gel(x,dx);
778
gel(z,dz) = icopy(p1);
779
for (i=dx-1; i>=dy; i--)
780
{
781
av=avma; p1=gel(x,i);
782
for (j=i-dy+1; j<=i && j<=dz; j++)
783
p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
784
gel(z,i-dy) = avma == av? icopy(p1): gerepileuptoint(av, p1);
785
}
786
rem = (GEN)avma; av = (pari_sp)new_chunk(dx+3);
787
for (sx=0; ; i--)
788
{
789
p1 = gel(x,i);
790
for (j=0; j<=i && j<=dz; j++)
791
p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
792
if (signe(p1)) { sx = 1; break; }
793
if (!i) break;
794
set_avma(av);
795
}
796
lr=i+3; rem -= lr;
797
rem[0] = evaltyp(t_POL) | evallg(lr);
798
rem[1] = z[-1];
799
p1 = gerepileuptoint((pari_sp)rem, p1);
800
rem += 2; gel(rem,i) = p1;
801
for (i--; i>=0; i--)
802
{
803
av=avma; p1 = gel(x,i);
804
for (j=0; j<=i && j<=dz; j++)
805
p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
806
gel(rem,i) = avma == av? icopy(p1): gerepileuptoint(av, p1);
807
}
808
rem -= 2;
809
if (!sx) (void)ZX_renormalize(rem, lr);
810
return gerepileupto(av0,rem);
811
}
812
813
/* return x(1) */
814
GEN
815
ZX_eval1(GEN x)
816
{
817
pari_sp av = avma;
818
long i = lg(x)-1;
819
GEN s;
820
if (i < 2) return gen_0;
821
s = gel(x,i); i--;
822
if (i == 1) return icopy(s);
823
for ( ; i>=2; i--)
824
{
825
GEN c = gel(x,i);
826
if (signe(c)) s = addii(s, c);
827
}
828
return gerepileuptoint(av,s);
829
}
830
831
/* reduce T mod X^n - 1. Shallow function */
832
GEN
833
ZX_mod_Xnm1(GEN T, ulong n)
834
{
835
long i, j, L = lg(T), l = n+2;
836
GEN S;
837
if (L <= l) return T;
838
S = cgetg(l, t_POL);
839
S[1] = T[1];
840
for (i = 2; i < l; i++) gel(S,i) = gel(T,i);
841
for (j = 2; i < L; i++) {
842
gel(S,j) = addii(gel(S,j), gel(T,i));
843
if (++j == l) j = 2;
844
}
845
return normalizepol_lg(S, l);
846
}
847
848
/*******************************************************************/
849
/* */
850
/* ZXV */
851
/* */
852
/*******************************************************************/
853
854
int
855
ZXV_equal(GEN V, GEN W)
856
{
857
long l = lg(V);
858
if (l!=lg(W)) return 0;
859
while (--l > 0)
860
if (!ZX_equal(gel(V,l), gel(W,l))) return 0;
861
return 1;
862
}
863
864
GEN
865
ZXV_Z_mul(GEN x, GEN y)
866
{ pari_APPLY_same(ZX_Z_mul(gel(x,i), y)) }
867
868
GEN
869
ZXV_remi2n(GEN x, long N)
870
{ pari_APPLY_same(ZX_remi2n(gel(x,i), N)) }
871
872
GEN
873
ZXV_dotproduct(GEN x, GEN y)
874
{
875
pari_sp av = avma;
876
long i, lx = lg(x);
877
GEN c;
878
if (lx == 1) return pol_0(varn(x));
879
c = ZX_mul(gel(x,1), gel(y,1));
880
for (i = 2; i < lx; i++)
881
{
882
GEN t = ZX_mul(gel(x,i), gel(y,i));
883
if (signe(t)) c = ZX_add(c, t);
884
}
885
return gerepileupto(av, c);
886
}
887
888
GEN
889
ZXC_to_FlxC(GEN x, ulong p, long sv)
890
{ pari_APPLY_type(t_COL,typ(gel(x,i))==t_INT ?
891
Z_to_Flx(gel(x,i), p, sv): ZX_to_Flx(gel(x,i), p)) }
892
893
GEN
894
ZXM_to_FlxM(GEN x, ulong p, long sv)
895
{ pari_APPLY_same(ZXC_to_FlxC(gel(x,i), p, sv)) }
896
897
/*******************************************************************/
898
/* */
899
/* ZXQM */
900
/* */
901
/*******************************************************************/
902
903
GEN
904
ZXn_mul(GEN x, GEN y, long n)
905
{ return RgXn_red_shallow(ZX_mul(x, y), n); }
906
907
GEN
908
ZXn_sqr(GEN x, long n)
909
{ return RgXn_red_shallow(ZX_sqr(x), n); }
910
911
/*******************************************************************/
912
/* */
913
/* ZXQM */
914
/* */
915
/*******************************************************************/
916
917
static long
918
ZX_expi(GEN x)
919
{
920
if (signe(x)==0) return 0;
921
if (typ(x)==t_INT) return expi(x);
922
return ZX_expispec(x+2, lgpol(x));
923
}
924
925
static long
926
ZXC_expi(GEN x)
927
{
928
long i, l = lg(x), m=0;
929
for(i = 1; i < l; i++)
930
{
931
long e = ZX_expi(gel(x,i));
932
if (e > m) m = e;
933
}
934
return m;
935
}
936
937
static long
938
ZXM_expi(GEN x)
939
{
940
long i, l = lg(x), m=0;
941
for(i = 1; i < l; i++)
942
{
943
long e = ZXC_expi(gel(x,i));
944
if (e > m) m = e;
945
}
946
return m;
947
}
948
949
static GEN
950
ZX_eval2BIL(GEN x, long k)
951
{
952
if (signe(x)==0) return gen_0;
953
if (typ(x)==t_INT) return x;
954
return ZX_eval2BILspec(x+2, k, lgpol(x));
955
}
956
957
/*Eval x in 2^(k*BIL) in linear time*/
958
static GEN
959
ZXC_eval2BIL(GEN x, long k)
960
{
961
long i, lx = lg(x);
962
GEN A = cgetg(lx, t_COL);
963
for (i=1; i<lx; i++) gel(A,i) = ZX_eval2BIL(gel(x,i), k);
964
return A;
965
}
966
967
static GEN
968
ZXM_eval2BIL(GEN x, long k)
969
{
970
long i, lx = lg(x);
971
GEN A = cgetg(lx, t_MAT);
972
for (i=1; i<lx; i++) gel(A,i) = ZXC_eval2BIL(gel(x,i), k);
973
return A;
974
}
975
976
static GEN
977
Z_mod2BIL_ZXQ(GEN x, long bs, GEN T)
978
{
979
pari_sp av = avma;
980
long v = varn(T), d = 2*(degpol(T)-1);
981
GEN z = Z_mod2BIL_ZX(x, bs, d, 0);
982
setvarn(z, v);
983
return gerepileupto(av, ZX_rem(z, T));
984
}
985
986
static GEN
987
ZC_mod2BIL_ZXQC(GEN x, long bs, GEN T)
988
{
989
long i, lx = lg(x);
990
GEN A = cgetg(lx, t_COL);
991
for (i=1; i<lx; i++) gel(A,i) = Z_mod2BIL_ZXQ(gel(x,i), bs, T);
992
return A;
993
}
994
995
static GEN
996
ZM_mod2BIL_ZXQM(GEN x, long bs, GEN T)
997
{
998
long i, lx = lg(x);
999
GEN A = cgetg(lx, t_MAT);
1000
for (i=1; i<lx; i++) gel(A,i) = ZC_mod2BIL_ZXQC(gel(x,i), bs, T);
1001
return A;
1002
}
1003
1004
GEN
1005
ZXQM_mul(GEN x, GEN y, GEN T)
1006
{
1007
long d = degpol(T);
1008
GEN z;
1009
pari_sp av = avma;
1010
if (d == 0)
1011
z = ZM_mul(simplify_shallow(x),simplify_shallow(y));
1012
else
1013
{
1014
long e, n, N, ex = ZXM_expi(x), ey = ZXM_expi(y);
1015
1016
if ((ey && ex > 64 * ey) || (ex && ey > 64 * ex)) return RgM_mul_i(x, y);
1017
n = lg(x)-1;
1018
e = ex + ey + expu(d) + expu(n) + 4;
1019
N = divsBIL(e)+1;
1020
z = ZM_mul(ZXM_eval2BIL(x,N), ZXM_eval2BIL(y,N));
1021
z = ZM_mod2BIL_ZXQM(z, N, T);
1022
}
1023
return gerepileupto(av, z);
1024
}
1025
1026
GEN
1027
ZXQM_sqr(GEN x, GEN T)
1028
{
1029
long d = degpol(T);
1030
GEN z;
1031
pari_sp av = avma;
1032
if (d == 0)
1033
z = ZM_sqr(simplify_shallow(x));
1034
else
1035
{
1036
long ex = ZXM_expi(x), d = degpol(T), n = lg(x)-1;
1037
long e = 2*ex + expu(d) + expu(n) + 4;
1038
long N = divsBIL(e)+1;
1039
z = ZM_sqr(ZXM_eval2BIL(x,N));
1040
z = ZM_mod2BIL_ZXQM(z, N, T);
1041
}
1042
return gerepileupto(av, z);
1043
}
1044
1045
GEN
1046
QXQM_mul(GEN x, GEN y, GEN T)
1047
{
1048
GEN dx, nx = Q_primitive_part(x, &dx);
1049
GEN dy, ny = Q_primitive_part(y, &dy);
1050
GEN z = ZXQM_mul(nx, ny, T);
1051
if (dx || dy)
1052
{
1053
GEN d = dx ? dy ? gmul(dx, dy): dx : dy;
1054
if (!gequal1(d)) z = RgM_Rg_mul(z, d);
1055
}
1056
return z;
1057
}
1058
1059
GEN
1060
QXQM_sqr(GEN x, GEN T)
1061
{
1062
GEN dx, nx = Q_primitive_part(x, &dx);
1063
GEN z = ZXQM_sqr(nx, T);
1064
if (dx) z = RgM_Rg_mul(z, gsqr(dx));
1065
return z;
1066
}
1067
1068
static GEN
1069
Z_mod2BIL_Fq(GEN x, long bs, GEN T, GEN p)
1070
{
1071
pari_sp av = avma;
1072
long v = get_FpX_var(T), d = 2*(get_FpX_degree(T)-1);
1073
GEN z = Z_mod2BIL_ZX(x, bs, d, 0);
1074
setvarn(z, v);
1075
return gerepileupto(av, FpX_rem(z, T, p));
1076
}
1077
1078
static GEN
1079
ZC_mod2BIL_FqC(GEN x, long bs, GEN T, GEN p)
1080
{
1081
long i, lx = lg(x);
1082
GEN A = cgetg(lx, t_COL);
1083
for (i=1; i<lx; i++) gel(A,i) = Z_mod2BIL_Fq(gel(x,i), bs, T, p);
1084
return A;
1085
}
1086
1087
static GEN
1088
ZM_mod2BIL_FqM(GEN x, long bs, GEN T, GEN p)
1089
{
1090
long i, lx = lg(x);
1091
GEN A = cgetg(lx, t_MAT);
1092
for (i=1; i<lx; i++) gel(A,i) = ZC_mod2BIL_FqC(gel(x,i), bs, T, p);
1093
return A;
1094
}
1095
1096
GEN
1097
FqM_mul_Kronecker(GEN x, GEN y, GEN T, GEN p)
1098
{
1099
pari_sp av = avma;
1100
long ex = ZXM_expi(x), ey = ZXM_expi(y), d= degpol(T), n = lg(x)-1;
1101
long e = ex + ey + expu(d) + expu(n) + 4;
1102
long N = divsBIL(e)+1;
1103
GEN z = ZM_mul(ZXM_eval2BIL(x,N), ZXM_eval2BIL(y,N));
1104
return gerepileupto(av, ZM_mod2BIL_FqM(z, N, T, p));
1105
}
1106
1107
/*******************************************************************/
1108
/* */
1109
/* ZXX */
1110
/* */
1111
/*******************************************************************/
1112
1113
void
1114
RgX_check_ZXX(GEN x, const char *s)
1115
{
1116
long k = lg(x)-1;
1117
for ( ; k>1; k--) {
1118
GEN t = gel(x,k);
1119
switch(typ(t)) {
1120
case t_INT: break;
1121
case t_POL: if (RgX_is_ZX(t)) break;
1122
/* fall through */
1123
default: pari_err_TYPE(stack_strcat(s, " not in Z[X,Y]"),x);
1124
}
1125
}
1126
}
1127
1128
/*Renormalize (in place) polynomial with t_INT or ZX coefficients.*/
1129
GEN
1130
ZXX_renormalize(GEN x, long lx)
1131
{
1132
long i;
1133
for (i = lx-1; i>1; i--)
1134
if (signe(gel(x,i))) break;
1135
stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + (i+1)));
1136
setlg(x, i+1); setsigne(x, i!=1); return x;
1137
}
1138
1139
GEN
1140
ZXX_evalx0(GEN y)
1141
{
1142
long i, l = lg(y);
1143
GEN z = cgetg(l,t_POL); z[1] = y[1];
1144
for(i=2; i<l; i++)
1145
{
1146
GEN yi = gel(y,i);
1147
gel(z,i) = typ(yi)==t_INT? yi: constant_coeff(yi);
1148
}
1149
return ZX_renormalize(z,l);
1150
}
1151
1152
long
1153
ZXX_max_lg(GEN x)
1154
{
1155
long i, prec = 0, lx = lg(x);
1156
for (i=2; i<lx; i++)
1157
{
1158
GEN p = gel(x,i);
1159
long l = (typ(p) == t_INT)? lgefint(p): ZX_max_lg(p);
1160
if (l > prec) prec = l;
1161
}
1162
return prec;
1163
}
1164
1165
GEN
1166
ZXX_Z_mul(GEN y, GEN x)
1167
{
1168
long i, l = lg(y);
1169
GEN z = cgetg(l,t_POL); z[1] = y[1];
1170
for(i=2; i<l; i++)
1171
if(typ(gel(y,i))==t_INT)
1172
gel(z,i) = mulii(gel(y,i),x);
1173
else
1174
gel(z,i) = ZX_Z_mul(gel(y,i),x);
1175
return z;
1176
}
1177
1178
GEN
1179
ZXX_Z_add_shallow(GEN x, GEN y)
1180
{
1181
long i, l = lg(x);
1182
GEN z, a;
1183
if (signe(x)==0) return scalarpol(y,varn(x));
1184
z = cgetg(l,t_POL); z[1] = x[1];
1185
a = gel(x,2);
1186
gel(z, 2) = typ(a)==t_INT? addii(a,y): ZX_Z_add(a,y);
1187
for(i=3; i<l; i++)
1188
gel(z,i) = gel(x,i);
1189
return z;
1190
}
1191
1192
GEN
1193
ZXX_Z_divexact(GEN y, GEN x)
1194
{
1195
long i, l = lg(y);
1196
GEN z = cgetg(l,t_POL); z[1] = y[1];
1197
for(i=2; i<l; i++)
1198
if(typ(gel(y,i))==t_INT)
1199
gel(z,i) = diviiexact(gel(y,i),x);
1200
else
1201
gel(z,i) = ZX_Z_divexact(gel(y,i),x);
1202
return z;
1203
}
1204
1205
/* Kronecker substitution, ZXX -> ZX:
1206
* P(X,Y) = sum_{0<=i<lP} P_i(X) * Y^i, where deg P_i < n.
1207
* Returns P(X,X^(2n-1)) */
1208
GEN
1209
RgXX_to_Kronecker_spec(GEN P, long lP, long n)
1210
{
1211
long i, k, N = (n<<1) + 1;
1212
GEN y;
1213
if (!lP) return pol_0(0);
1214
y = cgetg((N-2)*lP + 2, t_POL) + 2;
1215
for (k=i=0; i<lP; i++)
1216
{
1217
long j;
1218
GEN c = gel(P,i);
1219
if (typ(c)!=t_POL)
1220
{
1221
gel(y,k++) = c;
1222
j = 3;
1223
}
1224
else
1225
{
1226
long l = lg(c);
1227
if (l-3 >= n)
1228
pari_err_BUG("RgXX_to_Kronecker, P is not reduced mod Q");
1229
for (j=2; j < l; j++) gel(y,k++) = gel(c,j);
1230
}
1231
if (i == lP-1) break;
1232
for ( ; j < N; j++) gel(y,k++) = gen_0;
1233
}
1234
y-=2; setlg(y, k+2); y[1] = evalsigne(1); return y;
1235
}
1236
1237
/* shallow, n = deg(T) */
1238
GEN
1239
Kronecker_to_ZXX(GEN z, long n, long v)
1240
{
1241
long i,j,lx,l, N = (n<<1)+1;
1242
GEN x, t;
1243
l = lg(z); lx = (l-2) / (N-2);
1244
x = cgetg(lx+3,t_POL);
1245
x[1] = z[1];
1246
for (i=2; i<lx+2; i++)
1247
{
1248
t = cgetg(N,t_POL); t[1] = evalvarn(v);
1249
for (j=2; j<N; j++) gel(t,j) = gel(z,j);
1250
z += (N-2);
1251
gel(x,i) = ZX_renormalize(t,N);
1252
}
1253
N = (l-2) % (N-2) + 2;
1254
t = cgetg(N,t_POL); t[1] = evalvarn(v);
1255
for (j=2; j<N; j++) gel(t,j) = gel(z,j);
1256
gel(x,i) = ZX_renormalize(t,N);
1257
return ZXX_renormalize(x, i+1);
1258
}
1259
1260
GEN
1261
RgXX_to_Kronecker(GEN P, long n)
1262
{
1263
GEN z = RgXX_to_Kronecker_spec(P+2, lgpol(P), n);
1264
setvarn(z,varn(P)); return z;
1265
}
1266
GEN
1267
ZXX_mul_Kronecker(GEN x, GEN y, long n)
1268
{ return ZX_mul(RgXX_to_Kronecker(x,n), RgXX_to_Kronecker(y,n)); }
1269
1270
GEN
1271
ZXX_sqr_Kronecker(GEN x, long n)
1272
{ return ZX_sqr(RgXX_to_Kronecker(x,n)); }
1273
1274
/* shallow, n = deg(T) */
1275
GEN
1276
Kronecker_to_ZXQX(GEN z, GEN T)
1277
{
1278
long i,j,lx,l, N = (degpol(T)<<1)+1;
1279
GEN x, t;
1280
l = lg(z); lx = (l-2) / (N-2);
1281
x = cgetg(lx+3,t_POL);
1282
x[1] = z[1];
1283
for (i=2; i<lx+2; i++)
1284
{
1285
t = cgetg(N,t_POL); t[1] = T[1];
1286
for (j=2; j<N; j++) gel(t,j) = gel(z,j);
1287
z += (N-2);
1288
gel(x,i) = ZX_rem(ZX_renormalize(t,N), T);
1289
}
1290
N = (l-2) % (N-2) + 2;
1291
t = cgetg(N,t_POL); t[1] = T[1];
1292
for (j=2; j<N; j++) gel(t,j) = gel(z,j);
1293
gel(x,i) = ZX_rem(ZX_renormalize(t,N), T);
1294
return ZXX_renormalize(x, i+1);
1295
}
1296
1297
GEN
1298
ZXQX_sqr(GEN x, GEN T)
1299
{
1300
pari_sp av = avma;
1301
long n = degpol(T);
1302
GEN z = ZXX_sqr_Kronecker(x, n);
1303
z = Kronecker_to_ZXQX(z, T);
1304
return gerepilecopy(av, z);
1305
}
1306
1307
GEN
1308
ZXQX_mul(GEN x, GEN y, GEN T)
1309
{
1310
pari_sp av = avma;
1311
long n = degpol(T);
1312
GEN z = ZXX_mul_Kronecker(x, y, n);
1313
z = Kronecker_to_ZXQX(z, T);
1314
return gerepilecopy(av, z);
1315
}
1316
1317
GEN
1318
ZXQX_ZXQ_mul(GEN P, GEN U, GEN T)
1319
{
1320
long i, lP;
1321
GEN res;
1322
res = cgetg_copy(P, &lP); res[1] = P[1];
1323
for(i=2; i<lP; i++)
1324
gel(res,i) = typ(gel(P,i))==t_POL? ZXQ_mul(U, gel(P,i), T)
1325
: gmul(U, gel(P,i));
1326
return ZXX_renormalize(res,lP);
1327
}
1328
1329
GEN
1330
QX_mul(GEN x, GEN y)
1331
{
1332
GEN dx, nx = Q_primitive_part(x, &dx);
1333
GEN dy, ny = Q_primitive_part(y, &dy);
1334
GEN z = ZX_mul(nx, ny);
1335
if (dx || dy)
1336
{
1337
GEN d = dx ? dy ? gmul(dx, dy): dx : dy;
1338
return ZX_Q_mul(z, d);
1339
} else
1340
return z;
1341
}
1342
1343
GEN
1344
QX_sqr(GEN x)
1345
{
1346
GEN dx, nx = Q_primitive_part(x, &dx);
1347
GEN z = ZX_sqr(nx);
1348
if (dx)
1349
return ZX_Q_mul(z, gsqr(dx));
1350
else
1351
return z;
1352
}
1353
1354
GEN
1355
QX_ZX_rem(GEN x, GEN y)
1356
{
1357
pari_sp av = avma;
1358
GEN d, nx = Q_primitive_part(x, &d);
1359
GEN r = ZX_rem(nx, y);
1360
if (d) r = ZX_Q_mul(r, d);
1361
return gerepileupto(av, r);
1362
}
1363
1364
GEN
1365
QXQX_mul(GEN x, GEN y, GEN T)
1366
{
1367
GEN dx, nx = Q_primitive_part(x, &dx);
1368
GEN dy, ny = Q_primitive_part(y, &dy);
1369
GEN z = ZXQX_mul(nx, ny, T);
1370
if (dx || dy)
1371
{
1372
GEN d = dx ? dy ? gmul(dx, dy): dx : dy;
1373
return ZXX_Q_mul(z, d);
1374
} else
1375
return z;
1376
}
1377
1378
GEN
1379
QXQX_sqr(GEN x, GEN T)
1380
{
1381
GEN dx, nx = Q_primitive_part(x, &dx);
1382
GEN z = ZXQX_sqr(nx, T);
1383
if (dx)
1384
return ZXX_Q_mul(z, gsqr(dx));
1385
else
1386
return z;
1387
}
1388
1389
GEN
1390
QXQX_powers(GEN P, long n, GEN T)
1391
{
1392
GEN v = cgetg(n+2, t_VEC);
1393
long i;
1394
gel(v, 1) = pol_1(varn(T));
1395
if (n==0) return v;
1396
gel(v, 2) = gcopy(P);
1397
for (i = 2; i <= n; i++) gel(v,i+1) = QXQX_mul(P, gel(v,i), T);
1398
return v;
1399
}
1400
1401
GEN
1402
QXQX_QXQ_mul(GEN P, GEN U, GEN T)
1403
{
1404
long i, lP;
1405
GEN res;
1406
res = cgetg_copy(P, &lP); res[1] = P[1];
1407
for(i=2; i<lP; i++)
1408
gel(res,i) = typ(gel(P,i))==t_POL? QXQ_mul(U, gel(P,i), T)
1409
: gmul(U, gel(P,i));
1410
return ZXX_renormalize(res,lP);
1411
}
1412
1413