| /* |
| * PI computation in Javascript using the QuickJS bignum extensions |
| */ |
| "use strict"; |
| "use bigint"; |
| |
| /* compute PI with a precision of 'prec' bits */ |
| function calc_pi(prec) { |
| const CHUD_A = 13591409; |
| const CHUD_B = 545140134; |
| const CHUD_C = 640320; |
| const CHUD_C3 = 10939058860032000; /* C^3/24 */ |
| const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ |
| |
| /* return [P, Q, G] */ |
| function chud_bs(a, b, need_G) { |
| var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; |
| if (a == (b - 1)) { |
| G = (2 * b - 1) * (6 * b - 1) * (6 * b - 5); |
| P = BigFloat(G * (CHUD_B * b + CHUD_A)); |
| if (b & 1) |
| P = -P; |
| G = BigFloat(G); |
| Q = BigFloat(b * b * b * CHUD_C3); |
| } else { |
| c = (a + b) >> 1; |
| [P1, Q1, G1] = chud_bs(a, c, true); |
| [P2, Q2, G2] = chud_bs(c, b, need_G); |
| P = P1 * Q2 + P2 * G1; |
| Q = Q1 * Q2; |
| if (need_G) |
| G = G1 * G2; |
| else |
| G = 0; |
| } |
| return [P, Q, G]; |
| } |
| |
| var n, P, Q, G; |
| /* number of serie terms */ |
| n = Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM) + 10; |
| [P, Q, G] = chud_bs(0, n, false); |
| Q = Q / (P + Q * CHUD_A); |
| G = (CHUD_C / 12) * BigFloat.sqrt(CHUD_C); |
| return Q * G; |
| } |
| |
| (function() { |
| var r, n_digits, n_bits; |
| if (typeof scriptArgs != "undefined") { |
| if (scriptArgs.length < 2) { |
| print("usage: pi n_digits"); |
| return; |
| } |
| n_digits = scriptArgs[1]; |
| } else { |
| n_digits = 1000; |
| } |
| n_bits = Math.ceil(n_digits * Math.log2(10)); |
| /* we add more bits to reduce the probability of bad rounding for |
| the last digits */ |
| BigFloatEnv.setPrec( () => { |
| r = calc_pi(); |
| print(r.toFixed(n_digits, BigFloatEnv.RNDZ)); |
| }, n_bits + 32); |
| })(); |