powm1.js (2922B)
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_60_0/boost/math/special_functions/powm1.hpp}. The implementation follows the original, but has been modified for JavaScript. 22 * 23 * ```text 24 * (C) Copyright John Maddock 2006. 25 * 26 * Use, modification and distribution are subject to the 27 * Boost Software License, Version 1.0. (See accompanying file 28 * LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) 29 * ``` 30 */ 31 32 'use strict'; 33 34 // MODULES // 35 36 var isnan = require( './../../../../base/assert/is-nan' ); 37 var abs = require( './../../../../base/special/abs' ); 38 var expm1 = require( './../../../../base/special/expm1' ); 39 var ln = require( './../../../../base/special/ln' ); 40 var pow = require( './../../../../base/special/pow' ); 41 var trunc = require( './../../../../base/special/trunc' ); 42 43 44 // MAIN // 45 46 /** 47 * Evaluates `bˣ - 1`. 48 * 49 * @param {number} b - base 50 * @param {number} x - exponent 51 * @returns {number} function value 52 * 53 * @example 54 * var y = powm1( 2.0, 3.0 ); 55 * // returns 7.0 56 * 57 * @example 58 * var y = powm1( 4.0, 0.5 ); 59 * // returns 1.0 60 * 61 * @example 62 * var y = powm1( 0.0, 100.0 ); 63 * // returns -1.0 64 * 65 * @example 66 * var y = powm1( 100.0, 0.0 ); 67 * // returns 0.0 68 * 69 * @example 70 * var y = powm1( 0.0, 0.0 ); 71 * // returns 0.0 72 * 73 * @example 74 * var y = powm1( 3.141592653589793, 5.0 ); 75 * // returns ~305.0197 76 * 77 * @example 78 * var y = powm1( NaN, 3.0 ); 79 * // returns NaN 80 * 81 * @example 82 * var y = powm1( 5.0, NaN ); 83 * // returns NaN 84 */ 85 function powm1( b, x ) { 86 var y; 87 if ( 88 isnan( b ) || 89 isnan( x ) 90 ) { 91 return NaN; 92 } 93 if ( x === 0.0 ) { 94 // Any number raised to zero (including 0) is always 1 => b^0 - 1 = 0 95 return 0.0; 96 } 97 if ( b === 0.0 ) { 98 // Zero raised to any number (except 0) is always zero => 0^x - 1 = -1 99 return -1.0; 100 } 101 if ( b < 0.0 && x%2.0 === 0 ) { 102 // If `x` is even, recognize that `(-b)**x == (b)**x`... 103 b = -b; 104 } 105 if ( b > 0.0 ) { 106 if ( 107 abs( x*(b-1.0) ) < 0.5 || 108 abs( x ) < 0.2 109 ) { 110 // No good/quick approximation for ln(b)*x, so we have to evaluate... 111 y = ln( b ) * x; 112 if ( y < 0.5 ) { 113 return expm1( y ); 114 } 115 } 116 } else if ( trunc( x ) !== x ) { 117 // Exponentiation would yield a complex result... 118 return NaN; 119 } 120 return pow( b, x ) - 1.0; 121 } 122 123 124 // EXPORTS // 125 126 module.exports = powm1;