betaln.js (2982B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2018 The Stdlib Authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * 19 * ## Notice 20 * 21 * The code is adapted from the Fortran routine from the FNLIB library of the [SLATEC Common Mathematical Library]{@link http://www.netlib.no/netlib/slatec/fnlib/albeta.f}. 22 * 23 * The original code was developed by W. Fullerton of Los Alamos Scientific Laboratory, a governmental institution, and is therefore public domain. 24 */ 25 26 'use strict'; 27 28 // MODULES // 29 30 var gammaln = require( './../../../../base/special/gammaln' ); 31 var log1p = require( './../../../../base/special/log1p' ); 32 var gamma = require( './../../../../base/special/gamma' ); 33 var max = require( './../../../../base/special/max' ); 34 var min = require( './../../../../base/special/min' ); 35 var ln = require( './../../../../base/special/ln' ); 36 var LN_SQRT_TWO_PI = require( '@stdlib/constants/float64/ln-sqrt-two-pi' ); 37 var NINF = require( '@stdlib/constants/float64/ninf' ); 38 var PINF = require( '@stdlib/constants/float64/pinf' ); 39 var correction = require( './gamma_correction.js' ); 40 41 42 // MAIN // 43 44 /** 45 * Evaluate the natural logarithm of the beta function. 46 * 47 * @param {NonNegativeNumber} a - first input value 48 * @param {NonNegativeNumber} b - second input value 49 * @returns {number} natural logarithm of beta function 50 * 51 * @example 52 * var v = betaln( 0.0, 0.0 ); 53 * // returns Infinity 54 * 55 * @example 56 * var v = betaln( 1.0, 1.0 ); 57 * // returns 0.0 58 * 59 * @example 60 * var v = betaln( -1.0, 2.0 ); 61 * // returns NaN 62 * 63 * @example 64 * var v = betaln( 5.0, 0.2 ); 65 * // returns ~1.218 66 * 67 * @example 68 * var v = betaln( 4.0, 1.0 ); 69 * // returns ~-1.386 70 * 71 * @example 72 * var v = betaln( NaN, 2.0 ); 73 * // returns NaN 74 */ 75 function betaln( a, b ) { 76 var corr; 77 var p; 78 var q; 79 80 p = min( a, b ); 81 q = max( a, b ); 82 83 if ( p < 0.0 ) { 84 return NaN; 85 } 86 if ( p === 0.0 ) { 87 return PINF; 88 } 89 if ( q === PINF ) { 90 return NINF; 91 } 92 // Case: p and q are big 93 if ( p >= 10.0 ) { 94 corr = correction( p ) + correction( q ) - correction( p+q ); 95 return ( -0.5*ln( q ) ) + LN_SQRT_TWO_PI + corr + ( (p-0.5) * ln( p/(p+q) ) ) + ( q*log1p( -p/(p+q) ) ); // eslint-disable-line max-len 96 } 97 // Case: p is small, but q is big 98 if ( q >= 10.0 ) { 99 corr = correction( q ) - correction( p+q ); 100 return gammaln( p ) + corr + p - (p*ln( p+q )) + ( (q-0.5)*log1p( -p/(p+q) ) ); // eslint-disable-line max-len 101 } 102 // Case: p and q are small 103 return ln( gamma( p ) * ( gamma( q ) / gamma( p+q ) ) ); 104 } 105 106 107 // EXPORTS // 108 109 module.exports = betaln;