2 * Copyright
(c) 2014 Advanced Micro Devices
, Inc.
4 * Permission is hereby granted
, free of charge
, to any person obtaining a copy
5 * of this software and associated documentation files
(the "Software"), to deal
6 * in the Software without restriction
, including without limitation the rights
7 * to use
, copy
, modify
, merge
, publish
, distribute
, sublicense
, and
/or sell
8 * copies of the Software
, and to permit persons to whom the Software is
9 * furnished to do so
, subject to the following conditions
:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED
"AS IS", WITHOUT WARRANTY OF ANY KIND
, EXPRESS OR
15 * IMPLIED
, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM
, DAMAGES OR OTHER
18 * LIABILITY
, WHETHER IN AN ACTION OF CONTRACT
, TORT OR OTHERWISE
, ARISING FROM
,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 #include
<clc
/clcmacro.h
>
29 _CLC_OVERLOAD _CLC_DEF float sinh
(float x
)
31 // After dealing with special cases the computation is split into regions as follows.
32 // abs
(x) >= max_sinh_arg
:
33 // sinh
(x) = sign
(x)*Inf
34 // abs
(x) >= small_threshold
:
35 // sinh
(x) = sign
(x)*exp
(abs(x))/2 computed using the splitexp and scaleDouble functions as for exp_amd
().
36 // abs
(x) < small_threshold
:
37 // compute p
= exp
(y) -
1 and then z
= 0.5*(p+(p/(p+1.0)))
38 // sinh
(x) is then sign
(x)*z.
40 const float max_sinh_arg
= 0x1.65a9fap
+6f
;
41 const float small_threshold
= 0x1.0a2b24p
+3f
;
44 uint aux
= ux
& EXSIGNBIT_SP32
;
46 float y
= as_float
(aux);
48 // We find the integer part y0 of y and the increment dy
= y - y0. We then compute
49 // z
= sinh
(y) = sinh
(y0)cosh
(dy) + cosh
(y0)sinh
(dy)
50 // where sinh
(y0) and cosh
(y0) are tabulated above.
52 ind
= (uint)ind
> 36U ?
0 : ind
;
62 mad
(dy2, 0.7746188980094184251527126e-12f
, 0.160576793121939886190847e-9f
),
63 0.250521176994133472333666e-7f
),
64 0.275573191913636406057211e-5f
),
65 0.198412698413242405162014e-3f
),
66 0.833333333333329931873097e-2f
),
67 0.166666666666666667013899e0f
);
68 sdy
= mad
(sdy, dy
*dy2
, dy
);
75 mad
(dy2, 0.1163921388172173692062032e-10f
, 0.208744349831471353536305e-8f
),
76 0.275573350756016588011357e-6f
),
77 0.248015872460622433115785e-4f
),
78 0.138888888889814854814536e-2f
),
79 0.416666666666660876512776e-1f
),
80 0.500000000000000005911074e0f
);
81 cdy
= mad
(cdy, dy2
, 1.0f
);
83 float2 tv
= USE_TABLE
(sinhcosh_tbl, ind
);
84 float z
= mad
(tv.s1
, sdy
, tv.s0
* cdy
);
85 z
= as_float
(xs | as_uint
(z));
87 // When y is large enough so that the negative exponential is negligible
,
88 // so sinh
(y) is approximated by sign
(x)*exp
(y)/2.
89 float t
= exp
(y -
0x1.62e500p-1f
);
90 float zsmall
= mad
(0x1.a0210ep-18f
, t
, t
);
91 zsmall
= as_float
(xs | as_uint
(zsmall));
92 z
= y
>= small_threshold ? zsmall
: z
;
95 float zinf
= as_float
(PINFBITPATT_SP32 | xs
);
96 z
= y
>= max_sinh_arg ? zinf
: z
;
97 z
= aux
> PINFBITPATT_SP32 | aux
< 0x38800000U ? x
: z
;
102 _CLC_UNARY_VECTORIZE
(_CLC_OVERLOAD _CLC_DEF
, float
, sinh
, float
);
105 #pragma OPENCL EXTENSION cl_khr_fp64
: enable
107 _CLC_OVERLOAD _CLC_DEF double sinh
(double x
)
109 // After dealing with special cases the computation is split into
110 // regions as follows
:
112 // abs
(x) >= max_sinh_arg
:
113 // sinh
(x) = sign
(x)*Inf
115 // abs
(x) >= small_threshold
:
116 // sinh
(x) = sign
(x)*exp
(abs(x))/2 computed using the
117 // splitexp and scaleDouble functions as for exp_amd
().
119 // abs
(x) < small_threshold
:
120 // compute p
= exp
(y) -
1 and then z
= 0.5*(p+(p/(p+1.0)))
121 // sinh
(x) is then sign
(x)*z.
123 const double max_sinh_arg
= 7.10475860073943977113e+02; // 0x408633ce8fb9f87e
125 // This is where exp
(-x) is insignificant compared to exp
(x) = ln
(2^
27)
126 const double small_threshold
= 0x1.2b708872320e2p
+4;
130 // In this range we find the integer part y0 of y
131 // and the increment dy
= y - y0. We then compute
132 // z
= sinh
(y) = sinh
(y0)cosh
(dy) + cosh
(y0)sinh
(dy)
133 // where sinh
(y0) and cosh
(y0) are obtained from tables
135 int ind
= min
((int)y
, 36);
137 double dy2
= dy
* dy
;
139 double sdy
= dy
* dy2
*
145 fma
(dy2, 0.7746188980094184251527126e-12, 0.160576793121939886190847e-9),
146 0.250521176994133472333666e-7),
147 0.275573191913636406057211e-5),
148 0.198412698413242405162014e-3),
149 0.833333333333329931873097e-2),
150 0.166666666666666667013899e0
);
152 double cdy
= dy2
* fma
(dy2,
157 fma
(dy2, 0.1163921388172173692062032e-10, 0.208744349831471353536305e-8),
158 0.275573350756016588011357e-6),
159 0.248015872460622433115785e-4),
160 0.138888888889814854814536e-2),
161 0.416666666666660876512776e-1),
162 0.500000000000000005911074e0
);
164 // At this point sinh
(dy) is approximated by dy
+ sdy.
165 // Shift some significant bits from dy to sdy.
166 double sdy1
= as_double
(as_ulong(dy) & 0xfffffffff8000000UL
);
167 double sdy2
= sdy
+ (dy - sdy1
);
169 double2 tv
= USE_TABLE
(cosh_tbl, ind
);
172 tv
= USE_TABLE
(sinh_tbl, ind
);
176 double z
= fma
(cl, sdy1
, fma
(sl, cdy
, fma
(cl, sdy2
, fma
(ct, sdy1
, fma
(st, cdy
, ct
*sdy2
)) + st
))) + sl
;
179 z
= (y < 0x1.0p-28
) | isnan
(x) | isinf
(x) ? y
: z
;
181 double t
= exp
(y -
0x1.62e42fefa3800p-1
);
182 t
= fma
(t, -
0x1.ef35793c76641p-45
, t
);
183 z
= y
>= small_threshold ? t
: z
;
184 z
= y
>= max_sinh_arg ? as_double
(PINFBITPATT_DP64) : z
;
186 return copysign
(z, x
);
189 _CLC_UNARY_VECTORIZE
(_CLC_OVERLOAD _CLC_DEF
, double
, sinh
, double
)
195 #pragma OPENCL EXTENSION cl_khr_fp16
: enable
197 _CLC_DEFINE_UNARY_BUILTIN_FP16
(sinh)