kernel_sin.js (3756B)
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/k_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 // VARIABLES // 36 37 var S1 = -1.66666666666666324348e-01; // 0xBFC55555, 0x55555549 38 var S2 = 8.33333333332248946124e-03; // 0x3F811111, 0x1110F8A6 39 var S3 = -1.98412698298579493134e-04; // 0xBF2A01A0, 0x19C161D5 40 var S4 = 2.75573137070700676789e-06; // 0x3EC71DE3, 0x57B1FE7D 41 var S5 = -2.50507602534068634195e-08; // 0xBE5AE5E6, 0x8A2B9CEB 42 var S6 = 1.58969099521155010221e-10; // 0x3DE5D93A, 0x5ACFD57C 43 44 45 // MAIN // 46 47 /** 48 * Computes the sine on \\( \approx \[-\pi/4, \pi/4] \\) (except on \\(-0\\)), where \\( \pi/4 \approx 0.7854 \\). 49 * 50 * ## Method 51 * 52 * - Since \\( \sin(-x) = -\sin(x) \\), we need only to consider positive \\(x\\). 53 * 54 * - Callers must return \\( \sin(-0) = -0 \\) without calling here since our odd polynomial is not evaluated in a way that preserves \\(-0\\). Callers may do the optimization \\( \sin(x) \approx x \\) for tiny \\(x\\). 55 * 56 * - \\( \sin(x) \\) is approximated by a polynomial of degree \\(13\\) on \\( \left\[0,\tfrac{pi}{4}\right] \\) 57 * 58 * ```tex 59 * \sin(x) \approx x + S_1 \cdot x^3 + \ldots + S_6 \cdot x^{13} 60 * ``` 61 * 62 * where 63 * 64 * ```tex 65 * \left| \frac{\sin(x)}{x} \left( 1 + S_1 \cdot x + S_2 \cdot x + S_3 \cdot x + S_4 \cdot x + S_5 \cdot x + S_6 \cdot x \right) \right| \le 2^{-58} 66 * ``` 67 * 68 * - We have 69 * 70 * ```tex 71 * \sin(x+y) = \sin(x) + \sin'(x') \cdot y \approx \sin(x) + (1-x*x/2) \cdot y 72 * ``` 73 * 74 * For better accuracy, let 75 * 76 * ```tex 77 * r = x^3 * \left( S_2 + x^2 \cdot \left( S_3 + x^2 * \left( S_4 + x^2 \cdot ( S_5+x^2 \cdot S_6 ) \right) \right) \right) 78 * ``` 79 * 80 * then 81 * 82 * ```tex 83 * \sin(x) = x + \left( S_1 \cdot x + ( x \cdot (r-y/2) + y ) \right) 84 * ``` 85 * 86 * 87 * @param {number} x - input value (in radians, assumed to be bounded by `~pi/4` in magnitude) 88 * @param {number} y - tail of `x` 89 * @returns {number} sine 90 * 91 * @example 92 * var v = kernelSin( 0.0, 0.0 ); 93 * // returns ~0.0 94 * 95 * @example 96 * var v = kernelSin( 3.141592653589793/6.0, 0.0 ); 97 * // returns ~0.5 98 * 99 * @example 100 * var v = kernelSin( 0.619, 9.279e-18 ); 101 * // returns ~0.58 102 * 103 * @example 104 * var v = kernelSin( NaN, 0.0 ); 105 * // returns NaN 106 * 107 * @example 108 * var v = kernelSin( 3.0, NaN ); 109 * // returns NaN 110 * 111 * @example 112 * var v = kernelSin( NaN, NaN ); 113 * // returns NaN 114 */ 115 function kernelSin( x, y ) { 116 var r; 117 var v; 118 var w; 119 var z; 120 121 z = x * x; 122 w = z * z; 123 r = S2 + (z * (S3 + (z*S4))) + (z * w * (S5 + (z*S6))); 124 v = z * x; 125 if ( y === 0.0 ) { 126 return x + (v * (S1 + (z*r))); 127 } 128 return x - (((z*((0.5*y) - (v*r))) - y) - (v*S1)); 129 } 130 131 132 // EXPORTS // 133 134 module.exports = kernelSin;