| /* |
| * PI computation in Javascript using the QuickJS bigfloat type |
| * (binary floating point) |
| */ |
| "use strict"; |
| |
| /* compute PI with a precision of 'prec' bits */ |
| function calc_pi() { |
| const CHUD_A = 13591409n; |
| const CHUD_B = 545140134n; |
| const CHUD_C = 640320n; |
| const CHUD_C3 = 10939058860032000n; /* 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 - 1n)) { |
| G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n); |
| P = BigFloat(G * (CHUD_B * b + CHUD_A)); |
| if (b & 1n) |
| P = -P; |
| G = BigFloat(G); |
| Q = BigFloat(b * b * b * CHUD_C3); |
| } else { |
| c = (a + b) >> 1n; |
| [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 = 0l; |
| } |
| return [P, Q, G]; |
| } |
| |
| var n, P, Q, G; |
| /* number of serie terms */ |
| n = BigInt(Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM)) + 10n; |
| [P, Q, G] = chud_bs(0n, n, false); |
| Q = Q / (P + Q * BigFloat(CHUD_A)); |
| G = BigFloat((CHUD_C / 12n)) * BigFloat.sqrt(BigFloat(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); |
| })(); |