29 #ifndef OPENCL_CL_HALF_H
30 #define OPENCL_CL_HALF_H
32 #include <CL/cl_platform.h>
50 } cl_half_rounding_mode;
54 #define CL_HALF_EXP_MASK 0x7C00
55 #define CL_HALF_MAX_FINITE_MAG 0x7BFF
61 static inline cl_half cl_half_handle_overflow(cl_half_rounding_mode rounding_mode,
64 if (rounding_mode == CL_HALF_RTZ)
67 return (sign << 15) | CL_HALF_MAX_FINITE_MAG;
69 else if (rounding_mode == CL_HALF_RTP && sign)
72 return (1 << 15) | CL_HALF_MAX_FINITE_MAG;
74 else if (rounding_mode == CL_HALF_RTN && !sign)
77 return CL_HALF_MAX_FINITE_MAG;
81 return (sign << 15) | CL_HALF_EXP_MASK;
87 static inline cl_half cl_half_handle_underflow(cl_half_rounding_mode rounding_mode,
90 if (rounding_mode == CL_HALF_RTP && !sign)
93 return (sign << 15) | 1;
95 else if (rounding_mode == CL_HALF_RTN && sign)
98 return (sign << 15) | 1;
109 static inline cl_half cl_half_from_float(cl_float f, cl_half_rounding_mode rounding_mode)
120 uint16_t sign = f32.i >> 31;
123 uint32_t f_exp = (f32.i >> (CL_FLT_MANT_DIG - 1)) & 0xFF;
124 uint32_t f_mant = f32.i & ((1 << (CL_FLT_MANT_DIG - 1)) - 1);
127 int32_t exp = f_exp - CL_FLT_MAX_EXP + 1;
130 uint16_t h_exp = (uint16_t)(exp + CL_HALF_MAX_EXP - 1);
133 uint32_t lsb_pos = CL_FLT_MANT_DIG - CL_HALF_MANT_DIG;
141 uint16_t h_mant = (uint16_t)(f_mant >> lsb_pos);
143 return (sign << 15) | CL_HALF_EXP_MASK | h_mant;
148 return (sign << 15) | CL_HALF_EXP_MASK;
153 if (!f_exp && !f_mant)
159 if (exp >= CL_HALF_MAX_EXP)
161 return cl_half_handle_overflow(rounding_mode, sign);
165 if (exp < (CL_HALF_MIN_EXP - CL_HALF_MANT_DIG - 1))
167 return cl_half_handle_underflow(rounding_mode, sign);
175 f_mant |= 1 << (CL_FLT_MANT_DIG - 1);
178 lsb_pos = -exp + (CL_FLT_MANT_DIG - 25);
182 uint16_t h_mant = (uint16_t)(f_mant >> lsb_pos);
185 uint32_t halfway = 1 << (lsb_pos - 1);
186 uint32_t mask = (halfway << 1) - 1;
187 switch (rounding_mode)
190 if ((f_mant & mask) > halfway)
195 else if ((f_mant & mask) == halfway)
206 if ((f_mant & mask) && !sign)
213 if ((f_mant & mask) && sign)
228 return (sign << 15) | (h_exp << 10) | h_mant;
235 static inline cl_half cl_half_from_double(cl_double d, cl_half_rounding_mode rounding_mode)
246 uint16_t sign = f64.i >> 63;
249 uint64_t d_exp = (f64.i >> (CL_DBL_MANT_DIG - 1)) & 0x7FF;
250 uint64_t d_mant = f64.i & (((uint64_t)1 << (CL_DBL_MANT_DIG - 1)) - 1);
253 int64_t exp = d_exp - CL_DBL_MAX_EXP + 1;
256 uint16_t h_exp = (uint16_t)(exp + CL_HALF_MAX_EXP - 1);
259 uint32_t lsb_pos = CL_DBL_MANT_DIG - CL_HALF_MANT_DIG;
267 uint16_t h_mant = (uint16_t)(d_mant >> lsb_pos);
269 return (sign << 15) | CL_HALF_EXP_MASK | h_mant;
274 return (sign << 15) | CL_HALF_EXP_MASK;
279 if (!d_exp && !d_mant)
285 if (exp >= CL_HALF_MAX_EXP)
287 return cl_half_handle_overflow(rounding_mode, sign);
291 if (exp < (CL_HALF_MIN_EXP - CL_HALF_MANT_DIG - 1))
293 return cl_half_handle_underflow(rounding_mode, sign);
301 d_mant |= (uint64_t)1 << (CL_DBL_MANT_DIG - 1);
304 lsb_pos = (uint32_t)(-exp + (CL_DBL_MANT_DIG - 25));
308 uint16_t h_mant = (uint16_t)(d_mant >> lsb_pos);
311 uint64_t halfway = (uint64_t)1 << (lsb_pos - 1);
312 uint64_t mask = (halfway << 1) - 1;
313 switch (rounding_mode)
316 if ((d_mant & mask) > halfway)
321 else if ((d_mant & mask) == halfway)
332 if ((d_mant & mask) && !sign)
339 if ((d_mant & mask) && sign)
354 return (sign << 15) | (h_exp << 10) | h_mant;
361 static inline cl_float cl_half_to_float(cl_half h)
371 uint16_t sign = h >> 15;
374 uint16_t h_exp = (h >> (CL_HALF_MANT_DIG - 1)) & 0x1F;
375 uint16_t h_mant = h & 0x3FF;
378 int32_t exp = h_exp - CL_HALF_MAX_EXP + 1;
381 uint32_t f_exp = exp + CL_FLT_MAX_EXP - 1;
389 uint32_t f_mant = h_mant << (CL_FLT_MANT_DIG - CL_HALF_MANT_DIG);
391 f32.i = (sign << 31) | 0x7F800000 | f_mant;
397 f32.i = (sign << 31) | 0x7F800000;
416 while ((h_mant & 0x400) == 0)
426 f32.i = (sign << 31) | (f_exp << 23) | (h_mant << 13);
431 #undef CL_HALF_EXP_MASK
432 #undef CL_HALF_MAX_FINITE_MAG