1*c217d954SCole Faust /*******************************************************************************
2*c217d954SCole Faust * Copyright (c) 2019-2020 The Khronos Group Inc.
3*c217d954SCole Faust *
4*c217d954SCole Faust * Licensed under the Apache License, Version 2.0 (the "License");
5*c217d954SCole Faust * you may not use this file except in compliance with the License.
6*c217d954SCole Faust * You may obtain a copy of the License at
7*c217d954SCole Faust *
8*c217d954SCole Faust * http://www.apache.org/licenses/LICENSE-2.0
9*c217d954SCole Faust *
10*c217d954SCole Faust * Unless required by applicable law or agreed to in writing, software
11*c217d954SCole Faust * distributed under the License is distributed on an "AS IS" BASIS,
12*c217d954SCole Faust * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*c217d954SCole Faust * See the License for the specific language governing permissions and
14*c217d954SCole Faust * limitations under the License.
15*c217d954SCole Faust ******************************************************************************/
16*c217d954SCole Faust
17*c217d954SCole Faust /**
18*c217d954SCole Faust * This is a header-only utility library that provides OpenCL host code with
19*c217d954SCole Faust * routines for converting to/from cl_half values.
20*c217d954SCole Faust *
21*c217d954SCole Faust * Example usage:
22*c217d954SCole Faust *
23*c217d954SCole Faust * #include <CL/cl_half.h>
24*c217d954SCole Faust * ...
25*c217d954SCole Faust * cl_half h = cl_half_from_float(0.5f, CL_HALF_RTE);
26*c217d954SCole Faust * cl_float f = cl_half_to_float(h);
27*c217d954SCole Faust */
28*c217d954SCole Faust
29*c217d954SCole Faust #ifndef OPENCL_CL_HALF_H
30*c217d954SCole Faust #define OPENCL_CL_HALF_H
31*c217d954SCole Faust
32*c217d954SCole Faust #include <CL/cl_platform.h>
33*c217d954SCole Faust
34*c217d954SCole Faust #include <stdint.h>
35*c217d954SCole Faust
36*c217d954SCole Faust #ifdef __cplusplus
37*c217d954SCole Faust extern "C" {
38*c217d954SCole Faust #endif
39*c217d954SCole Faust
40*c217d954SCole Faust
41*c217d954SCole Faust /**
42*c217d954SCole Faust * Rounding mode used when converting to cl_half.
43*c217d954SCole Faust */
44*c217d954SCole Faust typedef enum
45*c217d954SCole Faust {
46*c217d954SCole Faust CL_HALF_RTE, // round to nearest even
47*c217d954SCole Faust CL_HALF_RTZ, // round towards zero
48*c217d954SCole Faust CL_HALF_RTP, // round towards positive infinity
49*c217d954SCole Faust CL_HALF_RTN, // round towards negative infinity
50*c217d954SCole Faust } cl_half_rounding_mode;
51*c217d954SCole Faust
52*c217d954SCole Faust
53*c217d954SCole Faust /* Private utility macros. */
54*c217d954SCole Faust #define CL_HALF_EXP_MASK 0x7C00
55*c217d954SCole Faust #define CL_HALF_MAX_FINITE_MAG 0x7BFF
56*c217d954SCole Faust
57*c217d954SCole Faust
58*c217d954SCole Faust /*
59*c217d954SCole Faust * Utility to deal with values that overflow when converting to half precision.
60*c217d954SCole Faust */
cl_half_handle_overflow(cl_half_rounding_mode rounding_mode,uint16_t sign)61*c217d954SCole Faust static inline cl_half cl_half_handle_overflow(cl_half_rounding_mode rounding_mode,
62*c217d954SCole Faust uint16_t sign)
63*c217d954SCole Faust {
64*c217d954SCole Faust if (rounding_mode == CL_HALF_RTZ)
65*c217d954SCole Faust {
66*c217d954SCole Faust // Round overflow towards zero -> largest finite number (preserving sign)
67*c217d954SCole Faust return (sign << 15) | CL_HALF_MAX_FINITE_MAG;
68*c217d954SCole Faust }
69*c217d954SCole Faust else if (rounding_mode == CL_HALF_RTP && sign)
70*c217d954SCole Faust {
71*c217d954SCole Faust // Round negative overflow towards positive infinity -> most negative finite number
72*c217d954SCole Faust return (1 << 15) | CL_HALF_MAX_FINITE_MAG;
73*c217d954SCole Faust }
74*c217d954SCole Faust else if (rounding_mode == CL_HALF_RTN && !sign)
75*c217d954SCole Faust {
76*c217d954SCole Faust // Round positive overflow towards negative infinity -> largest finite number
77*c217d954SCole Faust return CL_HALF_MAX_FINITE_MAG;
78*c217d954SCole Faust }
79*c217d954SCole Faust
80*c217d954SCole Faust // Overflow to infinity
81*c217d954SCole Faust return (sign << 15) | CL_HALF_EXP_MASK;
82*c217d954SCole Faust }
83*c217d954SCole Faust
84*c217d954SCole Faust /*
85*c217d954SCole Faust * Utility to deal with values that underflow when converting to half precision.
86*c217d954SCole Faust */
cl_half_handle_underflow(cl_half_rounding_mode rounding_mode,uint16_t sign)87*c217d954SCole Faust static inline cl_half cl_half_handle_underflow(cl_half_rounding_mode rounding_mode,
88*c217d954SCole Faust uint16_t sign)
89*c217d954SCole Faust {
90*c217d954SCole Faust if (rounding_mode == CL_HALF_RTP && !sign)
91*c217d954SCole Faust {
92*c217d954SCole Faust // Round underflow towards positive infinity -> smallest positive value
93*c217d954SCole Faust return (sign << 15) | 1;
94*c217d954SCole Faust }
95*c217d954SCole Faust else if (rounding_mode == CL_HALF_RTN && sign)
96*c217d954SCole Faust {
97*c217d954SCole Faust // Round underflow towards negative infinity -> largest negative value
98*c217d954SCole Faust return (sign << 15) | 1;
99*c217d954SCole Faust }
100*c217d954SCole Faust
101*c217d954SCole Faust // Flush to zero
102*c217d954SCole Faust return (sign << 15);
103*c217d954SCole Faust }
104*c217d954SCole Faust
105*c217d954SCole Faust
106*c217d954SCole Faust /**
107*c217d954SCole Faust * Convert a cl_float to a cl_half.
108*c217d954SCole Faust */
cl_half_from_float(cl_float f,cl_half_rounding_mode rounding_mode)109*c217d954SCole Faust static inline cl_half cl_half_from_float(cl_float f, cl_half_rounding_mode rounding_mode)
110*c217d954SCole Faust {
111*c217d954SCole Faust // Type-punning to get direct access to underlying bits
112*c217d954SCole Faust union
113*c217d954SCole Faust {
114*c217d954SCole Faust cl_float f;
115*c217d954SCole Faust uint32_t i;
116*c217d954SCole Faust } f32;
117*c217d954SCole Faust f32.f = f;
118*c217d954SCole Faust
119*c217d954SCole Faust // Extract sign bit
120*c217d954SCole Faust uint16_t sign = f32.i >> 31;
121*c217d954SCole Faust
122*c217d954SCole Faust // Extract FP32 exponent and mantissa
123*c217d954SCole Faust uint32_t f_exp = (f32.i >> (CL_FLT_MANT_DIG - 1)) & 0xFF;
124*c217d954SCole Faust uint32_t f_mant = f32.i & ((1 << (CL_FLT_MANT_DIG - 1)) - 1);
125*c217d954SCole Faust
126*c217d954SCole Faust // Remove FP32 exponent bias
127*c217d954SCole Faust int32_t exp = f_exp - CL_FLT_MAX_EXP + 1;
128*c217d954SCole Faust
129*c217d954SCole Faust // Add FP16 exponent bias
130*c217d954SCole Faust uint16_t h_exp = (uint16_t)(exp + CL_HALF_MAX_EXP - 1);
131*c217d954SCole Faust
132*c217d954SCole Faust // Position of the bit that will become the FP16 mantissa LSB
133*c217d954SCole Faust uint32_t lsb_pos = CL_FLT_MANT_DIG - CL_HALF_MANT_DIG;
134*c217d954SCole Faust
135*c217d954SCole Faust // Check for NaN / infinity
136*c217d954SCole Faust if (f_exp == 0xFF)
137*c217d954SCole Faust {
138*c217d954SCole Faust if (f_mant)
139*c217d954SCole Faust {
140*c217d954SCole Faust // NaN -> propagate mantissa and silence it
141*c217d954SCole Faust uint16_t h_mant = (uint16_t)(f_mant >> lsb_pos);
142*c217d954SCole Faust h_mant |= 0x200;
143*c217d954SCole Faust return (sign << 15) | CL_HALF_EXP_MASK | h_mant;
144*c217d954SCole Faust }
145*c217d954SCole Faust else
146*c217d954SCole Faust {
147*c217d954SCole Faust // Infinity -> zero mantissa
148*c217d954SCole Faust return (sign << 15) | CL_HALF_EXP_MASK;
149*c217d954SCole Faust }
150*c217d954SCole Faust }
151*c217d954SCole Faust
152*c217d954SCole Faust // Check for zero
153*c217d954SCole Faust if (!f_exp && !f_mant)
154*c217d954SCole Faust {
155*c217d954SCole Faust return (sign << 15);
156*c217d954SCole Faust }
157*c217d954SCole Faust
158*c217d954SCole Faust // Check for overflow
159*c217d954SCole Faust if (exp >= CL_HALF_MAX_EXP)
160*c217d954SCole Faust {
161*c217d954SCole Faust return cl_half_handle_overflow(rounding_mode, sign);
162*c217d954SCole Faust }
163*c217d954SCole Faust
164*c217d954SCole Faust // Check for underflow
165*c217d954SCole Faust if (exp < (CL_HALF_MIN_EXP - CL_HALF_MANT_DIG - 1))
166*c217d954SCole Faust {
167*c217d954SCole Faust return cl_half_handle_underflow(rounding_mode, sign);
168*c217d954SCole Faust }
169*c217d954SCole Faust
170*c217d954SCole Faust // Check for value that will become denormal
171*c217d954SCole Faust if (exp < -14)
172*c217d954SCole Faust {
173*c217d954SCole Faust // Denormal -> include the implicit 1 from the FP32 mantissa
174*c217d954SCole Faust h_exp = 0;
175*c217d954SCole Faust f_mant |= 1 << (CL_FLT_MANT_DIG - 1);
176*c217d954SCole Faust
177*c217d954SCole Faust // Mantissa shift amount depends on exponent
178*c217d954SCole Faust lsb_pos = -exp + (CL_FLT_MANT_DIG - 25);
179*c217d954SCole Faust }
180*c217d954SCole Faust
181*c217d954SCole Faust // Generate FP16 mantissa by shifting FP32 mantissa
182*c217d954SCole Faust uint16_t h_mant = (uint16_t)(f_mant >> lsb_pos);
183*c217d954SCole Faust
184*c217d954SCole Faust // Check whether we need to round
185*c217d954SCole Faust uint32_t halfway = 1 << (lsb_pos - 1);
186*c217d954SCole Faust uint32_t mask = (halfway << 1) - 1;
187*c217d954SCole Faust switch (rounding_mode)
188*c217d954SCole Faust {
189*c217d954SCole Faust case CL_HALF_RTE:
190*c217d954SCole Faust if ((f_mant & mask) > halfway)
191*c217d954SCole Faust {
192*c217d954SCole Faust // More than halfway -> round up
193*c217d954SCole Faust h_mant += 1;
194*c217d954SCole Faust }
195*c217d954SCole Faust else if ((f_mant & mask) == halfway)
196*c217d954SCole Faust {
197*c217d954SCole Faust // Exactly halfway -> round to nearest even
198*c217d954SCole Faust if (h_mant & 0x1)
199*c217d954SCole Faust h_mant += 1;
200*c217d954SCole Faust }
201*c217d954SCole Faust break;
202*c217d954SCole Faust case CL_HALF_RTZ:
203*c217d954SCole Faust // Mantissa has already been truncated -> do nothing
204*c217d954SCole Faust break;
205*c217d954SCole Faust case CL_HALF_RTP:
206*c217d954SCole Faust if ((f_mant & mask) && !sign)
207*c217d954SCole Faust {
208*c217d954SCole Faust // Round positive numbers up
209*c217d954SCole Faust h_mant += 1;
210*c217d954SCole Faust }
211*c217d954SCole Faust break;
212*c217d954SCole Faust case CL_HALF_RTN:
213*c217d954SCole Faust if ((f_mant & mask) && sign)
214*c217d954SCole Faust {
215*c217d954SCole Faust // Round negative numbers down
216*c217d954SCole Faust h_mant += 1;
217*c217d954SCole Faust }
218*c217d954SCole Faust break;
219*c217d954SCole Faust }
220*c217d954SCole Faust
221*c217d954SCole Faust // Check for mantissa overflow
222*c217d954SCole Faust if (h_mant & 0x400)
223*c217d954SCole Faust {
224*c217d954SCole Faust h_exp += 1;
225*c217d954SCole Faust h_mant = 0;
226*c217d954SCole Faust }
227*c217d954SCole Faust
228*c217d954SCole Faust return (sign << 15) | (h_exp << 10) | h_mant;
229*c217d954SCole Faust }
230*c217d954SCole Faust
231*c217d954SCole Faust
232*c217d954SCole Faust /**
233*c217d954SCole Faust * Convert a cl_double to a cl_half.
234*c217d954SCole Faust */
cl_half_from_double(cl_double d,cl_half_rounding_mode rounding_mode)235*c217d954SCole Faust static inline cl_half cl_half_from_double(cl_double d, cl_half_rounding_mode rounding_mode)
236*c217d954SCole Faust {
237*c217d954SCole Faust // Type-punning to get direct access to underlying bits
238*c217d954SCole Faust union
239*c217d954SCole Faust {
240*c217d954SCole Faust cl_double d;
241*c217d954SCole Faust uint64_t i;
242*c217d954SCole Faust } f64;
243*c217d954SCole Faust f64.d = d;
244*c217d954SCole Faust
245*c217d954SCole Faust // Extract sign bit
246*c217d954SCole Faust uint16_t sign = f64.i >> 63;
247*c217d954SCole Faust
248*c217d954SCole Faust // Extract FP64 exponent and mantissa
249*c217d954SCole Faust uint64_t d_exp = (f64.i >> (CL_DBL_MANT_DIG - 1)) & 0x7FF;
250*c217d954SCole Faust uint64_t d_mant = f64.i & (((uint64_t)1 << (CL_DBL_MANT_DIG - 1)) - 1);
251*c217d954SCole Faust
252*c217d954SCole Faust // Remove FP64 exponent bias
253*c217d954SCole Faust int64_t exp = d_exp - CL_DBL_MAX_EXP + 1;
254*c217d954SCole Faust
255*c217d954SCole Faust // Add FP16 exponent bias
256*c217d954SCole Faust uint16_t h_exp = (uint16_t)(exp + CL_HALF_MAX_EXP - 1);
257*c217d954SCole Faust
258*c217d954SCole Faust // Position of the bit that will become the FP16 mantissa LSB
259*c217d954SCole Faust uint32_t lsb_pos = CL_DBL_MANT_DIG - CL_HALF_MANT_DIG;
260*c217d954SCole Faust
261*c217d954SCole Faust // Check for NaN / infinity
262*c217d954SCole Faust if (d_exp == 0x7FF)
263*c217d954SCole Faust {
264*c217d954SCole Faust if (d_mant)
265*c217d954SCole Faust {
266*c217d954SCole Faust // NaN -> propagate mantissa and silence it
267*c217d954SCole Faust uint16_t h_mant = (uint16_t)(d_mant >> lsb_pos);
268*c217d954SCole Faust h_mant |= 0x200;
269*c217d954SCole Faust return (sign << 15) | CL_HALF_EXP_MASK | h_mant;
270*c217d954SCole Faust }
271*c217d954SCole Faust else
272*c217d954SCole Faust {
273*c217d954SCole Faust // Infinity -> zero mantissa
274*c217d954SCole Faust return (sign << 15) | CL_HALF_EXP_MASK;
275*c217d954SCole Faust }
276*c217d954SCole Faust }
277*c217d954SCole Faust
278*c217d954SCole Faust // Check for zero
279*c217d954SCole Faust if (!d_exp && !d_mant)
280*c217d954SCole Faust {
281*c217d954SCole Faust return (sign << 15);
282*c217d954SCole Faust }
283*c217d954SCole Faust
284*c217d954SCole Faust // Check for overflow
285*c217d954SCole Faust if (exp >= CL_HALF_MAX_EXP)
286*c217d954SCole Faust {
287*c217d954SCole Faust return cl_half_handle_overflow(rounding_mode, sign);
288*c217d954SCole Faust }
289*c217d954SCole Faust
290*c217d954SCole Faust // Check for underflow
291*c217d954SCole Faust if (exp < (CL_HALF_MIN_EXP - CL_HALF_MANT_DIG - 1))
292*c217d954SCole Faust {
293*c217d954SCole Faust return cl_half_handle_underflow(rounding_mode, sign);
294*c217d954SCole Faust }
295*c217d954SCole Faust
296*c217d954SCole Faust // Check for value that will become denormal
297*c217d954SCole Faust if (exp < -14)
298*c217d954SCole Faust {
299*c217d954SCole Faust // Include the implicit 1 from the FP64 mantissa
300*c217d954SCole Faust h_exp = 0;
301*c217d954SCole Faust d_mant |= (uint64_t)1 << (CL_DBL_MANT_DIG - 1);
302*c217d954SCole Faust
303*c217d954SCole Faust // Mantissa shift amount depends on exponent
304*c217d954SCole Faust lsb_pos = (uint32_t)(-exp + (CL_DBL_MANT_DIG - 25));
305*c217d954SCole Faust }
306*c217d954SCole Faust
307*c217d954SCole Faust // Generate FP16 mantissa by shifting FP64 mantissa
308*c217d954SCole Faust uint16_t h_mant = (uint16_t)(d_mant >> lsb_pos);
309*c217d954SCole Faust
310*c217d954SCole Faust // Check whether we need to round
311*c217d954SCole Faust uint64_t halfway = (uint64_t)1 << (lsb_pos - 1);
312*c217d954SCole Faust uint64_t mask = (halfway << 1) - 1;
313*c217d954SCole Faust switch (rounding_mode)
314*c217d954SCole Faust {
315*c217d954SCole Faust case CL_HALF_RTE:
316*c217d954SCole Faust if ((d_mant & mask) > halfway)
317*c217d954SCole Faust {
318*c217d954SCole Faust // More than halfway -> round up
319*c217d954SCole Faust h_mant += 1;
320*c217d954SCole Faust }
321*c217d954SCole Faust else if ((d_mant & mask) == halfway)
322*c217d954SCole Faust {
323*c217d954SCole Faust // Exactly halfway -> round to nearest even
324*c217d954SCole Faust if (h_mant & 0x1)
325*c217d954SCole Faust h_mant += 1;
326*c217d954SCole Faust }
327*c217d954SCole Faust break;
328*c217d954SCole Faust case CL_HALF_RTZ:
329*c217d954SCole Faust // Mantissa has already been truncated -> do nothing
330*c217d954SCole Faust break;
331*c217d954SCole Faust case CL_HALF_RTP:
332*c217d954SCole Faust if ((d_mant & mask) && !sign)
333*c217d954SCole Faust {
334*c217d954SCole Faust // Round positive numbers up
335*c217d954SCole Faust h_mant += 1;
336*c217d954SCole Faust }
337*c217d954SCole Faust break;
338*c217d954SCole Faust case CL_HALF_RTN:
339*c217d954SCole Faust if ((d_mant & mask) && sign)
340*c217d954SCole Faust {
341*c217d954SCole Faust // Round negative numbers down
342*c217d954SCole Faust h_mant += 1;
343*c217d954SCole Faust }
344*c217d954SCole Faust break;
345*c217d954SCole Faust }
346*c217d954SCole Faust
347*c217d954SCole Faust // Check for mantissa overflow
348*c217d954SCole Faust if (h_mant & 0x400)
349*c217d954SCole Faust {
350*c217d954SCole Faust h_exp += 1;
351*c217d954SCole Faust h_mant = 0;
352*c217d954SCole Faust }
353*c217d954SCole Faust
354*c217d954SCole Faust return (sign << 15) | (h_exp << 10) | h_mant;
355*c217d954SCole Faust }
356*c217d954SCole Faust
357*c217d954SCole Faust
358*c217d954SCole Faust /**
359*c217d954SCole Faust * Convert a cl_half to a cl_float.
360*c217d954SCole Faust */
cl_half_to_float(cl_half h)361*c217d954SCole Faust static inline cl_float cl_half_to_float(cl_half h)
362*c217d954SCole Faust {
363*c217d954SCole Faust // Type-punning to get direct access to underlying bits
364*c217d954SCole Faust union
365*c217d954SCole Faust {
366*c217d954SCole Faust cl_float f;
367*c217d954SCole Faust uint32_t i;
368*c217d954SCole Faust } f32;
369*c217d954SCole Faust
370*c217d954SCole Faust // Extract sign bit
371*c217d954SCole Faust uint16_t sign = h >> 15;
372*c217d954SCole Faust
373*c217d954SCole Faust // Extract FP16 exponent and mantissa
374*c217d954SCole Faust uint16_t h_exp = (h >> (CL_HALF_MANT_DIG - 1)) & 0x1F;
375*c217d954SCole Faust uint16_t h_mant = h & 0x3FF;
376*c217d954SCole Faust
377*c217d954SCole Faust // Remove FP16 exponent bias
378*c217d954SCole Faust int32_t exp = h_exp - CL_HALF_MAX_EXP + 1;
379*c217d954SCole Faust
380*c217d954SCole Faust // Add FP32 exponent bias
381*c217d954SCole Faust uint32_t f_exp = exp + CL_FLT_MAX_EXP - 1;
382*c217d954SCole Faust
383*c217d954SCole Faust // Check for NaN / infinity
384*c217d954SCole Faust if (h_exp == 0x1F)
385*c217d954SCole Faust {
386*c217d954SCole Faust if (h_mant)
387*c217d954SCole Faust {
388*c217d954SCole Faust // NaN -> propagate mantissa and silence it
389*c217d954SCole Faust uint32_t f_mant = h_mant << (CL_FLT_MANT_DIG - CL_HALF_MANT_DIG);
390*c217d954SCole Faust f_mant |= 0x400000;
391*c217d954SCole Faust f32.i = (sign << 31) | 0x7F800000 | f_mant;
392*c217d954SCole Faust return f32.f;
393*c217d954SCole Faust }
394*c217d954SCole Faust else
395*c217d954SCole Faust {
396*c217d954SCole Faust // Infinity -> zero mantissa
397*c217d954SCole Faust f32.i = (sign << 31) | 0x7F800000;
398*c217d954SCole Faust return f32.f;
399*c217d954SCole Faust }
400*c217d954SCole Faust }
401*c217d954SCole Faust
402*c217d954SCole Faust // Check for zero / denormal
403*c217d954SCole Faust if (h_exp == 0)
404*c217d954SCole Faust {
405*c217d954SCole Faust if (h_mant == 0)
406*c217d954SCole Faust {
407*c217d954SCole Faust // Zero -> zero exponent
408*c217d954SCole Faust f_exp = 0;
409*c217d954SCole Faust }
410*c217d954SCole Faust else
411*c217d954SCole Faust {
412*c217d954SCole Faust // Denormal -> normalize it
413*c217d954SCole Faust // - Shift mantissa to make most-significant 1 implicit
414*c217d954SCole Faust // - Adjust exponent accordingly
415*c217d954SCole Faust uint32_t shift = 0;
416*c217d954SCole Faust while ((h_mant & 0x400) == 0)
417*c217d954SCole Faust {
418*c217d954SCole Faust h_mant <<= 1;
419*c217d954SCole Faust shift++;
420*c217d954SCole Faust }
421*c217d954SCole Faust h_mant &= 0x3FF;
422*c217d954SCole Faust f_exp -= shift - 1;
423*c217d954SCole Faust }
424*c217d954SCole Faust }
425*c217d954SCole Faust
426*c217d954SCole Faust f32.i = (sign << 31) | (f_exp << 23) | (h_mant << 13);
427*c217d954SCole Faust return f32.f;
428*c217d954SCole Faust }
429*c217d954SCole Faust
430*c217d954SCole Faust
431*c217d954SCole Faust #undef CL_HALF_EXP_MASK
432*c217d954SCole Faust #undef CL_HALF_MAX_FINITE_MAG
433*c217d954SCole Faust
434*c217d954SCole Faust
435*c217d954SCole Faust #ifdef __cplusplus
436*c217d954SCole Faust }
437*c217d954SCole Faust #endif
438*c217d954SCole Faust
439*c217d954SCole Faust
440*c217d954SCole Faust #endif /* OPENCL_CL_HALF_H */
441