Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

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

28479 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
15
#include "pari.h"
16
#include "paripriv.h"
17
18
/*******************************************************************/
19
/** **/
20
/** SPECIAL POLYNOMIALS **/
21
/** **/
22
/*******************************************************************/
23
/* Tchebichev polynomial: T0=1; T1=X; T(n)=2*X*T(n-1)-T(n-2)
24
* T(n) = (n/2) sum_{k=0}^{n/2} a_k x^(n-2k)
25
* where a_k = (-1)^k 2^(n-2k) (n-k-1)! / k!(n-2k)! is an integer
26
* and a_0 = 2^(n-1), a_k / a_{k-1} = - (n-2k+2)(n-2k+1) / 4k(n-k) */
27
GEN
28
polchebyshev1(long n, long v) /* Assume 4*n < LONG_MAX */
29
{
30
long k, l;
31
pari_sp av;
32
GEN q,a,r;
33
34
if (v<0) v = 0;
35
/* polchebyshev(-n,1) = polchebyshev(n,1) */
36
if (n < 0) n = -n;
37
if (n==0) return pol_1(v);
38
if (n==1) return pol_x(v);
39
40
q = cgetg(n+3, t_POL); r = q + n+2;
41
a = int2n(n-1);
42
gel(r--,0) = a;
43
gel(r--,0) = gen_0;
44
for (k=1,l=n; l>1; k++,l-=2)
45
{
46
av = avma;
47
a = diviuuexact(muluui(l, l-1, a), 4*k, n-k);
48
togglesign(a); a = gerepileuptoint(av, a);
49
gel(r--,0) = a;
50
gel(r--,0) = gen_0;
51
}
52
q[1] = evalsigne(1) | evalvarn(v);
53
return q;
54
}
55
static void
56
polchebyshev1_eval_aux(long n, GEN x, GEN *pt1, GEN *pt2)
57
{
58
GEN t1, t2, b;
59
if (n == 1) { *pt1 = gen_1; *pt2 = x; return; }
60
if (n == 0) { *pt1 = x; *pt2 = gen_1; return; }
61
polchebyshev1_eval_aux((n+1) >> 1, x, &t1, &t2);
62
b = gsub(gmul(gmul2n(t1,1), t2), x);
63
if (odd(n)) { *pt1 = gadd(gmul2n(gsqr(t1), 1), gen_m1); *pt2 = b; }
64
else { *pt1 = b; *pt2 = gadd(gmul2n(gsqr(t2), 1), gen_m1); }
65
}
66
static GEN
67
polchebyshev1_eval(long n, GEN x)
68
{
69
GEN t1, t2;
70
long i, v;
71
pari_sp av;
72
73
if (n < 0) n = -n;
74
if (n==0) return gen_1;
75
if (n==1) return gcopy(x);
76
av = avma;
77
v = u_lvalrem(n, 2, (ulong*)&n);
78
polchebyshev1_eval_aux((n+1)>>1, x, &t1, &t2);
79
if (n != 1) t2 = gsub(gmul(gmul2n(t1,1), t2), x);
80
for (i = 1; i <= v; i++) t2 = gadd(gmul2n(gsqr(t2), 1), gen_m1);
81
return gerepileupto(av, t2);
82
}
83
84
/* Chebychev polynomial of the second kind U(n,x): the coefficient in front of
85
* x^(n-2*m) is (-1)^m * 2^(n-2m)*(n-m)!/m!/(n-2m)! for m=0,1,...,n/2 */
86
GEN
87
polchebyshev2(long n, long v)
88
{
89
pari_sp av;
90
GEN q, a, r;
91
long m;
92
int neg = 0;
93
94
if (v<0) v = 0;
95
/* polchebyshev(-n,2) = -polchebyshev(n-2,2) */
96
if (n < 0) {
97
if (n == -1) return zeropol(v);
98
neg = 1; n = -n-2;
99
}
100
if (n==0) return neg ? scalar_ZX_shallow(gen_m1, v): pol_1(v);
101
102
q = cgetg(n+3, t_POL); r = q + n+2;
103
a = int2n(n);
104
if (neg) togglesign(a);
105
gel(r--,0) = a;
106
gel(r--,0) = gen_0;
107
for (m=1; 2*m<= n; m++)
108
{
109
av = avma;
110
a = diviuuexact(muluui(n-2*m+2, n-2*m+1, a), 4*m, n-m+1);
111
togglesign(a); a = gerepileuptoint(av, a);
112
gel(r--,0) = a;
113
gel(r--,0) = gen_0;
114
}
115
q[1] = evalsigne(1) | evalvarn(v);
116
return q;
117
}
118
static void
119
polchebyshev2_eval_aux(long n, GEN x, GEN *pu1, GEN *pu2)
120
{
121
GEN u1, u2, u, mu1;
122
if (n == 1) { *pu1 = gen_1; *pu2 = gmul2n(x,1); return; }
123
if (n == 0) { *pu1 = gen_0; *pu2 = gen_1; return; }
124
polchebyshev2_eval_aux(n >> 1, x, &u1, &u2);
125
mu1 = gneg(u1);
126
u = gmul(gadd(u2,u1), gadd(u2,mu1));
127
if (odd(n)) { *pu1 = u; *pu2 = gmul(gmul2n(u2,1), gadd(gmul(x,u2), mu1)); }
128
else { *pu2 = u; *pu1 = gmul(gmul2n(u1,1), gadd(u2, gmul(x,mu1))); }
129
}
130
static GEN
131
polchebyshev2_eval(long n, GEN x)
132
{
133
GEN u1, u2, mu1;
134
long neg = 0;
135
pari_sp av;
136
137
if (n < 0) {
138
if (n == -1) return gen_0;
139
neg = 1; n = -n-2;
140
}
141
if (n==0) return neg ? gen_m1: gen_1;
142
av = avma;
143
polchebyshev2_eval_aux(n>>1, x, &u1, &u2);
144
mu1 = gneg(u1);
145
if (odd(n)) u2 = gmul(gmul2n(u2,1), gadd(gmul(x,u2), mu1));
146
else u2 = gmul(gadd(u2,u1), gadd(u2,mu1));
147
if (neg) u2 = gneg(u2);
148
return gerepileupto(av, u2);
149
}
150
151
GEN
152
polchebyshev(long n, long kind, long v)
153
{
154
switch (kind)
155
{
156
case 1: return polchebyshev1(n, v);
157
case 2: return polchebyshev2(n, v);
158
default: pari_err_FLAG("polchebyshev");
159
}
160
return NULL; /* LCOV_EXCL_LINE */
161
}
162
GEN
163
polchebyshev_eval(long n, long kind, GEN x)
164
{
165
if (!x) return polchebyshev(n, kind, 0);
166
if (gequalX(x)) return polchebyshev(n, kind, varn(x));
167
switch (kind)
168
{
169
case 1: return polchebyshev1_eval(n, x);
170
case 2: return polchebyshev2_eval(n, x);
171
default: pari_err_FLAG("polchebyshev");
172
}
173
return NULL; /* LCOV_EXCL_LINE */
174
}
175
176
/* Hermite polynomial H(n,x): H(n+1) = 2x H(n) - 2n H(n-1)
177
* The coefficient in front of x^(n-2*m) is
178
* (-1)^m * n! * 2^(n-2m)/m!/(n-2m)! for m=0,1,...,n/2.. */
179
GEN
180
polhermite(long n, long v)
181
{
182
long m;
183
pari_sp av;
184
GEN q,a,r;
185
186
if (v<0) v = 0;
187
if (n==0) return pol_1(v);
188
189
q = cgetg(n+3, t_POL); r = q + n+2;
190
a = int2n(n);
191
gel(r--,0) = a;
192
gel(r--,0) = gen_0;
193
for (m=1; 2*m<= n; m++)
194
{
195
av = avma;
196
a = diviuexact(muluui(n-2*m+2, n-2*m+1, a), 4*m);
197
togglesign(a);
198
gel(r--,0) = a = gerepileuptoint(av, a);
199
gel(r--,0) = gen_0;
200
}
201
q[1] = evalsigne(1) | evalvarn(v);
202
return q;
203
}
204
static void
205
err_hermite(long n)
206
{ pari_err_DOMAIN("polhermite", "degree", "<", gen_0, stoi(n)); }
207
GEN
208
polhermite_eval0(long n, GEN x, long flag)
209
{
210
long i;
211
pari_sp av, av2;
212
GEN x2, u, v;
213
214
if (n < 0) err_hermite(n);
215
if (!x || gequalX(x))
216
{
217
long v = x? varn(x): 0;
218
if (flag)
219
{
220
if (!n) err_hermite(-1);
221
retmkvec2(polhermite(n-1,v),polhermite(n,v));
222
}
223
return polhermite(n, v);
224
}
225
if (n==0)
226
{
227
if (flag) err_hermite(-1);
228
return gen_1;
229
}
230
if (n==1)
231
{
232
if (flag) retmkvec2(gen_1, gmul2n(x,1));
233
return gmul2n(x,1);
234
}
235
av = avma; x2 = gmul2n(x,1); v = gen_1; u = x2;
236
av2= avma;
237
for (i=1; i<n; i++)
238
{ /* u = H_i(x), v = H_{i-1}(x), compute t = H_{i+1}(x) */
239
GEN t;
240
if ((i & 0xff) == 0) gerepileall(av2,2,&u, &v);
241
t = gsub(gmul(x2, u), gmulsg(2*i,v));
242
v = u; u = t;
243
}
244
if (flag) return gerepilecopy(av, mkvec2(v, u));
245
return gerepileupto(av, u);
246
}
247
GEN
248
polhermite_eval(long n, GEN x) { return polhermite_eval0(n, x, 0); }
249
250
/* Legendre polynomial
251
* L0=1; L1=X; (n+1)*L(n+1)=(2*n+1)*X*L(n)-n*L(n-1)
252
* L(n) = 2^-n sum_{k=0}^{n/2} a_k x^(n-2k)
253
* where a_k = (-1)^k (2n-2k)! / k! (n-k)! (n-2k)! is an integer
254
* and a_0 = binom(2n,n), a_k / a_{k-1} = - (n-2k+1)(n-2k+2) / 2k (2n-2k+1) */
255
GEN
256
pollegendre(long n, long v)
257
{
258
long k, l;
259
pari_sp av;
260
GEN a, r, q;
261
262
if (v<0) v = 0;
263
/* pollegendre(-n) = pollegendre(n-1) */
264
if (n < 0) n = -n-1;
265
if (n==0) return pol_1(v);
266
if (n==1) return pol_x(v);
267
268
av = avma;
269
q = cgetg(n+3, t_POL); r = q + n+2;
270
gel(r--,0) = a = binomialuu(n<<1,n);
271
gel(r--,0) = gen_0;
272
for (k=1,l=n; l>1; k++,l-=2)
273
{ /* l = n-2*k+2 */
274
av = avma;
275
a = diviuuexact(muluui(l, l-1, a), 2*k, n+l-1);
276
togglesign(a); a = gerepileuptoint(av, a);
277
gel(r--,0) = a;
278
gel(r--,0) = gen_0;
279
}
280
q[1] = evalsigne(1) | evalvarn(v);
281
return gerepileupto(av, gmul2n(q,-n));
282
}
283
/* q such that Ln * 2^n = q(x^2) [n even] or x q(x^2) [n odd] */
284
GEN
285
pollegendre_reduced(long n, long v)
286
{
287
long k, l, N;
288
pari_sp av;
289
GEN a, r, q;
290
291
if (v<0) v = 0;
292
/* pollegendre(-n) = pollegendre(n-1) */
293
if (n < 0) n = -n-1;
294
if (n<=1) return n? scalarpol_shallow(gen_2,v): pol_1(v);
295
296
N = n >> 1;
297
q = cgetg(N+3, t_POL); r = q + N+2;
298
gel(r--,0) = a = binomialuu(n<<1,n);
299
for (k=1,l=n; l>1; k++,l-=2)
300
{ /* l = n-2*k+2 */
301
av = avma;
302
a = diviuuexact(muluui(l, l-1, a), 2*k, n+l-1);
303
togglesign(a);
304
gel(r--,0) = a = gerepileuptoint(av, a);
305
}
306
q[1] = evalsigne(1) | evalvarn(v);
307
return q;
308
}
309
310
GEN
311
pollegendre_eval0(long n, GEN x, long flag)
312
{
313
pari_sp av;
314
GEN u, v;
315
long i;
316
317
if (n < 0) n = -n-1; /* L(-n) = L(n-1) */
318
/* n >= 0 */
319
if (flag && flag != 1) pari_err_FLAG("pollegendre");
320
if (!x || gequalX(x))
321
{
322
long v = x? varn(x): 0;
323
if (flag) retmkvec2(pollegendre(n-1,v), pollegendre(n,v));
324
return pollegendre(n, v);
325
}
326
if (n==0)
327
{
328
if (flag) retmkvec2(gen_1, gcopy(x));
329
return gen_1;
330
}
331
if (n==1)
332
{
333
if (flag) retmkvec2(gcopy(x), gen_1);
334
return gcopy(x);
335
}
336
av = avma; v = gen_1; u = x;
337
for (i=1; i<n; i++)
338
{ /* u = P_i(x), v = P_{i-1}(x), compute t = P_{i+1}(x) */
339
GEN t;
340
if ((i & 0xff) == 0) gerepileall(av,2,&u, &v);
341
t = gdivgs(gsub(gmul(gmulsg(2*i+1,x), u), gmulsg(i,v)), i+1);
342
v = u; u = t;
343
}
344
if (flag) return gerepilecopy(av, mkvec2(v, u));
345
return gerepileupto(av, u);
346
}
347
GEN
348
pollegendre_eval(long n, GEN x) { return pollegendre_eval0(n, x, 0); }
349
350
/* Laguerre polynomial
351
* L0^a = 1; L1^a = -X+a+1;
352
* (n+1)*L^a(n+1) = (-X+(2*n+a+1))*L^a(n) - (n+a)*L^a(n-1)
353
* L^a(n) = sum_{k=0}^n (-1)^k * binom(n+a,n-k) * x^k/k! */
354
GEN
355
pollaguerre(long n, GEN a, long v)
356
{
357
pari_sp av = avma;
358
GEN L = cgetg(n+3, t_POL), c1 = gen_1, c2 = mpfact(n);
359
long i;
360
361
L[1] = evalsigne(1) | evalvarn(v);
362
if (odd(n)) togglesign_safe(&c2);
363
for (i = n; i >= 0; i--)
364
{
365
gel(L, i+2) = gdiv(c1, c2);
366
if (i)
367
{
368
c2 = divis(c2,-i);
369
c1 = gdivgs(gmul(c1, gaddsg(i,a)), n+1-i);
370
}
371
}
372
return gerepilecopy(av, L);
373
}
374
static void
375
err_lag(long n)
376
{ pari_err_DOMAIN("pollaguerre", "degree", "<", gen_0, stoi(n)); }
377
GEN
378
pollaguerre_eval0(long n, GEN a, GEN x, long flag)
379
{
380
pari_sp av = avma;
381
long i;
382
GEN v, u;
383
384
if (n < 0) err_lag(n);
385
if (flag && flag != 1) pari_err_FLAG("pollaguerre");
386
if (!a) a = gen_0;
387
if (!x || gequalX(x))
388
{
389
long v = x? varn(x): 0;
390
if (flag)
391
{
392
if (!n) err_lag(-1);
393
retmkvec2(pollaguerre(n-1,a,v), pollaguerre(n,a,v));
394
}
395
return pollaguerre(n,a,v);
396
}
397
if (n==0)
398
{
399
if (flag) err_lag(-1);
400
return gen_1;
401
}
402
if (n==1)
403
{
404
if (flag) retmkvec2(gsub(gaddgs(a,1),x), gen_1);
405
return gsub(gaddgs(a,1),x);
406
}
407
av = avma; v = gen_1; u = gsub(gaddgs(a,1),x);
408
for (i=1; i<n; i++)
409
{ /* u = P_i(x), v = P_{i-1}(x), compute t = P_{i+1}(x) */
410
GEN t;
411
if ((i & 0xff) == 0) gerepileall(av,2,&u, &v);
412
t = gdivgs(gsub(gmul(gsub(gaddsg(2*i+1,a),x), u), gmul(gaddsg(i,a),v)), i+1);
413
v = u; u = t;
414
}
415
if (flag) return gerepilecopy(av, mkvec2(v, u));
416
return gerepileupto(av, u);
417
}
418
GEN
419
pollaguerre_eval(long n, GEN x, GEN a) { return pollaguerre_eval0(n, x, a, 0); }
420
421
/* polcyclo(p) = X^(p-1) + ... + 1 */
422
static GEN
423
polcyclo_prime(long p, long v)
424
{
425
GEN T = cgetg(p+2, t_POL);
426
long i;
427
T[1] = evalsigne(1) | evalvarn(v);
428
for (i = 2; i < p+2; i++) gel(T,i) = gen_1;
429
return T;
430
}
431
432
/* cyclotomic polynomial */
433
GEN
434
polcyclo(long n, long v)
435
{
436
long s, q, i, l;
437
pari_sp av=avma;
438
GEN T, P;
439
440
if (v<0) v = 0;
441
if (n < 3)
442
switch(n)
443
{
444
case 1: return deg1pol_shallow(gen_1, gen_m1, v);
445
case 2: return deg1pol_shallow(gen_1, gen_1, v);
446
default: pari_err_DOMAIN("polcyclo", "index", "<=", gen_0, stoi(n));
447
}
448
P = gel(factoru(n), 1); l = lg(P);
449
s = P[1]; T = polcyclo_prime(s, v);
450
for (i = 2; i < l; i++)
451
{ /* Phi_{np}(X) = Phi_n(X^p) / Phi_n(X) */
452
s *= P[i];
453
T = RgX_div(RgX_inflate(T, P[i]), T);
454
}
455
/* s = squarefree part of n */
456
q = n / s;
457
if (q == 1) return gerepileupto(av, T);
458
return gerepilecopy(av, RgX_inflate(T,q));
459
}
460
461
/* cyclotomic polynomial */
462
GEN
463
polcyclo_eval(long n, GEN x)
464
{
465
pari_sp av= avma;
466
GEN P, md, xd, yneg, ypos;
467
long l, s, i, j, q, tx;
468
long root_of_1 = 0;
469
470
if (!x) return polcyclo(n, 0);
471
tx = typ(x);
472
if (gequalX(x)) return polcyclo(n, varn(x));
473
if (n <= 0) pari_err_DOMAIN("polcyclo", "index", "<=", gen_0, stoi(n));
474
if (n == 1) return gsubgs(x, 1);
475
if (tx == t_INT && !signe(x)) return gen_1;
476
while ((n & 3) == 0) { n >>= 1; x = gsqr(x); } /* Phi_4n(x) = Phi_2n(x^2) */
477
/* n not divisible by 4 */
478
if (n == 2) return gerepileupto(av, gaddgs(x,1));
479
if (!odd(n)) { n >>= 1; x = gneg(x); } /* Phi_2n(x) = Phi_n(-x) for n>1 odd */
480
/* n odd > 2. s largest squarefree divisor of n */
481
P = gel(factoru(n), 1); s = zv_prod(P);
482
/* replace n by largest squarefree divisor */
483
q = n/s; if (q != 1) { x = gpowgs(x, q); n = s; }
484
l = lg(P)-1;
485
/* n squarefree odd > 2, l distinct prime divisors. Now handle x = 1 or -1 */
486
if (tx == t_INT) { /* shortcut */
487
if (is_pm1(x))
488
{
489
set_avma(av);
490
if (signe(x) > 0 && l == 1) return utoipos(P[1]);
491
return gen_1;
492
}
493
} else {
494
if (gequal1(x))
495
{ /* n is prime, return n; multiply by x to keep the type */
496
if (l == 1) return gerepileupto(av, gmulgs(x,n));
497
return gerepilecopy(av, x); /* else 1 */
498
}
499
if (gequalm1(x)) return gerepileupto(av, gneg(x)); /* -1 */
500
}
501
/* Heuristic: evaluation will probably not improve things */
502
if (tx == t_POL || tx == t_MAT || lg(x) > n)
503
return gerepileupto(av, poleval(polcyclo(n,0), x));
504
505
xd = cgetg((1L<<l) + 1, t_VEC); /* the x^d, where d | n */
506
md = cgetg((1L<<l) + 1, t_VECSMALL); /* the mu(d), where d | n */
507
gel(xd, 1) = x;
508
md[1] = 1;
509
/* Use Phi_n(x) = Prod_{d|n} (x^d-1)^mu(n/d).
510
* If x has exact order D, n = Dq, then the result is 0 if q = 1. Otherwise
511
* the factors with x^d-1, D|d are omitted and we multiply at the end by
512
* prod_{d | q} d^mu(q/d) = q if prime, 1 otherwise */
513
/* We store the factors with mu(d)= 1 (resp.-1) in ypos (resp yneg).
514
* At the end we return ypos/yneg if mu(n)=1 and yneg/ypos if mu(n)=-1 */
515
ypos = gsubgs(x,1);
516
yneg = gen_1;
517
for (i = 1; i <= l; i++)
518
{
519
long ti = 1L<<(i-1), p = P[i];
520
for (j = 1; j <= ti; j++) {
521
GEN X = gpowgs(gel(xd,j), p), t = gsubgs(X,1);
522
gel(xd,ti+j) = X;
523
md[ti+j] = -md[j];
524
if (gequal0(t))
525
{ /* x^d = 1; root_of_1 := the smallest index ti+j such that X == 1
526
* (whose bits code d: bit i-1 is set iff P[i] | d). If no such index
527
* exists, then root_of_1 remains 0. Do not multiply with X-1 if X = 1,
528
* we handle these factors at the end */
529
if (!root_of_1) root_of_1 = ti+j;
530
}
531
else
532
{
533
if (md[ti+j] == 1) ypos = gmul(ypos, t);
534
else yneg = gmul(yneg, t);
535
}
536
}
537
}
538
ypos = odd(l)? gdiv(yneg,ypos): gdiv(ypos,yneg);
539
if (root_of_1)
540
{
541
GEN X = gel(xd,(1<<l)); /* = x^n = 1 */
542
long bitmask_q = (1<<l) - root_of_1;
543
/* bitmask_q encodes q = n/d: bit (i-1) is 1 iff P[i] | q */
544
545
/* x is a root of unity. If bitmask_q = 0, then x was a primitive n-th
546
* root of 1 and the result is zero. Return X - 1 to preserve type. */
547
if (!bitmask_q) return gerepileupto(av, gsubgs(X, 1));
548
/* x is a primitive d-th root of unity, where d|n and d<n: we
549
* must multiply ypos by if(isprime(n/d), n/d, 1) */
550
ypos = gmul(ypos, X); /* multiply by X = 1 to preserve type */
551
/* If bitmask_q = 1<<(i-1) for some i <= l, then q == P[i] and we multiply
552
* by P[i]; otherwise q is composite and nothing more needs to be done */
553
if (!(bitmask_q & (bitmask_q-1))) /* detects power of 2, since bitmask!=0 */
554
{
555
i = vals(bitmask_q)+1; /* q = P[i] */
556
ypos = gmulgs(ypos, P[i]);
557
}
558
}
559
return gerepileupto(av, ypos);
560
}
561
/********************************************************************/
562
/** **/
563
/** HILBERT & PASCAL MATRICES **/
564
/** **/
565
/********************************************************************/
566
GEN
567
mathilbert(long n) /* Hilbert matrix of order n */
568
{
569
long i,j;
570
GEN p;
571
572
if (n < 0) pari_err_DOMAIN("mathilbert", "dimension", "<", gen_0, stoi(n));
573
p = cgetg(n+1,t_MAT);
574
for (j=1; j<=n; j++)
575
{
576
gel(p,j) = cgetg(n+1,t_COL);
577
for (i=1+(j==1); i<=n; i++)
578
gcoeff(p,i,j) = mkfrac(gen_1, utoipos(i+j-1));
579
}
580
if (n) gcoeff(p,1,1) = gen_1;
581
return p;
582
}
583
584
/* q-Pascal triangle = (choose(i,j)_q) (ordinary binomial if q = NULL) */
585
GEN
586
matqpascal(long n, GEN q)
587
{
588
long i, j, I;
589
pari_sp av = avma;
590
GEN m, qpow = NULL; /* gcc -Wall */
591
592
if (n < -1) pari_err_DOMAIN("matpascal", "n", "<", gen_m1, stoi(n));
593
n++; m = cgetg(n+1,t_MAT);
594
for (j=1; j<=n; j++) gel(m,j) = cgetg(n+1,t_COL);
595
if (q)
596
{
597
I = (n+1)/2;
598
if (I > 1) { qpow = new_chunk(I+1); gel(qpow,2)=q; }
599
for (j=3; j<=I; j++) gel(qpow,j) = gmul(q, gel(qpow,j-1));
600
}
601
for (i=1; i<=n; i++)
602
{
603
I = (i+1)/2; gcoeff(m,i,1)= gen_1;
604
if (q)
605
{
606
for (j=2; j<=I; j++)
607
gcoeff(m,i,j) = gadd(gmul(gel(qpow,j),gcoeff(m,i-1,j)),
608
gcoeff(m,i-1,j-1));
609
}
610
else
611
{
612
for (j=2; j<=I; j++)
613
gcoeff(m,i,j) = addii(gcoeff(m,i-1,j), gcoeff(m,i-1,j-1));
614
}
615
for ( ; j<=i; j++) gcoeff(m,i,j) = gcoeff(m,i,i+1-j);
616
for ( ; j<=n; j++) gcoeff(m,i,j) = gen_0;
617
}
618
return gerepilecopy(av, m);
619
}
620
621
GEN
622
eulerianpol(long N, long v)
623
{
624
pari_sp av = avma;
625
long n, n2, k = 0;
626
GEN A;
627
if (v < 0) v = 0;
628
if (N <= 0) pari_err_DOMAIN("eulerianpol", "index", "<=", gen_0, stoi(N));
629
if (N == 1) return pol_1(v);
630
if (N == 2) return deg1pol_shallow(gen_1, gen_1, v);
631
A = cgetg(N+1, t_VEC);
632
gel(A,1) = gen_1; gel(A,2) = gen_1; /* A_2 = x+1 */
633
for (n = 3; n <= N; n++)
634
{ /* A(n,k) = (n-k)A(n-1,k-1) + (k+1)A(n-1,k) */
635
n2 = n >> 1;
636
if (odd(n)) gel(A,n2+1) = mului(n+1, gel(A,n2));
637
for (k = n2-1; k; k--)
638
gel(A,k+1) = addii(mului(n-k, gel(A,k)), mului(k+1, gel(A,k+1)));
639
if (gc_needed(av,1))
640
{
641
if (DEBUGMEM>1) pari_warn(warnmem,"eulerianpol, %ld/%ld",n,N);
642
for (k = odd(n)? n2+1: n2; k < N; k++) gel(A,k+1) = gen_0;
643
A = gerepilecopy(av, A);
644
}
645
}
646
k = N >> 1; if (odd(N)) k++;
647
for (; k < N; k++) gel(A,k+1) = gel(A, N-k);
648
return gerepilecopy(av, RgV_to_RgX(A, v));
649
}
650
651
/******************************************************************/
652
/** **/
653
/** PRECISION CHANGES **/
654
/** **/
655
/******************************************************************/
656
657
GEN
658
gprec(GEN x, long d)
659
{
660
pari_sp av = avma;
661
if (d <= 0) pari_err_DOMAIN("gprec", "precision", "<=", gen_0, stoi(d));
662
return gerepilecopy(av, gprec_w(x, ndec2prec(d)));
663
}
664
665
/* not GC-safe; precision given in word length (including codewords) */
666
GEN
667
gprec_w(GEN x, long pr)
668
{
669
long lx, i;
670
GEN y;
671
672
switch(typ(x))
673
{
674
case t_REAL:
675
if (signe(x)) return realprec(x) != pr? rtor(x,pr): x;
676
i = -prec2nbits(pr);
677
if (i < expo(x)) return real_0_bit(i);
678
y = cgetr(2); y[1] = x[1]; return y;
679
case t_COMPLEX:
680
y = cgetg(3, t_COMPLEX);
681
gel(y,1) = gprec_w(gel(x,1),pr);
682
gel(y,2) = gprec_w(gel(x,2),pr);
683
break;
684
case t_POL: case t_SER:
685
y = cgetg_copy(x, &lx); y[1] = x[1];
686
for (i=2; i<lx; i++) gel(y,i) = gprec_w(gel(x,i),pr);
687
break;
688
case t_POLMOD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT:
689
y = cgetg_copy(x, &lx);
690
for (i=1; i<lx; i++) gel(y,i) = gprec_w(gel(x,i),pr);
691
break;
692
default: return x;
693
}
694
return y;
695
}
696
/* not GC-safe; precision given in word length (including codewords) */
697
GEN
698
gprec_wensure(GEN x, long pr)
699
{
700
long lx, i;
701
GEN y;
702
703
switch(typ(x))
704
{
705
case t_REAL:
706
if (signe(x)) return realprec(x) < pr? rtor(x,pr): x;
707
i = -prec2nbits(pr);
708
if (i < expo(x)) return real_0_bit(i);
709
y = cgetr(2); y[1] = x[1]; return y;
710
case t_COMPLEX:
711
y = cgetg(3, t_COMPLEX);
712
gel(y,1) = gprec_wensure(gel(x,1),pr);
713
gel(y,2) = gprec_wensure(gel(x,2),pr);
714
break;
715
case t_POL: case t_SER:
716
y = cgetg_copy(x, &lx); y[1] = x[1];
717
for (i=2; i<lx; i++) gel(y,i) = gprec_wensure(gel(x,i),pr);
718
break;
719
case t_POLMOD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT:
720
y = cgetg_copy(x, &lx);
721
for (i=1; i<lx; i++) gel(y,i) = gprec_wensure(gel(x,i),pr);
722
break;
723
default: return x;
724
}
725
return y;
726
}
727
728
/* not GC-safe; precision given in word length (including codewords),
729
* truncate mantissa to precision 'pr' but never increase it */
730
GEN
731
gprec_wtrunc(GEN x, long pr)
732
{
733
long lx, i;
734
GEN y;
735
736
switch(typ(x))
737
{
738
case t_REAL:
739
return (signe(x) && realprec(x) > pr)? rtor(x,pr): x;
740
case t_COMPLEX:
741
y = cgetg(3, t_COMPLEX);
742
gel(y,1) = gprec_wtrunc(gel(x,1),pr);
743
gel(y,2) = gprec_wtrunc(gel(x,2),pr);
744
break;
745
case t_POL:
746
case t_SER:
747
y = cgetg_copy(x, &lx); y[1] = x[1];
748
for (i=2; i<lx; i++) gel(y,i) = gprec_wtrunc(gel(x,i),pr);
749
break;
750
case t_POLMOD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT:
751
y = cgetg_copy(x, &lx);
752
for (i=1; i<lx; i++) gel(y,i) = gprec_wtrunc(gel(x,i),pr);
753
break;
754
default: return x;
755
}
756
return y;
757
}
758
759
/********************************************************************/
760
/** **/
761
/** SERIES TRANSFORMS **/
762
/** **/
763
/********************************************************************/
764
/** LAPLACE TRANSFORM (OF A SERIES) **/
765
/********************************************************************/
766
static GEN
767
serlaplace(GEN x)
768
{
769
long i, l = lg(x), e = valp(x);
770
GEN t, y = cgetg(l,t_SER);
771
if (e < 0) pari_err_DOMAIN("laplace","valuation","<",gen_0,stoi(e));
772
t = mpfact(e); y[1] = x[1];
773
for (i=2; i<l; i++)
774
{
775
gel(y,i) = gmul(t, gel(x,i));
776
e++; t = mului(e,t);
777
}
778
return y;
779
}
780
static GEN
781
pollaplace(GEN x)
782
{
783
long i, e = 0, l = lg(x);
784
GEN t = gen_1, y = cgetg(l,t_POL);
785
y[1] = x[1];
786
for (i=2; i<l; i++)
787
{
788
gel(y,i) = gmul(t, gel(x,i));
789
e++; t = mului(e,t);
790
}
791
return y;
792
}
793
GEN
794
laplace(GEN x)
795
{
796
pari_sp av = avma;
797
switch(typ(x))
798
{
799
case t_POL: x = pollaplace(x); break;
800
case t_SER: x = serlaplace(x); break;
801
default: if (is_scalar_t(typ(x))) return gcopy(x);
802
pari_err_TYPE("laplace",x);
803
}
804
return gerepilecopy(av, x);
805
}
806
807
/********************************************************************/
808
/** CONVOLUTION PRODUCT (OF TWO SERIES) **/
809
/********************************************************************/
810
GEN
811
convol(GEN x, GEN y)
812
{
813
long j, lx, ly, ex, ey, vx = varn(x);
814
GEN z;
815
816
if (typ(x) != t_SER) pari_err_TYPE("convol",x);
817
if (typ(y) != t_SER) pari_err_TYPE("convol",y);
818
if (varn(y) != vx) pari_err_VAR("convol", x,y);
819
ex = valp(x);
820
ey = valp(y);
821
if (ser_isexactzero(x))
822
return scalarser(gadd(Rg_get_0(x), Rg_get_0(y)), varn(x), maxss(ex,ey));
823
lx = lg(x) + ex; x -= ex;
824
ly = lg(y) + ey; y -= ey;
825
/* inputs shifted: x[i] and y[i] now correspond to monomials of same degree */
826
if (ly < lx) lx = ly; /* min length */
827
if (ex < ey) ex = ey; /* max valuation */
828
if (lx - ex < 3) return zeroser(vx, lx-2);
829
830
z = cgetg(lx - ex, t_SER);
831
z[1] = evalvalp(ex) | evalvarn(vx);
832
for (j = ex+2; j<lx; j++) gel(z,j-ex) = gmul(gel(x,j),gel(y,j));
833
return normalize(z);
834
}
835
836
/***********************************************************************/
837
/* OPERATIONS ON DIRICHLET SERIES: *, / */
838
/* (+, -, scalar multiplication are done on the corresponding vectors) */
839
/***********************************************************************/
840
static long
841
dirval(GEN x)
842
{
843
long i = 1, lx = lg(x);
844
while (i < lx && gequal0(gel(x,i))) i++;
845
return i;
846
}
847
848
GEN
849
dirmul(GEN x, GEN y)
850
{
851
pari_sp av = avma, av2;
852
long nx, ny, nz, dx, dy, i, j, k;
853
GEN z;
854
855
if (typ(x)!=t_VEC) pari_err_TYPE("dirmul",x);
856
if (typ(y)!=t_VEC) pari_err_TYPE("dirmul",y);
857
dx = dirval(x); nx = lg(x)-1;
858
dy = dirval(y); ny = lg(y)-1;
859
if (ny-dy < nx-dx) { swap(x,y); lswap(nx,ny); lswap(dx,dy); }
860
nz = minss(nx*dy,ny*dx);
861
y = RgV_kill0(y);
862
av2 = avma;
863
z = zerovec(nz);
864
for (j=dx; j<=nx; j++)
865
{
866
GEN c = gel(x,j);
867
if (gequal0(c)) continue;
868
if (gequal1(c))
869
{
870
for (k=dy,i=j*dy; i<=nz; i+=j,k++)
871
if (gel(y,k)) gel(z,i) = gadd(gel(z,i),gel(y,k));
872
}
873
else if (gequalm1(c))
874
{
875
for (k=dy,i=j*dy; i<=nz; i+=j,k++)
876
if (gel(y,k)) gel(z,i) = gsub(gel(z,i),gel(y,k));
877
}
878
else
879
{
880
for (k=dy,i=j*dy; i<=nz; i+=j,k++)
881
if (gel(y,k)) gel(z,i) = gadd(gel(z,i),gmul(c,gel(y,k)));
882
}
883
if (gc_needed(av2,3))
884
{
885
if (DEBUGMEM>1) pari_warn(warnmem,"dirmul, %ld/%ld",j,nx);
886
z = gerepilecopy(av2,z);
887
}
888
}
889
return gerepilecopy(av,z);
890
}
891
892
GEN
893
dirdiv(GEN x, GEN y)
894
{
895
pari_sp av = avma, av2;
896
long nx,ny,nz, dx,dy, i,j,k;
897
GEN p1;
898
899
if (typ(x)!=t_VEC) pari_err_TYPE("dirdiv",x);
900
if (typ(y)!=t_VEC) pari_err_TYPE("dirdiv",y);
901
dx = dirval(x); nx = lg(x)-1;
902
dy = dirval(y); ny = lg(y)-1;
903
if (dy != 1 || !ny) pari_err_INV("dirdiv",y);
904
nz = minss(nx,ny*dx);
905
p1 = gel(y,1);
906
if (gequal1(p1)) p1 = NULL; else y = gdiv(y,p1);
907
y = RgV_kill0(y);
908
av2 = avma;
909
x = p1 ? gdiv(x,p1): leafcopy(x);
910
for (j=1; j<dx; j++) gel(x,j) = gen_0;
911
setlg(x,nz+1);
912
for (j=dx; j<=nz; j++)
913
{
914
GEN c = gel(x,j);
915
if (gequal0(c)) continue;
916
if (gequal1(c))
917
{
918
for (i=j+j,k=2; i<=nz; i+=j,k++)
919
if (gel(y,k)) gel(x,i) = gsub(gel(x,i),gel(y,k));
920
}
921
else if (gequalm1(c))
922
{
923
for (i=j+j,k=2; i<=nz; i+=j,k++)
924
if (gel(y,k)) gel(x,i) = gadd(gel(x,i),gel(y,k));
925
}
926
else
927
{
928
for (i=j+j,k=2; i<=nz; i+=j,k++)
929
if (gel(y,k)) gel(x,i) = gsub(gel(x,i),gmul(c,gel(y,k)));
930
}
931
if (gc_needed(av2,3))
932
{
933
if (DEBUGMEM>1) pari_warn(warnmem,"dirdiv, %ld/%ld",j,nz);
934
x = gerepilecopy(av2,x);
935
}
936
}
937
return gerepilecopy(av,x);
938
}
939
940
/*******************************************************************/
941
/** **/
942
/** COMBINATORICS **/
943
/** **/
944
/*******************************************************************/
945
/** BINOMIAL COEFFICIENTS **/
946
/*******************************************************************/
947
GEN
948
binomialuu(ulong n, ulong k)
949
{
950
pari_sp ltop = avma;
951
GEN z;
952
if (k > n) return gen_0;
953
k = minuu(k,n-k);
954
if (!k) return gen_1;
955
if (k == 1) return utoipos(n);
956
z = diviiexact(mulu_interval(n-k+1, n), mulu_interval(2UL, k));
957
return gerepileuptoint(ltop,z);
958
}
959
960
GEN
961
binomial(GEN n, long k)
962
{
963
long i, prec;
964
pari_sp av;
965
GEN y;
966
967
if (k <= 1)
968
{
969
if (is_noncalc_t(typ(n))) pari_err_TYPE("binomial",n);
970
if (k < 0) return gen_0;
971
if (k == 0) return gen_1;
972
return gcopy(n);
973
}
974
av = avma;
975
if (typ(n) == t_INT)
976
{
977
if (signe(n) > 0)
978
{
979
GEN z = subiu(n,k);
980
if (cmpis(z,k) < 0)
981
{
982
k = itos(z); set_avma(av);
983
if (k <= 1)
984
{
985
if (k < 0) return gen_0;
986
if (k == 0) return gen_1;
987
return icopy(n);
988
}
989
}
990
}
991
/* k > 1 */
992
if (lgefint(n) == 3 && signe(n) > 0)
993
{
994
y = binomialuu(itou(n),(ulong)k);
995
return gerepileupto(av, y);
996
}
997
else
998
{
999
y = cgetg(k+1,t_VEC);
1000
for (i=1; i<=k; i++) gel(y,i) = subiu(n,i-1);
1001
y = ZV_prod(y);
1002
}
1003
y = diviiexact(y, mpfact(k));
1004
return gerepileuptoint(av, y);
1005
}
1006
1007
prec = precision(n);
1008
if (prec && k > 200 + 0.8*prec2nbits(prec)) {
1009
GEN A = mpfactr(k, prec), B = ggamma(gsubgs(n,k-1), prec);
1010
return gerepileupto(av, gdiv(ggamma(gaddgs(n,1), prec), gmul(A,B)));
1011
}
1012
1013
y = cgetg(k+1,t_VEC);
1014
for (i=1; i<=k; i++) gel(y,i) = gsubgs(n,i-1);
1015
return gerepileupto(av, gdiv(RgV_prod(y), mpfact(k)));
1016
}
1017
1018
GEN
1019
binomial0(GEN x, GEN k)
1020
{
1021
if (!k)
1022
{
1023
if (typ(x) != t_INT || signe(x) < 0) pari_err_TYPE("binomial", x);
1024
return vecbinomial(itos(x));
1025
}
1026
if (typ(k) != t_INT) pari_err_TYPE("binomial", k);
1027
return binomial(x, itos(k));
1028
}
1029
1030
/* Assume n >= 0, return bin, bin[k+1] = binomial(n, k) */
1031
GEN
1032
vecbinomial(long n)
1033
{
1034
long d, k;
1035
GEN C;
1036
if (!n) return mkvec(gen_1);
1037
C = cgetg(n+2, t_VEC) + 1; /* C[k] = binomial(n, k) */
1038
gel(C,0) = gen_1;
1039
gel(C,1) = utoipos(n); d = (n + 1) >> 1;
1040
for (k=2; k <= d; k++)
1041
{
1042
pari_sp av = avma;
1043
gel(C,k) = gerepileuptoint(av, diviuexact(mului(n-k+1, gel(C,k-1)), k));
1044
}
1045
for ( ; k <= n; k++) gel(C,k) = gel(C,n-k);
1046
return C - 1;
1047
}
1048
1049
/********************************************************************/
1050
/** STIRLING NUMBERS **/
1051
/********************************************************************/
1052
/* Stirling number of the 2nd kind. The number of ways of partitioning
1053
a set of n elements into m nonempty subsets. */
1054
GEN
1055
stirling2(ulong n, ulong m)
1056
{
1057
pari_sp av = avma;
1058
GEN s, bmk;
1059
ulong k;
1060
if (n==0) return (m == 0)? gen_1: gen_0;
1061
if (m > n || m == 0) return gen_0;
1062
if (m==n) return gen_1;
1063
/* k = 0 */
1064
bmk = gen_1; s = powuu(m, n);
1065
for (k = 1; k <= ((m-1)>>1); ++k)
1066
{ /* bmk = binomial(m, k) */
1067
GEN c, kn, mkn;
1068
bmk = diviuexact(mului(m-k+1, bmk), k);
1069
kn = powuu(k, n); mkn = powuu(m-k, n);
1070
c = odd(m)? subii(mkn,kn): addii(mkn,kn);
1071
c = mulii(bmk, c);
1072
s = odd(k)? subii(s, c): addii(s, c);
1073
if (gc_needed(av,2))
1074
{
1075
if(DEBUGMEM>1) pari_warn(warnmem,"stirling2");
1076
gerepileall(av, 2, &s, &bmk);
1077
}
1078
}
1079
/* k = m/2 */
1080
if (!odd(m))
1081
{
1082
GEN c;
1083
bmk = diviuexact(mului(k+1, bmk), k);
1084
c = mulii(bmk, powuu(k,n));
1085
s = odd(k)? subii(s, c): addii(s, c);
1086
}
1087
return gerepileuptoint(av, diviiexact(s, mpfact(m)));
1088
}
1089
1090
/* Stirling number of the first kind. Up to the sign, the number of
1091
permutations of n symbols which have exactly m cycles. */
1092
GEN
1093
stirling1(ulong n, ulong m)
1094
{
1095
pari_sp ltop=avma;
1096
ulong k;
1097
GEN s, t;
1098
if (n < m) return gen_0;
1099
else if (n==m) return gen_1;
1100
/* t = binomial(n-1+k, m-1) * binomial(2n-m, n-m-k) */
1101
/* k = n-m > 0 */
1102
t = binomialuu(2*n-m-1, m-1);
1103
s = mulii(t, stirling2(2*(n-m), n-m));
1104
if (odd(n-m)) togglesign(s);
1105
for (k = n-m-1; k > 0; --k)
1106
{
1107
GEN c;
1108
t = diviuuexact(muluui(n-m+k+1, n+k+1, t), n+k, n-m-k);
1109
c = mulii(t, stirling2(n-m+k, k));
1110
s = odd(k)? subii(s, c): addii(s, c);
1111
if ((k & 0x1f) == 0) {
1112
t = gerepileuptoint(ltop, t);
1113
s = gerepileuptoint(avma, s);
1114
}
1115
}
1116
return gerepileuptoint(ltop, s);
1117
}
1118
1119
GEN
1120
stirling(long n, long m, long flag)
1121
{
1122
if (n < 0) pari_err_DOMAIN("stirling", "n", "<", gen_0, stoi(n));
1123
if (m < 0) pari_err_DOMAIN("stirling", "m", "<", gen_0, stoi(m));
1124
switch (flag)
1125
{
1126
case 1: return stirling1((ulong)n,(ulong)m);
1127
case 2: return stirling2((ulong)n,(ulong)m);
1128
default: pari_err_FLAG("stirling");
1129
}
1130
return NULL; /*LCOV_EXCL_LINE*/
1131
}
1132
1133
/*******************************************************************/
1134
/** **/
1135
/** RECIPROCAL POLYNOMIAL **/
1136
/** **/
1137
/*******************************************************************/
1138
/* return coefficients s.t x = x_0 X^n + ... + x_n */
1139
GEN
1140
polrecip(GEN x)
1141
{
1142
long tx = typ(x);
1143
if (is_scalar_t(tx)) return gcopy(x);
1144
if (tx != t_POL) pari_err_TYPE("polrecip",x);
1145
return RgX_recip(x);
1146
}
1147
1148
/********************************************************************/
1149
/** **/
1150
/** POLYNOMIAL INTERPOLATION **/
1151
/** **/
1152
/********************************************************************/
1153
/* given complex roots L[i], i <= n of some monic T in C[X], return
1154
* the T'(L[i]), computed stably via products of differences */
1155
GEN
1156
vandermondeinverseinit(GEN L)
1157
{
1158
long i, j, l = lg(L);
1159
GEN V = cgetg(l, t_VEC);
1160
for (i = 1; i < l; i++)
1161
{
1162
pari_sp av = avma;
1163
GEN W = cgetg(l-1,t_VEC);
1164
long k = 1;
1165
for (j = 1; j < l; j++)
1166
if (i != j) gel(W, k++) = gsub(gel(L,i), gel(L,j));
1167
gel(V,i) = gerepileupto(av, RgV_prod(W));
1168
}
1169
return V;
1170
}
1171
1172
/* Compute the inverse of the van der Monde matrix of T multiplied by den */
1173
GEN
1174
vandermondeinverse(GEN L, GEN T, GEN den, GEN prep)
1175
{
1176
pari_sp av = avma;
1177
long i, n = lg(L)-1;
1178
GEN M = cgetg(n+1, t_MAT);
1179
1180
if (!prep) prep = vandermondeinverseinit(L);
1181
if (den && equali1(den)) den = NULL;
1182
for (i = 1; i <= n; i++)
1183
{
1184
GEN d = gel(prep,i);
1185
GEN P = RgX_Rg_mul(RgX_div_by_X_x(T, gel(L,i), NULL),
1186
den? gdiv(den,d): ginv(d));
1187
gel(M,i) = RgX_to_RgC(P,n);
1188
}
1189
return gerepilecopy(av, M);
1190
}
1191
1192
static GEN
1193
RgV_polint_fast(GEN X, GEN Y, long v)
1194
{
1195
GEN p, pol;
1196
long t, pa;
1197
if (X) t = RgV_type2(X,Y, &p, &pol, &pa);
1198
else t = Rg_type(Y, &p, &pol, &pa);
1199
if (t != t_INTMOD) return NULL;
1200
Y = RgC_to_FpC(Y, p);
1201
X = X? RgC_to_FpC(X, p): identity_ZV(lg(Y)-1);
1202
return FpX_to_mod(FpV_polint(X, Y, p, v), p);
1203
}
1204
/* allow X = NULL for [1,...,n] */
1205
GEN
1206
RgV_polint(GEN X, GEN Y, long v)
1207
{
1208
pari_sp av0 = avma, av;
1209
GEN Q, L, P = NULL;
1210
long i, l = lg(Y);
1211
if ((Q = RgV_polint_fast(X,Y,v))) return Q;
1212
if (!X) X = identity_ZV(l-1);
1213
L = vandermondeinverseinit(X);
1214
Q = roots_to_pol(X, v); av = avma;
1215
for (i=1; i<l; i++)
1216
{
1217
GEN T, dP;
1218
if (gequal0(gel(Y,i))) continue;
1219
T = RgX_div_by_X_x(Q, gel(X,i), NULL);
1220
dP = RgX_Rg_mul(T, gmul(gel(Y,i), ginv(gel(L,i))));
1221
P = P? RgX_add(P, dP): dP;
1222
if (gc_needed(av,2))
1223
{
1224
if (DEBUGMEM>1) pari_warn(warnmem,"RgV_polint i = %ld/%ld", i, l-1);
1225
P = gerepileupto(av, P);
1226
}
1227
}
1228
if (!P) { set_avma(av); return zeropol(v); }
1229
return gerepileupto(av0, P);
1230
}
1231
static int
1232
inC(GEN x)
1233
{
1234
switch(typ(x)) {
1235
case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: case t_QUAD: return 1;
1236
default: return 0;
1237
}
1238
}
1239
static long
1240
check_dy(GEN X, GEN x, long n)
1241
{
1242
GEN D = NULL;
1243
long i, ns = 0;
1244
if (!inC(x)) return -1;
1245
for (i = 0; i < n; i++)
1246
{
1247
GEN t = gsub(x, gel(X,i));
1248
if (!inC(t)) return -1;
1249
t = gabs(t, DEFAULTPREC);
1250
if (!D || gcmp(t,D) < 0) { ns = i; D = t; }
1251
}
1252
/* X[ns] is closest to x */
1253
return ns;
1254
}
1255
/* X,Y are "spec" GEN vectors with n > 0 components ( at X[0], ... X[n-1] ) */
1256
GEN
1257
polintspec(GEN X, GEN Y, GEN x, long n, long *pe)
1258
{
1259
long i, m, ns;
1260
pari_sp av = avma, av2;
1261
GEN y, c, d, dy = NULL; /* gcc -Wall */
1262
1263
if (pe) *pe = -HIGHEXPOBIT;
1264
if (n == 1) return gmul(gel(Y,0), Rg_get_1(x));
1265
if (!X) X = identity_ZV(n) + 1;
1266
av2 = avma;
1267
ns = check_dy(X, x, n); if (ns < 0) { pe = NULL; ns = 0; }
1268
c = cgetg(n+1, t_VEC);
1269
d = cgetg(n+1, t_VEC); for (i=0; i<n; i++) gel(c,i+1) = gel(d,i+1) = gel(Y,i);
1270
y = gel(d,ns+1);
1271
/* divided differences */
1272
for (m = 1; m < n; m++)
1273
{
1274
for (i = 0; i < n-m; i++)
1275
{
1276
GEN ho = gsub(gel(X,i),x), hp = gsub(gel(X,i+m),x), den = gsub(ho,hp);
1277
if (gequal0(den))
1278
{
1279
char *x1 = stack_sprintf("X[%ld]", i+1);
1280
char *x2 = stack_sprintf("X[%ld]", i+m+1);
1281
pari_err_DOMAIN("polinterpolate",x1,"=",strtoGENstr(x2), X);
1282
}
1283
den = gdiv(gsub(gel(c,i+2),gel(d,i+1)), den);
1284
gel(c,i+1) = gmul(ho,den);
1285
gel(d,i+1) = gmul(hp,den);
1286
}
1287
dy = (2*ns < n-m)? gel(c,ns+1): gel(d,ns--);
1288
y = gadd(y,dy);
1289
if (gc_needed(av2,2))
1290
{
1291
if (DEBUGMEM>1) pari_warn(warnmem,"polint, %ld/%ld",m,n-1);
1292
gerepileall(av2, 4, &y, &c, &d, &dy);
1293
}
1294
}
1295
if (pe && inC(dy)) *pe = gexpo(dy);
1296
return gerepileupto(av, y);
1297
}
1298
1299
GEN
1300
polint_i(GEN X, GEN Y, GEN t, long *pe)
1301
{
1302
long lx = lg(X), vt;
1303
1304
if (! is_vec_t(typ(X))) pari_err_TYPE("polinterpolate",X);
1305
if (Y)
1306
{
1307
if (! is_vec_t(typ(Y))) pari_err_TYPE("polinterpolate",Y);
1308
if (lx != lg(Y)) pari_err_DIM("polinterpolate");
1309
}
1310
else
1311
{
1312
Y = X;
1313
X = NULL;
1314
}
1315
if (pe) *pe = -HIGHEXPOBIT;
1316
vt = t? gvar(t): 0;
1317
if (vt != NO_VARIABLE)
1318
{ /* formal interpolation */
1319
pari_sp av;
1320
long v0, vY = gvar(Y);
1321
GEN P;
1322
if (X) vY = varnmax(vY, gvar(X));
1323
/* shortcut */
1324
if (varncmp(vY, vt) > 0 && (!t || gequalX(t))) return RgV_polint(X, Y, vt);
1325
av = avma;
1326
/* first interpolate in high priority variable, then substitute t */
1327
v0 = fetch_var_higher();
1328
P = RgV_polint(X, Y, v0);
1329
P = gsubst(P, v0, t? t: pol_x(0));
1330
(void)delete_var();
1331
return gerepileupto(av, P);
1332
}
1333
/* numerical interpolation */
1334
if (lx == 1) return Rg_get_0(t);
1335
return polintspec(X? X+1: NULL,Y+1,t,lx-1, pe);
1336
}
1337
GEN
1338
polint(GEN X, GEN Y, GEN t, GEN *pe)
1339
{
1340
long e;
1341
GEN p = polint_i(X, Y, t, &e);
1342
if (pe) *pe = stoi(e);
1343
return p;
1344
}
1345
1346
/********************************************************************/
1347
/** **/
1348
/** MODREVERSE **/
1349
/** **/
1350
/********************************************************************/
1351
static void
1352
err_reverse(GEN x, GEN T)
1353
{
1354
pari_err_DOMAIN("modreverse","deg(minpoly(z))", "<", stoi(degpol(T)),
1355
mkpolmod(x,T));
1356
}
1357
1358
/* return y such that Mod(y, charpoly(Mod(a,T)) = Mod(a,T) */
1359
GEN
1360
RgXQ_reverse(GEN a, GEN T)
1361
{
1362
pari_sp av = avma;
1363
long n = degpol(T);
1364
GEN y;
1365
1366
if (n <= 1) {
1367
if (n <= 0) return gcopy(a);
1368
return gerepileupto(av, gneg(gdiv(gel(T,2), gel(T,3))));
1369
}
1370
if (typ(a) != t_POL || !signe(a)) err_reverse(a,T);
1371
y = RgXV_to_RgM(RgXQ_powers(a,n-1,T), n);
1372
y = RgM_solve(y, col_ei(n, 2));
1373
if (!y) err_reverse(a,T);
1374
return gerepilecopy(av, RgV_to_RgX(y, varn(T)));
1375
}
1376
GEN
1377
QXQ_reverse(GEN a, GEN T)
1378
{
1379
pari_sp av = avma;
1380
long n = degpol(T);
1381
GEN y;
1382
1383
if (n <= 1) {
1384
if (n <= 0) return gcopy(a);
1385
return gerepileupto(av, gneg(gdiv(gel(T,2), gel(T,3))));
1386
}
1387
if (typ(a) != t_POL || !signe(a)) err_reverse(a,T);
1388
if (gequalX(a)) return gcopy(a);
1389
y = RgXV_to_RgM(QXQ_powers(a,n-1,T), n);
1390
y = QM_gauss(y, col_ei(n, 2));
1391
if (!y) err_reverse(a,T);
1392
return gerepilecopy(av, RgV_to_RgX(y, varn(T)));
1393
}
1394
1395
GEN
1396
modreverse(GEN x)
1397
{
1398
long v, n;
1399
GEN T, a;
1400
1401
if (typ(x)!=t_POLMOD) pari_err_TYPE("modreverse",x);
1402
T = gel(x,1); n = degpol(T); if (n <= 0) return gcopy(x);
1403
a = gel(x,2);
1404
v = varn(T);
1405
retmkpolmod(RgXQ_reverse(a, T),
1406
(n==1)? gsub(pol_x(v), a): RgXQ_charpoly(a, T, v));
1407
}
1408
1409
/********************************************************************/
1410
/** **/
1411
/** MERGESORT **/
1412
/** **/
1413
/********************************************************************/
1414
static int
1415
cmp_small(GEN x, GEN y) {
1416
long a = (long)x, b = (long)y;
1417
return a>b? 1: (a<b? -1: 0);
1418
}
1419
1420
static int
1421
veccmp(void *data, GEN x, GEN y)
1422
{
1423
GEN k = (GEN)data;
1424
long i, s, lk = lg(k), lx = minss(lg(x), lg(y));
1425
1426
if (!is_vec_t(typ(x))) pari_err_TYPE("lexicographic vecsort",x);
1427
if (!is_vec_t(typ(y))) pari_err_TYPE("lexicographic vecsort",y);
1428
for (i=1; i<lk; i++)
1429
{
1430
long c = k[i];
1431
if (c >= lx)
1432
pari_err_TYPE("lexicographic vecsort, index too large", stoi(c));
1433
s = lexcmp(gel(x,c), gel(y,c));
1434
if (s) return s;
1435
}
1436
return 0;
1437
}
1438
1439
/* return permutation sorting v[1..n], removing duplicates. Assume n > 0 */
1440
static GEN
1441
gen_sortspec_uniq(GEN v, long n, void *E, int (*cmp)(void*,GEN,GEN))
1442
{
1443
pari_sp av;
1444
long NX, nx, ny, m, ix, iy, i;
1445
GEN x, y, w, W;
1446
int s;
1447
switch(n)
1448
{
1449
case 1: return mkvecsmall(1);
1450
case 2:
1451
s = cmp(E,gel(v,1),gel(v,2));
1452
if (s < 0) return mkvecsmall2(1,2);
1453
else if (s > 0) return mkvecsmall2(2,1);
1454
return mkvecsmall(1);
1455
case 3:
1456
s = cmp(E,gel(v,1),gel(v,2));
1457
if (s < 0) {
1458
s = cmp(E,gel(v,2),gel(v,3));
1459
if (s < 0) return mkvecsmall3(1,2,3);
1460
else if (s == 0) return mkvecsmall2(1,2);
1461
s = cmp(E,gel(v,1),gel(v,3));
1462
if (s < 0) return mkvecsmall3(1,3,2);
1463
else if (s > 0) return mkvecsmall3(3,1,2);
1464
return mkvecsmall2(1,2);
1465
} else if (s > 0) {
1466
s = cmp(E,gel(v,1),gel(v,3));
1467
if (s < 0) return mkvecsmall3(2,1,3);
1468
else if (s == 0) return mkvecsmall2(2,1);
1469
s = cmp(E,gel(v,2),gel(v,3));
1470
if (s < 0) return mkvecsmall3(2,3,1);
1471
else if (s > 0) return mkvecsmall3(3,2,1);
1472
return mkvecsmall2(2,1);
1473
} else {
1474
s = cmp(E,gel(v,1),gel(v,3));
1475
if (s < 0) return mkvecsmall2(1,3);
1476
else if (s == 0) return mkvecsmall(1);
1477
return mkvecsmall2(3,1);
1478
}
1479
}
1480
NX = nx = n>>1; ny = n-nx;
1481
av = avma;
1482
x = gen_sortspec_uniq(v, nx,E,cmp); nx = lg(x)-1;
1483
y = gen_sortspec_uniq(v+NX,ny,E,cmp); ny = lg(y)-1;
1484
w = cgetg(n+1, t_VECSMALL);
1485
m = ix = iy = 1;
1486
while (ix<=nx && iy<=ny)
1487
{
1488
s = cmp(E, gel(v,x[ix]), gel(v,y[iy]+NX));
1489
if (s < 0)
1490
w[m++] = x[ix++];
1491
else if (s > 0)
1492
w[m++] = y[iy++]+NX;
1493
else {
1494
w[m++] = x[ix++];
1495
iy++;
1496
}
1497
}
1498
while (ix<=nx) w[m++] = x[ix++];
1499
while (iy<=ny) w[m++] = y[iy++]+NX;
1500
set_avma(av);
1501
W = cgetg(m, t_VECSMALL);
1502
for (i = 1; i < m; i++) W[i] = w[i];
1503
return W;
1504
}
1505
1506
/* return permutation sorting v[1..n]. Assume n > 0 */
1507
static GEN
1508
gen_sortspec(GEN v, long n, void *E, int (*cmp)(void*,GEN,GEN))
1509
{
1510
long nx, ny, m, ix, iy;
1511
GEN x, y, w;
1512
switch(n)
1513
{
1514
case 1:
1515
(void)cmp(E,gel(v,1),gel(v,1)); /* check for type error */
1516
return mkvecsmall(1);
1517
case 2:
1518
return cmp(E,gel(v,1),gel(v,2)) <= 0? mkvecsmall2(1,2)
1519
: mkvecsmall2(2,1);
1520
case 3:
1521
if (cmp(E,gel(v,1),gel(v,2)) <= 0) {
1522
if (cmp(E,gel(v,2),gel(v,3)) <= 0) return mkvecsmall3(1,2,3);
1523
return (cmp(E,gel(v,1),gel(v,3)) <= 0)? mkvecsmall3(1,3,2)
1524
: mkvecsmall3(3,1,2);
1525
} else {
1526
if (cmp(E,gel(v,1),gel(v,3)) <= 0) return mkvecsmall3(2,1,3);
1527
return (cmp(E,gel(v,2),gel(v,3)) <= 0)? mkvecsmall3(2,3,1)
1528
: mkvecsmall3(3,2,1);
1529
}
1530
}
1531
nx = n>>1; ny = n-nx;
1532
w = cgetg(n+1,t_VECSMALL);
1533
x = gen_sortspec(v, nx,E,cmp);
1534
y = gen_sortspec(v+nx,ny,E,cmp);
1535
m = ix = iy = 1;
1536
while (ix<=nx && iy<=ny)
1537
if (cmp(E, gel(v,x[ix]), gel(v,y[iy]+nx))<=0)
1538
w[m++] = x[ix++];
1539
else
1540
w[m++] = y[iy++]+nx;
1541
while (ix<=nx) w[m++] = x[ix++];
1542
while (iy<=ny) w[m++] = y[iy++]+nx;
1543
set_avma((pari_sp)w); return w;
1544
}
1545
1546
static void
1547
init_sort(GEN *x, long *tx, long *lx)
1548
{
1549
*tx = typ(*x);
1550
if (*tx == t_LIST)
1551
{
1552
if (list_typ(*x)!=t_LIST_RAW) pari_err_TYPE("sort",*x);
1553
*x = list_data(*x);
1554
*lx = *x? lg(*x): 1;
1555
} else {
1556
if (!is_matvec_t(*tx) && *tx != t_VECSMALL) pari_err_TYPE("gen_sort",*x);
1557
*lx = lg(*x);
1558
}
1559
}
1560
1561
/* (x o y)[1..lx-1], destroy y */
1562
INLINE GEN
1563
sort_extract(GEN x, GEN y, long tx, long lx)
1564
{
1565
long i;
1566
switch(tx)
1567
{
1568
case t_VECSMALL:
1569
for (i=1; i<lx; i++) y[i] = x[y[i]];
1570
break;
1571
case t_LIST:
1572
settyp(y,t_VEC);
1573
for (i=1; i<lx; i++) gel(y,i) = gel(x,y[i]);
1574
return gtolist(y);
1575
default:
1576
settyp(y,tx);
1577
for (i=1; i<lx; i++) gel(y,i) = gcopy(gel(x,y[i]));
1578
}
1579
return y;
1580
}
1581
1582
static GEN
1583
triv_sort(long tx) { return tx == t_LIST? mklist(): cgetg(1, tx); }
1584
/* Sort the vector x, using cmp to compare entries. */
1585
GEN
1586
gen_sort_uniq(GEN x, void *E, int (*cmp)(void*,GEN,GEN))
1587
{
1588
long tx, lx;
1589
GEN y;
1590
1591
init_sort(&x, &tx, &lx);
1592
if (lx==1) return triv_sort(tx);
1593
y = gen_sortspec_uniq(x,lx-1,E,cmp);
1594
return sort_extract(x, y, tx, lg(y)); /* lg(y) <= lx */
1595
}
1596
/* Sort the vector x, using cmp to compare entries. */
1597
GEN
1598
gen_sort(GEN x, void *E, int (*cmp)(void*,GEN,GEN))
1599
{
1600
long tx, lx;
1601
GEN y;
1602
1603
init_sort(&x, &tx, &lx);
1604
if (lx==1) return triv_sort(tx);
1605
y = gen_sortspec(x,lx-1,E,cmp);
1606
return sort_extract(x, y, tx, lx);
1607
}
1608
/* indirect sort: return the permutation that would sort x */
1609
GEN
1610
gen_indexsort_uniq(GEN x, void *E, int (*cmp)(void*,GEN,GEN))
1611
{
1612
long tx, lx;
1613
init_sort(&x, &tx, &lx);
1614
if (lx==1) return cgetg(1, t_VECSMALL);
1615
return gen_sortspec_uniq(x,lx-1,E,cmp);
1616
}
1617
/* indirect sort: return the permutation that would sort x */
1618
GEN
1619
gen_indexsort(GEN x, void *E, int (*cmp)(void*,GEN,GEN))
1620
{
1621
long tx, lx;
1622
init_sort(&x, &tx, &lx);
1623
if (lx==1) return cgetg(1, t_VECSMALL);
1624
return gen_sortspec(x,lx-1,E,cmp);
1625
}
1626
1627
/* Sort the vector x in place, using cmp to compare entries */
1628
void
1629
gen_sort_inplace(GEN x, void *E, int (*cmp)(void*,GEN,GEN), GEN *perm)
1630
{
1631
long tx, lx, i;
1632
pari_sp av = avma;
1633
GEN y;
1634
1635
init_sort(&x, &tx, &lx);
1636
if (lx<=2)
1637
{
1638
if (perm) *perm = lx == 1? cgetg(1, t_VECSMALL): mkvecsmall(1);
1639
return;
1640
}
1641
y = gen_sortspec(x,lx-1, E, cmp);
1642
if (perm)
1643
{
1644
GEN z = new_chunk(lx);
1645
for (i=1; i<lx; i++) gel(z,i) = gel(x,y[i]);
1646
for (i=1; i<lx; i++) gel(x,i) = gel(z,i);
1647
*perm = y;
1648
set_avma((pari_sp)y);
1649
} else {
1650
for (i=1; i<lx; i++) gel(y,i) = gel(x,y[i]);
1651
for (i=1; i<lx; i++) gel(x,i) = gel(y,i);
1652
set_avma(av);
1653
}
1654
}
1655
GEN
1656
gen_sort_shallow(GEN x, void *E, int (*cmp)(void*,GEN,GEN))
1657
{
1658
long tx, lx, i;
1659
pari_sp av;
1660
GEN y, z;
1661
1662
init_sort(&x, &tx, &lx);
1663
if (lx<=2) return x;
1664
z = cgetg(lx, tx); av = avma;
1665
y = gen_sortspec(x,lx-1, E, cmp);
1666
for (i=1; i<lx; i++) gel(z,i) = gel(x,y[i]);
1667
return gc_const(av, z);
1668
}
1669
1670
static int
1671
closurecmp(void *data, GEN x, GEN y)
1672
{
1673
pari_sp av = avma;
1674
long s = gsigne(closure_callgen2((GEN)data, x,y));
1675
set_avma(av); return s;
1676
}
1677
static void
1678
check_positive_entries(GEN k)
1679
{
1680
long i, l = lg(k);
1681
for (i=1; i<l; i++)
1682
if (k[i] <= 0) pari_err_DOMAIN("sort_function", "index", "<", gen_0, stoi(k[i]));
1683
}
1684
1685
typedef int (*CMP_FUN)(void*,GEN,GEN);
1686
/* return NULL if t_CLOSURE k is a "key" (arity 1) and not a sorting func */
1687
static CMP_FUN
1688
sort_function(void **E, GEN x, GEN k)
1689
{
1690
int (*cmp)(GEN,GEN) = &lexcmp;
1691
long tx = typ(x);
1692
if (!k)
1693
{
1694
*E = (void*)((typ(x) == t_VECSMALL)? cmp_small: cmp);
1695
return &cmp_nodata;
1696
}
1697
if (tx == t_VECSMALL) pari_err_TYPE("sort_function", x);
1698
switch(typ(k))
1699
{
1700
case t_INT: k = mkvecsmall(itos(k)); break;
1701
case t_VEC: case t_COL: k = ZV_to_zv(k); break;
1702
case t_VECSMALL: break;
1703
case t_CLOSURE:
1704
if (closure_is_variadic(k))
1705
pari_err_TYPE("sort_function, variadic cmpf",k);
1706
*E = (void*)k;
1707
switch(closure_arity(k))
1708
{
1709
case 1: return NULL; /* wrt key */
1710
case 2: return &closurecmp;
1711
default: pari_err_TYPE("sort_function, cmpf arity != 1, 2",k);
1712
}
1713
default: pari_err_TYPE("sort_function",k);
1714
}
1715
check_positive_entries(k);
1716
*E = (void*)k; return &veccmp;
1717
}
1718
1719
#define cmp_IND 1
1720
#define cmp_LEX 2 /* FIXME: backward compatibility, ignored */
1721
#define cmp_REV 4
1722
#define cmp_UNIQ 8
1723
GEN
1724
vecsort0(GEN x, GEN k, long flag)
1725
{
1726
void *E;
1727
int (*CMP)(void*,GEN,GEN) = sort_function(&E, x, k);
1728
1729
if (flag < 0 || flag > (cmp_REV|cmp_LEX|cmp_IND|cmp_UNIQ))
1730
pari_err_FLAG("vecsort");
1731
if (!CMP)
1732
{ /* wrt key: precompute all values, O(n) calls instead of O(n log n) */
1733
pari_sp av = avma;
1734
GEN v, y;
1735
long i, tx, lx;
1736
init_sort(&x, &tx, &lx);
1737
if (lx == 1) return flag&cmp_IND? cgetg(1,t_VECSMALL): triv_sort(tx);
1738
v = cgetg(lx, t_VEC);
1739
for (i = 1; i < lx; i++) gel(v,i) = closure_callgen1(k, gel(x,i));
1740
y = vecsort0(v, NULL, flag | cmp_IND);
1741
y = flag&cmp_IND? y: sort_extract(x, y, tx, lg(y));
1742
return gerepileupto(av, y);
1743
}
1744
if (flag&cmp_UNIQ)
1745
x = flag&cmp_IND? gen_indexsort_uniq(x, E, CMP): gen_sort_uniq(x, E, CMP);
1746
else
1747
x = flag&cmp_IND? gen_indexsort(x, E, CMP): gen_sort(x, E, CMP);
1748
if (flag & cmp_REV)
1749
{ /* reverse order */
1750
GEN y = x;
1751
if (typ(x)==t_LIST) { y = list_data(x); if (!y) return x; }
1752
vecreverse_inplace(y);
1753
}
1754
return x;
1755
}
1756
1757
GEN
1758
indexsort(GEN x) { return gen_indexsort(x, (void*)&gcmp, cmp_nodata); }
1759
GEN
1760
indexlexsort(GEN x) { return gen_indexsort(x, (void*)&lexcmp, cmp_nodata); }
1761
GEN
1762
indexvecsort(GEN x, GEN k)
1763
{
1764
if (typ(k) != t_VECSMALL) pari_err_TYPE("vecsort",k);
1765
return gen_indexsort(x, (void*)k, &veccmp);
1766
}
1767
1768
GEN
1769
sort(GEN x) { return gen_sort(x, (void*)gcmp, cmp_nodata); }
1770
GEN
1771
lexsort(GEN x) { return gen_sort(x, (void*)lexcmp, cmp_nodata); }
1772
GEN
1773
vecsort(GEN x, GEN k)
1774
{
1775
if (typ(k) != t_VECSMALL) pari_err_TYPE("vecsort",k);
1776
return gen_sort(x, (void*)k, &veccmp);
1777
}
1778
/* adapted from gen_search; don't export: keys of T[i] should be precomputed */
1779
static long
1780
key_search(GEN T, GEN x, GEN code)
1781
{
1782
long u = lg(T)-1, i, l, s;
1783
1784
if (!u) return 0;
1785
l = 1; x = closure_callgen1(code, x);
1786
do
1787
{
1788
i = (l+u)>>1; s = lexcmp(x, closure_callgen1(code, gel(T,i)));
1789
if (!s) return i;
1790
if (s<0) u=i-1; else l=i+1;
1791
} while (u>=l);
1792
return 0;
1793
}
1794
long
1795
vecsearch(GEN v, GEN x, GEN k)
1796
{
1797
pari_sp av = avma;
1798
void *E;
1799
int (*CMP)(void*,GEN,GEN) = sort_function(&E, v, k);
1800
long r, tv = typ(v);
1801
if (tv == t_VECSMALL)
1802
x = (GEN)itos(x);
1803
else if (!is_matvec_t(tv)) pari_err_TYPE("vecsearch", v);
1804
r = CMP? gen_search(v, x, E, CMP): key_search(v, x, k);
1805
return gc_long(av, r < 0? 0: r);
1806
}
1807
1808
GEN
1809
ZV_indexsort(GEN L) { return gen_indexsort(L, (void*)&cmpii, &cmp_nodata); }
1810
GEN
1811
ZV_sort(GEN L) { return gen_sort(L, (void*)&cmpii, &cmp_nodata); }
1812
GEN
1813
ZV_sort_uniq(GEN L) { return gen_sort_uniq(L, (void*)&cmpii, &cmp_nodata); }
1814
void
1815
ZV_sort_inplace(GEN L) { gen_sort_inplace(L, (void*)&cmpii, &cmp_nodata,NULL); }
1816
1817
GEN
1818
vec_equiv(GEN F)
1819
{
1820
pari_sp av = avma;
1821
long j, k, L = lg(F);
1822
GEN w = cgetg(L, t_VEC);
1823
GEN perm = gen_indexsort(F, (void*)&cmp_universal, cmp_nodata);
1824
for (j = k = 1; j < L;)
1825
{
1826
GEN v = cgetg(L, t_VECSMALL);
1827
long l = 1, o = perm[j];
1828
v[l++] = o;
1829
for (j++; j < L; v[l++] = perm[j++])
1830
if (!gequal(gel(F,o), gel(F, perm[j]))) break;
1831
setlg(v, l); gel(w, k++) = v;
1832
}
1833
setlg(w, k); return gerepilecopy(av,w);
1834
}
1835
1836
GEN
1837
vec_reduce(GEN v, GEN *pE)
1838
{
1839
GEN E, F, P = gen_indexsort(v, (void*)cmp_universal, cmp_nodata);
1840
long i, m, l;
1841
F = cgetg_copy(v, &l);
1842
*pE = E = cgetg(l, t_VECSMALL);
1843
for (i = m = 1; i < l;)
1844
{
1845
GEN u = gel(v, P[i]);
1846
long k;
1847
for(k = i + 1; k < l; k++)
1848
if (cmp_universal(gel(v, P[k]), u)) break;
1849
E[m] = k - i; gel(F, m) = u; i = k; m++;
1850
}
1851
setlg(F, m);
1852
setlg(E, m); return F;
1853
}
1854
1855
/********************************************************************/
1856
/** SEARCH IN SORTED VECTOR **/
1857
/********************************************************************/
1858
/* index of x in table T, 0 otherwise */
1859
long
1860
tablesearch(GEN T, GEN x, int (*cmp)(GEN,GEN))
1861
{
1862
long l = 1, u = lg(T)-1, i, s;
1863
1864
while (u>=l)
1865
{
1866
i = (l+u)>>1; s = cmp(x, gel(T,i));
1867
if (!s) return i;
1868
if (s<0) u=i-1; else l=i+1;
1869
}
1870
return 0;
1871
}
1872
1873
/* looks if x belongs to the set T and returns the index if yes, 0 if no */
1874
long
1875
gen_search(GEN T, GEN x, void *data, int (*cmp)(void*,GEN,GEN))
1876
{
1877
long u = lg(T)-1, i, l, s;
1878
1879
if (!u) return -1;
1880
l = 1;
1881
do
1882
{
1883
i = (l+u) >> 1; s = cmp(data, x, gel(T,i));
1884
if (!s) return i;
1885
if (s < 0) u = i-1; else l = i+1;
1886
} while (u >= l);
1887
return -((s < 0)? i: i+1);
1888
}
1889
1890
long
1891
ZV_search(GEN x, GEN y) { return tablesearch(x, y, cmpii); }
1892
1893
long
1894
zv_search(GEN T, long x)
1895
{
1896
long l = 1, u = lg(T)-1;
1897
while (u>=l)
1898
{
1899
long i = (l+u)>>1;
1900
if (x < T[i]) u = i-1;
1901
else if (x > T[i]) l = i+1;
1902
else return i;
1903
}
1904
return 0;
1905
}
1906
1907
/********************************************************************/
1908
/** COMPARISON FUNCTIONS **/
1909
/********************************************************************/
1910
int
1911
cmp_nodata(void *data, GEN x, GEN y)
1912
{
1913
int (*cmp)(GEN,GEN)=(int (*)(GEN,GEN)) data;
1914
return cmp(x,y);
1915
}
1916
1917
/* assume x and y come from the same idealprimedec call (uniformizer unique) */
1918
int
1919
cmp_prime_over_p(GEN x, GEN y)
1920
{
1921
long k = pr_get_f(x) - pr_get_f(y); /* diff. between residue degree */
1922
return k? ((k > 0)? 1: -1)
1923
: ZV_cmp(pr_get_gen(x), pr_get_gen(y));
1924
}
1925
1926
int
1927
cmp_prime_ideal(GEN x, GEN y)
1928
{
1929
int k = cmpii(pr_get_p(x), pr_get_p(y));
1930
return k? k: cmp_prime_over_p(x,y);
1931
}
1932
1933
/* assume x and y are t_POL in the same variable whose coeffs can be
1934
* compared (used to sort polynomial factorizations) */
1935
int
1936
gen_cmp_RgX(void *data, GEN x, GEN y)
1937
{
1938
int (*coeff_cmp)(GEN,GEN)=(int(*)(GEN,GEN))data;
1939
long i, lx = lg(x), ly = lg(y);
1940
int fl;
1941
if (lx > ly) return 1;
1942
if (lx < ly) return -1;
1943
for (i=lx-1; i>1; i--)
1944
if ((fl = coeff_cmp(gel(x,i), gel(y,i)))) return fl;
1945
return 0;
1946
}
1947
1948
static int
1949
cmp_RgX_Rg(GEN x, GEN y)
1950
{
1951
long lx = lgpol(x), ly;
1952
if (lx > 1) return 1;
1953
ly = gequal0(y) ? 0:1;
1954
if (lx > ly) return 1;
1955
if (lx < ly) return -1;
1956
if (lx==0) return 0;
1957
return gcmp(gel(x,2), y);
1958
}
1959
int
1960
cmp_RgX(GEN x, GEN y)
1961
{
1962
if (typ(x) == t_POLMOD) x = gel(x,2);
1963
if (typ(y) == t_POLMOD) y = gel(y,2);
1964
if (typ(x) == t_POL) {
1965
if (typ(y) != t_POL) return cmp_RgX_Rg(x, y);
1966
} else {
1967
if (typ(y) != t_POL) return gcmp(x,y);
1968
return - cmp_RgX_Rg(y,x);
1969
}
1970
return gen_cmp_RgX((void*)&gcmp,x,y);
1971
}
1972
1973
int
1974
cmp_Flx(GEN x, GEN y)
1975
{
1976
long i, lx = lg(x), ly = lg(y);
1977
if (lx > ly) return 1;
1978
if (lx < ly) return -1;
1979
for (i=lx-1; i>1; i--)
1980
if (uel(x,i) != uel(y,i)) return uel(x,i)<uel(y,i)? -1: 1;
1981
return 0;
1982
}
1983
/********************************************************************/
1984
/** MERGE & SORT FACTORIZATIONS **/
1985
/********************************************************************/
1986
/* merge fx, fy two factorizations, whose 1st column is sorted in strictly
1987
* increasing order wrt cmp */
1988
GEN
1989
merge_factor(GEN fx, GEN fy, void *data, int (*cmp)(void *,GEN,GEN))
1990
{
1991
GEN x = gel(fx,1), e = gel(fx,2), M, E;
1992
GEN y = gel(fy,1), f = gel(fy,2);
1993
long ix, iy, m, lx = lg(x), ly = lg(y), l = lx+ly-1;
1994
1995
M = cgetg(l, t_COL);
1996
E = cgetg(l, t_COL);
1997
1998
m = ix = iy = 1;
1999
while (ix<lx && iy<ly)
2000
{
2001
int s = cmp(data, gel(x,ix), gel(y,iy));
2002
if (s < 0)
2003
{ gel(M,m) = gel(x,ix); gel(E,m) = gel(e,ix); ix++; }
2004
else if (s == 0)
2005
{
2006
GEN z = gel(x,ix), g = addii(gel(e,ix), gel(f,iy));
2007
iy++; ix++; if (!signe(g)) continue;
2008
gel(M,m) = z; gel(E,m) = g;
2009
}
2010
else
2011
{ gel(M,m) = gel(y,iy); gel(E,m) = gel(f,iy); iy++; }
2012
m++;
2013
}
2014
while (ix<lx) { gel(M,m) = gel(x,ix); gel(E,m) = gel(e,ix); ix++; m++; }
2015
while (iy<ly) { gel(M,m) = gel(y,iy); gel(E,m) = gel(f,iy); iy++; m++; }
2016
setlg(M, m);
2017
setlg(E, m); return mkmat2(M, E);
2018
}
2019
/* merge two sorted vectors, removing duplicates. Shallow */
2020
GEN
2021
merge_sort_uniq(GEN x, GEN y, void *data, int (*cmp)(void *,GEN,GEN))
2022
{
2023
long i, j, k, lx = lg(x), ly = lg(y);
2024
GEN z = cgetg(lx + ly - 1, typ(x));
2025
i = j = k = 1;
2026
while (i<lx && j<ly)
2027
{
2028
int s = cmp(data, gel(x,i), gel(y,j));
2029
if (s < 0)
2030
gel(z,k++) = gel(x,i++);
2031
else if (s > 0)
2032
gel(z,k++) = gel(y,j++);
2033
else
2034
{ gel(z,k++) = gel(x,i++); j++; }
2035
}
2036
while (i<lx) gel(z,k++) = gel(x,i++);
2037
while (j<ly) gel(z,k++) = gel(y,j++);
2038
setlg(z, k); return z;
2039
}
2040
/* in case of equal keys in x,y, take the key from x */
2041
static GEN
2042
ZV_union_shallow_t(GEN x, GEN y, long t)
2043
{
2044
long i, j, k, lx = lg(x), ly = lg(y);
2045
GEN z = cgetg(lx + ly - 1, t);
2046
i = j = k = 1;
2047
while (i<lx && j<ly)
2048
{
2049
int s = cmpii(gel(x,i), gel(y,j));
2050
if (s < 0)
2051
gel(z,k++) = gel(x,i++);
2052
else if (s > 0)
2053
gel(z,k++) = gel(y,j++);
2054
else
2055
{ gel(z,k++) = gel(x,i++); j++; }
2056
}
2057
while (i < lx) gel(z,k++) = gel(x,i++);
2058
while (j < ly) gel(z,k++) = gel(y,j++);
2059
setlg(z, k); return z;
2060
}
2061
GEN
2062
ZV_union_shallow(GEN x, GEN y)
2063
{ return ZV_union_shallow_t(x, y, t_VEC); }
2064
GEN
2065
ZC_union_shallow(GEN x, GEN y)
2066
{ return ZV_union_shallow_t(x, y, t_COL); }
2067
2068
/* sort generic factorization, in place */
2069
GEN
2070
sort_factor(GEN y, void *data, int (*cmp)(void *,GEN,GEN))
2071
{
2072
GEN a, b, A, B, w;
2073
pari_sp av;
2074
long n, i;
2075
2076
a = gel(y,1); n = lg(a); if (n == 1) return y;
2077
b = gel(y,2); av = avma;
2078
A = new_chunk(n);
2079
B = new_chunk(n);
2080
w = gen_sortspec(a, n-1, data, cmp);
2081
for (i=1; i<n; i++) { long k=w[i]; gel(A,i) = gel(a,k); gel(B,i) = gel(b,k); }
2082
for (i=1; i<n; i++) { gel(a,i) = gel(A,i); gel(b,i) = gel(B,i); }
2083
set_avma(av); return y;
2084
}
2085
/* sort polynomial factorization, in place */
2086
GEN
2087
sort_factor_pol(GEN y,int (*cmp)(GEN,GEN))
2088
{
2089
(void)sort_factor(y,(void*)cmp, &gen_cmp_RgX);
2090
return y;
2091
}
2092
2093
/***********************************************************************/
2094
/* */
2095
/* SET OPERATIONS */
2096
/* */
2097
/***********************************************************************/
2098
GEN
2099
gtoset(GEN x)
2100
{
2101
long lx;
2102
if (!x) return cgetg(1, t_VEC);
2103
switch(typ(x))
2104
{
2105
case t_VEC:
2106
case t_COL: lx = lg(x); break;
2107
case t_LIST:
2108
if (list_typ(x)==t_LIST_MAP) return mapdomain(x);
2109
x = list_data(x); lx = x? lg(x): 1; break;
2110
case t_VECSMALL: lx = lg(x); x = zv_to_ZV(x); break;
2111
default: return mkveccopy(x);
2112
}
2113
if (lx==1) return cgetg(1,t_VEC);
2114
x = gen_sort_uniq(x, (void*)&cmp_universal, cmp_nodata);
2115
settyp(x, t_VEC); /* it may be t_COL */
2116
return x;
2117
}
2118
2119
long
2120
setisset(GEN x)
2121
{
2122
long i, lx = lg(x);
2123
2124
if (typ(x) != t_VEC) return 0;
2125
if (lx == 1) return 1;
2126
for (i=1; i<lx-1; i++)
2127
if (cmp_universal(gel(x,i+1), gel(x,i)) <= 0) return 0;
2128
return 1;
2129
}
2130
2131
long
2132
setsearch(GEN T, GEN y, long flag)
2133
{
2134
long i, lx;
2135
switch(typ(T))
2136
{
2137
case t_VEC: lx = lg(T); break;
2138
case t_LIST:
2139
if (list_typ(T) != t_LIST_RAW) pari_err_TYPE("setsearch",T);
2140
T = list_data(T); lx = T? lg(T): 1; break;
2141
default: pari_err_TYPE("setsearch",T);
2142
return 0; /*LCOV_EXCL_LINE*/
2143
}
2144
if (lx==1) return flag? 1: 0;
2145
i = gen_search(T,y,(void*)cmp_universal,cmp_nodata);
2146
if (i > 0) return flag? 0: i;
2147
return flag ? -i: 0;
2148
}
2149
2150
GEN
2151
setunion_i(GEN x, GEN y)
2152
{ return merge_sort_uniq(x,y, (void*)cmp_universal, cmp_nodata); }
2153
2154
GEN
2155
setunion(GEN x, GEN y)
2156
{
2157
pari_sp av = avma;
2158
if (typ(x) != t_VEC) pari_err_TYPE("setunion",x);
2159
if (typ(y) != t_VEC) pari_err_TYPE("setunion",y);
2160
return gerepilecopy(av, setunion_i(x, y));
2161
}
2162
2163
GEN
2164
setintersect(GEN x, GEN y)
2165
{
2166
long ix = 1, iy = 1, iz = 1, lx = lg(x), ly = lg(y);
2167
pari_sp av = avma;
2168
GEN z = cgetg(lx,t_VEC);
2169
if (typ(x) != t_VEC) pari_err_TYPE("setintersect",x);
2170
if (typ(y) != t_VEC) pari_err_TYPE("setintersect",y);
2171
while (ix < lx && iy < ly)
2172
{
2173
int c = cmp_universal(gel(x,ix), gel(y,iy));
2174
if (c < 0) ix++;
2175
else if (c > 0) iy++;
2176
else { gel(z, iz++) = gel(x,ix); ix++; iy++; }
2177
}
2178
setlg(z,iz); return gerepilecopy(av,z);
2179
}
2180
2181
GEN
2182
gen_setminus(GEN A, GEN B, int (*cmp)(GEN,GEN))
2183
{
2184
pari_sp ltop = avma;
2185
long i = 1, j = 1, k = 1, lx = lg(A), ly = lg(B);
2186
GEN diff = cgetg(lx,t_VEC);
2187
while (i < lx && j < ly)
2188
switch ( cmp(gel(A,i),gel(B,j)) )
2189
{
2190
case -1: gel(diff,k++) = gel(A,i++); break;
2191
case 1: j++; break;
2192
case 0: i++; break;
2193
}
2194
while (i < lx) gel(diff,k++) = gel(A,i++);
2195
setlg(diff,k);
2196
return gerepilecopy(ltop,diff);
2197
}
2198
2199
GEN
2200
setminus(GEN x, GEN y)
2201
{
2202
if (typ(x) != t_VEC) pari_err_TYPE("setminus",x);
2203
if (typ(y) != t_VEC) pari_err_TYPE("setminus",y);
2204
return gen_setminus(x,y,cmp_universal);
2205
}
2206
2207
GEN
2208
setbinop(GEN f, GEN x, GEN y)
2209
{
2210
pari_sp av = avma;
2211
long i, j, lx, ly, k = 1;
2212
GEN z;
2213
if (typ(f) != t_CLOSURE || closure_arity(f) != 2 || closure_is_variadic(f))
2214
pari_err_TYPE("setbinop [function needs exactly 2 arguments]",f);
2215
lx = lg(x);
2216
if (typ(x) != t_VEC) pari_err_TYPE("setbinop", x);
2217
if (y == NULL) { /* assume x = y and f symmetric */
2218
z = cgetg((((lx-1)*lx) >> 1) + 1, t_VEC);
2219
for (i = 1; i < lx; i++)
2220
for (j = i; j < lx; j++)
2221
gel(z, k++) = closure_callgen2(f, gel(x,i),gel(x,j));
2222
} else {
2223
ly = lg(y);
2224
if (typ(y) != t_VEC) pari_err_TYPE("setbinop", y);
2225
z = cgetg((lx-1)*(ly-1) + 1, t_VEC);
2226
for (i = 1; i < lx; i++)
2227
for (j = 1; j < ly; j++)
2228
gel(z, k++) = closure_callgen2(f, gel(x,i),gel(y,j));
2229
}
2230
return gerepileupto(av, gtoset(z));
2231
}
2232
2233