125c28e83SPiotr Jasiukajtis /* 225c28e83SPiotr Jasiukajtis * CDDL HEADER START 325c28e83SPiotr Jasiukajtis * 425c28e83SPiotr Jasiukajtis * The contents of this file are subject to the terms of the 525c28e83SPiotr Jasiukajtis * Common Development and Distribution License (the "License"). 625c28e83SPiotr Jasiukajtis * You may not use this file except in compliance with the License. 725c28e83SPiotr Jasiukajtis * 825c28e83SPiotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 925c28e83SPiotr Jasiukajtis * or http://www.opensolaris.org/os/licensing. 1025c28e83SPiotr Jasiukajtis * See the License for the specific language governing permissions 1125c28e83SPiotr Jasiukajtis * and limitations under the License. 1225c28e83SPiotr Jasiukajtis * 1325c28e83SPiotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each 1425c28e83SPiotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1525c28e83SPiotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the 1625c28e83SPiotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying 1725c28e83SPiotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner] 1825c28e83SPiotr Jasiukajtis * 1925c28e83SPiotr Jasiukajtis * CDDL HEADER END 2025c28e83SPiotr Jasiukajtis */ 2125c28e83SPiotr Jasiukajtis 2225c28e83SPiotr Jasiukajtis /* 2325c28e83SPiotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 2425c28e83SPiotr Jasiukajtis */ 2525c28e83SPiotr Jasiukajtis /* 2625c28e83SPiotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 2725c28e83SPiotr Jasiukajtis * Use is subject to license terms. 2825c28e83SPiotr Jasiukajtis */ 2925c28e83SPiotr Jasiukajtis 30*ddc0e0b5SRichard Lowe #pragma weak __asin = asin 3125c28e83SPiotr Jasiukajtis 3225c28e83SPiotr Jasiukajtis /* INDENT OFF */ 3325c28e83SPiotr Jasiukajtis /* 3425c28e83SPiotr Jasiukajtis * asin(x) 3525c28e83SPiotr Jasiukajtis * Method : 3625c28e83SPiotr Jasiukajtis * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ... 3725c28e83SPiotr Jasiukajtis * we approximate asin(x) on [0,0.5] by 3825c28e83SPiotr Jasiukajtis * asin(x) = x + x*x^2*R(x^2) 3925c28e83SPiotr Jasiukajtis * where 4025c28e83SPiotr Jasiukajtis * R(x^2) is a rational approximation of (asin(x)-x)/x^3 4125c28e83SPiotr Jasiukajtis * and its remez error is bounded by 4225c28e83SPiotr Jasiukajtis * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75) 4325c28e83SPiotr Jasiukajtis * 4425c28e83SPiotr Jasiukajtis * For x in [0.5,1] 4525c28e83SPiotr Jasiukajtis * asin(x) = pi/2-2*asin(sqrt((1-x)/2)) 4625c28e83SPiotr Jasiukajtis * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2; 4725c28e83SPiotr Jasiukajtis * then for x>0.98 4825c28e83SPiotr Jasiukajtis * asin(x) = pi/2 - 2*(s+s*z*R(z)) 4925c28e83SPiotr Jasiukajtis * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) 5025c28e83SPiotr Jasiukajtis * For x<=0.98, let pio4_hi = pio2_hi/2, then 5125c28e83SPiotr Jasiukajtis * f = hi part of s; 5225c28e83SPiotr Jasiukajtis * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) 5325c28e83SPiotr Jasiukajtis * and 5425c28e83SPiotr Jasiukajtis * asin(x) = pi/2 - 2*(s+s*z*R(z)) 5525c28e83SPiotr Jasiukajtis * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) 5625c28e83SPiotr Jasiukajtis * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) 5725c28e83SPiotr Jasiukajtis * 5825c28e83SPiotr Jasiukajtis * Special cases: 5925c28e83SPiotr Jasiukajtis * if x is NaN, return x itself; 6025c28e83SPiotr Jasiukajtis * if |x|>1, return NaN with invalid signal. 6125c28e83SPiotr Jasiukajtis * 6225c28e83SPiotr Jasiukajtis */ 6325c28e83SPiotr Jasiukajtis /* INDENT ON */ 6425c28e83SPiotr Jasiukajtis 6525c28e83SPiotr Jasiukajtis #include "libm_protos.h" /* _SVID_libm_error */ 6625c28e83SPiotr Jasiukajtis #include "libm_macros.h" 6725c28e83SPiotr Jasiukajtis #include <math.h> 6825c28e83SPiotr Jasiukajtis 6925c28e83SPiotr Jasiukajtis /* INDENT OFF */ 7025c28e83SPiotr Jasiukajtis static const double xxx[] = { 7125c28e83SPiotr Jasiukajtis /* one */ 1.00000000000000000000e+00, /* 3FF00000, 00000000 */ 7225c28e83SPiotr Jasiukajtis /* huge */ 1.000e+300, 7325c28e83SPiotr Jasiukajtis /* pio2_hi */ 1.57079632679489655800e+00, /* 3FF921FB, 54442D18 */ 7425c28e83SPiotr Jasiukajtis /* pio2_lo */ 6.12323399573676603587e-17, /* 3C91A626, 33145C07 */ 7525c28e83SPiotr Jasiukajtis /* pio4_hi */ 7.85398163397448278999e-01, /* 3FE921FB, 54442D18 */ 7625c28e83SPiotr Jasiukajtis /* coefficient for R(x^2) */ 7725c28e83SPiotr Jasiukajtis /* pS0 */ 1.66666666666666657415e-01, /* 3FC55555, 55555555 */ 7825c28e83SPiotr Jasiukajtis /* pS1 */ -3.25565818622400915405e-01, /* BFD4D612, 03EB6F7D */ 7925c28e83SPiotr Jasiukajtis /* pS2 */ 2.01212532134862925881e-01, /* 3FC9C155, 0E884455 */ 8025c28e83SPiotr Jasiukajtis /* pS3 */ -4.00555345006794114027e-02, /* BFA48228, B5688F3B */ 8125c28e83SPiotr Jasiukajtis /* pS4 */ 7.91534994289814532176e-04, /* 3F49EFE0, 7501B288 */ 8225c28e83SPiotr Jasiukajtis /* pS5 */ 3.47933107596021167570e-05, /* 3F023DE1, 0DFDF709 */ 8325c28e83SPiotr Jasiukajtis /* qS1 */ -2.40339491173441421878e+00, /* C0033A27, 1C8A2D4B */ 8425c28e83SPiotr Jasiukajtis /* qS2 */ 2.02094576023350569471e+00, /* 40002AE5, 9C598AC8 */ 8525c28e83SPiotr Jasiukajtis /* qS3 */ -6.88283971605453293030e-01, /* BFE6066C, 1B8D0159 */ 8625c28e83SPiotr Jasiukajtis /* qS4 */ 7.70381505559019352791e-02 /* 3FB3B8C5, B12E9282 */ 8725c28e83SPiotr Jasiukajtis }; 8825c28e83SPiotr Jasiukajtis #define one xxx[0] 8925c28e83SPiotr Jasiukajtis #define huge xxx[1] 9025c28e83SPiotr Jasiukajtis #define pio2_hi xxx[2] 9125c28e83SPiotr Jasiukajtis #define pio2_lo xxx[3] 9225c28e83SPiotr Jasiukajtis #define pio4_hi xxx[4] 9325c28e83SPiotr Jasiukajtis #define pS0 xxx[5] 9425c28e83SPiotr Jasiukajtis #define pS1 xxx[6] 9525c28e83SPiotr Jasiukajtis #define pS2 xxx[7] 9625c28e83SPiotr Jasiukajtis #define pS3 xxx[8] 9725c28e83SPiotr Jasiukajtis #define pS4 xxx[9] 9825c28e83SPiotr Jasiukajtis #define pS5 xxx[10] 9925c28e83SPiotr Jasiukajtis #define qS1 xxx[11] 10025c28e83SPiotr Jasiukajtis #define qS2 xxx[12] 10125c28e83SPiotr Jasiukajtis #define qS3 xxx[13] 10225c28e83SPiotr Jasiukajtis #define qS4 xxx[14] 10325c28e83SPiotr Jasiukajtis /* INDENT ON */ 10425c28e83SPiotr Jasiukajtis 10525c28e83SPiotr Jasiukajtis double 10625c28e83SPiotr Jasiukajtis asin(double x) { 10725c28e83SPiotr Jasiukajtis double t, w, p, q, c, r, s; 10825c28e83SPiotr Jasiukajtis int hx, ix, i; 10925c28e83SPiotr Jasiukajtis 11025c28e83SPiotr Jasiukajtis hx = ((int *) &x)[HIWORD]; 11125c28e83SPiotr Jasiukajtis ix = hx & 0x7fffffff; 11225c28e83SPiotr Jasiukajtis if (ix >= 0x3ff00000) { /* |x| >= 1 */ 11325c28e83SPiotr Jasiukajtis if (((ix - 0x3ff00000) | ((int *) &x)[LOWORD]) == 0) 11425c28e83SPiotr Jasiukajtis /* asin(1)=+-pi/2 with inexact */ 11525c28e83SPiotr Jasiukajtis return (x * pio2_hi + x * pio2_lo); 11625c28e83SPiotr Jasiukajtis else if (isnan(x)) 11725c28e83SPiotr Jasiukajtis #if defined(FPADD_TRAPS_INCOMPLETE_ON_NAN) 11825c28e83SPiotr Jasiukajtis return (ix >= 0x7ff80000 ? x : (x - x) / (x - x)); 11925c28e83SPiotr Jasiukajtis /* assumes sparc-like QNaN */ 12025c28e83SPiotr Jasiukajtis #else 12125c28e83SPiotr Jasiukajtis return (x - x) / (x - x); /* asin(|x|>1) is NaN */ 12225c28e83SPiotr Jasiukajtis #endif 12325c28e83SPiotr Jasiukajtis else 12425c28e83SPiotr Jasiukajtis return (_SVID_libm_err(x, x, 2)); 12525c28e83SPiotr Jasiukajtis } else if (ix < 0x3fe00000) { /* |x| < 0.5 */ 12625c28e83SPiotr Jasiukajtis if (ix < 0x3e400000) { /* if |x| < 2**-27 */ 12725c28e83SPiotr Jasiukajtis if ((i = (int) x) == 0) 12825c28e83SPiotr Jasiukajtis /* return x with inexact if x != 0 */ 12925c28e83SPiotr Jasiukajtis return (x); 13025c28e83SPiotr Jasiukajtis } 13125c28e83SPiotr Jasiukajtis t = x * x; 13225c28e83SPiotr Jasiukajtis p = t * (pS0 + t * (pS1 + t * (pS2 + t * (pS3 + 13325c28e83SPiotr Jasiukajtis t * (pS4 + t * pS5))))); 13425c28e83SPiotr Jasiukajtis q = one + t * (qS1 + t * (qS2 + t * (qS3 + t * qS4))); 13525c28e83SPiotr Jasiukajtis w = p / q; 13625c28e83SPiotr Jasiukajtis return (x + x * w); 13725c28e83SPiotr Jasiukajtis } 13825c28e83SPiotr Jasiukajtis /* 1 > |x| >= 0.5 */ 13925c28e83SPiotr Jasiukajtis w = one - fabs(x); 14025c28e83SPiotr Jasiukajtis t = w * 0.5; 14125c28e83SPiotr Jasiukajtis p = t * (pS0 + t * (pS1 + t * (pS2 + t * (pS3 + t * (pS4 + t * pS5))))); 14225c28e83SPiotr Jasiukajtis q = one + t * (qS1 + t * (qS2 + t * (qS3 + t * qS4))); 14325c28e83SPiotr Jasiukajtis s = sqrt(t); 14425c28e83SPiotr Jasiukajtis if (ix >= 0x3FEF3333) { /* if |x| > 0.975 */ 14525c28e83SPiotr Jasiukajtis w = p / q; 14625c28e83SPiotr Jasiukajtis t = pio2_hi - (2.0 * (s + s * w) - pio2_lo); 14725c28e83SPiotr Jasiukajtis } else { 14825c28e83SPiotr Jasiukajtis w = s; 14925c28e83SPiotr Jasiukajtis ((int *) &w)[LOWORD] = 0; 15025c28e83SPiotr Jasiukajtis c = (t - w * w) / (s + w); 15125c28e83SPiotr Jasiukajtis r = p / q; 15225c28e83SPiotr Jasiukajtis p = 2.0 * s * r - (pio2_lo - 2.0 * c); 15325c28e83SPiotr Jasiukajtis q = pio4_hi - 2.0 * w; 15425c28e83SPiotr Jasiukajtis t = pio4_hi - (p - q); 15525c28e83SPiotr Jasiukajtis } 15625c28e83SPiotr Jasiukajtis return (hx > 0 ? t : -t); 15725c28e83SPiotr Jasiukajtis } 158