1 1.1 mrg /* e_atan2l.c -- long double version of e_atan2.c. 2 1.1 mrg * Conversion to long double by Jakub Jelinek, jj (at) ultra.linux.cz. 3 1.1 mrg */ 4 1.1 mrg 5 1.1 mrg /* 6 1.1 mrg * ==================================================== 7 1.1 mrg * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 8 1.1 mrg * 9 1.1 mrg * Developed at SunPro, a Sun Microsystems, Inc. business. 10 1.1 mrg * Permission to use, copy, modify, and distribute this 11 1.1 mrg * software is freely granted, provided that this notice 12 1.1 mrg * is preserved. 13 1.1 mrg * ==================================================== 14 1.1 mrg */ 15 1.1 mrg 16 1.1 mrg /* atan2q(y,x) 17 1.1 mrg * Method : 18 1.1 mrg * 1. Reduce y to positive by atan2l(y,x)=-atan2l(-y,x). 19 1.1 mrg * 2. Reduce x to positive by (if x and y are unexceptional): 20 1.1 mrg * ARG (x+iy) = arctan(y/x) ... if x > 0, 21 1.1 mrg * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, 22 1.1 mrg * 23 1.1 mrg * Special cases: 24 1.1 mrg * 25 1.1 mrg * ATAN2((anything), NaN ) is NaN; 26 1.1 mrg * ATAN2(NAN , (anything) ) is NaN; 27 1.1 mrg * ATAN2(+-0, +(anything but NaN)) is +-0 ; 28 1.1 mrg * ATAN2(+-0, -(anything but NaN)) is +-pi ; 29 1.1 mrg * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; 30 1.1 mrg * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; 31 1.1 mrg * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; 32 1.1 mrg * ATAN2(+-INF,+INF ) is +-pi/4 ; 33 1.1 mrg * ATAN2(+-INF,-INF ) is +-3pi/4; 34 1.1 mrg * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; 35 1.1 mrg * 36 1.1 mrg * Constants: 37 1.1 mrg * The hexadecimal values are the intended ones for the following 38 1.1 mrg * constants. The decimal values may be used, provided that the 39 1.1 mrg * compiler will convert from decimal to binary accurately enough 40 1.1 mrg * to produce the hexadecimal values shown. 41 1.1 mrg */ 42 1.1 mrg 43 1.1 mrg #include "quadmath-imp.h" 44 1.1 mrg 45 1.1 mrg static const __float128 46 1.1 mrg tiny = 1.0e-4900Q, 47 1.1 mrg zero = 0.0, 48 1.1 mrg pi_o_4 = 7.85398163397448309615660845819875699e-01Q, /* 3ffe921fb54442d18469898cc51701b8 */ 49 1.1 mrg pi_o_2 = 1.57079632679489661923132169163975140e+00Q, /* 3fff921fb54442d18469898cc51701b8 */ 50 1.1 mrg pi = 3.14159265358979323846264338327950280e+00Q, /* 4000921fb54442d18469898cc51701b8 */ 51 1.1 mrg pi_lo = 8.67181013012378102479704402604335225e-35Q; /* 3f8dcd129024e088a67cc74020bbea64 */ 52 1.1 mrg 53 1.1 mrg __float128 54 1.1 mrg atan2q(__float128 y, __float128 x) 55 1.1 mrg { 56 1.1 mrg __float128 z; 57 1.1 mrg int64_t k,m,hx,hy,ix,iy; 58 1.1 mrg uint64_t lx,ly; 59 1.1 mrg 60 1.1 mrg GET_FLT128_WORDS64(hx,lx,x); 61 1.1 mrg ix = hx&0x7fffffffffffffffLL; 62 1.1 mrg GET_FLT128_WORDS64(hy,ly,y); 63 1.1 mrg iy = hy&0x7fffffffffffffffLL; 64 1.1 mrg if(((ix|((lx|-lx)>>63))>0x7fff000000000000LL)|| 65 1.1 mrg ((iy|((ly|-ly)>>63))>0x7fff000000000000LL)) /* x or y is NaN */ 66 1.1 mrg return x+y; 67 1.1 mrg if(((hx-0x3fff000000000000LL)|lx)==0) return atanq(y); /* x=1.0L */ 68 1.1 mrg m = ((hy>>63)&1)|((hx>>62)&2); /* 2*sign(x)+sign(y) */ 69 1.1 mrg 70 1.1 mrg /* when y = 0 */ 71 1.1 mrg if((iy|ly)==0) { 72 1.1 mrg switch(m) { 73 1.1 mrg case 0: 74 1.1 mrg case 1: return y; /* atan(+-0,+anything)=+-0 */ 75 1.1 mrg case 2: return pi+tiny;/* atan(+0,-anything) = pi */ 76 1.1 mrg case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ 77 1.1 mrg } 78 1.1 mrg } 79 1.1 mrg /* when x = 0 */ 80 1.1 mrg if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; 81 1.1 mrg 82 1.1 mrg /* when x is INF */ 83 1.1 mrg if(ix==0x7fff000000000000LL) { 84 1.1 mrg if(iy==0x7fff000000000000LL) { 85 1.1 mrg switch(m) { 86 1.1 mrg case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ 87 1.1 mrg case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ 88 1.1 mrg case 2: return 3*pi_o_4+tiny;/*atan(+INF,-INF)*/ 89 1.1 mrg case 3: return -3*pi_o_4-tiny;/*atan(-INF,-INF)*/ 90 1.1 mrg } 91 1.1 mrg } else { 92 1.1 mrg switch(m) { 93 1.1 mrg case 0: return zero ; /* atan(+...,+INF) */ 94 1.1 mrg case 1: return -zero ; /* atan(-...,+INF) */ 95 1.1 mrg case 2: return pi+tiny ; /* atan(+...,-INF) */ 96 1.1 mrg case 3: return -pi-tiny ; /* atan(-...,-INF) */ 97 1.1 mrg } 98 1.1 mrg } 99 1.1 mrg } 100 1.1 mrg /* when y is INF */ 101 1.1 mrg if(iy==0x7fff000000000000LL) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; 102 1.1 mrg 103 1.1 mrg /* compute y/x */ 104 1.1 mrg k = (iy-ix)>>48; 105 1.1 mrg if(k > 120) z=pi_o_2+0.5Q*pi_lo; /* |y/x| > 2**120 */ 106 1.1 mrg else if(hx<0&&k<-120) z=0; /* |y|/x < -2**120 */ 107 1.1 mrg else z=atanq(fabsq(y/x)); /* safe to do y/x */ 108 1.1 mrg switch (m) { 109 1.1 mrg case 0: return z ; /* atan(+,+) */ 110 1.1 mrg case 1: { 111 1.1 mrg uint64_t zh; 112 1.1 mrg GET_FLT128_MSW64(zh,z); 113 1.1 mrg SET_FLT128_MSW64(z,zh ^ 0x8000000000000000ULL); 114 1.1 mrg } 115 1.1 mrg return z ; /* atan(-,+) */ 116 1.1 mrg case 2: return pi-(z-pi_lo);/* atan(+,-) */ 117 1.1 mrg default: /* case 3 */ 118 1.1 mrg return (z-pi_lo)-pi;/* atan(-,-) */ 119 1.1 mrg } 120 1.1 mrg } 121