[SampleProfileLoader] Fix integer overflow in generateMDProfMetadata (#90217)
[llvm-project.git] / libclc / generic / lib / math / cosh.cl
blob1a672755d1f7c00dbdd8220830fe1a5f86ab02bb
1 /*
2 * Copyright (c) 2014,2015 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
20 * THE SOFTWARE.
23 #include <clc/clc.h>
25 #include "math.h"
26 #include "tables.h"
27 #include "../clcmacro.h"
29 _CLC_OVERLOAD _CLC_DEF float cosh(float x) {
31 // After dealing with special cases the computation is split into regions as follows.
32 // abs(x) >= max_cosh_arg:
33 // cosh(x) = sign(x)*Inf
34 // abs(x) >= small_threshold:
35 // cosh(x) = sign(x)*exp(abs(x))/2 computed using the
36 // splitexp and scaleDouble functions as for exp_amd().
37 // abs(x) < small_threshold:
38 // compute p = exp(y) - 1 and then z = 0.5*(p+(p/(p+1.0)))
39 // cosh(x) is then z.
41 const float max_cosh_arg = 0x1.65a9fap+6f;
42 const float small_threshold = 0x1.0a2b24p+3f;
44 uint ux = as_uint(x);
45 uint aux = ux & EXSIGNBIT_SP32;
46 float y = as_float(aux);
48 // 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 // z = cosh(y) = cosh(y0)cosh(dy) + sinh(y0)sinh(dy)
51 // where sinh(y0) and cosh(y0) are tabulated above.
53 int ind = (int)y;
54 ind = (uint)ind > 36U ? 0 : ind;
56 float dy = y - ind;
57 float dy2 = dy * dy;
59 float sdy = mad(dy2,
60 mad(dy2,
61 mad(dy2,
62 mad(dy2,
63 mad(dy2,
64 mad(dy2, 0.7746188980094184251527126e-12f, 0.160576793121939886190847e-9f),
65 0.250521176994133472333666e-7f),
66 0.275573191913636406057211e-5f),
67 0.198412698413242405162014e-3f),
68 0.833333333333329931873097e-2f),
69 0.166666666666666667013899e0f);
70 sdy = mad(sdy, dy*dy2, dy);
72 float cdy = mad(dy2,
73 mad(dy2,
74 mad(dy2,
75 mad(dy2,
76 mad(dy2,
77 mad(dy2, 0.1163921388172173692062032e-10f, 0.208744349831471353536305e-8f),
78 0.275573350756016588011357e-6f),
79 0.248015872460622433115785e-4f),
80 0.138888888889814854814536e-2f),
81 0.416666666666660876512776e-1f),
82 0.500000000000000005911074e0f);
83 cdy = mad(cdy, dy2, 1.0f);
85 float2 tv = USE_TABLE(sinhcosh_tbl, ind);
86 float z = mad(tv.s0, sdy, tv.s1 * cdy);
88 // When exp(-x) is insignificant compared to exp(x), return exp(x)/2
89 float t = exp(y - 0x1.62e500p-1f);
90 float zsmall = mad(0x1.a0210ep-18f, t, t);
91 z = y >= small_threshold ? zsmall : z;
93 // Corner cases
94 z = y >= max_cosh_arg ? as_float(PINFBITPATT_SP32) : z;
95 z = aux > PINFBITPATT_SP32 ? as_float(QNANBITPATT_SP32) : z;
96 z = aux < 0x38800000 ? 1.0f : z;
98 return z;
101 _CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, float, cosh, float);
103 #ifdef cl_khr_fp64
104 #pragma OPENCL EXTENSION cl_khr_fp64 : enable
106 _CLC_OVERLOAD _CLC_DEF double cosh(double x) {
108 // After dealing with special cases the computation is split into
109 // regions as follows:
111 // abs(x) >= max_cosh_arg:
112 // cosh(x) = sign(x)*Inf
114 // abs(x) >= small_threshold:
115 // cosh(x) = sign(x)*exp(abs(x))/2 computed using the
116 // splitexp and scaleDouble functions as for exp_amd().
118 // abs(x) < small_threshold:
119 // compute p = exp(y) - 1 and then z = 0.5*(p+(p/(p+1.0)))
120 // cosh(x) is then sign(x)*z.
122 // This is ln(2^1025)
123 const double max_cosh_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;
128 double y = fabs(x);
130 // In this range we find the integer part y0 of y
131 // and the increment dy = y - y0. We then compute
132 // z = cosh(y) = cosh(y0)cosh(dy) + sinh(y0)sinh(dy)
133 // where sinh(y0) and cosh(y0) are tabulated above.
135 int ind = min((int)y, 36);
136 double dy = y - ind;
137 double dy2 = dy * dy;
139 double sdy = dy * dy2 *
140 fma(dy2,
141 fma(dy2,
142 fma(dy2,
143 fma(dy2,
144 fma(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,
153 fma(dy2,
154 fma(dy2,
155 fma(dy2,
156 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 // and cosh(dy) is approximated by 1 + cdy.
166 double2 tv = USE_TABLE(cosh_tbl, ind);
167 double cl = tv.s0;
168 double ct = tv.s1;
169 tv = USE_TABLE(sinh_tbl, ind);
170 double sl = tv.s0;
171 double st = tv.s1;
173 double z = fma(sl, dy, fma(sl, sdy, fma(cl, cdy, fma(st, dy, fma(st, sdy, ct*cdy)) + ct))) + cl;
175 // Other cases
176 z = y < 0x1.0p-28 ? 1.0 : z;
178 double t = exp(y - 0x1.62e42fefa3800p-1);
179 t = fma(t, -0x1.ef35793c76641p-45, t);
180 z = y >= small_threshold ? t : z;
182 z = y >= max_cosh_arg ? as_double(PINFBITPATT_DP64) : z;
184 z = isinf(x) | isnan(x) ? y : z;
186 return z;
190 _CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, double, cosh, double)
192 #endif