s_atanl.c revision 181074
1124524Sume/* @(#)s_atan.c 5.1 93/09/24 */
266776Skris/* FreeBSD: head/lib/msun/src/s_atan.c 176451 2008-02-22 02:30:36Z das */
355163Sshin/*
455163Sshin * ====================================================
555163Sshin * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
662632Skris *
755163Sshin * Developed at SunPro, a Sun Microsystems, Inc. business.
855163Sshin * Permission to use, copy, modify, and distribute this
955163Sshin * software is freely granted, provided that this notice
1055163Sshin * is preserved.
1155163Sshin * ====================================================
1255163Sshin */
1355163Sshin
1455163Sshin#include <sys/cdefs.h>
1555163Sshin__FBSDID("$FreeBSD: head/lib/msun/src/s_atanl.c 181074 2008-07-31 22:41:26Z das $");
1655163Sshin
1755163Sshin/*
1862632Skris * See comments in s_atan.c.
1955163Sshin * Converted to long double by David Schultz <das@FreeBSD.ORG>.
2055163Sshin */
2155163Sshin
2255163Sshin#include <float.h>
2355163Sshin
2455163Sshin#include "invtrig.h"
2555163Sshin#include "math.h"
2655163Sshin#include "math_private.h"
2755163Sshin
2855163Sshinstatic const long double
2955163Sshinone   = 1.0,
3055163Sshinhuge   = 1.0e300;
3155163Sshin
3255163Sshinlong double
3355163Sshinatanl(long double x)
3455163Sshin{
3555163Sshin	union IEEEl2bits u;
3655163Sshin	long double w,s1,s2,z;
3755163Sshin	int id;
3866776Skris	int16_t expsign, expt;
3955163Sshin	int32_t expman;
4055163Sshin
4155163Sshin	u.e = x;
4255163Sshin	expsign = u.xbits.expsign;
4355163Sshin	expt = expsign & 0x7fff;
4455163Sshin	if(expt >= ATAN_CONST) {	/* if |x| is large, atan(x)~=pi/2 */
4555163Sshin	    if(expt == BIAS + LDBL_MAX_EXP &&
46118787Sume	       ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)!=0)
4755163Sshin		return x+x;		/* NaN */
4855163Sshin	    if(expsign>0) return  atanhi[3]+atanlo[3];
4955163Sshin	    else     return -atanhi[3]-atanlo[3];
5055163Sshin	}
5155163Sshin	/* Extract the exponent and the first few bits of the mantissa. */
5255163Sshin	/* XXX There should be a more convenient way to do this. */
5355163Sshin	expman = (expt << 8) | ((u.bits.manh >> (MANH_SIZE - 9)) & 0xff);
5455163Sshin	if (expman < ((BIAS - 2) << 8) + 0xc0) {	/* |x| < 0.4375 */
5555163Sshin	    if (expt < ATAN_LINEAR) {	/* if |x| is small, atanl(x)~=x */
5655163Sshin		if(huge+x>one) return x;	/* raise inexact */
5755163Sshin	    }
5855163Sshin	    id = -1;
5955163Sshin	} else {
6062632Skris	x = fabsl(x);
6155163Sshin	if (expman < (BIAS << 8) + 0x30) {		/* |x| < 1.1875 */
6255163Sshin	    if (expman < ((BIAS - 1) << 8) + 0x60) {	/* 7/16 <=|x|<11/16 */
6362632Skris		id = 0; x = (2.0*x-one)/(2.0+x);
6455163Sshin	    } else {			/* 11/16<=|x|< 19/16 */
6555163Sshin		id = 1; x  = (x-one)/(x+one);
66118998Sume	    }
67118998Sume	} else {
6855163Sshin	    if (expman < ((BIAS + 1) << 8) + 0x38) {	/* |x| < 2.4375 */
6955163Sshin		id = 2; x  = (x-1.5)/(one+1.5*x);
70124524Sume	    } else {			/* 2.4375 <= |x| < 2^ATAN_CONST */
7155163Sshin		id = 3; x  = -1.0/x;
7262632Skris	    }
7355163Sshin	}}
7455163Sshin    /* end of argument reduction */
7555163Sshin	z = x*x;
7655163Sshin	w = z*z;
7755163Sshin    /* break sum aT[i]z**(i+1) into odd and even poly */
7855163Sshin	s1 = z*T_even(w);
7955163Sshin	s2 = w*T_odd(w);
8055163Sshin	if (id<0) return x - x*(s1+s2);
8162632Skris	else {
8255163Sshin	    z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
83119027Sume	    return (expsign<0)? -z:z;
8455163Sshin	}
8555163Sshin}
86118660Sume