[Beignet] [PATCH] Improve precision of sinpi/cospi

Ruiling Song ruiling.song at intel.com
Mon Feb 17 00:54:20 PST 2014


Signed-off-by: Ruiling Song <ruiling.song at intel.com>
---
 backend/src/ocl_stdlib.tmpl.h |  110 ++++++++++++++++++++---------------------
 1 file changed, 54 insertions(+), 56 deletions(-)

diff --git a/backend/src/ocl_stdlib.tmpl.h b/backend/src/ocl_stdlib.tmpl.h
index d191b8e..d2cc144 100755
--- a/backend/src/ocl_stdlib.tmpl.h
+++ b/backend/src/ocl_stdlib.tmpl.h
@@ -1479,65 +1479,63 @@ INLINE_OVERLOADABLE float tan(float x)
 
 INLINE_OVERLOADABLE float native_cos(float x) { return __gen_ocl_cos(x); }
 INLINE_OVERLOADABLE float __gen_ocl_internal_cospi(float x) {
-  return __gen_ocl_cos(x * M_PI_F);
+  int ix;
+  if(isinf(x) || isnan(x)) { return NAN; }
+  if(x < 0.0f) { x = -x; }
+  GEN_OCL_GET_FLOAT_WORD(ix, x);
+  if(x> 0x1.0p24) return 1.0f;
+  float m = __gen_ocl_internal_floor(x);
+  ix = (int)m;
+  m = x-m;
+  if((ix&0x1) != 0) m+=1.0f;
+    ix = __gen_ocl_internal_floor(m*4.0f);
+
+  switch(ix) {
+   case 0:
+    return __kernel_cosf(m*M_PI_F, 0.0f);
+   case 1:
+   case 2:
+    return __kernel_sinf((0.5f-m)*M_PI_F, 0.0f, 0);
+   case 3:
+   case 4:
+    return -__kernel_cosf((m-1.0f)*M_PI_F, 0.0f);
+   case 5:
+   case 6:
+    return __kernel_sinf((m-1.5f)*M_PI_F, 0.0f, 0);
+   default:
+    return __kernel_cosf((2.0f-m)*M_PI_F, 0.0f);
+   }
 }
 INLINE_OVERLOADABLE float native_sin(float x) { return __gen_ocl_sin(x); }
 INLINE_OVERLOADABLE float __gen_ocl_internal_sinpi(float x) {
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * 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.
- * ====================================================
- */
-  float y, z;
-  int n, ix;
-  ix = *(int *) (&x) & 0x7fffffff;
-  if (ix < 0x3e800000)
-    return __gen_ocl_sin(M_PI_F * x);
-  y = -x;
-  z = __gen_ocl_rndd(y);
-  if (z != y) {
-    y *= 0.5f;
-    y = 2.f * (y - __gen_ocl_rndd(y));
-    n = y * 4.f;
-  } else {
-    if (ix >= 0x4b800000) {
-      y = 0;
-      n = 0;
-    } else {
-      if (ix < 0x4b000000)
-        z = y + 8.3886080000e+06f;
-      int n = *(int *) (&z);
-      n &= 1;
-      y = n;
-      n <<= 2;
-    }
-  }
-  switch (n) {
-  case 0:
-    y = __gen_ocl_sin(M_PI_F * y);
-    break;
-  case 1:
-  case 2:
-    y = __gen_ocl_cos(M_PI_F * (0.5f - y));
-    break;
-  case 3:
-  case 4:
-    y = __gen_ocl_sin(M_PI_F * (1.f - y));
-    break;
-  case 5:
-  case 6:
-    y = -__gen_ocl_cos(M_PI_F * (y - 1.5f));
-    break;
-  default:
-    y = __gen_ocl_sin(M_PI_F * (y - 2.f));
-    break;
-  }
-  return -y;
+  float sign = 1.0f;
+  int ix;
+  if(isinf(x)) return NAN;
+  if(x < 0.0f) { x = -x; sign = -1.0f; }
+  GEN_OCL_GET_FLOAT_WORD(ix, x);
+  if(x> 0x1.0p24) return 0.0f;
+  float m = __gen_ocl_internal_floor(x);
+  ix = (int)m;
+  m = x-m;
+  if((ix&0x1) != 0) m+=1.0f;
+    ix = __gen_ocl_internal_floor(m*4.0f);
+
+  switch(ix) {
+   case 0:
+    return sign*__kernel_sinf(m*M_PI_F, 0.0f, 0);
+   case 1:
+   case 2:
+    return sign*__kernel_cosf((m-0.5f)*M_PI_F, 0.0f);
+   case 3:
+   case 4:
+    return -sign*__kernel_sinf((m-1.0f)*M_PI_F, 0.0f, 0);
+   case 5:
+   case 6:
+    return -sign*__kernel_cosf((m-1.5f)*M_PI_F, 0.0f);
+   default:
+    return -sign*__kernel_sinf((2.0f-m)*M_PI_F, 0.0f, 0);
+   }
+
 }
 INLINE_OVERLOADABLE float native_sqrt(float x) { return __gen_ocl_sqrt(x); }
 INLINE_OVERLOADABLE float native_rsqrt(float x) { return __gen_ocl_rsqrt(x); }
-- 
1.7.9.5



More information about the Beignet mailing list