Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

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

28495 views
License: GPL3
ubuntu2004
1
/* Copyright (C) 2002 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
/* Original code contributed by: Ralf Stephan ([email protected]).
16
* Updated by Bill Allombert (2014) to use Selberg formula for L
17
* following http://dx.doi.org/10.1112/S1461157012001088
18
*
19
* This program is basically the implementation of the script
20
*
21
* Psi(n, q) = my(a=sqrt(2/3)*Pi/q, b=n-1/24, c=sqrt(b));
22
* (sqrt(q)/(2*sqrt(2)*b*Pi))*(a*cosh(a*c)-(sinh(a*c)/c))
23
* L(n,q)=sqrt(k/3)*sum(l=0,2*k-1,
24
if(((3*l^2+l)/2+n)%k==0,(-1)^l*cos((6*l+1)/(6*k)*Pi)))
25
* part(n) = round(sum(q=1,5 + 0.24*sqrt(n),L(n,q)*Psi(n,q)))
26
*
27
* only faster.
28
*
29
* ------------------------------------------------------------------
30
* The first restriction depends on Pari's maximum precision of floating
31
* point reals, which is 268435454 bits in 2.2.4, since the algorithm needs
32
* high precision exponentials. For that engine, the maximum possible argument
33
* would be in [5*10^15,10^16], the computation of which would need days on
34
* a ~1-GHz computer. */
35
36
#include "pari.h"
37
#include "paripriv.h"
38
39
/****************************************************************/
40
41
/* Given c = sqrt(2/3)*Pi*sqrt(N-1/24)
42
* Psi(N, q) = my(a = c/q); sqrt(q) * (a*cosh(a) - sinh(a)) */
43
static GEN
44
psi(GEN c, ulong q, long prec)
45
{
46
GEN a = divru(c, q), ea = mpexp(a), invea = invr(ea);
47
GEN cha = shiftr(addrr(ea, invea), -1); /* ch(a) */
48
GEN sha = shiftr(subrr(ea, invea), -1); /* sh(a) */
49
return mulrr(sqrtr(utor(q,prec)), subrr(mulrr(a,cha), sha));
50
}
51
52
/* L(n,q)=sqrt(k/3)*sum(l=0,2*k-1,
53
if(((3*l^2+l)/2+n)%k==0,(-1)^l*cos((6*l+1)/(6*k)*Pi)))
54
* Never called with q < 3, so ignore this case */
55
static GEN
56
L(GEN n, ulong k, long bitprec)
57
{
58
ulong r, l, m;
59
long pr = nbits2prec(bitprec / k + k);
60
GEN s = utor(0,pr), pi = mppi(pr);
61
pari_sp av = avma;
62
63
r = 2; m = umodiu(n,k);
64
for (l = 0; l < 2*k; l++)
65
{
66
if (m == 0)
67
{
68
GEN c = mpcos(divru(mulru(pi, 6*l+1), 6*k));
69
if (odd(l)) subrrz(s, c, s); else addrrz(s, c, s);
70
set_avma(av);
71
}
72
m += r; if (m >= k) m -= k;
73
r += 3; if (r >= k) r -= k;
74
}
75
/* multiply by sqrt(k/3) */
76
return mulrr(s, sqrtr((k % 3)? rdivss(k,3,pr): utor(k/3,pr)));
77
}
78
79
/* Return a low precision estimate of log p(n). */
80
static GEN
81
estim(GEN n)
82
{
83
pari_sp av = avma;
84
GEN p1, pi = mppi (DEFAULTPREC);
85
86
p1 = divru( itor(shifti(n,1), DEFAULTPREC), 3 );
87
p1 = mpexp( mulrr(pi, sqrtr(p1)) ); /* exp(Pi * sqrt(2N/3)) */
88
p1 = divri (shiftr(p1,-2), n);
89
p1 = divrr(p1, sqrtr( utor(3,DEFAULTPREC) ));
90
return gerepileupto(av, mplog(p1));
91
}
92
93
/* c = sqrt(2/3)*Pi*sqrt(n-1/24); d = 1 / ((2*b)^(3/2) * Pi); */
94
static void
95
pinit(GEN n, GEN *c, GEN *d, ulong prec)
96
{
97
GEN b = divru( itor( subiu(muliu(n,24), 1), prec ), 24 ); /* n - 1/24 */
98
GEN sqrtb = sqrtr(b), Pi = mppi(prec), pi2sqrt2, pisqrt2d3;
99
100
pisqrt2d3 = mulrr(Pi, sqrtr( divru(utor(2, prec), 3) ));
101
pi2sqrt2 = mulrr(Pi, sqrtr( utor(8, prec) ));
102
*c = mulrr(pisqrt2d3, sqrtb);
103
*d = invr( mulrr(pi2sqrt2, mulrr(b,sqrtb)) );
104
}
105
106
/* part(n) = round(sum(q=1,5 + 0.24*sqrt(n), L(n,q)*Psi(n,q))) */
107
GEN
108
numbpart(GEN n)
109
{
110
pari_sp ltop = avma, av;
111
GEN sum, est, C, D, p1, p2;
112
long prec, bitprec;
113
ulong q;
114
115
if (typ(n) != t_INT) pari_err_TYPE("partition function",n);
116
if (signe(n) < 0) return gen_0;
117
if (abscmpiu(n, 2) < 0) return gen_1;
118
if (cmpii(n, uu32toi(0x38d7e, 0xa4c68000)) >= 0)
119
pari_err_OVERFLOW("numbpart [n < 10^15]");
120
est = estim(n);
121
bitprec = (long)(rtodbl(est)/M_LN2) + 32;
122
prec = nbits2prec(bitprec);
123
pinit(n, &C, &D, prec);
124
sum = cgetr (prec); affsr(0, sum);
125
/* Because N < 10^16 and q < sqrt(N), q fits into a long
126
* In fact q < 2 LONG_MAX / 3 */
127
av = avma; togglesign(est);
128
for (q = (ulong)(sqrt(gtodouble(n))*0.24 + 5); q >= 3; q--, set_avma(av))
129
{
130
GEN t = L(n, q, bitprec);
131
if (abscmprr(t, mpexp(divru(est,q))) < 0) continue;
132
133
t = mulrr(t, psi(gprec_w(C, nbits2prec(bitprec / q + 32)), q, prec));
134
affrr(addrr(sum, t), sum);
135
}
136
p1 = addrr(sum, psi(C, 1, prec));
137
p2 = psi(C, 2, prec);
138
affrr(mod2(n)? subrr(p1,p2): addrr(p1,p2), sum);
139
return gerepileuptoint (ltop, roundr(mulrr(D,sum)));
140
}
141
142
/* for loop over partitions of integer k.
143
* nbounds can restrict partitions to have length between nmin and nmax
144
* (the length is the number of non zero entries) and
145
* abounds restrict to integers between amin and amax.
146
*
147
* Start from central partition.
148
* By default, remove zero entries on the left.
149
*
150
* Algorithm:
151
*
152
* A partition of k is an increasing sequence v1,... vn with sum(vi)=k
153
* The starting point is the minimal n-partition of k: a,...a,a+1,.. a+1
154
* (a+1 is repeated r times with k = a * n + r).
155
*
156
* The procedure to obtain the next partition:
157
* - find the last index i<n such that v{i-1} != v{i} (that is vi is the start
158
* of the last constant range excluding vn).
159
* - decrease vi by one, and set v{i+1},... v{n} to be a minimal partition (of
160
* the right sum).
161
*
162
* Examples: we highlight the index i
163
* 1 1 2 2 3
164
* ^
165
* 1 1 1 3 3
166
* ^
167
* 1 1 1 2 4
168
* ^
169
* 1 1 1 1 5
170
* ^
171
* 0 2 2 2 3
172
* ^
173
* This is recursive in nature. Restrictions on upper bounds of the vi or on
174
* the length of the partitions are straightforward to take into account. */
175
176
static void
177
parse_interval(GEN a, long *amin, long *amax)
178
{
179
switch (typ(a))
180
{
181
case t_INT:
182
*amax = itos(a);
183
break;
184
case t_VEC:
185
if (lg(a) != 3)
186
pari_err_TYPE("forpart [expect vector of type [amin,amax]]",a);
187
*amin = gtos(gel(a,1));
188
*amax = gtos(gel(a,2));
189
if (*amin>*amax || *amin<0 || *amax<=0)
190
pari_err_TYPE("forpart [expect 0<=min<=max, 0<max]",a);
191
break;
192
default:
193
pari_err_TYPE("forpart",a);
194
}
195
}
196
197
void
198
forpart_init(forpart_t *T, long k, GEN abound, GEN nbound)
199
{
200
201
/* bound on coefficients */
202
T->amin=1;
203
if (abound) parse_interval(abound,&T->amin,&T->amax);
204
else T->amax = k;
205
/* strip leading zeros ? */
206
T->strip = (T->amin > 0) ? 1 : 0;
207
/* bound on number of nonzero coefficients */
208
T->nmin=0;
209
if (nbound) parse_interval(nbound,&T->nmin,&T->nmax);
210
else T->nmax = k;
211
212
/* non empty if nmin*amin <= k <= amax*nmax */
213
if ( T->amin*T->nmin > k || k > T->amax * T->nmax )
214
{
215
T->nmin = T->nmax = 0;
216
}
217
else
218
{
219
/* to reach nmin one must have k <= nmin*amax, otherwise increase nmin */
220
if ( T->nmin * T->amax < k )
221
T->nmin = 1 + (k - 1) / T->amax; /* ceil( k/tmax ) */
222
/* decrease nmax (if strip): k <= amin*nmax */
223
if (T->strip && T->nmax > k/T->amin)
224
T->nmax = k / T->amin; /* strip implies amin>0 */ /* fixme: take ceil( ) */
225
/* no need to change amin */
226
/* decrease amax if amax + (nmin-1)*amin > k */
227
if ( T->amax + (T->nmin-1)* T->amin > k )
228
T->amax = k - (T->nmin-1)* T->amin;
229
}
230
231
if ( T->amax < T->amin )
232
T->nmin = T->nmax = 0;
233
234
T->v = zero_zv(T->nmax); /* partitions will be of length <= nmax */
235
T->k = k;
236
}
237
238
GEN
239
forpart_next(forpart_t *T)
240
{
241
GEN v = T->v;
242
long n = lg(v)-1;
243
long i, s, a, k, vi, vn;
244
245
if (n>0 && v[n])
246
{
247
/* find index to increase: i s.t. v[i+1],...v[n] is central a,..a,a+1,..a+1
248
keep s = v[i] + v[i+1] + ... + v[n] */
249
s = a = v[n];
250
for(i = n-1; i>0 && v[i]+1 >= a; s += v[i--]);
251
if (i == 0) {
252
/* v is central [ a, a, .. a, a+1, .. a+1 ] */
253
if ((n+1) * T->amin > s || n == T->nmax) return NULL;
254
i = 1; n++;
255
setlg(v, n+1);
256
vi = T->amin;
257
} else {
258
s += v[i];
259
vi = v[i]+1;
260
}
261
} else {
262
/* init v */
263
s = T->k;
264
if (T->amin == 0) T->amin = 1;
265
if (T->strip) { n = T->nmin; setlg(T->v, n+1); }
266
if (s==0)
267
{
268
if (n==0 && T->nmin==0) {T->nmin++; return v;}
269
return NULL;
270
}
271
if (n==0) return NULL;
272
vi = T->amin;
273
i = T->strip ? 1 : n + 1 - T->nmin; /* first nonzero index */
274
if (s <= (n-i)*vi) return NULL;
275
}
276
/* now fill [ v[i],... v[n] ] with s, start at vi */
277
vn = s - (n-i)*vi; /* expected value for v[n] */
278
if (T->amax && vn > T->amax)
279
{
280
/* do not exceed amax */
281
long ai, q, r;
282
vn -= vi;
283
ai = T->amax - vi;
284
q = vn / ai; /* number of nmax */
285
r = vn % ai; /* value before nmax */
286
/* fill [ v[i],... v[n] ] as [ vi,... vi, vi+r, amax,... amax ] */
287
while ( q-- ) v[n--] = T->amax;
288
if ( n >= i ) v[n--] = vi + r;
289
while ( n >= i ) v[n--] = vi;
290
} else {
291
/* fill as [ v[i], ... v[i], vn ] */
292
for ( k=i; k<n; v[k++] = vi );
293
v[n] = vn;
294
}
295
return v;
296
}
297
298
GEN
299
forpart_prev(forpart_t *T)
300
{
301
GEN v = T->v;
302
long n = lg(v)-1;
303
long j, ni, q, r;
304
long i, s;
305
if (n>0 && v[n])
306
{
307
/* find index to decrease: start of last constant sequence, excluding v[n] */
308
i = n-1; s = v[n];
309
while (i>1 && (v[i-1]==v[i] || v[i+1]==T->amax))
310
s+= v[i--];
311
if (!i) return NULL;
312
/* amax condition: cannot decrease i if maximal on the right */
313
if ( v[i+1] == T->amax ) return NULL;
314
/* amin condition: stop if below except if strip & try to remove */
315
if (v[i] == T->amin) {
316
if (!T->strip) return NULL;
317
s += v[i]; v[i] = 0;
318
} else {
319
v[i]--; s++;
320
}
321
/* zero case... */
322
if (v[i] == 0)
323
{
324
if (T->nmin > n-i) return NULL; /* need too many non zero coeffs */
325
/* reduce size of v ? */
326
if (T->strip) {
327
i = 0; n--;
328
setlg(v, n+1);
329
}
330
}
331
} else
332
{
333
s = T->k;
334
i = 0;
335
if (s==0)
336
{
337
if (n==0 && T->nmin==0) {T->nmin++; return v;}
338
return NULL;
339
}
340
if (n*T->amax < s || s < T->nmin*T->amin) return NULL;
341
}
342
/* set minimal partition of sum s starting from index i+1 */
343
ni = n-i;
344
q = s / ni;
345
r = s % ni;
346
for(j=i+1; j<=n-r; j++) v[j]=q;
347
for(j=n-r+1; j<=n; j++) v[j]=q + 1;
348
return v;
349
}
350
351
static long
352
countpart(long k, GEN abound, GEN nbound)
353
{
354
pari_sp av = avma;
355
long n;
356
forpart_t T;
357
if (k<0) return 0;
358
forpart_init(&T, k, abound, nbound);
359
for (n=0; forpart_next(&T); n++)
360
set_avma(av);
361
return n;
362
}
363
364
GEN
365
partitions(long k, GEN abound, GEN nbound)
366
{
367
GEN v;
368
forpart_t T;
369
long i, n = countpart(k,abound,nbound);
370
if (n==0) return cgetg(1, t_VEC);
371
forpart_init(&T, k, abound, nbound);
372
v = cgetg(n+1, t_VEC);
373
for (i=1; i<=n; i++)
374
gel(v,i)=zv_copy(forpart_next(&T));
375
return v;
376
}
377
378
void
379
forpart(void *E, long call(void*, GEN), long k, GEN abound, GEN nbound)
380
{
381
pari_sp av = avma;
382
GEN v;
383
forpart_t T;
384
forpart_init(&T, k, abound, nbound);
385
while ((v=forpart_next(&T)))
386
if (call(E, v)) break;
387
set_avma(av);
388
}
389
390
void
391
forpart0(GEN k, GEN code, GEN abound, GEN nbound)
392
{
393
pari_sp av = avma;
394
if (typ(k) != t_INT) pari_err_TYPE("forpart",k);
395
if (signe(k)<0) return;
396
push_lex(gen_0, code);
397
forpart((void*)code, &gp_evalvoid, itos(k), abound, nbound);
398
pop_lex(1);
399
set_avma(av);
400
}
401
402