diff options
author | Pan Xiuli <xiuli.pan@intel.com> | 2016-08-08 11:31:19 +0800 |
---|---|---|
committer | Yang Rong <rong.r.yang@intel.com> | 2016-08-12 18:16:23 +0800 |
commit | ccf1f13e1218f94ac77e47a6e32b1ddda88796a7 (patch) | |
tree | c4ca3fdbd759eaea3a8b55969a83703679a8901b /utests/utest_helper.cpp | |
parent | 7e2a964816fdd9bebb43ecf587445c34b404d055 (diff) | |
download | beignet-ccf1f13e1218f94ac77e47a6e32b1ddda88796a7.tar.gz |
Utest: Move half related helper function into utest helper
For more half related tests, need to use helper funciton in utest.
Signed-off-by: Pan Xiuli <xiuli.pan@intel.com>
Reviewed-by: Yang Rong <rong.r.yang@intel.com>
Diffstat (limited to 'utests/utest_helper.cpp')
-rw-r--r-- | utests/utest_helper.cpp | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/utests/utest_helper.cpp b/utests/utest_helper.cpp index 3388d9fc..5a2ac6e6 100644 --- a/utests/utest_helper.cpp +++ b/utests/utest_helper.cpp @@ -28,6 +28,7 @@ #include <cstring> #include <cassert> #include <cmath> +#include <algorithm> #define FATAL(...) \ do { \ @@ -927,3 +928,121 @@ int cl_check_ocl20(void) free(device_version_str); return 1; } + +int cl_check_half(void) +{ + std::string extStr; + size_t param_value_size; + OCL_CALL(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, 0, 0, ¶m_value_size); + std::vector<char> param_value(param_value_size); + OCL_CALL(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, param_value_size, + param_value.empty() ? NULL : ¶m_value.front(), ¶m_value_size); + if (!param_value.empty()) + extStr = std::string(¶m_value.front(), param_value_size-1); + + if (std::strstr(extStr.c_str(), "cl_khr_fp16") == NULL) { + printf("No cl_khr_fp16, Skip!"); + return 0; + } + + return 1; +} + +uint32_t __half_to_float(uint16_t h, bool* isInf, bool* infSign) +{ + struct __FP32 { + uint32_t mantissa:23; + uint32_t exponent:8; + uint32_t sign:1; + }; + struct __FP16 { + uint32_t mantissa:10; + uint32_t exponent:5; + uint32_t sign:1; + }; + uint32_t f; + __FP32 o; + memset(&o, 0, sizeof(o)); + __FP16 i; + memcpy(&i, &h, sizeof(uint16_t)); + + if (isInf) + *isInf = false; + if (infSign) + *infSign = false; + + if (i.exponent == 0 && i.mantissa == 0) // (Signed) zero + o.sign = i.sign; + else { + if (i.exponent == 0) { // Denormal (converts to normalized) + // Adjust mantissa so it's normalized (and keep + // track of exponent adjustment) + int e = -1; + uint m = i.mantissa; + do { + e++; + m <<= 1; + } while ((m & 0x400) == 0); + + o.mantissa = (m & 0x3ff) << 13; + o.exponent = 127 - 15 - e; + o.sign = i.sign; + } else if (i.exponent == 0x1f) { // Inf/NaN + // NOTE: Both can be handled with same code path + // since we just pass through mantissa bits. + o.mantissa = i.mantissa << 13; + o.exponent = 255; + o.sign = i.sign; + + if (isInf) { + *isInf = (i.mantissa == 0); + if (infSign) + *infSign = !i.sign; + } + } else { // Normalized number + o.mantissa = i.mantissa << 13; + o.exponent = 127 - 15 + i.exponent; + o.sign = i.sign; + } + } + + memcpy(&f, &o, sizeof(uint32_t)); + return f; +} + + +uint16_t __float_to_half(uint32_t x) +{ + uint16_t bits = (x >> 16) & 0x8000; /* Get the sign */ + uint16_t m = (x >> 12) & 0x07ff; /* Keep one extra bit for rounding */ + unsigned int e = (x >> 23) & 0xff; /* Using int is faster here */ + + /* If zero, or denormal, or exponent underflows too much for a denormal + * half, return signed zero. */ + if (e < 103) + return bits; + + /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */ + if (e > 142) { + bits |= 0x7c00u; + /* If exponent was 0xff and one mantissa bit was set, it means NaN, + * not Inf, so make sure we set one mantissa bit too. */ + bits |= e == 255 && (x & 0x007fffffu); + return bits; + } + + /* If exponent underflows but not too much, return a denormal */ + if (e < 113) { + m |= 0x0800u; + /* Extra rounding may overflow and set mantissa to 0 and exponent + * to 1, which is OK. */ + bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1); + return bits; + } + + bits |= ((e - 112) << 10) | (m >> 1); + /* Extra rounding. An overflow will set mantissa to 0 and increment + * the exponent, which is OK. */ + bits += m & 1; + return bits; +} |