diff options
-rw-r--r-- | backend/src/libocl/tmpl/ocl_math_common.tmpl.cl | 34 | ||||
-rw-r--r-- | backend/src/libocl/tmpl/ocl_math_common.tmpl.h | 1 |
2 files changed, 35 insertions, 0 deletions
diff --git a/backend/src/libocl/tmpl/ocl_math_common.tmpl.cl b/backend/src/libocl/tmpl/ocl_math_common.tmpl.cl index a705e2ff..c370864a 100644 --- a/backend/src/libocl/tmpl/ocl_math_common.tmpl.cl +++ b/backend/src/libocl/tmpl/ocl_math_common.tmpl.cl @@ -1999,6 +1999,40 @@ OVERLOADABLE double tan(double x) } } +OVERLOADABLE double tanh(double x) +{ + double one=1.0, two=2.0, tiny = 1.0e-300; + double t,z; + int jx,ix; + + /* High word of |x|. */ + jx = __HI(x); + ix = jx&0x7fffffff; + + /* x is INF or NaN */ + if(ix>=0x7ff00000) { + if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */ + else return one/x-one; /* tanh(NaN) = NaN */ + } + + /* |x| < 22 */ + if (ix < 0x40360000) { /* |x|<22 */ + if (ix<0x3c800000) /* |x|<2**-55 */ + return x*(one+x); /* tanh(small) = small */ + if (ix>=0x3ff00000) { /* |x|>=1 */ + t = expm1(two*fabs(x)); + z = one - two/(t+two); + } else { + t = expm1(-two*fabs(x)); + z= -t/(t+two); + } + /* |x| > 22, return +-1 */ + } else { + z = one - tiny; /* raised inexact flag */ + } + return (jx>=0)? z: -z; +} + OVERLOADABLE double trunc(double x) { double ret = floor(fabs(x)); diff --git a/backend/src/libocl/tmpl/ocl_math_common.tmpl.h b/backend/src/libocl/tmpl/ocl_math_common.tmpl.h index 9ac3b31f..471f8664 100644 --- a/backend/src/libocl/tmpl/ocl_math_common.tmpl.h +++ b/backend/src/libocl/tmpl/ocl_math_common.tmpl.h @@ -58,6 +58,7 @@ OVERLOADABLE double sin(double x); OVERLOADABLE double sinh(double x); OVERLOADABLE double sqrt(double x); OVERLOADABLE double tan(double x); +OVERLOADABLE double tanh(double x); OVERLOADABLE double trunc(double x); |