13f708241SDavid Schultz 23f708241SDavid Schultz /* @(#)e_atan2.c 1.3 95/01/18 */ 33a8617a8SJordan K. Hubbard /* 43a8617a8SJordan K. Hubbard * ==================================================== 53a8617a8SJordan K. Hubbard * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 63a8617a8SJordan K. Hubbard * 73f708241SDavid Schultz * Developed at SunSoft, a Sun Microsystems, Inc. business. 83a8617a8SJordan K. Hubbard * Permission to use, copy, modify, and distribute this 93a8617a8SJordan K. Hubbard * software is freely granted, provided that this notice 103a8617a8SJordan K. Hubbard * is preserved. 113a8617a8SJordan K. Hubbard * ==================================================== 123f708241SDavid Schultz * 133a8617a8SJordan K. Hubbard */ 143a8617a8SJordan K. Hubbard 155aa554c7SDavid Schultz #include <sys/cdefs.h> 165aa554c7SDavid Schultz __FBSDID("$FreeBSD$"); 173a8617a8SJordan K. Hubbard 183a8617a8SJordan K. Hubbard /* __ieee754_atan2(y,x) 193a8617a8SJordan K. Hubbard * Method : 203a8617a8SJordan K. Hubbard * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). 213a8617a8SJordan K. Hubbard * 2. Reduce x to positive by (if x and y are unexceptional): 223a8617a8SJordan K. Hubbard * ARG (x+iy) = arctan(y/x) ... if x > 0, 233a8617a8SJordan K. Hubbard * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, 243a8617a8SJordan K. Hubbard * 253a8617a8SJordan K. Hubbard * Special cases: 263a8617a8SJordan K. Hubbard * 273a8617a8SJordan K. Hubbard * ATAN2((anything), NaN ) is NaN; 283a8617a8SJordan K. Hubbard * ATAN2(NAN , (anything) ) is NaN; 293a8617a8SJordan K. Hubbard * ATAN2(+-0, +(anything but NaN)) is +-0 ; 303a8617a8SJordan K. Hubbard * ATAN2(+-0, -(anything but NaN)) is +-pi ; 313a8617a8SJordan K. Hubbard * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; 323a8617a8SJordan K. Hubbard * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; 333a8617a8SJordan K. Hubbard * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; 343a8617a8SJordan K. Hubbard * ATAN2(+-INF,+INF ) is +-pi/4 ; 353a8617a8SJordan K. Hubbard * ATAN2(+-INF,-INF ) is +-3pi/4; 363a8617a8SJordan K. Hubbard * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; 373a8617a8SJordan K. Hubbard * 383a8617a8SJordan K. Hubbard * Constants: 393a8617a8SJordan K. Hubbard * The hexadecimal values are the intended ones for the following 403a8617a8SJordan K. Hubbard * constants. The decimal values may be used, provided that the 413a8617a8SJordan K. Hubbard * compiler will convert from decimal to binary accurately enough 423a8617a8SJordan K. Hubbard * to produce the hexadecimal values shown. 433a8617a8SJordan K. Hubbard */ 443a8617a8SJordan K. Hubbard 4517303c62SDavid Schultz #include <float.h> 4617303c62SDavid Schultz 473a8617a8SJordan K. Hubbard #include "math.h" 483a8617a8SJordan K. Hubbard #include "math_private.h" 493a8617a8SJordan K. Hubbard 5016608a81SDavid Schultz static volatile double 5116608a81SDavid Schultz tiny = 1.0e-300; 523a8617a8SJordan K. Hubbard static const double 533a8617a8SJordan K. Hubbard zero = 0.0, 543a8617a8SJordan K. Hubbard pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ 553a8617a8SJordan K. Hubbard pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */ 5616608a81SDavid Schultz pi = 3.1415926535897931160E+00; /* 0x400921FB, 0x54442D18 */ 5716608a81SDavid Schultz static volatile double 583a8617a8SJordan K. Hubbard pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ 593a8617a8SJordan K. Hubbard 60a82bbc73SAlfred Perlstein double 613819e840SPeter Wemm __ieee754_atan2(double y, double x) 623a8617a8SJordan K. Hubbard { 633a8617a8SJordan K. Hubbard double z; 643a8617a8SJordan K. Hubbard int32_t k,m,hx,hy,ix,iy; 653a8617a8SJordan K. Hubbard u_int32_t lx,ly; 663a8617a8SJordan K. Hubbard 673a8617a8SJordan K. Hubbard EXTRACT_WORDS(hx,lx,x); 683a8617a8SJordan K. Hubbard ix = hx&0x7fffffff; 693a8617a8SJordan K. Hubbard EXTRACT_WORDS(hy,ly,y); 703a8617a8SJordan K. Hubbard iy = hy&0x7fffffff; 713a8617a8SJordan K. Hubbard if(((ix|((lx|-lx)>>31))>0x7ff00000)|| 723a8617a8SJordan K. Hubbard ((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */ 73*6f1b8a07SBruce Evans return nan_mix(x, y); 74f5ce1664SEitan Adler if(hx==0x3ff00000&&lx==0) return atan(y); /* x=1.0 */ 753a8617a8SJordan K. Hubbard m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ 763a8617a8SJordan K. Hubbard 773a8617a8SJordan K. Hubbard /* when y = 0 */ 783a8617a8SJordan K. Hubbard if((iy|ly)==0) { 793a8617a8SJordan K. Hubbard switch(m) { 803a8617a8SJordan K. Hubbard case 0: 813a8617a8SJordan K. Hubbard case 1: return y; /* atan(+-0,+anything)=+-0 */ 823a8617a8SJordan K. Hubbard case 2: return pi+tiny;/* atan(+0,-anything) = pi */ 833a8617a8SJordan K. Hubbard case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ 843a8617a8SJordan K. Hubbard } 853a8617a8SJordan K. Hubbard } 863a8617a8SJordan K. Hubbard /* when x = 0 */ 873a8617a8SJordan K. Hubbard if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; 883a8617a8SJordan K. Hubbard 893a8617a8SJordan K. Hubbard /* when x is INF */ 903a8617a8SJordan K. Hubbard if(ix==0x7ff00000) { 913a8617a8SJordan K. Hubbard if(iy==0x7ff00000) { 923a8617a8SJordan K. Hubbard switch(m) { 933a8617a8SJordan K. Hubbard case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ 943a8617a8SJordan K. Hubbard case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ 953a8617a8SJordan K. Hubbard case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ 963a8617a8SJordan K. Hubbard case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ 973a8617a8SJordan K. Hubbard } 983a8617a8SJordan K. Hubbard } else { 993a8617a8SJordan K. Hubbard switch(m) { 1003a8617a8SJordan K. Hubbard case 0: return zero ; /* atan(+...,+INF) */ 1013a8617a8SJordan K. Hubbard case 1: return -zero ; /* atan(-...,+INF) */ 1023a8617a8SJordan K. Hubbard case 2: return pi+tiny ; /* atan(+...,-INF) */ 1033a8617a8SJordan K. Hubbard case 3: return -pi-tiny ; /* atan(-...,-INF) */ 1043a8617a8SJordan K. Hubbard } 1053a8617a8SJordan K. Hubbard } 1063a8617a8SJordan K. Hubbard } 1073a8617a8SJordan K. Hubbard /* when y is INF */ 1083a8617a8SJordan K. Hubbard if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; 1093a8617a8SJordan K. Hubbard 1103a8617a8SJordan K. Hubbard /* compute y/x */ 1113a8617a8SJordan K. Hubbard k = (iy-ix)>>20; 1129d7d0936SDavid Schultz if(k > 60) { /* |y/x| > 2**60 */ 1139d7d0936SDavid Schultz z=pi_o_2+0.5*pi_lo; 1149d7d0936SDavid Schultz m&=1; 1159d7d0936SDavid Schultz } 1169d7d0936SDavid Schultz else if(hx<0&&k<-60) z=0.0; /* 0 > |y|/x > -2**-60 */ 1173a8617a8SJordan K. Hubbard else z=atan(fabs(y/x)); /* safe to do y/x */ 1183a8617a8SJordan K. Hubbard switch (m) { 1193a8617a8SJordan K. Hubbard case 0: return z ; /* atan(+,+) */ 1209d7d0936SDavid Schultz case 1: return -z ; /* atan(-,+) */ 1213a8617a8SJordan K. Hubbard case 2: return pi-(z-pi_lo);/* atan(+,-) */ 1223a8617a8SJordan K. Hubbard default: /* case 3 */ 1233a8617a8SJordan K. Hubbard return (z-pi_lo)-pi;/* atan(-,-) */ 1243a8617a8SJordan K. Hubbard } 1253a8617a8SJordan K. Hubbard } 12617303c62SDavid Schultz 12717303c62SDavid Schultz #if LDBL_MANT_DIG == 53 12817303c62SDavid Schultz __weak_reference(atan2, atan2l); 12917303c62SDavid Schultz #endif 130