UNPKG

distriprob

Version:

A library for calculating the PDF, CDFs, and quantile function values of common probability distributions

217 lines (216 loc) 5.9 kB
"use strict"; const async_1 = require("./async"); const random_1 = require("./random"); const cfs = require("./continuedFractionSolver"); const gamma = require("./gamma"); const rf = require("./rootFind"); // This import and then renaming of imports is necessary to allow the async module to // correctly generate web worker scripts. const lnGamma = gamma.lnGamma; const continuedFractionSolver = cfs.continuedFractionSolver; const rootFind = rf.rootFind; function lnBeta(x, y) { return (lnGamma(x) + lnGamma(y)) - lnGamma(x + y); } exports.lnBeta = lnBeta; /** * a function to calculate the "d_i" values from * http://www.stat.tamu.edu/~jnewton/604/chap3.pdf pp.15-16 * in the calculation of the IB(incomplete beta function) * * @param i - the index of the d_i values * @param x - parameter from the IB function * @param a - parameter from the IB function * @param b - parameter from the IB function * @returns {any} - the d_i value */ function d(i, x, a, b) { var result; var m; if (i % 2 === 0) { m = i / 2; result = (m * (b - m) * x) / ((a + 2 * m - 1) * (a + 2 * m)); } else if (i % 2 === 1) { m = (i - 1) / 2; result = -((a + m) * (a + b + m) * x) / ((a + 2 * m) * (a + 2 * m + 1)); } return result; } exports.d = d; function continuedFraction(x, a, b) { function num(j) { if (j === 1) { return 1; } else { return d(j - 1, x, a, b); } } function denom(j) { if (j === 0) { return 0; } else { return 1; } } return continuedFractionSolver(num, denom); } exports.continuedFraction = continuedFraction; function lnIncompleteBeta(x, a, b) { const comparator = (a + 1) / (a + b + 1); if (x >= comparator) { return Math.log(1 - Math.exp(lnIncompleteBeta(1 - x, b, a))); } const alnx = a * Math.log(x); const bln1MinusX = b * Math.log(1 - x); const lna = Math.log(a); const lnBetaAB = lnBeta(a, b); const lnContinuedFraction = Math.log(continuedFraction(x, a, b)); return alnx + bln1MinusX - lna - lnBetaAB + lnContinuedFraction; } exports.lnIncompleteBeta = lnIncompleteBeta; function incompleteBeta(x, a, b) { return Math.exp(lnIncompleteBeta(x, a, b)); } exports.incompleteBeta = incompleteBeta; function inverseIncompleteBeta(p, a, b) { const lnIncompBeta = function (x) { return lnIncompleteBeta(x, a, b); }; const derivativeLnIncompleteBeta = function (x) { const lnBetaAB = lnBeta(a, b); const lnIncBetaXAB = lnIncompleteBeta(x, a, b); const bMinus1TimesLn1MinusX = (b - 1) * Math.log(1 - x); const aMinus1TimesLnX = (a - 1) * Math.log(x); return Math.exp(bMinus1TimesLn1MinusX + aMinus1TimesLnX - lnBetaAB - lnIncBetaXAB); }; return rootFind(lnIncompBeta, derivativeLnIncompleteBeta, Math.log(p), 0.5, 1, 0); } exports.inverseIncompleteBeta = inverseIncompleteBeta; function pdfSync(x, alpha, beta) { if (x < 0 || x > 1) { return 0; } else { return Math.exp(((alpha - 1) * Math.log(x)) + ((beta - 1) * Math.log(1 - x)) - lnBeta(alpha, beta)); } } exports.pdfSync = pdfSync; function pdf(x, alpha, beta) { return async_1.asyncGen([lnGamma, lnBeta], pdfSync, [x, alpha, beta]); } exports.pdf = pdf; function cdfSync(x, alpha, beta, lowerTail = true) { if (x <= 0) { if (lowerTail) { return 0; } else { return 1; } } else if (x >= 1) { if (lowerTail) { return 1; } else { return 0; } } else { if (lowerTail) { return incompleteBeta(x, alpha, beta); } else { return incompleteBeta(1 - x, beta, alpha); } } } exports.cdfSync = cdfSync; function cdf(x, alpha, beta, lowerTail = true) { return async_1.asyncGen([ lnBeta, lnGamma, continuedFractionSolver, d, continuedFraction, lnIncompleteBeta, incompleteBeta ], cdfSync, [x, alpha, beta, lowerTail]); } exports.cdf = cdf; function quantileSync(p, alpha, beta, lowerTail = true) { function f(val) { return cdfSync(val, alpha, beta, lowerTail); } function fPrime(val) { if (lowerTail) { return pdfSync(val, alpha, beta); } else { return -pdfSync(val, alpha, beta); } } const mean = alpha / (alpha + beta); if (p === 0) { if (lowerTail) { return 0; } else { return 1; } } else if (p === 1) { if (lowerTail) { return 1; } else { return 0; } } else { return rootFind(f, fPrime, p, mean, 1, 0); } } exports.quantileSync = quantileSync; function quantile(x, alpha, beta, lowerTail = true) { return async_1.asyncGen([ rf.newton, rf.bisection, rootFind, lnBeta, lnGamma, continuedFractionSolver, d, continuedFraction, lnIncompleteBeta, incompleteBeta, pdfSync, cdfSync ], quantileSync, [x, alpha, beta, lowerTail]); } exports.quantile = quantile; function randomSync(n, alpha, beta, seed, randoms) { return random_1.randSync(n, quantileSync, [alpha, beta], seed, randoms); } exports.randomSync = randomSync; function random(n, alpha, beta, seed) { return random_1.rand(n, quantileSync, [alpha, beta], seed, [ rf.newton, rf.bisection, rootFind, lnBeta, lnGamma, continuedFractionSolver, d, continuedFraction, lnIncompleteBeta, incompleteBeta, pdfSync, cdfSync ]); } exports.random = random;