UNPKG

@stdlib/math-base-special-asin

Version:

Compute the arcsine of a double-precision floating-point number.

139 lines (125 loc) 3.34 kB
/** * @license Apache-2.0 * * Copyright (c) 2018 The Stdlib Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * * ## Notice * * The original C code, long comment, copyright, license, and constants are from [Cephes]{@link http://www.netlib.org/cephes}. The implementation follows the original, but has been modified for JavaScript. * * ```text * Copyright 1984, 1995, 2000 by Stephen L. Moshier * * Some software in this archive may be from the book _Methods and Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster International, 1989) or from the Cephes Mathematical Library, a commercial product. In either event, it is copyrighted by the author. What you see here may be used freely but it comes with no support or guarantee. * * Stephen L. Moshier * moshier@na-net.ornl.gov * ``` */ 'use strict'; // MODULES // var isnan = require( '@stdlib/math-base-assert-is-nan' ); var sqrt = require( '@stdlib/math-base-special-sqrt' ); var PIO4 = require( '@stdlib/constants-float64-fourth-pi' ); var ratevalPQ = require( './rational_pq.js' ); var ratevalRS = require( './rational_rs.js' ); // VARIABLES // var MOREBITS = 6.123233995736765886130e-17; // pi/2 = PIO2 + MOREBITS // MAIN // /** * Computes the arcsine of a double-precision floating-point number. * * ## Method * * - A rational function of the form * * ```tex * x + x^3 \frac{P(x^2)}{Q(x^2)} * ``` * * is used for \\(\|x\|\\) in the interval \\(\[0, 0.5\]\\). If \\(\|x\| > 0.5\\), it is transformed by the identity * * ```tex * \operatorname{asin}(x) = \frac{\pi}{2} - 2 \operatorname{asin}( \sqrt{ (1-x)/2 } ) * ``` * * ## Notes * * - Relative error: * * | arithmetic | domain | # trials | peak | rms | * |:-----------|:-------|:---------|:--------|:--------| * | DEC | -1, 1 | 40000 | 2.6e-17 | 7.1e-18 | * | IEEE | -1, 1 | 10^6 | 1.9e-16 | 5.4e-17 | * * @param {number} x - input value * @returns {number} arcsine (in radians) * * @example * var v = asin( 0.0 ); * // returns ~0.0 * * @example * var v = asin( 3.141592653589793/4.0 ); * // returns ~0.903 * * @example * var v = asin( -3.141592653589793/6.0 ); * // returns ~-0.551 * * @example * var v = asin( NaN ); * // returns NaN */ function asin( x ) { var sgn; var zz; var a; var p; var z; if ( isnan( x ) ) { return NaN; } if ( x > 0.0 ) { a = x; } else { sgn = true; a = -x; } if ( a > 1.0 ) { return NaN; } if ( a > 0.625 ) { // arcsin(1-x) = pi/2 - sqrt(2x)(1+R(x)) zz = 1.0 - a; p = zz * ratevalRS( zz ); zz = sqrt( zz + zz ); z = PIO4 - zz; zz = ( zz*p ) - MOREBITS; z -= zz; z += PIO4; } else { if ( a < 1.0e-8 ) { return x; } zz = a * a; z = zz * ratevalPQ( zz ); z = ( a*z ) + a; } return ( sgn ) ? -z : z; } // EXPORTS // module.exports = asin;