time-to-botec

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

kernel_cos.js (3589B)


      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_cos.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 polyval13 = require( './polyval_c13.js' );
     38 var polyval46 = require( './polyval_c46.js' );
     39 
     40 
     41 // MAIN //
     42 
     43 /**
     44 * Computes the cosine on \\( \[-\pi/4, \pi/4] \\), where \\( \pi/4 \approx 0.785398164 \\).
     45 *
     46 * ## Method
     47 *
     48 * -   Since \\( \cos(-x) = \cos(x) \\), we need only to consider positive \\(x\\).
     49 *
     50 * -   If \\( x < 2^{-27} \\), return \\(1\\) which is inexact if \\( x \ne 0 \\).
     51 *
     52 * -   \\( cos(x) \\) is approximated by a polynomial of degree \\(14\\) on \\( \[0,\pi/4] \\).
     53 *
     54 *     ```tex
     55 *     \cos(x) \approx 1 - \frac{x \cdot x}{2} + C_1 \cdot x^4 + \ldots + C_6 \cdot x^{14}
     56 *     ```
     57 *
     58 *     where the Remez error is
     59 *
     60 *     ```tex
     61 *     \left| \cos(x) - \left( 1 - \frac{x^2}{2} + C_1x^4 + C_2x^6 + C_3x^8 + C_4x^{10} + C_5x^{12} + C_6x^{15} \right) \right| \le 2^{-58}
     62 *     ```
     63 *
     64 * -   Let \\( C_1x^4 + C_2x^6 + C_3x^8 + C_4x^{10} + C_5x^{12} + C_6x^{14} \\), then
     65 *
     66 *     ```tex
     67 *     \cos(x) \approx 1 - \frac{x \cdot x}{2} + r
     68 *     ```
     69 *
     70 *     Since
     71 *
     72 *     ```tex
     73 *     \cos(x+y) \approx \cos(x) - \sin(x) \cdot y \approx \cos(x) - x \cdot y
     74 *     ```
     75 *
     76 *     a correction term is necessary in \\( \cos(x) \\). Hence,
     77 *
     78 *     ```tex
     79 *     \cos(x+y) = 1 - \left( \frac{x \cdot x}{2} - (r - x \cdot y) \right)
     80 *     ```
     81 *
     82 *     For better accuracy, rearrange to
     83 *
     84 *     ```tex
     85 *     \cos(x+y) \approx w + \left( t + ( r - x \cdot y ) \right)
     86 *     ```
     87 *
     88 *     where \\( w = 1 - \frac{x \cdot x}{2} \\) and \\( t \\) is a tiny correction term (\\( 1 - \frac{x \cdot x}{2} = w + t \\) exactly in infinite precision). The exactness of \\(w + t\\) in infinite precision depends on \\(w\\) and \\(t\\) having the same precision as \\(x\\).
     89 *
     90 *
     91 * @param {number} x - input value (in radians, assumed to be bounded by ~pi/4 in magnitude)
     92 * @param {number} y - tail of `x`
     93 * @returns {number} cosine
     94 *
     95 * @example
     96 * var v = kernelCos( 0.0, 0.0 );
     97 * // returns ~1.0
     98 *
     99 * @example
    100 * var v = kernelCos( 3.141592653589793/6.0, 0.0 );
    101 * // returns ~0.866
    102 *
    103 * @example
    104 * var v = kernelCos( 0.785, -1.144e-17 );
    105 * // returns ~0.707
    106 *
    107 * @example
    108 * var v = kernelCos( NaN, 0.0 );
    109 * // returns NaN
    110 */
    111 function kernelCos( x, y ) {
    112 	var hz;
    113 	var r;
    114 	var w;
    115 	var z;
    116 
    117 	z = x * x;
    118 	w = z * z;
    119 	r = z * polyval13( z );
    120 	r += w * w * polyval46( z );
    121 	hz = 0.5 * z;
    122 	w = 1.0 - hz;
    123 	return w + ( ((1.0-w) - hz) + ((z*r) - (x*y)) );
    124 }
    125 
    126 
    127 // EXPORTS //
    128 
    129 module.exports = kernelCos;