quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

pi_bigdecimal.js (2124B)


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