time-to-botec

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

atan.js (3508B)


      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, long comment, copyright, license, and constants are from [Cephes]{@link http://www.netlib.org/cephes}. The implementation follows the original, but has been modified for JavaScript.
     22 *
     23 * ```text
     24 * Copyright 1984, 1995, 2000 by Stephen L. Moshier
     25 *
     26 * Some software in this archive may be from the book _Methods and Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster International, 1989) or from the Cephes Mathematical Library, a commercial product. In either event, it is copyrighted by the author. What you see here may be used freely but it comes with no support or guarantee.
     27 *
     28 * Stephen L. Moshier
     29 * moshier@na-net.ornl.gov
     30 * ```
     31 */
     32 
     33 'use strict';
     34 
     35 // MODULES //
     36 
     37 var isnan = require( './../../../../base/assert/is-nan' );
     38 var PINF = require( '@stdlib/constants/float64/pinf' );
     39 var PIO2 = require( '@stdlib/constants/float64/half-pi' );
     40 var PIO4 = require( '@stdlib/constants/float64/fourth-pi' );
     41 var NINF = require( '@stdlib/constants/float64/ninf' );
     42 var polyvalP = require( './polyval_p.js' );
     43 var polyvalQ = require( './polyval_q.js' );
     44 
     45 
     46 // VARIABLES //
     47 
     48 var MOREBITS = 6.123233995736765886130e-17; // pi/2 = PIO2 + MOREBITS.
     49 var T3P8 = 2.41421356237309504880; // tan( 3*pi/8 )
     50 
     51 
     52 // MAIN //
     53 
     54 /**
     55 * Computes the arctangent of a number.
     56 *
     57 * ## Method
     58 *
     59 * -   Range reduction is from three intervals into the interval from 0 to 0.66. The approximant uses a rational function of degree 4/5 of the form
     60 *
     61 *     ```tex
     62 *     x + x^3 \frac{P(x)}{Q(x)}
     63 *     ```
     64 *
     65 * ## Notes
     66 *
     67 * -   Relative error:
     68 *
     69 *     | arithmetic | domain  | # trials | peak    | rms     |
     70 *     |:-----------|:--------|:---------|:--------|:--------|
     71 *     | DEC        | -10, 10 | 50000    | 2.4e-17 | 8.3e-18 |
     72 *     | IEEE       | -10, 10 | 10^6     | 1.8e-16 | 5.0e-17 |
     73 *
     74 * @param {number} x - input value
     75 * @returns {number} arctangent (in radians)
     76 *
     77 * @example
     78 * var v = atan( 0.0 );
     79 * // returns ~0.0
     80 *
     81 * @example
     82 * var PI = require( '@stdlib/constants/float64/pi' );
     83 *
     84 * var v = atan( -PI/4.0 );
     85 * // returns ~-0.666
     86 *
     87 * @example
     88 * var PI = require( '@stdlib/constants/float64/pi' );
     89 *
     90 * var v = atan( PI/4.0 );
     91 * // returns ~0.666
     92 *
     93 * @example
     94 * var v = atan( NaN );
     95 * // returns NaN
     96 */
     97 function atan( x ) {
     98 	var flg;
     99 	var sgn;
    100 	var y;
    101 	var z;
    102 	if ( isnan( x ) || x === 0.0 ) {
    103 		return x;
    104 	}
    105 	if ( x === PINF ) {
    106 		return PIO2;
    107 	}
    108 	if ( x === NINF ) {
    109 		return -PIO2;
    110 	}
    111 	if ( x < 0.0 ) {
    112 		sgn = true;
    113 		x = -x;
    114 	}
    115 	// Range reduction:
    116 	flg = 0;
    117 	if ( x > T3P8 ) {
    118 		y = PIO2;
    119 		flg = 1;
    120 		x = -( 1.0/x );
    121 	}
    122 	else if ( x <= 0.66 ) {
    123 		y = 0.0;
    124 	}
    125 	else {
    126 		y = PIO4;
    127 		flg = 2;
    128 		x = (x-1.0) / (x+1.0);
    129 	}
    130 	z = x * x;
    131 	z = z*polyvalP( z ) / polyvalQ( z );
    132 	z = ( x*z ) + x;
    133 	if ( flg === 2 ) {
    134 		z += 0.5 * MOREBITS;
    135 	}
    136 	else if ( flg === 1 ) {
    137 		z += MOREBITS;
    138 	}
    139 	y += z;
    140 	return ( sgn ) ? -y : y;
    141 }
    142 
    143 
    144 // EXPORTS //
    145 
    146 module.exports = atan;