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 57 w = fabsl(x); 58 if (isnanl(x)) 59 return (x + x); 60 else if (w <= half) { 61 if (w < small) { 62 #ifndef lint 63 volatile long double dummy = w + big; 64 /* inexact if w != 0 */ 65 #endif 66 return (x); 67 } else 68 return (atanl(x / sqrtl(one - x * x))); 69 } else if (w < one) { 70 t = one - w; 71 w = t + t; 72 return (atanl(x / sqrtl(w - t * t))); 73 } else if (w == one) 74 return (atan2l(x, zero)); /* asin(+-1) = +- PI/2 */ 75 else 76 return (zero / zero); /* |x| > 1: invalid */ 77 }