time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

atanh.js (3207B)


      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/e_atanh.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 isnan = require( './../../../../base/assert/is-nan' );
     38 var log1p = require( './../../../../base/special/log1p' );
     39 var PINF = require( '@stdlib/constants/float64/pinf' );
     40 var NINF = require( '@stdlib/constants/float64/ninf' );
     41 
     42 
     43 // VARIABLES //
     44 
     45 var NEAR_ZERO = 1.0 / (1 << 28); // 2**-28
     46 
     47 
     48 // MAIN //
     49 
     50 /**
     51 * Computes the hyperbolic arctangent of a number.
     52 *
     53 * ## Method
     54 *
     55 * 1.  Reduce \\( x \\) to positive by \\( \operatorname{atanh}(-x) = -\operatorname{atanh}(x) \\)
     56 *
     57 * 2.  For \\( x \ge 0.5 \\), we calculate
     58 *
     59 *     ```tex
     60 *     \operatorname{atanh}(x) = \frac{1}{2} \cdot \log\left( 1 + \tfrac{2x}{1-x} \right) = \frac{1}{2} \cdot \operatorname{log1p}\left( 2 \tfrac{x}{1-x} \right)
     61 *     ```
     62 *
     63 *     For \\( x < 0.5 \\), we have
     64 *
     65 *     ```tex
     66 *     \operatorname{atanh}(x) = \frac{1}{2} \cdot \operatorname{log1p}\left( 2x + \tfrac{2x^2}{1-x} \right)
     67 *     ```
     68 *
     69 * ## Special Cases
     70 *
     71 * ```tex
     72 * \begin{align*}
     73 * \operatorname{atanh}(\mathrm{NaN}) &= \mathrm{NaN}\\
     74 * \operatorname{atanh}(1.0) &= \infty \\
     75 * \operatorname{atanh}(-1.0) &= -\infty \\
     76 * \end{align*}
     77 * ```
     78 *
     79 * @param {number} x - input value
     80 * @returns {number} hyperbolic arctangent (in radians)
     81 *
     82 * @example
     83 * var v = atanh( 0.0 );
     84 * // returns 0.0
     85 *
     86 * @example
     87 * var v = atanh( 0.9 );
     88 * // returns ~1.472
     89 *
     90 * @example
     91 * var v = atanh( 1.0 );
     92 * // returns Infinity
     93 *
     94 * @example
     95 * var v = atanh( -1.0 );
     96 * // returns -Infinity
     97 *
     98 * @example
     99 * var v = atanh( NaN );
    100 * // returns NaN
    101 */
    102 function atanh( x ) {
    103 	var sgn;
    104 	var t;
    105 	if ( isnan( x ) ) {
    106 		return NaN;
    107 	}
    108 	if ( x < -1.0 || x > 1.0 ) {
    109 		return NaN;
    110 	}
    111 	if ( x === 1.0 ) {
    112 		return PINF;
    113 	}
    114 	if ( x === -1.0 ) {
    115 		return NINF;
    116 	}
    117 	if ( x < 0.0 ) {
    118 		sgn = true;
    119 		x = -x;
    120 	}
    121 	// Case: |x| < 2**-28
    122 	if ( x < NEAR_ZERO ) {
    123 		return ( sgn ) ? -x : x;
    124 	}
    125 	if ( x < 0.5 ) {
    126 		t = x + x;
    127 		t = 0.5 * log1p( t + ( t*x/(1-x) ) );
    128 	} else {
    129 		t = 0.5 * log1p( (x+x) / (1-x) );
    130 	}
    131 	return ( sgn ) ? -t : t;
    132 }
    133 
    134 
    135 // EXPORTS //
    136 
    137 module.exports = atanh;