[Beignet] [PATCH] backend: add double version of atan2

rander rander.wang at intel.com
Thu Mar 30 06:21:07 UTC 2017


	cp from fdlibm, and need to be refined to pass cft

Signed-off-by: rander <rander.wang at intel.com>
---
 backend/src/libocl/tmpl/ocl_math_common.tmpl.cl | 85 +++++++++++++++++++++++++
 backend/src/libocl/tmpl/ocl_math_common.tmpl.h  |  1 +
 2 files changed, 86 insertions(+)

diff --git a/backend/src/libocl/tmpl/ocl_math_common.tmpl.cl b/backend/src/libocl/tmpl/ocl_math_common.tmpl.cl
index d6ee279..d1e67f4 100644
--- a/backend/src/libocl/tmpl/ocl_math_common.tmpl.cl
+++ b/backend/src/libocl/tmpl/ocl_math_common.tmpl.cl
@@ -311,6 +311,91 @@ OVERLOADABLE double atan(double x)
 	}
 }
 
+OVERLOADABLE double atan2(double x, double y)
+{
+	double 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 */
+
+	double z;
+	int k,m,hx,hy,ix,iy;
+	unsigned lx,ly;
+
+	hx = __HI(x); ix = hx&0x7fffffff;
+	lx = __LO(x);
+	hy = __HI(y); iy = hy&0x7fffffff;
+	ly = __LO(y);
+	if(((ix|((lx|-lx)>>31))>0x7ff00000)||
+	   ((iy|((ly|-ly)>>31))>0x7ff00000))	/* x or y is NaN */
+	   return x+y;
+
+	if((hx-0x3ff00000|lx)==0)
+		{
+			if(iy>=0x44100000) {	/* if |x| >= 2^66 */
+			if(iy>0x7ff00000 ||(iy==0x7ff00000 && (__LO(y)!=0)))
+			return y+y;		/* NaN */
+			if(hy >0)
+					return  pi_o_2;
+			else
+					return pi;
+			}
+				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 (hx<0)?  -pi-tiny: pi+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 3.0*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 pi_o_2; /* atan(-...,+INF) */
+			case 2: return  pi_o_2+tiny  ;  /* atan(+...,-INF) */
+			case 3: return -pi_o_2-tiny  ;  /* atan(-...,-INF) */
+		}
+		}
+	}
+	/* when y is INF */
+	if(iy==0x7ff00000) return (hx<0)? -pi-tiny: pi+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 2: __setHigh(&z, __HI(z) ^ 0x80000000);
+			return	   pi_o_2 - z  ;   /* atan(-,+) */
+		case 1: return  pi_o_2 + (z-pi_lo);/* atan(+,-) */
+		default: /* case 3 */
+			__setHigh(&z, __HI(z) ^ 0x80000000);
+				return  (z-pi_lo)-pi_o_2;/* atan(-,-) */
+	}
+}
+
 OVERLOADABLE double ceil(double x)
 {
     double ret;
diff --git a/backend/src/libocl/tmpl/ocl_math_common.tmpl.h b/backend/src/libocl/tmpl/ocl_math_common.tmpl.h
index 46dc788..2f4b85a 100644
--- a/backend/src/libocl/tmpl/ocl_math_common.tmpl.h
+++ b/backend/src/libocl/tmpl/ocl_math_common.tmpl.h
@@ -27,6 +27,7 @@ OVERLOADABLE double asin(double x);
 OVERLOADABLE double asinpi(double x);
 OVERLOADABLE double asinh(double x);
 OVERLOADABLE double atan(double x);
+OVERLOADABLE double atan2(double x, double y);
 OVERLOADABLE double ceil(double x);
 OVERLOADABLE double copysign(double x, double y);
 OVERLOADABLE double fabs(double x);
-- 
2.7.4



More information about the Beignet mailing list