1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #ifndef TEST_CONFORMANCE_CLCPP_HALF_UTILS_HPP
17 #define TEST_CONFORMANCE_CLCPP_HALF_UTILS_HPP
18
19 #include "../common.hpp"
20 #include "../funcs_test_utils.hpp"
21
22 #include <cmath>
23
24 namespace detail
25 {
26
27 template<class INT_TYPE>
clz(INT_TYPE x)28 inline int clz(INT_TYPE x)
29 {
30 int count = 0;
31 if(std::is_unsigned<INT_TYPE>::value)
32 {
33 cl_ulong value = x;
34 value <<= 8 * sizeof(value) - (8 * sizeof(x));
35 for(count = 0; 0 == (value & (CL_LONG_MIN)); count++)
36 {
37 value <<= 1;
38 }
39 }
40 else
41 {
42 cl_long value = x;
43 value <<= 8 * sizeof(value) - (8 * sizeof(x));
44 for(count = 0; 0 == (value & (CL_LONG_MIN)); count++)
45 {
46 value <<= 1;
47 }
48 }
49 return count;
50 }
51
52 } // namespace detail
53
half2float(cl_half us)54 inline cl_float half2float(cl_half us)
55 {
56 uint32_t u = us;
57 uint32_t sign = (u << 16) & 0x80000000;
58 int32_t exponent = (u & 0x7c00) >> 10;
59 uint32_t mantissa = (u & 0x03ff) << 13;
60 union{ cl_uint u; cl_float f;}uu;
61
62 if( exponent == 0 )
63 {
64 if( mantissa == 0 )
65 return sign ? -0.0f : 0.0f;
66
67 int shift = detail::clz( mantissa ) - 8;
68 exponent -= shift-1;
69 mantissa <<= shift;
70 mantissa &= 0x007fffff;
71 }
72 else
73 if( exponent == 31)
74 {
75 uu.u = mantissa | sign;
76 if( mantissa )
77 uu.u |= 0x7fc00000;
78 else
79 uu.u |= 0x7f800000;
80
81 return uu.f;
82 }
83
84 exponent += 127 - 15;
85 exponent <<= 23;
86
87 exponent |= mantissa;
88 uu.u = exponent | sign;
89
90 return uu.f;
91 }
92
float2half_rte(cl_float f)93 inline cl_ushort float2half_rte(cl_float f)
94 {
95 union{ cl_float f; cl_uint u; } u = {f};
96 cl_uint sign = (u.u >> 16) & 0x8000;
97 cl_float x = fabsf(f);
98
99 //Nan
100 if( x != x )
101 {
102 u.u >>= (24-11);
103 u.u &= 0x7fff;
104 u.u |= 0x0200; //silence the NaN
105 return u.u | sign;
106 }
107
108 // overflow
109 if( x >= MAKE_HEX_FLOAT(0x1.ffep15f, 0x1ffeL, 3) )
110 return 0x7c00 | sign;
111
112 // underflow
113 if( x <= MAKE_HEX_FLOAT(0x1.0p-25f, 0x1L, -25) )
114 return sign; // The halfway case can return 0x0001 or 0. 0 is even.
115
116 // very small
117 if( x < MAKE_HEX_FLOAT(0x1.8p-24f, 0x18L, -28) )
118 return sign | 1;
119
120 // half denormal
121 if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) )
122 {
123 u.f = x * MAKE_HEX_FLOAT(0x1.0p-125f, 0x1L, -125);
124 return sign | u.u;
125 }
126
127 u.f *= MAKE_HEX_FLOAT(0x1.0p13f, 0x1L, 13);
128 u.u &= 0x7f800000;
129 x += u.f;
130 u.f = x - u.f;
131 u.f *= MAKE_HEX_FLOAT(0x1.0p-112f, 0x1L, -112);
132
133 return (u.u >> (24-11)) | sign;
134 }
135
136 #endif // TEST_CONFORMANCE_CLCPP_HALF_UTILS_HPP
137