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
24 #include
<clc
/clcmacro.h
>
28 _CLC_OVERLOAD _CLC_DEF float atanh
(float x
) {
30 uint ax
= ux
& EXSIGNBIT_SP32
;
34 float z
= as_float
(QNANBITPATT_SP32);
37 float t
= as_float
(xs | PINFBITPATT_SP32
);
38 z
= ax
== 0x3f800000U ? t
: z
;
42 t
= MATH_DIVIDE
(2.0f
*t
, 1.0f - t
);
44 t
= as_float
(xs | as_uint
(t));
45 z
= ax
< 0x3f800000U ? t
: z
;
49 float a
= mad
(mad(0.92834212715e-2f
, t
, -
0.28120347286e0f
), t
, 0.39453629046e0f
);
50 float b
= mad
(mad(0.45281890445e0f
, t
, -
0.15537744551e1f
), t
, 0.11836088638e1f
);
51 float p
= MATH_DIVIDE
(a, b
);
53 z
= ax
< 0x3f000000 ? t
: z
;
56 z
= ax
< 0x39000000U ? x
: z
;
61 _CLC_UNARY_VECTORIZE
(_CLC_OVERLOAD _CLC_DEF
, float
, atanh
, float
)
64 #pragma OPENCL EXTENSION cl_khr_fp64
: enable
66 _CLC_OVERLOAD _CLC_DEF double atanh
(double x
) {
67 double absx
= fabs
(x);
69 double ret
= absx
== 1.0 ? as_double
(PINFBITPATT_DP64) : as_double
(QNANBITPATT_DP64);
72 // Note that atanh
(x) = 0.5 * ln
((1+x
)/(1-x))
73 // For greater accuracy we use
74 // ln
((1+x
)/(1-x)) = ln
(1 + 2x
/(1-x)) = log1p
(2x/(1-x)).
75 double r
= 0.5 * log1p
(2.0
* absx
/ (1.0 - absx
));
76 ret
= absx
< 1.0 ? r
: ret
;
79 ret
= x
< 0.0 ? r
: ret
;
81 // Arguments up to
0.5 in magnitude are
82 // approximated by a
[5,5] minimax polynomial
89 fma
(t, -
0.10468158892753136958e-3, 0.28728638600548514553e-1),
90 -
0.28180210961780814148e0
),
91 0.88468142536501647470e0
),
92 -
0.11028356797846341457e1
),
93 0.47482573589747356373e0
);
99 fma
(t, -
0.35861554370169537512e-1, 0.49561196555503101989e0
),
100 -
0.22608883748988489342e1
),
101 0.45414700626084508355e1
),
102 -
0.41631933639693546274e1
),
103 0.14244772076924206909e1
);
105 r
= fma
(x*t
, pn
/pd
, x
);
106 ret
= absx
< 0.5 ? r
: ret
;
111 _CLC_UNARY_VECTORIZE
(_CLC_OVERLOAD _CLC_DEF
, double
, atanh
, double
)
115 _CLC_DEFINE_UNARY_BUILTIN_FP16
(atanh)