asinh.js (3205B)
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 following copyright, license, and long comment were part of the original implementation available as part of [FreeBSD]{@link https://svnweb.freebsd.org/base/release/9.3.0/lib/msun/src/s_asinh.c?view=markup}. The implementation follows the original, but has been modified for JavaScript. 22 * 23 * ```text 24 * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. 25 * 26 * Developed at SunPro, a Sun Microsystems, Inc. business. 27 * Permission to use, copy, modify, and distribute this 28 * software is freely granted, provided that this notice 29 * is preserved. 30 * ``` 31 */ 32 33 'use strict'; 34 35 // MODULES // 36 37 var isinfinite = require( './../../../../base/assert/is-infinite' ); 38 var isnan = require( './../../../../base/assert/is-nan' ); 39 var log1p = require( './../../../../base/special/log1p' ); 40 var sqrt = require( './../../../../base/special/sqrt' ); 41 var LN2 = require( '@stdlib/constants/float64/ln-two' ); 42 var ln = require( './../../../../base/special/ln' ); 43 44 45 // VARIABLES // 46 47 var NEAR_ZERO = 1.0 / (1 << 28); // 2**-28 48 var HUGE = 1 << 28; // 2**28 49 50 51 // MAIN // 52 53 /** 54 * Computes the hyperbolic arcsine of a number. 55 * 56 * ## Method 57 * 58 * Based on 59 * 60 * ```tex 61 * \operatorname{asinh}(x) = \operatorname{sgn}(x) \cdot \log \left( |x| + \sqrt{x^2 + 1} \right) 62 * ``` 63 * 64 * we have 65 * 66 * ```tex 67 * \operatorname{asinh}(x) = \begin{cases} 68 * x & \text{ if } 1+x^2 =1, \\ 69 * \operatorname{sgn}(x) \cdot \left( \log(x) + \tfrac{\ln}{2} \right) & \text{ if large } |x| \\ 70 * \operatorname{sgn}(x) \cdot \log\left( 2 |x| + 1 / ( |x|+ \sqrt{x^2+1} ) \right) & \text{ if } |x| > 2 \\ 71 * \operatorname{sgn}(x) \cdot \operatorname{log1p}\left( |x| + \tfrac{x^2}{1 + \sqrt{1+x^2}} \right) & \text{otherwise} 72 * \end{cases} 73 * ``` 74 * 75 * @param {number} x - input value 76 * @returns {number} hyperbolic arcsine (in radians) 77 * 78 * @example 79 * var v = asinh( 0.0 ); 80 * // returns 0.0 81 * 82 * @example 83 * var v = asinh( 2.0 ); 84 * // returns ~1.444 85 * 86 * @example 87 * var v = asinh( -2.0 ); 88 * // returns ~-1.444 89 * 90 * @example 91 * var v = asinh( NaN ); 92 * // returns NaN 93 */ 94 function asinh( x ) { 95 var sgn; 96 var xx; 97 var t; 98 if ( isnan( x ) || isinfinite( x ) ) { 99 return x; 100 } 101 if ( x < 0.0 ) { 102 x = -x; 103 sgn = true; 104 } 105 // Case: |x| < 2**-28 106 if ( x < NEAR_ZERO ) { 107 t = x; 108 } 109 // Case: |x| > 2**28 110 else if ( x > HUGE ) { 111 t = ln( x ) + LN2; 112 } 113 // Case: 2**28 > |x| > 2.0 114 else if ( x > 2.0 ) { 115 t = ln( (2.0*x) + ( 1.0 / (sqrt( (x*x) + 1.0 ) + x) ) ); 116 } 117 // Case: 2.0 > |x| > 2**-28 118 else { 119 xx = x * x; 120 t = log1p( x + ( xx/(1.0 + sqrt(1.0 + xx)) ) ); 121 } 122 return ( sgn ) ? -t : t; 123 } 124 125 126 // EXPORTS // 127 128 module.exports = asinh;