• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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