e_atan2.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       e_atan2.c (3828B)
       ---
            1 /* @(#)e_atan2.c 5.1 93/09/24 */
            2 /*
            3  * ====================================================
            4  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
            5  *
            6  * Developed at SunPro, a Sun Microsystems, Inc. business.
            7  * Permission to use, copy, modify, and distribute this
            8  * software is freely granted, provided that this notice
            9  * is preserved.
           10  * ====================================================
           11  */
           12 
           13 #ifndef lint
           14 static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_atan2.c,v 1.9 2003/07/23 04:53:46 peter Exp $";
           15 #endif
           16 
           17 /* __ieee754_atan2(y,x)
           18  * Method :
           19  *        1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
           20  *        2. Reduce x to positive by (if x and y are unexceptional):
           21  *                ARG (x+iy) = arctan(y/x)              ... if x > 0,
           22  *                ARG (x+iy) = pi - arctan[y/(-x)]   ... if x < 0,
           23  *
           24  * Special cases:
           25  *
           26  *        ATAN2((anything), NaN ) is NaN;
           27  *        ATAN2(NAN , (anything) ) is NaN;
           28  *        ATAN2(+-0, +(anything but NaN)) is +-0  ;
           29  *        ATAN2(+-0, -(anything but NaN)) is +-pi ;
           30  *        ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
           31  *        ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
           32  *        ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
           33  *        ATAN2(+-INF,+INF ) is +-pi/4 ;
           34  *        ATAN2(+-INF,-INF ) is +-3pi/4;
           35  *        ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
           36  *
           37  * Constants:
           38  * The hexadecimal values are the intended ones for the following
           39  * constants. The decimal values may be used, provided that the
           40  * compiler will convert from decimal to binary accurately enough
           41  * to produce the hexadecimal values shown.
           42  */
           43 
           44 #include "math.h"
           45 #include "math_private.h"
           46 
           47 static const double
           48 tiny  = 1.0e-300,
           49 zero  = 0.0,
           50 pi_o_4  = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
           51 pi_o_2  = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
           52 pi      = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
           53 pi_lo   = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
           54 
           55 double
           56 __ieee754_atan2(double y, double x)
           57 {
           58         double z;
           59         int32_t k,m,hx,hy,ix,iy;
           60         u_int32_t lx,ly;
           61 
           62         EXTRACT_WORDS(hx,lx,x);
           63         ix = hx&0x7fffffff;
           64         EXTRACT_WORDS(hy,ly,y);
           65         iy = hy&0x7fffffff;
           66         if(((ix|((lx|-lx)>>31))>0x7ff00000)||
           67            ((iy|((ly|-ly)>>31))>0x7ff00000))        /* x or y is NaN */
           68            return x+y;
           69         if(((hx-0x3ff00000)|lx)==0) return atan(y);   /* x=1.0 */
           70         m = ((hy>>31)&1)|((hx>>30)&2);        /* 2*sign(x)+sign(y) */
           71 
           72     /* when y = 0 */
           73         if((iy|ly)==0) {
           74             switch(m) {
           75                 case 0:
           76                 case 1: return y;         /* atan(+-0,+anything)=+-0 */
           77                 case 2: return  pi+tiny;/* atan(+0,-anything) = pi */
           78                 case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
           79             }
           80         }
           81     /* when x = 0 */
           82         if((ix|lx)==0) return (hy<0)?  -pi_o_2-tiny: pi_o_2+tiny;
           83 
           84     /* when x is INF */
           85         if(ix==0x7ff00000) {
           86             if(iy==0x7ff00000) {
           87                 switch(m) {
           88                     case 0: return  pi_o_4+tiny;/* atan(+INF,+INF) */
           89                     case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
           90                     case 2: return  3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
           91                     case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
           92                 }
           93             } else {
           94                 switch(m) {
           95                     case 0: return  zero  ;        /* atan(+...,+INF) */
           96                     case 1: return -zero  ;        /* atan(-...,+INF) */
           97                     case 2: return  pi+tiny  ;        /* atan(+...,-INF) */
           98                     case 3: return -pi-tiny  ;        /* atan(-...,-INF) */
           99                 }
          100             }
          101         }
          102     /* when y is INF */
          103         if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
          104 
          105     /* compute y/x */
          106         k = (iy-ix)>>20;
          107         if(k > 60) z=pi_o_2+0.5*pi_lo;         /* |y/x| >  2**60 */
          108         else if(hx<0&&k<-60) z=0.0;         /* |y|/x < -2**60 */
          109         else z=atan(fabs(y/x));                /* safe to do y/x */
          110         switch (m) {
          111             case 0: return       z  ;        /* atan(+,+) */
          112             case 1: {
          113                           u_int32_t zh;
          114                       GET_HIGH_WORD(zh,z);
          115                       SET_HIGH_WORD(z,zh ^ 0x80000000);
          116                     }
          117                     return       z  ;        /* atan(-,+) */
          118             case 2: return  pi-(z-pi_lo);/* atan(+,-) */
          119             default: /* case 3 */
          120                         return  (z-pi_lo)-pi;/* atan(-,-) */
          121         }
          122 }