temme1.js (4147B)
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 original C++ code and copyright notice are from the [Boost library]{@link http://www.boost.org/doc/libs/1_64_0/boost/math/special_functions/detail/ibeta_inverse.hpp}. The implementation has been modified for JavaScript. 22 * 23 * ```text 24 * Copyright John Maddock 2006. 25 * Copyright Paul A. Bristow 2007. 26 * 27 * Use, modification and distribution are subject to the 28 * Boost Software License, Version 1.0. (See accompanying file 29 * LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) 30 * ``` 31 */ 32 33 'use strict'; 34 35 // MODULES // 36 37 var evalpoly = require( './../../../../base/tools/evalpoly' ); 38 var erfcinv = require( './../../../../base/special/erfcinv' ); 39 var sqrt = require( './../../../../base/special/sqrt' ); 40 var exp = require( './../../../../base/special/exp' ); 41 var SQRT2 = require( '@stdlib/constants/float64/sqrt-two' ); 42 43 44 // VARIABLES // 45 46 // Workspaces for the polynomial coefficients: 47 var workspace = [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]; 48 var terms = [ 0.0, 0.0, 0.0, 0.0 ]; 49 50 51 // MAIN // 52 53 /** 54 * Carries out the first method by Temme (described in section 2). 55 * 56 * ## References 57 * 58 * - Temme, N. M. 1992. "Incomplete Laplace Integrals: Uniform Asymptotic Expansion with Application to the Incomplete Beta Function." _Journal of Computational and Applied Mathematics_ 41 (1–2): 1638–63. doi:[10.1016/0377-0427(92)90244-R](https://doi.org/10.1016/0377-0427(92)90244-R). 59 * 60 * @private 61 * @param {PositiveNumber} a - function parameter 62 * @param {PositiveNumber} b - function parameter 63 * @param {Probability} z - function parameter 64 * @returns {number} function value 65 */ 66 function temme1( a, b, z ) { 67 var eta0; 68 var eta2; 69 var eta; 70 var B2; 71 var B3; 72 var B; 73 var c; 74 75 // Get the first approximation for eta from the inverse error function (Eq: 2.9 and 2.10): 76 eta0 = erfcinv( 2.0 * z ); 77 eta0 /= -sqrt( a / 2.0 ); 78 79 terms[ 0 ] = eta0; 80 81 // Calculate powers: 82 B = b - a; 83 B2 = B * B; 84 B3 = B2 * B; 85 86 // Calculate correction terms: 87 88 // See eq following 2.15: 89 workspace[ 0 ] = -B * SQRT2 / 2; 90 workspace[ 1 ] = ( 1 - (2.0*B) ) / 8.0; 91 workspace[ 2 ] = -(B * SQRT2 / 48.0); 92 workspace[ 3 ] = -1.0 / 192.0; 93 workspace[ 4 ] = -B * SQRT2 / 3840.0; 94 workspace[ 5 ] = 0.0; 95 workspace[ 6 ] = 0.0; 96 terms[ 1 ] = evalpoly( workspace, eta0 ); 97 98 // Eq Following 2.17: 99 workspace[ 0 ] = B * SQRT2 * ( (3.0*B) - 2.0) / 12.0; 100 workspace[ 1 ] = ( (20.0*B2) - (12.0*B) + 1.0 ) / 128.0; 101 workspace[ 2 ] = B * SQRT2 * ( (20.0*B) - 1.0) / 960.0; 102 workspace[ 3 ] = ( (16.0*B2) + (30.0*B) - 15.0) / 4608.0; 103 workspace[ 4 ] = B * SQRT2 * ( (21.0*B) + 32) / 53760.0; 104 workspace[ 5 ] = (-(32.0*B2) + 63.0) / 368640.0; 105 workspace[ 6 ] = -B * SQRT2 * ( (120.0*B) + 17.0) / 25804480.0; 106 terms[ 2 ] = evalpoly( workspace, eta0 ); 107 108 // Eq Following 2.17: 109 workspace[ 0 ] = B * SQRT2 * ( (-75*B2) + (80.0*B) - 16.0) / 480.0; 110 workspace[ 1 ] = ( (-1080.0*B3) + (868.0*B2) - (90.0*B) - 45.0) / 9216.0; 111 workspace[ 2 ] = B * SQRT2 * ( (-1190.0*B2) + (84.0*B) + 373.0) / 53760.0; 112 workspace[ 3 ] = ( (-2240.0*B3)-(2508.0*B2)+(2100.0*B)-165.0 ) / 368640.0; 113 workspace[ 4 ] = 0.0; 114 workspace[ 5 ] = 0.0; 115 workspace[ 6 ] = 0.0; 116 terms[ 3 ] = evalpoly( workspace, eta0 ); 117 118 // Bring them together to get a final estimate for eta: 119 eta = evalpoly( terms, 1.0/a ); 120 121 // Now we need to convert eta to the return value `x`, by solving the appropriate quadratic equation: 122 eta2 = eta * eta; 123 c = -exp( -eta2 / 2.0 ); 124 if ( eta2 === 0.0 ) { 125 return 0.5; 126 } 127 return ( 1.0 + ( eta * sqrt( ( 1.0+c ) / eta2 ) ) ) / 2.0; 128 } 129 130 131 // EXPORTS // 132 133 module.exports = temme1;