Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2018 The PARI group.12This file is part of the PARI/GP package.34PARI/GP is free software; you can redistribute it and/or modify it under the5terms of the GNU General Public License as published by the Free Software6Foundation; either version 2 of the License, or (at your option) any later7version. It is distributed in the hope that it will be useful, but WITHOUT8ANY WARRANTY WHATSOEVER.910Check the License for details. You should have received a copy of it, along11with the package; see the file 'COPYING'. If not, write to the Free Software12Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */1314#include "pari.h"15#include "paripriv.h"1617#define DEBUGLEVEL DEBUGLEVEL_bern1819/********************************************************************/20/** **/21/** BERNOULLI NUMBERS B_2k **/22/** **/23/********************************************************************/2425/* D = divisorsu(n). Return a/b = \sum_{p-1 | 2n: p prime} 1/p26* B_2k + a/b in Z [Clausen-von Staudt] */27static GEN28fracB2k(GEN D)29{30GEN a = utoipos(5), b = utoipos(6); /* 1/2 + 1/3 */31long i, l = lg(D);32for (i = 2; i < l; i++) /* skip 1 */33{34ulong p = 2*D[i] + 1; /* a/b += 1/p */35if (uisprime(p)) { a = addii(muliu(a,p), b); b = muliu(b,p); }36}37return mkfrac(a,b);38}39/* precision needed to compute B_k for all k <= N */40long41bernbitprec(long N)42{ /* 1.612086 ~ log(8Pi) / 2 */43const double log2PI = 1.83787706641;44double t = (N + 0.5) * log((double)N) - N*(1 + log2PI) + 1.612086;45return (long)ceil(t / M_LN2) + 16;46}47static long48bernprec(long N) { return nbits2prec(bernbitprec(N)); }49/* \sum_{k > M} k^(-n) <= M^(1-n) / (n-1) < 2^-bit_accuracy(prec) */50static long51zetamaxpow(long n, long prec)52{53long b = bit_accuracy(prec), M = (long)exp2((double)b/(n-1.0));54return M | 1; /* make it odd */55}56/* zeta(k) using 'max' precomputed odd powers */57static GEN58bern_zeta(long k, GEN pow, long max, long prec)59{60GEN s = gel(pow, max);61long j;62for (j = max - 2; j >= 3; j -= 2) s = addrr(s, gel(pow,j));63return divrr(addrs(s,1), subsr(1, real2n(-k, prec)));64}65/* z * j^2 */66static GEN67mulru2(GEN z, ulong j)68{ return (j | HIGHMASK)? mulru(mulru(z, j), j)69: mulru(z, j*j); }70/* 1 <= m <= n, set y[1] = B_{2m}, ... y[n-m+1] = B_{2n} in Q */71static void72bernset(GEN *y, long m, long n)73{74long i, j, k, bit, prec, max, N = n << 1; /* up to B_N */75GEN A, C, pow;76bit = bernbitprec(N);77prec = nbits2prec(bit);78A = sqrr(Pi2n(1, prec)); /* (2Pi)^2 */79C = divrr(mpfactr(N, prec), powru(A, n)); shiftr_inplace(C,1);80max = zetamaxpow(N, prec);81pow = cgetg(max+1, t_VEC);82for (j = 3; j <= max; j += 2)83{ /* fixed point, precision decreases with j */84long b = bit - N * log2(j), p = b <= 0? LOWDEFAULTPREC: nbits2prec(b);85gel(pow,j) = invr(rpowuu(j, N, p));86}87y += n - m;88for (i = n, k = N;; i--)89{ /* set B_n, k = 2i */90pari_sp av2 = avma;91GEN B, z = fracB2k(divisorsu(i)), s = bern_zeta(k, pow, max, prec);92long j;93/* s = zeta(k), C = 2*k! / (2Pi)^k */94B = mulrr(s, C); if (!odd(i)) setsigne(B, -1); /* B ~ B_n */95B = roundr(addrr(B, fractor(z,LOWDEFAULTPREC))); /* B - z = B_n */96*y-- = gclone(gsub(B, z));97if (i == m) break;98affrr(divrunu(mulrr(C,A), k-1), C);99for (j = max; j >= 3; j -= 2) affrr(mulru2(gel(pow,j), j), gel(pow,j));100set_avma(av2);101k -= 2;102if ((k & 0xf) == 0)103{ /* reduce precision if possible */104long bit2 = bernbitprec(k), prec2 = nbits2prec(bit2), max2;105if (prec2 == prec) continue;106prec = prec2;107max2 = zetamaxpow(k,prec);108if (max2 > max) continue;109bit = bit2;110max = max2;111setprec(C, prec);112for (j = 3; j <= max; j += 2)113{114GEN P = gel(pow,j);115long b = bit + expo(P), p = b <= 0? LOWDEFAULTPREC: nbits2prec(b);116if (realprec(P) > p) setprec(P, p);117}118}119}120}121/* need B[2..2*nb] as t_INT or t_FRAC */122void123constbern(long nb)124{125const pari_sp av = avma;126long i, l;127GEN B;128pari_timer T;129130l = bernzone? lg(bernzone): 0;131if (l > nb) return;132133nb = maxss(nb, l + 127);134B = cgetg_block(nb+1, t_VEC);135if (bernzone)136{ for (i = 1; i < l; i++) gel(B,i) = gel(bernzone,i); }137else138{139gel(B,1) = gclone(mkfracss(1,6));140gel(B,2) = gclone(mkfracss(-1,30));141gel(B,3) = gclone(mkfracss(1,42));142gel(B,4) = gclone(mkfracss(-1,30));143gel(B,5) = gclone(mkfracss(5,66));144gel(B,6) = gclone(mkfracss(-691,2730));145gel(B,7) = gclone(mkfracss(7,6));146gel(B,8) = gclone(mkfracss(-3617,510));147gel(B,9) = gclone(mkfracss(43867,798));148gel(B,10)= gclone(mkfracss(-174611,330));149gel(B,11)= gclone(mkfracss(854513,138));150gel(B,12)= gclone(mkfracss(-236364091,2730));151gel(B,13)= gclone(mkfracss(8553103,6)); /* B_26 */152l = 14;153}154set_avma(av);155if (DEBUGLEVEL) {156err_printf("caching Bernoulli numbers 2*%ld to 2*%ld\n", l, nb);157timer_start(&T);158}159bernset((GEN*)B + l, l, nb);160if (DEBUGLEVEL) timer_printf(&T, "Bernoulli");161swap(B, bernzone); guncloneNULL(B);162set_avma(av);163}164/* Obsolete, kept for backward compatibility */165void166mpbern(long n, long prec) { (void)prec; constbern(n); }167168/* assume n even > 0, if iz != NULL, assume iz = 1/zeta(n) */169static GEN170bernreal_using_zeta(long n, long prec)171{172GEN pi2 = Pi2n(1, prec+EXTRAPRECWORD);173GEN iz = inv_szeta_euler(n, prec);174GEN z = divrr(mpfactr(n, prec), mulrr(powru(pi2, n), iz));175shiftr_inplace(z, 1); /* 2 * n! * zeta(n) / (2Pi)^n */176if ((n & 3) == 0) setsigne(z, -1);177return z;178}179/* assume n even > 0, B = NULL or good approximation to B_n */180static GEN181bernfrac_i(long n, GEN B)182{183GEN z = fracB2k(divisorsu(n >> 1));184if (!B) B = bernreal_using_zeta(n, bernprec(n));185B = roundr( gadd(B, fractor(z,LOWDEFAULTPREC)) );186return gsub(B, z);187}188GEN189bernfrac(long n)190{191pari_sp av;192long k;193if (n <= 1)194{195if (n < 0) pari_err_DOMAIN("bernfrac", "index", "<", gen_0, stoi(n));196return n? mkfrac(gen_m1,gen_2): gen_1;197}198if (odd(n)) return gen_0;199k = n >> 1;200if (!bernzone) constbern(0);201if (bernzone && k < lg(bernzone)) return gel(bernzone, k);202av = avma;203return gerepileupto(av, bernfrac_i(n, NULL));204}205GEN206bernvec(long n)207{208long i, l;209GEN y;210if (n < 0) return cgetg(1, t_VEC);211constbern(n);212l = n+2; y = cgetg(l, t_VEC); gel(y,1) = gen_1;213for (i = 2; i < l; i++) gel(y,i) = gel(bernzone,i-1);214return y;215}216217/* x := pol_x(v); B_k(x) = \sum_{i=0}^k binomial(k, i) B_i x^{k-i} */218static GEN219bernpol_i(long k, long v)220{221GEN B, C;222long i;223if (v < 0) v = 0;224constbern(k >> 1); /* cache B_2, ..., B_2[k/2] */225C = vecbinomial(k);226B = cgetg(k + 3, t_POL);227for (i = 0; i <= k; ++i) gel(B, k-i+2) = gmul(gel(C,i+1), bernfrac(i));228B[1] = evalsigne(1) | evalvarn(v);229return B;230}231GEN232bernpol(long k, long v)233{234pari_sp av = avma;235if (k < 0) pari_err_DOMAIN("bernpol", "index", "<", gen_0, stoi(k));236return gerepileupto(av, bernpol_i(k, v));237}238/* x := pol_x(v); return 1^e + ... + x^e = x^e + (B_{e+1}(x) - B_{e+1})/(e+1) */239static GEN240faulhaber(long e, long v)241{242GEN B;243if (e == 0) return pol_x(v);244B = RgX_integ(bernpol_i(e, v)); /* (B_{e+1}(x) - B_{e+1}) / (e+1) */245gel(B,e+2) = gaddgs(gel(B,e+2), 1); /* add x^e, in place */246return B;247}248/* sum_v T(v), T a polynomial expression in v */249GEN250sumformal(GEN T, long v)251{252pari_sp av = avma, av2;253long i, t, d;254GEN R;255256T = simplify_shallow(T);257t = typ(T);258if (is_scalar_t(t))259return gerepileupto(av, monomialcopy(T, 1, v < 0? 0: v));260if (t != t_POL) pari_err_TYPE("sumformal [not a t_POL]", T);261if (v < 0) v = varn(T);262av2 = avma;263R = gen_0;264d = poldegree(T,v);265for (i = d; i >= 0; i--)266{267GEN c = polcoef(T, i, v);268if (gequal0(c)) continue;269R = gadd(R, gmul(c, faulhaber(i, v)));270if (gc_needed(av2,3))271{272if(DEBUGMEM>1) pari_warn(warnmem,"sumformal, i = %ld/%ld", i,d);273R = gerepileupto(av2, R);274}275}276return gerepileupto(av, R);277}278279/* 1/zeta(n) using Euler product. Assume n > 0. */280GEN281inv_szeta_euler(long n, long prec)282{283long bit = prec2nbits(prec);284GEN z, res;285pari_sp av, av2;286double A, D, lba;287ulong p, lim;288forprime_t S;289290if (n > bit) return real_1(prec);291292lba = prec2nbits_mul(prec, M_LN2);293D = exp((lba - log((double)(n-1))) / (n-1));294lim = 1 + (ulong)ceil(D);295if (lim < 3) return subir(gen_1,real2n(-n,prec));296res = cgetr(prec); av = avma; incrprec(prec);297298(void)u_forprime_init(&S, 3, lim);299av2 = avma; A = n / M_LN2; z = subir(gen_1, real2n(-n, prec));300while ((p = u_forprime_next(&S)))301{302long l = bit - (long)floor(A * log((double)p));303GEN h;304305if (l < BITS_IN_LONG) l = BITS_IN_LONG;306l = minss(prec, nbits2prec(l));307h = divrr(z, rpowuu(p, (ulong)n, l));308z = subrr(z, h);309if (gc_needed(av,1))310{311if (DEBUGMEM>1) pari_warn(warnmem,"inv_szeta_euler, p = %lu/%lu", p,lim);312z = gerepileuptoleaf(av2, z);313}314}315affrr(z, res); set_avma(av); return res;316}317318/* Return B_n */319GEN320bernreal(long n, long prec)321{322pari_sp av;323GEN B;324long p, k;325if (n < 0) pari_err_DOMAIN("bernreal", "index", "<", gen_0, stoi(n));326if (n == 0) return real_1(prec);327if (n == 1) return real_m2n(-1,prec); /*-1/2*/328if (odd(n)) return real_0(prec);329330k = n >> 1;331if (!bernzone) constbern(0);332if (k < lg(bernzone)) return fractor(gel(bernzone,k), prec);333p = bernprec(n); av = avma;334B = bernreal_using_zeta(n, minss(p, prec));335if (p < prec) B = fractor(bernfrac_i(n, B), prec);336return gerepileuptoleaf(av, B);337}338339GEN340eulerpol(long k, long v)341{342pari_sp av = avma;343GEN B, E;344if (k < 0) pari_err_DOMAIN("eulerpol", "index", "<", gen_0, stoi(k));345k++; B = bernpol_i(k, v);346E = RgX_Rg_mul(RgX_sub(B, RgX_rescale(B, gen_2)), sstoQ(2,k));347return gerepileupto(av, E);348}349350/**************************************************************/351/* Euler numbers */352/**************************************************************/353354/* precision needed to compute E_k for all k <= N */355static long356eulerbitprec(long N)357{ /* 1.1605 ~ log(32/Pi) / 2 */358const double logPIS2 = 0.4515827;359double t = (N + 0.5) * log((double)N) - N*(1 + logPIS2) + 1.1605;360return (long)ceil(t / M_LN2) + 16;361}362static long363eulerprec(long N) { return nbits2prec(eulerbitprec(N)); }364365/* sum_{k > M, k odd} (-1)^((k-1)/2)k^(-n) < M^(-n) < 2^-bit_accuracy(prec) */366static long367lfun4maxpow(long n, long prec)368{369long b = bit_accuracy(prec), M = (long)exp2((double)b/(n+0.));370return M | 1; /* make it odd */371}372373/* lfun4(k) using 'max' precomputed odd powers */374static GEN375euler_lfun4(GEN pow, long max)376{377GEN s = ((max & 3L) == 1) ? gel(pow, max) : negr(gel(pow, max));378long j;379for (j = max - 2; j >= 3; j -= 2)380s = ((j & 3L) == 1) ? addrr(s, gel(pow,j)) : subrr(s, gel(pow,j));381return addrs(s, 1);382}383384/* 1 <= m <= n, set y[1] = E_{2m}, ... y[n-m+1] = E_{2n} in Z */385static void386eulerset(GEN *y, long m, long n)387{388long i, j, k, bit, prec, max, N = n << 1, N1 = N + 1; /* up to E_N */389GEN A, C, pow;390bit = eulerbitprec(N);391prec = nbits2prec(bit);392A = sqrr(Pi2n(-1, prec)); /* (Pi/2)^2 */393C = divrr(mpfactr(N, prec), mulrr(powru(A, n), Pi2n(-2,prec)));394max = lfun4maxpow(N1, prec);395pow = cgetg(max+1, t_VEC);396for (j = 3; j <= max; j += 2)397{ /* fixed point, precision decreases with j */398long b = bit - N1 * log2(j), p = b <= 0? LOWDEFAULTPREC: nbits2prec(b);399gel(pow,j) = invr(rpowuu(j, N1, p));400}401y += n - m;402for (i = n, k = N1;; i--)403{ /* set E_n, k = 2i + 1 */404pari_sp av2 = avma;405GEN E, s = euler_lfun4(pow, max);406long j;407/* s = lfun4(k), C = (4/Pi)*k! / (Pi/2)^k */408E = roundr(mulrr(s, C)); if (odd(i)) setsigne(E, -1); /* E ~ E_n */409*y-- = gclone(E);410if (i == m) break;411affrr(divrunu(mulrr(C,A), k-2), C);412for (j = max; j >= 3; j -= 2) affrr(mulru2(gel(pow,j), j), gel(pow,j));413set_avma(av2);414k -= 2;415if ((k & 0xf) == 0)416{ /* reduce precision if possible */417long bit2 = eulerbitprec(k), prec2 = nbits2prec(bit2), max2;418if (prec2 == prec) continue;419prec = prec2;420max2 = lfun4maxpow(k,prec);421if (max2 > max) continue;422bit = bit2;423max = max2;424setprec(C, prec);425for (j = 3; j <= max; j += 2)426{427GEN P = gel(pow,j);428long b = bit + expo(P), p = b <= 0? LOWDEFAULTPREC: nbits2prec(b);429if (realprec(P) > p) setprec(P, p);430}431}432}433}434435/* need E[2..2*nb] as t_INT */436static void437constreuler(long nb)438{439const pari_sp av = avma;440long i, l;441GEN E;442pari_timer T;443444l = eulerzone? lg(eulerzone): 0;445if (l > nb) return;446447nb = maxss(nb, l + 127);448E = cgetg_block(nb+1, t_VEC);449if (eulerzone)450{ for (i = 1; i < l; i++) gel(E,i) = gel(eulerzone,i); }451else452{453gel(E,1) = gclone(stoi(-1));454gel(E,2) = gclone(stoi(5));455gel(E,3) = gclone(stoi(-61));456gel(E,4) = gclone(stoi(1385));457gel(E,5) = gclone(stoi(-50521));458gel(E,6) = gclone(stoi(2702765));459gel(E,7) = gclone(stoi(-199360981));460l = 8;461}462set_avma(av);463if (DEBUGLEVEL) {464err_printf("caching Euler numbers 2*%ld to 2*%ld\n", l, nb);465timer_start(&T);466}467eulerset((GEN*)E + l, l, nb);468if (DEBUGLEVEL) timer_printf(&T, "Euler");469swap(E, eulerzone); guncloneNULL(E);470set_avma(av);471}472473/* 1/lfun(-4,n) using Euler product. Assume n > 0. */474static GEN475inv_lfun4(long n, long prec)476{477long bit = prec2nbits(prec);478GEN z, res;479pari_sp av, av2;480double A;481ulong p, lim;482forprime_t S;483484if (n > bit) return real_1(prec);485486lim = 1 + (ulong)ceil(exp2((double)bit / n));487res = cgetr(prec); av = avma; incrprec(prec);488489(void)u_forprime_init(&S, 3, lim);490av2 = avma; A = n / M_LN2; z = real_1(prec);491while ((p = u_forprime_next(&S)))492{493long l = bit - (long)floor(A * log((double)p));494GEN h;495496if (l < BITS_IN_LONG) l = BITS_IN_LONG;497l = minss(prec, nbits2prec(l));498h = rpowuu(p, (ulong)n, l); if ((p & 3UL) == 1) setsigne(h, -1);499z = addrr(z, divrr(z, h)); /* z *= 1 - chi_{-4}(p) / p^n */500if (gc_needed(av,1))501{502if (DEBUGMEM>1) pari_warn(warnmem,"inv_lfun4, p = %lu/%lu", p,lim);503z = gerepileuptoleaf(av2, z);504}505}506affrr(z, res); set_avma(av); return res;507}508/* assume n even > 0, E_n = (-1)^(n/2) (4/Pi) n! lfun4(n+1) / (Pi/2)^n */509static GEN510eulerreal_using_lfun4(long n, long prec)511{512GEN pisur2 = Pi2n(-1, prec+EXTRAPRECWORD);513GEN iz = inv_lfun4(n+1, prec);514GEN z = divrr(mpfactr(n, prec), mulrr(powru(pisur2, n+1), iz));515if ((n & 3L) == 2) setsigne(z, -1);516shiftr_inplace(z, 1); return z;517}518/* Euler numbers: 1, 0, -1, 0, 5, 0, -61,... */519GEN520eulerfrac(long n)521{522pari_sp av;523long k;524GEN E;525if (n <= 0)526{527if (n < 0) pari_err_DOMAIN("eulerfrac", "index", "<", gen_0, stoi(n));528return gen_1;529}530if (odd(n)) return gen_0;531k = n >> 1;532if (!eulerzone) constreuler(0);533if (eulerzone && k < lg(eulerzone)) return gel(eulerzone, k);534av = avma; E = eulerreal_using_lfun4(n, eulerprec(n));535return gerepileuptoleaf(av, roundr(E));536}537GEN538eulervec(long n)539{540long i, l;541GEN y;542if (n < 0) return cgetg(1, t_VEC);543constreuler(n);544l = n+2; y = cgetg(l, t_VEC); gel(y,1) = gen_1;545for (i = 2; i < l; i++) gel(y,i) = gel(eulerzone,i-1);546return y;547}548549/* Return E_n */550GEN551eulerreal(long n, long prec)552{553pari_sp av = avma;554GEN B;555long p, k;556if (n < 0) pari_err_DOMAIN("eulerreal", "index", "<", gen_0, stoi(n));557if (n == 0) return real_1(prec);558if (odd(n)) return real_0(prec);559560k = n >> 1;561if (!eulerzone) constreuler(0);562if (k < lg(eulerzone)) return itor(gel(eulerzone,k), prec);563p = eulerprec(n);564B = eulerreal_using_lfun4(n, minss(p, prec));565if (p < prec) B = itor(roundr(B), prec);566return gerepileuptoleaf(av, B);567}568569570