117303c62SDavid Schultz 217303c62SDavid Schultz /* @(#)e_atan2.c 1.3 95/01/18 */ 317303c62SDavid Schultz /* FreeBSD: head/lib/msun/src/e_atan2.c 176451 2008-02-22 02:30:36Z das */ 417303c62SDavid Schultz /* 517303c62SDavid Schultz * ==================================================== 617303c62SDavid Schultz * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 717303c62SDavid Schultz * 817303c62SDavid Schultz * Developed at SunSoft, a Sun Microsystems, Inc. business. 917303c62SDavid Schultz * Permission to use, copy, modify, and distribute this 1017303c62SDavid Schultz * software is freely granted, provided that this notice 1117303c62SDavid Schultz * is preserved. 1217303c62SDavid Schultz * ==================================================== 1317303c62SDavid Schultz * 1417303c62SDavid Schultz */ 1517303c62SDavid Schultz 1617303c62SDavid Schultz #include <sys/cdefs.h> 1717303c62SDavid Schultz __FBSDID("$FreeBSD$"); 1817303c62SDavid Schultz 1917303c62SDavid Schultz /* 2017303c62SDavid Schultz * See comments in e_atan2.c. 2117303c62SDavid Schultz * Converted to long double by David Schultz <das@FreeBSD.ORG>. 2217303c62SDavid Schultz */ 2317303c62SDavid Schultz 2417303c62SDavid Schultz #include <float.h> 2517303c62SDavid Schultz 2617303c62SDavid Schultz #include "invtrig.h" 2717303c62SDavid Schultz #include "math.h" 2817303c62SDavid Schultz #include "math_private.h" 2917303c62SDavid Schultz 3017303c62SDavid Schultz static volatile long double 3117303c62SDavid Schultz tiny = 1.0e-300; 3217303c62SDavid Schultz static const long double 331192a80eSDavid Schultz zero = 0.0; 341192a80eSDavid Schultz 351192a80eSDavid Schultz #ifdef __i386__ 361192a80eSDavid Schultz /* XXX Work around the fact that gcc truncates long double constants on i386 */ 371192a80eSDavid Schultz static volatile double 381192a80eSDavid Schultz pi1 = 3.14159265358979311600e+00, /* 0x1.921fb54442d18p+1 */ 391192a80eSDavid Schultz pi2 = 1.22514845490862001043e-16; /* 0x1.1a80000000000p-53 */ 401192a80eSDavid Schultz #define pi ((long double)pi1 + pi2) 411192a80eSDavid Schultz #else 421192a80eSDavid Schultz static const long double 4317303c62SDavid Schultz pi = 3.14159265358979323846264338327950280e+00L; 441192a80eSDavid Schultz #endif 4517303c62SDavid Schultz 4617303c62SDavid Schultz long double 4717303c62SDavid Schultz atan2l(long double y, long double x) 4817303c62SDavid Schultz { 4917303c62SDavid Schultz union IEEEl2bits ux, uy; 5017303c62SDavid Schultz long double z; 5117303c62SDavid Schultz int32_t k,m; 5217303c62SDavid Schultz int16_t exptx, expsignx, expty, expsigny; 5317303c62SDavid Schultz 5417303c62SDavid Schultz uy.e = y; 5517303c62SDavid Schultz expsigny = uy.xbits.expsign; 5617303c62SDavid Schultz expty = expsigny & 0x7fff; 5717303c62SDavid Schultz ux.e = x; 5817303c62SDavid Schultz expsignx = ux.xbits.expsign; 5917303c62SDavid Schultz exptx = expsignx & 0x7fff; 6017303c62SDavid Schultz 6117303c62SDavid Schultz if ((exptx==BIAS+LDBL_MAX_EXP && 6217303c62SDavid Schultz ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)!=0) || /* x is NaN */ 6317303c62SDavid Schultz (expty==BIAS+LDBL_MAX_EXP && 6417303c62SDavid Schultz ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* y is NaN */ 6517303c62SDavid Schultz return x+y; 6617303c62SDavid Schultz if (expsignx==BIAS && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0) 6717303c62SDavid Schultz return atanl(y); /* x=1.0 */ 6817303c62SDavid Schultz m = ((expsigny>>15)&1)|((expsignx>>14)&2); /* 2*sign(x)+sign(y) */ 6917303c62SDavid Schultz 7017303c62SDavid Schultz /* when y = 0 */ 7117303c62SDavid Schultz if(expty==0 && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)==0) { 7217303c62SDavid Schultz switch(m) { 7317303c62SDavid Schultz case 0: 7417303c62SDavid Schultz case 1: return y; /* atan(+-0,+anything)=+-0 */ 7517303c62SDavid Schultz case 2: return pi+tiny;/* atan(+0,-anything) = pi */ 7617303c62SDavid Schultz case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ 7717303c62SDavid Schultz } 7817303c62SDavid Schultz } 7917303c62SDavid Schultz /* when x = 0 */ 8017303c62SDavid Schultz if(exptx==0 && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0) 8117303c62SDavid Schultz return (expsigny<0)? -pio2_hi-tiny: pio2_hi+tiny; 8217303c62SDavid Schultz 8317303c62SDavid Schultz /* when x is INF */ 8417303c62SDavid Schultz if(exptx==BIAS+LDBL_MAX_EXP) { 8517303c62SDavid Schultz if(expty==BIAS+LDBL_MAX_EXP) { 8617303c62SDavid Schultz switch(m) { 8717303c62SDavid Schultz case 0: return pio2_hi*0.5+tiny;/* atan(+INF,+INF) */ 8817303c62SDavid Schultz case 1: return -pio2_hi*0.5-tiny;/* atan(-INF,+INF) */ 8917303c62SDavid Schultz case 2: return 1.5*pio2_hi+tiny;/*atan(+INF,-INF)*/ 9017303c62SDavid Schultz case 3: return -1.5*pio2_hi-tiny;/*atan(-INF,-INF)*/ 9117303c62SDavid Schultz } 9217303c62SDavid Schultz } else { 9317303c62SDavid Schultz switch(m) { 9417303c62SDavid Schultz case 0: return zero ; /* atan(+...,+INF) */ 9517303c62SDavid Schultz case 1: return -zero ; /* atan(-...,+INF) */ 9617303c62SDavid Schultz case 2: return pi+tiny ; /* atan(+...,-INF) */ 9717303c62SDavid Schultz case 3: return -pi-tiny ; /* atan(-...,-INF) */ 9817303c62SDavid Schultz } 9917303c62SDavid Schultz } 10017303c62SDavid Schultz } 10117303c62SDavid Schultz /* when y is INF */ 10217303c62SDavid Schultz if(expty==BIAS+LDBL_MAX_EXP) 10317303c62SDavid Schultz return (expsigny<0)? -pio2_hi-tiny: pio2_hi+tiny; 10417303c62SDavid Schultz 10517303c62SDavid Schultz /* compute y/x */ 10617303c62SDavid Schultz k = expty-exptx; 10717303c62SDavid Schultz if(k > LDBL_MANT_DIG+2) z=pio2_hi+pio2_lo; /* |y/x| huge */ 10817303c62SDavid Schultz else if(expsignx<0&&k<-LDBL_MANT_DIG-2) z=0.0; /* |y/x| tiny, x<0 */ 10917303c62SDavid Schultz else z=atanl(fabsl(y/x)); /* safe to do y/x */ 11017303c62SDavid Schultz switch (m) { 11117303c62SDavid Schultz case 0: return z ; /* atan(+,+) */ 11217303c62SDavid Schultz case 1: return -z ; /* atan(-,+) */ 11317303c62SDavid Schultz case 2: return pi-(z-pi_lo);/* atan(+,-) */ 11417303c62SDavid Schultz default: /* case 3 */ 11517303c62SDavid Schultz return (z-pi_lo)-pi;/* atan(-,-) */ 11617303c62SDavid Schultz } 11717303c62SDavid Schultz } 118