1/* 2 * PI computation in Javascript using the QuickJS bigfloat type 3 * (binary floating point) 4 */ 5"use strict"; 6 7/* compute PI with a precision of 'prec' bits */ 8function calc_pi() { 9 const CHUD_A = 13591409n; 10 const CHUD_B = 545140134n; 11 const CHUD_C = 640320n; 12 const CHUD_C3 = 10939058860032000n; /* C^3/24 */ 13 const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ 14 15 /* return [P, Q, G] */ 16 function chud_bs(a, b, need_G) { 17 var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; 18 if (a == (b - 1n)) { 19 G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n); 20 P = BigFloat(G * (CHUD_B * b + CHUD_A)); 21 if (b & 1n) 22 P = -P; 23 G = BigFloat(G); 24 Q = BigFloat(b * b * b * CHUD_C3); 25 } else { 26 c = (a + b) >> 1n; 27 [P1, Q1, G1] = chud_bs(a, c, true); 28 [P2, Q2, G2] = chud_bs(c, b, need_G); 29 P = P1 * Q2 + P2 * G1; 30 Q = Q1 * Q2; 31 if (need_G) 32 G = G1 * G2; 33 else 34 G = 0l; 35 } 36 return [P, Q, G]; 37 } 38 39 var n, P, Q, G; 40 /* number of serie terms */ 41 n = BigInt(Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM)) + 10n; 42 [P, Q, G] = chud_bs(0n, n, false); 43 Q = Q / (P + Q * BigFloat(CHUD_A)); 44 G = BigFloat((CHUD_C / 12n)) * BigFloat.sqrt(BigFloat(CHUD_C)); 45 return Q * G; 46} 47 48(function() { 49 var r, n_digits, n_bits; 50 if (typeof scriptArgs != "undefined") { 51 if (scriptArgs.length < 2) { 52 print("usage: pi n_digits"); 53 return; 54 } 55 n_digits = scriptArgs[1]; 56 } else { 57 n_digits = 1000; 58 } 59 n_bits = Math.ceil(n_digits * Math.log2(10)); 60 /* we add more bits to reduce the probability of bad rounding for 61 the last digits */ 62 BigFloatEnv.setPrec( () => { 63 r = calc_pi(); 64 print(r.toFixed(n_digits, BigFloatEnv.RNDZ)); 65 }, n_bits + 32); 66})(); 67