1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24 */ 25 /* 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 #if defined(ELFOBJ) 31 #pragma weak asinl = __asinl 32 #endif 33 34 /* 35 * asinl(x) = atan2l(x,sqrt(1-x*x)); 36 * 37 * For better accuracy, 1-x*x is computed as follows 38 * 1-x*x if x < 0.5, 39 * 2*(1-|x|)-(1-|x|)*(1-|x|) if x >= 0.5. 40 * 41 * Special cases: 42 * if x is NaN, return x itself; 43 * if |x|>1, return NaN with invalid signal. 44 */ 45 46 #include "libm.h" 47 48 static const long double zero = 0.0L, small = 1.0e-20L, half = 0.5L, one = 1.0L; 49 #ifndef lint 50 static const long double big = 1.0e+20L; 51 #endif 52 53 long double 54 asinl(long double x) { 55 long double t, w; 56 volatile long double dummy; 57 58 w = fabsl(x); 59 if (isnanl(x)) 60 return (x + x); 61 else if (w <= half) { 62 if (w < small) { 63 #ifndef lint 64 dummy = w + big; 65 /* inexact if w != 0 */ 66 #endif 67 return (x); 68 } else 69 return (atanl(x / sqrtl(one - x * x))); 70 } else if (w < one) { 71 t = one - w; 72 w = t + t; 73 return (atanl(x / sqrtl(w - t * t))); 74 } else if (w == one) 75 return (atan2l(x, zero)); /* asin(+-1) = +- PI/2 */ 76 else 77 return (zero / zero); /* |x| > 1: invalid */ 78 } 79