time-to-botec

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

tan.js (3537B)


      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_tan.c}. The implementation follows the original, but has been modified for JavaScript.
     22 *
     23 * ```text
     24 * Copyright (C) 1993 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 getHighWord = require( '@stdlib/number/float64/base/get-high-word' );
     38 var kernelTan = require( './../../../../base/special/kernel-tan' );
     39 var rempio2 = require( './../../../../base/special/rempio2' );
     40 
     41 
     42 // VARIABLES //
     43 
     44 // Scratch buffer:
     45 var buffer = [ 0.0, 0.0 ]; // WARNING: not thread safe
     46 
     47 // High word absolute value mask: 0x7fffffff => 01111111111111111111111111111111
     48 var HIGH_WORD_ABS_MASK = 0x7fffffff|0; // asm type annotation
     49 
     50 // High word for pi/4: 0x3fe921fb => 00111111111010010010000111111011
     51 var HIGH_WORD_PIO4 = 0x3fe921fb|0; // asm type annotation
     52 
     53 // High word exponent mask: 0x7ff00000 => 01111111111100000000000000000000
     54 var HIGH_WORD_EXPONENT_MASK = 0x7ff00000|0; // asm type annotation
     55 
     56 // High word for a small value: 2^-27 = 7.450580596923828e-9 => high word => 0x3e400000 => 00111110010000000000000000000000
     57 var HIGH_WORD_TWO_NEG_27 = 0x3e400000|0; // asm type annotation
     58 
     59 
     60 // MAIN //
     61 
     62 /**
     63 * Evaluates the tangent of a number.
     64 *
     65 * ## Method
     66 *
     67 * -   Let \\(S\\), \\(C\\), and \\(T\\) denote the \\(\sin\\), \\(\cos\\), and \\(\tan\\), respectively, on \\(\[-\pi/4, +\pi/4\]\\).
     68 *
     69 * -   Reduce the argument \\(x\\) to \\(y1+y2 = x-k\pi/2\\) in \\(\[-\pi/4, +\pi/4\]\\), and let \\(n = k \mod 4\\).
     70 *
     71 * -   We have
     72 *
     73 *     | n | sin(x) | cos(x) | tan(x) |
     74 *     | - | ------ | ------ | ------ |
     75 *     | 0 |    S   |    C   |   T    |
     76 *     | 1 |    C   |   -S   |  -1/T  |
     77 *     | 2 |   -S   |   -C   |   T    |
     78 *     | 3 |   -C   |    S   |  -1/T  |
     79 *
     80 *
     81 * @param {number} x - input value (in radians)
     82 * @returns {number} tangent
     83 *
     84 * @example
     85 * var v = tan( 0.0 );
     86 * // returns ~0.0
     87 *
     88 * @example
     89 * var v = tan( -3.141592653589793/4.0 );
     90 * // returns ~-1.0
     91 *
     92 * @example
     93 * var v = tan( 3.141592653589793/4.0 );
     94 * // returns ~1.0
     95 *
     96 * @example
     97 * var v = tan( NaN );
     98 * // returns NaN
     99 */
    100 function tan( x ) {
    101 	var ix;
    102 	var n;
    103 
    104 	ix = getHighWord( x );
    105 	ix &= HIGH_WORD_ABS_MASK;
    106 
    107 	// Case: |x| ~< π/4
    108 	if ( ix <= HIGH_WORD_PIO4 ) {
    109 		// Case: |x| < 2**-27
    110 		if ( ix < HIGH_WORD_TWO_NEG_27 ) {
    111 			return x;
    112 		}
    113 		return kernelTan( x, 0.0, 1 );
    114 	}
    115 	// Case: tan(Inf or NaN) is NaN
    116 	if ( ix >= HIGH_WORD_EXPONENT_MASK ) {
    117 		return NaN;
    118 	}
    119 	// Argument reduction needed...
    120 	n = rempio2( x, buffer );
    121 	return kernelTan( buffer[ 0 ], buffer[ 1 ], 1-((n&1)<<1) );
    122 }
    123 
    124 
    125 // EXPORTS //
    126 
    127 module.exports = tan;