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;