time-to-botec

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

sin.js (3773B)


      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_sin.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 kernelCos = require( './../../../../base/special/kernel-cos' );
     39 var kernelSin = require( './../../../../base/special/kernel-sin' );
     40 var rempio2 = require( './../../../../base/special/rempio2' );
     41 
     42 
     43 // VARIABLES //
     44 
     45 // Absolute value mask: 0x7fffffff = 2147483647 => 01111111111111111111111111111111
     46 var ABS_MASK = 0x7fffffff|0; // asm type annotation
     47 
     48 // Exponent mask: 0x7ff00000 = 2146435072 => 01111111111100000000000000000000
     49 var EXPONENT_MASK = 0x7ff00000|0; // asm type annotation
     50 
     51 // High word for PI/4: 0x3fe921fb = 1072243195 => 00111111111010010010000111111011
     52 var PIO4_HIGH_WORD = 0x3fe921fb|0; // asm type annotation
     53 
     54 // 2^-26 = 1.4901161193847656e-8 => 0011111001010000000000000000000000000000000000000000000000000000 => high word => 00111110010100000000000000000000 => 0x3e500000 = 1045430272
     55 var SMALL_HIGH_WORD = 0x3e500000|0; // asm type annotation
     56 
     57 // Array for storing remainder elements:
     58 var Y = [ 0.0, 0.0 ]; // WARNING: not thread safe
     59 
     60 
     61 // MAIN //
     62 
     63 /**
     64 * Computes the sine of a number.
     65 *
     66 * ## Method
     67 *
     68 * -   Let \\(S\\), \\(C\\), and \\(T\\) denote the \\(\sin\\), \\(\cos\\), and \\(\tan\\), respectively, on \\(\[-\pi/4, +\pi/4\]\\).
     69 *
     70 * -   Reduce the argument \\(x\\) to \\(y1+y2 = x-k\pi/2\\) in \\(\[-\pi/4, +\pi/4\]\\), and let \\(n = k \mod 4\\).
     71 *
     72 * -   We have
     73 *
     74 *     | n | sin(x) | cos(x) | tan(x) |
     75 *     | - | ------ | ------ | ------ |
     76 *     | 0 |   S    |   C    |    T   |
     77 *     | 1 |   C    |  -S    |  -1/T  |
     78 *     | 2 |  -S    |  -C    |    T   |
     79 *     | 3 |  -C    |   S    |  -1/T  |
     80 *
     81 *
     82 * @param {number} x - input value (in radians)
     83 * @returns {number} sine
     84 *
     85 * @example
     86 * var v = sin( 0.0 );
     87 * // returns ~0.0
     88 *
     89 * @example
     90 * var v = sin( 3.141592653589793/2.0 );
     91 * // returns ~1.0
     92 *
     93 * @example
     94 * var v = sin( -3.141592653589793/6.0 );
     95 * // returns ~-0.5
     96 *
     97 * @example
     98 * var v = sin( NaN );
     99 * // returns NaN
    100 */
    101 function sin( x ) {
    102 	var ix;
    103 	var n;
    104 
    105 	ix = getHighWord( x );
    106 	ix &= ABS_MASK;
    107 
    108 	// Case: |x| ~< π/4
    109 	if ( ix <= PIO4_HIGH_WORD ) {
    110 		// Case: |x| ~< 2^-26
    111 		if ( ix < SMALL_HIGH_WORD ) {
    112 			return x;
    113 		}
    114 		return kernelSin( x, 0.0 );
    115 	}
    116 	// Case: x is NaN or infinity
    117 	if ( ix >= EXPONENT_MASK ) {
    118 		return NaN;
    119 	}
    120 	// Argument reduction...
    121 	n = rempio2( x, Y );
    122 	switch ( n & 3 ) {
    123 	case 0:
    124 		return kernelSin( Y[ 0 ], Y[ 1 ] );
    125 	case 1:
    126 		return kernelCos( Y[ 0 ], Y[ 1 ] );
    127 	case 2:
    128 		return -kernelSin( Y[ 0 ], Y[ 1 ] );
    129 	default:
    130 		return -kernelCos( Y[ 0 ], Y[ 1 ] );
    131 	}
    132 }
    133 
    134 
    135 // EXPORTS //
    136 
    137 module.exports = sin;