about summary refs log tree commit diff
path: root/sysdeps/ieee754/dbl-64/e_atan2.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2001-03-12 00:04:52 +0000
committerUlrich Drepper <drepper@redhat.com>2001-03-12 00:04:52 +0000
commite4d8276142b9c07b23043ef44b0fe8fa7bcc3121 (patch)
treef153a80b6ce0fdd3261ff18a16fd80bd965231c3 /sysdeps/ieee754/dbl-64/e_atan2.c
parentd3c8723f6415af59a6ec14fcb918ad0e4d1fb588 (diff)
downloadglibc-e4d8276142b9c07b23043ef44b0fe8fa7bcc3121.tar.gz
glibc-e4d8276142b9c07b23043ef44b0fe8fa7bcc3121.tar.xz
glibc-e4d8276142b9c07b23043ef44b0fe8fa7bcc3121.zip
Update.
2001-03-11  Ulrich Drepper  <drepper@redhat.com>

	Last-bit accurate math library implementation by IBM Haifa.
	Contributed by Abraham Ziv <ziv@il.ibm.com>, Moshe Olshansky
	<olshansk@il.ibm.com>, Ealan Henis <ealan@il.ibm.com>, and
	Anna Reitman <reitman@il.ibm.com>.
	* math/Makefile (dbl-only-routines): New variable.
	(libm-routines): Add $(dbl-only-routines).
	* sysdeps/ieee754/dbl-64/e_acos.c: Empty, definition is in e_asin.c.
	* sysdeps/ieee754/dbl-64/e_asin.c: Replaced with accurate asin
	implementation.
	* sysdeps/ieee754/dbl-64/e_atan2.c: Replaced with accurate atan2
	implementation.
	* sysdeps/ieee754/dbl-64/e_exp.c: Replaced with accurate exp
	implementation.
	* sysdeps/ieee754/dbl-64/e_lgamma_r.c: Don't use __kernel_sin and
	__kernel_cos.
	* sysdeps/ieee754/dbl-64/e_log.c: Replaced with accurate log
	implementation.
	* sysdeps/ieee754/dbl-64/e_remainder.c: Replaced with accurate
	remainder implementation.
	* sysdeps/ieee754/dbl-64/e_pow.c: Replaced with accurate pow
	implementation.
	* sysdeps/ieee754/dbl-64/e_sqrt.c: Replaced with accurate sqrt
	implementation.
	* sysdeps/ieee754/dbl-64/k_cos.c: Empty, definition is in s_sin.c.
	* sysdeps/ieee754/dbl-64/k_sin.c: Empty, definition is in s_sin.c.
	* sysdeps/ieee754/dbl-64/s_atan.c: Replaced with accurate atan
	implementation.
	* sysdeps/ieee754/dbl-64/s_cos.c: Empty, definition is in s_sin.c.
	* sysdeps/ieee754/dbl-64/s_sin.c: Replaced with accurate sin/cos
	implementation.
	* sysdeps/ieee754/dbl-64/s_sincos.c: Rewritten to not use __kernel_sin
	and __kernel_cos.
	* sysdeps/ieee754/dbl-64/s_tan.c: Replaced with accurate tan
	implementation.
	* sysdeps/ieee754/dbl-64/Dist: Add new non-code files.
	* sysdeps/ieee754/dbl-64/MathLib.h: New file.
	* sysdeps/ieee754/dbl-64/asincos.tbl: New file.
	* sysdeps/ieee754/dbl-64/atnat.h: New file.
	* sysdeps/ieee754/dbl-64/atnat2.h: New file.
	* sysdeps/ieee754/dbl-64/branred.c: New file.
	* sysdeps/ieee754/dbl-64/branred.h: New file.
	* sysdeps/ieee754/dbl-64/dla.h: New file.
	* sysdeps/ieee754/dbl-64/doasin.c: New file.
	* sysdeps/ieee754/dbl-64/doasin.h: New file.
	* sysdeps/ieee754/dbl-64/dosincos.c: New file.
	* sysdeps/ieee754/dbl-64/dosincos.h: New file.
	* sysdeps/ieee754/dbl-64/endian.h: New file.
	* sysdeps/ieee754/dbl-64/halfulp.c: New file.
	* sysdeps/ieee754/dbl-64/mpa.c: New file.
	* sysdeps/ieee754/dbl-64/mpa.h: New file.
	* sysdeps/ieee754/dbl-64/mpa2.h: New file.
	* sysdeps/ieee754/dbl-64/mpatan.c: New file.
	* sysdeps/ieee754/dbl-64/mpatan.h: New file.
	* sysdeps/ieee754/dbl-64/mpatan2.c: New file.
	* sysdeps/ieee754/dbl-64/mpexp.c: New file.
	* sysdeps/ieee754/dbl-64/mpexp.h: New file.
	* sysdeps/ieee754/dbl-64/mplog.c: New file.
	* sysdeps/ieee754/dbl-64/mplog.h: New file.
	* sysdeps/ieee754/dbl-64/mpsqrt.c: New file.
	* sysdeps/ieee754/dbl-64/mpsqrt.h: New file.
	* sysdeps/ieee754/dbl-64/mptan.c: New file.
	* sysdeps/ieee754/dbl-64/mydefs.h: New file.
	* sysdeps/ieee754/dbl-64/powtwo.tbl: New file.
	* sysdeps/ieee754/dbl-64/root.tbl: New file.
	* sysdeps/ieee754/dbl-64/sincos.tbl: New file.
	* sysdeps/ieee754/dbl-64/sincos32.c: New file.
	* sysdeps/ieee754/dbl-64/sincos32.h: New file.
	* sysdeps/ieee754/dbl-64/slowexp.c: New file.
	* sysdeps/ieee754/dbl-64/slowpow.c: New file.
	* sysdeps/ieee754/dbl-64/uasncs.h: New file.
	* sysdeps/ieee754/dbl-64/uatan.tbl: New file.
	* sysdeps/ieee754/dbl-64/uexp.h: New file.
	* sysdeps/ieee754/dbl-64/uexp.tbl: New file.
	* sysdeps/ieee754/dbl-64/ulog.h: New file.
	* sysdeps/ieee754/dbl-64/ulog.tbl: New file.
	* sysdeps/ieee754/dbl-64/upow.h: New file.
	* sysdeps/ieee754/dbl-64/upow.tbl: New file.
	* sysdeps/ieee754/dbl-64/urem.h: New file.
	* sysdeps/ieee754/dbl-64/uroot.h: New file.
	* sysdeps/ieee754/dbl-64/usncs.h: New file.
	* sysdeps/ieee754/dbl-64/utan.h: New file.
	* sysdeps/ieee754/dbl-64/utan.tbl: New file.
	* sysdeps/i386/fpu/branred.c: New file.
	* sysdeps/i386/fpu/doasin.c: New file.
	* sysdeps/i386/fpu/dosincos.c: New file.
	* sysdeps/i386/fpu/halfulp.c: New file.
	* sysdeps/i386/fpu/mpa.c: New file.
	* sysdeps/i386/fpu/mpatan.c: New file.
	* sysdeps/i386/fpu/mpatan2.c: New file.
	* sysdeps/i386/fpu/mpexp.c: New file.
	* sysdeps/i386/fpu/mplog.c: New file.
	* sysdeps/i386/fpu/mpsqrt.c: New file.
	* sysdeps/i386/fpu/mptan.c: New file.
	* sysdeps/i386/fpu/sincos32.c: New file.
	* sysdeps/i386/fpu/slowexp.c: New file.
	* sysdeps/i386/fpu/slowpow.c: New file.
	* sysdeps/ia64/fpu/branred.c: New file.
	* sysdeps/ia64/fpu/doasin.c: New file.
	* sysdeps/ia64/fpu/dosincos.c: New file.
	* sysdeps/ia64/fpu/halfulp.c: New file.
	* sysdeps/ia64/fpu/mpa.c: New file.
	* sysdeps/ia64/fpu/mpatan.c: New file.
	* sysdeps/ia64/fpu/mpatan2.c: New file.
	* sysdeps/ia64/fpu/mpexp.c: New file.
	* sysdeps/ia64/fpu/mplog.c: New file.
	* sysdeps/ia64/fpu/mpsqrt.c: New file.
	* sysdeps/ia64/fpu/mptan.c: New file.
	* sysdeps/ia64/fpu/sincos32.c: New file.
	* sysdeps/ia64/fpu/slowexp.c: New file.
	* sysdeps/ia64/fpu/slowpow.c: New file.
	* sysdeps/m68k/fpu/branred.c: New file.
	* sysdeps/m68k/fpu/doasin.c: New file.
	* sysdeps/m68k/fpu/dosincos.c: New file.
	* sysdeps/m68k/fpu/halfulp.c: New file.
	* sysdeps/m68k/fpu/mpa.c: New file.
	* sysdeps/m68k/fpu/mpatan.c: New file.
	* sysdeps/m68k/fpu/mpatan2.c: New file.
	* sysdeps/m68k/fpu/mpexp.c: New file.
	* sysdeps/m68k/fpu/mplog.c: New file.
	* sysdeps/m68k/fpu/mpsqrt.c: New file.
	* sysdeps/m68k/fpu/mptan.c: New file.
	* sysdeps/m68k/fpu/sincos32.c: New file.
	* sysdeps/m68k/fpu/slowexp.c: New file.
	* sysdeps/m68k/fpu/slowpow.c: New file.

	* iconvdata/gconv-modules: Add a number of alias, mostly for IBM
	codepages.
Diffstat (limited to 'sysdeps/ieee754/dbl-64/e_atan2.c')
-rw-r--r--sysdeps/ieee754/dbl-64/e_atan2.c511
1 files changed, 388 insertions, 123 deletions
diff --git a/sysdeps/ieee754/dbl-64/e_atan2.c b/sysdeps/ieee754/dbl-64/e_atan2.c
index ae7d759a9f..11342d87d3 100644
--- a/sysdeps/ieee754/dbl-64/e_atan2.c
+++ b/sysdeps/ieee754/dbl-64/e_atan2.c
@@ -1,130 +1,395 @@
-/* @(#)e_atan2.c 5.1 93/09/24 */
 /*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * IBM Accurate Mathematical Library
+ * Copyright (c) International Business Machines Corp., 2001
  *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice 
- * is preserved.
- * ====================================================
- */
-
-#if defined(LIBM_SCCS) && !defined(lint)
-static char rcsid[] = "$NetBSD: e_atan2.c,v 1.8 1995/05/10 20:44:51 jtc Exp $";
-#endif
-
-/* __ieee754_atan2(y,x)
- * Method :
- *	1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
- *	2. Reduce x to positive by (if x and y are unexceptional): 
- *		ARG (x+iy) = arctan(y/x)   	   ... if x > 0,
- *		ARG (x+iy) = pi - arctan[y/(-x)]   ... if x < 0,
- *
- * Special cases:
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  *
- *	ATAN2((anything), NaN ) is NaN;
- *	ATAN2(NAN , (anything) ) is NaN;
- *	ATAN2(+-0, +(anything but NaN)) is +-0  ;
- *	ATAN2(+-0, -(anything but NaN)) is +-pi ;
- *	ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
- *	ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
- *	ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
- *	ATAN2(+-INF,+INF ) is +-pi/4 ;
- *	ATAN2(+-INF,-INF ) is +-3pi/4;
- *	ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * Constants:
- * The hexadecimal values are the intended ones for the following 
- * constants. The decimal values may be used, provided that the 
- * compiler will convert from decimal to binary accurately enough 
- * to produce the hexadecimal values shown.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
+/************************************************************************/
+/*  MODULE_NAME: atnat2.c                                               */
+/*                                                                      */
+/*  FUNCTIONS: uatan2                                                   */
+/*             atan2Mp                                                  */
+/*             signArctan2                                              */
+/*             normalized                                               */
+/*                                                                      */
+/*  FILES NEEDED: dla.h endian.h mpa.h mydefs.h atnat2.h                */
+/*                mpatan.c mpatan2.c mpsqrt.c                           */
+/*                uatan.tbl                                             */
+/*                                                                      */
+/* An ultimate atan2() routine. Given two IEEE double machine numbers y,*/
+/* x it computes the correctly rounded (to nearest) value of atan2(y,x).*/
+/*                                                                      */
+/* Assumption: Machine arithmetic operations are performed in           */
+/* round to nearest mode of IEEE 754 standard.                          */
+/*                                                                      */
+/************************************************************************/
+
+#include "dla.h"
+#include "mpa.h"
+#include "MathLib.h"
+#include "uatan.tbl"
+#include "atnat2.h"
+/************************************************************************/
+/* An ultimate atan2 routine. Given two IEEE double machine numbers y,x */
+/* it computes the correctly rounded (to nearest) value of atan2(y,x).  */
+/* Assumption: Machine arithmetic operations are performed in           */
+/* round to nearest mode of IEEE 754 standard.                          */
+/************************************************************************/
+static double atan2Mp(double ,double ,const int[]);
+static double signArctan2(double ,double);
+static double normalized(double ,double,double ,double);
+void __mpatan2(mp_no *,mp_no *,mp_no *,int);
+
+double __ieee754_atan2(double y,double x) {
+
+  int i,de,ux,dx,uy,dy,p;
+  static const int pr[MM]={6,8,10,20,32};
+  double ax,ay,u,du,u9,ua,v,vv,dv,t1,t2,t3,t4,t5,t6,t7,t8,
+         z,zz,z1,z2,cor,s1,ss1,s2,ss2;
+  number num;
+  mp_no mperr,mpt1,mpx,mpy,mpz,mpz1,mpz2;
+
+  static const int ep= 59768832,   /*  57*16**5   */
+                   em=-59768832;   /* -57*16**5   */
+
+  /* x=NaN or y=NaN */
+  num.d = x;  ux = num.i[HIGH_HALF];  dx = num.i[LOW_HALF];
+  if   ((ux&0x7ff00000)    ==0x7ff00000) {
+    if (((ux&0x000fffff)|dx)!=0x00000000) return x+x; }
+  num.d = y;  uy = num.i[HIGH_HALF];  dy = num.i[LOW_HALF];
+  if   ((uy&0x7ff00000)    ==0x7ff00000) {
+    if (((uy&0x000fffff)|dy)!=0x00000000) return y+y; }
+
+  /* y=+-0 */
+  if      (uy==0x00000000) {
+    if    (dy==0x00000000) {
+      if  ((ux&0x80000000)==0x00000000)  return ZERO;
+      else                               return opi.d; } }
+  else if (uy==0x80000000) {
+    if    (dy==0x00000000) {
+      if  ((ux&0x80000000)==0x00000000)  return MZERO;
+      else                               return mopi.d;} }
+
+  /* x=+-0 */
+  if (x==ZERO) {
+    if ((uy&0x80000000)==0x00000000)     return hpi.d;
+    else                                 return mhpi.d; }
+
+  /* x=+-INF */
+  if          (ux==0x7ff00000) {
+    if        (dx==0x00000000) {
+      if      (uy==0x7ff00000) {
+        if    (dy==0x00000000)  return qpi.d; }
+      else if (uy==0xfff00000) {
+        if    (dy==0x00000000)  return mqpi.d; }
+      else {
+        if    ((uy&0x80000000)==0x00000000)  return ZERO;
+        else                                 return MZERO; }
+    }
+  }
+  else if     (ux==0xfff00000) {
+    if        (dx==0x00000000) {
+      if      (uy==0x7ff00000) {
+        if    (dy==0x00000000)  return tqpi.d; }
+      else if (uy==0xfff00000) {
+        if    (dy==0x00000000)  return mtqpi.d; }
+      else                     {
+        if    ((uy&0x80000000)==0x00000000)  return opi.d;
+        else                                 return mopi.d; }
+    }
+  }
+
+  /* y=+-INF */
+  if      (uy==0x7ff00000) {
+    if    (dy==0x00000000)  return hpi.d; }
+  else if (uy==0xfff00000) {
+    if    (dy==0x00000000)  return mhpi.d; }
+
+  /* either x/y or y/x is very close to zero */
+  ax = (x<ZERO) ? -x : x;    ay = (y<ZERO) ? -y : y;
+  de = (uy & 0x7ff00000) - (ux & 0x7ff00000);
+  if      (de>=ep)  { return ((y>ZERO) ? hpi.d : mhpi.d); }
+  else if (de<=em)  {
+    if    (x>ZERO)  {
+      if  ((z=ay/ax)<TWOM1022)  return normalized(ax,ay,y,z);
+      else                      return signArctan2(y,z); }
+    else            { return ((y>ZERO) ? opi.d : mopi.d); } }
+
+  /* if either x or y is extremely close to zero, scale abs(x), abs(y). */
+  if (ax<twom500.d || ay<twom500.d) { ax*=two500.d;  ay*=two500.d; }
+
+  /* x,y which are neither special nor extreme */
+  if (ay<ax) {
+    u=ay/ax;
+    EMULV(ax,u,v,vv,t1,t2,t3,t4,t5)
+    du=((ay-v)-vv)/ax; }
+  else {
+    u=ax/ay;
+    EMULV(ay,u,v,vv,t1,t2,t3,t4,t5)
+    du=((ax-v)-vv)/ay; }
 
-#include "math.h"
-#include "math_private.h"
-
-#ifdef __STDC__
-static const double 
-#else
-static double 
-#endif
-tiny  = 1.0e-300,
-zero  = 0.0,
-pi_o_4  = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
-pi_o_2  = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
-pi      = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
-pi_lo   = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
-
-#ifdef __STDC__
-	double __ieee754_atan2(double y, double x)
-#else
-	double __ieee754_atan2(y,x)
-	double  y,x;
-#endif
-{  
-	double z;
-	int32_t k,m,hx,hy,ix,iy;
-	u_int32_t lx,ly;
-
-	EXTRACT_WORDS(hx,lx,x);
-	ix = hx&0x7fffffff;
-	EXTRACT_WORDS(hy,ly,y);
-	iy = hy&0x7fffffff;
-	if(((ix|((lx|-lx)>>31))>0x7ff00000)||
-	   ((iy|((ly|-ly)>>31))>0x7ff00000))	/* x or y is NaN */
-	   return x+y;
-	if(((hx-0x3ff00000)|lx)==0) return __atan(y);   /* x=1.0 */
-	m = ((hy>>31)&1)|((hx>>30)&2);	/* 2*sign(x)+sign(y) */
-
-    /* when y = 0 */
-	if((iy|ly)==0) {
-	    switch(m) {
-		case 0: 
-		case 1: return y; 	/* atan(+-0,+anything)=+-0 */
-		case 2: return  pi+tiny;/* atan(+0,-anything) = pi */
-		case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
-	    }
-	}
-    /* when x = 0 */
-	if((ix|lx)==0) return (hy<0)?  -pi_o_2-tiny: pi_o_2+tiny;
-	    
-    /* when x is INF */
-	if(ix==0x7ff00000) {
-	    if(iy==0x7ff00000) {
-		switch(m) {
-		    case 0: return  pi_o_4+tiny;/* atan(+INF,+INF) */
-		    case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
-		    case 2: return  3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
-		    case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
-		}
-	    } else {
-		switch(m) {
-		    case 0: return  zero  ;	/* atan(+...,+INF) */
-		    case 1: return -zero  ;	/* atan(-...,+INF) */
-		    case 2: return  pi+tiny  ;	/* atan(+...,-INF) */
-		    case 3: return -pi-tiny  ;	/* atan(-...,-INF) */
-		}
-	    }
-	}
-    /* when y is INF */
-	if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
-
-    /* compute y/x */
-	k = (iy-ix)>>20;
-	if(k > 60) z=pi_o_2+0.5*pi_lo; 	/* |y/x| >  2**60 */
-	else if(hx<0&&k<-60) z=0.0; 	/* |y|/x < -2**60 */
-	else z=__atan(fabs(y/x));	/* safe to do y/x */
-	switch (m) {
-	    case 0: return       z  ;	/* atan(+,+) */
-	    case 1: {
-	    	      u_int32_t zh;
-		      GET_HIGH_WORD(zh,z);
-		      SET_HIGH_WORD(z,zh ^ 0x80000000);
-		    }
-		    return       z  ;	/* atan(-,+) */
-	    case 2: return  pi-(z-pi_lo);/* atan(+,-) */
-	    default: /* case 3 */
-	    	    return  (z-pi_lo)-pi;/* atan(-,-) */
-	}
+  if (x>ZERO) {
+
+    /* (i)   x>0, abs(y)< abs(x):  atan(ay/ax) */
+    if (ay<ax) {
+      if (u<inv16.d) {
+        v=u*u;  zz=du+u*v*(d3.d+v*(d5.d+v*(d7.d+v*(d9.d+v*(d11.d+v*d13.d)))));
+        if ((z=u+(zz-u1.d*u)) == u+(zz+u1.d*u))  return signArctan2(y,z);
+
+        MUL2(u,du,u,du,v,vv,t1,t2,t3,t4,t5,t6,t7,t8)
+        s1=v*(f11.d+v*(f13.d+v*(f15.d+v*(f17.d+v*f19.d))));
+        ADD2(f9.d,ff9.d,s1,ZERO,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f7.d,ff7.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f5.d,ff5.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f3.d,ff3.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        MUL2(u,du,s1,ss1,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(u,du,s2,ss2,s1,ss1,t1,t2)
+        if ((z=s1+(ss1-u5.d*s1)) == s1+(ss1+u5.d*s1))  return signArctan2(y,z);
+        return atan2Mp(x,y,pr);
+      }
+      else {
+        i=(TWO52+TWO8*u)-TWO52;  i-=16;
+        t3=u-cij[i][0].d;
+        EADD(t3,du,v,dv)
+        t1=cij[i][1].d;  t2=cij[i][2].d;
+        zz=v*t2+(dv*t2+v*v*(cij[i][3].d+v*(cij[i][4].d+
+                         v*(cij[i][5].d+v* cij[i][6].d))));
+        if (i<112) {
+          if (i<48)  u9=u91.d;    /* u < 1/4        */
+          else       u9=u92.d; }  /* 1/4 <= u < 1/2 */
+        else {
+          if (i<176) u9=u93.d;    /* 1/2 <= u < 3/4 */
+          else       u9=u94.d; }  /* 3/4 <= u <= 1  */
+        if ((z=t1+(zz-u9*t1)) == t1+(zz+u9*t1))  return signArctan2(y,z);
+
+        t1=u-hij[i][0].d;
+        EADD(t1,du,v,vv)
+        s1=v*(hij[i][11].d+v*(hij[i][12].d+v*(hij[i][13].d+
+           v*(hij[i][14].d+v* hij[i][15].d))));
+        ADD2(hij[i][9].d,hij[i][10].d,s1,ZERO,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][7].d,hij[i][8].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][5].d,hij[i][6].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][3].d,hij[i][4].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][1].d,hij[i][2].d,s1,ss1,s2,ss2,t1,t2)
+        if ((z=s2+(ss2-ub.d*s2)) == s2+(ss2+ub.d*s2))  return signArctan2(y,z);
+        return atan2Mp(x,y,pr);
+      }
+    }
+
+    /* (ii)  x>0, abs(x)<=abs(y):  pi/2-atan(ax/ay) */
+    else {
+      if (u<inv16.d) {
+        v=u*u;
+        zz=u*v*(d3.d+v*(d5.d+v*(d7.d+v*(d9.d+v*(d11.d+v*d13.d)))));
+        ESUB(hpi.d,u,t2,cor)
+        t3=((hpi1.d+cor)-du)-zz;
+        if ((z=t2+(t3-u2.d)) == t2+(t3+u2.d))  return signArctan2(y,z);
+
+        MUL2(u,du,u,du,v,vv,t1,t2,t3,t4,t5,t6,t7,t8)
+        s1=v*(f11.d+v*(f13.d+v*(f15.d+v*(f17.d+v*f19.d))));
+        ADD2(f9.d,ff9.d,s1,ZERO,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f7.d,ff7.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f5.d,ff5.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f3.d,ff3.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        MUL2(u,du,s1,ss1,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(u,du,s2,ss2,s1,ss1,t1,t2)
+        SUB2(hpi.d,hpi1.d,s1,ss1,s2,ss2,t1,t2)
+        if ((z=s2+(ss2-u6.d)) == s2+(ss2+u6.d))  return signArctan2(y,z);
+        return atan2Mp(x,y,pr);
+      }
+      else {
+        i=(TWO52+TWO8*u)-TWO52;  i-=16;
+        v=(u-cij[i][0].d)+du;
+        zz=hpi1.d-v*(cij[i][2].d+v*(cij[i][3].d+v*(cij[i][4].d+
+                                 v*(cij[i][5].d+v* cij[i][6].d))));
+        t1=hpi.d-cij[i][1].d;
+        if (i<112)  ua=ua1.d;  /* w <  1/2 */
+        else        ua=ua2.d;  /* w >= 1/2 */
+        if ((z=t1+(zz-ua)) == t1+(zz+ua))  return signArctan2(y,z);
+
+        t1=u-hij[i][0].d;
+        EADD(t1,du,v,vv)
+        s1=v*(hij[i][11].d+v*(hij[i][12].d+v*(hij[i][13].d+
+           v*(hij[i][14].d+v* hij[i][15].d))));
+        ADD2(hij[i][9].d,hij[i][10].d,s1,ZERO,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][7].d,hij[i][8].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][5].d,hij[i][6].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][3].d,hij[i][4].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][1].d,hij[i][2].d,s1,ss1,s2,ss2,t1,t2)
+        SUB2(hpi.d,hpi1.d,s2,ss2,s1,ss1,t1,t2)
+        if ((z=s1+(ss1-uc.d)) == s1+(ss1+uc.d))  return signArctan2(y,z);
+        return atan2Mp(x,y,pr);
+      }
+    }
+  }
+  else {
+
+    /* (iii) x<0, abs(x)< abs(y):  pi/2+atan(ax/ay) */
+    if (ax<ay) {
+      if (u<inv16.d) {
+        v=u*u;
+        zz=u*v*(d3.d+v*(d5.d+v*(d7.d+v*(d9.d+v*(d11.d+v*d13.d)))));
+        EADD(hpi.d,u,t2,cor)
+        t3=((hpi1.d+cor)+du)+zz;
+        if ((z=t2+(t3-u3.d)) == t2+(t3+u3.d))  return signArctan2(y,z);
+
+        MUL2(u,du,u,du,v,vv,t1,t2,t3,t4,t5,t6,t7,t8)
+        s1=v*(f11.d+v*(f13.d+v*(f15.d+v*(f17.d+v*f19.d))));
+        ADD2(f9.d,ff9.d,s1,ZERO,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f7.d,ff7.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f5.d,ff5.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f3.d,ff3.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        MUL2(u,du,s1,ss1,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(u,du,s2,ss2,s1,ss1,t1,t2)
+        ADD2(hpi.d,hpi1.d,s1,ss1,s2,ss2,t1,t2)
+        if ((z=s2+(ss2-u7.d)) == s2+(ss2+u7.d))  return signArctan2(y,z);
+        return atan2Mp(x,y,pr);
+      }
+      else {
+        i=(TWO52+TWO8*u)-TWO52;  i-=16;
+        v=(u-cij[i][0].d)+du;
+        zz=hpi1.d+v*(cij[i][2].d+v*(cij[i][3].d+v*(cij[i][4].d+
+                                 v*(cij[i][5].d+v* cij[i][6].d))));
+        t1=hpi.d+cij[i][1].d;
+        if (i<112)  ua=ua1.d;  /* w <  1/2 */
+        else        ua=ua2.d;  /* w >= 1/2 */
+        if ((z=t1+(zz-ua)) == t1+(zz+ua))  return signArctan2(y,z);
+
+        t1=u-hij[i][0].d;
+        EADD(t1,du,v,vv)
+        s1=v*(hij[i][11].d+v*(hij[i][12].d+v*(hij[i][13].d+
+           v*(hij[i][14].d+v* hij[i][15].d))));
+        ADD2(hij[i][9].d,hij[i][10].d,s1,ZERO,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][7].d,hij[i][8].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][5].d,hij[i][6].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][3].d,hij[i][4].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][1].d,hij[i][2].d,s1,ss1,s2,ss2,t1,t2)
+        ADD2(hpi.d,hpi1.d,s2,ss2,s1,ss1,t1,t2)
+        if ((z=s1+(ss1-uc.d)) == s1+(ss1+uc.d))  return signArctan2(y,z);
+        return atan2Mp(x,y,pr);
+      }
+    }
+
+    /* (iv)  x<0, abs(y)<=abs(x):  pi-atan(ax/ay) */
+    else {
+      if (u<inv16.d) {
+        v=u*u;
+        zz=u*v*(d3.d+v*(d5.d+v*(d7.d+v*(d9.d+v*(d11.d+v*d13.d)))));
+        ESUB(opi.d,u,t2,cor)
+        t3=((opi1.d+cor)-du)-zz;
+        if ((z=t2+(t3-u4.d)) == t2+(t3+u4.d))  return signArctan2(y,z);
+
+        MUL2(u,du,u,du,v,vv,t1,t2,t3,t4,t5,t6,t7,t8)
+        s1=v*(f11.d+v*(f13.d+v*(f15.d+v*(f17.d+v*f19.d))));
+        ADD2(f9.d,ff9.d,s1,ZERO,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f7.d,ff7.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f5.d,ff5.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(f3.d,ff3.d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        MUL2(u,du,s1,ss1,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(u,du,s2,ss2,s1,ss1,t1,t2)
+        SUB2(opi.d,opi1.d,s1,ss1,s2,ss2,t1,t2)
+        if ((z=s2+(ss2-u8.d)) == s2+(ss2+u8.d))  return signArctan2(y,z);
+        return atan2Mp(x,y,pr);
+      }
+      else {
+        i=(TWO52+TWO8*u)-TWO52;  i-=16;
+        v=(u-cij[i][0].d)+du;
+        zz=opi1.d-v*(cij[i][2].d+v*(cij[i][3].d+v*(cij[i][4].d+
+                                 v*(cij[i][5].d+v* cij[i][6].d))));
+        t1=opi.d-cij[i][1].d;
+        if (i<112)  ua=ua1.d;  /* w <  1/2 */
+        else        ua=ua2.d;  /* w >= 1/2 */
+        if ((z=t1+(zz-ua)) == t1+(zz+ua))  return signArctan2(y,z);
+
+        t1=u-hij[i][0].d;
+        EADD(t1,du,v,vv)
+        s1=v*(hij[i][11].d+v*(hij[i][12].d+v*(hij[i][13].d+
+           v*(hij[i][14].d+v* hij[i][15].d))));
+        ADD2(hij[i][9].d,hij[i][10].d,s1,ZERO,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][7].d,hij[i][8].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][5].d,hij[i][6].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][3].d,hij[i][4].d,s1,ss1,s2,ss2,t1,t2)
+        MUL2(v,vv,s2,ss2,s1,ss1,t1,t2,t3,t4,t5,t6,t7,t8)
+        ADD2(hij[i][1].d,hij[i][2].d,s1,ss1,s2,ss2,t1,t2)
+        SUB2(opi.d,opi1.d,s2,ss2,s1,ss1,t1,t2)
+        if ((z=s1+(ss1-uc.d)) == s1+(ss1+uc.d))  return signArctan2(y,z);
+        return atan2Mp(x,y,pr);
+      }
+    }
+  }
+}
+  /* Treat the Denormalized case */
+static double  normalized(double ax,double ay,double y, double z)
+    { int p;
+      mp_no mpx,mpy,mpz,mperr,mpz2,mpt1;
+  p=6;
+  dbl_mp(ax,&mpx,p);  dbl_mp(ay,&mpy,p);  dvd(&mpy,&mpx,&mpz,p);
+  dbl_mp(ue.d,&mpt1,p);   mul(&mpz,&mpt1,&mperr,p);
+  sub(&mpz,&mperr,&mpz2,p);  mp_dbl(&mpz2,&z,p);
+  return signArctan2(y,z);
+}
+  /* Fix the sign and return after stage 1 or stage 2 */
+static double signArctan2(double y,double z)
+{
+  return ((y<ZERO) ? -z : z);
+}
+  /* Stage 3: Perform a multi-Precision computation */
+static double  atan2Mp(double x,double y,const int pr[])
+{
+  double z1,z2;
+  int i,p;
+  mp_no mpx,mpy,mpz,mpz1,mpz2,mperr,mpt1;
+  for (i=0; i<MM; i++) {
+    p = pr[i];
+    dbl_mp(x,&mpx,p);  dbl_mp(y,&mpy,p);
+    __mpatan2(&mpy,&mpx,&mpz,p);
+    dbl_mp(ud[i].d,&mpt1,p);   mul(&mpz,&mpt1,&mperr,p);
+    add(&mpz,&mperr,&mpz1,p);  sub(&mpz,&mperr,&mpz2,p);
+    mp_dbl(&mpz1,&z1,p);       mp_dbl(&mpz2,&z2,p);
+    if (z1==z2)   return z1;
+  }
+  return z1; /*if unpossible to do exact computing */
 }